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