|
1 /* |
|
2 * cook.c - read and translate ELF files. |
|
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 |
|
22 #ifndef lint |
|
23 static const char rcsid[] = "@(#) $Id: cook.c,v 1.28 2006/07/07 22:15:50 michael Exp $"; |
|
24 #endif /* lint */ |
|
25 |
|
26 const Elf_Scn _elf_scn_init = INIT_SCN; |
|
27 const Scn_Data _elf_data_init = INIT_DATA; |
|
28 |
|
29 Elf_Type |
|
30 _elf_scn_type(unsigned t) { |
|
31 switch (t) { |
|
32 case SHT_DYNAMIC: return ELF_T_DYN; |
|
33 case SHT_DYNSYM: return ELF_T_SYM; |
|
34 case SHT_HASH: return ELF_T_WORD; |
|
35 case SHT_REL: return ELF_T_REL; |
|
36 case SHT_RELA: return ELF_T_RELA; |
|
37 case SHT_SYMTAB: return ELF_T_SYM; |
|
38 case SHT_SYMTAB_SHNDX: return ELF_T_WORD; /* XXX: really? */ |
|
39 #if __LIBELF_SYMBOL_VERSIONS |
|
40 #if __LIBELF_SUN_SYMBOL_VERSIONS |
|
41 case SHT_SUNW_verdef: return ELF_T_VDEF; |
|
42 case SHT_SUNW_verneed: return ELF_T_VNEED; |
|
43 case SHT_SUNW_versym: return ELF_T_HALF; |
|
44 #else /* __LIBELF_SUN_SYMBOL_VERSIONS */ |
|
45 case SHT_GNU_verdef: return ELF_T_VDEF; |
|
46 case SHT_GNU_verneed: return ELF_T_VNEED; |
|
47 case SHT_GNU_versym: return ELF_T_HALF; |
|
48 #endif /* __LIBELF_SUN_SYMBOL_VERSIONS */ |
|
49 #endif /* __LIBELF_SYMBOL_VERSIONS */ |
|
50 } |
|
51 return ELF_T_BYTE; |
|
52 } |
|
53 |
|
54 /* |
|
55 * Check for overflow on 32-bit systems |
|
56 */ |
|
57 #define overflow(a,b,t) (sizeof(a) < sizeof(t) && (t)(a) != (b)) |
|
58 |
|
59 #define truncerr(t) ((t)==ELF_T_EHDR?ERROR_TRUNC_EHDR: \ |
|
60 ((t)==ELF_T_PHDR?ERROR_TRUNC_PHDR: \ |
|
61 ERROR_INTERNAL)) |
|
62 #define memerr(t) ((t)==ELF_T_EHDR?ERROR_MEM_EHDR: \ |
|
63 ((t)==ELF_T_PHDR?ERROR_MEM_PHDR: \ |
|
64 ERROR_INTERNAL)) |
|
65 |
|
66 Elf_Data* |
|
67 _elf_xlatetom(const Elf *elf, Elf_Data *dst, const Elf_Data *src) { |
|
68 if (elf->e_class == ELFCLASS32) { |
|
69 return elf32_xlatetom(dst, src, elf->e_encoding); |
|
70 } |
|
71 #if __LIBELF64 |
|
72 else if (elf->e_class == ELFCLASS64) { |
|
73 return elf64_xlatetom(dst, src, elf->e_encoding); |
|
74 } |
|
75 #endif /* __LIBELF64 */ |
|
76 seterr(ERROR_UNIMPLEMENTED); |
|
77 return NULL; |
|
78 } |
|
79 |
|
80 static char* |
|
81 _elf_item(void *buf, Elf *elf, Elf_Type type, size_t off) { |
|
82 Elf_Data src, dst; |
|
83 |
|
84 elf_assert(valid_type(type)); |
|
85 if (off < 0 || off > elf->e_size) { |
|
86 seterr(ERROR_OUTSIDE); |
|
87 return NULL; |
|
88 } |
|
89 |
|
90 src.d_type = type; |
|
91 src.d_version = elf->e_version; |
|
92 src.d_size = _fsize(elf->e_class, src.d_version, type); |
|
93 elf_assert(src.d_size); |
|
94 if ((elf->e_size - off) < src.d_size) { |
|
95 seterr(truncerr(type)); |
|
96 return NULL; |
|
97 } |
|
98 |
|
99 dst.d_version = _elf_version; |
|
100 dst.d_size = _msize(elf->e_class, dst.d_version, type); |
|
101 elf_assert(dst.d_size); |
|
102 |
|
103 if (!(dst.d_buf = buf) && !(dst.d_buf = malloc(dst.d_size))) { |
|
104 seterr(memerr(type)); |
|
105 return NULL; |
|
106 } |
|
107 |
|
108 elf_assert(elf->e_data); |
|
109 if (elf->e_rawdata) { |
|
110 src.d_buf = elf->e_rawdata + off; |
|
111 } |
|
112 else { |
|
113 src.d_buf = elf->e_data + off; |
|
114 } |
|
115 |
|
116 if (_elf_xlatetom(elf, &dst, &src)) { |
|
117 return (char*)dst.d_buf; |
|
118 } |
|
119 if (dst.d_buf != buf) { |
|
120 free(dst.d_buf); |
|
121 } |
|
122 return NULL; |
|
123 } |
|
124 |
|
125 static int |
|
126 _elf_cook_phdr(Elf *elf) { |
|
127 size_t num, off, entsz; |
|
128 |
|
129 if (elf->e_class == ELFCLASS32) { |
|
130 num = ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum; |
|
131 off = ((Elf32_Ehdr*)elf->e_ehdr)->e_phoff; |
|
132 entsz = ((Elf32_Ehdr*)elf->e_ehdr)->e_phentsize; |
|
133 } |
|
134 #if __LIBELF64 |
|
135 else if (elf->e_class == ELFCLASS64) { |
|
136 num = ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum; |
|
137 off = ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff; |
|
138 entsz = ((Elf64_Ehdr*)elf->e_ehdr)->e_phentsize; |
|
139 /* |
|
140 * Check for overflow on 32-bit systems |
|
141 */ |
|
142 if (overflow(off, ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff, Elf64_Off)) { |
|
143 seterr(ERROR_OUTSIDE); |
|
144 return 0; |
|
145 } |
|
146 } |
|
147 #endif /* __LIBELF64 */ |
|
148 else { |
|
149 seterr(ERROR_UNIMPLEMENTED); |
|
150 return 0; |
|
151 } |
|
152 if (off) { |
|
153 Elf_Scn *scn; |
|
154 size_t size; |
|
155 unsigned i; |
|
156 char *p; |
|
157 |
|
158 if (num == PN_XNUM) { |
|
159 /* |
|
160 * Overflow in ehdr->e_phnum. |
|
161 * Get real value from first SHDR. |
|
162 */ |
|
163 if (!(scn = elf->e_scn_1)) { |
|
164 seterr(ERROR_NOSUCHSCN); |
|
165 return 0; |
|
166 } |
|
167 if (elf->e_class == ELFCLASS32) { |
|
168 num = scn->s_shdr32.sh_info; |
|
169 } |
|
170 #if __LIBELF64 |
|
171 else if (elf->e_class == ELFCLASS64) { |
|
172 num = scn->s_shdr64.sh_info; |
|
173 } |
|
174 #endif /* __LIBELF64 */ |
|
175 /* we already had this |
|
176 else { |
|
177 seterr(ERROR_UNIMPLEMENTED); |
|
178 return 0; |
|
179 } |
|
180 */ |
|
181 } |
|
182 |
|
183 size = _fsize(elf->e_class, elf->e_version, ELF_T_PHDR); |
|
184 elf_assert(size); |
|
185 #if ENABLE_EXTENDED_FORMAT |
|
186 if (entsz < size) { |
|
187 #else /* ENABLE_EXTENDED_FORMAT */ |
|
188 if (entsz != size) { |
|
189 #endif /* ENABLE_EXTENDED_FORMAT */ |
|
190 seterr(ERROR_EHDR_PHENTSIZE); |
|
191 return 0; |
|
192 } |
|
193 size = _msize(elf->e_class, _elf_version, ELF_T_PHDR); |
|
194 elf_assert(size); |
|
195 if (!(p = malloc(num * size))) { |
|
196 seterr(memerr(ELF_T_PHDR)); |
|
197 return 0; |
|
198 } |
|
199 for (i = 0; i < num; i++) { |
|
200 if (!_elf_item(p + i * size, elf, ELF_T_PHDR, off + i * entsz)) { |
|
201 free(p); |
|
202 return 0; |
|
203 } |
|
204 } |
|
205 elf->e_phdr = p; |
|
206 elf->e_phnum = num; |
|
207 } |
|
208 return 1; |
|
209 } |
|
210 |
|
211 static int |
|
212 _elf_cook_shdr(Elf *elf) { |
|
213 size_t num, off, entsz; |
|
214 |
|
215 if (elf->e_class == ELFCLASS32) { |
|
216 num = ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum; |
|
217 off = ((Elf32_Ehdr*)elf->e_ehdr)->e_shoff; |
|
218 entsz = ((Elf32_Ehdr*)elf->e_ehdr)->e_shentsize; |
|
219 } |
|
220 #if __LIBELF64 |
|
221 else if (elf->e_class == ELFCLASS64) { |
|
222 num = ((Elf64_Ehdr*)elf->e_ehdr)->e_shnum; |
|
223 off = ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff; |
|
224 entsz = ((Elf64_Ehdr*)elf->e_ehdr)->e_shentsize; |
|
225 /* |
|
226 * Check for overflow on 32-bit systems |
|
227 */ |
|
228 if (overflow(off, ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff, Elf64_Off)) { |
|
229 seterr(ERROR_OUTSIDE); |
|
230 return 0; |
|
231 } |
|
232 } |
|
233 #endif /* __LIBELF64 */ |
|
234 else { |
|
235 seterr(ERROR_UNIMPLEMENTED); |
|
236 return 0; |
|
237 } |
|
238 if (off) { |
|
239 struct tmp { |
|
240 Elf_Scn scn; |
|
241 Scn_Data data; |
|
242 } *head; |
|
243 Elf_Data src, dst; |
|
244 Elf_Scn *scn; |
|
245 Scn_Data *sd; |
|
246 unsigned i; |
|
247 |
|
248 if (off < 0 || off > elf->e_size) { |
|
249 seterr(ERROR_OUTSIDE); |
|
250 return 0; |
|
251 } |
|
252 |
|
253 src.d_type = ELF_T_SHDR; |
|
254 src.d_version = elf->e_version; |
|
255 src.d_size = _fsize(elf->e_class, src.d_version, ELF_T_SHDR); |
|
256 elf_assert(src.d_size); |
|
257 #if ENABLE_EXTENDED_FORMAT |
|
258 if (entsz < src.d_size) { |
|
259 #else /* ENABLE_EXTENDED_FORMAT */ |
|
260 if (entsz != src.d_size) { |
|
261 #endif /* ENABLE_EXTENDED_FORMAT */ |
|
262 seterr(ERROR_EHDR_SHENTSIZE); |
|
263 return 0; |
|
264 } |
|
265 dst.d_version = EV_CURRENT; |
|
266 |
|
267 if (num == 0) { |
|
268 union { |
|
269 Elf32_Shdr sh32; |
|
270 #if __LIBELF64 |
|
271 Elf64_Shdr sh64; |
|
272 #endif /* __LIBELF64 */ |
|
273 } u; |
|
274 |
|
275 /* |
|
276 * Overflow in ehdr->e_shnum. |
|
277 * Get real value from first SHDR. |
|
278 */ |
|
279 if (elf->e_size - off < entsz) { |
|
280 seterr(ERROR_TRUNC_SHDR); |
|
281 return 0; |
|
282 } |
|
283 if (elf->e_rawdata) { |
|
284 src.d_buf = elf->e_rawdata + off; |
|
285 } |
|
286 else { |
|
287 src.d_buf = elf->e_data + off; |
|
288 } |
|
289 dst.d_buf = &u; |
|
290 dst.d_size = sizeof(u); |
|
291 if (!_elf_xlatetom(elf, &dst, &src)) { |
|
292 return 0; |
|
293 } |
|
294 elf_assert(dst.d_size == _msize(elf->e_class, EV_CURRENT, ELF_T_SHDR)); |
|
295 elf_assert(dst.d_type == ELF_T_SHDR); |
|
296 if (elf->e_class == ELFCLASS32) { |
|
297 num = u.sh32.sh_size; |
|
298 } |
|
299 #if __LIBELF64 |
|
300 else if (elf->e_class == ELFCLASS64) { |
|
301 num = u.sh64.sh_size; |
|
302 /* |
|
303 * Check for overflow on 32-bit systems |
|
304 */ |
|
305 if (overflow(num, u.sh64.sh_size, Elf64_Xword)) { |
|
306 seterr(ERROR_OUTSIDE); |
|
307 return 0; |
|
308 } |
|
309 } |
|
310 #endif /* __LIBELF64 */ |
|
311 } |
|
312 |
|
313 if ((elf->e_size - off) / entsz < num) { |
|
314 seterr(ERROR_TRUNC_SHDR); |
|
315 return 0; |
|
316 } |
|
317 |
|
318 if (!(head = (struct tmp*)malloc(num * sizeof(struct tmp)))) { |
|
319 seterr(ERROR_MEM_SCN); |
|
320 return 0; |
|
321 } |
|
322 for (scn = NULL, i = num; i-- > 0; ) { |
|
323 head[i].scn = _elf_scn_init; |
|
324 head[i].data = _elf_data_init; |
|
325 head[i].scn.s_link = scn; |
|
326 if (!scn) { |
|
327 elf->e_scn_n = &head[i].scn; |
|
328 } |
|
329 scn = &head[i].scn; |
|
330 sd = &head[i].data; |
|
331 |
|
332 if (elf->e_rawdata) { |
|
333 src.d_buf = elf->e_rawdata + off + i * entsz; |
|
334 } |
|
335 else { |
|
336 src.d_buf = elf->e_data + off + i * entsz; |
|
337 } |
|
338 dst.d_buf = &scn->s_uhdr; |
|
339 dst.d_size = sizeof(scn->s_uhdr); |
|
340 if (!_elf_xlatetom(elf, &dst, &src)) { |
|
341 elf->e_scn_n = NULL; |
|
342 free(head); |
|
343 return 0; |
|
344 } |
|
345 elf_assert(dst.d_size == _msize(elf->e_class, EV_CURRENT, ELF_T_SHDR)); |
|
346 elf_assert(dst.d_type == ELF_T_SHDR); |
|
347 |
|
348 scn->s_elf = elf; |
|
349 scn->s_index = i; |
|
350 scn->s_data_1 = sd; |
|
351 scn->s_data_n = sd; |
|
352 |
|
353 sd->sd_scn = scn; |
|
354 |
|
355 if (elf->e_class == ELFCLASS32) { |
|
356 Elf32_Shdr *shdr = &scn->s_shdr32; |
|
357 |
|
358 scn->s_type = shdr->sh_type; |
|
359 scn->s_size = shdr->sh_size; |
|
360 scn->s_offset = shdr->sh_offset; |
|
361 sd->sd_data.d_align = shdr->sh_addralign; |
|
362 sd->sd_data.d_type = _elf_scn_type(scn->s_type); |
|
363 } |
|
364 #if __LIBELF64 |
|
365 else if (elf->e_class == ELFCLASS64) { |
|
366 Elf64_Shdr *shdr = &scn->s_shdr64; |
|
367 |
|
368 scn->s_type = shdr->sh_type; |
|
369 scn->s_size = shdr->sh_size; |
|
370 scn->s_offset = shdr->sh_offset; |
|
371 sd->sd_data.d_align = shdr->sh_addralign; |
|
372 /* |
|
373 * Check for overflow on 32-bit systems |
|
374 */ |
|
375 if (overflow(scn->s_size, shdr->sh_size, Elf64_Xword) |
|
376 || overflow(scn->s_offset, shdr->sh_offset, Elf64_Off) |
|
377 || overflow(sd->sd_data.d_align, shdr->sh_addralign, Elf64_Xword)) { |
|
378 seterr(ERROR_OUTSIDE); |
|
379 return 0; |
|
380 } |
|
381 sd->sd_data.d_type = _elf_scn_type(scn->s_type); |
|
382 /* |
|
383 * QUIRKS MODE: |
|
384 * |
|
385 * Some 64-bit architectures use 64-bit entries in the |
|
386 * .hash section. This violates the ELF standard, and |
|
387 * should be fixed. It's mostly harmless as long as the |
|
388 * binary and the machine running your program have the |
|
389 * same byte order, but you're in trouble if they don't, |
|
390 * and if the entry size is wrong. |
|
391 * |
|
392 * As a workaround, I let libelf guess the right size |
|
393 * for the binary. This relies pretty much on the fact |
|
394 * that the binary provides correct data in the section |
|
395 * headers. If it doesn't, it's probably broken anyway. |
|
396 * Therefore, libelf uses a standard conforming value |
|
397 * when it's not absolutely sure. |
|
398 */ |
|
399 if (scn->s_type == SHT_HASH) { |
|
400 int override = 0; |
|
401 |
|
402 /* |
|
403 * sh_entsize must reflect the entry size |
|
404 */ |
|
405 if (shdr->sh_entsize == ELF64_FSZ_ADDR) { |
|
406 override++; |
|
407 } |
|
408 /* |
|
409 * sh_size must be a multiple of sh_entsize |
|
410 */ |
|
411 if (shdr->sh_size % ELF64_FSZ_ADDR == 0) { |
|
412 override++; |
|
413 } |
|
414 /* |
|
415 * There must be room for at least 2 entries |
|
416 */ |
|
417 if (shdr->sh_size >= 2 * ELF64_FSZ_ADDR) { |
|
418 override++; |
|
419 } |
|
420 /* |
|
421 * sh_addralign must be correctly set |
|
422 */ |
|
423 if (shdr->sh_addralign == ELF64_FSZ_ADDR) { |
|
424 override++; |
|
425 } |
|
426 /* |
|
427 * The section must be properly aligned |
|
428 */ |
|
429 if (shdr->sh_offset % ELF64_FSZ_ADDR == 0) { |
|
430 override++; |
|
431 } |
|
432 /* XXX: also look at the data? */ |
|
433 /* |
|
434 * Make a conservative decision... |
|
435 */ |
|
436 if (override >= 5) { |
|
437 sd->sd_data.d_type = ELF_T_ADDR; |
|
438 } |
|
439 } |
|
440 /* |
|
441 * END QUIRKS MODE. |
|
442 */ |
|
443 } |
|
444 #endif /* __LIBELF64 */ |
|
445 /* we already had this |
|
446 else { |
|
447 seterr(ERROR_UNIMPLEMENTED); |
|
448 return 0; |
|
449 } |
|
450 */ |
|
451 |
|
452 sd->sd_data.d_size = scn->s_size; |
|
453 sd->sd_data.d_version = _elf_version; |
|
454 } |
|
455 elf_assert(scn == &head[0].scn); |
|
456 elf->e_scn_1 = &head[0].scn; |
|
457 head[0].scn.s_freeme = 1; |
|
458 } |
|
459 return 1; |
|
460 } |
|
461 |
|
462 static int |
|
463 _elf_cook_file(Elf *elf) { |
|
464 elf->e_ehdr = _elf_item(NULL, elf, ELF_T_EHDR, 0); |
|
465 if (!elf->e_ehdr) { |
|
466 return 0; |
|
467 } |
|
468 /* |
|
469 * Note: _elf_cook_phdr may require the first section header! |
|
470 */ |
|
471 if (!_elf_cook_shdr(elf)) { |
|
472 return 0; |
|
473 } |
|
474 if (!_elf_cook_phdr(elf)) { |
|
475 return 0; |
|
476 } |
|
477 return 1; |
|
478 } |
|
479 |
|
480 int |
|
481 _elf_cook(Elf *elf) { |
|
482 elf_assert(_elf_scn_init.s_magic == SCN_MAGIC); |
|
483 elf_assert(_elf_data_init.sd_magic == DATA_MAGIC); |
|
484 elf_assert(elf); |
|
485 elf_assert(elf->e_magic == ELF_MAGIC); |
|
486 elf_assert(elf->e_kind == ELF_K_ELF); |
|
487 elf_assert(!elf->e_ehdr); |
|
488 if (!valid_version(elf->e_version)) { |
|
489 seterr(ERROR_UNKNOWN_VERSION); |
|
490 } |
|
491 else if (!valid_encoding(elf->e_encoding)) { |
|
492 seterr(ERROR_UNKNOWN_ENCODING); |
|
493 } |
|
494 else if (valid_class(elf->e_class)) { |
|
495 return _elf_cook_file(elf); |
|
496 } |
|
497 else { |
|
498 seterr(ERROR_UNKNOWN_CLASS); |
|
499 } |
|
500 return 0; |
|
501 } |