xref: /netbsd-src/external/gpl3/binutils.old/dist/libiberty/simple-object-elf.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
116dce513Schristos /* simple-object-elf.c -- routines to manipulate ELF object files.
2*e992f068Schristos    Copyright (C) 2010-2022 Free Software Foundation, Inc.
316dce513Schristos    Written by Ian Lance Taylor, Google.
416dce513Schristos 
516dce513Schristos This program is free software; you can redistribute it and/or modify it
616dce513Schristos under the terms of the GNU General Public License as published by the
716dce513Schristos Free Software Foundation; either version 2, or (at your option) any
816dce513Schristos later version.
916dce513Schristos 
1016dce513Schristos This program is distributed in the hope that it will be useful,
1116dce513Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1216dce513Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1316dce513Schristos GNU General Public License for more details.
1416dce513Schristos 
1516dce513Schristos You should have received a copy of the GNU General Public License
1616dce513Schristos along with this program; if not, write to the Free Software
1716dce513Schristos Foundation, 51 Franklin Street - Fifth Floor,
1816dce513Schristos Boston, MA 02110-1301, USA.  */
1916dce513Schristos 
2016dce513Schristos #include "config.h"
2116dce513Schristos #include "libiberty.h"
2216dce513Schristos #include "simple-object.h"
2316dce513Schristos 
2416dce513Schristos #include <errno.h>
25012573ebSchristos /* mingw.org's MinGW doesn't have ENOTSUP.  */
26012573ebSchristos #ifndef ENOTSUP
27012573ebSchristos # define ENOTSUP ENOSYS
28012573ebSchristos #endif
2916dce513Schristos #include <stddef.h>
3016dce513Schristos 
3116dce513Schristos #ifdef HAVE_STDLIB_H
3216dce513Schristos #include <stdlib.h>
3316dce513Schristos #endif
3416dce513Schristos 
3516dce513Schristos #ifdef HAVE_STDINT_H
3616dce513Schristos #include <stdint.h>
3716dce513Schristos #endif
3816dce513Schristos 
3916dce513Schristos #ifdef HAVE_STRING_H
4016dce513Schristos #include <string.h>
4116dce513Schristos #endif
4216dce513Schristos 
4316dce513Schristos #ifdef HAVE_INTTYPES_H
4416dce513Schristos #include <inttypes.h>
4516dce513Schristos #endif
4616dce513Schristos 
4716dce513Schristos #include "simple-object-common.h"
4816dce513Schristos 
4916dce513Schristos /* ELF structures and constants.  */
5016dce513Schristos 
5116dce513Schristos /* 32-bit ELF file header.  */
5216dce513Schristos 
5316dce513Schristos typedef struct {
5416dce513Schristos   unsigned char	e_ident[16];		/* ELF "magic number" */
5516dce513Schristos   unsigned char	e_type[2];		/* Identifies object file type */
5616dce513Schristos   unsigned char	e_machine[2];		/* Specifies required architecture */
5716dce513Schristos   unsigned char	e_version[4];		/* Identifies object file version */
5816dce513Schristos   unsigned char	e_entry[4];		/* Entry point virtual address */
5916dce513Schristos   unsigned char	e_phoff[4];		/* Program header table file offset */
6016dce513Schristos   unsigned char	e_shoff[4];		/* Section header table file offset */
6116dce513Schristos   unsigned char	e_flags[4];		/* Processor-specific flags */
6216dce513Schristos   unsigned char	e_ehsize[2];		/* ELF header size in bytes */
6316dce513Schristos   unsigned char	e_phentsize[2];		/* Program header table entry size */
6416dce513Schristos   unsigned char	e_phnum[2];		/* Program header table entry count */
6516dce513Schristos   unsigned char	e_shentsize[2];		/* Section header table entry size */
6616dce513Schristos   unsigned char	e_shnum[2];		/* Section header table entry count */
6716dce513Schristos   unsigned char	e_shstrndx[2];		/* Section header string table index */
6816dce513Schristos } Elf32_External_Ehdr;
6916dce513Schristos 
7016dce513Schristos /* 64-bit ELF file header.  */
7116dce513Schristos 
7216dce513Schristos typedef struct {
7316dce513Schristos   unsigned char	e_ident[16];		/* ELF "magic number" */
7416dce513Schristos   unsigned char	e_type[2];		/* Identifies object file type */
7516dce513Schristos   unsigned char	e_machine[2];		/* Specifies required architecture */
7616dce513Schristos   unsigned char	e_version[4];		/* Identifies object file version */
7716dce513Schristos   unsigned char	e_entry[8];		/* Entry point virtual address */
7816dce513Schristos   unsigned char	e_phoff[8];		/* Program header table file offset */
7916dce513Schristos   unsigned char	e_shoff[8];		/* Section header table file offset */
8016dce513Schristos   unsigned char	e_flags[4];		/* Processor-specific flags */
8116dce513Schristos   unsigned char	e_ehsize[2];		/* ELF header size in bytes */
8216dce513Schristos   unsigned char	e_phentsize[2];		/* Program header table entry size */
8316dce513Schristos   unsigned char	e_phnum[2];		/* Program header table entry count */
8416dce513Schristos   unsigned char	e_shentsize[2];		/* Section header table entry size */
8516dce513Schristos   unsigned char	e_shnum[2];		/* Section header table entry count */
8616dce513Schristos   unsigned char	e_shstrndx[2];		/* Section header string table index */
8716dce513Schristos } Elf64_External_Ehdr;
8816dce513Schristos 
8916dce513Schristos /* Indexes and values in e_ident field of Ehdr.  */
9016dce513Schristos 
9116dce513Schristos #define EI_MAG0		0	/* File identification byte 0 index */
9216dce513Schristos #define ELFMAG0		   0x7F	/* Magic number byte 0 */
9316dce513Schristos 
9416dce513Schristos #define EI_MAG1		1	/* File identification byte 1 index */
9516dce513Schristos #define ELFMAG1		    'E'	/* Magic number byte 1 */
9616dce513Schristos 
9716dce513Schristos #define EI_MAG2		2	/* File identification byte 2 index */
9816dce513Schristos #define ELFMAG2		    'L'	/* Magic number byte 2 */
9916dce513Schristos 
10016dce513Schristos #define EI_MAG3		3	/* File identification byte 3 index */
10116dce513Schristos #define ELFMAG3		    'F'	/* Magic number byte 3 */
10216dce513Schristos 
10316dce513Schristos #define EI_CLASS	4	/* File class */
10416dce513Schristos #define ELFCLASSNONE	      0	/* Invalid class */
10516dce513Schristos #define ELFCLASS32	      1	/* 32-bit objects */
10616dce513Schristos #define ELFCLASS64	      2	/* 64-bit objects */
10716dce513Schristos 
10816dce513Schristos #define EI_DATA		5	/* Data encoding */
10916dce513Schristos #define ELFDATANONE	      0	/* Invalid data encoding */
11016dce513Schristos #define ELFDATA2LSB	      1	/* 2's complement, little endian */
11116dce513Schristos #define ELFDATA2MSB	      2	/* 2's complement, big endian */
11216dce513Schristos 
11316dce513Schristos #define EI_VERSION	6	/* File version */
11416dce513Schristos #define EV_CURRENT	1		/* Current version */
11516dce513Schristos 
11616dce513Schristos #define EI_OSABI	7	/* Operating System/ABI indication */
11716dce513Schristos 
11816dce513Schristos /* Values for e_type field of Ehdr.  */
11916dce513Schristos 
12016dce513Schristos #define ET_REL		1	/* Relocatable file */
12116dce513Schristos 
12216dce513Schristos /* Values for e_machine field of Ehdr.  */
12316dce513Schristos 
12416dce513Schristos #define EM_SPARC	  2	/* SUN SPARC */
12516dce513Schristos #define EM_SPARC32PLUS	 18	/* Sun's "v8plus" */
12616dce513Schristos 
12716dce513Schristos /* Special section index values.  */
12816dce513Schristos 
129ede78133Schristos #define SHN_UNDEF	0		/* Undefined section */
13016dce513Schristos #define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
131ede78133Schristos #define SHN_COMMON	0xFFF2	/* Associated symbol is in common */
13216dce513Schristos #define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
133ede78133Schristos #define SHN_HIRESERVE	0xffff		/* End of reserved indices */
134ede78133Schristos 
13516dce513Schristos 
13616dce513Schristos /* 32-bit ELF program header.  */
13716dce513Schristos 
13816dce513Schristos typedef struct {
13916dce513Schristos   unsigned char	p_type[4];		/* Identifies program segment type */
14016dce513Schristos   unsigned char	p_offset[4];		/* Segment file offset */
14116dce513Schristos   unsigned char	p_vaddr[4];		/* Segment virtual address */
14216dce513Schristos   unsigned char	p_paddr[4];		/* Segment physical address */
14316dce513Schristos   unsigned char	p_filesz[4];		/* Segment size in file */
14416dce513Schristos   unsigned char	p_memsz[4];		/* Segment size in memory */
14516dce513Schristos   unsigned char	p_flags[4];		/* Segment flags */
14616dce513Schristos   unsigned char	p_align[4];		/* Segment alignment, file & memory */
14716dce513Schristos } Elf32_External_Phdr;
14816dce513Schristos 
14916dce513Schristos /* 64-bit ELF program header.  */
15016dce513Schristos 
15116dce513Schristos typedef struct {
15216dce513Schristos   unsigned char	p_type[4];		/* Identifies program segment type */
15316dce513Schristos   unsigned char	p_flags[4];		/* Segment flags */
15416dce513Schristos   unsigned char	p_offset[8];		/* Segment file offset */
15516dce513Schristos   unsigned char	p_vaddr[8];		/* Segment virtual address */
15616dce513Schristos   unsigned char	p_paddr[8];		/* Segment physical address */
15716dce513Schristos   unsigned char	p_filesz[8];		/* Segment size in file */
15816dce513Schristos   unsigned char	p_memsz[8];		/* Segment size in memory */
15916dce513Schristos   unsigned char	p_align[8];		/* Segment alignment, file & memory */
16016dce513Schristos } Elf64_External_Phdr;
16116dce513Schristos 
16216dce513Schristos /* 32-bit ELF section header */
16316dce513Schristos 
16416dce513Schristos typedef struct {
16516dce513Schristos   unsigned char	sh_name[4];		/* Section name, index in string tbl */
16616dce513Schristos   unsigned char	sh_type[4];		/* Type of section */
16716dce513Schristos   unsigned char	sh_flags[4];		/* Miscellaneous section attributes */
16816dce513Schristos   unsigned char	sh_addr[4];		/* Section virtual addr at execution */
16916dce513Schristos   unsigned char	sh_offset[4];		/* Section file offset */
17016dce513Schristos   unsigned char	sh_size[4];		/* Size of section in bytes */
17116dce513Schristos   unsigned char	sh_link[4];		/* Index of another section */
17216dce513Schristos   unsigned char	sh_info[4];		/* Additional section information */
17316dce513Schristos   unsigned char	sh_addralign[4];	/* Section alignment */
17416dce513Schristos   unsigned char	sh_entsize[4];		/* Entry size if section holds table */
17516dce513Schristos } Elf32_External_Shdr;
17616dce513Schristos 
17716dce513Schristos /* 64-bit ELF section header.  */
17816dce513Schristos 
17916dce513Schristos typedef struct {
18016dce513Schristos   unsigned char	sh_name[4];		/* Section name, index in string tbl */
18116dce513Schristos   unsigned char	sh_type[4];		/* Type of section */
18216dce513Schristos   unsigned char	sh_flags[8];		/* Miscellaneous section attributes */
18316dce513Schristos   unsigned char	sh_addr[8];		/* Section virtual addr at execution */
18416dce513Schristos   unsigned char	sh_offset[8];		/* Section file offset */
18516dce513Schristos   unsigned char	sh_size[8];		/* Size of section in bytes */
18616dce513Schristos   unsigned char	sh_link[4];		/* Index of another section */
18716dce513Schristos   unsigned char	sh_info[4];		/* Additional section information */
18816dce513Schristos   unsigned char	sh_addralign[8];	/* Section alignment */
18916dce513Schristos   unsigned char	sh_entsize[8];		/* Entry size if section holds table */
19016dce513Schristos } Elf64_External_Shdr;
19116dce513Schristos 
19216dce513Schristos /* Values for sh_type field.  */
19316dce513Schristos 
194ede78133Schristos #define SHT_NULL	0		/* Section header table entry unused */
19516dce513Schristos #define SHT_PROGBITS	1		/* Program data */
196ede78133Schristos #define SHT_SYMTAB	2		/* Link editing symbol table */
19716dce513Schristos #define SHT_STRTAB	3		/* A string table */
198ede78133Schristos #define SHT_RELA	4		/* Relocation entries with addends */
199ede78133Schristos #define SHT_REL		9		/* Relocation entries, no addends */
200ede78133Schristos #define SHT_GROUP	17		/* Section contains a section group */
201ede78133Schristos #define SHT_SYMTAB_SHNDX 18		/* Extended section indeces */
202ede78133Schristos 
203ede78133Schristos /* Values for sh_flags field.  */
204ede78133Schristos 
205ede78133Schristos #define SHF_INFO_LINK	0x00000040	/* `sh_info' contains SHT index */
206ede78133Schristos #define SHF_EXECINSTR	0x00000004	/* Executable section.  */
207ede78133Schristos #define SHF_EXCLUDE	0x80000000	/* Link editor is to exclude this
208ede78133Schristos 					   section from executable and
209ede78133Schristos 					   shared library that it builds
210ede78133Schristos 					   when those objects are not to be
211ede78133Schristos 					   further relocated.  */
212ede78133Schristos /* Symbol table entry.  */
213ede78133Schristos 
214ede78133Schristos typedef struct
215ede78133Schristos {
216ede78133Schristos   unsigned char st_name[4];                /* Symbol name (string tbl index) */
217ede78133Schristos   unsigned char st_value[4];               /* Symbol value */
218ede78133Schristos   unsigned char st_size[4];                /* Symbol size */
219ede78133Schristos   unsigned char st_info;                /* Symbol type and binding */
220ede78133Schristos   unsigned char st_other;               /* Symbol visibility */
221ede78133Schristos   unsigned char st_shndx[2];               /* Section index */
222ede78133Schristos } Elf32_External_Sym;
223ede78133Schristos 
224ede78133Schristos typedef struct
225ede78133Schristos {
226ede78133Schristos   unsigned char st_name[4];                /* Symbol name (string tbl index) */
227ede78133Schristos   unsigned char st_info;                /* Symbol type and binding */
228ede78133Schristos   unsigned char st_other;               /* Symbol visibility */
229ede78133Schristos   unsigned char st_shndx[2];               /* Section index */
230ede78133Schristos   unsigned char st_value[8];               /* Symbol value */
231ede78133Schristos   unsigned char st_size[8];                /* Symbol size */
232ede78133Schristos } Elf64_External_Sym;
233ede78133Schristos 
234ede78133Schristos #define ELF_ST_BIND(val)              (((unsigned char) (val)) >> 4)
235ede78133Schristos #define ELF_ST_TYPE(val)              ((val) & 0xf)
236ede78133Schristos #define ELF_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
237ede78133Schristos 
238ede78133Schristos #define STT_NOTYPE	0	/* Symbol type is unspecified */
239ede78133Schristos #define STT_OBJECT	1	/* Symbol is a data object */
240ede78133Schristos #define STT_FUNC	2	/* Symbol is a code object */
241ede78133Schristos #define STT_TLS		6	/* Thread local data object */
242ede78133Schristos #define STT_GNU_IFUNC	10	/* Symbol is an indirect code object */
243ede78133Schristos 
244ede78133Schristos #define STB_LOCAL	0	/* Local symbol */
245ede78133Schristos #define STB_GLOBAL	1	/* Global symbol */
246ede78133Schristos #define STB_WEAK	2	/* Weak global */
247ede78133Schristos 
248ede78133Schristos #define STV_DEFAULT	0	/* Visibility is specified by binding type */
249ede78133Schristos #define STV_HIDDEN	2	/* Can only be seen inside currect component */
25016dce513Schristos 
25116dce513Schristos /* Functions to fetch and store different ELF types, depending on the
25216dce513Schristos    endianness and size.  */
25316dce513Schristos 
25416dce513Schristos struct elf_type_functions
25516dce513Schristos {
25616dce513Schristos   unsigned short (*fetch_Elf_Half) (const unsigned char *);
25716dce513Schristos   unsigned int (*fetch_Elf_Word) (const unsigned char *);
25816dce513Schristos   ulong_type (*fetch_Elf_Addr) (const unsigned char *);
25916dce513Schristos   void (*set_Elf_Half) (unsigned char *, unsigned short);
26016dce513Schristos   void (*set_Elf_Word) (unsigned char *, unsigned int);
26116dce513Schristos   void (*set_Elf_Addr) (unsigned char *, ulong_type);
26216dce513Schristos };
26316dce513Schristos 
26416dce513Schristos static const struct elf_type_functions elf_big_32_functions =
26516dce513Schristos {
26616dce513Schristos   simple_object_fetch_big_16,
26716dce513Schristos   simple_object_fetch_big_32,
26816dce513Schristos   simple_object_fetch_big_32_ulong,
26916dce513Schristos   simple_object_set_big_16,
27016dce513Schristos   simple_object_set_big_32,
27116dce513Schristos   simple_object_set_big_32_ulong
27216dce513Schristos };
27316dce513Schristos 
27416dce513Schristos static const struct elf_type_functions elf_little_32_functions =
27516dce513Schristos {
27616dce513Schristos   simple_object_fetch_little_16,
27716dce513Schristos   simple_object_fetch_little_32,
27816dce513Schristos   simple_object_fetch_little_32_ulong,
27916dce513Schristos   simple_object_set_little_16,
28016dce513Schristos   simple_object_set_little_32,
28116dce513Schristos   simple_object_set_little_32_ulong
28216dce513Schristos };
28316dce513Schristos 
28416dce513Schristos #ifdef UNSIGNED_64BIT_TYPE
28516dce513Schristos 
28616dce513Schristos static const struct elf_type_functions elf_big_64_functions =
28716dce513Schristos {
28816dce513Schristos   simple_object_fetch_big_16,
28916dce513Schristos   simple_object_fetch_big_32,
29016dce513Schristos   simple_object_fetch_big_64,
29116dce513Schristos   simple_object_set_big_16,
29216dce513Schristos   simple_object_set_big_32,
29316dce513Schristos   simple_object_set_big_64
29416dce513Schristos };
29516dce513Schristos 
29616dce513Schristos static const struct elf_type_functions elf_little_64_functions =
29716dce513Schristos {
29816dce513Schristos   simple_object_fetch_little_16,
29916dce513Schristos   simple_object_fetch_little_32,
30016dce513Schristos   simple_object_fetch_little_64,
30116dce513Schristos   simple_object_set_little_16,
30216dce513Schristos   simple_object_set_little_32,
30316dce513Schristos   simple_object_set_little_64
30416dce513Schristos };
30516dce513Schristos 
30616dce513Schristos #endif
30716dce513Schristos 
30816dce513Schristos /* Hideous macro to fetch the value of a field from an external ELF
30916dce513Schristos    struct of some sort.  TYPEFUNCS is the set of type functions.
31016dce513Schristos    BUFFER points to the external data.  STRUCTTYPE is the appropriate
31116dce513Schristos    struct type.  FIELD is a field within the struct.  TYPE is the type
31216dce513Schristos    of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr.  */
31316dce513Schristos 
31416dce513Schristos #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
31516dce513Schristos   ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
31616dce513Schristos 
31716dce513Schristos /* Even more hideous macro to fetch the value of FIELD from BUFFER.
31816dce513Schristos    SIZE is 32 or 64.  STRUCTTYPE is the name of the struct from
31916dce513Schristos    elf/external.h: Ehdr, Shdr, etc.  FIELD is the name of a field in
32016dce513Schristos    the struct.  TYPE is the type of the field in the struct: Elf_Half,
32116dce513Schristos    Elf_Word, or Elf_Addr.  */
32216dce513Schristos 
32316dce513Schristos #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER,	\
32416dce513Schristos 			      FIELD, TYPE)				\
32516dce513Schristos   ELF_FETCH_STRUCT_FIELD (TYPEFUNCS,					\
32616dce513Schristos 			  Elf ## SIZE ## _External_ ## STRUCTTYPE,	\
32716dce513Schristos 			  FIELD, BUFFER, TYPE)
32816dce513Schristos 
32916dce513Schristos /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value.  */
33016dce513Schristos 
33116dce513Schristos #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER,		\
33216dce513Schristos 			FIELD, TYPE)					\
33316dce513Schristos   ((CLASS) == ELFCLASS32						\
33416dce513Schristos     ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,	\
33516dce513Schristos 			     TYPE)					\
33616dce513Schristos     : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,	\
33716dce513Schristos 			     TYPE))
33816dce513Schristos 
33916dce513Schristos /* Hideous macro to set the value of a field in an external ELF
34016dce513Schristos    structure to VAL.  TYPEFUNCS is the set of type functions.  BUFFER
34116dce513Schristos    points to the external data.  STRUCTTYPE is the appropriate
34216dce513Schristos    structure type.  FIELD is a field within the struct.  TYPE is the
34316dce513Schristos    type of the field in the struct: Elf_Half, Elf_Word, or
34416dce513Schristos    Elf_Addr.  */
34516dce513Schristos 
34616dce513Schristos #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
34716dce513Schristos   (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
34816dce513Schristos 
34916dce513Schristos /* Even more hideous macro to set the value of FIELD in BUFFER to VAL.
35016dce513Schristos    SIZE is 32 or 64.  STRUCTTYPE is the name of the struct from
35116dce513Schristos    elf/external.h: Ehdr, Shdr, etc.  FIELD is the name of a field in
35216dce513Schristos    the struct.  TYPE is the type of the field in the struct: Elf_Half,
35316dce513Schristos    Elf_Word, or Elf_Addr.  */
35416dce513Schristos 
35516dce513Schristos #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
35616dce513Schristos 			    TYPE, VAL)					\
35716dce513Schristos   ELF_SET_STRUCT_FIELD (TYPEFUNCS,					\
35816dce513Schristos 			Elf ## SIZE ## _External_ ## STRUCTTYPE,	\
35916dce513Schristos 			FIELD, BUFFER, TYPE, VAL)
36016dce513Schristos 
36116dce513Schristos /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value.  */
36216dce513Schristos 
36316dce513Schristos #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD,	\
36416dce513Schristos 		      TYPE, VAL)					\
36516dce513Schristos   ((CLASS) == ELFCLASS32						\
36616dce513Schristos     ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,	\
36716dce513Schristos 			   TYPE, VAL)					\
36816dce513Schristos     : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,	\
36916dce513Schristos 			   TYPE, VAL))
37016dce513Schristos 
37116dce513Schristos /* Private data for an simple_object_read.  */
37216dce513Schristos 
37316dce513Schristos struct simple_object_elf_read
37416dce513Schristos {
37516dce513Schristos   /* Type functions.  */
37616dce513Schristos   const struct elf_type_functions* type_functions;
37716dce513Schristos   /* Elf data.  */
37816dce513Schristos   unsigned char ei_data;
37916dce513Schristos   /* Elf class.  */
38016dce513Schristos   unsigned char ei_class;
38116dce513Schristos   /* ELF OS ABI.  */
38216dce513Schristos   unsigned char ei_osabi;
38316dce513Schristos   /* Elf machine number.  */
38416dce513Schristos   unsigned short machine;
38516dce513Schristos   /* Processor specific flags.  */
38616dce513Schristos   unsigned int flags;
38716dce513Schristos   /* File offset of section headers.  */
38816dce513Schristos   ulong_type shoff;
38916dce513Schristos   /* Number of sections.  */
39016dce513Schristos   unsigned int shnum;
39116dce513Schristos   /* Index of string table section header.  */
39216dce513Schristos   unsigned int shstrndx;
39316dce513Schristos };
39416dce513Schristos 
39516dce513Schristos /* Private data for an simple_object_attributes.  */
39616dce513Schristos 
39716dce513Schristos struct simple_object_elf_attributes
39816dce513Schristos {
39916dce513Schristos   /* Type functions.  */
40016dce513Schristos   const struct elf_type_functions* type_functions;
40116dce513Schristos   /* Elf data.  */
40216dce513Schristos   unsigned char ei_data;
40316dce513Schristos   /* Elf class.  */
40416dce513Schristos   unsigned char ei_class;
40516dce513Schristos   /* ELF OS ABI.  */
40616dce513Schristos   unsigned char ei_osabi;
40716dce513Schristos   /* Elf machine number.  */
40816dce513Schristos   unsigned short machine;
40916dce513Schristos   /* Processor specific flags.  */
41016dce513Schristos   unsigned int flags;
41116dce513Schristos };
41216dce513Schristos 
413ede78133Schristos /* Private data for an simple_object_write.  */
414ede78133Schristos 
415ede78133Schristos struct simple_object_elf_write
416ede78133Schristos {
417ede78133Schristos   struct simple_object_elf_attributes attrs;
418ede78133Schristos   unsigned char *shdrs;
419ede78133Schristos };
420ede78133Schristos 
42116dce513Schristos /* See if we have an ELF file.  */
42216dce513Schristos 
42316dce513Schristos 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)42416dce513Schristos simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
42516dce513Schristos 			 int descriptor, off_t offset,
42616dce513Schristos 			 const char *segment_name ATTRIBUTE_UNUSED,
42716dce513Schristos 			 const char **errmsg, int *err)
42816dce513Schristos {
42916dce513Schristos   unsigned char ei_data;
43016dce513Schristos   unsigned char ei_class;
43116dce513Schristos   const struct elf_type_functions *type_functions;
43216dce513Schristos   unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
43316dce513Schristos   struct simple_object_elf_read *eor;
43416dce513Schristos 
43516dce513Schristos   if (header[EI_MAG0] != ELFMAG0
43616dce513Schristos       || header[EI_MAG1] != ELFMAG1
43716dce513Schristos       || header[EI_MAG2] != ELFMAG2
43816dce513Schristos       || header[EI_MAG3] != ELFMAG3
43916dce513Schristos       || header[EI_VERSION] != EV_CURRENT)
44016dce513Schristos     {
44116dce513Schristos       *errmsg = NULL;
44216dce513Schristos       *err = 0;
44316dce513Schristos       return NULL;
44416dce513Schristos     }
44516dce513Schristos 
44616dce513Schristos   ei_data = header[EI_DATA];
44716dce513Schristos   if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
44816dce513Schristos     {
44916dce513Schristos       *errmsg = "unknown ELF endianness";
45016dce513Schristos       *err = 0;
45116dce513Schristos       return NULL;
45216dce513Schristos     }
45316dce513Schristos 
45416dce513Schristos   ei_class = header[EI_CLASS];
45516dce513Schristos   switch (ei_class)
45616dce513Schristos     {
45716dce513Schristos     case ELFCLASS32:
45816dce513Schristos       type_functions = (ei_data == ELFDATA2LSB
45916dce513Schristos 			? &elf_little_32_functions
46016dce513Schristos 			: &elf_big_32_functions);
46116dce513Schristos       break;
46216dce513Schristos 
46316dce513Schristos     case ELFCLASS64:
46416dce513Schristos #ifndef UNSIGNED_64BIT_TYPE
46516dce513Schristos       *errmsg = "64-bit ELF objects not supported";
46616dce513Schristos       *err = 0;
46716dce513Schristos       return NULL;
46816dce513Schristos #else
46916dce513Schristos       type_functions = (ei_data == ELFDATA2LSB
47016dce513Schristos 			? &elf_little_64_functions
47116dce513Schristos 			: &elf_big_64_functions);
47216dce513Schristos       break;
47316dce513Schristos #endif
47416dce513Schristos 
47516dce513Schristos     default:
47616dce513Schristos       *errmsg = "unrecognized ELF size";
47716dce513Schristos       *err = 0;
47816dce513Schristos       return NULL;
47916dce513Schristos     }
48016dce513Schristos 
48116dce513Schristos   if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr,
48216dce513Schristos 				    errmsg, err))
48316dce513Schristos     return NULL;
48416dce513Schristos 
48516dce513Schristos   eor = XNEW (struct simple_object_elf_read);
48616dce513Schristos   eor->type_functions = type_functions;
48716dce513Schristos   eor->ei_data = ei_data;
48816dce513Schristos   eor->ei_class = ei_class;
48916dce513Schristos   eor->ei_osabi = header[EI_OSABI];
49016dce513Schristos   eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
49116dce513Schristos 				  e_machine, Elf_Half);
49216dce513Schristos   eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
49316dce513Schristos 				e_flags, Elf_Word);
49416dce513Schristos   eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
49516dce513Schristos 				e_shoff, Elf_Addr);
49616dce513Schristos   eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
49716dce513Schristos 				e_shnum, Elf_Half);
49816dce513Schristos   eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
49916dce513Schristos 				   e_shstrndx, Elf_Half);
50016dce513Schristos 
50116dce513Schristos   if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
50216dce513Schristos       && eor->shoff != 0)
50316dce513Schristos     {
50416dce513Schristos       unsigned char shdr[sizeof (Elf64_External_Shdr)];
50516dce513Schristos 
50616dce513Schristos       /* Object file has more than 0xffff sections.  */
50716dce513Schristos 
50816dce513Schristos       if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr,
50916dce513Schristos 					(ei_class == ELFCLASS32
51016dce513Schristos 					 ? sizeof (Elf32_External_Shdr)
51116dce513Schristos 					 : sizeof (Elf64_External_Shdr)),
51216dce513Schristos 					errmsg, err))
51316dce513Schristos 	{
51416dce513Schristos 	  XDELETE (eor);
51516dce513Schristos 	  return NULL;
51616dce513Schristos 	}
51716dce513Schristos 
51816dce513Schristos       if (eor->shnum == 0)
51916dce513Schristos 	eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
52016dce513Schristos 				      shdr, sh_size, Elf_Addr);
52116dce513Schristos 
52216dce513Schristos       if (eor->shstrndx == SHN_XINDEX)
52316dce513Schristos 	{
52416dce513Schristos 	  eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
52516dce513Schristos 					   shdr, sh_link, Elf_Word);
52616dce513Schristos 
52716dce513Schristos 	  /* Versions of the GNU binutils between 2.12 and 2.18 did
52816dce513Schristos 	     not handle objects with more than SHN_LORESERVE sections
52916dce513Schristos 	     correctly.  All large section indexes were offset by
53016dce513Schristos 	     0x100.  There is more information at
531*e992f068Schristos 	     https://sourceware.org/PR5900 .
53216dce513Schristos 	     Fortunately these object files are easy to detect, as the
53316dce513Schristos 	     GNU binutils always put the section header string table
53416dce513Schristos 	     near the end of the list of sections.  Thus if the
53516dce513Schristos 	     section header string table index is larger than the
53616dce513Schristos 	     number of sections, then we know we have to subtract
53716dce513Schristos 	     0x100 to get the real section index.  */
53816dce513Schristos 	  if (eor->shstrndx >= eor->shnum
53916dce513Schristos 	      && eor->shstrndx >= SHN_LORESERVE + 0x100)
54016dce513Schristos 	    eor->shstrndx -= 0x100;
54116dce513Schristos 	}
54216dce513Schristos     }
54316dce513Schristos 
54416dce513Schristos   if (eor->shstrndx >= eor->shnum)
54516dce513Schristos     {
54616dce513Schristos       *errmsg = "invalid ELF shstrndx >= shnum";
54716dce513Schristos       *err = 0;
54816dce513Schristos       XDELETE (eor);
54916dce513Schristos       return NULL;
55016dce513Schristos     }
55116dce513Schristos 
552012573ebSchristos   if (eor->shstrndx == 0)
553012573ebSchristos     {
554012573ebSchristos       *errmsg = "invalid ELF shstrndx == 0";
555012573ebSchristos       *err = 0;
556012573ebSchristos       XDELETE (eor);
557012573ebSchristos       return NULL;
558012573ebSchristos     }
559012573ebSchristos 
56016dce513Schristos   return (void *) eor;
56116dce513Schristos }
56216dce513Schristos 
56316dce513Schristos /* Find all sections in an ELF file.  */
56416dce513Schristos 
56516dce513Schristos 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)56616dce513Schristos simple_object_elf_find_sections (simple_object_read *sobj,
56716dce513Schristos 				 int (*pfn) (void *, const char *,
56816dce513Schristos 					     off_t offset, off_t length),
56916dce513Schristos 				 void *data,
57016dce513Schristos 				 int *err)
57116dce513Schristos {
57216dce513Schristos   struct simple_object_elf_read *eor =
57316dce513Schristos     (struct simple_object_elf_read *) sobj->data;
57416dce513Schristos   const struct elf_type_functions *type_functions = eor->type_functions;
57516dce513Schristos   unsigned char ei_class = eor->ei_class;
57616dce513Schristos   size_t shdr_size;
57716dce513Schristos   unsigned int shnum;
57816dce513Schristos   unsigned char *shdrs;
57916dce513Schristos   const char *errmsg;
58016dce513Schristos   unsigned char *shstrhdr;
58116dce513Schristos   size_t name_size;
58216dce513Schristos   off_t shstroff;
58316dce513Schristos   unsigned char *names;
58416dce513Schristos   unsigned int i;
58516dce513Schristos 
58616dce513Schristos   shdr_size = (ei_class == ELFCLASS32
58716dce513Schristos 	       ? sizeof (Elf32_External_Shdr)
58816dce513Schristos 	       : sizeof (Elf64_External_Shdr));
58916dce513Schristos 
59016dce513Schristos   /* Read the section headers.  We skip section 0, which is not a
59116dce513Schristos      useful section.  */
59216dce513Schristos 
59316dce513Schristos   shnum = eor->shnum;
59416dce513Schristos   shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
59516dce513Schristos 
59616dce513Schristos   if (!simple_object_internal_read (sobj->descriptor,
59716dce513Schristos 				    sobj->offset + eor->shoff + shdr_size,
59816dce513Schristos 				    shdrs,
59916dce513Schristos 				    shdr_size * (shnum - 1),
60016dce513Schristos 				    &errmsg, err))
60116dce513Schristos     {
60216dce513Schristos       XDELETEVEC (shdrs);
60316dce513Schristos       return errmsg;
60416dce513Schristos     }
60516dce513Schristos 
60616dce513Schristos   /* Read the section names.  */
60716dce513Schristos 
60816dce513Schristos   shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
60916dce513Schristos   name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
61016dce513Schristos 			       shstrhdr, sh_size, Elf_Addr);
61116dce513Schristos   shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
61216dce513Schristos 			      shstrhdr, sh_offset, Elf_Addr);
61316dce513Schristos   names = XNEWVEC (unsigned char, name_size);
61416dce513Schristos   if (!simple_object_internal_read (sobj->descriptor,
61516dce513Schristos 				    sobj->offset + shstroff,
61616dce513Schristos 				    names, name_size, &errmsg, err))
61716dce513Schristos     {
61816dce513Schristos       XDELETEVEC (names);
61916dce513Schristos       XDELETEVEC (shdrs);
62016dce513Schristos       return errmsg;
62116dce513Schristos     }
62216dce513Schristos 
62316dce513Schristos   for (i = 1; i < shnum; ++i)
62416dce513Schristos     {
62516dce513Schristos       unsigned char *shdr;
62616dce513Schristos       unsigned int sh_name;
62716dce513Schristos       const char *name;
62816dce513Schristos       off_t offset;
62916dce513Schristos       off_t length;
63016dce513Schristos 
63116dce513Schristos       shdr = shdrs + (i - 1) * shdr_size;
63216dce513Schristos       sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
63316dce513Schristos 				 shdr, sh_name, Elf_Word);
63416dce513Schristos       if (sh_name >= name_size)
63516dce513Schristos 	{
63616dce513Schristos 	  *err = 0;
63716dce513Schristos 	  XDELETEVEC (names);
63816dce513Schristos 	  XDELETEVEC (shdrs);
63916dce513Schristos 	  return "ELF section name out of range";
64016dce513Schristos 	}
64116dce513Schristos 
64216dce513Schristos       name = (const char *) names + sh_name;
64316dce513Schristos       offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
64416dce513Schristos 				shdr, sh_offset, Elf_Addr);
64516dce513Schristos       length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
64616dce513Schristos 				shdr, sh_size, Elf_Addr);
64716dce513Schristos 
64816dce513Schristos       if (!(*pfn) (data, name, offset, length))
64916dce513Schristos 	break;
65016dce513Schristos     }
65116dce513Schristos 
65216dce513Schristos   XDELETEVEC (names);
65316dce513Schristos   XDELETEVEC (shdrs);
65416dce513Schristos 
65516dce513Schristos   return NULL;
65616dce513Schristos }
65716dce513Schristos 
65816dce513Schristos /* Fetch the attributes for an simple_object_read.  */
65916dce513Schristos 
66016dce513Schristos static void *
simple_object_elf_fetch_attributes(simple_object_read * sobj,const char ** errmsg ATTRIBUTE_UNUSED,int * err ATTRIBUTE_UNUSED)66116dce513Schristos simple_object_elf_fetch_attributes (simple_object_read *sobj,
66216dce513Schristos 				    const char **errmsg ATTRIBUTE_UNUSED,
66316dce513Schristos 				    int *err ATTRIBUTE_UNUSED)
66416dce513Schristos {
66516dce513Schristos   struct simple_object_elf_read *eor =
66616dce513Schristos     (struct simple_object_elf_read *) sobj->data;
66716dce513Schristos   struct simple_object_elf_attributes *ret;
66816dce513Schristos 
66916dce513Schristos   ret = XNEW (struct simple_object_elf_attributes);
67016dce513Schristos   ret->type_functions = eor->type_functions;
67116dce513Schristos   ret->ei_data = eor->ei_data;
67216dce513Schristos   ret->ei_class = eor->ei_class;
67316dce513Schristos   ret->ei_osabi = eor->ei_osabi;
67416dce513Schristos   ret->machine = eor->machine;
67516dce513Schristos   ret->flags = eor->flags;
67616dce513Schristos   return ret;
67716dce513Schristos }
67816dce513Schristos 
67916dce513Schristos /* Release the privata data for an simple_object_read.  */
68016dce513Schristos 
68116dce513Schristos static void
simple_object_elf_release_read(void * data)68216dce513Schristos simple_object_elf_release_read (void *data)
68316dce513Schristos {
68416dce513Schristos   XDELETE (data);
68516dce513Schristos }
68616dce513Schristos 
68716dce513Schristos /* Compare two attributes structures.  */
68816dce513Schristos 
68916dce513Schristos static const char *
simple_object_elf_attributes_merge(void * todata,void * fromdata,int * err)69016dce513Schristos simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
69116dce513Schristos {
69216dce513Schristos   struct simple_object_elf_attributes *to =
69316dce513Schristos     (struct simple_object_elf_attributes *) todata;
69416dce513Schristos   struct simple_object_elf_attributes *from =
69516dce513Schristos     (struct simple_object_elf_attributes *) fromdata;
69616dce513Schristos 
69716dce513Schristos   if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
69816dce513Schristos     {
69916dce513Schristos       *err = 0;
70016dce513Schristos       return "ELF object format mismatch";
70116dce513Schristos     }
70216dce513Schristos 
70316dce513Schristos   if (to->machine != from->machine)
70416dce513Schristos     {
70516dce513Schristos       int ok;
70616dce513Schristos 
70716dce513Schristos       /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
70816dce513Schristos 	 output of EM_SPARC32PLUS.  */
70916dce513Schristos       ok = 0;
71016dce513Schristos       switch (to->machine)
71116dce513Schristos 	{
71216dce513Schristos 	case EM_SPARC:
71316dce513Schristos 	  if (from->machine == EM_SPARC32PLUS)
71416dce513Schristos 	    {
71516dce513Schristos 	      to->machine = from->machine;
71616dce513Schristos 	      ok = 1;
71716dce513Schristos 	    }
71816dce513Schristos 	  break;
71916dce513Schristos 
72016dce513Schristos 	case EM_SPARC32PLUS:
72116dce513Schristos 	  if (from->machine == EM_SPARC)
72216dce513Schristos 	    ok = 1;
72316dce513Schristos 	  break;
72416dce513Schristos 
72516dce513Schristos 	default:
72616dce513Schristos 	  break;
72716dce513Schristos 	}
72816dce513Schristos 
72916dce513Schristos       if (!ok)
73016dce513Schristos 	{
73116dce513Schristos 	  *err = 0;
73216dce513Schristos 	  return "ELF machine number mismatch";
73316dce513Schristos 	}
73416dce513Schristos     }
73516dce513Schristos 
73616dce513Schristos   return NULL;
73716dce513Schristos }
73816dce513Schristos 
73916dce513Schristos /* Release the private data for an attributes structure.  */
74016dce513Schristos 
74116dce513Schristos static void
simple_object_elf_release_attributes(void * data)74216dce513Schristos simple_object_elf_release_attributes (void *data)
74316dce513Schristos {
74416dce513Schristos   XDELETE (data);
74516dce513Schristos }
74616dce513Schristos 
74716dce513Schristos /* Prepare to write out a file.  */
74816dce513Schristos 
74916dce513Schristos static void *
simple_object_elf_start_write(void * attributes_data,const char ** errmsg ATTRIBUTE_UNUSED,int * err ATTRIBUTE_UNUSED)75016dce513Schristos simple_object_elf_start_write (void *attributes_data,
75116dce513Schristos 			       const char **errmsg ATTRIBUTE_UNUSED,
75216dce513Schristos 			       int *err ATTRIBUTE_UNUSED)
75316dce513Schristos {
75416dce513Schristos   struct simple_object_elf_attributes *attrs =
75516dce513Schristos     (struct simple_object_elf_attributes *) attributes_data;
756ede78133Schristos   struct simple_object_elf_write *ret;
75716dce513Schristos 
75816dce513Schristos   /* We're just going to record the attributes, but we need to make a
75916dce513Schristos      copy because the user may delete them.  */
760ede78133Schristos   ret = XNEW (struct simple_object_elf_write);
761ede78133Schristos   ret->attrs = *attrs;
762ede78133Schristos   ret->shdrs = NULL;
76316dce513Schristos   return ret;
76416dce513Schristos }
76516dce513Schristos 
76616dce513Schristos /* Write out an ELF ehdr.  */
76716dce513Schristos 
76816dce513Schristos static int
simple_object_elf_write_ehdr(simple_object_write * sobj,int descriptor,const char ** errmsg,int * err)76916dce513Schristos simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
77016dce513Schristos 			      const char **errmsg, int *err)
77116dce513Schristos {
77216dce513Schristos   struct simple_object_elf_attributes *attrs =
77316dce513Schristos     (struct simple_object_elf_attributes *) sobj->data;
77416dce513Schristos   const struct elf_type_functions* fns;
77516dce513Schristos   unsigned char cl;
77616dce513Schristos   size_t ehdr_size;
77716dce513Schristos   unsigned char buf[sizeof (Elf64_External_Ehdr)];
77816dce513Schristos   simple_object_write_section *section;
77916dce513Schristos   unsigned int shnum;
78016dce513Schristos   unsigned int shstrndx;
78116dce513Schristos 
78216dce513Schristos   fns = attrs->type_functions;
78316dce513Schristos   cl = attrs->ei_class;
78416dce513Schristos 
78516dce513Schristos   shnum = 0;
78616dce513Schristos   for (section = sobj->sections; section != NULL; section = section->next)
78716dce513Schristos     ++shnum;
78816dce513Schristos   if (shnum > 0)
78916dce513Schristos     {
79016dce513Schristos       /* Add a section header for the dummy section and one for
79116dce513Schristos 	 .shstrtab.  */
79216dce513Schristos       shnum += 2;
79316dce513Schristos     }
79416dce513Schristos 
79516dce513Schristos   ehdr_size = (cl == ELFCLASS32
79616dce513Schristos 	       ? sizeof (Elf32_External_Ehdr)
79716dce513Schristos 	       : sizeof (Elf64_External_Ehdr));
79816dce513Schristos   memset (buf, 0, sizeof (Elf64_External_Ehdr));
79916dce513Schristos 
80016dce513Schristos   buf[EI_MAG0] = ELFMAG0;
80116dce513Schristos   buf[EI_MAG1] = ELFMAG1;
80216dce513Schristos   buf[EI_MAG2] = ELFMAG2;
80316dce513Schristos   buf[EI_MAG3] = ELFMAG3;
80416dce513Schristos   buf[EI_CLASS] = cl;
80516dce513Schristos   buf[EI_DATA] = attrs->ei_data;
80616dce513Schristos   buf[EI_VERSION] = EV_CURRENT;
80716dce513Schristos   buf[EI_OSABI] = attrs->ei_osabi;
80816dce513Schristos 
80916dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
81016dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
81116dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
81216dce513Schristos   /* e_entry left as zero.  */
81316dce513Schristos   /* e_phoff left as zero.  */
81416dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
81516dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
81616dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
81716dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
81816dce513Schristos 		 (cl == ELFCLASS32
81916dce513Schristos 		  ? sizeof (Elf32_External_Phdr)
82016dce513Schristos 		  : sizeof (Elf64_External_Phdr)));
82116dce513Schristos   /* e_phnum left as zero.  */
82216dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
82316dce513Schristos 		 (cl == ELFCLASS32
82416dce513Schristos 		  ? sizeof (Elf32_External_Shdr)
82516dce513Schristos 		  : sizeof (Elf64_External_Shdr)));
82616dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half,
82716dce513Schristos 		 shnum >= SHN_LORESERVE ? 0 : shnum);
82816dce513Schristos   if (shnum == 0)
82916dce513Schristos     shstrndx = 0;
83016dce513Schristos   else
83116dce513Schristos     {
83216dce513Schristos       shstrndx = shnum - 1;
83316dce513Schristos       if (shstrndx >= SHN_LORESERVE)
83416dce513Schristos 	shstrndx = SHN_XINDEX;
83516dce513Schristos     }
83616dce513Schristos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half, shstrndx);
83716dce513Schristos 
83816dce513Schristos   return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
83916dce513Schristos 				       errmsg, err);
84016dce513Schristos }
84116dce513Schristos 
84216dce513Schristos /* Write out an ELF shdr.  */
84316dce513Schristos 
84416dce513Schristos 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)84516dce513Schristos simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
84616dce513Schristos 			      off_t offset, unsigned int sh_name,
84716dce513Schristos 			      unsigned int sh_type, unsigned int sh_flags,
848ede78133Schristos 			      off_t sh_addr,
84916dce513Schristos 			      unsigned int sh_offset, unsigned int sh_size,
850ede78133Schristos 			      unsigned int sh_link, unsigned int sh_info,
851ede78133Schristos 			      size_t sh_addralign,
852ede78133Schristos 			      size_t sh_entsize,
85316dce513Schristos 			      const char **errmsg, int *err)
85416dce513Schristos {
85516dce513Schristos   struct simple_object_elf_attributes *attrs =
85616dce513Schristos     (struct simple_object_elf_attributes *) sobj->data;
85716dce513Schristos   const struct elf_type_functions* fns;
85816dce513Schristos   unsigned char cl;
85916dce513Schristos   size_t shdr_size;
86016dce513Schristos   unsigned char buf[sizeof (Elf64_External_Shdr)];
86116dce513Schristos 
86216dce513Schristos   fns = attrs->type_functions;
86316dce513Schristos   cl = attrs->ei_class;
86416dce513Schristos 
86516dce513Schristos   shdr_size = (cl == ELFCLASS32
86616dce513Schristos 	       ? sizeof (Elf32_External_Shdr)
86716dce513Schristos 	       : sizeof (Elf64_External_Shdr));
86816dce513Schristos   memset (buf, 0, sizeof (Elf64_External_Shdr));
86916dce513Schristos 
87016dce513Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
87116dce513Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
87216dce513Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
873ede78133Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addr, Elf_Addr, sh_addr);
87416dce513Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
87516dce513Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
87616dce513Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
877ede78133Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_info, Elf_Word, sh_info);
87816dce513Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
879ede78133Schristos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Addr, sh_entsize);
88016dce513Schristos 
88116dce513Schristos   return simple_object_internal_write (descriptor, offset, buf, shdr_size,
88216dce513Schristos 				       errmsg, err);
88316dce513Schristos }
88416dce513Schristos 
88516dce513Schristos /* Write out a complete ELF file.
88616dce513Schristos    Ehdr
88716dce513Schristos    initial dummy Shdr
88816dce513Schristos    user-created Shdrs
88916dce513Schristos    .shstrtab Shdr
89016dce513Schristos    user-created section data
89116dce513Schristos    .shstrtab data  */
89216dce513Schristos 
89316dce513Schristos static const char *
simple_object_elf_write_to_file(simple_object_write * sobj,int descriptor,int * err)89416dce513Schristos simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
89516dce513Schristos 				 int *err)
89616dce513Schristos {
897ede78133Schristos   struct simple_object_elf_write *eow =
898ede78133Schristos     (struct simple_object_elf_write *) sobj->data;
899ede78133Schristos   struct simple_object_elf_attributes *attrs = &eow->attrs;
90016dce513Schristos   unsigned char cl;
90116dce513Schristos   size_t ehdr_size;
90216dce513Schristos   size_t shdr_size;
90316dce513Schristos   const char *errmsg;
90416dce513Schristos   simple_object_write_section *section;
90516dce513Schristos   unsigned int shnum;
90616dce513Schristos   size_t shdr_offset;
90716dce513Schristos   size_t sh_offset;
90816dce513Schristos   unsigned int first_sh_size;
90916dce513Schristos   unsigned int first_sh_link;
91016dce513Schristos   size_t sh_name;
91116dce513Schristos   unsigned char zero;
912ede78133Schristos   unsigned secnum;
91316dce513Schristos 
91416dce513Schristos   if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
91516dce513Schristos     return errmsg;
91616dce513Schristos 
91716dce513Schristos   cl = attrs->ei_class;
91816dce513Schristos   if (cl == ELFCLASS32)
91916dce513Schristos     {
92016dce513Schristos       ehdr_size = sizeof (Elf32_External_Ehdr);
92116dce513Schristos       shdr_size = sizeof (Elf32_External_Shdr);
92216dce513Schristos     }
92316dce513Schristos   else
92416dce513Schristos     {
92516dce513Schristos       ehdr_size = sizeof (Elf64_External_Ehdr);
92616dce513Schristos       shdr_size = sizeof (Elf64_External_Shdr);
92716dce513Schristos     }
92816dce513Schristos 
92916dce513Schristos   shnum = 0;
93016dce513Schristos   for (section = sobj->sections; section != NULL; section = section->next)
93116dce513Schristos     ++shnum;
93216dce513Schristos   if (shnum == 0)
93316dce513Schristos     return NULL;
93416dce513Schristos 
93516dce513Schristos   /* Add initial dummy Shdr and .shstrtab.  */
93616dce513Schristos   shnum += 2;
93716dce513Schristos 
93816dce513Schristos   shdr_offset = ehdr_size;
93916dce513Schristos   sh_offset = shdr_offset + shnum * shdr_size;
94016dce513Schristos 
94116dce513Schristos   if (shnum < SHN_LORESERVE)
94216dce513Schristos     first_sh_size = 0;
94316dce513Schristos   else
94416dce513Schristos     first_sh_size = shnum;
94516dce513Schristos   if (shnum - 1 < SHN_LORESERVE)
94616dce513Schristos     first_sh_link = 0;
94716dce513Schristos   else
94816dce513Schristos     first_sh_link = shnum - 1;
94916dce513Schristos   if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
950ede78133Schristos 				     0, 0, 0, 0, 0, first_sh_size, first_sh_link,
951ede78133Schristos 				     0, 0, 0, &errmsg, err))
95216dce513Schristos     return errmsg;
95316dce513Schristos 
95416dce513Schristos   shdr_offset += shdr_size;
95516dce513Schristos 
95616dce513Schristos   sh_name = 1;
957ede78133Schristos   secnum = 0;
95816dce513Schristos   for (section = sobj->sections; section != NULL; section = section->next)
95916dce513Schristos     {
96016dce513Schristos       size_t mask;
96116dce513Schristos       size_t new_sh_offset;
96216dce513Schristos       size_t sh_size;
96316dce513Schristos       struct simple_object_write_section_buffer *buffer;
964ede78133Schristos       unsigned int sh_type = SHT_PROGBITS;
965ede78133Schristos       unsigned int sh_flags = 0;
966ede78133Schristos       off_t sh_addr = 0;
967ede78133Schristos       unsigned int sh_link = 0;
968ede78133Schristos       unsigned int sh_info = 0;
969ede78133Schristos       size_t sh_addralign = 1U << section->align;
970ede78133Schristos       size_t sh_entsize = 0;
971ede78133Schristos       if (eow->shdrs)
972ede78133Schristos 	{
973ede78133Schristos 	  sh_type = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
974ede78133Schristos 				     eow->shdrs + secnum * shdr_size,
975ede78133Schristos 				     sh_type, Elf_Word);
976ede78133Schristos 	  sh_flags = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
977ede78133Schristos 				      eow->shdrs + secnum * shdr_size,
978ede78133Schristos 				      sh_flags, Elf_Addr);
979ede78133Schristos 	  sh_addr = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
980ede78133Schristos 				     eow->shdrs + secnum * shdr_size,
981ede78133Schristos 				     sh_addr, Elf_Addr);
982ede78133Schristos 	  sh_link = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
983ede78133Schristos 				     eow->shdrs + secnum * shdr_size,
984ede78133Schristos 				     sh_link, Elf_Word);
985ede78133Schristos 	  sh_info = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
986ede78133Schristos 				     eow->shdrs + secnum * shdr_size,
987ede78133Schristos 				     sh_info, Elf_Word);
988ede78133Schristos 	  sh_addralign = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
989ede78133Schristos 					  eow->shdrs + secnum * shdr_size,
990ede78133Schristos 					  sh_addralign, Elf_Addr);
991ede78133Schristos 	  sh_entsize = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
992ede78133Schristos 					eow->shdrs + secnum * shdr_size,
993ede78133Schristos 					sh_entsize, Elf_Addr);
994ede78133Schristos 	  secnum++;
995ede78133Schristos 	}
99616dce513Schristos 
997ede78133Schristos       mask = sh_addralign - 1;
99816dce513Schristos       new_sh_offset = sh_offset + mask;
99916dce513Schristos       new_sh_offset &= ~ mask;
100016dce513Schristos       while (new_sh_offset > sh_offset)
100116dce513Schristos 	{
100216dce513Schristos 	  unsigned char zeroes[16];
100316dce513Schristos 	  size_t write;
100416dce513Schristos 
100516dce513Schristos 	  memset (zeroes, 0, sizeof zeroes);
100616dce513Schristos 	  write = new_sh_offset - sh_offset;
100716dce513Schristos 	  if (write > sizeof zeroes)
100816dce513Schristos 	    write = sizeof zeroes;
100916dce513Schristos 	  if (!simple_object_internal_write (descriptor, sh_offset, zeroes,
101016dce513Schristos 					     write, &errmsg, err))
101116dce513Schristos 	    return errmsg;
101216dce513Schristos 	  sh_offset += write;
101316dce513Schristos 	}
101416dce513Schristos 
101516dce513Schristos       sh_size = 0;
101616dce513Schristos       for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
101716dce513Schristos 	{
101816dce513Schristos 	  if (!simple_object_internal_write (descriptor, sh_offset + sh_size,
101916dce513Schristos 					     ((const unsigned char *)
102016dce513Schristos 					      buffer->buffer),
102116dce513Schristos 					     buffer->size, &errmsg, err))
102216dce513Schristos 	    return errmsg;
102316dce513Schristos 	  sh_size += buffer->size;
102416dce513Schristos 	}
102516dce513Schristos 
102616dce513Schristos       if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
1027ede78133Schristos 					 sh_name, sh_type, sh_flags,
1028ede78133Schristos 					 sh_addr, sh_offset,
1029ede78133Schristos 					 sh_size, sh_link, sh_info,
1030ede78133Schristos 					 sh_addralign, sh_entsize,
103116dce513Schristos 					 &errmsg, err))
103216dce513Schristos 	return errmsg;
103316dce513Schristos 
103416dce513Schristos       shdr_offset += shdr_size;
103516dce513Schristos       sh_name += strlen (section->name) + 1;
103616dce513Schristos       sh_offset += sh_size;
103716dce513Schristos     }
103816dce513Schristos 
103916dce513Schristos   if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
1040ede78133Schristos 				     sh_name, SHT_STRTAB, 0, 0, sh_offset,
1041ede78133Schristos 				     sh_name + strlen (".shstrtab") + 1, 0, 0,
1042ede78133Schristos 				     1, 0, &errmsg, err))
104316dce513Schristos     return errmsg;
104416dce513Schristos 
104516dce513Schristos   /* .shstrtab has a leading zero byte.  */
104616dce513Schristos   zero = 0;
104716dce513Schristos   if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
104816dce513Schristos 				     &errmsg, err))
104916dce513Schristos     return errmsg;
105016dce513Schristos   ++sh_offset;
105116dce513Schristos 
105216dce513Schristos   for (section = sobj->sections; section != NULL; section = section->next)
105316dce513Schristos     {
105416dce513Schristos       size_t len;
105516dce513Schristos 
105616dce513Schristos       len = strlen (section->name) + 1;
105716dce513Schristos       if (!simple_object_internal_write (descriptor, sh_offset,
105816dce513Schristos 					 (const unsigned char *) section->name,
105916dce513Schristos 					 len, &errmsg, err))
106016dce513Schristos 	return errmsg;
106116dce513Schristos       sh_offset += len;
106216dce513Schristos     }
106316dce513Schristos 
106416dce513Schristos   if (!simple_object_internal_write (descriptor, sh_offset,
106516dce513Schristos 				     (const unsigned char *) ".shstrtab",
106616dce513Schristos 				     strlen (".shstrtab") + 1, &errmsg, err))
106716dce513Schristos     return errmsg;
106816dce513Schristos 
106916dce513Schristos   return NULL;
107016dce513Schristos }
107116dce513Schristos 
107216dce513Schristos /* Release the private data for an simple_object_write structure.  */
107316dce513Schristos 
107416dce513Schristos static void
simple_object_elf_release_write(void * data)107516dce513Schristos simple_object_elf_release_write (void *data)
107616dce513Schristos {
1077ede78133Schristos   struct simple_object_elf_write *eow = (struct simple_object_elf_write *) data;
1078ede78133Schristos   if (eow->shdrs)
1079ede78133Schristos     XDELETE (eow->shdrs);
108016dce513Schristos   XDELETE (data);
108116dce513Schristos }
108216dce513Schristos 
1083ede78133Schristos /* Copy all sections in an ELF file.  */
1084ede78133Schristos 
1085ede78133Schristos static const char *
simple_object_elf_copy_lto_debug_sections(simple_object_read * sobj,simple_object_write * dobj,char * (* pfn)(const char *),int * err)1086ede78133Schristos simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
1087ede78133Schristos 					   simple_object_write *dobj,
1088ede78133Schristos 					   char *(*pfn) (const char *),
1089ede78133Schristos 					   int *err)
1090ede78133Schristos {
1091ede78133Schristos   struct simple_object_elf_read *eor =
1092ede78133Schristos     (struct simple_object_elf_read *) sobj->data;
1093ede78133Schristos   const struct elf_type_functions *type_functions = eor->type_functions;
1094ede78133Schristos   struct simple_object_elf_write *eow =
1095ede78133Schristos     (struct simple_object_elf_write *) dobj->data;
1096ede78133Schristos   unsigned char ei_class = eor->ei_class;
1097ede78133Schristos   size_t shdr_size;
1098ede78133Schristos   unsigned int shnum;
1099ede78133Schristos   unsigned char *shdrs;
1100ede78133Schristos   const char *errmsg;
1101ede78133Schristos   unsigned char *shstrhdr;
1102ede78133Schristos   size_t name_size;
1103ede78133Schristos   off_t shstroff;
1104ede78133Schristos   unsigned char *names;
1105ede78133Schristos   unsigned int i;
1106ede78133Schristos   int changed;
1107ede78133Schristos   int *pfnret;
1108ede78133Schristos   const char **pfnname;
1109ede78133Schristos   unsigned new_i;
1110ede78133Schristos   unsigned *sh_map;
1111ede78133Schristos   unsigned first_shndx = 0;
1112ede78133Schristos   unsigned int *symtab_indices_shndx;
1113ede78133Schristos 
1114ede78133Schristos   shdr_size = (ei_class == ELFCLASS32
1115ede78133Schristos 	       ? sizeof (Elf32_External_Shdr)
1116ede78133Schristos 	       : sizeof (Elf64_External_Shdr));
1117ede78133Schristos 
1118ede78133Schristos   /* Read the section headers.  We skip section 0, which is not a
1119ede78133Schristos      useful section.  */
1120ede78133Schristos 
1121ede78133Schristos   shnum = eor->shnum;
1122ede78133Schristos   shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
1123ede78133Schristos 
1124ede78133Schristos   if (!simple_object_internal_read (sobj->descriptor,
1125ede78133Schristos 				    sobj->offset + eor->shoff + shdr_size,
1126ede78133Schristos 				    shdrs,
1127ede78133Schristos 				    shdr_size * (shnum - 1),
1128ede78133Schristos 				    &errmsg, err))
1129ede78133Schristos     {
1130ede78133Schristos       XDELETEVEC (shdrs);
1131ede78133Schristos       return errmsg;
1132ede78133Schristos     }
1133ede78133Schristos 
1134ede78133Schristos   /* Read the section names.  */
1135ede78133Schristos 
1136ede78133Schristos   shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
1137ede78133Schristos   name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1138ede78133Schristos 			       shstrhdr, sh_size, Elf_Addr);
1139ede78133Schristos   shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1140ede78133Schristos 			      shstrhdr, sh_offset, Elf_Addr);
1141ede78133Schristos   names = XNEWVEC (unsigned char, name_size);
1142ede78133Schristos   if (!simple_object_internal_read (sobj->descriptor,
1143ede78133Schristos 				    sobj->offset + shstroff,
1144ede78133Schristos 				    names, name_size, &errmsg, err))
1145ede78133Schristos     {
1146ede78133Schristos       XDELETEVEC (names);
1147ede78133Schristos       XDELETEVEC (shdrs);
1148ede78133Schristos       return errmsg;
1149ede78133Schristos     }
1150ede78133Schristos 
1151ede78133Schristos   pfnret = XNEWVEC (int, shnum);
1152ede78133Schristos   pfnname = XNEWVEC (const char *, shnum);
1153ede78133Schristos 
1154ede78133Schristos   /* Map of symtab to index section.  */
1155ede78133Schristos   symtab_indices_shndx = XCNEWVEC (unsigned int, shnum - 1);
1156ede78133Schristos 
1157ede78133Schristos   /* First perform the callbacks to know which sections to preserve and
1158ede78133Schristos      what name to use for those.  */
1159ede78133Schristos   for (i = 1; i < shnum; ++i)
1160ede78133Schristos     {
1161ede78133Schristos       unsigned char *shdr;
1162ede78133Schristos       unsigned int sh_name, sh_type;
1163ede78133Schristos       const char *name;
1164ede78133Schristos       char *ret;
1165ede78133Schristos 
1166ede78133Schristos       shdr = shdrs + (i - 1) * shdr_size;
1167ede78133Schristos       sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1168ede78133Schristos 				 shdr, sh_name, Elf_Word);
1169ede78133Schristos       if (sh_name >= name_size)
1170ede78133Schristos 	{
1171ede78133Schristos 	  *err = 0;
1172ede78133Schristos 	  XDELETEVEC (names);
1173ede78133Schristos 	  XDELETEVEC (shdrs);
1174ede78133Schristos 	  return "ELF section name out of range";
1175ede78133Schristos 	}
1176ede78133Schristos 
1177ede78133Schristos       name = (const char *) names + sh_name;
1178ede78133Schristos 
1179ede78133Schristos       ret = (*pfn) (name);
1180ede78133Schristos       pfnret[i - 1] = ret == NULL ? -1 : 0;
1181ede78133Schristos       pfnname[i - 1] = ret == NULL ? name : ret;
1182ede78133Schristos       if (first_shndx == 0
1183ede78133Schristos 	  && pfnret[i - 1] == 0)
1184ede78133Schristos 	first_shndx = i;
1185ede78133Schristos 
1186ede78133Schristos       /* Remember the indexes of existing SHT_SYMTAB_SHNDX sections.  */
1187ede78133Schristos       sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1188ede78133Schristos 				 shdr, sh_type, Elf_Word);
1189ede78133Schristos       if (sh_type == SHT_SYMTAB_SHNDX)
1190ede78133Schristos 	{
1191ede78133Schristos 	  unsigned int sh_link;
1192ede78133Schristos 	  sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1193ede78133Schristos 				     shdr, sh_link, Elf_Word);
1194*e992f068Schristos 	  symtab_indices_shndx[sh_link - 1] = i - 1;
1195ede78133Schristos 	  /* Always discard the extended index sections, after
1196ede78133Schristos 	     copying it will not be needed.  This way we don't need to
1197ede78133Schristos 	     update it and deal with the ordering constraints of
1198ede78133Schristos 	     processing the existing symtab and changing the index.  */
1199ede78133Schristos 	  pfnret[i - 1] = -1;
1200ede78133Schristos 	}
1201ede78133Schristos     }
1202ede78133Schristos 
1203ede78133Schristos   /* Mark sections as preserved that are required by to be preserved
1204ede78133Schristos      sections.  */
1205ede78133Schristos   do
1206ede78133Schristos     {
1207ede78133Schristos       changed = 0;
1208ede78133Schristos       for (i = 1; i < shnum; ++i)
1209ede78133Schristos 	{
1210ede78133Schristos 	  unsigned char *shdr;
1211ede78133Schristos 	  unsigned int sh_type, sh_info, sh_link;
1212ede78133Schristos 	  off_t offset;
1213ede78133Schristos 	  off_t length;
1214ede78133Schristos 
1215ede78133Schristos 	  shdr = shdrs + (i - 1) * shdr_size;
1216ede78133Schristos 	  sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1217ede78133Schristos 				     shdr, sh_type, Elf_Word);
1218ede78133Schristos 	  sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1219ede78133Schristos 				     shdr, sh_info, Elf_Word);
1220ede78133Schristos 	  sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1221ede78133Schristos 				     shdr, sh_link, Elf_Word);
1222ede78133Schristos 	  if (sh_type == SHT_GROUP)
1223ede78133Schristos 	    {
1224ede78133Schristos 	      /* Mark groups containing copied sections.  */
1225ede78133Schristos 	      unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class,
1226ede78133Schristos 						  Shdr, shdr, sh_entsize,
1227ede78133Schristos 						  Elf_Addr);
1228ede78133Schristos 	      unsigned char *ent, *buf;
1229ede78133Schristos 	      int keep = 0;
1230ede78133Schristos 	      offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1231ede78133Schristos 					shdr, sh_offset, Elf_Addr);
1232ede78133Schristos 	      length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1233ede78133Schristos 					shdr, sh_size, Elf_Addr);
1234ede78133Schristos 	      buf = XNEWVEC (unsigned char, length);
1235ede78133Schristos 	      if (!simple_object_internal_read (sobj->descriptor,
1236ede78133Schristos 						sobj->offset + offset, buf,
1237ede78133Schristos 						(size_t) length, &errmsg, err))
1238ede78133Schristos 		{
1239ede78133Schristos 		  XDELETEVEC (buf);
1240ede78133Schristos 		  XDELETEVEC (names);
1241ede78133Schristos 		  XDELETEVEC (shdrs);
1242ede78133Schristos 		  return errmsg;
1243ede78133Schristos 		}
1244ede78133Schristos 	      for (ent = buf + entsize; ent < buf + length; ent += entsize)
1245ede78133Schristos 		{
1246ede78133Schristos 		  unsigned sec = type_functions->fetch_Elf_Word (ent);
1247ede78133Schristos 		  if (pfnret[sec - 1] == 0)
1248ede78133Schristos 		    keep = 1;
1249ede78133Schristos 		}
1250ede78133Schristos 	      if (keep)
1251ede78133Schristos 		{
1252ede78133Schristos 		  changed |= (pfnret[sh_link - 1] == -1
1253ede78133Schristos 			      || pfnret[i - 1] == -1);
1254ede78133Schristos 		  pfnret[sh_link - 1] = 0;
1255ede78133Schristos 		  pfnret[i - 1] = 0;
1256ede78133Schristos 		}
1257ede78133Schristos 	    }
1258ede78133Schristos 	  if (sh_type == SHT_RELA
1259ede78133Schristos 	      || sh_type == SHT_REL)
1260ede78133Schristos 	    {
1261ede78133Schristos 	      /* Mark relocation sections and symtab of copied sections.  */
1262ede78133Schristos 	      if (pfnret[sh_info - 1] == 0)
1263ede78133Schristos 		{
1264ede78133Schristos 		  changed |= (pfnret[sh_link - 1] == -1
1265ede78133Schristos 			      || pfnret[i - 1] == -1);
1266ede78133Schristos 		  pfnret[sh_link - 1] = 0;
1267ede78133Schristos 		  pfnret[i - 1] = 0;
1268ede78133Schristos 		}
1269ede78133Schristos 	    }
1270ede78133Schristos 	  if (sh_type == SHT_SYMTAB)
1271ede78133Schristos 	    {
1272ede78133Schristos 	      /* Mark strings sections of copied symtabs.  */
1273ede78133Schristos 	      if (pfnret[i - 1] == 0)
1274ede78133Schristos 		{
1275ede78133Schristos 		  changed |= pfnret[sh_link - 1] == -1;
1276ede78133Schristos 		  pfnret[sh_link - 1] = 0;
1277ede78133Schristos 		}
1278ede78133Schristos 	    }
1279ede78133Schristos 	}
1280ede78133Schristos     }
1281ede78133Schristos   while (changed);
1282ede78133Schristos 
1283ede78133Schristos   /* Compute a mapping of old -> new section numbers.  */
1284ede78133Schristos   sh_map = XNEWVEC (unsigned, shnum);
1285ede78133Schristos   sh_map[0] = 0;
1286ede78133Schristos   new_i = 1;
1287ede78133Schristos   for (i = 1; i < shnum; ++i)
1288ede78133Schristos     {
1289ede78133Schristos       if (pfnret[i - 1] == -1)
1290ede78133Schristos 	sh_map[i] = 0;
1291ede78133Schristos       else
1292ede78133Schristos 	sh_map[i] = new_i++;
1293ede78133Schristos     }
1294ede78133Schristos   if (new_i - 1 >= SHN_LORESERVE)
1295ede78133Schristos     {
1296ede78133Schristos       *err = ENOTSUP;
1297ede78133Schristos       return "Too many copied sections";
1298ede78133Schristos     }
1299ede78133Schristos   eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_i - 1));
1300ede78133Schristos 
1301ede78133Schristos   /* Then perform the actual copying.  */
1302ede78133Schristos   new_i = 0;
1303ede78133Schristos   for (i = 1; i < shnum; ++i)
1304ede78133Schristos     {
1305ede78133Schristos       unsigned char *shdr;
1306ede78133Schristos       unsigned int sh_name, sh_type;
1307ede78133Schristos       const char *name;
1308ede78133Schristos       off_t offset;
1309ede78133Schristos       off_t length;
1310ede78133Schristos       simple_object_write_section *dest;
1311ede78133Schristos       off_t flags;
1312ede78133Schristos       unsigned char *buf;
1313ede78133Schristos 
1314ede78133Schristos       if (pfnret[i - 1])
1315ede78133Schristos 	continue;
1316ede78133Schristos 
1317ede78133Schristos       new_i++;
1318ede78133Schristos       shdr = shdrs + (i - 1) * shdr_size;
1319ede78133Schristos       sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1320ede78133Schristos 				 shdr, sh_name, Elf_Word);
1321ede78133Schristos       if (sh_name >= name_size)
1322ede78133Schristos 	{
1323ede78133Schristos 	  *err = 0;
1324ede78133Schristos 	  XDELETEVEC (names);
1325ede78133Schristos 	  XDELETEVEC (shdrs);
1326ede78133Schristos 	  XDELETEVEC (symtab_indices_shndx);
1327ede78133Schristos 	  return "ELF section name out of range";
1328ede78133Schristos 	}
1329ede78133Schristos 
1330ede78133Schristos       name = pfnname[i - 1];
1331ede78133Schristos       offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1332ede78133Schristos 				shdr, sh_offset, Elf_Addr);
1333ede78133Schristos       length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1334ede78133Schristos 				shdr, sh_size, Elf_Addr);
1335ede78133Schristos       sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1336ede78133Schristos 				 shdr, sh_type, Elf_Word);
1337ede78133Schristos 
1338ede78133Schristos       dest = simple_object_write_create_section (dobj, pfnname[i - 1],
1339ede78133Schristos 						 0, &errmsg, err);
1340ede78133Schristos       if (dest == NULL)
1341ede78133Schristos 	{
1342ede78133Schristos 	  XDELETEVEC (names);
1343ede78133Schristos 	  XDELETEVEC (shdrs);
1344ede78133Schristos 	  XDELETEVEC (symtab_indices_shndx);
1345ede78133Schristos 	  return errmsg;
1346ede78133Schristos 	}
1347ede78133Schristos 
1348ede78133Schristos       /* Record the SHDR of the source.  */
1349ede78133Schristos       memcpy (eow->shdrs + (new_i - 1) * shdr_size, shdr, shdr_size);
1350ede78133Schristos       shdr = eow->shdrs + (new_i - 1) * shdr_size;
1351ede78133Schristos 
1352ede78133Schristos       /* Copy the data.
1353ede78133Schristos 	 ???  This is quite wasteful and ideally would be delayed until
1354ede78133Schristos 	 write_to_file ().  Thus it questions the interfacing
1355ede78133Schristos 	 which eventually should contain destination creation plus
1356ede78133Schristos 	 writing.  */
1357ede78133Schristos       buf = XNEWVEC (unsigned char, length);
1358ede78133Schristos       if (!simple_object_internal_read (sobj->descriptor,
1359ede78133Schristos 					sobj->offset + offset, buf,
1360ede78133Schristos 					(size_t) length, &errmsg, err))
1361ede78133Schristos 	{
1362ede78133Schristos 	  XDELETEVEC (buf);
1363ede78133Schristos 	  XDELETEVEC (names);
1364ede78133Schristos 	  XDELETEVEC (shdrs);
1365ede78133Schristos 	  XDELETEVEC (symtab_indices_shndx);
1366ede78133Schristos 	  return errmsg;
1367ede78133Schristos 	}
1368ede78133Schristos 
1369012573ebSchristos       /* If we are processing .symtab purge any symbols
1370012573ebSchristos 	 in discarded sections.  */
1371ede78133Schristos       if (sh_type == SHT_SYMTAB)
1372ede78133Schristos 	{
1373ede78133Schristos 	  unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1374ede78133Schristos 					      shdr, sh_entsize, Elf_Addr);
1375012573ebSchristos 	  size_t prevailing_name_idx = 0;
1376ede78133Schristos 	  unsigned char *ent;
1377ede78133Schristos 	  unsigned *shndx_table = NULL;
1378ede78133Schristos 	  /* Read the section index table if present.  */
1379ede78133Schristos 	  if (symtab_indices_shndx[i - 1] != 0)
1380ede78133Schristos 	    {
1381*e992f068Schristos 	      unsigned char *sidxhdr = shdrs + symtab_indices_shndx[i - 1] * shdr_size;
1382ede78133Schristos 	      off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1383ede78133Schristos 					       sidxhdr, sh_offset, Elf_Addr);
1384ede78133Schristos 	      size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1385ede78133Schristos 					       sidxhdr, sh_size, Elf_Addr);
1386*e992f068Schristos 	      unsigned int shndx_type
1387*e992f068Schristos 		= ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1388*e992f068Schristos 				   sidxhdr, sh_type, Elf_Word);
1389*e992f068Schristos 	      if (shndx_type != SHT_SYMTAB_SHNDX)
1390*e992f068Schristos 		return "Wrong section type of a SYMTAB SECTION INDICES section";
1391ede78133Schristos 	      shndx_table = (unsigned *)XNEWVEC (char, sidxsz);
1392ede78133Schristos 	      simple_object_internal_read (sobj->descriptor,
1393ede78133Schristos 					   sobj->offset + sidxoff,
1394ede78133Schristos 					   (unsigned char *)shndx_table,
1395ede78133Schristos 					   sidxsz, &errmsg, err);
1396ede78133Schristos 	    }
1397012573ebSchristos 
1398012573ebSchristos 	  /* Find a WEAK HIDDEN symbol which name we will use for removed
1399012573ebSchristos 	     symbols.  We know there's a prevailing weak hidden symbol
1400012573ebSchristos 	     at the start of the .debug_info section.  */
1401012573ebSchristos 	  for (ent = buf; ent < buf + length; ent += entsize)
1402012573ebSchristos 	    {
1403012573ebSchristos 	      unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
1404012573ebSchristos 						   Sym, ent,
1405012573ebSchristos 						   st_shndx, Elf_Half);
1406012573ebSchristos 	      unsigned char *st_info;
1407012573ebSchristos 	      unsigned char *st_other;
1408012573ebSchristos 	      if (ei_class == ELFCLASS32)
1409012573ebSchristos 		{
1410012573ebSchristos 		  st_info = &((Elf32_External_Sym *)ent)->st_info;
1411012573ebSchristos 		  st_other = &((Elf32_External_Sym *)ent)->st_other;
1412012573ebSchristos 		}
1413012573ebSchristos 	      else
1414012573ebSchristos 		{
1415012573ebSchristos 		  st_info = &((Elf64_External_Sym *)ent)->st_info;
1416012573ebSchristos 		  st_other = &((Elf64_External_Sym *)ent)->st_other;
1417012573ebSchristos 		}
1418012573ebSchristos 	      if (st_shndx == SHN_XINDEX)
1419012573ebSchristos 		st_shndx = type_functions->fetch_Elf_Word
1420012573ebSchristos 		    ((unsigned char *)(shndx_table + (ent - buf) / entsize));
1421012573ebSchristos 
1422012573ebSchristos 	      if (st_shndx != SHN_COMMON
1423012573ebSchristos 		  && !(st_shndx != SHN_UNDEF
1424012573ebSchristos 		       && st_shndx < shnum
1425012573ebSchristos 		       && pfnret[st_shndx - 1] == -1)
1426012573ebSchristos 		  && ELF_ST_BIND (*st_info) == STB_WEAK
1427012573ebSchristos 		  && *st_other == STV_HIDDEN)
1428012573ebSchristos 		{
1429012573ebSchristos 		  prevailing_name_idx = ELF_FETCH_FIELD (type_functions,
1430012573ebSchristos 							 ei_class, Sym, ent,
1431012573ebSchristos 							 st_name, Elf_Word);
1432012573ebSchristos 		  break;
1433012573ebSchristos 		}
1434012573ebSchristos 	    }
1435012573ebSchristos 
1436ede78133Schristos 	  for (ent = buf; ent < buf + length; ent += entsize)
1437ede78133Schristos 	    {
1438ede78133Schristos 	      unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
1439ede78133Schristos 						   Sym, ent,
1440ede78133Schristos 						   st_shndx, Elf_Half);
1441ede78133Schristos 	      unsigned raw_st_shndx = st_shndx;
1442ede78133Schristos 	      unsigned char *st_info;
1443ede78133Schristos 	      unsigned char *st_other;
1444ede78133Schristos 	      int discard = 0;
1445ede78133Schristos 	      if (ei_class == ELFCLASS32)
1446ede78133Schristos 		{
1447ede78133Schristos 		  st_info = &((Elf32_External_Sym *)ent)->st_info;
1448ede78133Schristos 		  st_other = &((Elf32_External_Sym *)ent)->st_other;
1449ede78133Schristos 		}
1450ede78133Schristos 	      else
1451ede78133Schristos 		{
1452ede78133Schristos 		  st_info = &((Elf64_External_Sym *)ent)->st_info;
1453ede78133Schristos 		  st_other = &((Elf64_External_Sym *)ent)->st_other;
1454ede78133Schristos 		}
1455ede78133Schristos 	      if (st_shndx == SHN_XINDEX)
1456ede78133Schristos 		st_shndx = type_functions->fetch_Elf_Word
1457ede78133Schristos 		    ((unsigned char *)(shndx_table + (ent - buf) / entsize));
1458012573ebSchristos 	      /* Eliminate all COMMONs - this includes __gnu_lto_slim
1459012573ebSchristos 		 which otherwise cause endless LTO plugin invocation.
1460012573ebSchristos 		 FIXME: remove the condition once we remove emission
1461012573ebSchristos 		 of __gnu_lto_slim symbol.  */
1462ede78133Schristos 	      if (st_shndx == SHN_COMMON)
1463ede78133Schristos 		discard = 1;
1464ede78133Schristos 	      /* We also need to remove symbols refering to sections
1465ede78133Schristos 		 we'll eventually remove as with fat LTO objects
1466ede78133Schristos 		 we otherwise get duplicate symbols at final link
1467ede78133Schristos 		 (with GNU ld, gold is fine and ignores symbols in
1468ede78133Schristos 		 sections marked as EXCLUDE).  ld/20513  */
1469ede78133Schristos 	      else if (st_shndx != SHN_UNDEF
1470ede78133Schristos 		       && st_shndx < shnum
1471ede78133Schristos 		       && pfnret[st_shndx - 1] == -1)
1472ede78133Schristos 		discard = 1;
1473*e992f068Schristos 	      /* We also need to remove global UNDEFs which can
1474*e992f068Schristos 		 cause link fails later.  */
1475*e992f068Schristos 	      else if (st_shndx == SHN_UNDEF
1476*e992f068Schristos 		       && ELF_ST_BIND (*st_info) == STB_GLOBAL)
1477*e992f068Schristos 		discard = 1;
1478ede78133Schristos 
1479ede78133Schristos 	      if (discard)
1480ede78133Schristos 		{
1481ede78133Schristos 		  /* Make discarded symbols undefined and unnamed
1482ede78133Schristos 		     in case it is local.  */
1483ede78133Schristos 		  int bind = ELF_ST_BIND (*st_info);
1484ede78133Schristos 		  int other = STV_DEFAULT;
1485ede78133Schristos 		  if (bind == STB_LOCAL)
1486ede78133Schristos 		    {
1487ede78133Schristos 		      /* Make discarded local symbols unnamed and
1488ede78133Schristos 			 defined in the first prevailing section.  */
1489ede78133Schristos 		      ELF_SET_FIELD (type_functions, ei_class, Sym,
1490ede78133Schristos 				     ent, st_name, Elf_Word, 0);
1491ede78133Schristos 		      ELF_SET_FIELD (type_functions, ei_class, Sym,
1492ede78133Schristos 				     ent, st_shndx, Elf_Half,
1493ede78133Schristos 				     sh_map[first_shndx]);
1494ede78133Schristos 		    }
1495ede78133Schristos 		  else
1496ede78133Schristos 		    {
1497ede78133Schristos 		      /* Make discarded global symbols hidden weak
1498012573ebSchristos 			 undefined and sharing a name of a prevailing
1499012573ebSchristos 			 symbol.  */
1500ede78133Schristos 		      bind = STB_WEAK;
1501ede78133Schristos 		      other = STV_HIDDEN;
1502ede78133Schristos 		      ELF_SET_FIELD (type_functions, ei_class, Sym,
1503ede78133Schristos 				     ent, st_name, Elf_Word,
1504012573ebSchristos 				     prevailing_name_idx);
1505ede78133Schristos 		      ELF_SET_FIELD (type_functions, ei_class, Sym,
1506ede78133Schristos 				     ent, st_shndx, Elf_Half, SHN_UNDEF);
1507ede78133Schristos 		    }
1508ede78133Schristos 		  *st_other = other;
1509ede78133Schristos 		  *st_info = ELF_ST_INFO (bind, STT_NOTYPE);
1510ede78133Schristos 		  ELF_SET_FIELD (type_functions, ei_class, Sym,
1511ede78133Schristos 				 ent, st_value, Elf_Addr, 0);
1512ede78133Schristos 		  ELF_SET_FIELD (type_functions, ei_class, Sym,
1513ede78133Schristos 				 ent, st_size, Elf_Word, 0);
1514ede78133Schristos 		}
1515ede78133Schristos 	      else if (raw_st_shndx < SHN_LORESERVE
1516ede78133Schristos 		       || raw_st_shndx == SHN_XINDEX)
1517ede78133Schristos 		/* Remap the section reference.  */
1518ede78133Schristos 		ELF_SET_FIELD (type_functions, ei_class, Sym,
1519ede78133Schristos 			       ent, st_shndx, Elf_Half, sh_map[st_shndx]);
1520ede78133Schristos 	    }
1521ede78133Schristos 	  XDELETEVEC (shndx_table);
1522ede78133Schristos 	}
1523ede78133Schristos       else if (sh_type == SHT_GROUP)
1524ede78133Schristos 	{
1525ede78133Schristos 	  /* Remap section indices in groups and remove removed members.  */
1526ede78133Schristos 	  unsigned char *ent, *dst;
1527ede78133Schristos 	  for (dst = ent = buf + 4; ent < buf + length; ent += 4)
1528ede78133Schristos 	    {
1529ede78133Schristos 	      unsigned shndx = type_functions->fetch_Elf_Word (ent);
1530ede78133Schristos 	      if (pfnret[shndx - 1] == -1)
1531ede78133Schristos 		;
1532ede78133Schristos 	      else
1533ede78133Schristos 		{
1534ede78133Schristos 		  type_functions->set_Elf_Word (dst, sh_map[shndx]);
1535ede78133Schristos 		  dst += 4;
1536ede78133Schristos 		}
1537ede78133Schristos 	    }
1538ede78133Schristos 	  /* Adjust the length.  */
1539ede78133Schristos 	  length = dst - buf;
1540ede78133Schristos 	}
1541ede78133Schristos 
1542ede78133Schristos       errmsg = simple_object_write_add_data (dobj, dest,
1543ede78133Schristos 					     buf, length, 1, err);
1544ede78133Schristos       XDELETEVEC (buf);
1545ede78133Schristos       if (errmsg)
1546ede78133Schristos 	{
1547ede78133Schristos 	  XDELETEVEC (names);
1548ede78133Schristos 	  XDELETEVEC (shdrs);
1549ede78133Schristos 	  XDELETEVEC (symtab_indices_shndx);
1550ede78133Schristos 	  return errmsg;
1551ede78133Schristos 	}
1552ede78133Schristos 
1553ede78133Schristos       flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1554ede78133Schristos 			       shdr, sh_flags, Elf_Addr);
1555ede78133Schristos       /* Remap the section references.  */
1556ede78133Schristos       {
1557ede78133Schristos 	unsigned int sh_info, sh_link;
1558ede78133Schristos 	if (flags & SHF_INFO_LINK || sh_type == SHT_REL || sh_type == SHT_RELA)
1559ede78133Schristos 	  {
1560ede78133Schristos 	    sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1561ede78133Schristos 				       shdr, sh_info, Elf_Word);
1562ede78133Schristos 	    sh_info = sh_map[sh_info];
1563ede78133Schristos 	    ELF_SET_FIELD (type_functions, ei_class, Shdr,
1564ede78133Schristos 			   shdr, sh_info, Elf_Word, sh_info);
1565ede78133Schristos 	  }
1566ede78133Schristos 	sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
1567ede78133Schristos 				   shdr, sh_link, Elf_Word);
1568ede78133Schristos 	sh_link = sh_map[sh_link];
1569ede78133Schristos 	ELF_SET_FIELD (type_functions, ei_class, Shdr,
1570ede78133Schristos 		       shdr, sh_link, Elf_Word, sh_link);
1571ede78133Schristos       }
1572ede78133Schristos       /* The debugobj doesn't contain any code, thus no trampolines.
1573ede78133Schristos 	 Even when the original object needs trampolines, debugobj
1574ede78133Schristos 	 doesn't.  */
1575ede78133Schristos       if (strcmp (name, ".note.GNU-stack") == 0)
1576ede78133Schristos 	flags &= ~SHF_EXECINSTR;
1577ede78133Schristos       /* Clear SHF_EXCLUDE on to be preserved sections.  */
1578ede78133Schristos       flags &= ~SHF_EXCLUDE;
1579ede78133Schristos       ELF_SET_FIELD (type_functions, ei_class, Shdr,
1580ede78133Schristos 		     shdr, sh_flags, Elf_Addr, flags);
1581ede78133Schristos     }
1582ede78133Schristos 
1583ede78133Schristos   XDELETEVEC (names);
1584ede78133Schristos   XDELETEVEC (shdrs);
1585ede78133Schristos   XDELETEVEC (pfnret);
1586ede78133Schristos   XDELETEVEC (pfnname);
1587ede78133Schristos   XDELETEVEC (symtab_indices_shndx);
1588ede78133Schristos   XDELETEVEC (sh_map);
1589ede78133Schristos 
1590ede78133Schristos   return NULL;
1591ede78133Schristos }
1592ede78133Schristos 
1593ede78133Schristos 
159416dce513Schristos /* The ELF functions.  */
159516dce513Schristos 
159616dce513Schristos const struct simple_object_functions simple_object_elf_functions =
159716dce513Schristos {
159816dce513Schristos   simple_object_elf_match,
159916dce513Schristos   simple_object_elf_find_sections,
160016dce513Schristos   simple_object_elf_fetch_attributes,
160116dce513Schristos   simple_object_elf_release_read,
160216dce513Schristos   simple_object_elf_attributes_merge,
160316dce513Schristos   simple_object_elf_release_attributes,
160416dce513Schristos   simple_object_elf_start_write,
160516dce513Schristos   simple_object_elf_write_to_file,
1606ede78133Schristos   simple_object_elf_release_write,
1607ede78133Schristos   simple_object_elf_copy_lto_debug_sections
160816dce513Schristos };
1609