1 /* Conversion functions for versioning information.
2    Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5 
6    This file is free software; you can redistribute it and/or modify
7    it under the terms of either
8 
9      * the GNU Lesser General Public License as published by the Free
10        Software Foundation; either version 3 of the License, or (at
11        your option) any later version
12 
13    or
14 
15      * the GNU General Public License as published by the Free
16        Software Foundation; either version 2 of the License, or (at
17        your option) any later version
18 
19    or both in parallel, as here.
20 
21    elfutils is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24    General Public License for more details.
25 
26    You should have received copies of the GNU General Public License and
27    the GNU Lesser General Public License along with this program.  If
28    not, see <http://www.gnu.org/licenses/>.  */
29 
30 #include <assert.h>
31 #include <gelf.h>
32 
33 #include "libelfP.h"
34 
35 
36 static void
elf_cvt_Verdef(void * dest,const void * src,size_t len,int encode)37 elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
38 {
39   /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
40      To recognize them we have to walk the data structure and convert
41      them one after the other.  The ENCODE parameter specifies whether
42      we are encoding or decoding.  When we are encoding we can immediately
43      use the data in the buffer; if not, we have to decode the data before
44      using it.  */
45   size_t def_offset = 0;
46   GElf_Verdef *ddest;
47   GElf_Verdef *dsrc;
48 
49   /* We rely on the types being all the same size.  */
50   assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
51   assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
52   assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
53   assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
54 
55   if (len == 0)
56     return;
57 
58   /* Below we rely on the next field offsets to be correct, start by
59      copying over all data as is in case some data isn't translated.
60      We don't want to leave (undefined) garbage in the dest buffer.  */
61   memmove (dest, src, len);
62 
63   do
64     {
65       size_t aux_offset;
66       GElf_Verdaux *asrc;
67 
68       /* Test for correct offset.  */
69       if (def_offset > len || len - def_offset < sizeof (GElf_Verdef))
70 	return;
71 
72       /* Work the tree from the first record.  */
73       ddest = (GElf_Verdef *) ((char *) dest + def_offset);
74       dsrc = (GElf_Verdef *) ((char *) src + def_offset);
75 
76       /* Decode first if necessary.  */
77       if (! encode)
78 	{
79 	  ddest->vd_version = bswap_16 (dsrc->vd_version);
80 	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
81 	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
82 	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
83 	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
84 	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
85 	  ddest->vd_next = bswap_32 (dsrc->vd_next);
86 
87 	  aux_offset = def_offset + ddest->vd_aux;
88 	}
89       else
90 	aux_offset = def_offset + dsrc->vd_aux;
91 
92       /* Handle all the auxiliary records belonging to this definition.  */
93       do
94 	{
95 	  GElf_Verdaux *adest;
96 
97 	  /* Test for correct offset.  */
98 	  if (aux_offset > len || len - aux_offset < sizeof (GElf_Verdaux))
99 	    return;
100 
101 	  adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
102 	  asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
103 
104 	  if (encode)
105 	    aux_offset += asrc->vda_next;
106 
107 	  adest->vda_name = bswap_32 (asrc->vda_name);
108 	  adest->vda_next = bswap_32 (asrc->vda_next);
109 
110 	  if (! encode)
111 	    aux_offset += adest->vda_next;
112 	}
113       while (asrc->vda_next != 0);
114 
115       /* Encode now if necessary.  */
116       if (encode)
117 	{
118 	  def_offset += dsrc->vd_next;
119 
120 	  ddest->vd_version = bswap_16 (dsrc->vd_version);
121 	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
122 	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
123 	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
124 	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
125 	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
126 	  ddest->vd_next = bswap_32 (dsrc->vd_next);
127 	}
128       else
129 	def_offset += ddest->vd_next;
130     }
131   while (dsrc->vd_next != 0);
132 }
133 
134 
135 static void
elf_cvt_Verneed(void * dest,const void * src,size_t len,int encode)136 elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
137 {
138   /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
139      To recognize them we have to walk the data structure and convert
140      them one after the other.  The ENCODE parameter specifies whether
141      we are encoding or decoding.  When we are encoding we can immediately
142      use the data in the buffer; if not, we have to decode the data before
143      using it.  */
144   size_t need_offset = 0;
145   GElf_Verneed *ndest;
146   GElf_Verneed *nsrc;
147 
148   /* We rely on the types being all the same size.  */
149   assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
150   assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
151   assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
152   assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
153 
154   if (len == 0)
155     return;
156 
157   /* Below we rely on the next field offsets to be correct, start by
158      copying over all data as is in case some data isn't translated.
159      We don't want to leave (undefined) garbage in the dest buffer.  */
160   memmove (dest, src, len);
161 
162   do
163     {
164       size_t aux_offset;
165       GElf_Vernaux *asrc;
166 
167       /* Test for correct offset.  */
168       if (need_offset > len || len - need_offset < sizeof (GElf_Verneed))
169 	return;
170 
171       /* Work the tree from the first record.  */
172       ndest = (GElf_Verneed *) ((char *) dest + need_offset);
173       nsrc = (GElf_Verneed *) ((char *) src + need_offset);
174 
175       /* Decode first if necessary.  */
176       if (! encode)
177 	{
178 	  ndest->vn_version = bswap_16 (nsrc->vn_version);
179 	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
180 	  ndest->vn_file = bswap_32 (nsrc->vn_file);
181 	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
182 	  ndest->vn_next = bswap_32 (nsrc->vn_next);
183 
184 	  aux_offset = need_offset + ndest->vn_aux;
185 	}
186       else
187 	aux_offset = need_offset + nsrc->vn_aux;
188 
189       /* Handle all the auxiliary records belonging to this requirement.  */
190       do
191 	{
192 	  GElf_Vernaux *adest;
193 
194 	  /* Test for correct offset.  */
195 	  if (aux_offset > len || len - aux_offset < sizeof (GElf_Vernaux))
196 	    return;
197 
198 	  adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
199 	  asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
200 
201 	  if (encode)
202 	    aux_offset += asrc->vna_next;
203 
204 	  adest->vna_hash = bswap_32 (asrc->vna_hash);
205 	  adest->vna_flags = bswap_16 (asrc->vna_flags);
206 	  adest->vna_other = bswap_16 (asrc->vna_other);
207 	  adest->vna_name = bswap_32 (asrc->vna_name);
208 	  adest->vna_next = bswap_32 (asrc->vna_next);
209 
210 	  if (! encode)
211 	    aux_offset += adest->vna_next;
212 	}
213       while (asrc->vna_next != 0);
214 
215       /* Encode now if necessary.  */
216       if (encode)
217 	{
218 	  need_offset += nsrc->vn_next;
219 
220 	  ndest->vn_version = bswap_16 (nsrc->vn_version);
221 	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
222 	  ndest->vn_file = bswap_32 (nsrc->vn_file);
223 	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
224 	  ndest->vn_next = bswap_32 (nsrc->vn_next);
225 	}
226       else
227 	need_offset += ndest->vn_next;
228     }
229   while (nsrc->vn_next != 0);
230 }
231