|
1 /* |
|
2 * 32.xlatetof.c - implementation of the elf32_xlateto[fm](3) functions. |
|
3 * Copyright (C) 1995 - 2006 Michael Riepe |
|
4 * |
|
5 * This library is free software; you can redistribute it and/or |
|
6 * modify it under the terms of the GNU Library General Public |
|
7 * License as published by the Free Software Foundation; either |
|
8 * version 2 of the License, or (at your option) any later version. |
|
9 * |
|
10 * This library is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 * Library General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Library General Public |
|
16 * License along with this library; if not, write to the Free Software |
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 */ |
|
19 |
|
20 #include <private.h> |
|
21 #include <ext_types.h> |
|
22 #include <byteswap.h> |
|
23 |
|
24 #ifndef lint |
|
25 static const char rcsid[] = "@(#) $Id: 32.xlatetof.c,v 1.26 2006/07/27 22:33:40 michael Exp $"; |
|
26 #endif /* lint */ |
|
27 |
|
28 /* |
|
29 * Ugly, ugly |
|
30 */ |
|
31 #ifdef _WIN32 |
|
32 # define Cat2(a,b)a##b |
|
33 # define Cat3(a,b,c)a##b##c |
|
34 # define Ex1(m1,m2,a,b)m1##m2(a##b) |
|
35 # define Ex2(m1,m2,a,b,c)m1##m2(a,b##c) |
|
36 #else /* _WIN32 */ |
|
37 # define x |
|
38 # if defined/**/x |
|
39 # define Cat2(a,b)a##b |
|
40 # define Cat3(a,b,c)a##b##c |
|
41 # define Ex1(m1,m2,a,b)m1##m2(a##b) |
|
42 # define Ex2(m1,m2,a,b,c)m1##m2(a,b##c) |
|
43 # else |
|
44 # define Cat2(a,b)a/**/b |
|
45 # define Cat3(a,b,c)a/**/b/**/c |
|
46 # define Ex1(m1,m2,a,b)m1/**/m2(a/**/b) |
|
47 # define Ex2(m1,m2,a,b,c)m1/**/m2(a,b/**/c) |
|
48 # endif |
|
49 # undef x |
|
50 #endif /* _WIN32 */ |
|
51 |
|
52 /* |
|
53 * auxiliary macros for execution order reversal |
|
54 */ |
|
55 #define seq_forw(a,b) a b |
|
56 #define seq_back(a,b) b a |
|
57 |
|
58 /* |
|
59 * function instantiator |
|
60 */ |
|
61 #define copy_type_e_io(name,e,io,tfrom,tto,copy) \ |
|
62 static size_t \ |
|
63 Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) { \ |
|
64 n /= sizeof(tfrom); \ |
|
65 if (n && dst) { \ |
|
66 const tfrom *from = (const tfrom*)src; \ |
|
67 tto *to = (tto*)dst; \ |
|
68 size_t i; \ |
|
69 \ |
|
70 if (sizeof(tfrom) < sizeof(tto)) { \ |
|
71 from += n; \ |
|
72 to += n; \ |
|
73 for (i = 0; i < n; i++) { \ |
|
74 --from; \ |
|
75 --to; \ |
|
76 copy(e,io,seq_back) \ |
|
77 } \ |
|
78 } \ |
|
79 else { \ |
|
80 for (i = 0; i < n; i++) { \ |
|
81 copy(e,io,seq_forw) \ |
|
82 from++; \ |
|
83 to++; \ |
|
84 } \ |
|
85 } \ |
|
86 } \ |
|
87 return n * sizeof(tto); \ |
|
88 } |
|
89 |
|
90 #define copy_type_e(name,e,type,copy) \ |
|
91 copy_type_e_io(name,e,tom,Cat2(__ext_,type),type,copy) \ |
|
92 copy_type_e_io(name,e,tof,type,Cat2(__ext_,type),copy) |
|
93 |
|
94 /* |
|
95 * master function instantiator |
|
96 */ |
|
97 #define copy_type(name,version,type,copy) \ |
|
98 copy_type_e(Cat3(name,L,version),L,type,copy) \ |
|
99 copy_type_e(Cat3(name,M,version),M,type,copy) |
|
100 |
|
101 /* |
|
102 * scalar copying |
|
103 */ |
|
104 #define copy_scalar_tom(type) *to = Cat2(__load_,type)(*from); |
|
105 #define copy_scalar_tof(type) Cat2(__store_,type)(*to, *from); |
|
106 |
|
107 /* |
|
108 * structure member copying |
|
109 */ |
|
110 #define copy_tom(mb,type) to->mb = Cat2(__load_,type)(from->mb); |
|
111 #define copy_tof(mb,type) Cat2(__store_,type)(to->mb, from->mb); |
|
112 |
|
113 /* |
|
114 * structure member copying (direction independent) |
|
115 */ |
|
116 #define copy_byte(e,io,mb) to->mb = from->mb; |
|
117 #define copy_addr(e,io,mb) Ex2(copy_,io,mb,u32,e) |
|
118 #define copy_half(e,io,mb) Ex2(copy_,io,mb,u16,e) |
|
119 #define copy_off(e,io,mb) Ex2(copy_,io,mb,u32,e) |
|
120 #define copy_sword(e,io,mb) Ex2(copy_,io,mb,i32,e) |
|
121 #define copy_word(e,io,mb) Ex2(copy_,io,mb,u32,e) |
|
122 #define copy_arr(e,io,mb) \ |
|
123 array_copy(to->mb, sizeof(to->mb), from->mb, sizeof(from->mb)); |
|
124 |
|
125 /* |
|
126 * scalar copying (direction independent) |
|
127 * these macros are used as `copy' arguments to copy_type() |
|
128 */ |
|
129 #define copy_addr_11(e,io,seq) Ex1(copy_scalar_,io,u32,e) |
|
130 #define copy_half_11(e,io,seq) Ex1(copy_scalar_,io,u16,e) |
|
131 #define copy_off_11(e,io,seq) Ex1(copy_scalar_,io,u32,e) |
|
132 #define copy_sword_11(e,io,seq) Ex1(copy_scalar_,io,i32,e) |
|
133 #define copy_word_11(e,io,seq) Ex1(copy_scalar_,io,u32,e) |
|
134 |
|
135 /* |
|
136 * structure copying (direction independent) |
|
137 * these macros are used as `copy' arguments to copy_type() |
|
138 */ |
|
139 #define copy_dyn_11(e,io,seq) \ |
|
140 seq(copy_sword(e,io,d_tag), \ |
|
141 seq(copy_addr(e,io,d_un.d_ptr), \ |
|
142 nullcopy)) |
|
143 #define copy_ehdr_11(e,io,seq) \ |
|
144 seq(copy_arr(e,io,e_ident), \ |
|
145 seq(copy_half(e,io,e_type), \ |
|
146 seq(copy_half(e,io,e_machine), \ |
|
147 seq(copy_word(e,io,e_version), \ |
|
148 seq(copy_addr(e,io,e_entry), \ |
|
149 seq(copy_off(e,io,e_phoff), \ |
|
150 seq(copy_off(e,io,e_shoff), \ |
|
151 seq(copy_word(e,io,e_flags), \ |
|
152 seq(copy_half(e,io,e_ehsize), \ |
|
153 seq(copy_half(e,io,e_phentsize), \ |
|
154 seq(copy_half(e,io,e_phnum), \ |
|
155 seq(copy_half(e,io,e_shentsize), \ |
|
156 seq(copy_half(e,io,e_shnum), \ |
|
157 seq(copy_half(e,io,e_shstrndx), \ |
|
158 nullcopy)))))))))))))) |
|
159 #define copy_phdr_11(e,io,seq) \ |
|
160 seq(copy_word(e,io,p_type), \ |
|
161 seq(copy_off(e,io,p_offset), \ |
|
162 seq(copy_addr(e,io,p_vaddr), \ |
|
163 seq(copy_addr(e,io,p_paddr), \ |
|
164 seq(copy_word(e,io,p_filesz), \ |
|
165 seq(copy_word(e,io,p_memsz), \ |
|
166 seq(copy_word(e,io,p_flags), \ |
|
167 seq(copy_word(e,io,p_align), \ |
|
168 nullcopy)))))))) |
|
169 #define copy_rela_11(e,io,seq) \ |
|
170 seq(copy_addr(e,io,r_offset), \ |
|
171 seq(copy_word(e,io,r_info), \ |
|
172 seq(copy_sword(e,io,r_addend), \ |
|
173 nullcopy))) |
|
174 #define copy_rel_11(e,io,seq) \ |
|
175 seq(copy_addr(e,io,r_offset), \ |
|
176 seq(copy_word(e,io,r_info), \ |
|
177 nullcopy)) |
|
178 #define copy_shdr_11(e,io,seq) \ |
|
179 seq(copy_word(e,io,sh_name), \ |
|
180 seq(copy_word(e,io,sh_type), \ |
|
181 seq(copy_word(e,io,sh_flags), \ |
|
182 seq(copy_addr(e,io,sh_addr), \ |
|
183 seq(copy_off(e,io,sh_offset), \ |
|
184 seq(copy_word(e,io,sh_size), \ |
|
185 seq(copy_word(e,io,sh_link), \ |
|
186 seq(copy_word(e,io,sh_info), \ |
|
187 seq(copy_word(e,io,sh_addralign), \ |
|
188 seq(copy_word(e,io,sh_entsize), \ |
|
189 nullcopy)))))))))) |
|
190 #define copy_sym_11(e,io,seq) \ |
|
191 seq(copy_word(e,io,st_name), \ |
|
192 seq(copy_addr(e,io,st_value), \ |
|
193 seq(copy_word(e,io,st_size), \ |
|
194 seq(copy_byte(e,io,st_info), \ |
|
195 seq(copy_byte(e,io,st_other), \ |
|
196 seq(copy_half(e,io,st_shndx), \ |
|
197 nullcopy)))))) |
|
198 |
|
199 #define nullcopy /**/ |
|
200 |
|
201 static size_t |
|
202 byte_copy(unsigned char *dst, const unsigned char *src, size_t n) { |
|
203 if (n && dst && dst != src) { |
|
204 #if HAVE_BROKEN_MEMMOVE |
|
205 size_t i; |
|
206 |
|
207 if (dst >= src + n || dst + n <= src) { |
|
208 memcpy(dst, src, n); |
|
209 } |
|
210 else if (dst < src) { |
|
211 for (i = 0; i < n; i++) { |
|
212 dst[i] = src[i]; |
|
213 } |
|
214 } |
|
215 else { |
|
216 for (i = n; --i; ) { |
|
217 dst[i] = src[i]; |
|
218 } |
|
219 } |
|
220 #else /* HAVE_BROKEN_MEMMOVE */ |
|
221 memmove(dst, src, n); |
|
222 #endif /* HAVE_BROKEN_MEMMOVE */ |
|
223 } |
|
224 return n; |
|
225 } |
|
226 |
|
227 static void |
|
228 array_copy(unsigned char *dst, size_t dlen, const unsigned char *src, size_t slen) { |
|
229 byte_copy(dst, src, dlen < slen ? dlen : slen); |
|
230 if (dlen > slen) { |
|
231 memset(dst + slen, 0, dlen - slen); |
|
232 } |
|
233 } |
|
234 |
|
235 /* |
|
236 * instantiate copy functions |
|
237 */ |
|
238 copy_type(addr_32,_,Elf32_Addr,copy_addr_11) |
|
239 copy_type(half_32,_,Elf32_Half,copy_half_11) |
|
240 copy_type(off_32,_,Elf32_Off,copy_off_11) |
|
241 copy_type(sword_32,_,Elf32_Sword,copy_sword_11) |
|
242 copy_type(word_32,_,Elf32_Word,copy_word_11) |
|
243 copy_type(dyn_32,11,Elf32_Dyn,copy_dyn_11) |
|
244 copy_type(ehdr_32,11,Elf32_Ehdr,copy_ehdr_11) |
|
245 copy_type(phdr_32,11,Elf32_Phdr,copy_phdr_11) |
|
246 copy_type(rela_32,11,Elf32_Rela,copy_rela_11) |
|
247 copy_type(rel_32,11,Elf32_Rel,copy_rel_11) |
|
248 copy_type(shdr_32,11,Elf32_Shdr,copy_shdr_11) |
|
249 copy_type(sym_32,11,Elf32_Sym,copy_sym_11) |
|
250 |
|
251 typedef size_t (*xlator)(unsigned char*, const unsigned char*, size_t); |
|
252 typedef xlator xltab[ELF_T_NUM][2]; |
|
253 |
|
254 /* |
|
255 * translation table (32-bit, version 1 -> version 1) |
|
256 */ |
|
257 #if PIC |
|
258 static xltab |
|
259 #else /* PIC */ |
|
260 static const xltab |
|
261 #endif /* PIC */ |
|
262 xlate32_11[/*encoding*/] = { |
|
263 { |
|
264 { byte_copy, byte_copy }, |
|
265 { addr_32L__tom, addr_32L__tof }, |
|
266 { dyn_32L11_tom, dyn_32L11_tof }, |
|
267 { ehdr_32L11_tom, ehdr_32L11_tof }, |
|
268 { half_32L__tom, half_32L__tof }, |
|
269 { off_32L__tom, off_32L__tof }, |
|
270 { phdr_32L11_tom, phdr_32L11_tof }, |
|
271 { rela_32L11_tom, rela_32L11_tof }, |
|
272 { rel_32L11_tom, rel_32L11_tof }, |
|
273 { shdr_32L11_tom, shdr_32L11_tof }, |
|
274 { sword_32L__tom, sword_32L__tof }, |
|
275 { sym_32L11_tom, sym_32L11_tof }, |
|
276 { word_32L__tom, word_32L__tof }, |
|
277 { 0, 0 }, /* there is no Sxword */ |
|
278 { 0, 0 }, /* there is no Xword */ |
|
279 #if __LIBELF_SYMBOL_VERSIONS |
|
280 { _elf_verdef_32L11_tom, _elf_verdef_32L11_tof }, |
|
281 { _elf_verneed_32L11_tom, _elf_verneed_32L11_tof }, |
|
282 #else /* __LIBELF_SYMBOL_VERSIONS */ |
|
283 { 0, 0 }, |
|
284 { 0, 0 }, |
|
285 #endif /* __LIBELF_SYMBOL_VERSIONS */ |
|
286 }, |
|
287 { |
|
288 { byte_copy, byte_copy }, |
|
289 { addr_32M__tom, addr_32M__tof }, |
|
290 { dyn_32M11_tom, dyn_32M11_tof }, |
|
291 { ehdr_32M11_tom, ehdr_32M11_tof }, |
|
292 { half_32M__tom, half_32M__tof }, |
|
293 { off_32M__tom, off_32M__tof }, |
|
294 { phdr_32M11_tom, phdr_32M11_tof }, |
|
295 { rela_32M11_tom, rela_32M11_tof }, |
|
296 { rel_32M11_tom, rel_32M11_tof }, |
|
297 { shdr_32M11_tom, shdr_32M11_tof }, |
|
298 { sword_32M__tom, sword_32M__tof }, |
|
299 { sym_32M11_tom, sym_32M11_tof }, |
|
300 { word_32M__tom, word_32M__tof }, |
|
301 { 0, 0 }, /* there is no Sxword */ |
|
302 { 0, 0 }, /* there is no Xword */ |
|
303 #if __LIBELF_SYMBOL_VERSIONS |
|
304 { _elf_verdef_32M11_tom, _elf_verdef_32M11_tof }, |
|
305 { _elf_verneed_32M11_tom, _elf_verneed_32M11_tof }, |
|
306 #else /* __LIBELF_SYMBOL_VERSIONS */ |
|
307 { 0, 0 }, |
|
308 { 0, 0 }, |
|
309 #endif /* __LIBELF_SYMBOL_VERSIONS */ |
|
310 }, |
|
311 }; |
|
312 |
|
313 /* |
|
314 * main translation table (32-bit) |
|
315 */ |
|
316 #if PIC |
|
317 static xltab* |
|
318 #else /* PIC */ |
|
319 static const xltab *const |
|
320 #endif /* PIC */ |
|
321 xlate32[EV_CURRENT - EV_NONE][EV_CURRENT - EV_NONE] = { |
|
322 { xlate32_11, }, |
|
323 }; |
|
324 |
|
325 #define translator(sv,dv,enc,type,d) \ |
|
326 (xlate32[(sv) - EV_NONE - 1] \ |
|
327 [(dv) - EV_NONE - 1] \ |
|
328 [(enc) - ELFDATA2LSB] \ |
|
329 [(type) - ELF_T_BYTE] \ |
|
330 [d]) |
|
331 |
|
332 /* |
|
333 * destination buffer size |
|
334 */ |
|
335 size_t |
|
336 _elf32_xltsize(const Elf_Data *src, unsigned dv, unsigned encode, int tof) { |
|
337 Elf_Type type = src->d_type; |
|
338 unsigned sv = src->d_version; |
|
339 xlator op; |
|
340 |
|
341 if (!valid_version(sv) || !valid_version(dv)) { |
|
342 seterr(ERROR_UNKNOWN_VERSION); |
|
343 return (size_t)-1; |
|
344 } |
|
345 if (tof) { |
|
346 /* |
|
347 * Encoding doesn't really matter (the translator only looks at |
|
348 * the source, which resides in memory), but we need a proper |
|
349 * encoding to select a translator... |
|
350 */ |
|
351 encode = ELFDATA2LSB; |
|
352 } |
|
353 else if (!valid_encoding(encode)) { |
|
354 seterr(ERROR_UNKNOWN_ENCODING); |
|
355 return (size_t)-1; |
|
356 } |
|
357 if (!valid_type(type)) { |
|
358 seterr(ERROR_UNKNOWN_TYPE); |
|
359 return (size_t)-1; |
|
360 } |
|
361 if (!(op = translator(sv, dv, encode, type, tof))) { |
|
362 seterr(ERROR_UNKNOWN_TYPE); |
|
363 return (size_t)-1; |
|
364 } |
|
365 return (*op)(NULL, src->d_buf, src->d_size); |
|
366 } |
|
367 |
|
368 /* |
|
369 * direction-independent translation |
|
370 */ |
|
371 static Elf_Data* |
|
372 elf32_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) { |
|
373 Elf_Type type; |
|
374 int dv; |
|
375 int sv; |
|
376 size_t dsize; |
|
377 size_t tmp; |
|
378 xlator op; |
|
379 |
|
380 if (!src || !dst) { |
|
381 return NULL; |
|
382 } |
|
383 if (!src->d_buf || !dst->d_buf) { |
|
384 seterr(ERROR_NULLBUF); |
|
385 return NULL; |
|
386 } |
|
387 if (!valid_encoding(encode)) { |
|
388 seterr(ERROR_UNKNOWN_ENCODING); |
|
389 return NULL; |
|
390 } |
|
391 sv = src->d_version; |
|
392 dv = dst->d_version; |
|
393 if (!valid_version(sv) || !valid_version(dv)) { |
|
394 seterr(ERROR_UNKNOWN_VERSION); |
|
395 return NULL; |
|
396 } |
|
397 type = src->d_type; |
|
398 if (!valid_type(type)) { |
|
399 seterr(ERROR_UNKNOWN_TYPE); |
|
400 return NULL; |
|
401 } |
|
402 op = translator(sv, dv, encode, type, tof); |
|
403 if (!op) { |
|
404 seterr(ERROR_UNKNOWN_TYPE); |
|
405 return NULL; |
|
406 } |
|
407 dsize = (*op)(NULL, src->d_buf, src->d_size); |
|
408 if (dsize == (size_t)-1) { |
|
409 return NULL; |
|
410 } |
|
411 if (dst->d_size < dsize) { |
|
412 seterr(ERROR_DST2SMALL); |
|
413 return NULL; |
|
414 } |
|
415 if (dsize) { |
|
416 tmp = (*op)(dst->d_buf, src->d_buf, src->d_size); |
|
417 if (tmp == (size_t)-1) { |
|
418 return NULL; |
|
419 } |
|
420 elf_assert(tmp == dsize); |
|
421 } |
|
422 dst->d_size = dsize; |
|
423 dst->d_type = type; |
|
424 return dst; |
|
425 } |
|
426 |
|
427 /* |
|
428 * finally, the "official" translation functions |
|
429 */ |
|
430 Elf_Data* |
|
431 elf32_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned encode) { |
|
432 return elf32_xlate(dst, src, encode, 0); |
|
433 } |
|
434 |
|
435 Elf_Data* |
|
436 elf32_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned encode) { |
|
437 return elf32_xlate(dst, src, encode, 1); |
|
438 } |