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