]>
Commit | Line | Data |
---|---|---|
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 | ||
37 | static void | |
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 | ||
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 | ||
160 | static void | |
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 | ||
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 | } |