Mercurial > hg > CbC > CbC_gcc
comparison libiberty/simple-object-elf.c @ 68:561a7518be6b
update gcc-4.6
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 21 Aug 2011 07:07:55 +0900 |
parents | |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
67:f6334be47118 | 68:561a7518be6b |
---|---|
1 /* simple-object-elf.c -- routines to manipulate ELF object files. | |
2 Copyright 2010 Free Software Foundation, Inc. | |
3 Written by Ian Lance Taylor, Google. | |
4 | |
5 This program is free software; you can redistribute it and/or modify it | |
6 under the terms of the GNU General Public License as published by the | |
7 Free Software Foundation; either version 2, or (at your option) any | |
8 later version. | |
9 | |
10 This program 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 | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program; if not, write to the Free Software | |
17 Foundation, 51 Franklin Street - Fifth Floor, | |
18 Boston, MA 02110-1301, USA. */ | |
19 | |
20 #include "config.h" | |
21 #include "libiberty.h" | |
22 #include "simple-object.h" | |
23 | |
24 #include <errno.h> | |
25 #include <stddef.h> | |
26 | |
27 #ifdef HAVE_STDLIB_H | |
28 #include <stdlib.h> | |
29 #endif | |
30 | |
31 #ifdef HAVE_STDINT_H | |
32 #include <stdint.h> | |
33 #endif | |
34 | |
35 #ifdef HAVE_STRING_H | |
36 #include <string.h> | |
37 #endif | |
38 | |
39 #ifdef HAVE_INTTYPES_H | |
40 #include <inttypes.h> | |
41 #endif | |
42 | |
43 #include "simple-object-common.h" | |
44 | |
45 /* ELF structures and constants. */ | |
46 | |
47 /* 32-bit ELF file header. */ | |
48 | |
49 typedef struct { | |
50 unsigned char e_ident[16]; /* ELF "magic number" */ | |
51 unsigned char e_type[2]; /* Identifies object file type */ | |
52 unsigned char e_machine[2]; /* Specifies required architecture */ | |
53 unsigned char e_version[4]; /* Identifies object file version */ | |
54 unsigned char e_entry[4]; /* Entry point virtual address */ | |
55 unsigned char e_phoff[4]; /* Program header table file offset */ | |
56 unsigned char e_shoff[4]; /* Section header table file offset */ | |
57 unsigned char e_flags[4]; /* Processor-specific flags */ | |
58 unsigned char e_ehsize[2]; /* ELF header size in bytes */ | |
59 unsigned char e_phentsize[2]; /* Program header table entry size */ | |
60 unsigned char e_phnum[2]; /* Program header table entry count */ | |
61 unsigned char e_shentsize[2]; /* Section header table entry size */ | |
62 unsigned char e_shnum[2]; /* Section header table entry count */ | |
63 unsigned char e_shstrndx[2]; /* Section header string table index */ | |
64 } Elf32_External_Ehdr; | |
65 | |
66 /* 64-bit ELF file header. */ | |
67 | |
68 typedef struct { | |
69 unsigned char e_ident[16]; /* ELF "magic number" */ | |
70 unsigned char e_type[2]; /* Identifies object file type */ | |
71 unsigned char e_machine[2]; /* Specifies required architecture */ | |
72 unsigned char e_version[4]; /* Identifies object file version */ | |
73 unsigned char e_entry[8]; /* Entry point virtual address */ | |
74 unsigned char e_phoff[8]; /* Program header table file offset */ | |
75 unsigned char e_shoff[8]; /* Section header table file offset */ | |
76 unsigned char e_flags[4]; /* Processor-specific flags */ | |
77 unsigned char e_ehsize[2]; /* ELF header size in bytes */ | |
78 unsigned char e_phentsize[2]; /* Program header table entry size */ | |
79 unsigned char e_phnum[2]; /* Program header table entry count */ | |
80 unsigned char e_shentsize[2]; /* Section header table entry size */ | |
81 unsigned char e_shnum[2]; /* Section header table entry count */ | |
82 unsigned char e_shstrndx[2]; /* Section header string table index */ | |
83 } Elf64_External_Ehdr; | |
84 | |
85 /* Indexes and values in e_ident field of Ehdr. */ | |
86 | |
87 #define EI_MAG0 0 /* File identification byte 0 index */ | |
88 #define ELFMAG0 0x7F /* Magic number byte 0 */ | |
89 | |
90 #define EI_MAG1 1 /* File identification byte 1 index */ | |
91 #define ELFMAG1 'E' /* Magic number byte 1 */ | |
92 | |
93 #define EI_MAG2 2 /* File identification byte 2 index */ | |
94 #define ELFMAG2 'L' /* Magic number byte 2 */ | |
95 | |
96 #define EI_MAG3 3 /* File identification byte 3 index */ | |
97 #define ELFMAG3 'F' /* Magic number byte 3 */ | |
98 | |
99 #define EI_CLASS 4 /* File class */ | |
100 #define ELFCLASSNONE 0 /* Invalid class */ | |
101 #define ELFCLASS32 1 /* 32-bit objects */ | |
102 #define ELFCLASS64 2 /* 64-bit objects */ | |
103 | |
104 #define EI_DATA 5 /* Data encoding */ | |
105 #define ELFDATANONE 0 /* Invalid data encoding */ | |
106 #define ELFDATA2LSB 1 /* 2's complement, little endian */ | |
107 #define ELFDATA2MSB 2 /* 2's complement, big endian */ | |
108 | |
109 #define EI_VERSION 6 /* File version */ | |
110 #define EV_CURRENT 1 /* Current version */ | |
111 | |
112 #define EI_OSABI 7 /* Operating System/ABI indication */ | |
113 | |
114 /* Values for e_type field of Ehdr. */ | |
115 | |
116 #define ET_REL 1 /* Relocatable file */ | |
117 | |
118 /* Values for e_machine field of Ehdr. */ | |
119 | |
120 #define EM_SPARC 2 /* SUN SPARC */ | |
121 #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ | |
122 | |
123 /* Special section index values. */ | |
124 | |
125 #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ | |
126 #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ | |
127 | |
128 /* 32-bit ELF program header. */ | |
129 | |
130 typedef struct { | |
131 unsigned char p_type[4]; /* Identifies program segment type */ | |
132 unsigned char p_offset[4]; /* Segment file offset */ | |
133 unsigned char p_vaddr[4]; /* Segment virtual address */ | |
134 unsigned char p_paddr[4]; /* Segment physical address */ | |
135 unsigned char p_filesz[4]; /* Segment size in file */ | |
136 unsigned char p_memsz[4]; /* Segment size in memory */ | |
137 unsigned char p_flags[4]; /* Segment flags */ | |
138 unsigned char p_align[4]; /* Segment alignment, file & memory */ | |
139 } Elf32_External_Phdr; | |
140 | |
141 /* 64-bit ELF program header. */ | |
142 | |
143 typedef struct { | |
144 unsigned char p_type[4]; /* Identifies program segment type */ | |
145 unsigned char p_flags[4]; /* Segment flags */ | |
146 unsigned char p_offset[8]; /* Segment file offset */ | |
147 unsigned char p_vaddr[8]; /* Segment virtual address */ | |
148 unsigned char p_paddr[8]; /* Segment physical address */ | |
149 unsigned char p_filesz[8]; /* Segment size in file */ | |
150 unsigned char p_memsz[8]; /* Segment size in memory */ | |
151 unsigned char p_align[8]; /* Segment alignment, file & memory */ | |
152 } Elf64_External_Phdr; | |
153 | |
154 /* 32-bit ELF section header */ | |
155 | |
156 typedef struct { | |
157 unsigned char sh_name[4]; /* Section name, index in string tbl */ | |
158 unsigned char sh_type[4]; /* Type of section */ | |
159 unsigned char sh_flags[4]; /* Miscellaneous section attributes */ | |
160 unsigned char sh_addr[4]; /* Section virtual addr at execution */ | |
161 unsigned char sh_offset[4]; /* Section file offset */ | |
162 unsigned char sh_size[4]; /* Size of section in bytes */ | |
163 unsigned char sh_link[4]; /* Index of another section */ | |
164 unsigned char sh_info[4]; /* Additional section information */ | |
165 unsigned char sh_addralign[4]; /* Section alignment */ | |
166 unsigned char sh_entsize[4]; /* Entry size if section holds table */ | |
167 } Elf32_External_Shdr; | |
168 | |
169 /* 64-bit ELF section header. */ | |
170 | |
171 typedef struct { | |
172 unsigned char sh_name[4]; /* Section name, index in string tbl */ | |
173 unsigned char sh_type[4]; /* Type of section */ | |
174 unsigned char sh_flags[8]; /* Miscellaneous section attributes */ | |
175 unsigned char sh_addr[8]; /* Section virtual addr at execution */ | |
176 unsigned char sh_offset[8]; /* Section file offset */ | |
177 unsigned char sh_size[8]; /* Size of section in bytes */ | |
178 unsigned char sh_link[4]; /* Index of another section */ | |
179 unsigned char sh_info[4]; /* Additional section information */ | |
180 unsigned char sh_addralign[8]; /* Section alignment */ | |
181 unsigned char sh_entsize[8]; /* Entry size if section holds table */ | |
182 } Elf64_External_Shdr; | |
183 | |
184 /* Values for sh_type field. */ | |
185 | |
186 #define SHT_PROGBITS 1 /* Program data */ | |
187 #define SHT_STRTAB 3 /* A string table */ | |
188 | |
189 /* Functions to fetch and store different ELF types, depending on the | |
190 endianness and size. */ | |
191 | |
192 struct elf_type_functions | |
193 { | |
194 unsigned short (*fetch_Elf_Half) (const unsigned char *); | |
195 unsigned int (*fetch_Elf_Word) (const unsigned char *); | |
196 ulong_type (*fetch_Elf_Addr) (const unsigned char *); | |
197 void (*set_Elf_Half) (unsigned char *, unsigned short); | |
198 void (*set_Elf_Word) (unsigned char *, unsigned int); | |
199 void (*set_Elf_Addr) (unsigned char *, ulong_type); | |
200 }; | |
201 | |
202 static const struct elf_type_functions elf_big_32_functions = | |
203 { | |
204 simple_object_fetch_big_16, | |
205 simple_object_fetch_big_32, | |
206 simple_object_fetch_big_32_ulong, | |
207 simple_object_set_big_16, | |
208 simple_object_set_big_32, | |
209 simple_object_set_big_32_ulong | |
210 }; | |
211 | |
212 static const struct elf_type_functions elf_little_32_functions = | |
213 { | |
214 simple_object_fetch_little_16, | |
215 simple_object_fetch_little_32, | |
216 simple_object_fetch_little_32_ulong, | |
217 simple_object_set_little_16, | |
218 simple_object_set_little_32, | |
219 simple_object_set_little_32_ulong | |
220 }; | |
221 | |
222 #ifdef UNSIGNED_64BIT_TYPE | |
223 | |
224 static const struct elf_type_functions elf_big_64_functions = | |
225 { | |
226 simple_object_fetch_big_16, | |
227 simple_object_fetch_big_32, | |
228 simple_object_fetch_big_64, | |
229 simple_object_set_big_16, | |
230 simple_object_set_big_32, | |
231 simple_object_set_big_64 | |
232 }; | |
233 | |
234 static const struct elf_type_functions elf_little_64_functions = | |
235 { | |
236 simple_object_fetch_little_16, | |
237 simple_object_fetch_little_32, | |
238 simple_object_fetch_little_64, | |
239 simple_object_set_little_16, | |
240 simple_object_set_little_32, | |
241 simple_object_set_little_64 | |
242 }; | |
243 | |
244 #endif | |
245 | |
246 /* Hideous macro to fetch the value of a field from an external ELF | |
247 struct of some sort. TYPEFUNCS is the set of type functions. | |
248 BUFFER points to the external data. STRUCTTYPE is the appropriate | |
249 struct type. FIELD is a field within the struct. TYPE is the type | |
250 of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ | |
251 | |
252 #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \ | |
253 ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD))) | |
254 | |
255 /* Even more hideous macro to fetch the value of FIELD from BUFFER. | |
256 SIZE is 32 or 64. STRUCTTYPE is the name of the struct from | |
257 elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in | |
258 the struct. TYPE is the type of the field in the struct: Elf_Half, | |
259 Elf_Word, or Elf_Addr. */ | |
260 | |
261 #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, \ | |
262 FIELD, TYPE) \ | |
263 ELF_FETCH_STRUCT_FIELD (TYPEFUNCS, \ | |
264 Elf ## SIZE ## _External_ ## STRUCTTYPE, \ | |
265 FIELD, BUFFER, TYPE) | |
266 | |
267 /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value. */ | |
268 | |
269 #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, \ | |
270 FIELD, TYPE) \ | |
271 ((CLASS) == ELFCLASS32 \ | |
272 ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \ | |
273 TYPE) \ | |
274 : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \ | |
275 TYPE)) | |
276 | |
277 /* Hideous macro to set the value of a field in an external ELF | |
278 structure to VAL. TYPEFUNCS is the set of type functions. BUFFER | |
279 points to the external data. STRUCTTYPE is the appropriate | |
280 structure type. FIELD is a field within the struct. TYPE is the | |
281 type of the field in the struct: Elf_Half, Elf_Word, or | |
282 Elf_Addr. */ | |
283 | |
284 #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \ | |
285 (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL)) | |
286 | |
287 /* Even more hideous macro to set the value of FIELD in BUFFER to VAL. | |
288 SIZE is 32 or 64. STRUCTTYPE is the name of the struct from | |
289 elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in | |
290 the struct. TYPE is the type of the field in the struct: Elf_Half, | |
291 Elf_Word, or Elf_Addr. */ | |
292 | |
293 #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \ | |
294 TYPE, VAL) \ | |
295 ELF_SET_STRUCT_FIELD (TYPEFUNCS, \ | |
296 Elf ## SIZE ## _External_ ## STRUCTTYPE, \ | |
297 FIELD, BUFFER, TYPE, VAL) | |
298 | |
299 /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value. */ | |
300 | |
301 #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD, \ | |
302 TYPE, VAL) \ | |
303 ((CLASS) == ELFCLASS32 \ | |
304 ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \ | |
305 TYPE, VAL) \ | |
306 : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \ | |
307 TYPE, VAL)) | |
308 | |
309 /* Private data for an simple_object_read. */ | |
310 | |
311 struct simple_object_elf_read | |
312 { | |
313 /* Type functions. */ | |
314 const struct elf_type_functions* type_functions; | |
315 /* Elf data. */ | |
316 unsigned char ei_data; | |
317 /* Elf class. */ | |
318 unsigned char ei_class; | |
319 /* ELF OS ABI. */ | |
320 unsigned char ei_osabi; | |
321 /* Elf machine number. */ | |
322 unsigned short machine; | |
323 /* Processor specific flags. */ | |
324 unsigned int flags; | |
325 /* File offset of section headers. */ | |
326 ulong_type shoff; | |
327 /* Number of sections. */ | |
328 unsigned int shnum; | |
329 /* Index of string table section header. */ | |
330 unsigned int shstrndx; | |
331 }; | |
332 | |
333 /* Private data for an simple_object_attributes. */ | |
334 | |
335 struct simple_object_elf_attributes | |
336 { | |
337 /* Type functions. */ | |
338 const struct elf_type_functions* type_functions; | |
339 /* Elf data. */ | |
340 unsigned char ei_data; | |
341 /* Elf class. */ | |
342 unsigned char ei_class; | |
343 /* ELF OS ABI. */ | |
344 unsigned char ei_osabi; | |
345 /* Elf machine number. */ | |
346 unsigned short machine; | |
347 /* Processor specific flags. */ | |
348 unsigned int flags; | |
349 }; | |
350 | |
351 /* See if we have an ELF file. */ | |
352 | |
353 static void * | |
354 simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN], | |
355 int descriptor, off_t offset, | |
356 const char *segment_name ATTRIBUTE_UNUSED, | |
357 const char **errmsg, int *err) | |
358 { | |
359 unsigned char ei_data; | |
360 unsigned char ei_class; | |
361 const struct elf_type_functions *type_functions; | |
362 unsigned char ehdr[sizeof (Elf64_External_Ehdr)]; | |
363 struct simple_object_elf_read *eor; | |
364 | |
365 if (header[EI_MAG0] != ELFMAG0 | |
366 || header[EI_MAG1] != ELFMAG1 | |
367 || header[EI_MAG2] != ELFMAG2 | |
368 || header[EI_MAG3] != ELFMAG3 | |
369 || header[EI_VERSION] != EV_CURRENT) | |
370 { | |
371 *errmsg = NULL; | |
372 *err = 0; | |
373 return NULL; | |
374 } | |
375 | |
376 ei_data = header[EI_DATA]; | |
377 if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB) | |
378 { | |
379 *errmsg = "unknown ELF endianness"; | |
380 *err = 0; | |
381 return NULL; | |
382 } | |
383 | |
384 ei_class = header[EI_CLASS]; | |
385 switch (ei_class) | |
386 { | |
387 case ELFCLASS32: | |
388 type_functions = (ei_data == ELFDATA2LSB | |
389 ? &elf_little_32_functions | |
390 : &elf_big_32_functions); | |
391 break; | |
392 | |
393 case ELFCLASS64: | |
394 #ifndef UNSIGNED_64BIT_TYPE | |
395 *errmsg = "64-bit ELF objects not supported"; | |
396 *err = 0; | |
397 return NULL; | |
398 #else | |
399 type_functions = (ei_data == ELFDATA2LSB | |
400 ? &elf_little_64_functions | |
401 : &elf_big_64_functions); | |
402 break; | |
403 #endif | |
404 | |
405 default: | |
406 *errmsg = "unrecognized ELF size"; | |
407 *err = 0; | |
408 return NULL; | |
409 } | |
410 | |
411 if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr, | |
412 errmsg, err)) | |
413 return NULL; | |
414 | |
415 eor = XNEW (struct simple_object_elf_read); | |
416 eor->type_functions = type_functions; | |
417 eor->ei_data = ei_data; | |
418 eor->ei_class = ei_class; | |
419 eor->ei_osabi = header[EI_OSABI]; | |
420 eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, | |
421 e_machine, Elf_Half); | |
422 eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, | |
423 e_flags, Elf_Word); | |
424 eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, | |
425 e_shoff, Elf_Addr); | |
426 eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, | |
427 e_shnum, Elf_Half); | |
428 eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, | |
429 e_shstrndx, Elf_Half); | |
430 | |
431 if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX) | |
432 && eor->shoff != 0) | |
433 { | |
434 unsigned char shdr[sizeof (Elf64_External_Shdr)]; | |
435 | |
436 /* Object file has more than 0xffff sections. */ | |
437 | |
438 if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr, | |
439 (ei_class == ELFCLASS32 | |
440 ? sizeof (Elf32_External_Shdr) | |
441 : sizeof (Elf64_External_Shdr)), | |
442 errmsg, err)) | |
443 { | |
444 XDELETE (eor); | |
445 return NULL; | |
446 } | |
447 | |
448 if (eor->shnum == 0) | |
449 eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, | |
450 shdr, sh_size, Elf_Addr); | |
451 | |
452 if (eor->shstrndx == SHN_XINDEX) | |
453 { | |
454 eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, | |
455 shdr, sh_link, Elf_Word); | |
456 | |
457 /* Versions of the GNU binutils between 2.12 and 2.18 did | |
458 not handle objects with more than SHN_LORESERVE sections | |
459 correctly. All large section indexes were offset by | |
460 0x100. There is more information at | |
461 http://sourceware.org/bugzilla/show_bug.cgi?id-5900 . | |
462 Fortunately these object files are easy to detect, as the | |
463 GNU binutils always put the section header string table | |
464 near the end of the list of sections. Thus if the | |
465 section header string table index is larger than the | |
466 number of sections, then we know we have to subtract | |
467 0x100 to get the real section index. */ | |
468 if (eor->shstrndx >= eor->shnum | |
469 && eor->shstrndx >= SHN_LORESERVE + 0x100) | |
470 eor->shstrndx -= 0x100; | |
471 } | |
472 } | |
473 | |
474 if (eor->shstrndx >= eor->shnum) | |
475 { | |
476 *errmsg = "invalid ELF shstrndx >= shnum"; | |
477 *err = 0; | |
478 XDELETE (eor); | |
479 return NULL; | |
480 } | |
481 | |
482 return (void *) eor; | |
483 } | |
484 | |
485 /* Find all sections in an ELF file. */ | |
486 | |
487 static const char * | |
488 simple_object_elf_find_sections (simple_object_read *sobj, | |
489 int (*pfn) (void *, const char *, | |
490 off_t offset, off_t length), | |
491 void *data, | |
492 int *err) | |
493 { | |
494 struct simple_object_elf_read *eor = | |
495 (struct simple_object_elf_read *) sobj->data; | |
496 const struct elf_type_functions *type_functions = eor->type_functions; | |
497 unsigned char ei_class = eor->ei_class; | |
498 size_t shdr_size; | |
499 unsigned int shnum; | |
500 unsigned char *shdrs; | |
501 const char *errmsg; | |
502 unsigned char *shstrhdr; | |
503 size_t name_size; | |
504 off_t shstroff; | |
505 unsigned char *names; | |
506 unsigned int i; | |
507 | |
508 shdr_size = (ei_class == ELFCLASS32 | |
509 ? sizeof (Elf32_External_Shdr) | |
510 : sizeof (Elf64_External_Shdr)); | |
511 | |
512 /* Read the section headers. We skip section 0, which is not a | |
513 useful section. */ | |
514 | |
515 shnum = eor->shnum; | |
516 shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1)); | |
517 | |
518 if (!simple_object_internal_read (sobj->descriptor, | |
519 sobj->offset + eor->shoff + shdr_size, | |
520 shdrs, | |
521 shdr_size * (shnum - 1), | |
522 &errmsg, err)) | |
523 { | |
524 XDELETEVEC (shdrs); | |
525 return errmsg; | |
526 } | |
527 | |
528 /* Read the section names. */ | |
529 | |
530 shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size; | |
531 name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, | |
532 shstrhdr, sh_size, Elf_Addr); | |
533 shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, | |
534 shstrhdr, sh_offset, Elf_Addr); | |
535 names = XNEWVEC (unsigned char, name_size); | |
536 if (!simple_object_internal_read (sobj->descriptor, | |
537 sobj->offset + shstroff, | |
538 names, name_size, &errmsg, err)) | |
539 { | |
540 XDELETEVEC (names); | |
541 XDELETEVEC (shdrs); | |
542 return errmsg; | |
543 } | |
544 | |
545 for (i = 1; i < shnum; ++i) | |
546 { | |
547 unsigned char *shdr; | |
548 unsigned int sh_name; | |
549 const char *name; | |
550 off_t offset; | |
551 off_t length; | |
552 | |
553 shdr = shdrs + (i - 1) * shdr_size; | |
554 sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, | |
555 shdr, sh_name, Elf_Word); | |
556 if (sh_name >= name_size) | |
557 { | |
558 *err = 0; | |
559 XDELETEVEC (names); | |
560 XDELETEVEC (shdrs); | |
561 return "ELF section name out of range"; | |
562 } | |
563 | |
564 name = (const char *) names + sh_name; | |
565 offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, | |
566 shdr, sh_offset, Elf_Addr); | |
567 length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, | |
568 shdr, sh_size, Elf_Addr); | |
569 | |
570 if (!(*pfn) (data, name, offset, length)) | |
571 break; | |
572 } | |
573 | |
574 XDELETEVEC (names); | |
575 XDELETEVEC (shdrs); | |
576 | |
577 return NULL; | |
578 } | |
579 | |
580 /* Fetch the attributes for an simple_object_read. */ | |
581 | |
582 static void * | |
583 simple_object_elf_fetch_attributes (simple_object_read *sobj, | |
584 const char **errmsg ATTRIBUTE_UNUSED, | |
585 int *err ATTRIBUTE_UNUSED) | |
586 { | |
587 struct simple_object_elf_read *eor = | |
588 (struct simple_object_elf_read *) sobj->data; | |
589 struct simple_object_elf_attributes *ret; | |
590 | |
591 ret = XNEW (struct simple_object_elf_attributes); | |
592 ret->type_functions = eor->type_functions; | |
593 ret->ei_data = eor->ei_data; | |
594 ret->ei_class = eor->ei_class; | |
595 ret->ei_osabi = eor->ei_osabi; | |
596 ret->machine = eor->machine; | |
597 ret->flags = eor->flags; | |
598 return ret; | |
599 } | |
600 | |
601 /* Release the privata data for an simple_object_read. */ | |
602 | |
603 static void | |
604 simple_object_elf_release_read (void *data) | |
605 { | |
606 XDELETE (data); | |
607 } | |
608 | |
609 /* Compare two attributes structures. */ | |
610 | |
611 static const char * | |
612 simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err) | |
613 { | |
614 struct simple_object_elf_attributes *to = | |
615 (struct simple_object_elf_attributes *) todata; | |
616 struct simple_object_elf_attributes *from = | |
617 (struct simple_object_elf_attributes *) fromdata; | |
618 | |
619 if (to->ei_data != from->ei_data || to->ei_class != from->ei_class) | |
620 { | |
621 *err = 0; | |
622 return "ELF object format mismatch"; | |
623 } | |
624 | |
625 if (to->machine != from->machine) | |
626 { | |
627 int ok; | |
628 | |
629 /* EM_SPARC and EM_SPARC32PLUS are compatible and force an | |
630 output of EM_SPARC32PLUS. */ | |
631 ok = 0; | |
632 switch (to->machine) | |
633 { | |
634 case EM_SPARC: | |
635 if (from->machine == EM_SPARC32PLUS) | |
636 { | |
637 to->machine = from->machine; | |
638 ok = 1; | |
639 } | |
640 break; | |
641 | |
642 case EM_SPARC32PLUS: | |
643 if (from->machine == EM_SPARC) | |
644 ok = 1; | |
645 break; | |
646 | |
647 default: | |
648 break; | |
649 } | |
650 | |
651 if (!ok) | |
652 { | |
653 *err = 0; | |
654 return "ELF machine number mismatch"; | |
655 } | |
656 } | |
657 | |
658 return NULL; | |
659 } | |
660 | |
661 /* Release the private data for an attributes structure. */ | |
662 | |
663 static void | |
664 simple_object_elf_release_attributes (void *data) | |
665 { | |
666 XDELETE (data); | |
667 } | |
668 | |
669 /* Prepare to write out a file. */ | |
670 | |
671 static void * | |
672 simple_object_elf_start_write (void *attributes_data, | |
673 const char **errmsg ATTRIBUTE_UNUSED, | |
674 int *err ATTRIBUTE_UNUSED) | |
675 { | |
676 struct simple_object_elf_attributes *attrs = | |
677 (struct simple_object_elf_attributes *) attributes_data; | |
678 struct simple_object_elf_attributes *ret; | |
679 | |
680 /* We're just going to record the attributes, but we need to make a | |
681 copy because the user may delete them. */ | |
682 ret = XNEW (struct simple_object_elf_attributes); | |
683 *ret = *attrs; | |
684 return ret; | |
685 } | |
686 | |
687 /* Write out an ELF ehdr. */ | |
688 | |
689 static int | |
690 simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor, | |
691 const char **errmsg, int *err) | |
692 { | |
693 struct simple_object_elf_attributes *attrs = | |
694 (struct simple_object_elf_attributes *) sobj->data; | |
695 const struct elf_type_functions* fns; | |
696 unsigned char cl; | |
697 size_t ehdr_size; | |
698 unsigned char buf[sizeof (Elf64_External_Ehdr)]; | |
699 simple_object_write_section *section; | |
700 unsigned int shnum; | |
701 | |
702 fns = attrs->type_functions; | |
703 cl = attrs->ei_class; | |
704 | |
705 shnum = 0; | |
706 for (section = sobj->sections; section != NULL; section = section->next) | |
707 ++shnum; | |
708 if (shnum > 0) | |
709 { | |
710 /* Add a section header for the dummy section and one for | |
711 .shstrtab. */ | |
712 shnum += 2; | |
713 } | |
714 | |
715 ehdr_size = (cl == ELFCLASS32 | |
716 ? sizeof (Elf32_External_Ehdr) | |
717 : sizeof (Elf64_External_Ehdr)); | |
718 memset (buf, 0, sizeof (Elf64_External_Ehdr)); | |
719 | |
720 buf[EI_MAG0] = ELFMAG0; | |
721 buf[EI_MAG1] = ELFMAG1; | |
722 buf[EI_MAG2] = ELFMAG2; | |
723 buf[EI_MAG3] = ELFMAG3; | |
724 buf[EI_CLASS] = cl; | |
725 buf[EI_DATA] = attrs->ei_data; | |
726 buf[EI_VERSION] = EV_CURRENT; | |
727 buf[EI_OSABI] = attrs->ei_osabi; | |
728 | |
729 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL); | |
730 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine); | |
731 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT); | |
732 /* e_entry left as zero. */ | |
733 /* e_phoff left as zero. */ | |
734 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size); | |
735 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags); | |
736 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size); | |
737 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half, | |
738 (cl == ELFCLASS32 | |
739 ? sizeof (Elf32_External_Phdr) | |
740 : sizeof (Elf64_External_Phdr))); | |
741 /* e_phnum left as zero. */ | |
742 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half, | |
743 (cl == ELFCLASS32 | |
744 ? sizeof (Elf32_External_Shdr) | |
745 : sizeof (Elf64_External_Shdr))); | |
746 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, shnum); | |
747 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half, | |
748 shnum == 0 ? 0 : shnum - 1); | |
749 | |
750 return simple_object_internal_write (descriptor, 0, buf, ehdr_size, | |
751 errmsg, err); | |
752 } | |
753 | |
754 /* Write out an ELF shdr. */ | |
755 | |
756 static int | |
757 simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor, | |
758 off_t offset, unsigned int sh_name, | |
759 unsigned int sh_type, unsigned int sh_flags, | |
760 unsigned int sh_offset, unsigned int sh_size, | |
761 unsigned int sh_addralign, const char **errmsg, | |
762 int *err) | |
763 { | |
764 struct simple_object_elf_attributes *attrs = | |
765 (struct simple_object_elf_attributes *) sobj->data; | |
766 const struct elf_type_functions* fns; | |
767 unsigned char cl; | |
768 size_t shdr_size; | |
769 unsigned char buf[sizeof (Elf64_External_Shdr)]; | |
770 | |
771 fns = attrs->type_functions; | |
772 cl = attrs->ei_class; | |
773 | |
774 shdr_size = (cl == ELFCLASS32 | |
775 ? sizeof (Elf32_External_Shdr) | |
776 : sizeof (Elf64_External_Shdr)); | |
777 memset (buf, 0, sizeof (Elf64_External_Shdr)); | |
778 | |
779 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name); | |
780 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type); | |
781 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags); | |
782 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset); | |
783 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size); | |
784 /* sh_link left as zero. */ | |
785 /* sh_info left as zero. */ | |
786 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign); | |
787 /* sh_entsize left as zero. */ | |
788 | |
789 return simple_object_internal_write (descriptor, offset, buf, shdr_size, | |
790 errmsg, err); | |
791 } | |
792 | |
793 /* Write out a complete ELF file. | |
794 Ehdr | |
795 initial dummy Shdr | |
796 user-created Shdrs | |
797 .shstrtab Shdr | |
798 user-created section data | |
799 .shstrtab data */ | |
800 | |
801 static const char * | |
802 simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, | |
803 int *err) | |
804 { | |
805 struct simple_object_elf_attributes *attrs = | |
806 (struct simple_object_elf_attributes *) sobj->data; | |
807 unsigned char cl; | |
808 size_t ehdr_size; | |
809 size_t shdr_size; | |
810 const char *errmsg; | |
811 simple_object_write_section *section; | |
812 unsigned int shnum; | |
813 size_t shdr_offset; | |
814 size_t sh_offset; | |
815 size_t sh_name; | |
816 unsigned char zero; | |
817 | |
818 if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err)) | |
819 return errmsg; | |
820 | |
821 cl = attrs->ei_class; | |
822 if (cl == ELFCLASS32) | |
823 { | |
824 ehdr_size = sizeof (Elf32_External_Ehdr); | |
825 shdr_size = sizeof (Elf32_External_Shdr); | |
826 } | |
827 else | |
828 { | |
829 ehdr_size = sizeof (Elf64_External_Ehdr); | |
830 shdr_size = sizeof (Elf64_External_Shdr); | |
831 } | |
832 | |
833 shnum = 0; | |
834 for (section = sobj->sections; section != NULL; section = section->next) | |
835 ++shnum; | |
836 if (shnum == 0) | |
837 return NULL; | |
838 | |
839 /* Add initial dummy Shdr and .shstrtab. */ | |
840 shnum += 2; | |
841 | |
842 shdr_offset = ehdr_size; | |
843 sh_offset = shdr_offset + shnum * shdr_size; | |
844 | |
845 if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, | |
846 0, 0, 0, 0, 0, 0, &errmsg, err)) | |
847 return errmsg; | |
848 | |
849 shdr_offset += shdr_size; | |
850 | |
851 sh_name = 1; | |
852 for (section = sobj->sections; section != NULL; section = section->next) | |
853 { | |
854 size_t mask; | |
855 size_t new_sh_offset; | |
856 size_t sh_size; | |
857 struct simple_object_write_section_buffer *buffer; | |
858 | |
859 mask = (1U << section->align) - 1; | |
860 new_sh_offset = sh_offset + mask; | |
861 new_sh_offset &= ~ mask; | |
862 while (new_sh_offset > sh_offset) | |
863 { | |
864 unsigned char zeroes[16]; | |
865 size_t write; | |
866 | |
867 memset (zeroes, 0, sizeof zeroes); | |
868 write = new_sh_offset - sh_offset; | |
869 if (write > sizeof zeroes) | |
870 write = sizeof zeroes; | |
871 if (!simple_object_internal_write (descriptor, sh_offset, zeroes, | |
872 write, &errmsg, err)) | |
873 return errmsg; | |
874 sh_offset += write; | |
875 } | |
876 | |
877 sh_size = 0; | |
878 for (buffer = section->buffers; buffer != NULL; buffer = buffer->next) | |
879 { | |
880 if (!simple_object_internal_write (descriptor, sh_offset + sh_size, | |
881 ((const unsigned char *) | |
882 buffer->buffer), | |
883 buffer->size, &errmsg, err)) | |
884 return errmsg; | |
885 sh_size += buffer->size; | |
886 } | |
887 | |
888 if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, | |
889 sh_name, SHT_PROGBITS, 0, sh_offset, | |
890 sh_size, 1U << section->align, | |
891 &errmsg, err)) | |
892 return errmsg; | |
893 | |
894 shdr_offset += shdr_size; | |
895 sh_name += strlen (section->name) + 1; | |
896 sh_offset += sh_size; | |
897 } | |
898 | |
899 if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, | |
900 sh_name, SHT_STRTAB, 0, sh_offset, | |
901 sh_name + strlen (".shstrtab") + 1, | |
902 1, &errmsg, err)) | |
903 return errmsg; | |
904 | |
905 /* .shstrtab has a leading zero byte. */ | |
906 zero = 0; | |
907 if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1, | |
908 &errmsg, err)) | |
909 return errmsg; | |
910 ++sh_offset; | |
911 | |
912 for (section = sobj->sections; section != NULL; section = section->next) | |
913 { | |
914 size_t len; | |
915 | |
916 len = strlen (section->name) + 1; | |
917 if (!simple_object_internal_write (descriptor, sh_offset, | |
918 (const unsigned char *) section->name, | |
919 len, &errmsg, err)) | |
920 return errmsg; | |
921 sh_offset += len; | |
922 } | |
923 | |
924 if (!simple_object_internal_write (descriptor, sh_offset, | |
925 (const unsigned char *) ".shstrtab", | |
926 strlen (".shstrtab") + 1, &errmsg, err)) | |
927 return errmsg; | |
928 | |
929 return NULL; | |
930 } | |
931 | |
932 /* Release the private data for an simple_object_write structure. */ | |
933 | |
934 static void | |
935 simple_object_elf_release_write (void *data) | |
936 { | |
937 XDELETE (data); | |
938 } | |
939 | |
940 /* The ELF functions. */ | |
941 | |
942 const struct simple_object_functions simple_object_elf_functions = | |
943 { | |
944 simple_object_elf_match, | |
945 simple_object_elf_find_sections, | |
946 simple_object_elf_fetch_attributes, | |
947 simple_object_elf_release_read, | |
948 simple_object_elf_attributes_merge, | |
949 simple_object_elf_release_attributes, | |
950 simple_object_elf_start_write, | |
951 simple_object_elf_write_to_file, | |
952 simple_object_elf_release_write | |
953 }; |