]> git.ipfire.org Git - thirdparty/elfutils.git/blame - libelf/version_xlate.h
funcretval-struct
[thirdparty/elfutils.git] / libelf / version_xlate.h
CommitLineData
b08d5a8f 1/* Conversion functions for versioning information.
59c1f123 2 Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
0346d5fd 3 Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
de2ed97f 4 This file is part of elfutils.
b08d5a8f
UD
5 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6
de2ed97f
MW
7 This file is free software; you can redistribute it and/or modify
8 it under the terms of either
b08d5a8f 9
de2ed97f
MW
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
361df7da
UD
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.
b08d5a8f 26
de2ed97f
MW
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/>. */
b08d5a8f
UD
30
31#include <assert.h>
32#include <gelf.h>
33
34#include "libelfP.h"
35
36
37static void
38elf_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
59c1f123
MW
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
b08d5a8f
UD
64 do
65 {
66 size_t aux_offset;
67 GElf_Verdaux *asrc;
68
69 /* Test for correct offset. */
0346d5fd
MW
70 if (def_offset > len
71 || len - def_offset < sizeof (GElf_Verdef)
72 || (def_offset & (__alignof__ (GElf_Verdef) - 1)) != 0)
b08d5a8f
UD
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
2785ba7a
MW
90 if (ddest->vd_aux > len - def_offset)
91 return;
b08d5a8f
UD
92 aux_offset = def_offset + ddest->vd_aux;
93 }
94 else
2785ba7a
MW
95 {
96 if (dsrc->vd_aux > len - def_offset)
97 return;
98 aux_offset = def_offset + dsrc->vd_aux;
99 }
b08d5a8f
UD
100
101 /* Handle all the auxiliary records belonging to this definition. */
102 do
103 {
104 GElf_Verdaux *adest;
105
106 /* Test for correct offset. */
0346d5fd
MW
107 if (aux_offset > len
108 || len - aux_offset < sizeof (GElf_Verdaux)
109 || (aux_offset & (__alignof__ (GElf_Verdaux) - 1)) != 0)
b08d5a8f
UD
110 return;
111
112 adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
113 asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
114
115 if (encode)
2785ba7a
MW
116 {
117 if (asrc->vda_next > len - aux_offset)
118 return;
119 aux_offset += asrc->vda_next;
120 }
b08d5a8f
UD
121
122 adest->vda_name = bswap_32 (asrc->vda_name);
123 adest->vda_next = bswap_32 (asrc->vda_next);
124
125 if (! encode)
2785ba7a
MW
126 {
127 if (adest->vda_next > len - aux_offset)
128 return;
129 aux_offset += adest->vda_next;
130 }
b08d5a8f
UD
131 }
132 while (asrc->vda_next != 0);
133
134 /* Encode now if necessary. */
135 if (encode)
136 {
2785ba7a
MW
137 if (dsrc->vd_next > len - def_offset)
138 return;
b08d5a8f
UD
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
2785ba7a
MW
150 {
151 if (ddest->vd_next > len - def_offset)
152 return;
153 def_offset += ddest->vd_next;
154 }
b08d5a8f
UD
155 }
156 while (dsrc->vd_next != 0);
157}
158
159
160static void
161elf_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
59c1f123
MW
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
b08d5a8f
UD
187 do
188 {
189 size_t aux_offset;
190 GElf_Vernaux *asrc;
191
192 /* Test for correct offset. */
0346d5fd
MW
193 if (need_offset > len
194 || len - need_offset < sizeof (GElf_Verneed)
195 || (need_offset & (__alignof__ (GElf_Verneed) - 1)) != 0)
b08d5a8f
UD
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
2785ba7a
MW
211 if (ndest->vn_aux > len - need_offset)
212 return;
b08d5a8f
UD
213 aux_offset = need_offset + ndest->vn_aux;
214 }
215 else
2785ba7a
MW
216 {
217 if (nsrc->vn_aux > len - need_offset)
218 return;
219 aux_offset = need_offset + nsrc->vn_aux;
220 }
b08d5a8f
UD
221
222 /* Handle all the auxiliary records belonging to this requirement. */
223 do
224 {
225 GElf_Vernaux *adest;
226
227 /* Test for correct offset. */
0346d5fd
MW
228 if (aux_offset > len
229 || len - aux_offset < sizeof (GElf_Vernaux)
230 || (aux_offset & (__alignof__ (GElf_Vernaux) - 1)) != 0)
b08d5a8f
UD
231 return;
232
233 adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
234 asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
235
236 if (encode)
2785ba7a
MW
237 {
238 if (asrc->vna_next > len - aux_offset)
239 return;
240 aux_offset += asrc->vna_next;
241 }
b08d5a8f
UD
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)
2785ba7a
MW
250 {
251 if (adest->vna_next > len - aux_offset)
252 return;
253 aux_offset += adest->vna_next;
254 }
b08d5a8f
UD
255 }
256 while (asrc->vna_next != 0);
257
258 /* Encode now if necessary. */
259 if (encode)
260 {
2785ba7a
MW
261 if (nsrc->vn_next > len - need_offset)
262 return;
b08d5a8f
UD
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
2785ba7a
MW
272 {
273 if (ndest->vn_next > len - need_offset)
274 return;
275 need_offset += ndest->vn_next;
276 }
b08d5a8f
UD
277 }
278 while (nsrc->vn_next != 0);
279}