11debfc3dSmrg /* simple-object-elf.c -- routines to manipulate ELF object files.
2*8feb0f0bSmrg Copyright (C) 2010-2020 Free Software Foundation, Inc.
31debfc3dSmrg Written by Ian Lance Taylor, Google.
41debfc3dSmrg
51debfc3dSmrg This program is free software; you can redistribute it and/or modify it
61debfc3dSmrg under the terms of the GNU General Public License as published by the
71debfc3dSmrg Free Software Foundation; either version 2, or (at your option) any
81debfc3dSmrg later version.
91debfc3dSmrg
101debfc3dSmrg This program is distributed in the hope that it will be useful,
111debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
121debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
131debfc3dSmrg GNU General Public License for more details.
141debfc3dSmrg
151debfc3dSmrg You should have received a copy of the GNU General Public License
161debfc3dSmrg along with this program; if not, write to the Free Software
171debfc3dSmrg Foundation, 51 Franklin Street - Fifth Floor,
181debfc3dSmrg Boston, MA 02110-1301, USA. */
191debfc3dSmrg
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "libiberty.h"
221debfc3dSmrg #include "simple-object.h"
231debfc3dSmrg
241debfc3dSmrg #include <errno.h>
25a2dc1f3fSmrg /* mingw.org's MinGW doesn't have ENOTSUP. */
26a2dc1f3fSmrg #ifndef ENOTSUP
27a2dc1f3fSmrg # define ENOTSUP ENOSYS
28a2dc1f3fSmrg #endif
291debfc3dSmrg #include <stddef.h>
301debfc3dSmrg
311debfc3dSmrg #ifdef HAVE_STDLIB_H
321debfc3dSmrg #include <stdlib.h>
331debfc3dSmrg #endif
341debfc3dSmrg
351debfc3dSmrg #ifdef HAVE_STDINT_H
361debfc3dSmrg #include <stdint.h>
371debfc3dSmrg #endif
381debfc3dSmrg
391debfc3dSmrg #ifdef HAVE_STRING_H
401debfc3dSmrg #include <string.h>
411debfc3dSmrg #endif
421debfc3dSmrg
431debfc3dSmrg #ifdef HAVE_INTTYPES_H
441debfc3dSmrg #include <inttypes.h>
451debfc3dSmrg #endif
461debfc3dSmrg
471debfc3dSmrg #include "simple-object-common.h"
481debfc3dSmrg
491debfc3dSmrg /* ELF structures and constants. */
501debfc3dSmrg
511debfc3dSmrg /* 32-bit ELF file header. */
521debfc3dSmrg
531debfc3dSmrg typedef struct {
541debfc3dSmrg unsigned char e_ident[16]; /* ELF "magic number" */
551debfc3dSmrg unsigned char e_type[2]; /* Identifies object file type */
561debfc3dSmrg unsigned char e_machine[2]; /* Specifies required architecture */
571debfc3dSmrg unsigned char e_version[4]; /* Identifies object file version */
581debfc3dSmrg unsigned char e_entry[4]; /* Entry point virtual address */
591debfc3dSmrg unsigned char e_phoff[4]; /* Program header table file offset */
601debfc3dSmrg unsigned char e_shoff[4]; /* Section header table file offset */
611debfc3dSmrg unsigned char e_flags[4]; /* Processor-specific flags */
621debfc3dSmrg unsigned char e_ehsize[2]; /* ELF header size in bytes */
631debfc3dSmrg unsigned char e_phentsize[2]; /* Program header table entry size */
641debfc3dSmrg unsigned char e_phnum[2]; /* Program header table entry count */
651debfc3dSmrg unsigned char e_shentsize[2]; /* Section header table entry size */
661debfc3dSmrg unsigned char e_shnum[2]; /* Section header table entry count */
671debfc3dSmrg unsigned char e_shstrndx[2]; /* Section header string table index */
681debfc3dSmrg } Elf32_External_Ehdr;
691debfc3dSmrg
701debfc3dSmrg /* 64-bit ELF file header. */
711debfc3dSmrg
721debfc3dSmrg typedef struct {
731debfc3dSmrg unsigned char e_ident[16]; /* ELF "magic number" */
741debfc3dSmrg unsigned char e_type[2]; /* Identifies object file type */
751debfc3dSmrg unsigned char e_machine[2]; /* Specifies required architecture */
761debfc3dSmrg unsigned char e_version[4]; /* Identifies object file version */
771debfc3dSmrg unsigned char e_entry[8]; /* Entry point virtual address */
781debfc3dSmrg unsigned char e_phoff[8]; /* Program header table file offset */
791debfc3dSmrg unsigned char e_shoff[8]; /* Section header table file offset */
801debfc3dSmrg unsigned char e_flags[4]; /* Processor-specific flags */
811debfc3dSmrg unsigned char e_ehsize[2]; /* ELF header size in bytes */
821debfc3dSmrg unsigned char e_phentsize[2]; /* Program header table entry size */
831debfc3dSmrg unsigned char e_phnum[2]; /* Program header table entry count */
841debfc3dSmrg unsigned char e_shentsize[2]; /* Section header table entry size */
851debfc3dSmrg unsigned char e_shnum[2]; /* Section header table entry count */
861debfc3dSmrg unsigned char e_shstrndx[2]; /* Section header string table index */
871debfc3dSmrg } Elf64_External_Ehdr;
881debfc3dSmrg
891debfc3dSmrg /* Indexes and values in e_ident field of Ehdr. */
901debfc3dSmrg
911debfc3dSmrg #define EI_MAG0 0 /* File identification byte 0 index */
921debfc3dSmrg #define ELFMAG0 0x7F /* Magic number byte 0 */
931debfc3dSmrg
941debfc3dSmrg #define EI_MAG1 1 /* File identification byte 1 index */
951debfc3dSmrg #define ELFMAG1 'E' /* Magic number byte 1 */
961debfc3dSmrg
971debfc3dSmrg #define EI_MAG2 2 /* File identification byte 2 index */
981debfc3dSmrg #define ELFMAG2 'L' /* Magic number byte 2 */
991debfc3dSmrg
1001debfc3dSmrg #define EI_MAG3 3 /* File identification byte 3 index */
1011debfc3dSmrg #define ELFMAG3 'F' /* Magic number byte 3 */
1021debfc3dSmrg
1031debfc3dSmrg #define EI_CLASS 4 /* File class */
1041debfc3dSmrg #define ELFCLASSNONE 0 /* Invalid class */
1051debfc3dSmrg #define ELFCLASS32 1 /* 32-bit objects */
1061debfc3dSmrg #define ELFCLASS64 2 /* 64-bit objects */
1071debfc3dSmrg
1081debfc3dSmrg #define EI_DATA 5 /* Data encoding */
1091debfc3dSmrg #define ELFDATANONE 0 /* Invalid data encoding */
1101debfc3dSmrg #define ELFDATA2LSB 1 /* 2's complement, little endian */
1111debfc3dSmrg #define ELFDATA2MSB 2 /* 2's complement, big endian */
1121debfc3dSmrg
1131debfc3dSmrg #define EI_VERSION 6 /* File version */
1141debfc3dSmrg #define EV_CURRENT 1 /* Current version */
1151debfc3dSmrg
1161debfc3dSmrg #define EI_OSABI 7 /* Operating System/ABI indication */
1171debfc3dSmrg
1181debfc3dSmrg /* Values for e_type field of Ehdr. */
1191debfc3dSmrg
1201debfc3dSmrg #define ET_REL 1 /* Relocatable file */
1211debfc3dSmrg
1221debfc3dSmrg /* Values for e_machine field of Ehdr. */
1231debfc3dSmrg
1241debfc3dSmrg #define EM_SPARC 2 /* SUN SPARC */
1251debfc3dSmrg #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
1261debfc3dSmrg
1271debfc3dSmrg /* Special section index values. */
1281debfc3dSmrg
129a2dc1f3fSmrg #define SHN_UNDEF 0 /* Undefined section */
1301debfc3dSmrg #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
131a2dc1f3fSmrg #define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
1321debfc3dSmrg #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
133a2dc1f3fSmrg #define SHN_HIRESERVE 0xffff /* End of reserved indices */
134a2dc1f3fSmrg
1351debfc3dSmrg
1361debfc3dSmrg /* 32-bit ELF program header. */
1371debfc3dSmrg
1381debfc3dSmrg typedef struct {
1391debfc3dSmrg unsigned char p_type[4]; /* Identifies program segment type */
1401debfc3dSmrg unsigned char p_offset[4]; /* Segment file offset */
1411debfc3dSmrg unsigned char p_vaddr[4]; /* Segment virtual address */
1421debfc3dSmrg unsigned char p_paddr[4]; /* Segment physical address */
1431debfc3dSmrg unsigned char p_filesz[4]; /* Segment size in file */
1441debfc3dSmrg unsigned char p_memsz[4]; /* Segment size in memory */
1451debfc3dSmrg unsigned char p_flags[4]; /* Segment flags */
1461debfc3dSmrg unsigned char p_align[4]; /* Segment alignment, file & memory */
1471debfc3dSmrg } Elf32_External_Phdr;
1481debfc3dSmrg
1491debfc3dSmrg /* 64-bit ELF program header. */
1501debfc3dSmrg
1511debfc3dSmrg typedef struct {
1521debfc3dSmrg unsigned char p_type[4]; /* Identifies program segment type */
1531debfc3dSmrg unsigned char p_flags[4]; /* Segment flags */
1541debfc3dSmrg unsigned char p_offset[8]; /* Segment file offset */
1551debfc3dSmrg unsigned char p_vaddr[8]; /* Segment virtual address */
1561debfc3dSmrg unsigned char p_paddr[8]; /* Segment physical address */
1571debfc3dSmrg unsigned char p_filesz[8]; /* Segment size in file */
1581debfc3dSmrg unsigned char p_memsz[8]; /* Segment size in memory */
1591debfc3dSmrg unsigned char p_align[8]; /* Segment alignment, file & memory */
1601debfc3dSmrg } Elf64_External_Phdr;
1611debfc3dSmrg
1621debfc3dSmrg /* 32-bit ELF section header */
1631debfc3dSmrg
1641debfc3dSmrg typedef struct {
1651debfc3dSmrg unsigned char sh_name[4]; /* Section name, index in string tbl */
1661debfc3dSmrg unsigned char sh_type[4]; /* Type of section */
1671debfc3dSmrg unsigned char sh_flags[4]; /* Miscellaneous section attributes */
1681debfc3dSmrg unsigned char sh_addr[4]; /* Section virtual addr at execution */
1691debfc3dSmrg unsigned char sh_offset[4]; /* Section file offset */
1701debfc3dSmrg unsigned char sh_size[4]; /* Size of section in bytes */
1711debfc3dSmrg unsigned char sh_link[4]; /* Index of another section */
1721debfc3dSmrg unsigned char sh_info[4]; /* Additional section information */
1731debfc3dSmrg unsigned char sh_addralign[4]; /* Section alignment */
1741debfc3dSmrg unsigned char sh_entsize[4]; /* Entry size if section holds table */
1751debfc3dSmrg } Elf32_External_Shdr;
1761debfc3dSmrg
1771debfc3dSmrg /* 64-bit ELF section header. */
1781debfc3dSmrg
1791debfc3dSmrg typedef struct {
1801debfc3dSmrg unsigned char sh_name[4]; /* Section name, index in string tbl */
1811debfc3dSmrg unsigned char sh_type[4]; /* Type of section */
1821debfc3dSmrg unsigned char sh_flags[8]; /* Miscellaneous section attributes */
1831debfc3dSmrg unsigned char sh_addr[8]; /* Section virtual addr at execution */
1841debfc3dSmrg unsigned char sh_offset[8]; /* Section file offset */
1851debfc3dSmrg unsigned char sh_size[8]; /* Size of section in bytes */
1861debfc3dSmrg unsigned char sh_link[4]; /* Index of another section */
1871debfc3dSmrg unsigned char sh_info[4]; /* Additional section information */
1881debfc3dSmrg unsigned char sh_addralign[8]; /* Section alignment */
1891debfc3dSmrg unsigned char sh_entsize[8]; /* Entry size if section holds table */
1901debfc3dSmrg } Elf64_External_Shdr;
1911debfc3dSmrg
1921debfc3dSmrg /* Values for sh_type field. */
1931debfc3dSmrg
194a2dc1f3fSmrg #define SHT_NULL 0 /* Section header table entry unused */
1951debfc3dSmrg #define SHT_PROGBITS 1 /* Program data */
196a2dc1f3fSmrg #define SHT_SYMTAB 2 /* Link editing symbol table */
1971debfc3dSmrg #define SHT_STRTAB 3 /* A string table */
198a2dc1f3fSmrg #define SHT_RELA 4 /* Relocation entries with addends */
199a2dc1f3fSmrg #define SHT_REL 9 /* Relocation entries, no addends */
200a2dc1f3fSmrg #define SHT_GROUP 17 /* Section contains a section group */
201a2dc1f3fSmrg #define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
202a2dc1f3fSmrg
203a2dc1f3fSmrg /* Values for sh_flags field. */
204a2dc1f3fSmrg
205a2dc1f3fSmrg #define SHF_INFO_LINK 0x00000040 /* `sh_info' contains SHT index */
206a2dc1f3fSmrg #define SHF_EXECINSTR 0x00000004 /* Executable section. */
207a2dc1f3fSmrg #define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this
208a2dc1f3fSmrg section from executable and
209a2dc1f3fSmrg shared library that it builds
210a2dc1f3fSmrg when those objects are not to be
211a2dc1f3fSmrg further relocated. */
212a2dc1f3fSmrg /* Symbol table entry. */
213a2dc1f3fSmrg
214a2dc1f3fSmrg typedef struct
215a2dc1f3fSmrg {
216a2dc1f3fSmrg unsigned char st_name[4]; /* Symbol name (string tbl index) */
217a2dc1f3fSmrg unsigned char st_value[4]; /* Symbol value */
218a2dc1f3fSmrg unsigned char st_size[4]; /* Symbol size */
219a2dc1f3fSmrg unsigned char st_info; /* Symbol type and binding */
220a2dc1f3fSmrg unsigned char st_other; /* Symbol visibility */
221a2dc1f3fSmrg unsigned char st_shndx[2]; /* Section index */
222a2dc1f3fSmrg } Elf32_External_Sym;
223a2dc1f3fSmrg
224a2dc1f3fSmrg typedef struct
225a2dc1f3fSmrg {
226a2dc1f3fSmrg unsigned char st_name[4]; /* Symbol name (string tbl index) */
227a2dc1f3fSmrg unsigned char st_info; /* Symbol type and binding */
228a2dc1f3fSmrg unsigned char st_other; /* Symbol visibility */
229a2dc1f3fSmrg unsigned char st_shndx[2]; /* Section index */
230a2dc1f3fSmrg unsigned char st_value[8]; /* Symbol value */
231a2dc1f3fSmrg unsigned char st_size[8]; /* Symbol size */
232a2dc1f3fSmrg } Elf64_External_Sym;
233a2dc1f3fSmrg
234a2dc1f3fSmrg #define ELF_ST_BIND(val) (((unsigned char) (val)) >> 4)
235a2dc1f3fSmrg #define ELF_ST_TYPE(val) ((val) & 0xf)
236a2dc1f3fSmrg #define ELF_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
237a2dc1f3fSmrg
238a2dc1f3fSmrg #define STT_NOTYPE 0 /* Symbol type is unspecified */
239a2dc1f3fSmrg #define STT_OBJECT 1 /* Symbol is a data object */
240a2dc1f3fSmrg #define STT_FUNC 2 /* Symbol is a code object */
241a2dc1f3fSmrg #define STT_TLS 6 /* Thread local data object */
242a2dc1f3fSmrg #define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */
243a2dc1f3fSmrg
244a2dc1f3fSmrg #define STB_LOCAL 0 /* Local symbol */
245a2dc1f3fSmrg #define STB_GLOBAL 1 /* Global symbol */
246a2dc1f3fSmrg #define STB_WEAK 2 /* Weak global */
247a2dc1f3fSmrg
248a2dc1f3fSmrg #define STV_DEFAULT 0 /* Visibility is specified by binding type */
249a2dc1f3fSmrg #define STV_HIDDEN 2 /* Can only be seen inside currect component */
2501debfc3dSmrg
2511debfc3dSmrg /* Functions to fetch and store different ELF types, depending on the
2521debfc3dSmrg endianness and size. */
2531debfc3dSmrg
2541debfc3dSmrg struct elf_type_functions
2551debfc3dSmrg {
2561debfc3dSmrg unsigned short (*fetch_Elf_Half) (const unsigned char *);
2571debfc3dSmrg unsigned int (*fetch_Elf_Word) (const unsigned char *);
2581debfc3dSmrg ulong_type (*fetch_Elf_Addr) (const unsigned char *);
2591debfc3dSmrg void (*set_Elf_Half) (unsigned char *, unsigned short);
2601debfc3dSmrg void (*set_Elf_Word) (unsigned char *, unsigned int);
2611debfc3dSmrg void (*set_Elf_Addr) (unsigned char *, ulong_type);
2621debfc3dSmrg };
2631debfc3dSmrg
2641debfc3dSmrg static const struct elf_type_functions elf_big_32_functions =
2651debfc3dSmrg {
2661debfc3dSmrg simple_object_fetch_big_16,
2671debfc3dSmrg simple_object_fetch_big_32,
2681debfc3dSmrg simple_object_fetch_big_32_ulong,
2691debfc3dSmrg simple_object_set_big_16,
2701debfc3dSmrg simple_object_set_big_32,
2711debfc3dSmrg simple_object_set_big_32_ulong
2721debfc3dSmrg };
2731debfc3dSmrg
2741debfc3dSmrg static const struct elf_type_functions elf_little_32_functions =
2751debfc3dSmrg {
2761debfc3dSmrg simple_object_fetch_little_16,
2771debfc3dSmrg simple_object_fetch_little_32,
2781debfc3dSmrg simple_object_fetch_little_32_ulong,
2791debfc3dSmrg simple_object_set_little_16,
2801debfc3dSmrg simple_object_set_little_32,
2811debfc3dSmrg simple_object_set_little_32_ulong
2821debfc3dSmrg };
2831debfc3dSmrg
2841debfc3dSmrg #ifdef UNSIGNED_64BIT_TYPE
2851debfc3dSmrg
2861debfc3dSmrg static const struct elf_type_functions elf_big_64_functions =
2871debfc3dSmrg {
2881debfc3dSmrg simple_object_fetch_big_16,
2891debfc3dSmrg simple_object_fetch_big_32,
2901debfc3dSmrg simple_object_fetch_big_64,
2911debfc3dSmrg simple_object_set_big_16,
2921debfc3dSmrg simple_object_set_big_32,
2931debfc3dSmrg simple_object_set_big_64
2941debfc3dSmrg };
2951debfc3dSmrg
2961debfc3dSmrg static const struct elf_type_functions elf_little_64_functions =
2971debfc3dSmrg {
2981debfc3dSmrg simple_object_fetch_little_16,
2991debfc3dSmrg simple_object_fetch_little_32,
3001debfc3dSmrg simple_object_fetch_little_64,
3011debfc3dSmrg simple_object_set_little_16,
3021debfc3dSmrg simple_object_set_little_32,
3031debfc3dSmrg simple_object_set_little_64
3041debfc3dSmrg };
3051debfc3dSmrg
3061debfc3dSmrg #endif
3071debfc3dSmrg
3081debfc3dSmrg /* Hideous macro to fetch the value of a field from an external ELF
3091debfc3dSmrg struct of some sort. TYPEFUNCS is the set of type functions.
3101debfc3dSmrg BUFFER points to the external data. STRUCTTYPE is the appropriate
3111debfc3dSmrg struct type. FIELD is a field within the struct. TYPE is the type
3121debfc3dSmrg of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */
3131debfc3dSmrg
3141debfc3dSmrg #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
3151debfc3dSmrg ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
3161debfc3dSmrg
3171debfc3dSmrg /* Even more hideous macro to fetch the value of FIELD from BUFFER.
3181debfc3dSmrg SIZE is 32 or 64. STRUCTTYPE is the name of the struct from
3191debfc3dSmrg elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in
3201debfc3dSmrg the struct. TYPE is the type of the field in the struct: Elf_Half,
3211debfc3dSmrg Elf_Word, or Elf_Addr. */
3221debfc3dSmrg
3231debfc3dSmrg #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, \
3241debfc3dSmrg FIELD, TYPE) \
3251debfc3dSmrg ELF_FETCH_STRUCT_FIELD (TYPEFUNCS, \
3261debfc3dSmrg Elf ## SIZE ## _External_ ## STRUCTTYPE, \
3271debfc3dSmrg FIELD, BUFFER, TYPE)
3281debfc3dSmrg
3291debfc3dSmrg /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value. */
3301debfc3dSmrg
3311debfc3dSmrg #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, \
3321debfc3dSmrg FIELD, TYPE) \
3331debfc3dSmrg ((CLASS) == ELFCLASS32 \
3341debfc3dSmrg ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \
3351debfc3dSmrg TYPE) \
3361debfc3dSmrg : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \
3371debfc3dSmrg TYPE))
3381debfc3dSmrg
3391debfc3dSmrg /* Hideous macro to set the value of a field in an external ELF
3401debfc3dSmrg structure to VAL. TYPEFUNCS is the set of type functions. BUFFER
3411debfc3dSmrg points to the external data. STRUCTTYPE is the appropriate
3421debfc3dSmrg structure type. FIELD is a field within the struct. TYPE is the
3431debfc3dSmrg type of the field in the struct: Elf_Half, Elf_Word, or
3441debfc3dSmrg Elf_Addr. */
3451debfc3dSmrg
3461debfc3dSmrg #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
3471debfc3dSmrg (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
3481debfc3dSmrg
3491debfc3dSmrg /* Even more hideous macro to set the value of FIELD in BUFFER to VAL.
3501debfc3dSmrg SIZE is 32 or 64. STRUCTTYPE is the name of the struct from
3511debfc3dSmrg elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in
3521debfc3dSmrg the struct. TYPE is the type of the field in the struct: Elf_Half,
3531debfc3dSmrg Elf_Word, or Elf_Addr. */
3541debfc3dSmrg
3551debfc3dSmrg #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
3561debfc3dSmrg TYPE, VAL) \
3571debfc3dSmrg ELF_SET_STRUCT_FIELD (TYPEFUNCS, \
3581debfc3dSmrg Elf ## SIZE ## _External_ ## STRUCTTYPE, \
3591debfc3dSmrg FIELD, BUFFER, TYPE, VAL)
3601debfc3dSmrg
3611debfc3dSmrg /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value. */
3621debfc3dSmrg
3631debfc3dSmrg #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD, \
3641debfc3dSmrg TYPE, VAL) \
3651debfc3dSmrg ((CLASS) == ELFCLASS32 \
3661debfc3dSmrg ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \
3671debfc3dSmrg TYPE, VAL) \
3681debfc3dSmrg : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \
3691debfc3dSmrg TYPE, VAL))
3701debfc3dSmrg
3711debfc3dSmrg /* Private data for an simple_object_read. */
3721debfc3dSmrg
3731debfc3dSmrg struct simple_object_elf_read
3741debfc3dSmrg {
3751debfc3dSmrg /* Type functions. */
3761debfc3dSmrg const struct elf_type_functions* type_functions;
3771debfc3dSmrg /* Elf data. */
3781debfc3dSmrg unsigned char ei_data;
3791debfc3dSmrg /* Elf class. */
3801debfc3dSmrg unsigned char ei_class;
3811debfc3dSmrg /* ELF OS ABI. */
3821debfc3dSmrg unsigned char ei_osabi;
3831debfc3dSmrg /* Elf machine number. */
3841debfc3dSmrg unsigned short machine;
3851debfc3dSmrg /* Processor specific flags. */
3861debfc3dSmrg unsigned int flags;
3871debfc3dSmrg /* File offset of section headers. */
3881debfc3dSmrg ulong_type shoff;
3891debfc3dSmrg /* Number of sections. */
3901debfc3dSmrg unsigned int shnum;
3911debfc3dSmrg /* Index of string table section header. */
3921debfc3dSmrg unsigned int shstrndx;
3931debfc3dSmrg };
3941debfc3dSmrg
3951debfc3dSmrg /* Private data for an simple_object_attributes. */
3961debfc3dSmrg
3971debfc3dSmrg struct simple_object_elf_attributes
3981debfc3dSmrg {
3991debfc3dSmrg /* Type functions. */
4001debfc3dSmrg const struct elf_type_functions* type_functions;
4011debfc3dSmrg /* Elf data. */
4021debfc3dSmrg unsigned char ei_data;
4031debfc3dSmrg /* Elf class. */
4041debfc3dSmrg unsigned char ei_class;
4051debfc3dSmrg /* ELF OS ABI. */
4061debfc3dSmrg unsigned char ei_osabi;
4071debfc3dSmrg /* Elf machine number. */
4081debfc3dSmrg unsigned short machine;
4091debfc3dSmrg /* Processor specific flags. */
4101debfc3dSmrg unsigned int flags;
4111debfc3dSmrg };
4121debfc3dSmrg
413a2dc1f3fSmrg /* Private data for an simple_object_write. */
414a2dc1f3fSmrg
415a2dc1f3fSmrg struct simple_object_elf_write
416a2dc1f3fSmrg {
417a2dc1f3fSmrg struct simple_object_elf_attributes attrs;
418a2dc1f3fSmrg unsigned char *shdrs;
419a2dc1f3fSmrg };
420a2dc1f3fSmrg
4211debfc3dSmrg /* See if we have an ELF file. */
4221debfc3dSmrg
4231debfc3dSmrg static void *
simple_object_elf_match(unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],int descriptor,off_t offset,const char * segment_name ATTRIBUTE_UNUSED,const char ** errmsg,int * err)4241debfc3dSmrg simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
4251debfc3dSmrg int descriptor, off_t offset,
4261debfc3dSmrg const char *segment_name ATTRIBUTE_UNUSED,
4271debfc3dSmrg const char **errmsg, int *err)
4281debfc3dSmrg {
4291debfc3dSmrg unsigned char ei_data;
4301debfc3dSmrg unsigned char ei_class;
4311debfc3dSmrg const struct elf_type_functions *type_functions;
4321debfc3dSmrg unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
4331debfc3dSmrg struct simple_object_elf_read *eor;
4341debfc3dSmrg
4351debfc3dSmrg if (header[EI_MAG0] != ELFMAG0
4361debfc3dSmrg || header[EI_MAG1] != ELFMAG1
4371debfc3dSmrg || header[EI_MAG2] != ELFMAG2
4381debfc3dSmrg || header[EI_MAG3] != ELFMAG3
4391debfc3dSmrg || header[EI_VERSION] != EV_CURRENT)
4401debfc3dSmrg {
4411debfc3dSmrg *errmsg = NULL;
4421debfc3dSmrg *err = 0;
4431debfc3dSmrg return NULL;
4441debfc3dSmrg }
4451debfc3dSmrg
4461debfc3dSmrg ei_data = header[EI_DATA];
4471debfc3dSmrg if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
4481debfc3dSmrg {
4491debfc3dSmrg *errmsg = "unknown ELF endianness";
4501debfc3dSmrg *err = 0;
4511debfc3dSmrg return NULL;
4521debfc3dSmrg }
4531debfc3dSmrg
4541debfc3dSmrg ei_class = header[EI_CLASS];
4551debfc3dSmrg switch (ei_class)
4561debfc3dSmrg {
4571debfc3dSmrg case ELFCLASS32:
4581debfc3dSmrg type_functions = (ei_data == ELFDATA2LSB
4591debfc3dSmrg ? &elf_little_32_functions
4601debfc3dSmrg : &elf_big_32_functions);
4611debfc3dSmrg break;
4621debfc3dSmrg
4631debfc3dSmrg case ELFCLASS64:
4641debfc3dSmrg #ifndef UNSIGNED_64BIT_TYPE
4651debfc3dSmrg *errmsg = "64-bit ELF objects not supported";
4661debfc3dSmrg *err = 0;
4671debfc3dSmrg return NULL;
4681debfc3dSmrg #else
4691debfc3dSmrg type_functions = (ei_data == ELFDATA2LSB
4701debfc3dSmrg ? &elf_little_64_functions
4711debfc3dSmrg : &elf_big_64_functions);
4721debfc3dSmrg break;
4731debfc3dSmrg #endif
4741debfc3dSmrg
4751debfc3dSmrg default:
4761debfc3dSmrg *errmsg = "unrecognized ELF size";
4771debfc3dSmrg *err = 0;
4781debfc3dSmrg return NULL;
4791debfc3dSmrg }
4801debfc3dSmrg
4811debfc3dSmrg if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr,
4821debfc3dSmrg errmsg, err))
4831debfc3dSmrg return NULL;
4841debfc3dSmrg
4851debfc3dSmrg eor = XNEW (struct simple_object_elf_read);
4861debfc3dSmrg eor->type_functions = type_functions;
4871debfc3dSmrg eor->ei_data = ei_data;
4881debfc3dSmrg eor->ei_class = ei_class;
4891debfc3dSmrg eor->ei_osabi = header[EI_OSABI];
4901debfc3dSmrg eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
4911debfc3dSmrg e_machine, Elf_Half);
4921debfc3dSmrg eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
4931debfc3dSmrg e_flags, Elf_Word);
4941debfc3dSmrg eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
4951debfc3dSmrg e_shoff, Elf_Addr);
4961debfc3dSmrg eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
4971debfc3dSmrg e_shnum, Elf_Half);
4981debfc3dSmrg eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
4991debfc3dSmrg e_shstrndx, Elf_Half);
5001debfc3dSmrg
5011debfc3dSmrg if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
5021debfc3dSmrg && eor->shoff != 0)
5031debfc3dSmrg {
5041debfc3dSmrg unsigned char shdr[sizeof (Elf64_External_Shdr)];
5051debfc3dSmrg
5061debfc3dSmrg /* Object file has more than 0xffff sections. */
5071debfc3dSmrg
5081debfc3dSmrg if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr,
5091debfc3dSmrg (ei_class == ELFCLASS32
5101debfc3dSmrg ? sizeof (Elf32_External_Shdr)
5111debfc3dSmrg : sizeof (Elf64_External_Shdr)),
5121debfc3dSmrg errmsg, err))
5131debfc3dSmrg {
5141debfc3dSmrg XDELETE (eor);
5151debfc3dSmrg return NULL;
5161debfc3dSmrg }
5171debfc3dSmrg
5181debfc3dSmrg if (eor->shnum == 0)
5191debfc3dSmrg eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
5201debfc3dSmrg shdr, sh_size, Elf_Addr);
5211debfc3dSmrg
5221debfc3dSmrg if (eor->shstrndx == SHN_XINDEX)
5231debfc3dSmrg {
5241debfc3dSmrg eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
5251debfc3dSmrg shdr, sh_link, Elf_Word);
5261debfc3dSmrg
5271debfc3dSmrg /* Versions of the GNU binutils between 2.12 and 2.18 did
5281debfc3dSmrg not handle objects with more than SHN_LORESERVE sections
5291debfc3dSmrg correctly. All large section indexes were offset by
5301debfc3dSmrg 0x100. There is more information at
531*8feb0f0bSmrg https://sourceware.org/PR5900 .
5321debfc3dSmrg Fortunately these object files are easy to detect, as the
5331debfc3dSmrg GNU binutils always put the section header string table
5341debfc3dSmrg near the end of the list of sections. Thus if the
5351debfc3dSmrg section header string table index is larger than the
5361debfc3dSmrg number of sections, then we know we have to subtract
5371debfc3dSmrg 0x100 to get the real section index. */
5381debfc3dSmrg if (eor->shstrndx >= eor->shnum
5391debfc3dSmrg && eor->shstrndx >= SHN_LORESERVE + 0x100)
5401debfc3dSmrg eor->shstrndx -= 0x100;
5411debfc3dSmrg }
5421debfc3dSmrg }
5431debfc3dSmrg
5441debfc3dSmrg if (eor->shstrndx >= eor->shnum)
5451debfc3dSmrg {
5461debfc3dSmrg *errmsg = "invalid ELF shstrndx >= shnum";
5471debfc3dSmrg *err = 0;
5481debfc3dSmrg XDELETE (eor);
5491debfc3dSmrg return NULL;
5501debfc3dSmrg }
5511debfc3dSmrg
552a2dc1f3fSmrg if (eor->shstrndx == 0)
553a2dc1f3fSmrg {
554a2dc1f3fSmrg *errmsg = "invalid ELF shstrndx == 0";
555a2dc1f3fSmrg *err = 0;
556a2dc1f3fSmrg XDELETE (eor);
557a2dc1f3fSmrg return NULL;
558a2dc1f3fSmrg }
559a2dc1f3fSmrg
5601debfc3dSmrg return (void *) eor;
5611debfc3dSmrg }
5621debfc3dSmrg
5631debfc3dSmrg /* Find all sections in an ELF file. */
5641debfc3dSmrg
5651debfc3dSmrg static const char *
simple_object_elf_find_sections(simple_object_read * sobj,int (* pfn)(void *,const char *,off_t offset,off_t length),void * data,int * err)5661debfc3dSmrg simple_object_elf_find_sections (simple_object_read *sobj,
5671debfc3dSmrg int (*pfn) (void *, const char *,
5681debfc3dSmrg off_t offset, off_t length),
5691debfc3dSmrg void *data,
5701debfc3dSmrg int *err)
5711debfc3dSmrg {
5721debfc3dSmrg struct simple_object_elf_read *eor =
5731debfc3dSmrg (struct simple_object_elf_read *) sobj->data;
5741debfc3dSmrg const struct elf_type_functions *type_functions = eor->type_functions;
5751debfc3dSmrg unsigned char ei_class = eor->ei_class;
5761debfc3dSmrg size_t shdr_size;
5771debfc3dSmrg unsigned int shnum;
5781debfc3dSmrg unsigned char *shdrs;
5791debfc3dSmrg const char *errmsg;
5801debfc3dSmrg unsigned char *shstrhdr;
5811debfc3dSmrg size_t name_size;
5821debfc3dSmrg off_t shstroff;
5831debfc3dSmrg unsigned char *names;
5841debfc3dSmrg unsigned int i;
5851debfc3dSmrg
5861debfc3dSmrg shdr_size = (ei_class == ELFCLASS32
5871debfc3dSmrg ? sizeof (Elf32_External_Shdr)
5881debfc3dSmrg : sizeof (Elf64_External_Shdr));
5891debfc3dSmrg
5901debfc3dSmrg /* Read the section headers. We skip section 0, which is not a
5911debfc3dSmrg useful section. */
5921debfc3dSmrg
5931debfc3dSmrg shnum = eor->shnum;
5941debfc3dSmrg shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
5951debfc3dSmrg
5961debfc3dSmrg if (!simple_object_internal_read (sobj->descriptor,
5971debfc3dSmrg sobj->offset + eor->shoff + shdr_size,
5981debfc3dSmrg shdrs,
5991debfc3dSmrg shdr_size * (shnum - 1),
6001debfc3dSmrg &errmsg, err))
6011debfc3dSmrg {
6021debfc3dSmrg XDELETEVEC (shdrs);
6031debfc3dSmrg return errmsg;
6041debfc3dSmrg }
6051debfc3dSmrg
6061debfc3dSmrg /* Read the section names. */
6071debfc3dSmrg
6081debfc3dSmrg shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
6091debfc3dSmrg name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
6101debfc3dSmrg shstrhdr, sh_size, Elf_Addr);
6111debfc3dSmrg shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
6121debfc3dSmrg shstrhdr, sh_offset, Elf_Addr);
6131debfc3dSmrg names = XNEWVEC (unsigned char, name_size);
6141debfc3dSmrg if (!simple_object_internal_read (sobj->descriptor,
6151debfc3dSmrg sobj->offset + shstroff,
6161debfc3dSmrg names, name_size, &errmsg, err))
6171debfc3dSmrg {
6181debfc3dSmrg XDELETEVEC (names);
6191debfc3dSmrg XDELETEVEC (shdrs);
6201debfc3dSmrg return errmsg;
6211debfc3dSmrg }
6221debfc3dSmrg
6231debfc3dSmrg for (i = 1; i < shnum; ++i)
6241debfc3dSmrg {
6251debfc3dSmrg unsigned char *shdr;
6261debfc3dSmrg unsigned int sh_name;
6271debfc3dSmrg const char *name;
6281debfc3dSmrg off_t offset;
6291debfc3dSmrg off_t length;
6301debfc3dSmrg
6311debfc3dSmrg shdr = shdrs + (i - 1) * shdr_size;
6321debfc3dSmrg sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
6331debfc3dSmrg shdr, sh_name, Elf_Word);
6341debfc3dSmrg if (sh_name >= name_size)
6351debfc3dSmrg {
6361debfc3dSmrg *err = 0;
6371debfc3dSmrg XDELETEVEC (names);
6381debfc3dSmrg XDELETEVEC (shdrs);
6391debfc3dSmrg return "ELF section name out of range";
6401debfc3dSmrg }
6411debfc3dSmrg
6421debfc3dSmrg name = (const char *) names + sh_name;
6431debfc3dSmrg offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
6441debfc3dSmrg shdr, sh_offset, Elf_Addr);
6451debfc3dSmrg length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
6461debfc3dSmrg shdr, sh_size, Elf_Addr);
6471debfc3dSmrg
6481debfc3dSmrg if (!(*pfn) (data, name, offset, length))
6491debfc3dSmrg break;
6501debfc3dSmrg }
6511debfc3dSmrg
6521debfc3dSmrg XDELETEVEC (names);
6531debfc3dSmrg XDELETEVEC (shdrs);
6541debfc3dSmrg
6551debfc3dSmrg return NULL;
6561debfc3dSmrg }
6571debfc3dSmrg
6581debfc3dSmrg /* Fetch the attributes for an simple_object_read. */
6591debfc3dSmrg
6601debfc3dSmrg static void *
simple_object_elf_fetch_attributes(simple_object_read * sobj,const char ** errmsg ATTRIBUTE_UNUSED,int * err ATTRIBUTE_UNUSED)6611debfc3dSmrg simple_object_elf_fetch_attributes (simple_object_read *sobj,
6621debfc3dSmrg const char **errmsg ATTRIBUTE_UNUSED,
6631debfc3dSmrg int *err ATTRIBUTE_UNUSED)
6641debfc3dSmrg {
6651debfc3dSmrg struct simple_object_elf_read *eor =
6661debfc3dSmrg (struct simple_object_elf_read *) sobj->data;
6671debfc3dSmrg struct simple_object_elf_attributes *ret;
6681debfc3dSmrg
6691debfc3dSmrg ret = XNEW (struct simple_object_elf_attributes);
6701debfc3dSmrg ret->type_functions = eor->type_functions;
6711debfc3dSmrg ret->ei_data = eor->ei_data;
6721debfc3dSmrg ret->ei_class = eor->ei_class;
6731debfc3dSmrg ret->ei_osabi = eor->ei_osabi;
6741debfc3dSmrg ret->machine = eor->machine;
6751debfc3dSmrg ret->flags = eor->flags;
6761debfc3dSmrg return ret;
6771debfc3dSmrg }
6781debfc3dSmrg
6791debfc3dSmrg /* Release the privata data for an simple_object_read. */
6801debfc3dSmrg
6811debfc3dSmrg static void
simple_object_elf_release_read(void * data)6821debfc3dSmrg simple_object_elf_release_read (void *data)
6831debfc3dSmrg {
6841debfc3dSmrg XDELETE (data);
6851debfc3dSmrg }
6861debfc3dSmrg
6871debfc3dSmrg /* Compare two attributes structures. */
6881debfc3dSmrg
6891debfc3dSmrg static const char *
simple_object_elf_attributes_merge(void * todata,void * fromdata,int * err)6901debfc3dSmrg simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
6911debfc3dSmrg {
6921debfc3dSmrg struct simple_object_elf_attributes *to =
6931debfc3dSmrg (struct simple_object_elf_attributes *) todata;
6941debfc3dSmrg struct simple_object_elf_attributes *from =
6951debfc3dSmrg (struct simple_object_elf_attributes *) fromdata;
6961debfc3dSmrg
6971debfc3dSmrg if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
6981debfc3dSmrg {
6991debfc3dSmrg *err = 0;
7001debfc3dSmrg return "ELF object format mismatch";
7011debfc3dSmrg }
7021debfc3dSmrg
7031debfc3dSmrg if (to->machine != from->machine)
7041debfc3dSmrg {
7051debfc3dSmrg int ok;
7061debfc3dSmrg
7071debfc3dSmrg /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
7081debfc3dSmrg output of EM_SPARC32PLUS. */
7091debfc3dSmrg ok = 0;
7101debfc3dSmrg switch (to->machine)
7111debfc3dSmrg {
7121debfc3dSmrg case EM_SPARC:
7131debfc3dSmrg if (from->machine == EM_SPARC32PLUS)
7141debfc3dSmrg {
7151debfc3dSmrg to->machine = from->machine;
7161debfc3dSmrg ok = 1;
7171debfc3dSmrg }
7181debfc3dSmrg break;
7191debfc3dSmrg
7201debfc3dSmrg case EM_SPARC32PLUS:
7211debfc3dSmrg if (from->machine == EM_SPARC)
7221debfc3dSmrg ok = 1;
7231debfc3dSmrg break;
7241debfc3dSmrg
7251debfc3dSmrg default:
7261debfc3dSmrg break;
7271debfc3dSmrg }
7281debfc3dSmrg
7291debfc3dSmrg if (!ok)
7301debfc3dSmrg {
7311debfc3dSmrg *err = 0;
7321debfc3dSmrg return "ELF machine number mismatch";
7331debfc3dSmrg }
7341debfc3dSmrg }
7351debfc3dSmrg
7361debfc3dSmrg return NULL;
7371debfc3dSmrg }
7381debfc3dSmrg
7391debfc3dSmrg /* Release the private data for an attributes structure. */
7401debfc3dSmrg
7411debfc3dSmrg static void
simple_object_elf_release_attributes(void * data)7421debfc3dSmrg simple_object_elf_release_attributes (void *data)
7431debfc3dSmrg {
7441debfc3dSmrg XDELETE (data);
7451debfc3dSmrg }
7461debfc3dSmrg
7471debfc3dSmrg /* Prepare to write out a file. */
7481debfc3dSmrg
7491debfc3dSmrg static void *
simple_object_elf_start_write(void * attributes_data,const char ** errmsg ATTRIBUTE_UNUSED,int * err ATTRIBUTE_UNUSED)7501debfc3dSmrg simple_object_elf_start_write (void *attributes_data,
7511debfc3dSmrg const char **errmsg ATTRIBUTE_UNUSED,
7521debfc3dSmrg int *err ATTRIBUTE_UNUSED)
7531debfc3dSmrg {
7541debfc3dSmrg struct simple_object_elf_attributes *attrs =
7551debfc3dSmrg (struct simple_object_elf_attributes *) attributes_data;
756a2dc1f3fSmrg struct simple_object_elf_write *ret;
7571debfc3dSmrg
7581debfc3dSmrg /* We're just going to record the attributes, but we need to make a
7591debfc3dSmrg copy because the user may delete them. */
760a2dc1f3fSmrg ret = XNEW (struct simple_object_elf_write);
761a2dc1f3fSmrg ret->attrs = *attrs;
762a2dc1f3fSmrg ret->shdrs = NULL;
7631debfc3dSmrg return ret;
7641debfc3dSmrg }
7651debfc3dSmrg
7661debfc3dSmrg /* Write out an ELF ehdr. */
7671debfc3dSmrg
7681debfc3dSmrg static int
simple_object_elf_write_ehdr(simple_object_write * sobj,int descriptor,const char ** errmsg,int * err)7691debfc3dSmrg simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
7701debfc3dSmrg const char **errmsg, int *err)
7711debfc3dSmrg {
7721debfc3dSmrg struct simple_object_elf_attributes *attrs =
7731debfc3dSmrg (struct simple_object_elf_attributes *) sobj->data;
7741debfc3dSmrg const struct elf_type_functions* fns;
7751debfc3dSmrg unsigned char cl;
7761debfc3dSmrg size_t ehdr_size;
7771debfc3dSmrg unsigned char buf[sizeof (Elf64_External_Ehdr)];
7781debfc3dSmrg simple_object_write_section *section;
7791debfc3dSmrg unsigned int shnum;
7801debfc3dSmrg unsigned int shstrndx;
7811debfc3dSmrg
7821debfc3dSmrg fns = attrs->type_functions;
7831debfc3dSmrg cl = attrs->ei_class;
7841debfc3dSmrg
7851debfc3dSmrg shnum = 0;
7861debfc3dSmrg for (section = sobj->sections; section != NULL; section = section->next)
7871debfc3dSmrg ++shnum;
7881debfc3dSmrg if (shnum > 0)
7891debfc3dSmrg {
7901debfc3dSmrg /* Add a section header for the dummy section and one for
7911debfc3dSmrg .shstrtab. */
7921debfc3dSmrg shnum += 2;
7931debfc3dSmrg }
7941debfc3dSmrg
7951debfc3dSmrg ehdr_size = (cl == ELFCLASS32
7961debfc3dSmrg ? sizeof (Elf32_External_Ehdr)
7971debfc3dSmrg : sizeof (Elf64_External_Ehdr));
7981debfc3dSmrg memset (buf, 0, sizeof (Elf64_External_Ehdr));
7991debfc3dSmrg
8001debfc3dSmrg buf[EI_MAG0] = ELFMAG0;
8011debfc3dSmrg buf[EI_MAG1] = ELFMAG1;
8021debfc3dSmrg buf[EI_MAG2] = ELFMAG2;
8031debfc3dSmrg buf[EI_MAG3] = ELFMAG3;
8041debfc3dSmrg buf[EI_CLASS] = cl;
8051debfc3dSmrg buf[EI_DATA] = attrs->ei_data;
8061debfc3dSmrg buf[EI_VERSION] = EV_CURRENT;
8071debfc3dSmrg buf[EI_OSABI] = attrs->ei_osabi;
8081debfc3dSmrg
8091debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
8101debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
8111debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
8121debfc3dSmrg /* e_entry left as zero. */
8131debfc3dSmrg /* e_phoff left as zero. */
8141debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
8151debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
8161debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
8171debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
8181debfc3dSmrg (cl == ELFCLASS32
8191debfc3dSmrg ? sizeof (Elf32_External_Phdr)
8201debfc3dSmrg : sizeof (Elf64_External_Phdr)));
8211debfc3dSmrg /* e_phnum left as zero. */
8221debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
8231debfc3dSmrg (cl == ELFCLASS32
8241debfc3dSmrg ? sizeof (Elf32_External_Shdr)
8251debfc3dSmrg : sizeof (Elf64_External_Shdr)));
8261debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half,
8271debfc3dSmrg shnum >= SHN_LORESERVE ? 0 : shnum);
8281debfc3dSmrg if (shnum == 0)
8291debfc3dSmrg shstrndx = 0;
8301debfc3dSmrg else
8311debfc3dSmrg {
8321debfc3dSmrg shstrndx = shnum - 1;
8331debfc3dSmrg if (shstrndx >= SHN_LORESERVE)
8341debfc3dSmrg shstrndx = SHN_XINDEX;
8351debfc3dSmrg }
8361debfc3dSmrg ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half, shstrndx);
8371debfc3dSmrg
8381debfc3dSmrg return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
8391debfc3dSmrg errmsg, err);
8401debfc3dSmrg }
8411debfc3dSmrg
8421debfc3dSmrg /* Write out an ELF shdr. */
8431debfc3dSmrg
8441debfc3dSmrg static int
simple_object_elf_write_shdr(simple_object_write * sobj,int descriptor,off_t offset,unsigned int sh_name,unsigned int sh_type,unsigned int sh_flags,off_t sh_addr,unsigned int sh_offset,unsigned int sh_size,unsigned int sh_link,unsigned int sh_info,size_t sh_addralign,size_t sh_entsize,const char ** errmsg,int * err)8451debfc3dSmrg simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
8461debfc3dSmrg off_t offset, unsigned int sh_name,
8471debfc3dSmrg unsigned int sh_type, unsigned int sh_flags,
848a2dc1f3fSmrg off_t sh_addr,
8491debfc3dSmrg unsigned int sh_offset, unsigned int sh_size,
850a2dc1f3fSmrg unsigned int sh_link, unsigned int sh_info,
851a2dc1f3fSmrg size_t sh_addralign,
852a2dc1f3fSmrg size_t sh_entsize,
8531debfc3dSmrg const char **errmsg, int *err)
8541debfc3dSmrg {
8551debfc3dSmrg struct simple_object_elf_attributes *attrs =
8561debfc3dSmrg (struct simple_object_elf_attributes *) sobj->data;
8571debfc3dSmrg const struct elf_type_functions* fns;
8581debfc3dSmrg unsigned char cl;
8591debfc3dSmrg size_t shdr_size;
8601debfc3dSmrg unsigned char buf[sizeof (Elf64_External_Shdr)];
8611debfc3dSmrg
8621debfc3dSmrg fns = attrs->type_functions;
8631debfc3dSmrg cl = attrs->ei_class;
8641debfc3dSmrg
8651debfc3dSmrg shdr_size = (cl == ELFCLASS32
8661debfc3dSmrg ? sizeof (Elf32_External_Shdr)
8671debfc3dSmrg : sizeof (Elf64_External_Shdr));
8681debfc3dSmrg memset (buf, 0, sizeof (Elf64_External_Shdr));
8691debfc3dSmrg
8701debfc3dSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
8711debfc3dSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
8721debfc3dSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
873a2dc1f3fSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addr, Elf_Addr, sh_addr);
8741debfc3dSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
8751debfc3dSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
8761debfc3dSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
877a2dc1f3fSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_info, Elf_Word, sh_info);
8781debfc3dSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
879a2dc1f3fSmrg ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Addr, sh_entsize);
8801debfc3dSmrg
8811debfc3dSmrg return simple_object_internal_write (descriptor, offset, buf, shdr_size,
8821debfc3dSmrg errmsg, err);
8831debfc3dSmrg }
8841debfc3dSmrg
8851debfc3dSmrg /* Write out a complete ELF file.
8861debfc3dSmrg Ehdr
8871debfc3dSmrg initial dummy Shdr
8881debfc3dSmrg user-created Shdrs
8891debfc3dSmrg .shstrtab Shdr
8901debfc3dSmrg user-created section data
8911debfc3dSmrg .shstrtab data */
8921debfc3dSmrg
8931debfc3dSmrg static const char *
simple_object_elf_write_to_file(simple_object_write * sobj,int descriptor,int * err)8941debfc3dSmrg simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
8951debfc3dSmrg int *err)
8961debfc3dSmrg {
897a2dc1f3fSmrg struct simple_object_elf_write *eow =
898a2dc1f3fSmrg (struct simple_object_elf_write *) sobj->data;
899a2dc1f3fSmrg struct simple_object_elf_attributes *attrs = &eow->attrs;
9001debfc3dSmrg unsigned char cl;
9011debfc3dSmrg size_t ehdr_size;
9021debfc3dSmrg size_t shdr_size;
9031debfc3dSmrg const char *errmsg;
9041debfc3dSmrg simple_object_write_section *section;
9051debfc3dSmrg unsigned int shnum;
9061debfc3dSmrg size_t shdr_offset;
9071debfc3dSmrg size_t sh_offset;
9081debfc3dSmrg unsigned int first_sh_size;
9091debfc3dSmrg unsigned int first_sh_link;
9101debfc3dSmrg size_t sh_name;
9111debfc3dSmrg unsigned char zero;
912a2dc1f3fSmrg unsigned secnum;
9131debfc3dSmrg
9141debfc3dSmrg if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
9151debfc3dSmrg return errmsg;
9161debfc3dSmrg
9171debfc3dSmrg cl = attrs->ei_class;
9181debfc3dSmrg if (cl == ELFCLASS32)
9191debfc3dSmrg {
9201debfc3dSmrg ehdr_size = sizeof (Elf32_External_Ehdr);
9211debfc3dSmrg shdr_size = sizeof (Elf32_External_Shdr);
9221debfc3dSmrg }
9231debfc3dSmrg else
9241debfc3dSmrg {
9251debfc3dSmrg ehdr_size = sizeof (Elf64_External_Ehdr);
9261debfc3dSmrg shdr_size = sizeof (Elf64_External_Shdr);
9271debfc3dSmrg }
9281debfc3dSmrg
9291debfc3dSmrg shnum = 0;
9301debfc3dSmrg for (section = sobj->sections; section != NULL; section = section->next)
9311debfc3dSmrg ++shnum;
9321debfc3dSmrg if (shnum == 0)
9331debfc3dSmrg return NULL;
9341debfc3dSmrg
9351debfc3dSmrg /* Add initial dummy Shdr and .shstrtab. */
9361debfc3dSmrg shnum += 2;
9371debfc3dSmrg
9381debfc3dSmrg shdr_offset = ehdr_size;
9391debfc3dSmrg sh_offset = shdr_offset + shnum * shdr_size;
9401debfc3dSmrg
9411debfc3dSmrg if (shnum < SHN_LORESERVE)
9421debfc3dSmrg first_sh_size = 0;
9431debfc3dSmrg else
9441debfc3dSmrg first_sh_size = shnum;
9451debfc3dSmrg if (shnum - 1 < SHN_LORESERVE)
9461debfc3dSmrg first_sh_link = 0;
9471debfc3dSmrg else
9481debfc3dSmrg first_sh_link = shnum - 1;
9491debfc3dSmrg if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
950a2dc1f3fSmrg 0, 0, 0, 0, 0, first_sh_size, first_sh_link,
951a2dc1f3fSmrg 0, 0, 0, &errmsg, err))
9521debfc3dSmrg return errmsg;
9531debfc3dSmrg
9541debfc3dSmrg shdr_offset += shdr_size;
9551debfc3dSmrg
9561debfc3dSmrg sh_name = 1;
957a2dc1f3fSmrg secnum = 0;
9581debfc3dSmrg for (section = sobj->sections; section != NULL; section = section->next)
9591debfc3dSmrg {
9601debfc3dSmrg size_t mask;
9611debfc3dSmrg size_t new_sh_offset;
9621debfc3dSmrg size_t sh_size;
9631debfc3dSmrg struct simple_object_write_section_buffer *buffer;
964a2dc1f3fSmrg unsigned int sh_type = SHT_PROGBITS;
965a2dc1f3fSmrg unsigned int sh_flags = 0;
966a2dc1f3fSmrg off_t sh_addr = 0;
967a2dc1f3fSmrg unsigned int sh_link = 0;
968a2dc1f3fSmrg unsigned int sh_info = 0;
969a2dc1f3fSmrg size_t sh_addralign = 1U << section->align;
970a2dc1f3fSmrg size_t sh_entsize = 0;
971a2dc1f3fSmrg if (eow->shdrs)
972a2dc1f3fSmrg {
973a2dc1f3fSmrg sh_type = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
974a2dc1f3fSmrg eow->shdrs + secnum * shdr_size,
975a2dc1f3fSmrg sh_type, Elf_Word);
976a2dc1f3fSmrg sh_flags = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
977a2dc1f3fSmrg eow->shdrs + secnum * shdr_size,
978a2dc1f3fSmrg sh_flags, Elf_Addr);
979a2dc1f3fSmrg sh_addr = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
980a2dc1f3fSmrg eow->shdrs + secnum * shdr_size,
981a2dc1f3fSmrg sh_addr, Elf_Addr);
982a2dc1f3fSmrg sh_link = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
983a2dc1f3fSmrg eow->shdrs + secnum * shdr_size,
984a2dc1f3fSmrg sh_link, Elf_Word);
985a2dc1f3fSmrg sh_info = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
986a2dc1f3fSmrg eow->shdrs + secnum * shdr_size,
987a2dc1f3fSmrg sh_info, Elf_Word);
988a2dc1f3fSmrg sh_addralign = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
989a2dc1f3fSmrg eow->shdrs + secnum * shdr_size,
990a2dc1f3fSmrg sh_addralign, Elf_Addr);
991a2dc1f3fSmrg sh_entsize = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
992a2dc1f3fSmrg eow->shdrs + secnum * shdr_size,
993a2dc1f3fSmrg sh_entsize, Elf_Addr);
994a2dc1f3fSmrg secnum++;
995a2dc1f3fSmrg }
9961debfc3dSmrg
997a2dc1f3fSmrg mask = sh_addralign - 1;
9981debfc3dSmrg new_sh_offset = sh_offset + mask;
9991debfc3dSmrg new_sh_offset &= ~ mask;
10001debfc3dSmrg while (new_sh_offset > sh_offset)
10011debfc3dSmrg {
10021debfc3dSmrg unsigned char zeroes[16];
10031debfc3dSmrg size_t write;
10041debfc3dSmrg
10051debfc3dSmrg memset (zeroes, 0, sizeof zeroes);
10061debfc3dSmrg write = new_sh_offset - sh_offset;
10071debfc3dSmrg if (write > sizeof zeroes)
10081debfc3dSmrg write = sizeof zeroes;
10091debfc3dSmrg if (!simple_object_internal_write (descriptor, sh_offset, zeroes,
10101debfc3dSmrg write, &errmsg, err))
10111debfc3dSmrg return errmsg;
10121debfc3dSmrg sh_offset += write;
10131debfc3dSmrg }
10141debfc3dSmrg
10151debfc3dSmrg sh_size = 0;
10161debfc3dSmrg for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
10171debfc3dSmrg {
10181debfc3dSmrg if (!simple_object_internal_write (descriptor, sh_offset + sh_size,
10191debfc3dSmrg ((const unsigned char *)
10201debfc3dSmrg buffer->buffer),
10211debfc3dSmrg buffer->size, &errmsg, err))
10221debfc3dSmrg return errmsg;
10231debfc3dSmrg sh_size += buffer->size;
10241debfc3dSmrg }
10251debfc3dSmrg
10261debfc3dSmrg if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
1027a2dc1f3fSmrg sh_name, sh_type, sh_flags,
1028a2dc1f3fSmrg sh_addr, sh_offset,
1029a2dc1f3fSmrg sh_size, sh_link, sh_info,
1030a2dc1f3fSmrg sh_addralign, sh_entsize,
10311debfc3dSmrg &errmsg, err))
10321debfc3dSmrg return errmsg;
10331debfc3dSmrg
10341debfc3dSmrg shdr_offset += shdr_size;
10351debfc3dSmrg sh_name += strlen (section->name) + 1;
10361debfc3dSmrg sh_offset += sh_size;
10371debfc3dSmrg }
10381debfc3dSmrg
10391debfc3dSmrg if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
1040a2dc1f3fSmrg sh_name, SHT_STRTAB, 0, 0, sh_offset,
1041a2dc1f3fSmrg sh_name + strlen (".shstrtab") + 1, 0, 0,
1042a2dc1f3fSmrg 1, 0, &errmsg, err))
10431debfc3dSmrg return errmsg;
10441debfc3dSmrg
10451debfc3dSmrg /* .shstrtab has a leading zero byte. */
10461debfc3dSmrg zero = 0;
10471debfc3dSmrg if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
10481debfc3dSmrg &errmsg, err))
10491debfc3dSmrg return errmsg;
10501debfc3dSmrg ++sh_offset;
10511debfc3dSmrg
10521debfc3dSmrg for (section = sobj->sections; section != NULL; section = section->next)
10531debfc3dSmrg {
10541debfc3dSmrg size_t len;
10551debfc3dSmrg
10561debfc3dSmrg len = strlen (section->name) + 1;
10571debfc3dSmrg if (!simple_object_internal_write (descriptor, sh_offset,
10581debfc3dSmrg (const unsigned char *) section->name,
10591debfc3dSmrg len, &errmsg, err))
10601debfc3dSmrg return errmsg;
10611debfc3dSmrg sh_offset += len;
10621debfc3dSmrg }
10631debfc3dSmrg
10641debfc3dSmrg if (!simple_object_internal_write (descriptor, sh_offset,
10651debfc3dSmrg (const unsigned char *) ".shstrtab",
10661debfc3dSmrg strlen (".shstrtab") + 1, &errmsg, err))
10671debfc3dSmrg return errmsg;
10681debfc3dSmrg
10691debfc3dSmrg return NULL;
10701debfc3dSmrg }
10711debfc3dSmrg
10721debfc3dSmrg /* Release the private data for an simple_object_write structure. */
10731debfc3dSmrg
10741debfc3dSmrg static void
simple_object_elf_release_write(void * data)10751debfc3dSmrg simple_object_elf_release_write (void *data)
10761debfc3dSmrg {
1077a2dc1f3fSmrg struct simple_object_elf_write *eow = (struct simple_object_elf_write *) data;
1078a2dc1f3fSmrg if (eow->shdrs)
1079a2dc1f3fSmrg XDELETE (eow->shdrs);
10801debfc3dSmrg XDELETE (data);
10811debfc3dSmrg }
10821debfc3dSmrg
1083a2dc1f3fSmrg /* Copy all sections in an ELF file. */
1084a2dc1f3fSmrg
1085a2dc1f3fSmrg static const char *
simple_object_elf_copy_lto_debug_sections(simple_object_read * sobj,simple_object_write * dobj,char * (* pfn)(const char *),int * err)1086a2dc1f3fSmrg simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
1087a2dc1f3fSmrg simple_object_write *dobj,
1088a2dc1f3fSmrg char *(*pfn) (const char *),
1089a2dc1f3fSmrg int *err)
1090a2dc1f3fSmrg {
1091a2dc1f3fSmrg struct simple_object_elf_read *eor =
1092a2dc1f3fSmrg (struct simple_object_elf_read *) sobj->data;
1093a2dc1f3fSmrg const struct elf_type_functions *type_functions = eor->type_functions;
1094a2dc1f3fSmrg struct simple_object_elf_write *eow =
1095a2dc1f3fSmrg (struct simple_object_elf_write *) dobj->data;
1096a2dc1f3fSmrg unsigned char ei_class = eor->ei_class;
1097a2dc1f3fSmrg size_t shdr_size;
1098a2dc1f3fSmrg unsigned int shnum;
1099a2dc1f3fSmrg unsigned char *shdrs;
1100a2dc1f3fSmrg const char *errmsg;
1101a2dc1f3fSmrg unsigned char *shstrhdr;
1102a2dc1f3fSmrg size_t name_size;
1103a2dc1f3fSmrg off_t shstroff;
1104a2dc1f3fSmrg unsigned char *names;
1105a2dc1f3fSmrg unsigned int i;
1106a2dc1f3fSmrg int changed;
1107a2dc1f3fSmrg int *pfnret;
1108a2dc1f3fSmrg const char **pfnname;
1109a2dc1f3fSmrg unsigned new_i;
1110a2dc1f3fSmrg unsigned *sh_map;
1111a2dc1f3fSmrg unsigned first_shndx = 0;
1112a2dc1f3fSmrg unsigned int *symtab_indices_shndx;
1113a2dc1f3fSmrg
1114a2dc1f3fSmrg shdr_size = (ei_class == ELFCLASS32
1115a2dc1f3fSmrg ? sizeof (Elf32_External_Shdr)
1116a2dc1f3fSmrg : sizeof (Elf64_External_Shdr));
1117a2dc1f3fSmrg
1118a2dc1f3fSmrg /* Read the section headers. We skip section 0, which is not a
1119a2dc1f3fSmrg useful section. */
1120a2dc1f3fSmrg
1121a2dc1f3fSmrg shnum = eor->shnum;
1122a2dc1f3fSmrg shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
1123a2dc1f3fSmrg
1124a2dc1f3fSmrg if (!simple_object_internal_read (sobj->descriptor,
1125a2dc1f3fSmrg sobj->offset + eor->shoff + shdr_size,
1126a2dc1f3fSmrg shdrs,
1127a2dc1f3fSmrg shdr_size * (shnum - 1),
1128a2dc1f3fSmrg &errmsg, err))
1129a2dc1f3fSmrg {
1130a2dc1f3fSmrg XDELETEVEC (shdrs);
1131a2dc1f3fSmrg return errmsg;
1132a2dc1f3fSmrg }
1133a2dc1f3fSmrg
1134a2dc1f3fSmrg /* Read the section names. */
1135a2dc1f3fSmrg
1136a2dc1f3fSmrg shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
1137a2dc1f3fSmrg name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1138a2dc1f3fSmrg shstrhdr, sh_size, Elf_Addr);
1139a2dc1f3fSmrg shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1140a2dc1f3fSmrg shstrhdr, sh_offset, Elf_Addr);
1141a2dc1f3fSmrg names = XNEWVEC (unsigned char, name_size);
1142a2dc1f3fSmrg if (!simple_object_internal_read (sobj->descriptor,
1143a2dc1f3fSmrg sobj->offset + shstroff,
1144a2dc1f3fSmrg names, name_size, &errmsg, err))
1145a2dc1f3fSmrg {
1146a2dc1f3fSmrg XDELETEVEC (names);
1147a2dc1f3fSmrg XDELETEVEC (shdrs);
1148a2dc1f3fSmrg return errmsg;
1149a2dc1f3fSmrg }
1150a2dc1f3fSmrg
1151a2dc1f3fSmrg pfnret = XNEWVEC (int, shnum);
1152a2dc1f3fSmrg pfnname = XNEWVEC (const char *, shnum);
1153a2dc1f3fSmrg
1154a2dc1f3fSmrg /* Map of symtab to index section. */
1155a2dc1f3fSmrg symtab_indices_shndx = XCNEWVEC (unsigned int, shnum - 1);
1156a2dc1f3fSmrg
1157a2dc1f3fSmrg /* First perform the callbacks to know which sections to preserve and
1158a2dc1f3fSmrg what name to use for those. */
1159a2dc1f3fSmrg for (i = 1; i < shnum; ++i)
1160a2dc1f3fSmrg {
1161a2dc1f3fSmrg unsigned char *shdr;
1162a2dc1f3fSmrg unsigned int sh_name, sh_type;
1163a2dc1f3fSmrg const char *name;
1164a2dc1f3fSmrg char *ret;
1165a2dc1f3fSmrg
1166a2dc1f3fSmrg shdr = shdrs + (i - 1) * shdr_size;
1167a2dc1f3fSmrg sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1168a2dc1f3fSmrg shdr, sh_name, Elf_Word);
1169a2dc1f3fSmrg if (sh_name >= name_size)
1170a2dc1f3fSmrg {
1171a2dc1f3fSmrg *err = 0;
1172a2dc1f3fSmrg XDELETEVEC (names);
1173a2dc1f3fSmrg XDELETEVEC (shdrs);
1174a2dc1f3fSmrg return "ELF section name out of range";
1175a2dc1f3fSmrg }
1176a2dc1f3fSmrg
1177a2dc1f3fSmrg name = (const char *) names + sh_name;
1178a2dc1f3fSmrg
1179a2dc1f3fSmrg ret = (*pfn) (name);
1180a2dc1f3fSmrg pfnret[i - 1] = ret == NULL ? -1 : 0;
1181a2dc1f3fSmrg pfnname[i - 1] = ret == NULL ? name : ret;
1182a2dc1f3fSmrg if (first_shndx == 0
1183a2dc1f3fSmrg && pfnret[i - 1] == 0)
1184a2dc1f3fSmrg first_shndx = i;
1185a2dc1f3fSmrg
1186a2dc1f3fSmrg /* Remember the indexes of existing SHT_SYMTAB_SHNDX sections. */
1187a2dc1f3fSmrg sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1188a2dc1f3fSmrg shdr, sh_type, Elf_Word);
1189a2dc1f3fSmrg if (sh_type == SHT_SYMTAB_SHNDX)
1190a2dc1f3fSmrg {
1191a2dc1f3fSmrg unsigned int sh_link;
1192a2dc1f3fSmrg sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1193a2dc1f3fSmrg shdr, sh_link, Elf_Word);
1194*8feb0f0bSmrg symtab_indices_shndx[sh_link - 1] = i - 1;
1195a2dc1f3fSmrg /* Always discard the extended index sections, after
1196a2dc1f3fSmrg copying it will not be needed. This way we don't need to
1197a2dc1f3fSmrg update it and deal with the ordering constraints of
1198a2dc1f3fSmrg processing the existing symtab and changing the index. */
1199a2dc1f3fSmrg pfnret[i - 1] = -1;
1200a2dc1f3fSmrg }
1201a2dc1f3fSmrg }
1202a2dc1f3fSmrg
1203a2dc1f3fSmrg /* Mark sections as preserved that are required by to be preserved
1204a2dc1f3fSmrg sections. */
1205a2dc1f3fSmrg do
1206a2dc1f3fSmrg {
1207a2dc1f3fSmrg changed = 0;
1208a2dc1f3fSmrg for (i = 1; i < shnum; ++i)
1209a2dc1f3fSmrg {
1210a2dc1f3fSmrg unsigned char *shdr;
1211a2dc1f3fSmrg unsigned int sh_type, sh_info, sh_link;
1212a2dc1f3fSmrg off_t offset;
1213a2dc1f3fSmrg off_t length;
1214a2dc1f3fSmrg
1215a2dc1f3fSmrg shdr = shdrs + (i - 1) * shdr_size;
1216a2dc1f3fSmrg sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1217a2dc1f3fSmrg shdr, sh_type, Elf_Word);
1218a2dc1f3fSmrg sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1219a2dc1f3fSmrg shdr, sh_info, Elf_Word);
1220a2dc1f3fSmrg sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1221a2dc1f3fSmrg shdr, sh_link, Elf_Word);
1222a2dc1f3fSmrg if (sh_type == SHT_GROUP)
1223a2dc1f3fSmrg {
1224a2dc1f3fSmrg /* Mark groups containing copied sections. */
1225a2dc1f3fSmrg unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class,
1226a2dc1f3fSmrg Shdr, shdr, sh_entsize,
1227a2dc1f3fSmrg Elf_Addr);
1228a2dc1f3fSmrg unsigned char *ent, *buf;
1229a2dc1f3fSmrg int keep = 0;
1230a2dc1f3fSmrg offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1231a2dc1f3fSmrg shdr, sh_offset, Elf_Addr);
1232a2dc1f3fSmrg length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1233a2dc1f3fSmrg shdr, sh_size, Elf_Addr);
1234a2dc1f3fSmrg buf = XNEWVEC (unsigned char, length);
1235a2dc1f3fSmrg if (!simple_object_internal_read (sobj->descriptor,
1236a2dc1f3fSmrg sobj->offset + offset, buf,
1237a2dc1f3fSmrg (size_t) length, &errmsg, err))
1238a2dc1f3fSmrg {
1239a2dc1f3fSmrg XDELETEVEC (buf);
1240a2dc1f3fSmrg XDELETEVEC (names);
1241a2dc1f3fSmrg XDELETEVEC (shdrs);
1242a2dc1f3fSmrg return errmsg;
1243a2dc1f3fSmrg }
1244a2dc1f3fSmrg for (ent = buf + entsize; ent < buf + length; ent += entsize)
1245a2dc1f3fSmrg {
1246a2dc1f3fSmrg unsigned sec = type_functions->fetch_Elf_Word (ent);
1247a2dc1f3fSmrg if (pfnret[sec - 1] == 0)
1248a2dc1f3fSmrg keep = 1;
1249a2dc1f3fSmrg }
1250a2dc1f3fSmrg if (keep)
1251a2dc1f3fSmrg {
1252a2dc1f3fSmrg changed |= (pfnret[sh_link - 1] == -1
1253a2dc1f3fSmrg || pfnret[i - 1] == -1);
1254a2dc1f3fSmrg pfnret[sh_link - 1] = 0;
1255a2dc1f3fSmrg pfnret[i - 1] = 0;
1256a2dc1f3fSmrg }
1257a2dc1f3fSmrg }
1258a2dc1f3fSmrg if (sh_type == SHT_RELA
1259a2dc1f3fSmrg || sh_type == SHT_REL)
1260a2dc1f3fSmrg {
1261a2dc1f3fSmrg /* Mark relocation sections and symtab of copied sections. */
1262a2dc1f3fSmrg if (pfnret[sh_info - 1] == 0)
1263a2dc1f3fSmrg {
1264a2dc1f3fSmrg changed |= (pfnret[sh_link - 1] == -1
1265a2dc1f3fSmrg || pfnret[i - 1] == -1);
1266a2dc1f3fSmrg pfnret[sh_link - 1] = 0;
1267a2dc1f3fSmrg pfnret[i - 1] = 0;
1268a2dc1f3fSmrg }
1269a2dc1f3fSmrg }
1270a2dc1f3fSmrg if (sh_type == SHT_SYMTAB)
1271a2dc1f3fSmrg {
1272a2dc1f3fSmrg /* Mark strings sections of copied symtabs. */
1273a2dc1f3fSmrg if (pfnret[i - 1] == 0)
1274a2dc1f3fSmrg {
1275a2dc1f3fSmrg changed |= pfnret[sh_link - 1] == -1;
1276a2dc1f3fSmrg pfnret[sh_link - 1] = 0;
1277a2dc1f3fSmrg }
1278a2dc1f3fSmrg }
1279a2dc1f3fSmrg }
1280a2dc1f3fSmrg }
1281a2dc1f3fSmrg while (changed);
1282a2dc1f3fSmrg
1283a2dc1f3fSmrg /* Compute a mapping of old -> new section numbers. */
1284a2dc1f3fSmrg sh_map = XNEWVEC (unsigned, shnum);
1285a2dc1f3fSmrg sh_map[0] = 0;
1286a2dc1f3fSmrg new_i = 1;
1287a2dc1f3fSmrg for (i = 1; i < shnum; ++i)
1288a2dc1f3fSmrg {
1289a2dc1f3fSmrg if (pfnret[i - 1] == -1)
1290a2dc1f3fSmrg sh_map[i] = 0;
1291a2dc1f3fSmrg else
1292a2dc1f3fSmrg sh_map[i] = new_i++;
1293a2dc1f3fSmrg }
1294a2dc1f3fSmrg if (new_i - 1 >= SHN_LORESERVE)
1295a2dc1f3fSmrg {
1296a2dc1f3fSmrg *err = ENOTSUP;
1297a2dc1f3fSmrg return "Too many copied sections";
1298a2dc1f3fSmrg }
1299a2dc1f3fSmrg eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_i - 1));
1300a2dc1f3fSmrg
1301a2dc1f3fSmrg /* Then perform the actual copying. */
1302a2dc1f3fSmrg new_i = 0;
1303a2dc1f3fSmrg for (i = 1; i < shnum; ++i)
1304a2dc1f3fSmrg {
1305a2dc1f3fSmrg unsigned char *shdr;
1306a2dc1f3fSmrg unsigned int sh_name, sh_type;
1307a2dc1f3fSmrg const char *name;
1308a2dc1f3fSmrg off_t offset;
1309a2dc1f3fSmrg off_t length;
1310a2dc1f3fSmrg simple_object_write_section *dest;
1311a2dc1f3fSmrg off_t flags;
1312a2dc1f3fSmrg unsigned char *buf;
1313a2dc1f3fSmrg
1314a2dc1f3fSmrg if (pfnret[i - 1])
1315a2dc1f3fSmrg continue;
1316a2dc1f3fSmrg
1317a2dc1f3fSmrg new_i++;
1318a2dc1f3fSmrg shdr = shdrs + (i - 1) * shdr_size;
1319a2dc1f3fSmrg sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1320a2dc1f3fSmrg shdr, sh_name, Elf_Word);
1321a2dc1f3fSmrg if (sh_name >= name_size)
1322a2dc1f3fSmrg {
1323a2dc1f3fSmrg *err = 0;
1324a2dc1f3fSmrg XDELETEVEC (names);
1325a2dc1f3fSmrg XDELETEVEC (shdrs);
1326a2dc1f3fSmrg XDELETEVEC (symtab_indices_shndx);
1327a2dc1f3fSmrg return "ELF section name out of range";
1328a2dc1f3fSmrg }
1329a2dc1f3fSmrg
1330a2dc1f3fSmrg name = pfnname[i - 1];
1331a2dc1f3fSmrg offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1332a2dc1f3fSmrg shdr, sh_offset, Elf_Addr);
1333a2dc1f3fSmrg length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1334a2dc1f3fSmrg shdr, sh_size, Elf_Addr);
1335a2dc1f3fSmrg sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1336a2dc1f3fSmrg shdr, sh_type, Elf_Word);
1337a2dc1f3fSmrg
1338a2dc1f3fSmrg dest = simple_object_write_create_section (dobj, pfnname[i - 1],
1339a2dc1f3fSmrg 0, &errmsg, err);
1340a2dc1f3fSmrg if (dest == NULL)
1341a2dc1f3fSmrg {
1342a2dc1f3fSmrg XDELETEVEC (names);
1343a2dc1f3fSmrg XDELETEVEC (shdrs);
1344a2dc1f3fSmrg XDELETEVEC (symtab_indices_shndx);
1345a2dc1f3fSmrg return errmsg;
1346a2dc1f3fSmrg }
1347a2dc1f3fSmrg
1348a2dc1f3fSmrg /* Record the SHDR of the source. */
1349a2dc1f3fSmrg memcpy (eow->shdrs + (new_i - 1) * shdr_size, shdr, shdr_size);
1350a2dc1f3fSmrg shdr = eow->shdrs + (new_i - 1) * shdr_size;
1351a2dc1f3fSmrg
1352a2dc1f3fSmrg /* Copy the data.
1353a2dc1f3fSmrg ??? This is quite wasteful and ideally would be delayed until
1354a2dc1f3fSmrg write_to_file (). Thus it questions the interfacing
1355a2dc1f3fSmrg which eventually should contain destination creation plus
1356a2dc1f3fSmrg writing. */
1357a2dc1f3fSmrg buf = XNEWVEC (unsigned char, length);
1358a2dc1f3fSmrg if (!simple_object_internal_read (sobj->descriptor,
1359a2dc1f3fSmrg sobj->offset + offset, buf,
1360a2dc1f3fSmrg (size_t) length, &errmsg, err))
1361a2dc1f3fSmrg {
1362a2dc1f3fSmrg XDELETEVEC (buf);
1363a2dc1f3fSmrg XDELETEVEC (names);
1364a2dc1f3fSmrg XDELETEVEC (shdrs);
1365a2dc1f3fSmrg XDELETEVEC (symtab_indices_shndx);
1366a2dc1f3fSmrg return errmsg;
1367a2dc1f3fSmrg }
1368a2dc1f3fSmrg
1369*8feb0f0bSmrg /* If we are processing .symtab purge any symbols
1370*8feb0f0bSmrg in discarded sections. */
1371a2dc1f3fSmrg if (sh_type == SHT_SYMTAB)
1372a2dc1f3fSmrg {
1373a2dc1f3fSmrg unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1374a2dc1f3fSmrg shdr, sh_entsize, Elf_Addr);
1375*8feb0f0bSmrg size_t prevailing_name_idx = 0;
1376a2dc1f3fSmrg unsigned char *ent;
1377a2dc1f3fSmrg unsigned *shndx_table = NULL;
1378a2dc1f3fSmrg /* Read the section index table if present. */
1379a2dc1f3fSmrg if (symtab_indices_shndx[i - 1] != 0)
1380a2dc1f3fSmrg {
1381*8feb0f0bSmrg unsigned char *sidxhdr = shdrs + symtab_indices_shndx[i - 1] * shdr_size;
1382a2dc1f3fSmrg off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1383a2dc1f3fSmrg sidxhdr, sh_offset, Elf_Addr);
1384a2dc1f3fSmrg size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1385a2dc1f3fSmrg sidxhdr, sh_size, Elf_Addr);
1386*8feb0f0bSmrg unsigned int shndx_type
1387*8feb0f0bSmrg = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1388*8feb0f0bSmrg sidxhdr, sh_type, Elf_Word);
1389*8feb0f0bSmrg if (shndx_type != SHT_SYMTAB_SHNDX)
1390*8feb0f0bSmrg return "Wrong section type of a SYMTAB SECTION INDICES section";
1391a2dc1f3fSmrg shndx_table = (unsigned *)XNEWVEC (char, sidxsz);
1392a2dc1f3fSmrg simple_object_internal_read (sobj->descriptor,
1393a2dc1f3fSmrg sobj->offset + sidxoff,
1394a2dc1f3fSmrg (unsigned char *)shndx_table,
1395a2dc1f3fSmrg sidxsz, &errmsg, err);
1396a2dc1f3fSmrg }
1397*8feb0f0bSmrg
1398*8feb0f0bSmrg /* Find a WEAK HIDDEN symbol which name we will use for removed
1399*8feb0f0bSmrg symbols. We know there's a prevailing weak hidden symbol
1400*8feb0f0bSmrg at the start of the .debug_info section. */
1401*8feb0f0bSmrg for (ent = buf; ent < buf + length; ent += entsize)
1402*8feb0f0bSmrg {
1403*8feb0f0bSmrg unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
1404*8feb0f0bSmrg Sym, ent,
1405*8feb0f0bSmrg st_shndx, Elf_Half);
1406*8feb0f0bSmrg unsigned char *st_info;
1407*8feb0f0bSmrg unsigned char *st_other;
1408*8feb0f0bSmrg if (ei_class == ELFCLASS32)
1409*8feb0f0bSmrg {
1410*8feb0f0bSmrg st_info = &((Elf32_External_Sym *)ent)->st_info;
1411*8feb0f0bSmrg st_other = &((Elf32_External_Sym *)ent)->st_other;
1412*8feb0f0bSmrg }
1413*8feb0f0bSmrg else
1414*8feb0f0bSmrg {
1415*8feb0f0bSmrg st_info = &((Elf64_External_Sym *)ent)->st_info;
1416*8feb0f0bSmrg st_other = &((Elf64_External_Sym *)ent)->st_other;
1417*8feb0f0bSmrg }
1418*8feb0f0bSmrg if (st_shndx == SHN_XINDEX)
1419*8feb0f0bSmrg st_shndx = type_functions->fetch_Elf_Word
1420*8feb0f0bSmrg ((unsigned char *)(shndx_table + (ent - buf) / entsize));
1421*8feb0f0bSmrg
1422*8feb0f0bSmrg if (st_shndx != SHN_COMMON
1423*8feb0f0bSmrg && !(st_shndx != SHN_UNDEF
1424*8feb0f0bSmrg && st_shndx < shnum
1425*8feb0f0bSmrg && pfnret[st_shndx - 1] == -1)
1426*8feb0f0bSmrg && ELF_ST_BIND (*st_info) == STB_WEAK
1427*8feb0f0bSmrg && *st_other == STV_HIDDEN)
1428*8feb0f0bSmrg {
1429*8feb0f0bSmrg prevailing_name_idx = ELF_FETCH_FIELD (type_functions,
1430*8feb0f0bSmrg ei_class, Sym, ent,
1431*8feb0f0bSmrg st_name, Elf_Word);
1432*8feb0f0bSmrg break;
1433*8feb0f0bSmrg }
1434*8feb0f0bSmrg }
1435*8feb0f0bSmrg
1436a2dc1f3fSmrg for (ent = buf; ent < buf + length; ent += entsize)
1437a2dc1f3fSmrg {
1438a2dc1f3fSmrg unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
1439a2dc1f3fSmrg Sym, ent,
1440a2dc1f3fSmrg st_shndx, Elf_Half);
1441a2dc1f3fSmrg unsigned raw_st_shndx = st_shndx;
1442a2dc1f3fSmrg unsigned char *st_info;
1443a2dc1f3fSmrg unsigned char *st_other;
1444a2dc1f3fSmrg int discard = 0;
1445a2dc1f3fSmrg if (ei_class == ELFCLASS32)
1446a2dc1f3fSmrg {
1447a2dc1f3fSmrg st_info = &((Elf32_External_Sym *)ent)->st_info;
1448a2dc1f3fSmrg st_other = &((Elf32_External_Sym *)ent)->st_other;
1449a2dc1f3fSmrg }
1450a2dc1f3fSmrg else
1451a2dc1f3fSmrg {
1452a2dc1f3fSmrg st_info = &((Elf64_External_Sym *)ent)->st_info;
1453a2dc1f3fSmrg st_other = &((Elf64_External_Sym *)ent)->st_other;
1454a2dc1f3fSmrg }
1455a2dc1f3fSmrg if (st_shndx == SHN_XINDEX)
1456a2dc1f3fSmrg st_shndx = type_functions->fetch_Elf_Word
1457a2dc1f3fSmrg ((unsigned char *)(shndx_table + (ent - buf) / entsize));
1458*8feb0f0bSmrg /* Eliminate all COMMONs - this includes __gnu_lto_slim
1459*8feb0f0bSmrg which otherwise cause endless LTO plugin invocation.
1460*8feb0f0bSmrg FIXME: remove the condition once we remove emission
1461*8feb0f0bSmrg of __gnu_lto_slim symbol. */
1462a2dc1f3fSmrg if (st_shndx == SHN_COMMON)
1463a2dc1f3fSmrg discard = 1;
1464a2dc1f3fSmrg /* We also need to remove symbols refering to sections
1465a2dc1f3fSmrg we'll eventually remove as with fat LTO objects
1466a2dc1f3fSmrg we otherwise get duplicate symbols at final link
1467a2dc1f3fSmrg (with GNU ld, gold is fine and ignores symbols in
1468a2dc1f3fSmrg sections marked as EXCLUDE). ld/20513 */
1469a2dc1f3fSmrg else if (st_shndx != SHN_UNDEF
1470a2dc1f3fSmrg && st_shndx < shnum
1471a2dc1f3fSmrg && pfnret[st_shndx - 1] == -1)
1472a2dc1f3fSmrg discard = 1;
1473*8feb0f0bSmrg /* We also need to remove global UNDEFs which can
1474*8feb0f0bSmrg cause link fails later. */
1475*8feb0f0bSmrg else if (st_shndx == SHN_UNDEF
1476*8feb0f0bSmrg && ELF_ST_BIND (*st_info) == STB_GLOBAL)
1477*8feb0f0bSmrg discard = 1;
1478a2dc1f3fSmrg
1479a2dc1f3fSmrg if (discard)
1480a2dc1f3fSmrg {
1481a2dc1f3fSmrg /* Make discarded symbols undefined and unnamed
1482a2dc1f3fSmrg in case it is local. */
1483a2dc1f3fSmrg int bind = ELF_ST_BIND (*st_info);
1484a2dc1f3fSmrg int other = STV_DEFAULT;
1485a2dc1f3fSmrg if (bind == STB_LOCAL)
1486a2dc1f3fSmrg {
1487a2dc1f3fSmrg /* Make discarded local symbols unnamed and
1488a2dc1f3fSmrg defined in the first prevailing section. */
1489a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Sym,
1490a2dc1f3fSmrg ent, st_name, Elf_Word, 0);
1491a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Sym,
1492a2dc1f3fSmrg ent, st_shndx, Elf_Half,
1493a2dc1f3fSmrg sh_map[first_shndx]);
1494a2dc1f3fSmrg }
1495a2dc1f3fSmrg else
1496a2dc1f3fSmrg {
1497a2dc1f3fSmrg /* Make discarded global symbols hidden weak
1498*8feb0f0bSmrg undefined and sharing a name of a prevailing
1499*8feb0f0bSmrg symbol. */
1500a2dc1f3fSmrg bind = STB_WEAK;
1501a2dc1f3fSmrg other = STV_HIDDEN;
1502a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Sym,
1503a2dc1f3fSmrg ent, st_name, Elf_Word,
1504*8feb0f0bSmrg prevailing_name_idx);
1505a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Sym,
1506a2dc1f3fSmrg ent, st_shndx, Elf_Half, SHN_UNDEF);
1507a2dc1f3fSmrg }
1508a2dc1f3fSmrg *st_other = other;
1509a2dc1f3fSmrg *st_info = ELF_ST_INFO (bind, STT_NOTYPE);
1510a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Sym,
1511a2dc1f3fSmrg ent, st_value, Elf_Addr, 0);
1512a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Sym,
1513a2dc1f3fSmrg ent, st_size, Elf_Word, 0);
1514a2dc1f3fSmrg }
1515a2dc1f3fSmrg else if (raw_st_shndx < SHN_LORESERVE
1516a2dc1f3fSmrg || raw_st_shndx == SHN_XINDEX)
1517a2dc1f3fSmrg /* Remap the section reference. */
1518a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Sym,
1519a2dc1f3fSmrg ent, st_shndx, Elf_Half, sh_map[st_shndx]);
1520a2dc1f3fSmrg }
1521a2dc1f3fSmrg XDELETEVEC (shndx_table);
1522a2dc1f3fSmrg }
1523a2dc1f3fSmrg else if (sh_type == SHT_GROUP)
1524a2dc1f3fSmrg {
1525a2dc1f3fSmrg /* Remap section indices in groups and remove removed members. */
1526a2dc1f3fSmrg unsigned char *ent, *dst;
1527a2dc1f3fSmrg for (dst = ent = buf + 4; ent < buf + length; ent += 4)
1528a2dc1f3fSmrg {
1529a2dc1f3fSmrg unsigned shndx = type_functions->fetch_Elf_Word (ent);
1530a2dc1f3fSmrg if (pfnret[shndx - 1] == -1)
1531a2dc1f3fSmrg ;
1532a2dc1f3fSmrg else
1533a2dc1f3fSmrg {
1534a2dc1f3fSmrg type_functions->set_Elf_Word (dst, sh_map[shndx]);
1535a2dc1f3fSmrg dst += 4;
1536a2dc1f3fSmrg }
1537a2dc1f3fSmrg }
1538a2dc1f3fSmrg /* Adjust the length. */
1539a2dc1f3fSmrg length = dst - buf;
1540a2dc1f3fSmrg }
1541a2dc1f3fSmrg
1542a2dc1f3fSmrg errmsg = simple_object_write_add_data (dobj, dest,
1543a2dc1f3fSmrg buf, length, 1, err);
1544a2dc1f3fSmrg XDELETEVEC (buf);
1545a2dc1f3fSmrg if (errmsg)
1546a2dc1f3fSmrg {
1547a2dc1f3fSmrg XDELETEVEC (names);
1548a2dc1f3fSmrg XDELETEVEC (shdrs);
1549a2dc1f3fSmrg XDELETEVEC (symtab_indices_shndx);
1550a2dc1f3fSmrg return errmsg;
1551a2dc1f3fSmrg }
1552a2dc1f3fSmrg
1553a2dc1f3fSmrg flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1554a2dc1f3fSmrg shdr, sh_flags, Elf_Addr);
1555a2dc1f3fSmrg /* Remap the section references. */
1556a2dc1f3fSmrg {
1557a2dc1f3fSmrg unsigned int sh_info, sh_link;
1558a2dc1f3fSmrg if (flags & SHF_INFO_LINK || sh_type == SHT_REL || sh_type == SHT_RELA)
1559a2dc1f3fSmrg {
1560a2dc1f3fSmrg sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1561a2dc1f3fSmrg shdr, sh_info, Elf_Word);
1562a2dc1f3fSmrg sh_info = sh_map[sh_info];
1563a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Shdr,
1564a2dc1f3fSmrg shdr, sh_info, Elf_Word, sh_info);
1565a2dc1f3fSmrg }
1566a2dc1f3fSmrg sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1567a2dc1f3fSmrg shdr, sh_link, Elf_Word);
1568a2dc1f3fSmrg sh_link = sh_map[sh_link];
1569a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Shdr,
1570a2dc1f3fSmrg shdr, sh_link, Elf_Word, sh_link);
1571a2dc1f3fSmrg }
1572a2dc1f3fSmrg /* The debugobj doesn't contain any code, thus no trampolines.
1573a2dc1f3fSmrg Even when the original object needs trampolines, debugobj
1574a2dc1f3fSmrg doesn't. */
1575a2dc1f3fSmrg if (strcmp (name, ".note.GNU-stack") == 0)
1576a2dc1f3fSmrg flags &= ~SHF_EXECINSTR;
1577a2dc1f3fSmrg /* Clear SHF_EXCLUDE on to be preserved sections. */
1578a2dc1f3fSmrg flags &= ~SHF_EXCLUDE;
1579a2dc1f3fSmrg ELF_SET_FIELD (type_functions, ei_class, Shdr,
1580a2dc1f3fSmrg shdr, sh_flags, Elf_Addr, flags);
1581a2dc1f3fSmrg }
1582a2dc1f3fSmrg
1583a2dc1f3fSmrg XDELETEVEC (names);
1584a2dc1f3fSmrg XDELETEVEC (shdrs);
1585a2dc1f3fSmrg XDELETEVEC (pfnret);
1586a2dc1f3fSmrg XDELETEVEC (pfnname);
1587a2dc1f3fSmrg XDELETEVEC (symtab_indices_shndx);
1588a2dc1f3fSmrg XDELETEVEC (sh_map);
1589a2dc1f3fSmrg
1590a2dc1f3fSmrg return NULL;
1591a2dc1f3fSmrg }
1592a2dc1f3fSmrg
1593a2dc1f3fSmrg
15941debfc3dSmrg /* The ELF functions. */
15951debfc3dSmrg
15961debfc3dSmrg const struct simple_object_functions simple_object_elf_functions =
15971debfc3dSmrg {
15981debfc3dSmrg simple_object_elf_match,
15991debfc3dSmrg simple_object_elf_find_sections,
16001debfc3dSmrg simple_object_elf_fetch_attributes,
16011debfc3dSmrg simple_object_elf_release_read,
16021debfc3dSmrg simple_object_elf_attributes_merge,
16031debfc3dSmrg simple_object_elf_release_attributes,
16041debfc3dSmrg simple_object_elf_start_write,
16051debfc3dSmrg simple_object_elf_write_to_file,
1606a2dc1f3fSmrg simple_object_elf_release_write,
1607a2dc1f3fSmrg simple_object_elf_copy_lto_debug_sections
16081debfc3dSmrg };
1609