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