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