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