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