1be9ac0eaSchristos /* simple-object-elf.c -- routines to manipulate ELF object files.
2*cb63e24eSchristos Copyright (C) 2010-2024 Free Software Foundation, Inc.
3be9ac0eaSchristos Written by Ian Lance Taylor, Google.
4be9ac0eaSchristos
5be9ac0eaSchristos This program is free software; you can redistribute it and/or modify it
6be9ac0eaSchristos under the terms of the GNU General Public License as published by the
7be9ac0eaSchristos Free Software Foundation; either version 2, or (at your option) any
8be9ac0eaSchristos later version.
9be9ac0eaSchristos
10be9ac0eaSchristos This program is distributed in the hope that it will be useful,
11be9ac0eaSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
12be9ac0eaSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13be9ac0eaSchristos GNU General Public License for more details.
14be9ac0eaSchristos
15be9ac0eaSchristos You should have received a copy of the GNU General Public License
16be9ac0eaSchristos along with this program; if not, write to the Free Software
17be9ac0eaSchristos Foundation, 51 Franklin Street - Fifth Floor,
18be9ac0eaSchristos Boston, MA 02110-1301, USA. */
19be9ac0eaSchristos
20be9ac0eaSchristos #include "config.h"
21be9ac0eaSchristos #include "libiberty.h"
22be9ac0eaSchristos #include "simple-object.h"
23be9ac0eaSchristos
24be9ac0eaSchristos #include <errno.h>
256f4ced0bSchristos /* mingw.org's MinGW doesn't have ENOTSUP. */
266f4ced0bSchristos #ifndef ENOTSUP
276f4ced0bSchristos # define ENOTSUP ENOSYS
286f4ced0bSchristos #endif
29be9ac0eaSchristos #include <stddef.h>
30be9ac0eaSchristos
31be9ac0eaSchristos #ifdef HAVE_STDLIB_H
32be9ac0eaSchristos #include <stdlib.h>
33be9ac0eaSchristos #endif
34be9ac0eaSchristos
35be9ac0eaSchristos #ifdef HAVE_STDINT_H
36be9ac0eaSchristos #include <stdint.h>
37be9ac0eaSchristos #endif
38be9ac0eaSchristos
39be9ac0eaSchristos #ifdef HAVE_STRING_H
40be9ac0eaSchristos #include <string.h>
41be9ac0eaSchristos #endif
42be9ac0eaSchristos
43be9ac0eaSchristos #ifdef HAVE_INTTYPES_H
44be9ac0eaSchristos #include <inttypes.h>
45be9ac0eaSchristos #endif
46be9ac0eaSchristos
47be9ac0eaSchristos #include "simple-object-common.h"
48be9ac0eaSchristos
49be9ac0eaSchristos /* ELF structures and constants. */
50be9ac0eaSchristos
51be9ac0eaSchristos /* 32-bit ELF file header. */
52be9ac0eaSchristos
53be9ac0eaSchristos typedef struct {
54be9ac0eaSchristos unsigned char e_ident[16]; /* ELF "magic number" */
55be9ac0eaSchristos unsigned char e_type[2]; /* Identifies object file type */
56be9ac0eaSchristos unsigned char e_machine[2]; /* Specifies required architecture */
57be9ac0eaSchristos unsigned char e_version[4]; /* Identifies object file version */
58be9ac0eaSchristos unsigned char e_entry[4]; /* Entry point virtual address */
59be9ac0eaSchristos unsigned char e_phoff[4]; /* Program header table file offset */
60be9ac0eaSchristos unsigned char e_shoff[4]; /* Section header table file offset */
61be9ac0eaSchristos unsigned char e_flags[4]; /* Processor-specific flags */
62be9ac0eaSchristos unsigned char e_ehsize[2]; /* ELF header size in bytes */
63be9ac0eaSchristos unsigned char e_phentsize[2]; /* Program header table entry size */
64be9ac0eaSchristos unsigned char e_phnum[2]; /* Program header table entry count */
65be9ac0eaSchristos unsigned char e_shentsize[2]; /* Section header table entry size */
66be9ac0eaSchristos unsigned char e_shnum[2]; /* Section header table entry count */
67be9ac0eaSchristos unsigned char e_shstrndx[2]; /* Section header string table index */
68be9ac0eaSchristos } Elf32_External_Ehdr;
69be9ac0eaSchristos
70be9ac0eaSchristos /* 64-bit ELF file header. */
71be9ac0eaSchristos
72be9ac0eaSchristos typedef struct {
73be9ac0eaSchristos unsigned char e_ident[16]; /* ELF "magic number" */
74be9ac0eaSchristos unsigned char e_type[2]; /* Identifies object file type */
75be9ac0eaSchristos unsigned char e_machine[2]; /* Specifies required architecture */
76be9ac0eaSchristos unsigned char e_version[4]; /* Identifies object file version */
77be9ac0eaSchristos unsigned char e_entry[8]; /* Entry point virtual address */
78be9ac0eaSchristos unsigned char e_phoff[8]; /* Program header table file offset */
79be9ac0eaSchristos unsigned char e_shoff[8]; /* Section header table file offset */
80be9ac0eaSchristos unsigned char e_flags[4]; /* Processor-specific flags */
81be9ac0eaSchristos unsigned char e_ehsize[2]; /* ELF header size in bytes */
82be9ac0eaSchristos unsigned char e_phentsize[2]; /* Program header table entry size */
83be9ac0eaSchristos unsigned char e_phnum[2]; /* Program header table entry count */
84be9ac0eaSchristos unsigned char e_shentsize[2]; /* Section header table entry size */
85be9ac0eaSchristos unsigned char e_shnum[2]; /* Section header table entry count */
86be9ac0eaSchristos unsigned char e_shstrndx[2]; /* Section header string table index */
87be9ac0eaSchristos } Elf64_External_Ehdr;
88be9ac0eaSchristos
89be9ac0eaSchristos /* Indexes and values in e_ident field of Ehdr. */
90be9ac0eaSchristos
91be9ac0eaSchristos #define EI_MAG0 0 /* File identification byte 0 index */
92be9ac0eaSchristos #define ELFMAG0 0x7F /* Magic number byte 0 */
93be9ac0eaSchristos
94be9ac0eaSchristos #define EI_MAG1 1 /* File identification byte 1 index */
95be9ac0eaSchristos #define ELFMAG1 'E' /* Magic number byte 1 */
96be9ac0eaSchristos
97be9ac0eaSchristos #define EI_MAG2 2 /* File identification byte 2 index */
98be9ac0eaSchristos #define ELFMAG2 'L' /* Magic number byte 2 */
99be9ac0eaSchristos
100be9ac0eaSchristos #define EI_MAG3 3 /* File identification byte 3 index */
101be9ac0eaSchristos #define ELFMAG3 'F' /* Magic number byte 3 */
102be9ac0eaSchristos
103be9ac0eaSchristos #define EI_CLASS 4 /* File class */
104be9ac0eaSchristos #define ELFCLASSNONE 0 /* Invalid class */
105be9ac0eaSchristos #define ELFCLASS32 1 /* 32-bit objects */
106be9ac0eaSchristos #define ELFCLASS64 2 /* 64-bit objects */
107be9ac0eaSchristos
108be9ac0eaSchristos #define EI_DATA 5 /* Data encoding */
109be9ac0eaSchristos #define ELFDATANONE 0 /* Invalid data encoding */
110be9ac0eaSchristos #define ELFDATA2LSB 1 /* 2's complement, little endian */
111be9ac0eaSchristos #define ELFDATA2MSB 2 /* 2's complement, big endian */
112be9ac0eaSchristos
113be9ac0eaSchristos #define EI_VERSION 6 /* File version */
114be9ac0eaSchristos #define EV_CURRENT 1 /* Current version */
115be9ac0eaSchristos
116be9ac0eaSchristos #define EI_OSABI 7 /* Operating System/ABI indication */
117be9ac0eaSchristos
118be9ac0eaSchristos /* Values for e_type field of Ehdr. */
119be9ac0eaSchristos
120be9ac0eaSchristos #define ET_REL 1 /* Relocatable file */
121be9ac0eaSchristos
122883529b6Schristos /* Values for e_machine field of Ehdr. */
123883529b6Schristos
124883529b6Schristos #define EM_SPARC 2 /* SUN SPARC */
125883529b6Schristos #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
126883529b6Schristos
127be9ac0eaSchristos /* Special section index values. */
128be9ac0eaSchristos
129fc4f4269Schristos #define SHN_UNDEF 0 /* Undefined section */
130be9ac0eaSchristos #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
131fc4f4269Schristos #define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
132be9ac0eaSchristos #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
133c1a20988Schristos #define SHN_HIRESERVE 0xffff /* End of reserved indices */
134be9ac0eaSchristos
135fc4f4269Schristos
136be9ac0eaSchristos /* 32-bit ELF program header. */
137be9ac0eaSchristos
138be9ac0eaSchristos typedef struct {
139be9ac0eaSchristos unsigned char p_type[4]; /* Identifies program segment type */
140be9ac0eaSchristos unsigned char p_offset[4]; /* Segment file offset */
141be9ac0eaSchristos unsigned char p_vaddr[4]; /* Segment virtual address */
142be9ac0eaSchristos unsigned char p_paddr[4]; /* Segment physical address */
143be9ac0eaSchristos unsigned char p_filesz[4]; /* Segment size in file */
144be9ac0eaSchristos unsigned char p_memsz[4]; /* Segment size in memory */
145be9ac0eaSchristos unsigned char p_flags[4]; /* Segment flags */
146be9ac0eaSchristos unsigned char p_align[4]; /* Segment alignment, file & memory */
147be9ac0eaSchristos } Elf32_External_Phdr;
148be9ac0eaSchristos
149be9ac0eaSchristos /* 64-bit ELF program header. */
150be9ac0eaSchristos
151be9ac0eaSchristos typedef struct {
152be9ac0eaSchristos unsigned char p_type[4]; /* Identifies program segment type */
153be9ac0eaSchristos unsigned char p_flags[4]; /* Segment flags */
154be9ac0eaSchristos unsigned char p_offset[8]; /* Segment file offset */
155be9ac0eaSchristos unsigned char p_vaddr[8]; /* Segment virtual address */
156be9ac0eaSchristos unsigned char p_paddr[8]; /* Segment physical address */
157be9ac0eaSchristos unsigned char p_filesz[8]; /* Segment size in file */
158be9ac0eaSchristos unsigned char p_memsz[8]; /* Segment size in memory */
159be9ac0eaSchristos unsigned char p_align[8]; /* Segment alignment, file & memory */
160be9ac0eaSchristos } Elf64_External_Phdr;
161be9ac0eaSchristos
162be9ac0eaSchristos /* 32-bit ELF section header */
163be9ac0eaSchristos
164be9ac0eaSchristos typedef struct {
165be9ac0eaSchristos unsigned char sh_name[4]; /* Section name, index in string tbl */
166be9ac0eaSchristos unsigned char sh_type[4]; /* Type of section */
167be9ac0eaSchristos unsigned char sh_flags[4]; /* Miscellaneous section attributes */
168be9ac0eaSchristos unsigned char sh_addr[4]; /* Section virtual addr at execution */
169be9ac0eaSchristos unsigned char sh_offset[4]; /* Section file offset */
170be9ac0eaSchristos unsigned char sh_size[4]; /* Size of section in bytes */
171be9ac0eaSchristos unsigned char sh_link[4]; /* Index of another section */
172be9ac0eaSchristos unsigned char sh_info[4]; /* Additional section information */
173be9ac0eaSchristos unsigned char sh_addralign[4]; /* Section alignment */
174be9ac0eaSchristos unsigned char sh_entsize[4]; /* Entry size if section holds table */
175be9ac0eaSchristos } Elf32_External_Shdr;
176be9ac0eaSchristos
177be9ac0eaSchristos /* 64-bit ELF section header. */
178be9ac0eaSchristos
179be9ac0eaSchristos typedef struct {
180be9ac0eaSchristos unsigned char sh_name[4]; /* Section name, index in string tbl */
181be9ac0eaSchristos unsigned char sh_type[4]; /* Type of section */
182be9ac0eaSchristos unsigned char sh_flags[8]; /* Miscellaneous section attributes */
183be9ac0eaSchristos unsigned char sh_addr[8]; /* Section virtual addr at execution */
184be9ac0eaSchristos unsigned char sh_offset[8]; /* Section file offset */
185be9ac0eaSchristos unsigned char sh_size[8]; /* Size of section in bytes */
186be9ac0eaSchristos unsigned char sh_link[4]; /* Index of another section */
187be9ac0eaSchristos unsigned char sh_info[4]; /* Additional section information */
188be9ac0eaSchristos unsigned char sh_addralign[8]; /* Section alignment */
189be9ac0eaSchristos unsigned char sh_entsize[8]; /* Entry size if section holds table */
190be9ac0eaSchristos } Elf64_External_Shdr;
191be9ac0eaSchristos
192be9ac0eaSchristos /* Values for sh_type field. */
193be9ac0eaSchristos
194fc4f4269Schristos #define SHT_NULL 0 /* Section header table entry unused */
195be9ac0eaSchristos #define SHT_PROGBITS 1 /* Program data */
196fc4f4269Schristos #define SHT_SYMTAB 2 /* Link editing symbol table */
197be9ac0eaSchristos #define SHT_STRTAB 3 /* A string table */
198fc4f4269Schristos #define SHT_RELA 4 /* Relocation entries with addends */
199fc4f4269Schristos #define SHT_REL 9 /* Relocation entries, no addends */
200fc4f4269Schristos #define SHT_GROUP 17 /* Section contains a section group */
201c1a20988Schristos #define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
202fc4f4269Schristos
203fc4f4269Schristos /* Values for sh_flags field. */
204fc4f4269Schristos
205c1a20988Schristos #define SHF_INFO_LINK 0x00000040 /* `sh_info' contains SHT index */
206fc4f4269Schristos #define SHF_EXECINSTR 0x00000004 /* Executable section. */
207fc4f4269Schristos #define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this
208fc4f4269Schristos section from executable and
209fc4f4269Schristos shared library that it builds
210fc4f4269Schristos when those objects are not to be
211fc4f4269Schristos further relocated. */
212fc4f4269Schristos /* Symbol table entry. */
213fc4f4269Schristos
214fc4f4269Schristos typedef struct
215fc4f4269Schristos {
216fc4f4269Schristos unsigned char st_name[4]; /* Symbol name (string tbl index) */
217fc4f4269Schristos unsigned char st_value[4]; /* Symbol value */
218fc4f4269Schristos unsigned char st_size[4]; /* Symbol size */
219fc4f4269Schristos unsigned char st_info; /* Symbol type and binding */
220fc4f4269Schristos unsigned char st_other; /* Symbol visibility */
221fc4f4269Schristos unsigned char st_shndx[2]; /* Section index */
222fc4f4269Schristos } Elf32_External_Sym;
223fc4f4269Schristos
224fc4f4269Schristos typedef struct
225fc4f4269Schristos {
226fc4f4269Schristos unsigned char st_name[4]; /* Symbol name (string tbl index) */
227fc4f4269Schristos unsigned char st_info; /* Symbol type and binding */
228fc4f4269Schristos unsigned char st_other; /* Symbol visibility */
229fc4f4269Schristos unsigned char st_shndx[2]; /* Section index */
230fc4f4269Schristos unsigned char st_value[8]; /* Symbol value */
231fc4f4269Schristos unsigned char st_size[8]; /* Symbol size */
232fc4f4269Schristos } Elf64_External_Sym;
233fc4f4269Schristos
234fc4f4269Schristos #define ELF_ST_BIND(val) (((unsigned char) (val)) >> 4)
235fc4f4269Schristos #define ELF_ST_TYPE(val) ((val) & 0xf)
236fc4f4269Schristos #define ELF_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
237fc4f4269Schristos
238fc4f4269Schristos #define STT_NOTYPE 0 /* Symbol type is unspecified */
239fc4f4269Schristos #define STT_OBJECT 1 /* Symbol is a data object */
240fc4f4269Schristos #define STT_FUNC 2 /* Symbol is a code object */
241fc4f4269Schristos #define STT_TLS 6 /* Thread local data object */
242fc4f4269Schristos #define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */
243fc4f4269Schristos
244fc4f4269Schristos #define STB_LOCAL 0 /* Local symbol */
245fc4f4269Schristos #define STB_GLOBAL 1 /* Global symbol */
246fc4f4269Schristos #define STB_WEAK 2 /* Weak global */
247fc4f4269Schristos
248fc4f4269Schristos #define STV_DEFAULT 0 /* Visibility is specified by binding type */
249fc4f4269Schristos #define STV_HIDDEN 2 /* Can only be seen inside currect component */
250be9ac0eaSchristos
251be9ac0eaSchristos /* Functions to fetch and store different ELF types, depending on the
252be9ac0eaSchristos endianness and size. */
253be9ac0eaSchristos
254be9ac0eaSchristos struct elf_type_functions
255be9ac0eaSchristos {
256be9ac0eaSchristos unsigned short (*fetch_Elf_Half) (const unsigned char *);
257be9ac0eaSchristos unsigned int (*fetch_Elf_Word) (const unsigned char *);
258be9ac0eaSchristos ulong_type (*fetch_Elf_Addr) (const unsigned char *);
259be9ac0eaSchristos void (*set_Elf_Half) (unsigned char *, unsigned short);
260be9ac0eaSchristos void (*set_Elf_Word) (unsigned char *, unsigned int);
261be9ac0eaSchristos void (*set_Elf_Addr) (unsigned char *, ulong_type);
262be9ac0eaSchristos };
263be9ac0eaSchristos
264be9ac0eaSchristos static const struct elf_type_functions elf_big_32_functions =
265be9ac0eaSchristos {
266be9ac0eaSchristos simple_object_fetch_big_16,
267be9ac0eaSchristos simple_object_fetch_big_32,
268be9ac0eaSchristos simple_object_fetch_big_32_ulong,
269be9ac0eaSchristos simple_object_set_big_16,
270be9ac0eaSchristos simple_object_set_big_32,
271be9ac0eaSchristos simple_object_set_big_32_ulong
272be9ac0eaSchristos };
273be9ac0eaSchristos
274be9ac0eaSchristos static const struct elf_type_functions elf_little_32_functions =
275be9ac0eaSchristos {
276be9ac0eaSchristos simple_object_fetch_little_16,
277be9ac0eaSchristos simple_object_fetch_little_32,
278be9ac0eaSchristos simple_object_fetch_little_32_ulong,
279be9ac0eaSchristos simple_object_set_little_16,
280be9ac0eaSchristos simple_object_set_little_32,
281be9ac0eaSchristos simple_object_set_little_32_ulong
282be9ac0eaSchristos };
283be9ac0eaSchristos
284be9ac0eaSchristos #ifdef UNSIGNED_64BIT_TYPE
285be9ac0eaSchristos
286be9ac0eaSchristos static const struct elf_type_functions elf_big_64_functions =
287be9ac0eaSchristos {
288be9ac0eaSchristos simple_object_fetch_big_16,
289be9ac0eaSchristos simple_object_fetch_big_32,
290be9ac0eaSchristos simple_object_fetch_big_64,
291be9ac0eaSchristos simple_object_set_big_16,
292be9ac0eaSchristos simple_object_set_big_32,
293be9ac0eaSchristos simple_object_set_big_64
294be9ac0eaSchristos };
295be9ac0eaSchristos
296be9ac0eaSchristos static const struct elf_type_functions elf_little_64_functions =
297be9ac0eaSchristos {
298be9ac0eaSchristos simple_object_fetch_little_16,
299be9ac0eaSchristos simple_object_fetch_little_32,
300be9ac0eaSchristos simple_object_fetch_little_64,
301be9ac0eaSchristos simple_object_set_little_16,
302be9ac0eaSchristos simple_object_set_little_32,
303be9ac0eaSchristos simple_object_set_little_64
304be9ac0eaSchristos };
305be9ac0eaSchristos
306be9ac0eaSchristos #endif
307be9ac0eaSchristos
308be9ac0eaSchristos /* Hideous macro to fetch the value of a field from an external ELF
309be9ac0eaSchristos struct of some sort. TYPEFUNCS is the set of type functions.
310be9ac0eaSchristos BUFFER points to the external data. STRUCTTYPE is the appropriate
311be9ac0eaSchristos struct type. FIELD is a field within the struct. TYPE is the type
312be9ac0eaSchristos of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */
313be9ac0eaSchristos
314be9ac0eaSchristos #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
315be9ac0eaSchristos ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
316be9ac0eaSchristos
317be9ac0eaSchristos /* Even more hideous macro to fetch the value of FIELD from BUFFER.
318be9ac0eaSchristos SIZE is 32 or 64. STRUCTTYPE is the name of the struct from
319be9ac0eaSchristos elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in
320be9ac0eaSchristos the struct. TYPE is the type of the field in the struct: Elf_Half,
321be9ac0eaSchristos Elf_Word, or Elf_Addr. */
322be9ac0eaSchristos
323be9ac0eaSchristos #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, \
324be9ac0eaSchristos FIELD, TYPE) \
325be9ac0eaSchristos ELF_FETCH_STRUCT_FIELD (TYPEFUNCS, \
326be9ac0eaSchristos Elf ## SIZE ## _External_ ## STRUCTTYPE, \
327be9ac0eaSchristos FIELD, BUFFER, TYPE)
328be9ac0eaSchristos
329be9ac0eaSchristos /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value. */
330be9ac0eaSchristos
331be9ac0eaSchristos #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, \
332be9ac0eaSchristos FIELD, TYPE) \
333be9ac0eaSchristos ((CLASS) == ELFCLASS32 \
334be9ac0eaSchristos ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \
335be9ac0eaSchristos TYPE) \
336be9ac0eaSchristos : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \
337be9ac0eaSchristos TYPE))
338be9ac0eaSchristos
339be9ac0eaSchristos /* Hideous macro to set the value of a field in an external ELF
340be9ac0eaSchristos structure to VAL. TYPEFUNCS is the set of type functions. BUFFER
341be9ac0eaSchristos points to the external data. STRUCTTYPE is the appropriate
342be9ac0eaSchristos structure type. FIELD is a field within the struct. TYPE is the
343be9ac0eaSchristos type of the field in the struct: Elf_Half, Elf_Word, or
344be9ac0eaSchristos Elf_Addr. */
345be9ac0eaSchristos
346be9ac0eaSchristos #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
347be9ac0eaSchristos (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
348be9ac0eaSchristos
349be9ac0eaSchristos /* Even more hideous macro to set the value of FIELD in BUFFER to VAL.
350be9ac0eaSchristos SIZE is 32 or 64. STRUCTTYPE is the name of the struct from
351be9ac0eaSchristos elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in
352be9ac0eaSchristos the struct. TYPE is the type of the field in the struct: Elf_Half,
353be9ac0eaSchristos Elf_Word, or Elf_Addr. */
354be9ac0eaSchristos
355be9ac0eaSchristos #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
356be9ac0eaSchristos TYPE, VAL) \
357be9ac0eaSchristos ELF_SET_STRUCT_FIELD (TYPEFUNCS, \
358be9ac0eaSchristos Elf ## SIZE ## _External_ ## STRUCTTYPE, \
359be9ac0eaSchristos FIELD, BUFFER, TYPE, VAL)
360be9ac0eaSchristos
361be9ac0eaSchristos /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value. */
362be9ac0eaSchristos
363be9ac0eaSchristos #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD, \
364be9ac0eaSchristos TYPE, VAL) \
365be9ac0eaSchristos ((CLASS) == ELFCLASS32 \
366be9ac0eaSchristos ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \
367be9ac0eaSchristos TYPE, VAL) \
368be9ac0eaSchristos : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \
369be9ac0eaSchristos TYPE, VAL))
370be9ac0eaSchristos
371be9ac0eaSchristos /* Private data for an simple_object_read. */
372be9ac0eaSchristos
373be9ac0eaSchristos struct simple_object_elf_read
374be9ac0eaSchristos {
375be9ac0eaSchristos /* Type functions. */
376be9ac0eaSchristos const struct elf_type_functions* type_functions;
377be9ac0eaSchristos /* Elf data. */
378be9ac0eaSchristos unsigned char ei_data;
379be9ac0eaSchristos /* Elf class. */
380be9ac0eaSchristos unsigned char ei_class;
381be9ac0eaSchristos /* ELF OS ABI. */
382be9ac0eaSchristos unsigned char ei_osabi;
383be9ac0eaSchristos /* Elf machine number. */
384be9ac0eaSchristos unsigned short machine;
385be9ac0eaSchristos /* Processor specific flags. */
386be9ac0eaSchristos unsigned int flags;
387be9ac0eaSchristos /* File offset of section headers. */
388be9ac0eaSchristos ulong_type shoff;
389be9ac0eaSchristos /* Number of sections. */
390be9ac0eaSchristos unsigned int shnum;
391be9ac0eaSchristos /* Index of string table section header. */
392be9ac0eaSchristos unsigned int shstrndx;
393be9ac0eaSchristos };
394be9ac0eaSchristos
395be9ac0eaSchristos /* Private data for an simple_object_attributes. */
396be9ac0eaSchristos
397be9ac0eaSchristos struct simple_object_elf_attributes
398be9ac0eaSchristos {
399be9ac0eaSchristos /* Type functions. */
400be9ac0eaSchristos const struct elf_type_functions* type_functions;
401be9ac0eaSchristos /* Elf data. */
402be9ac0eaSchristos unsigned char ei_data;
403be9ac0eaSchristos /* Elf class. */
404be9ac0eaSchristos unsigned char ei_class;
405be9ac0eaSchristos /* ELF OS ABI. */
406be9ac0eaSchristos unsigned char ei_osabi;
407be9ac0eaSchristos /* Elf machine number. */
408be9ac0eaSchristos unsigned short machine;
409be9ac0eaSchristos /* Processor specific flags. */
410be9ac0eaSchristos unsigned int flags;
411be9ac0eaSchristos };
412be9ac0eaSchristos
413fc4f4269Schristos /* Private data for an simple_object_write. */
414fc4f4269Schristos
415fc4f4269Schristos struct simple_object_elf_write
416fc4f4269Schristos {
417fc4f4269Schristos struct simple_object_elf_attributes attrs;
418fc4f4269Schristos unsigned char *shdrs;
419fc4f4269Schristos };
420fc4f4269Schristos
421be9ac0eaSchristos /* See if we have an ELF file. */
422be9ac0eaSchristos
423be9ac0eaSchristos 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)424be9ac0eaSchristos simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
425be9ac0eaSchristos int descriptor, off_t offset,
426be9ac0eaSchristos const char *segment_name ATTRIBUTE_UNUSED,
427be9ac0eaSchristos const char **errmsg, int *err)
428be9ac0eaSchristos {
429be9ac0eaSchristos unsigned char ei_data;
430be9ac0eaSchristos unsigned char ei_class;
431be9ac0eaSchristos const struct elf_type_functions *type_functions;
432be9ac0eaSchristos unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
433be9ac0eaSchristos struct simple_object_elf_read *eor;
434be9ac0eaSchristos
435be9ac0eaSchristos if (header[EI_MAG0] != ELFMAG0
436be9ac0eaSchristos || header[EI_MAG1] != ELFMAG1
437be9ac0eaSchristos || header[EI_MAG2] != ELFMAG2
438be9ac0eaSchristos || header[EI_MAG3] != ELFMAG3
439be9ac0eaSchristos || header[EI_VERSION] != EV_CURRENT)
440be9ac0eaSchristos {
441be9ac0eaSchristos *errmsg = NULL;
442be9ac0eaSchristos *err = 0;
443be9ac0eaSchristos return NULL;
444be9ac0eaSchristos }
445be9ac0eaSchristos
446be9ac0eaSchristos ei_data = header[EI_DATA];
447be9ac0eaSchristos if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
448be9ac0eaSchristos {
449be9ac0eaSchristos *errmsg = "unknown ELF endianness";
450be9ac0eaSchristos *err = 0;
451be9ac0eaSchristos return NULL;
452be9ac0eaSchristos }
453be9ac0eaSchristos
454be9ac0eaSchristos ei_class = header[EI_CLASS];
455be9ac0eaSchristos switch (ei_class)
456be9ac0eaSchristos {
457be9ac0eaSchristos case ELFCLASS32:
458be9ac0eaSchristos type_functions = (ei_data == ELFDATA2LSB
459be9ac0eaSchristos ? &elf_little_32_functions
460be9ac0eaSchristos : &elf_big_32_functions);
461be9ac0eaSchristos break;
462be9ac0eaSchristos
463be9ac0eaSchristos case ELFCLASS64:
464be9ac0eaSchristos #ifndef UNSIGNED_64BIT_TYPE
465be9ac0eaSchristos *errmsg = "64-bit ELF objects not supported";
466be9ac0eaSchristos *err = 0;
467be9ac0eaSchristos return NULL;
468be9ac0eaSchristos #else
469be9ac0eaSchristos type_functions = (ei_data == ELFDATA2LSB
470be9ac0eaSchristos ? &elf_little_64_functions
471be9ac0eaSchristos : &elf_big_64_functions);
472be9ac0eaSchristos break;
473be9ac0eaSchristos #endif
474be9ac0eaSchristos
475be9ac0eaSchristos default:
476be9ac0eaSchristos *errmsg = "unrecognized ELF size";
477be9ac0eaSchristos *err = 0;
478be9ac0eaSchristos return NULL;
479be9ac0eaSchristos }
480be9ac0eaSchristos
481be9ac0eaSchristos if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr,
482be9ac0eaSchristos errmsg, err))
483be9ac0eaSchristos return NULL;
484be9ac0eaSchristos
485be9ac0eaSchristos eor = XNEW (struct simple_object_elf_read);
486be9ac0eaSchristos eor->type_functions = type_functions;
487be9ac0eaSchristos eor->ei_data = ei_data;
488be9ac0eaSchristos eor->ei_class = ei_class;
489be9ac0eaSchristos eor->ei_osabi = header[EI_OSABI];
490be9ac0eaSchristos eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
491be9ac0eaSchristos e_machine, Elf_Half);
492be9ac0eaSchristos eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
493be9ac0eaSchristos e_flags, Elf_Word);
494be9ac0eaSchristos eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
495be9ac0eaSchristos e_shoff, Elf_Addr);
496be9ac0eaSchristos eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
497be9ac0eaSchristos e_shnum, Elf_Half);
498be9ac0eaSchristos eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
499be9ac0eaSchristos e_shstrndx, Elf_Half);
500be9ac0eaSchristos
501be9ac0eaSchristos if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
502be9ac0eaSchristos && eor->shoff != 0)
503be9ac0eaSchristos {
504be9ac0eaSchristos unsigned char shdr[sizeof (Elf64_External_Shdr)];
505be9ac0eaSchristos
506be9ac0eaSchristos /* Object file has more than 0xffff sections. */
507be9ac0eaSchristos
508be9ac0eaSchristos if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr,
509be9ac0eaSchristos (ei_class == ELFCLASS32
510be9ac0eaSchristos ? sizeof (Elf32_External_Shdr)
511be9ac0eaSchristos : sizeof (Elf64_External_Shdr)),
512be9ac0eaSchristos errmsg, err))
513be9ac0eaSchristos {
514be9ac0eaSchristos XDELETE (eor);
515be9ac0eaSchristos return NULL;
516be9ac0eaSchristos }
517be9ac0eaSchristos
518be9ac0eaSchristos if (eor->shnum == 0)
519be9ac0eaSchristos eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
520be9ac0eaSchristos shdr, sh_size, Elf_Addr);
521be9ac0eaSchristos
522be9ac0eaSchristos if (eor->shstrndx == SHN_XINDEX)
523be9ac0eaSchristos {
524be9ac0eaSchristos eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
525be9ac0eaSchristos shdr, sh_link, Elf_Word);
526be9ac0eaSchristos
527be9ac0eaSchristos /* Versions of the GNU binutils between 2.12 and 2.18 did
528be9ac0eaSchristos not handle objects with more than SHN_LORESERVE sections
529be9ac0eaSchristos correctly. All large section indexes were offset by
530be9ac0eaSchristos 0x100. There is more information at
5314f645668Schristos https://sourceware.org/PR5900 .
532be9ac0eaSchristos Fortunately these object files are easy to detect, as the
533be9ac0eaSchristos GNU binutils always put the section header string table
534be9ac0eaSchristos near the end of the list of sections. Thus if the
535be9ac0eaSchristos section header string table index is larger than the
536be9ac0eaSchristos number of sections, then we know we have to subtract
537be9ac0eaSchristos 0x100 to get the real section index. */
538be9ac0eaSchristos if (eor->shstrndx >= eor->shnum
539be9ac0eaSchristos && eor->shstrndx >= SHN_LORESERVE + 0x100)
540be9ac0eaSchristos eor->shstrndx -= 0x100;
541be9ac0eaSchristos }
542be9ac0eaSchristos }
543be9ac0eaSchristos
544be9ac0eaSchristos if (eor->shstrndx >= eor->shnum)
545be9ac0eaSchristos {
546be9ac0eaSchristos *errmsg = "invalid ELF shstrndx >= shnum";
547be9ac0eaSchristos *err = 0;
548be9ac0eaSchristos XDELETE (eor);
549be9ac0eaSchristos return NULL;
550be9ac0eaSchristos }
551be9ac0eaSchristos
5526f4ced0bSchristos if (eor->shstrndx == 0)
5536f4ced0bSchristos {
5546f4ced0bSchristos *errmsg = "invalid ELF shstrndx == 0";
5556f4ced0bSchristos *err = 0;
5566f4ced0bSchristos XDELETE (eor);
5576f4ced0bSchristos return NULL;
5586f4ced0bSchristos }
5596f4ced0bSchristos
560be9ac0eaSchristos return (void *) eor;
561be9ac0eaSchristos }
562be9ac0eaSchristos
563be9ac0eaSchristos /* Find all sections in an ELF file. */
564be9ac0eaSchristos
565be9ac0eaSchristos 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)566be9ac0eaSchristos simple_object_elf_find_sections (simple_object_read *sobj,
567be9ac0eaSchristos int (*pfn) (void *, const char *,
568be9ac0eaSchristos off_t offset, off_t length),
569be9ac0eaSchristos void *data,
570be9ac0eaSchristos int *err)
571be9ac0eaSchristos {
572be9ac0eaSchristos struct simple_object_elf_read *eor =
573be9ac0eaSchristos (struct simple_object_elf_read *) sobj->data;
574be9ac0eaSchristos const struct elf_type_functions *type_functions = eor->type_functions;
575be9ac0eaSchristos unsigned char ei_class = eor->ei_class;
576be9ac0eaSchristos size_t shdr_size;
577be9ac0eaSchristos unsigned int shnum;
578be9ac0eaSchristos unsigned char *shdrs;
579be9ac0eaSchristos const char *errmsg;
580be9ac0eaSchristos unsigned char *shstrhdr;
581be9ac0eaSchristos size_t name_size;
582be9ac0eaSchristos off_t shstroff;
583be9ac0eaSchristos unsigned char *names;
584be9ac0eaSchristos unsigned int i;
585be9ac0eaSchristos
586be9ac0eaSchristos shdr_size = (ei_class == ELFCLASS32
587be9ac0eaSchristos ? sizeof (Elf32_External_Shdr)
588be9ac0eaSchristos : sizeof (Elf64_External_Shdr));
589be9ac0eaSchristos
590be9ac0eaSchristos /* Read the section headers. We skip section 0, which is not a
591be9ac0eaSchristos useful section. */
592be9ac0eaSchristos
593be9ac0eaSchristos shnum = eor->shnum;
594be9ac0eaSchristos shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
595be9ac0eaSchristos
596be9ac0eaSchristos if (!simple_object_internal_read (sobj->descriptor,
597be9ac0eaSchristos sobj->offset + eor->shoff + shdr_size,
598be9ac0eaSchristos shdrs,
599be9ac0eaSchristos shdr_size * (shnum - 1),
600be9ac0eaSchristos &errmsg, err))
601be9ac0eaSchristos {
602be9ac0eaSchristos XDELETEVEC (shdrs);
603be9ac0eaSchristos return errmsg;
604be9ac0eaSchristos }
605be9ac0eaSchristos
606be9ac0eaSchristos /* Read the section names. */
607be9ac0eaSchristos
608be9ac0eaSchristos shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
609be9ac0eaSchristos name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
610be9ac0eaSchristos shstrhdr, sh_size, Elf_Addr);
611be9ac0eaSchristos shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
612be9ac0eaSchristos shstrhdr, sh_offset, Elf_Addr);
613be9ac0eaSchristos names = XNEWVEC (unsigned char, name_size);
614be9ac0eaSchristos if (!simple_object_internal_read (sobj->descriptor,
615be9ac0eaSchristos sobj->offset + shstroff,
616be9ac0eaSchristos names, name_size, &errmsg, err))
617be9ac0eaSchristos {
618be9ac0eaSchristos XDELETEVEC (names);
619be9ac0eaSchristos XDELETEVEC (shdrs);
620be9ac0eaSchristos return errmsg;
621be9ac0eaSchristos }
622be9ac0eaSchristos
623be9ac0eaSchristos for (i = 1; i < shnum; ++i)
624be9ac0eaSchristos {
625be9ac0eaSchristos unsigned char *shdr;
626be9ac0eaSchristos unsigned int sh_name;
627be9ac0eaSchristos const char *name;
628be9ac0eaSchristos off_t offset;
629be9ac0eaSchristos off_t length;
630be9ac0eaSchristos
631be9ac0eaSchristos shdr = shdrs + (i - 1) * shdr_size;
632be9ac0eaSchristos sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
633be9ac0eaSchristos shdr, sh_name, Elf_Word);
634be9ac0eaSchristos if (sh_name >= name_size)
635be9ac0eaSchristos {
636be9ac0eaSchristos *err = 0;
637be9ac0eaSchristos XDELETEVEC (names);
638be9ac0eaSchristos XDELETEVEC (shdrs);
639be9ac0eaSchristos return "ELF section name out of range";
640be9ac0eaSchristos }
641be9ac0eaSchristos
642be9ac0eaSchristos name = (const char *) names + sh_name;
643be9ac0eaSchristos offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
644be9ac0eaSchristos shdr, sh_offset, Elf_Addr);
645be9ac0eaSchristos length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
646be9ac0eaSchristos shdr, sh_size, Elf_Addr);
647be9ac0eaSchristos
648be9ac0eaSchristos if (!(*pfn) (data, name, offset, length))
649be9ac0eaSchristos break;
650be9ac0eaSchristos }
651be9ac0eaSchristos
652be9ac0eaSchristos XDELETEVEC (names);
653be9ac0eaSchristos XDELETEVEC (shdrs);
654be9ac0eaSchristos
655be9ac0eaSchristos return NULL;
656be9ac0eaSchristos }
657be9ac0eaSchristos
658be9ac0eaSchristos /* Fetch the attributes for an simple_object_read. */
659be9ac0eaSchristos
660be9ac0eaSchristos static void *
simple_object_elf_fetch_attributes(simple_object_read * sobj,const char ** errmsg ATTRIBUTE_UNUSED,int * err ATTRIBUTE_UNUSED)661be9ac0eaSchristos simple_object_elf_fetch_attributes (simple_object_read *sobj,
662be9ac0eaSchristos const char **errmsg ATTRIBUTE_UNUSED,
663be9ac0eaSchristos int *err ATTRIBUTE_UNUSED)
664be9ac0eaSchristos {
665be9ac0eaSchristos struct simple_object_elf_read *eor =
666be9ac0eaSchristos (struct simple_object_elf_read *) sobj->data;
667be9ac0eaSchristos struct simple_object_elf_attributes *ret;
668be9ac0eaSchristos
669be9ac0eaSchristos ret = XNEW (struct simple_object_elf_attributes);
670be9ac0eaSchristos ret->type_functions = eor->type_functions;
671be9ac0eaSchristos ret->ei_data = eor->ei_data;
672be9ac0eaSchristos ret->ei_class = eor->ei_class;
673be9ac0eaSchristos ret->ei_osabi = eor->ei_osabi;
674be9ac0eaSchristos ret->machine = eor->machine;
675be9ac0eaSchristos ret->flags = eor->flags;
676be9ac0eaSchristos return ret;
677be9ac0eaSchristos }
678be9ac0eaSchristos
679be9ac0eaSchristos /* Release the privata data for an simple_object_read. */
680be9ac0eaSchristos
681be9ac0eaSchristos static void
simple_object_elf_release_read(void * data)682be9ac0eaSchristos simple_object_elf_release_read (void *data)
683be9ac0eaSchristos {
684be9ac0eaSchristos XDELETE (data);
685be9ac0eaSchristos }
686be9ac0eaSchristos
687be9ac0eaSchristos /* Compare two attributes structures. */
688be9ac0eaSchristos
689be9ac0eaSchristos static const char *
simple_object_elf_attributes_merge(void * todata,void * fromdata,int * err)690883529b6Schristos simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
691be9ac0eaSchristos {
692883529b6Schristos struct simple_object_elf_attributes *to =
693883529b6Schristos (struct simple_object_elf_attributes *) todata;
694883529b6Schristos struct simple_object_elf_attributes *from =
695883529b6Schristos (struct simple_object_elf_attributes *) fromdata;
696be9ac0eaSchristos
697883529b6Schristos if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
698be9ac0eaSchristos {
699be9ac0eaSchristos *err = 0;
700be9ac0eaSchristos return "ELF object format mismatch";
701be9ac0eaSchristos }
702883529b6Schristos
703883529b6Schristos if (to->machine != from->machine)
704883529b6Schristos {
705883529b6Schristos int ok;
706883529b6Schristos
707883529b6Schristos /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
708883529b6Schristos output of EM_SPARC32PLUS. */
709883529b6Schristos ok = 0;
710883529b6Schristos switch (to->machine)
711883529b6Schristos {
712883529b6Schristos case EM_SPARC:
713883529b6Schristos if (from->machine == EM_SPARC32PLUS)
714883529b6Schristos {
715883529b6Schristos to->machine = from->machine;
716883529b6Schristos ok = 1;
717883529b6Schristos }
718883529b6Schristos break;
719883529b6Schristos
720883529b6Schristos case EM_SPARC32PLUS:
721883529b6Schristos if (from->machine == EM_SPARC)
722883529b6Schristos ok = 1;
723883529b6Schristos break;
724883529b6Schristos
725883529b6Schristos default:
726883529b6Schristos break;
727883529b6Schristos }
728883529b6Schristos
729883529b6Schristos if (!ok)
730883529b6Schristos {
731883529b6Schristos *err = 0;
732883529b6Schristos return "ELF machine number mismatch";
733883529b6Schristos }
734883529b6Schristos }
735883529b6Schristos
736be9ac0eaSchristos return NULL;
737be9ac0eaSchristos }
738be9ac0eaSchristos
739be9ac0eaSchristos /* Release the private data for an attributes structure. */
740be9ac0eaSchristos
741be9ac0eaSchristos static void
simple_object_elf_release_attributes(void * data)742be9ac0eaSchristos simple_object_elf_release_attributes (void *data)
743be9ac0eaSchristos {
744be9ac0eaSchristos XDELETE (data);
745be9ac0eaSchristos }
746be9ac0eaSchristos
747be9ac0eaSchristos /* Prepare to write out a file. */
748be9ac0eaSchristos
749be9ac0eaSchristos static void *
simple_object_elf_start_write(void * attributes_data,const char ** errmsg ATTRIBUTE_UNUSED,int * err ATTRIBUTE_UNUSED)750be9ac0eaSchristos simple_object_elf_start_write (void *attributes_data,
751be9ac0eaSchristos const char **errmsg ATTRIBUTE_UNUSED,
752be9ac0eaSchristos int *err ATTRIBUTE_UNUSED)
753be9ac0eaSchristos {
754be9ac0eaSchristos struct simple_object_elf_attributes *attrs =
755be9ac0eaSchristos (struct simple_object_elf_attributes *) attributes_data;
756fc4f4269Schristos struct simple_object_elf_write *ret;
757be9ac0eaSchristos
758be9ac0eaSchristos /* We're just going to record the attributes, but we need to make a
759be9ac0eaSchristos copy because the user may delete them. */
760fc4f4269Schristos ret = XNEW (struct simple_object_elf_write);
761fc4f4269Schristos ret->attrs = *attrs;
762fc4f4269Schristos ret->shdrs = NULL;
763be9ac0eaSchristos return ret;
764be9ac0eaSchristos }
765be9ac0eaSchristos
766be9ac0eaSchristos /* Write out an ELF ehdr. */
767be9ac0eaSchristos
768be9ac0eaSchristos static int
simple_object_elf_write_ehdr(simple_object_write * sobj,int descriptor,const char ** errmsg,int * err)769be9ac0eaSchristos simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
770be9ac0eaSchristos const char **errmsg, int *err)
771be9ac0eaSchristos {
772be9ac0eaSchristos struct simple_object_elf_attributes *attrs =
773be9ac0eaSchristos (struct simple_object_elf_attributes *) sobj->data;
774be9ac0eaSchristos const struct elf_type_functions* fns;
775be9ac0eaSchristos unsigned char cl;
776be9ac0eaSchristos size_t ehdr_size;
777be9ac0eaSchristos unsigned char buf[sizeof (Elf64_External_Ehdr)];
778be9ac0eaSchristos simple_object_write_section *section;
779be9ac0eaSchristos unsigned int shnum;
7809573673dSchristos unsigned int shstrndx;
781be9ac0eaSchristos
782be9ac0eaSchristos fns = attrs->type_functions;
783be9ac0eaSchristos cl = attrs->ei_class;
784be9ac0eaSchristos
785be9ac0eaSchristos shnum = 0;
786be9ac0eaSchristos for (section = sobj->sections; section != NULL; section = section->next)
787be9ac0eaSchristos ++shnum;
788be9ac0eaSchristos if (shnum > 0)
789be9ac0eaSchristos {
790be9ac0eaSchristos /* Add a section header for the dummy section and one for
791be9ac0eaSchristos .shstrtab. */
792be9ac0eaSchristos shnum += 2;
793be9ac0eaSchristos }
794be9ac0eaSchristos
795be9ac0eaSchristos ehdr_size = (cl == ELFCLASS32
796be9ac0eaSchristos ? sizeof (Elf32_External_Ehdr)
797be9ac0eaSchristos : sizeof (Elf64_External_Ehdr));
798be9ac0eaSchristos memset (buf, 0, sizeof (Elf64_External_Ehdr));
799be9ac0eaSchristos
800be9ac0eaSchristos buf[EI_MAG0] = ELFMAG0;
801be9ac0eaSchristos buf[EI_MAG1] = ELFMAG1;
802be9ac0eaSchristos buf[EI_MAG2] = ELFMAG2;
803be9ac0eaSchristos buf[EI_MAG3] = ELFMAG3;
804be9ac0eaSchristos buf[EI_CLASS] = cl;
805be9ac0eaSchristos buf[EI_DATA] = attrs->ei_data;
806be9ac0eaSchristos buf[EI_VERSION] = EV_CURRENT;
807be9ac0eaSchristos buf[EI_OSABI] = attrs->ei_osabi;
808be9ac0eaSchristos
809be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
810be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
811be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
812be9ac0eaSchristos /* e_entry left as zero. */
813be9ac0eaSchristos /* e_phoff left as zero. */
814be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
815be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
816be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
817be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
818be9ac0eaSchristos (cl == ELFCLASS32
819be9ac0eaSchristos ? sizeof (Elf32_External_Phdr)
820be9ac0eaSchristos : sizeof (Elf64_External_Phdr)));
821be9ac0eaSchristos /* e_phnum left as zero. */
822be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
823be9ac0eaSchristos (cl == ELFCLASS32
824be9ac0eaSchristos ? sizeof (Elf32_External_Shdr)
825be9ac0eaSchristos : sizeof (Elf64_External_Shdr)));
8269573673dSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half,
8279573673dSchristos shnum >= SHN_LORESERVE ? 0 : shnum);
8289573673dSchristos if (shnum == 0)
8299573673dSchristos shstrndx = 0;
8309573673dSchristos else
8319573673dSchristos {
8329573673dSchristos shstrndx = shnum - 1;
8339573673dSchristos if (shstrndx >= SHN_LORESERVE)
8349573673dSchristos shstrndx = SHN_XINDEX;
8359573673dSchristos }
8369573673dSchristos ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half, shstrndx);
837be9ac0eaSchristos
838be9ac0eaSchristos return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
839be9ac0eaSchristos errmsg, err);
840be9ac0eaSchristos }
841be9ac0eaSchristos
842be9ac0eaSchristos /* Write out an ELF shdr. */
843be9ac0eaSchristos
844be9ac0eaSchristos 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)845be9ac0eaSchristos simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
846be9ac0eaSchristos off_t offset, unsigned int sh_name,
847be9ac0eaSchristos unsigned int sh_type, unsigned int sh_flags,
848fc4f4269Schristos off_t sh_addr,
849be9ac0eaSchristos unsigned int sh_offset, unsigned int sh_size,
850fc4f4269Schristos unsigned int sh_link, unsigned int sh_info,
851fc4f4269Schristos size_t sh_addralign,
852fc4f4269Schristos size_t sh_entsize,
8539573673dSchristos const char **errmsg, int *err)
854be9ac0eaSchristos {
855be9ac0eaSchristos struct simple_object_elf_attributes *attrs =
856be9ac0eaSchristos (struct simple_object_elf_attributes *) sobj->data;
857be9ac0eaSchristos const struct elf_type_functions* fns;
858be9ac0eaSchristos unsigned char cl;
859be9ac0eaSchristos size_t shdr_size;
860be9ac0eaSchristos unsigned char buf[sizeof (Elf64_External_Shdr)];
861be9ac0eaSchristos
862be9ac0eaSchristos fns = attrs->type_functions;
863be9ac0eaSchristos cl = attrs->ei_class;
864be9ac0eaSchristos
865be9ac0eaSchristos shdr_size = (cl == ELFCLASS32
866be9ac0eaSchristos ? sizeof (Elf32_External_Shdr)
867be9ac0eaSchristos : sizeof (Elf64_External_Shdr));
868be9ac0eaSchristos memset (buf, 0, sizeof (Elf64_External_Shdr));
869be9ac0eaSchristos
870be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
871be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
872be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
873fc4f4269Schristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addr, Elf_Addr, sh_addr);
874be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
875be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
8769573673dSchristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
877fc4f4269Schristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_info, Elf_Word, sh_info);
878be9ac0eaSchristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
879fc4f4269Schristos ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Addr, sh_entsize);
880be9ac0eaSchristos
881be9ac0eaSchristos return simple_object_internal_write (descriptor, offset, buf, shdr_size,
882be9ac0eaSchristos errmsg, err);
883be9ac0eaSchristos }
884be9ac0eaSchristos
885be9ac0eaSchristos /* Write out a complete ELF file.
886be9ac0eaSchristos Ehdr
887be9ac0eaSchristos initial dummy Shdr
888be9ac0eaSchristos user-created Shdrs
889be9ac0eaSchristos .shstrtab Shdr
890be9ac0eaSchristos user-created section data
891be9ac0eaSchristos .shstrtab data */
892be9ac0eaSchristos
893be9ac0eaSchristos static const char *
simple_object_elf_write_to_file(simple_object_write * sobj,int descriptor,int * err)894be9ac0eaSchristos simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
895be9ac0eaSchristos int *err)
896be9ac0eaSchristos {
897fc4f4269Schristos struct simple_object_elf_write *eow =
898fc4f4269Schristos (struct simple_object_elf_write *) sobj->data;
899fc4f4269Schristos struct simple_object_elf_attributes *attrs = &eow->attrs;
900be9ac0eaSchristos unsigned char cl;
901be9ac0eaSchristos size_t ehdr_size;
902be9ac0eaSchristos size_t shdr_size;
903be9ac0eaSchristos const char *errmsg;
904be9ac0eaSchristos simple_object_write_section *section;
905be9ac0eaSchristos unsigned int shnum;
906be9ac0eaSchristos size_t shdr_offset;
907be9ac0eaSchristos size_t sh_offset;
9089573673dSchristos unsigned int first_sh_size;
9099573673dSchristos unsigned int first_sh_link;
910be9ac0eaSchristos size_t sh_name;
911be9ac0eaSchristos unsigned char zero;
912fc4f4269Schristos unsigned secnum;
913be9ac0eaSchristos
914be9ac0eaSchristos if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
915be9ac0eaSchristos return errmsg;
916be9ac0eaSchristos
917be9ac0eaSchristos cl = attrs->ei_class;
918be9ac0eaSchristos if (cl == ELFCLASS32)
919be9ac0eaSchristos {
920be9ac0eaSchristos ehdr_size = sizeof (Elf32_External_Ehdr);
921be9ac0eaSchristos shdr_size = sizeof (Elf32_External_Shdr);
922be9ac0eaSchristos }
923be9ac0eaSchristos else
924be9ac0eaSchristos {
925be9ac0eaSchristos ehdr_size = sizeof (Elf64_External_Ehdr);
926be9ac0eaSchristos shdr_size = sizeof (Elf64_External_Shdr);
927be9ac0eaSchristos }
928be9ac0eaSchristos
929be9ac0eaSchristos shnum = 0;
930be9ac0eaSchristos for (section = sobj->sections; section != NULL; section = section->next)
931be9ac0eaSchristos ++shnum;
932be9ac0eaSchristos if (shnum == 0)
933be9ac0eaSchristos return NULL;
934be9ac0eaSchristos
935be9ac0eaSchristos /* Add initial dummy Shdr and .shstrtab. */
936be9ac0eaSchristos shnum += 2;
937be9ac0eaSchristos
938be9ac0eaSchristos shdr_offset = ehdr_size;
939be9ac0eaSchristos sh_offset = shdr_offset + shnum * shdr_size;
940be9ac0eaSchristos
9419573673dSchristos if (shnum < SHN_LORESERVE)
9429573673dSchristos first_sh_size = 0;
9439573673dSchristos else
9449573673dSchristos first_sh_size = shnum;
9459573673dSchristos if (shnum - 1 < SHN_LORESERVE)
9469573673dSchristos first_sh_link = 0;
9479573673dSchristos else
9489573673dSchristos first_sh_link = shnum - 1;
949be9ac0eaSchristos if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
950fc4f4269Schristos 0, 0, 0, 0, 0, first_sh_size, first_sh_link,
951fc4f4269Schristos 0, 0, 0, &errmsg, err))
952be9ac0eaSchristos return errmsg;
953be9ac0eaSchristos
954be9ac0eaSchristos shdr_offset += shdr_size;
955be9ac0eaSchristos
956be9ac0eaSchristos sh_name = 1;
957fc4f4269Schristos secnum = 0;
958be9ac0eaSchristos for (section = sobj->sections; section != NULL; section = section->next)
959be9ac0eaSchristos {
960be9ac0eaSchristos size_t mask;
961be9ac0eaSchristos size_t new_sh_offset;
962be9ac0eaSchristos size_t sh_size;
963be9ac0eaSchristos struct simple_object_write_section_buffer *buffer;
964fc4f4269Schristos unsigned int sh_type = SHT_PROGBITS;
965fc4f4269Schristos unsigned int sh_flags = 0;
966fc4f4269Schristos off_t sh_addr = 0;
967fc4f4269Schristos unsigned int sh_link = 0;
968fc4f4269Schristos unsigned int sh_info = 0;
969fc4f4269Schristos size_t sh_addralign = 1U << section->align;
970fc4f4269Schristos size_t sh_entsize = 0;
971fc4f4269Schristos if (eow->shdrs)
972fc4f4269Schristos {
973fc4f4269Schristos sh_type = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
974fc4f4269Schristos eow->shdrs + secnum * shdr_size,
975fc4f4269Schristos sh_type, Elf_Word);
976fc4f4269Schristos sh_flags = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
977fc4f4269Schristos eow->shdrs + secnum * shdr_size,
978fc4f4269Schristos sh_flags, Elf_Addr);
979fc4f4269Schristos sh_addr = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
980fc4f4269Schristos eow->shdrs + secnum * shdr_size,
981fc4f4269Schristos sh_addr, Elf_Addr);
982fc4f4269Schristos sh_link = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
983fc4f4269Schristos eow->shdrs + secnum * shdr_size,
984fc4f4269Schristos sh_link, Elf_Word);
985fc4f4269Schristos sh_info = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
986fc4f4269Schristos eow->shdrs + secnum * shdr_size,
987fc4f4269Schristos sh_info, Elf_Word);
988fc4f4269Schristos sh_addralign = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
989fc4f4269Schristos eow->shdrs + secnum * shdr_size,
990fc4f4269Schristos sh_addralign, Elf_Addr);
991fc4f4269Schristos sh_entsize = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
992fc4f4269Schristos eow->shdrs + secnum * shdr_size,
993fc4f4269Schristos sh_entsize, Elf_Addr);
994fc4f4269Schristos secnum++;
995fc4f4269Schristos }
996be9ac0eaSchristos
997fc4f4269Schristos mask = sh_addralign - 1;
998be9ac0eaSchristos new_sh_offset = sh_offset + mask;
999be9ac0eaSchristos new_sh_offset &= ~ mask;
1000be9ac0eaSchristos while (new_sh_offset > sh_offset)
1001be9ac0eaSchristos {
1002be9ac0eaSchristos unsigned char zeroes[16];
1003be9ac0eaSchristos size_t write;
1004be9ac0eaSchristos
1005be9ac0eaSchristos memset (zeroes, 0, sizeof zeroes);
1006be9ac0eaSchristos write = new_sh_offset - sh_offset;
1007be9ac0eaSchristos if (write > sizeof zeroes)
1008be9ac0eaSchristos write = sizeof zeroes;
1009be9ac0eaSchristos if (!simple_object_internal_write (descriptor, sh_offset, zeroes,
1010be9ac0eaSchristos write, &errmsg, err))
1011be9ac0eaSchristos return errmsg;
1012be9ac0eaSchristos sh_offset += write;
1013be9ac0eaSchristos }
1014be9ac0eaSchristos
1015be9ac0eaSchristos sh_size = 0;
1016be9ac0eaSchristos for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
1017be9ac0eaSchristos {
1018be9ac0eaSchristos if (!simple_object_internal_write (descriptor, sh_offset + sh_size,
1019be9ac0eaSchristos ((const unsigned char *)
1020be9ac0eaSchristos buffer->buffer),
1021be9ac0eaSchristos buffer->size, &errmsg, err))
1022be9ac0eaSchristos return errmsg;
1023be9ac0eaSchristos sh_size += buffer->size;
1024be9ac0eaSchristos }
1025be9ac0eaSchristos
1026be9ac0eaSchristos if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
1027fc4f4269Schristos sh_name, sh_type, sh_flags,
1028fc4f4269Schristos sh_addr, sh_offset,
1029fc4f4269Schristos sh_size, sh_link, sh_info,
1030fc4f4269Schristos sh_addralign, sh_entsize,
1031be9ac0eaSchristos &errmsg, err))
1032be9ac0eaSchristos return errmsg;
1033be9ac0eaSchristos
1034be9ac0eaSchristos shdr_offset += shdr_size;
1035be9ac0eaSchristos sh_name += strlen (section->name) + 1;
1036be9ac0eaSchristos sh_offset += sh_size;
1037be9ac0eaSchristos }
1038be9ac0eaSchristos
1039be9ac0eaSchristos if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
1040fc4f4269Schristos sh_name, SHT_STRTAB, 0, 0, sh_offset,
1041fc4f4269Schristos sh_name + strlen (".shstrtab") + 1, 0, 0,
1042fc4f4269Schristos 1, 0, &errmsg, err))
1043be9ac0eaSchristos return errmsg;
1044be9ac0eaSchristos
1045be9ac0eaSchristos /* .shstrtab has a leading zero byte. */
1046be9ac0eaSchristos zero = 0;
1047be9ac0eaSchristos if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
1048be9ac0eaSchristos &errmsg, err))
1049be9ac0eaSchristos return errmsg;
1050be9ac0eaSchristos ++sh_offset;
1051be9ac0eaSchristos
1052be9ac0eaSchristos for (section = sobj->sections; section != NULL; section = section->next)
1053be9ac0eaSchristos {
1054be9ac0eaSchristos size_t len;
1055be9ac0eaSchristos
1056be9ac0eaSchristos len = strlen (section->name) + 1;
1057be9ac0eaSchristos if (!simple_object_internal_write (descriptor, sh_offset,
1058be9ac0eaSchristos (const unsigned char *) section->name,
1059be9ac0eaSchristos len, &errmsg, err))
1060be9ac0eaSchristos return errmsg;
1061be9ac0eaSchristos sh_offset += len;
1062be9ac0eaSchristos }
1063be9ac0eaSchristos
1064be9ac0eaSchristos if (!simple_object_internal_write (descriptor, sh_offset,
1065be9ac0eaSchristos (const unsigned char *) ".shstrtab",
1066be9ac0eaSchristos strlen (".shstrtab") + 1, &errmsg, err))
1067be9ac0eaSchristos return errmsg;
1068be9ac0eaSchristos
1069be9ac0eaSchristos return NULL;
1070be9ac0eaSchristos }
1071be9ac0eaSchristos
1072be9ac0eaSchristos /* Release the private data for an simple_object_write structure. */
1073be9ac0eaSchristos
1074be9ac0eaSchristos static void
simple_object_elf_release_write(void * data)1075be9ac0eaSchristos simple_object_elf_release_write (void *data)
1076be9ac0eaSchristos {
1077fc4f4269Schristos struct simple_object_elf_write *eow = (struct simple_object_elf_write *) data;
1078fc4f4269Schristos if (eow->shdrs)
1079fc4f4269Schristos XDELETE (eow->shdrs);
1080be9ac0eaSchristos XDELETE (data);
1081be9ac0eaSchristos }
1082be9ac0eaSchristos
1083fc4f4269Schristos /* Copy all sections in an ELF file. */
1084fc4f4269Schristos
1085fc4f4269Schristos static const char *
simple_object_elf_copy_lto_debug_sections(simple_object_read * sobj,simple_object_write * dobj,char * (* pfn)(const char *),int * err)1086fc4f4269Schristos simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
1087fc4f4269Schristos simple_object_write *dobj,
1088c1a20988Schristos char *(*pfn) (const char *),
1089fc4f4269Schristos int *err)
1090fc4f4269Schristos {
1091fc4f4269Schristos struct simple_object_elf_read *eor =
1092fc4f4269Schristos (struct simple_object_elf_read *) sobj->data;
1093fc4f4269Schristos const struct elf_type_functions *type_functions = eor->type_functions;
1094fc4f4269Schristos struct simple_object_elf_write *eow =
1095fc4f4269Schristos (struct simple_object_elf_write *) dobj->data;
1096fc4f4269Schristos unsigned char ei_class = eor->ei_class;
1097fc4f4269Schristos size_t shdr_size;
1098fc4f4269Schristos unsigned int shnum;
1099fc4f4269Schristos unsigned char *shdrs;
1100fc4f4269Schristos const char *errmsg;
1101fc4f4269Schristos unsigned char *shstrhdr;
1102fc4f4269Schristos size_t name_size;
1103fc4f4269Schristos off_t shstroff;
1104fc4f4269Schristos unsigned char *names;
1105fc4f4269Schristos unsigned int i;
1106fc4f4269Schristos int changed;
1107fc4f4269Schristos int *pfnret;
1108fc4f4269Schristos const char **pfnname;
1109c1a20988Schristos unsigned new_i;
1110c1a20988Schristos unsigned *sh_map;
1111fc4f4269Schristos unsigned first_shndx = 0;
1112c1a20988Schristos unsigned int *symtab_indices_shndx;
1113fc4f4269Schristos
1114fc4f4269Schristos shdr_size = (ei_class == ELFCLASS32
1115fc4f4269Schristos ? sizeof (Elf32_External_Shdr)
1116fc4f4269Schristos : sizeof (Elf64_External_Shdr));
1117fc4f4269Schristos
1118fc4f4269Schristos /* Read the section headers. We skip section 0, which is not a
1119fc4f4269Schristos useful section. */
1120fc4f4269Schristos
1121fc4f4269Schristos shnum = eor->shnum;
1122fc4f4269Schristos shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
1123fc4f4269Schristos
1124fc4f4269Schristos if (!simple_object_internal_read (sobj->descriptor,
1125fc4f4269Schristos sobj->offset + eor->shoff + shdr_size,
1126fc4f4269Schristos shdrs,
1127fc4f4269Schristos shdr_size * (shnum - 1),
1128fc4f4269Schristos &errmsg, err))
1129fc4f4269Schristos {
1130fc4f4269Schristos XDELETEVEC (shdrs);
1131fc4f4269Schristos return errmsg;
1132fc4f4269Schristos }
1133fc4f4269Schristos
1134fc4f4269Schristos /* Read the section names. */
1135fc4f4269Schristos
1136fc4f4269Schristos shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
1137fc4f4269Schristos name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1138fc4f4269Schristos shstrhdr, sh_size, Elf_Addr);
1139fc4f4269Schristos shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1140fc4f4269Schristos shstrhdr, sh_offset, Elf_Addr);
1141fc4f4269Schristos names = XNEWVEC (unsigned char, name_size);
1142fc4f4269Schristos if (!simple_object_internal_read (sobj->descriptor,
1143fc4f4269Schristos sobj->offset + shstroff,
1144fc4f4269Schristos names, name_size, &errmsg, err))
1145fc4f4269Schristos {
1146fc4f4269Schristos XDELETEVEC (names);
1147fc4f4269Schristos XDELETEVEC (shdrs);
1148fc4f4269Schristos return errmsg;
1149fc4f4269Schristos }
1150fc4f4269Schristos
1151fc4f4269Schristos pfnret = XNEWVEC (int, shnum);
1152fc4f4269Schristos pfnname = XNEWVEC (const char *, shnum);
1153fc4f4269Schristos
1154c1a20988Schristos /* Map of symtab to index section. */
1155c1a20988Schristos symtab_indices_shndx = XCNEWVEC (unsigned int, shnum - 1);
1156c1a20988Schristos
1157fc4f4269Schristos /* First perform the callbacks to know which sections to preserve and
1158fc4f4269Schristos what name to use for those. */
1159fc4f4269Schristos for (i = 1; i < shnum; ++i)
1160fc4f4269Schristos {
1161fc4f4269Schristos unsigned char *shdr;
1162c1a20988Schristos unsigned int sh_name, sh_type;
1163fc4f4269Schristos const char *name;
1164c1a20988Schristos char *ret;
1165fc4f4269Schristos
1166fc4f4269Schristos shdr = shdrs + (i - 1) * shdr_size;
1167fc4f4269Schristos sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1168fc4f4269Schristos shdr, sh_name, Elf_Word);
1169fc4f4269Schristos if (sh_name >= name_size)
1170fc4f4269Schristos {
1171fc4f4269Schristos *err = 0;
1172fc4f4269Schristos XDELETEVEC (names);
1173fc4f4269Schristos XDELETEVEC (shdrs);
1174fc4f4269Schristos return "ELF section name out of range";
1175fc4f4269Schristos }
1176fc4f4269Schristos
1177fc4f4269Schristos name = (const char *) names + sh_name;
1178fc4f4269Schristos
1179c1a20988Schristos ret = (*pfn) (name);
1180c1a20988Schristos pfnret[i - 1] = ret == NULL ? -1 : 0;
1181c1a20988Schristos pfnname[i - 1] = ret == NULL ? name : ret;
1182fc4f4269Schristos if (first_shndx == 0
1183fc4f4269Schristos && pfnret[i - 1] == 0)
1184fc4f4269Schristos first_shndx = i;
1185c1a20988Schristos
1186c1a20988Schristos /* Remember the indexes of existing SHT_SYMTAB_SHNDX sections. */
1187c1a20988Schristos sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1188c1a20988Schristos shdr, sh_type, Elf_Word);
1189c1a20988Schristos if (sh_type == SHT_SYMTAB_SHNDX)
1190c1a20988Schristos {
1191c1a20988Schristos unsigned int sh_link;
1192c1a20988Schristos sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1193c1a20988Schristos shdr, sh_link, Elf_Word);
11944f645668Schristos symtab_indices_shndx[sh_link - 1] = i - 1;
1195c1a20988Schristos /* Always discard the extended index sections, after
1196c1a20988Schristos copying it will not be needed. This way we don't need to
1197c1a20988Schristos update it and deal with the ordering constraints of
1198c1a20988Schristos processing the existing symtab and changing the index. */
1199c1a20988Schristos pfnret[i - 1] = -1;
1200c1a20988Schristos }
1201fc4f4269Schristos }
1202fc4f4269Schristos
1203fc4f4269Schristos /* Mark sections as preserved that are required by to be preserved
1204fc4f4269Schristos sections. */
1205fc4f4269Schristos do
1206fc4f4269Schristos {
1207fc4f4269Schristos changed = 0;
1208fc4f4269Schristos for (i = 1; i < shnum; ++i)
1209fc4f4269Schristos {
1210fc4f4269Schristos unsigned char *shdr;
1211fc4f4269Schristos unsigned int sh_type, sh_info, sh_link;
1212fc4f4269Schristos off_t offset;
1213fc4f4269Schristos off_t length;
1214fc4f4269Schristos
1215fc4f4269Schristos shdr = shdrs + (i - 1) * shdr_size;
1216fc4f4269Schristos sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1217fc4f4269Schristos shdr, sh_type, Elf_Word);
1218fc4f4269Schristos sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1219fc4f4269Schristos shdr, sh_info, Elf_Word);
1220fc4f4269Schristos sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1221fc4f4269Schristos shdr, sh_link, Elf_Word);
1222fc4f4269Schristos if (sh_type == SHT_GROUP)
1223fc4f4269Schristos {
1224fc4f4269Schristos /* Mark groups containing copied sections. */
1225fc4f4269Schristos unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class,
1226fc4f4269Schristos Shdr, shdr, sh_entsize,
1227fc4f4269Schristos Elf_Addr);
1228fc4f4269Schristos unsigned char *ent, *buf;
1229fc4f4269Schristos int keep = 0;
1230fc4f4269Schristos offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1231fc4f4269Schristos shdr, sh_offset, Elf_Addr);
1232fc4f4269Schristos length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1233fc4f4269Schristos shdr, sh_size, Elf_Addr);
1234fc4f4269Schristos buf = XNEWVEC (unsigned char, length);
1235fc4f4269Schristos if (!simple_object_internal_read (sobj->descriptor,
1236fc4f4269Schristos sobj->offset + offset, buf,
1237fc4f4269Schristos (size_t) length, &errmsg, err))
1238fc4f4269Schristos {
1239fc4f4269Schristos XDELETEVEC (buf);
1240fc4f4269Schristos XDELETEVEC (names);
1241fc4f4269Schristos XDELETEVEC (shdrs);
1242fc4f4269Schristos return errmsg;
1243fc4f4269Schristos }
1244fc4f4269Schristos for (ent = buf + entsize; ent < buf + length; ent += entsize)
1245fc4f4269Schristos {
1246fc4f4269Schristos unsigned sec = type_functions->fetch_Elf_Word (ent);
1247fc4f4269Schristos if (pfnret[sec - 1] == 0)
1248fc4f4269Schristos keep = 1;
1249fc4f4269Schristos }
1250fc4f4269Schristos if (keep)
1251fc4f4269Schristos {
1252fc4f4269Schristos changed |= (pfnret[sh_link - 1] == -1
1253fc4f4269Schristos || pfnret[i - 1] == -1);
1254fc4f4269Schristos pfnret[sh_link - 1] = 0;
1255fc4f4269Schristos pfnret[i - 1] = 0;
1256fc4f4269Schristos }
1257fc4f4269Schristos }
1258fc4f4269Schristos if (sh_type == SHT_RELA
1259fc4f4269Schristos || sh_type == SHT_REL)
1260fc4f4269Schristos {
1261fc4f4269Schristos /* Mark relocation sections and symtab of copied sections. */
1262fc4f4269Schristos if (pfnret[sh_info - 1] == 0)
1263fc4f4269Schristos {
1264fc4f4269Schristos changed |= (pfnret[sh_link - 1] == -1
1265fc4f4269Schristos || pfnret[i - 1] == -1);
1266fc4f4269Schristos pfnret[sh_link - 1] = 0;
1267fc4f4269Schristos pfnret[i - 1] = 0;
1268fc4f4269Schristos }
1269fc4f4269Schristos }
1270fc4f4269Schristos if (sh_type == SHT_SYMTAB)
1271fc4f4269Schristos {
1272fc4f4269Schristos /* Mark strings sections of copied symtabs. */
1273fc4f4269Schristos if (pfnret[i - 1] == 0)
1274fc4f4269Schristos {
1275fc4f4269Schristos changed |= pfnret[sh_link - 1] == -1;
1276fc4f4269Schristos pfnret[sh_link - 1] = 0;
1277fc4f4269Schristos }
1278fc4f4269Schristos }
1279fc4f4269Schristos }
1280fc4f4269Schristos }
1281fc4f4269Schristos while (changed);
1282fc4f4269Schristos
1283c1a20988Schristos /* Compute a mapping of old -> new section numbers. */
1284c1a20988Schristos sh_map = XNEWVEC (unsigned, shnum);
1285c1a20988Schristos sh_map[0] = 0;
1286c1a20988Schristos new_i = 1;
1287c1a20988Schristos for (i = 1; i < shnum; ++i)
1288c1a20988Schristos {
1289c1a20988Schristos if (pfnret[i - 1] == -1)
1290c1a20988Schristos sh_map[i] = 0;
1291c1a20988Schristos else
1292c1a20988Schristos sh_map[i] = new_i++;
1293c1a20988Schristos }
1294c1a20988Schristos if (new_i - 1 >= SHN_LORESERVE)
1295c1a20988Schristos {
1296c1a20988Schristos *err = ENOTSUP;
1297c1a20988Schristos return "Too many copied sections";
1298c1a20988Schristos }
1299c1a20988Schristos eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_i - 1));
1300c1a20988Schristos
1301fc4f4269Schristos /* Then perform the actual copying. */
1302c1a20988Schristos new_i = 0;
1303fc4f4269Schristos for (i = 1; i < shnum; ++i)
1304fc4f4269Schristos {
1305fc4f4269Schristos unsigned char *shdr;
1306fc4f4269Schristos unsigned int sh_name, sh_type;
1307fc4f4269Schristos const char *name;
1308fc4f4269Schristos off_t offset;
1309fc4f4269Schristos off_t length;
1310fc4f4269Schristos simple_object_write_section *dest;
1311fc4f4269Schristos off_t flags;
1312fc4f4269Schristos unsigned char *buf;
1313fc4f4269Schristos
1314c1a20988Schristos if (pfnret[i - 1])
1315c1a20988Schristos continue;
1316c1a20988Schristos
1317c1a20988Schristos new_i++;
1318fc4f4269Schristos shdr = shdrs + (i - 1) * shdr_size;
1319fc4f4269Schristos sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1320fc4f4269Schristos shdr, sh_name, Elf_Word);
1321fc4f4269Schristos if (sh_name >= name_size)
1322fc4f4269Schristos {
1323fc4f4269Schristos *err = 0;
1324fc4f4269Schristos XDELETEVEC (names);
1325fc4f4269Schristos XDELETEVEC (shdrs);
1326c1a20988Schristos XDELETEVEC (symtab_indices_shndx);
1327fc4f4269Schristos return "ELF section name out of range";
1328fc4f4269Schristos }
1329fc4f4269Schristos
1330c1a20988Schristos name = pfnname[i - 1];
1331fc4f4269Schristos offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1332fc4f4269Schristos shdr, sh_offset, Elf_Addr);
1333fc4f4269Schristos length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1334fc4f4269Schristos shdr, sh_size, Elf_Addr);
1335fc4f4269Schristos sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1336fc4f4269Schristos shdr, sh_type, Elf_Word);
1337fc4f4269Schristos
1338c1a20988Schristos dest = simple_object_write_create_section (dobj, pfnname[i - 1],
1339c1a20988Schristos 0, &errmsg, err);
1340fc4f4269Schristos if (dest == NULL)
1341fc4f4269Schristos {
1342fc4f4269Schristos XDELETEVEC (names);
1343fc4f4269Schristos XDELETEVEC (shdrs);
1344c1a20988Schristos XDELETEVEC (symtab_indices_shndx);
1345fc4f4269Schristos return errmsg;
1346fc4f4269Schristos }
1347fc4f4269Schristos
1348fc4f4269Schristos /* Record the SHDR of the source. */
1349c1a20988Schristos memcpy (eow->shdrs + (new_i - 1) * shdr_size, shdr, shdr_size);
1350c1a20988Schristos shdr = eow->shdrs + (new_i - 1) * shdr_size;
1351fc4f4269Schristos
1352fc4f4269Schristos /* Copy the data.
1353fc4f4269Schristos ??? This is quite wasteful and ideally would be delayed until
1354fc4f4269Schristos write_to_file (). Thus it questions the interfacing
1355fc4f4269Schristos which eventually should contain destination creation plus
1356fc4f4269Schristos writing. */
1357fc4f4269Schristos buf = XNEWVEC (unsigned char, length);
1358fc4f4269Schristos if (!simple_object_internal_read (sobj->descriptor,
1359fc4f4269Schristos sobj->offset + offset, buf,
1360fc4f4269Schristos (size_t) length, &errmsg, err))
1361fc4f4269Schristos {
1362fc4f4269Schristos XDELETEVEC (buf);
1363fc4f4269Schristos XDELETEVEC (names);
1364fc4f4269Schristos XDELETEVEC (shdrs);
1365c1a20988Schristos XDELETEVEC (symtab_indices_shndx);
1366fc4f4269Schristos return errmsg;
1367fc4f4269Schristos }
1368fc4f4269Schristos
13696f4ced0bSchristos /* If we are processing .symtab purge any symbols
13706f4ced0bSchristos in discarded sections. */
1371fc4f4269Schristos if (sh_type == SHT_SYMTAB)
1372fc4f4269Schristos {
1373fc4f4269Schristos unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1374fc4f4269Schristos shdr, sh_entsize, Elf_Addr);
13756f4ced0bSchristos size_t prevailing_name_idx = 0;
1376fc4f4269Schristos unsigned char *ent;
1377c1a20988Schristos unsigned *shndx_table = NULL;
1378c1a20988Schristos /* Read the section index table if present. */
1379c1a20988Schristos if (symtab_indices_shndx[i - 1] != 0)
1380c1a20988Schristos {
13814f645668Schristos unsigned char *sidxhdr = shdrs + symtab_indices_shndx[i - 1] * shdr_size;
1382c1a20988Schristos off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1383c1a20988Schristos sidxhdr, sh_offset, Elf_Addr);
1384c1a20988Schristos size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1385c1a20988Schristos sidxhdr, sh_size, Elf_Addr);
13864f645668Schristos unsigned int shndx_type
13874f645668Schristos = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
13884f645668Schristos sidxhdr, sh_type, Elf_Word);
13894f645668Schristos if (shndx_type != SHT_SYMTAB_SHNDX)
13904f645668Schristos return "Wrong section type of a SYMTAB SECTION INDICES section";
1391c1a20988Schristos shndx_table = (unsigned *)XNEWVEC (char, sidxsz);
1392c1a20988Schristos simple_object_internal_read (sobj->descriptor,
1393c1a20988Schristos sobj->offset + sidxoff,
1394c1a20988Schristos (unsigned char *)shndx_table,
1395c1a20988Schristos sidxsz, &errmsg, err);
1396c1a20988Schristos }
13976f4ced0bSchristos
13986f4ced0bSchristos /* Find a WEAK HIDDEN symbol which name we will use for removed
13996f4ced0bSchristos symbols. We know there's a prevailing weak hidden symbol
14006f4ced0bSchristos at the start of the .debug_info section. */
14016f4ced0bSchristos for (ent = buf; ent < buf + length; ent += entsize)
14026f4ced0bSchristos {
14036f4ced0bSchristos unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
14046f4ced0bSchristos Sym, ent,
14056f4ced0bSchristos st_shndx, Elf_Half);
14066f4ced0bSchristos unsigned char *st_info;
14076f4ced0bSchristos unsigned char *st_other;
14086f4ced0bSchristos if (ei_class == ELFCLASS32)
14096f4ced0bSchristos {
14106f4ced0bSchristos st_info = &((Elf32_External_Sym *)ent)->st_info;
14116f4ced0bSchristos st_other = &((Elf32_External_Sym *)ent)->st_other;
14126f4ced0bSchristos }
14136f4ced0bSchristos else
14146f4ced0bSchristos {
14156f4ced0bSchristos st_info = &((Elf64_External_Sym *)ent)->st_info;
14166f4ced0bSchristos st_other = &((Elf64_External_Sym *)ent)->st_other;
14176f4ced0bSchristos }
14186f4ced0bSchristos if (st_shndx == SHN_XINDEX)
14196f4ced0bSchristos st_shndx = type_functions->fetch_Elf_Word
14206f4ced0bSchristos ((unsigned char *)(shndx_table + (ent - buf) / entsize));
14216f4ced0bSchristos
14226f4ced0bSchristos if (st_shndx != SHN_COMMON
14236f4ced0bSchristos && !(st_shndx != SHN_UNDEF
14246f4ced0bSchristos && st_shndx < shnum
14256f4ced0bSchristos && pfnret[st_shndx - 1] == -1)
14266f4ced0bSchristos && ELF_ST_BIND (*st_info) == STB_WEAK
14276f4ced0bSchristos && *st_other == STV_HIDDEN)
14286f4ced0bSchristos {
14296f4ced0bSchristos prevailing_name_idx = ELF_FETCH_FIELD (type_functions,
14306f4ced0bSchristos ei_class, Sym, ent,
14316f4ced0bSchristos st_name, Elf_Word);
14326f4ced0bSchristos break;
14336f4ced0bSchristos }
14346f4ced0bSchristos }
14356f4ced0bSchristos
1436fc4f4269Schristos for (ent = buf; ent < buf + length; ent += entsize)
1437fc4f4269Schristos {
1438fc4f4269Schristos unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
1439fc4f4269Schristos Sym, ent,
1440fc4f4269Schristos st_shndx, Elf_Half);
1441c1a20988Schristos unsigned raw_st_shndx = st_shndx;
1442fc4f4269Schristos unsigned char *st_info;
1443fc4f4269Schristos unsigned char *st_other;
1444fc4f4269Schristos int discard = 0;
1445fc4f4269Schristos if (ei_class == ELFCLASS32)
1446fc4f4269Schristos {
1447fc4f4269Schristos st_info = &((Elf32_External_Sym *)ent)->st_info;
1448fc4f4269Schristos st_other = &((Elf32_External_Sym *)ent)->st_other;
1449fc4f4269Schristos }
1450fc4f4269Schristos else
1451fc4f4269Schristos {
1452fc4f4269Schristos st_info = &((Elf64_External_Sym *)ent)->st_info;
1453fc4f4269Schristos st_other = &((Elf64_External_Sym *)ent)->st_other;
1454fc4f4269Schristos }
1455c1a20988Schristos if (st_shndx == SHN_XINDEX)
1456c1a20988Schristos st_shndx = type_functions->fetch_Elf_Word
1457c1a20988Schristos ((unsigned char *)(shndx_table + (ent - buf) / entsize));
14586f4ced0bSchristos /* Eliminate all COMMONs - this includes __gnu_lto_slim
14596f4ced0bSchristos which otherwise cause endless LTO plugin invocation.
14606f4ced0bSchristos FIXME: remove the condition once we remove emission
14616f4ced0bSchristos of __gnu_lto_slim symbol. */
1462fc4f4269Schristos if (st_shndx == SHN_COMMON)
1463fc4f4269Schristos discard = 1;
1464fc4f4269Schristos /* We also need to remove symbols refering to sections
1465fc4f4269Schristos we'll eventually remove as with fat LTO objects
1466fc4f4269Schristos we otherwise get duplicate symbols at final link
1467fc4f4269Schristos (with GNU ld, gold is fine and ignores symbols in
1468fc4f4269Schristos sections marked as EXCLUDE). ld/20513 */
1469fc4f4269Schristos else if (st_shndx != SHN_UNDEF
1470fc4f4269Schristos && st_shndx < shnum
1471fc4f4269Schristos && pfnret[st_shndx - 1] == -1)
1472fc4f4269Schristos discard = 1;
14734f645668Schristos /* We also need to remove global UNDEFs which can
14744f645668Schristos cause link fails later. */
14754f645668Schristos else if (st_shndx == SHN_UNDEF
14764f645668Schristos && ELF_ST_BIND (*st_info) == STB_GLOBAL)
14774f645668Schristos discard = 1;
1478fc4f4269Schristos
1479fc4f4269Schristos if (discard)
1480fc4f4269Schristos {
1481fc4f4269Schristos /* Make discarded symbols undefined and unnamed
1482fc4f4269Schristos in case it is local. */
1483fc4f4269Schristos int bind = ELF_ST_BIND (*st_info);
1484fc4f4269Schristos int other = STV_DEFAULT;
1485fc4f4269Schristos if (bind == STB_LOCAL)
1486fc4f4269Schristos {
1487fc4f4269Schristos /* Make discarded local symbols unnamed and
1488fc4f4269Schristos defined in the first prevailing section. */
1489fc4f4269Schristos ELF_SET_FIELD (type_functions, ei_class, Sym,
1490fc4f4269Schristos ent, st_name, Elf_Word, 0);
1491fc4f4269Schristos ELF_SET_FIELD (type_functions, ei_class, Sym,
1492c1a20988Schristos ent, st_shndx, Elf_Half,
1493c1a20988Schristos sh_map[first_shndx]);
1494fc4f4269Schristos }
1495fc4f4269Schristos else
1496fc4f4269Schristos {
1497fc4f4269Schristos /* Make discarded global symbols hidden weak
14986f4ced0bSchristos undefined and sharing a name of a prevailing
14996f4ced0bSchristos symbol. */
1500fc4f4269Schristos bind = STB_WEAK;
1501fc4f4269Schristos other = STV_HIDDEN;
1502fc4f4269Schristos ELF_SET_FIELD (type_functions, ei_class, Sym,
1503fc4f4269Schristos ent, st_name, Elf_Word,
15046f4ced0bSchristos prevailing_name_idx);
1505fc4f4269Schristos ELF_SET_FIELD (type_functions, ei_class, Sym,
1506fc4f4269Schristos ent, st_shndx, Elf_Half, SHN_UNDEF);
1507fc4f4269Schristos }
1508fc4f4269Schristos *st_other = other;
1509fc4f4269Schristos *st_info = ELF_ST_INFO (bind, STT_NOTYPE);
1510fc4f4269Schristos ELF_SET_FIELD (type_functions, ei_class, Sym,
1511fc4f4269Schristos ent, st_value, Elf_Addr, 0);
1512fc4f4269Schristos ELF_SET_FIELD (type_functions, ei_class, Sym,
1513fc4f4269Schristos ent, st_size, Elf_Word, 0);
1514fc4f4269Schristos }
1515c1a20988Schristos else if (raw_st_shndx < SHN_LORESERVE
1516c1a20988Schristos || raw_st_shndx == SHN_XINDEX)
1517c1a20988Schristos /* Remap the section reference. */
1518c1a20988Schristos ELF_SET_FIELD (type_functions, ei_class, Sym,
1519c1a20988Schristos ent, st_shndx, Elf_Half, sh_map[st_shndx]);
1520fc4f4269Schristos }
1521c1a20988Schristos XDELETEVEC (shndx_table);
1522c1a20988Schristos }
1523c1a20988Schristos else if (sh_type == SHT_GROUP)
1524c1a20988Schristos {
1525c1a20988Schristos /* Remap section indices in groups and remove removed members. */
1526c1a20988Schristos unsigned char *ent, *dst;
1527c1a20988Schristos for (dst = ent = buf + 4; ent < buf + length; ent += 4)
1528c1a20988Schristos {
1529c1a20988Schristos unsigned shndx = type_functions->fetch_Elf_Word (ent);
1530c1a20988Schristos if (pfnret[shndx - 1] == -1)
1531c1a20988Schristos ;
1532c1a20988Schristos else
1533c1a20988Schristos {
1534c1a20988Schristos type_functions->set_Elf_Word (dst, sh_map[shndx]);
1535c1a20988Schristos dst += 4;
1536c1a20988Schristos }
1537c1a20988Schristos }
1538c1a20988Schristos /* Adjust the length. */
1539c1a20988Schristos length = dst - buf;
1540fc4f4269Schristos }
1541fc4f4269Schristos
1542fc4f4269Schristos errmsg = simple_object_write_add_data (dobj, dest,
1543fc4f4269Schristos buf, length, 1, err);
1544fc4f4269Schristos XDELETEVEC (buf);
1545fc4f4269Schristos if (errmsg)
1546fc4f4269Schristos {
1547fc4f4269Schristos XDELETEVEC (names);
1548fc4f4269Schristos XDELETEVEC (shdrs);
1549c1a20988Schristos XDELETEVEC (symtab_indices_shndx);
1550fc4f4269Schristos return errmsg;
1551fc4f4269Schristos }
1552fc4f4269Schristos
1553fc4f4269Schristos flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1554fc4f4269Schristos shdr, sh_flags, Elf_Addr);
1555c1a20988Schristos /* Remap the section references. */
1556fc4f4269Schristos {
1557c1a20988Schristos unsigned int sh_info, sh_link;
1558c1a20988Schristos if (flags & SHF_INFO_LINK || sh_type == SHT_REL || sh_type == SHT_RELA)
1559c1a20988Schristos {
1560c1a20988Schristos sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1561c1a20988Schristos shdr, sh_info, Elf_Word);
1562c1a20988Schristos sh_info = sh_map[sh_info];
1563c1a20988Schristos ELF_SET_FIELD (type_functions, ei_class, Shdr,
1564c1a20988Schristos shdr, sh_info, Elf_Word, sh_info);
1565c1a20988Schristos }
1566c1a20988Schristos sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1567c1a20988Schristos shdr, sh_link, Elf_Word);
1568c1a20988Schristos sh_link = sh_map[sh_link];
1569c1a20988Schristos ELF_SET_FIELD (type_functions, ei_class, Shdr,
1570c1a20988Schristos shdr, sh_link, Elf_Word, sh_link);
1571c1a20988Schristos }
1572fc4f4269Schristos /* The debugobj doesn't contain any code, thus no trampolines.
1573fc4f4269Schristos Even when the original object needs trampolines, debugobj
1574fc4f4269Schristos doesn't. */
1575fc4f4269Schristos if (strcmp (name, ".note.GNU-stack") == 0)
1576fc4f4269Schristos flags &= ~SHF_EXECINSTR;
1577c1a20988Schristos /* Clear SHF_EXCLUDE on to be preserved sections. */
1578fc4f4269Schristos flags &= ~SHF_EXCLUDE;
1579fc4f4269Schristos ELF_SET_FIELD (type_functions, ei_class, Shdr,
1580fc4f4269Schristos shdr, sh_flags, Elf_Addr, flags);
1581fc4f4269Schristos }
1582fc4f4269Schristos
1583fc4f4269Schristos XDELETEVEC (names);
1584fc4f4269Schristos XDELETEVEC (shdrs);
1585fc4f4269Schristos XDELETEVEC (pfnret);
1586fc4f4269Schristos XDELETEVEC (pfnname);
1587c1a20988Schristos XDELETEVEC (symtab_indices_shndx);
1588c1a20988Schristos XDELETEVEC (sh_map);
1589fc4f4269Schristos
1590fc4f4269Schristos return NULL;
1591fc4f4269Schristos }
1592fc4f4269Schristos
1593fc4f4269Schristos
1594be9ac0eaSchristos /* The ELF functions. */
1595be9ac0eaSchristos
1596be9ac0eaSchristos const struct simple_object_functions simple_object_elf_functions =
1597be9ac0eaSchristos {
1598be9ac0eaSchristos simple_object_elf_match,
1599be9ac0eaSchristos simple_object_elf_find_sections,
1600be9ac0eaSchristos simple_object_elf_fetch_attributes,
1601be9ac0eaSchristos simple_object_elf_release_read,
1602883529b6Schristos simple_object_elf_attributes_merge,
1603be9ac0eaSchristos simple_object_elf_release_attributes,
1604be9ac0eaSchristos simple_object_elf_start_write,
1605be9ac0eaSchristos simple_object_elf_write_to_file,
1606fc4f4269Schristos simple_object_elf_release_write,
1607fc4f4269Schristos simple_object_elf_copy_lto_debug_sections
1608be9ac0eaSchristos };
1609