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.
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
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.
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. */
21 #include "libiberty.h"
22 #include "simple-object.h"
39 #ifdef HAVE_INTTYPES_H
43 #include "simple-object-common.h"
45 /* ELF structures and constants. */
47 /* 32-bit ELF file header. */
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
;
66 /* 64-bit ELF file header. */
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
;
85 /* Indexes and values in e_ident field of Ehdr. */
87 #define EI_MAG0 0 /* File identification byte 0 index */
88 #define ELFMAG0 0x7F /* Magic number byte 0 */
90 #define EI_MAG1 1 /* File identification byte 1 index */
91 #define ELFMAG1 'E' /* Magic number byte 1 */
93 #define EI_MAG2 2 /* File identification byte 2 index */
94 #define ELFMAG2 'L' /* Magic number byte 2 */
96 #define EI_MAG3 3 /* File identification byte 3 index */
97 #define ELFMAG3 'F' /* Magic number byte 3 */
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 */
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 */
109 #define EI_VERSION 6 /* File version */
110 #define EV_CURRENT 1 /* Current version */
112 #define EI_OSABI 7 /* Operating System/ABI indication */
114 /* Values for e_type field of Ehdr. */
116 #define ET_REL 1 /* Relocatable file */
118 /* Values for e_machine field of Ehdr. */
120 #define EM_SPARC 2 /* SUN SPARC */
121 #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
123 /* Special section index values. */
125 #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
126 #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
128 /* 32-bit ELF program header. */
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
;
141 /* 64-bit ELF program header. */
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
;
154 /* 32-bit ELF section header */
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
;
169 /* 64-bit ELF section header. */
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
;
184 /* Values for sh_type field. */
186 #define SHT_PROGBITS 1 /* Program data */
187 #define SHT_STRTAB 3 /* A string table */
189 /* Functions to fetch and store different ELF types, depending on the
190 endianness and size. */
192 struct elf_type_functions
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
);
202 static const struct elf_type_functions elf_big_32_functions
=
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
212 static const struct elf_type_functions elf_little_32_functions
=
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
222 #ifdef UNSIGNED_64BIT_TYPE
224 static const struct elf_type_functions elf_big_64_functions
=
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
234 static const struct elf_type_functions elf_little_64_functions
=
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
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. */
252 #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
253 ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
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. */
261 #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, \
263 ELF_FETCH_STRUCT_FIELD (TYPEFUNCS, \
264 Elf ## SIZE ## _External_ ## STRUCTTYPE, \
267 /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value. */
269 #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, \
271 ((CLASS) == ELFCLASS32 \
272 ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \
274 : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \
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
284 #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
285 (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
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. */
293 #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
295 ELF_SET_STRUCT_FIELD (TYPEFUNCS, \
296 Elf ## SIZE ## _External_ ## STRUCTTYPE, \
297 FIELD, BUFFER, TYPE, VAL)
299 /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value. */
301 #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD, \
303 ((CLASS) == ELFCLASS32 \
304 ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \
306 : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \
309 /* Private data for an simple_object_read. */
311 struct simple_object_elf_read
313 /* Type functions. */
314 const struct elf_type_functions
* type_functions
;
316 unsigned char ei_data
;
318 unsigned char ei_class
;
320 unsigned char ei_osabi
;
321 /* Elf machine number. */
322 unsigned short machine
;
323 /* Processor specific flags. */
325 /* File offset of section headers. */
327 /* Number of sections. */
329 /* Index of string table section header. */
330 unsigned int shstrndx
;
333 /* Private data for an simple_object_attributes. */
335 struct simple_object_elf_attributes
337 /* Type functions. */
338 const struct elf_type_functions
* type_functions
;
340 unsigned char ei_data
;
342 unsigned char ei_class
;
344 unsigned char ei_osabi
;
345 /* Elf machine number. */
346 unsigned short machine
;
347 /* Processor specific flags. */
351 /* See if we have an ELF file. */
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
)
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
;
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
)
376 ei_data
= header
[EI_DATA
];
377 if (ei_data
!= ELFDATA2LSB
&& ei_data
!= ELFDATA2MSB
)
379 *errmsg
= "unknown ELF endianness";
384 ei_class
= header
[EI_CLASS
];
388 type_functions
= (ei_data
== ELFDATA2LSB
389 ? &elf_little_32_functions
390 : &elf_big_32_functions
);
394 #ifndef UNSIGNED_64BIT_TYPE
395 *errmsg
= "64-bit ELF objects not supported";
399 type_functions
= (ei_data
== ELFDATA2LSB
400 ? &elf_little_64_functions
401 : &elf_big_64_functions
);
406 *errmsg
= "unrecognized ELF size";
411 if (!simple_object_internal_read (descriptor
, offset
, ehdr
, sizeof ehdr
,
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
,
424 eor
->shoff
= ELF_FETCH_FIELD (type_functions
, ei_class
, Ehdr
, ehdr
,
426 eor
->shnum
= ELF_FETCH_FIELD (type_functions
, ei_class
, Ehdr
, ehdr
,
428 eor
->shstrndx
= ELF_FETCH_FIELD (type_functions
, ei_class
, Ehdr
, ehdr
,
429 e_shstrndx
, Elf_Half
);
431 if ((eor
->shnum
== 0 || eor
->shstrndx
== SHN_XINDEX
)
434 unsigned char shdr
[sizeof (Elf64_External_Shdr
)];
436 /* Object file has more than 0xffff sections. */
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
)),
449 eor
->shnum
= ELF_FETCH_FIELD (type_functions
, ei_class
, Shdr
,
450 shdr
, sh_size
, Elf_Addr
);
452 if (eor
->shstrndx
== SHN_XINDEX
)
454 eor
->shstrndx
= ELF_FETCH_FIELD (type_functions
, ei_class
, Shdr
,
455 shdr
, sh_link
, Elf_Word
);
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;
474 if (eor
->shstrndx
>= eor
->shnum
)
476 *errmsg
= "invalid ELF shstrndx >= shnum";
485 /* Find all sections in an ELF file. */
488 simple_object_elf_find_sections (simple_object_read
*sobj
,
489 int (*pfn
) (void *, const char *,
490 off_t offset
, off_t length
),
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
;
500 unsigned char *shdrs
;
502 unsigned char *shstrhdr
;
505 unsigned char *names
;
508 shdr_size
= (ei_class
== ELFCLASS32
509 ? sizeof (Elf32_External_Shdr
)
510 : sizeof (Elf64_External_Shdr
));
512 /* Read the section headers. We skip section 0, which is not a
516 shdrs
= XNEWVEC (unsigned char, shdr_size
* (shnum
- 1));
518 if (!simple_object_internal_read (sobj
->descriptor
,
519 sobj
->offset
+ eor
->shoff
+ shdr_size
,
521 shdr_size
* (shnum
- 1),
528 /* Read the section names. */
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
))
545 for (i
= 1; i
< shnum
; ++i
)
548 unsigned int sh_name
;
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
)
561 return "ELF section name out of range";
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
);
570 if (!(*pfn
) (data
, name
, offset
, length
))
580 /* Fetch the attributes for an simple_object_read. */
583 simple_object_elf_fetch_attributes (simple_object_read
*sobj
,
584 const char **errmsg ATTRIBUTE_UNUSED
,
585 int *err ATTRIBUTE_UNUSED
)
587 struct simple_object_elf_read
*eor
=
588 (struct simple_object_elf_read
*) sobj
->data
;
589 struct simple_object_elf_attributes
*ret
;
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
;
601 /* Release the privata data for an simple_object_read. */
604 simple_object_elf_release_read (void *data
)
609 /* Compare two attributes structures. */
612 simple_object_elf_attributes_merge (void *todata
, void *fromdata
, int *err
)
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
;
619 if (to
->ei_data
!= from
->ei_data
|| to
->ei_class
!= from
->ei_class
)
622 return "ELF object format mismatch";
625 if (to
->machine
!= from
->machine
)
629 /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
630 output of EM_SPARC32PLUS. */
635 if (from
->machine
== EM_SPARC32PLUS
)
637 to
->machine
= from
->machine
;
643 if (from
->machine
== EM_SPARC
)
654 return "ELF machine number mismatch";
661 /* Release the private data for an attributes structure. */
664 simple_object_elf_release_attributes (void *data
)
669 /* Prepare to write out a file. */
672 simple_object_elf_start_write (void *attributes_data
,
673 const char **errmsg ATTRIBUTE_UNUSED
,
674 int *err ATTRIBUTE_UNUSED
)
676 struct simple_object_elf_attributes
*attrs
=
677 (struct simple_object_elf_attributes
*) attributes_data
;
678 struct simple_object_elf_attributes
*ret
;
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
);
687 /* Write out an ELF ehdr. */
690 simple_object_elf_write_ehdr (simple_object_write
*sobj
, int descriptor
,
691 const char **errmsg
, int *err
)
693 struct simple_object_elf_attributes
*attrs
=
694 (struct simple_object_elf_attributes
*) sobj
->data
;
695 const struct elf_type_functions
* fns
;
698 unsigned char buf
[sizeof (Elf64_External_Ehdr
)];
699 simple_object_write_section
*section
;
701 unsigned int shstrndx
;
703 fns
= attrs
->type_functions
;
704 cl
= attrs
->ei_class
;
707 for (section
= sobj
->sections
; section
!= NULL
; section
= section
->next
)
711 /* Add a section header for the dummy section and one for
716 ehdr_size
= (cl
== ELFCLASS32
717 ? sizeof (Elf32_External_Ehdr
)
718 : sizeof (Elf64_External_Ehdr
));
719 memset (buf
, 0, sizeof (Elf64_External_Ehdr
));
721 buf
[EI_MAG0
] = ELFMAG0
;
722 buf
[EI_MAG1
] = ELFMAG1
;
723 buf
[EI_MAG2
] = ELFMAG2
;
724 buf
[EI_MAG3
] = ELFMAG3
;
726 buf
[EI_DATA
] = attrs
->ei_data
;
727 buf
[EI_VERSION
] = EV_CURRENT
;
728 buf
[EI_OSABI
] = attrs
->ei_osabi
;
730 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_type
, Elf_Half
, ET_REL
);
731 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_machine
, Elf_Half
, attrs
->machine
);
732 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_version
, Elf_Word
, EV_CURRENT
);
733 /* e_entry left as zero. */
734 /* e_phoff left as zero. */
735 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_shoff
, Elf_Addr
, ehdr_size
);
736 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_flags
, Elf_Word
, attrs
->flags
);
737 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_ehsize
, Elf_Half
, ehdr_size
);
738 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_phentsize
, Elf_Half
,
740 ? sizeof (Elf32_External_Phdr
)
741 : sizeof (Elf64_External_Phdr
)));
742 /* e_phnum left as zero. */
743 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_shentsize
, Elf_Half
,
745 ? sizeof (Elf32_External_Shdr
)
746 : sizeof (Elf64_External_Shdr
)));
747 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_shnum
, Elf_Half
,
748 shnum
>= SHN_LORESERVE
? 0 : shnum
);
753 shstrndx
= shnum
- 1;
754 if (shstrndx
>= SHN_LORESERVE
)
755 shstrndx
= SHN_XINDEX
;
757 ELF_SET_FIELD (fns
, cl
, Ehdr
, buf
, e_shstrndx
, Elf_Half
, shstrndx
);
759 return simple_object_internal_write (descriptor
, 0, buf
, ehdr_size
,
763 /* Write out an ELF shdr. */
766 simple_object_elf_write_shdr (simple_object_write
*sobj
, int descriptor
,
767 off_t offset
, unsigned int sh_name
,
768 unsigned int sh_type
, unsigned int sh_flags
,
769 unsigned int sh_offset
, unsigned int sh_size
,
770 unsigned int sh_link
, unsigned int sh_addralign
,
771 const char **errmsg
, int *err
)
773 struct simple_object_elf_attributes
*attrs
=
774 (struct simple_object_elf_attributes
*) sobj
->data
;
775 const struct elf_type_functions
* fns
;
778 unsigned char buf
[sizeof (Elf64_External_Shdr
)];
780 fns
= attrs
->type_functions
;
781 cl
= attrs
->ei_class
;
783 shdr_size
= (cl
== ELFCLASS32
784 ? sizeof (Elf32_External_Shdr
)
785 : sizeof (Elf64_External_Shdr
));
786 memset (buf
, 0, sizeof (Elf64_External_Shdr
));
788 ELF_SET_FIELD (fns
, cl
, Shdr
, buf
, sh_name
, Elf_Word
, sh_name
);
789 ELF_SET_FIELD (fns
, cl
, Shdr
, buf
, sh_type
, Elf_Word
, sh_type
);
790 ELF_SET_FIELD (fns
, cl
, Shdr
, buf
, sh_flags
, Elf_Addr
, sh_flags
);
791 ELF_SET_FIELD (fns
, cl
, Shdr
, buf
, sh_offset
, Elf_Addr
, sh_offset
);
792 ELF_SET_FIELD (fns
, cl
, Shdr
, buf
, sh_size
, Elf_Addr
, sh_size
);
793 ELF_SET_FIELD (fns
, cl
, Shdr
, buf
, sh_link
, Elf_Word
, sh_link
);
794 /* sh_info left as zero. */
795 ELF_SET_FIELD (fns
, cl
, Shdr
, buf
, sh_addralign
, Elf_Addr
, sh_addralign
);
796 /* sh_entsize left as zero. */
798 return simple_object_internal_write (descriptor
, offset
, buf
, shdr_size
,
802 /* Write out a complete ELF file.
807 user-created section data
811 simple_object_elf_write_to_file (simple_object_write
*sobj
, int descriptor
,
814 struct simple_object_elf_attributes
*attrs
=
815 (struct simple_object_elf_attributes
*) sobj
->data
;
820 simple_object_write_section
*section
;
824 unsigned int first_sh_size
;
825 unsigned int first_sh_link
;
829 if (!simple_object_elf_write_ehdr (sobj
, descriptor
, &errmsg
, err
))
832 cl
= attrs
->ei_class
;
833 if (cl
== ELFCLASS32
)
835 ehdr_size
= sizeof (Elf32_External_Ehdr
);
836 shdr_size
= sizeof (Elf32_External_Shdr
);
840 ehdr_size
= sizeof (Elf64_External_Ehdr
);
841 shdr_size
= sizeof (Elf64_External_Shdr
);
845 for (section
= sobj
->sections
; section
!= NULL
; section
= section
->next
)
850 /* Add initial dummy Shdr and .shstrtab. */
853 shdr_offset
= ehdr_size
;
854 sh_offset
= shdr_offset
+ shnum
* shdr_size
;
856 if (shnum
< SHN_LORESERVE
)
859 first_sh_size
= shnum
;
860 if (shnum
- 1 < SHN_LORESERVE
)
863 first_sh_link
= shnum
- 1;
864 if (!simple_object_elf_write_shdr (sobj
, descriptor
, shdr_offset
,
865 0, 0, 0, 0, first_sh_size
, first_sh_link
,
869 shdr_offset
+= shdr_size
;
872 for (section
= sobj
->sections
; section
!= NULL
; section
= section
->next
)
875 size_t new_sh_offset
;
877 struct simple_object_write_section_buffer
*buffer
;
879 mask
= (1U << section
->align
) - 1;
880 new_sh_offset
= sh_offset
+ mask
;
881 new_sh_offset
&= ~ mask
;
882 while (new_sh_offset
> sh_offset
)
884 unsigned char zeroes
[16];
887 memset (zeroes
, 0, sizeof zeroes
);
888 write
= new_sh_offset
- sh_offset
;
889 if (write
> sizeof zeroes
)
890 write
= sizeof zeroes
;
891 if (!simple_object_internal_write (descriptor
, sh_offset
, zeroes
,
892 write
, &errmsg
, err
))
898 for (buffer
= section
->buffers
; buffer
!= NULL
; buffer
= buffer
->next
)
900 if (!simple_object_internal_write (descriptor
, sh_offset
+ sh_size
,
901 ((const unsigned char *)
903 buffer
->size
, &errmsg
, err
))
905 sh_size
+= buffer
->size
;
908 if (!simple_object_elf_write_shdr (sobj
, descriptor
, shdr_offset
,
909 sh_name
, SHT_PROGBITS
, 0, sh_offset
,
910 sh_size
, 0, 1U << section
->align
,
914 shdr_offset
+= shdr_size
;
915 sh_name
+= strlen (section
->name
) + 1;
916 sh_offset
+= sh_size
;
919 if (!simple_object_elf_write_shdr (sobj
, descriptor
, shdr_offset
,
920 sh_name
, SHT_STRTAB
, 0, sh_offset
,
921 sh_name
+ strlen (".shstrtab") + 1, 0,
925 /* .shstrtab has a leading zero byte. */
927 if (!simple_object_internal_write (descriptor
, sh_offset
, &zero
, 1,
932 for (section
= sobj
->sections
; section
!= NULL
; section
= section
->next
)
936 len
= strlen (section
->name
) + 1;
937 if (!simple_object_internal_write (descriptor
, sh_offset
,
938 (const unsigned char *) section
->name
,
944 if (!simple_object_internal_write (descriptor
, sh_offset
,
945 (const unsigned char *) ".shstrtab",
946 strlen (".shstrtab") + 1, &errmsg
, err
))
952 /* Release the private data for an simple_object_write structure. */
955 simple_object_elf_release_write (void *data
)
960 /* The ELF functions. */
962 const struct simple_object_functions simple_object_elf_functions
=
964 simple_object_elf_match
,
965 simple_object_elf_find_sections
,
966 simple_object_elf_fetch_attributes
,
967 simple_object_elf_release_read
,
968 simple_object_elf_attributes_merge
,
969 simple_object_elf_release_attributes
,
970 simple_object_elf_start_write
,
971 simple_object_elf_write_to_file
,
972 simple_object_elf_release_write