/* simple-object-elf.c -- routines to manipulate ELF object files. Copyright (C) 2010-2026 Free Software Foundation, Inc. Written by Ian Lance Taylor, Google. This program is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version. This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details. You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, 51 Franklin Street - Fifth Floor,Boston, MA 02110-1301, USA. */ #include "config.h"#include "libiberty.h"#include "simple-object.h" #include <errno.h>/* mingw.org's MinGW doesn't have ENOTSUP. */#ifndef ENOTSUP# define ENOTSUP ENOSYS#endif#include <stddef.h> #ifdef HAVE_STDLIB_H#include <stdlib.h>#endif #ifdef HAVE_STDINT_H#include <stdint.h>#endif #ifdef HAVE_STRING_H#include <string.h>#endif #ifdef HAVE_INTTYPES_H#include <inttypes.h>#endif #include "simple-object-common.h" /* ELF structures and constants. */ /* 32-bit ELF file header. */ typedef struct { unsigned char e_ident[16]; /* ELF "magic number" */ unsigned char e_type[2]; /* Identifies object file type */ unsigned char e_machine[2]; /* Specifies required architecture */ unsigned char e_version[4]; /* Identifies object file version */ unsigned char e_entry[4]; /* Entry point virtual address */ unsigned char e_phoff[4]; /* Program header table file offset */ unsigned char e_shoff[4]; /* Section header table file offset */ unsigned char e_flags[4]; /* Processor-specific flags */ unsigned char e_ehsize[2]; /* ELF header size in bytes */ unsigned char e_phentsize[2]; /* Program header table entry size */ unsigned char e_phnum[2]; /* Program header table entry count */ unsigned char e_shentsize[2]; /* Section header table entry size */ unsigned char e_shnum[2]; /* Section header table entry count */ unsigned char e_shstrndx[2]; /* Section header string table index */} Elf32_External_Ehdr; /* 64-bit ELF file header. */ typedef struct { unsigned char e_ident[16]; /* ELF "magic number" */ unsigned char e_type[2]; /* Identifies object file type */ unsigned char e_machine[2]; /* Specifies required architecture */ unsigned char e_version[4]; /* Identifies object file version */ unsigned char e_entry[8]; /* Entry point virtual address */ unsigned char e_phoff[8]; /* Program header table file offset */ unsigned char e_shoff[8]; /* Section header table file offset */ unsigned char e_flags[4]; /* Processor-specific flags */ unsigned char e_ehsize[2]; /* ELF header size in bytes */ unsigned char e_phentsize[2]; /* Program header table entry size */ unsigned char e_phnum[2]; /* Program header table entry count */ unsigned char e_shentsize[2]; /* Section header table entry size */ unsigned char e_shnum[2]; /* Section header table entry count */ unsigned char e_shstrndx[2]; /* Section header string table index */} Elf64_External_Ehdr; /* Indexes and values in e_ident field of Ehdr. */ #define EI_MAG0 0 /* File identification byte 0 index */#define ELFMAG0 0x7F /* Magic number byte 0 */ #define EI_MAG1 1 /* File identification byte 1 index */#define ELFMAG1 'E' /* Magic number byte 1 */ #define EI_MAG2 2 /* File identification byte 2 index */#define ELFMAG2 'L' /* Magic number byte 2 */ #define EI_MAG3 3 /* File identification byte 3 index */#define ELFMAG3 'F' /* Magic number byte 3 */ #define EI_CLASS 4 /* File class */#define ELFCLASSNONE 0 /* Invalid class */#define ELFCLASS32 1 /* 32-bit objects */#define ELFCLASS64 2 /* 64-bit objects */ #define EI_DATA 5 /* Data encoding */#define ELFDATANONE 0 /* Invalid data encoding */#define ELFDATA2LSB 1 /* 2's complement, little endian */#define ELFDATA2MSB 2 /* 2's complement, big endian */ #define EI_VERSION 6 /* File version */#define EV_CURRENT 1 /* Current version */ #define EI_OSABI 7 /* Operating System/ABI indication */ /* Values for e_type field of Ehdr. */ #define ET_REL 1 /* Relocatable file */ /* Values for e_machine field of Ehdr. */ #define EM_SPARC 2 /* SUN SPARC */#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ /* Special section index values. */ #define SHN_UNDEF 0 /* Undefined section */#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */#define SHN_HIRESERVE 0xFFFF /* End of reserved indices */ /* 32-bit ELF program header. */ typedef struct { unsigned char p_type[4]; /* Identifies program segment type */ unsigned char p_offset[4]; /* Segment file offset */ unsigned char p_vaddr[4]; /* Segment virtual address */ unsigned char p_paddr[4]; /* Segment physical address */ unsigned char p_filesz[4]; /* Segment size in file */ unsigned char p_memsz[4]; /* Segment size in memory */ unsigned char p_flags[4]; /* Segment flags */ unsigned char p_align[4]; /* Segment alignment, file & memory */} Elf32_External_Phdr; /* 64-bit ELF program header. */ typedef struct { unsigned char p_type[4]; /* Identifies program segment type */ unsigned char p_flags[4]; /* Segment flags */ unsigned char p_offset[8]; /* Segment file offset */ unsigned char p_vaddr[8]; /* Segment virtual address */ unsigned char p_paddr[8]; /* Segment physical address */ unsigned char p_filesz[8]; /* Segment size in file */ unsigned char p_memsz[8]; /* Segment size in memory */ unsigned char p_align[8]; /* Segment alignment, file & memory */} Elf64_External_Phdr; /* 32-bit ELF section header */ typedef struct { unsigned char sh_name[4]; /* Section name, index in string tbl */ unsigned char sh_type[4]; /* Type of section */ unsigned char sh_flags[4]; /* Miscellaneous section attributes */ unsigned char sh_addr[4]; /* Section virtual addr at execution */ unsigned char sh_offset[4]; /* Section file offset */ unsigned char sh_size[4]; /* Size of section in bytes */ unsigned char sh_link[4]; /* Index of another section */ unsigned char sh_info[4]; /* Additional section information */ unsigned char sh_addralign[4]; /* Section alignment */ unsigned char sh_entsize[4]; /* Entry size if section holds table */} Elf32_External_Shdr; /* 64-bit ELF section header. */ typedef struct { unsigned char sh_name[4]; /* Section name, index in string tbl */ unsigned char sh_type[4]; /* Type of section */ unsigned char sh_flags[8]; /* Miscellaneous section attributes */ unsigned char sh_addr[8]; /* Section virtual addr at execution */ unsigned char sh_offset[8]; /* Section file offset */ unsigned char sh_size[8]; /* Size of section in bytes */ unsigned char sh_link[4]; /* Index of another section */ unsigned char sh_info[4]; /* Additional section information */ unsigned char sh_addralign[8]; /* Section alignment */ unsigned char sh_entsize[8]; /* Entry size if section holds table */} Elf64_External_Shdr; /* Values for sh_type field. */ #define SHT_NULL 0 /* Section header table entry unused */#define SHT_PROGBITS 1 /* Program data */#define SHT_SYMTAB 2 /* Link editing symbol table */#define SHT_STRTAB 3 /* A string table */#define SHT_RELA 4 /* Relocation entries with addends */#define SHT_REL 9 /* Relocation entries, no addends */#define SHT_GROUP 17 /* Section contains a section group */#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ /* Values for sh_flags field. */ #define SHF_INFO_LINK 0x00000040 /* `sh_info' contains SHT index */#define SHF_EXECINSTR 0x00000004 /* Executable section. */#define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this section from executable and shared library that it builds when those objects are not to be further relocated. *//* Symbol table entry. */ typedef struct{ unsigned char st_name[4]; /* Symbol name (string tbl index) */ unsigned char st_value[4]; /* Symbol value */ unsigned char st_size[4]; /* Symbol size */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ unsigned char st_shndx[2]; /* Section index */} Elf32_External_Sym; typedef struct{ unsigned char st_name[4]; /* Symbol name (string tbl index) */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ unsigned char st_shndx[2]; /* Section index */ unsigned char st_value[8]; /* Symbol value */ unsigned char st_size[8]; /* Symbol size */} Elf64_External_Sym; #define ELF_ST_BIND(val) (((unsigned char) (val)) >> 4)#define ELF_ST_TYPE(val) ((val) & 0xf)#define ELF_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) #define STT_NOTYPE 0 /* Symbol type is unspecified */#define STT_OBJECT 1 /* Symbol is a data object */#define STT_FUNC 2 /* Symbol is a code object */#define STT_TLS 6 /* Thread local data object */#define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */ #define STB_LOCAL 0 /* Local symbol */#define STB_GLOBAL 1 /* Global symbol */#define STB_WEAK 2 /* Weak global */ #define STV_DEFAULT 0 /* Visibility is specified by binding type */#define STV_HIDDEN 2 /* Can only be seen inside currect component */ /* Functions to fetch and store different ELF types, depending on the endianness and size. */ struct elf_type_functions{ unsigned short (*fetch_Elf_Half) (const unsigned char *); unsigned int (*fetch_Elf_Word) (const unsigned char *); ulong_type (*fetch_Elf_Addr) (const unsigned char *); void (*set_Elf_Half) (unsigned char *, unsigned short); void (*set_Elf_Word) (unsigned char *, unsigned int); void (*set_Elf_Addr) (unsigned char *, ulong_type);}; static const struct elf_type_functions elf_big_32_functions ={ simple_object_fetch_big_16, simple_object_fetch_big_32, simple_object_fetch_big_32_ulong, simple_object_set_big_16, simple_object_set_big_32, simple_object_set_big_32_ulong}; static const struct elf_type_functions elf_little_32_functions ={ simple_object_fetch_little_16, simple_object_fetch_little_32, simple_object_fetch_little_32_ulong, simple_object_set_little_16, simple_object_set_little_32, simple_object_set_little_32_ulong}; #ifdef UNSIGNED_64BIT_TYPE static const struct elf_type_functions elf_big_64_functions ={ simple_object_fetch_big_16, simple_object_fetch_big_32, simple_object_fetch_big_64, simple_object_set_big_16, simple_object_set_big_32, simple_object_set_big_64}; static const struct elf_type_functions elf_little_64_functions ={ simple_object_fetch_little_16, simple_object_fetch_little_32, simple_object_fetch_little_64, simple_object_set_little_16, simple_object_set_little_32, simple_object_set_little_64}; #endif /* Hideous macro to fetch the value of a field from an external ELF struct of some sort. TYPEFUNCS is the set of type functions. BUFFER points to the external data. STRUCTTYPE is the appropriate struct type. FIELD is a field within the struct. TYPE is the type of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \ ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD))) /* Even more hideous macro to fetch the value of FIELD from BUFFER. SIZE is 32 or 64. STRUCTTYPE is the name of the struct from elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in the struct. TYPE is the type of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, \ FIELD, TYPE) \ ELF_FETCH_STRUCT_FIELD (TYPEFUNCS, \ Elf ## SIZE ## _External_ ## STRUCTTYPE, \ FIELD, BUFFER, TYPE) /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value. */ #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, \ FIELD, TYPE) \ ((CLASS) == ELFCLASS32 \ ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \ TYPE) \ : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \ TYPE)) /* Hideous macro to set the value of a field in an external ELF structure to VAL. TYPEFUNCS is the set of type functions. BUFFER points to the external data. STRUCTTYPE is the appropriate structure type. FIELD is a field within the struct. TYPE is the type of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \ (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL)) /* Even more hideous macro to set the value of FIELD in BUFFER to VAL. SIZE is 32 or 64. STRUCTTYPE is the name of the struct from elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in the struct. TYPE is the type of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \ TYPE, VAL) \ ELF_SET_STRUCT_FIELD (TYPEFUNCS, \ Elf ## SIZE ## _External_ ## STRUCTTYPE, \ FIELD, BUFFER, TYPE, VAL) /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value. */ #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD, \ TYPE, VAL) \ ((CLASS) == ELFCLASS32 \ ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \ TYPE, VAL) \ : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \ TYPE, VAL)) /* Private data for an simple_object_read. */ struct simple_object_elf_read{ /* Type functions. */ const struct elf_type_functions* type_functions; /* Elf data. */ unsigned char ei_data; /* Elf class. */ unsigned char ei_class; /* ELF OS ABI. */ unsigned char ei_osabi; /* Elf machine number. */ unsigned short machine; /* Processor specific flags. */ unsigned int flags; /* File offset of section headers. */ ulong_type shoff; /* Number of sections. */ unsigned int shnum; /* Index of string table section header. */ unsigned int shstrndx;}; /* Private data for an simple_object_attributes. */ struct simple_object_elf_attributes{ /* Type functions. */ const struct elf_type_functions* type_functions; /* Elf data. */ unsigned char ei_data; /* Elf class. */ unsigned char ei_class; /* ELF OS ABI. */ unsigned char ei_osabi; /* Elf machine number. */ unsigned short machine; /* Processor specific flags. */ unsigned int flags;}; /* Private data for an simple_object_write. */ struct simple_object_elf_write{ struct simple_object_elf_attributes attrs; unsigned char *shdrs;}; /* See if we have an ELF file. */ 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){ unsigned char ei_data; unsigned char ei_class; const struct elf_type_functions *type_functions; unsigned char ehdr[sizeof (Elf64_External_Ehdr)]; struct simple_object_elf_read *eor; if (header[EI_MAG0] != ELFMAG0 || header[EI_MAG1] != ELFMAG1 || header[EI_MAG2] != ELFMAG2 || header[EI_MAG3] != ELFMAG3 || header[EI_VERSION] != EV_CURRENT) { *errmsg = NULL; *err = 0; return NULL; } ei_data = header[EI_DATA]; if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB) { *errmsg = "unknown ELF endianness"; *err = 0; return NULL; } ei_class = header[EI_CLASS]; switch (ei_class) { case ELFCLASS32: type_functions = (ei_data == ELFDATA2LSB ? &elf_little_32_functions : &elf_big_32_functions); break; case ELFCLASS64:#ifndef UNSIGNED_64BIT_TYPE *errmsg = "64-bit ELF objects not supported"; *err = 0; return NULL;#else type_functions = (ei_data == ELFDATA2LSB ? &elf_little_64_functions : &elf_big_64_functions); break;#endif default: *errmsg = "unrecognized ELF size"; *err = 0; return NULL; } if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr, errmsg, err)) return NULL; eor = XNEW (struct simple_object_elf_read); eor->type_functions = type_functions; eor->ei_data = ei_data; eor->ei_class = ei_class; eor->ei_osabi = header[EI_OSABI]; eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_machine, Elf_Half); eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_flags, Elf_Word); eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_shoff, Elf_Addr); eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_shnum, Elf_Half); eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_shstrndx, Elf_Half); Lines 1–500 of 1684. Load more
/* simple-object-elf.c -- routines to manipulate ELF object files. Copyright (C) 2010-2026 Free Software Foundation, Inc. Written by Ian Lance Taylor, Google. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include "libiberty.h" #include "simple-object.h" #include <errno.h> /* mingw.org's MinGW doesn't have ENOTSUP. */ #ifndef ENOTSUP # define ENOTSUP ENOSYS #endif #include <stddef.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif #ifdef HAVE_STDINT_H #include <stdint.h> #endif #ifdef HAVE_STRING_H #include <string.h> #endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif #include "simple-object-common.h" /* ELF structures and constants. */ /* 32-bit ELF file header. */ typedef struct { unsigned char e_ident[16]; /* ELF "magic number" */ unsigned char e_type[2]; /* Identifies object file type */ unsigned char e_machine[2]; /* Specifies required architecture */ unsigned char e_version[4]; /* Identifies object file version */ unsigned char e_entry[4]; /* Entry point virtual address */ unsigned char e_phoff[4]; /* Program header table file offset */ unsigned char e_shoff[4]; /* Section header table file offset */ unsigned char e_flags[4]; /* Processor-specific flags */ unsigned char e_ehsize[2]; /* ELF header size in bytes */ unsigned char e_phentsize[2]; /* Program header table entry size */ unsigned char e_phnum[2]; /* Program header table entry count */ unsigned char e_shentsize[2]; /* Section header table entry size */ unsigned char e_shnum[2]; /* Section header table entry count */ unsigned char e_shstrndx[2]; /* Section header string table index */ } Elf32_External_Ehdr; /* 64-bit ELF file header. */ typedef struct { unsigned char e_ident[16]; /* ELF "magic number" */ unsigned char e_type[2]; /* Identifies object file type */ unsigned char e_machine[2]; /* Specifies required architecture */ unsigned char e_version[4]; /* Identifies object file version */ unsigned char e_entry[8]; /* Entry point virtual address */ unsigned char e_phoff[8]; /* Program header table file offset */ unsigned char e_shoff[8]; /* Section header table file offset */ unsigned char e_flags[4]; /* Processor-specific flags */ unsigned char e_ehsize[2]; /* ELF header size in bytes */ unsigned char e_phentsize[2]; /* Program header table entry size */ unsigned char e_phnum[2]; /* Program header table entry count */ unsigned char e_shentsize[2]; /* Section header table entry size */ unsigned char e_shnum[2]; /* Section header table entry count */ unsigned char e_shstrndx[2]; /* Section header string table index */ } Elf64_External_Ehdr; /* Indexes and values in e_ident field of Ehdr. */ #define EI_MAG0 0 /* File identification byte 0 index */ #define ELFMAG0 0x7F /* Magic number byte 0 */ #define EI_MAG1 1 /* File identification byte 1 index */ #define ELFMAG1 'E' /* Magic number byte 1 */ #define EI_MAG2 2 /* File identification byte 2 index */ #define ELFMAG2 'L' /* Magic number byte 2 */ #define EI_MAG3 3 /* File identification byte 3 index */ #define ELFMAG3 'F' /* Magic number byte 3 */ #define EI_CLASS 4 /* File class */ #define ELFCLASSNONE 0 /* Invalid class */ #define ELFCLASS32 1 /* 32-bit objects */ #define ELFCLASS64 2 /* 64-bit objects */ #define EI_DATA 5 /* Data encoding */ #define ELFDATANONE 0 /* Invalid data encoding */ #define ELFDATA2LSB 1 /* 2's complement, little endian */ #define ELFDATA2MSB 2 /* 2's complement, big endian */ #define EI_VERSION 6 /* File version */ #define EV_CURRENT 1 /* Current version */ #define EI_OSABI 7 /* Operating System/ABI indication */ /* Values for e_type field of Ehdr. */ #define ET_REL 1 /* Relocatable file */ /* Values for e_machine field of Ehdr. */ #define EM_SPARC 2 /* SUN SPARC */ #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ /* Special section index values. */ #define SHN_UNDEF 0 /* Undefined section */ #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ #define SHN_COMMON 0xFFF2 /* Associated symbol is in common */ #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ #define SHN_HIRESERVE 0xFFFF /* End of reserved indices */ /* 32-bit ELF program header. */ typedef struct { unsigned char p_type[4]; /* Identifies program segment type */ unsigned char p_offset[4]; /* Segment file offset */ unsigned char p_vaddr[4]; /* Segment virtual address */ unsigned char p_paddr[4]; /* Segment physical address */ unsigned char p_filesz[4]; /* Segment size in file */ unsigned char p_memsz[4]; /* Segment size in memory */ unsigned char p_flags[4]; /* Segment flags */ unsigned char p_align[4]; /* Segment alignment, file & memory */ } Elf32_External_Phdr; /* 64-bit ELF program header. */ typedef struct { unsigned char p_type[4]; /* Identifies program segment type */ unsigned char p_flags[4]; /* Segment flags */ unsigned char p_offset[8]; /* Segment file offset */ unsigned char p_vaddr[8]; /* Segment virtual address */ unsigned char p_paddr[8]; /* Segment physical address */ unsigned char p_filesz[8]; /* Segment size in file */ unsigned char p_memsz[8]; /* Segment size in memory */ unsigned char p_align[8]; /* Segment alignment, file & memory */ } Elf64_External_Phdr; /* 32-bit ELF section header */ typedef struct { unsigned char sh_name[4]; /* Section name, index in string tbl */ unsigned char sh_type[4]; /* Type of section */ unsigned char sh_flags[4]; /* Miscellaneous section attributes */ unsigned char sh_addr[4]; /* Section virtual addr at execution */ unsigned char sh_offset[4]; /* Section file offset */ unsigned char sh_size[4]; /* Size of section in bytes */ unsigned char sh_link[4]; /* Index of another section */ unsigned char sh_info[4]; /* Additional section information */ unsigned char sh_addralign[4]; /* Section alignment */ unsigned char sh_entsize[4]; /* Entry size if section holds table */ } Elf32_External_Shdr; /* 64-bit ELF section header. */ typedef struct { unsigned char sh_name[4]; /* Section name, index in string tbl */ unsigned char sh_type[4]; /* Type of section */ unsigned char sh_flags[8]; /* Miscellaneous section attributes */ unsigned char sh_addr[8]; /* Section virtual addr at execution */ unsigned char sh_offset[8]; /* Section file offset */ unsigned char sh_size[8]; /* Size of section in bytes */ unsigned char sh_link[4]; /* Index of another section */ unsigned char sh_info[4]; /* Additional section information */ unsigned char sh_addralign[8]; /* Section alignment */ unsigned char sh_entsize[8]; /* Entry size if section holds table */ } Elf64_External_Shdr; /* Values for sh_type field. */ #define SHT_NULL 0 /* Section header table entry unused */ #define SHT_PROGBITS 1 /* Program data */ #define SHT_SYMTAB 2 /* Link editing symbol table */ #define SHT_STRTAB 3 /* A string table */ #define SHT_RELA 4 /* Relocation entries with addends */ #define SHT_REL 9 /* Relocation entries, no addends */ #define SHT_GROUP 17 /* Section contains a section group */ #define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ /* Values for sh_flags field. */ #define SHF_INFO_LINK 0x00000040 /* `sh_info' contains SHT index */ #define SHF_EXECINSTR 0x00000004 /* Executable section. */ #define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this section from executable and shared library that it builds when those objects are not to be further relocated. */ /* Symbol table entry. */ typedef struct { unsigned char st_name[4]; /* Symbol name (string tbl index) */ unsigned char st_value[4]; /* Symbol value */ unsigned char st_size[4]; /* Symbol size */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ unsigned char st_shndx[2]; /* Section index */ } Elf32_External_Sym; typedef struct { unsigned char st_name[4]; /* Symbol name (string tbl index) */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ unsigned char st_shndx[2]; /* Section index */ unsigned char st_value[8]; /* Symbol value */ unsigned char st_size[8]; /* Symbol size */ } Elf64_External_Sym; #define ELF_ST_BIND(val) (((unsigned char) (val)) >> 4) #define ELF_ST_TYPE(val) ((val) & 0xf) #define ELF_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) #define STT_NOTYPE 0 /* Symbol type is unspecified */ #define STT_OBJECT 1 /* Symbol is a data object */ #define STT_FUNC 2 /* Symbol is a code object */ #define STT_TLS 6 /* Thread local data object */ #define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */ #define STB_LOCAL 0 /* Local symbol */ #define STB_GLOBAL 1 /* Global symbol */ #define STB_WEAK 2 /* Weak global */ #define STV_DEFAULT 0 /* Visibility is specified by binding type */ #define STV_HIDDEN 2 /* Can only be seen inside currect component */ /* Functions to fetch and store different ELF types, depending on the endianness and size. */ struct elf_type_functions { unsigned short (*fetch_Elf_Half) (const unsigned char *); unsigned int (*fetch_Elf_Word) (const unsigned char *); ulong_type (*fetch_Elf_Addr) (const unsigned char *); void (*set_Elf_Half) (unsigned char *, unsigned short); void (*set_Elf_Word) (unsigned char *, unsigned int); void (*set_Elf_Addr) (unsigned char *, ulong_type); }; static const struct elf_type_functions elf_big_32_functions = { simple_object_fetch_big_16, simple_object_fetch_big_32, simple_object_fetch_big_32_ulong, simple_object_set_big_16, simple_object_set_big_32, simple_object_set_big_32_ulong }; static const struct elf_type_functions elf_little_32_functions = { simple_object_fetch_little_16, simple_object_fetch_little_32, simple_object_fetch_little_32_ulong, simple_object_set_little_16, simple_object_set_little_32, simple_object_set_little_32_ulong }; #ifdef UNSIGNED_64BIT_TYPE static const struct elf_type_functions elf_big_64_functions = { simple_object_fetch_big_16, simple_object_fetch_big_32, simple_object_fetch_big_64, simple_object_set_big_16, simple_object_set_big_32, simple_object_set_big_64 }; static const struct elf_type_functions elf_little_64_functions = { simple_object_fetch_little_16, simple_object_fetch_little_32, simple_object_fetch_little_64, simple_object_set_little_16, simple_object_set_little_32, simple_object_set_little_64 }; #endif /* Hideous macro to fetch the value of a field from an external ELF struct of some sort. TYPEFUNCS is the set of type functions. BUFFER points to the external data. STRUCTTYPE is the appropriate struct type. FIELD is a field within the struct. TYPE is the type of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \ ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD))) /* Even more hideous macro to fetch the value of FIELD from BUFFER. SIZE is 32 or 64. STRUCTTYPE is the name of the struct from elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in the struct. TYPE is the type of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, \ FIELD, TYPE) \ ELF_FETCH_STRUCT_FIELD (TYPEFUNCS, \ Elf ## SIZE ## _External_ ## STRUCTTYPE, \ FIELD, BUFFER, TYPE) /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value. */ #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, \ FIELD, TYPE) \ ((CLASS) == ELFCLASS32 \ ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \ TYPE) \ : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \ TYPE)) /* Hideous macro to set the value of a field in an external ELF structure to VAL. TYPEFUNCS is the set of type functions. BUFFER points to the external data. STRUCTTYPE is the appropriate structure type. FIELD is a field within the struct. TYPE is the type of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \ (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL)) /* Even more hideous macro to set the value of FIELD in BUFFER to VAL. SIZE is 32 or 64. STRUCTTYPE is the name of the struct from elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in the struct. TYPE is the type of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */ #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \ TYPE, VAL) \ ELF_SET_STRUCT_FIELD (TYPEFUNCS, \ Elf ## SIZE ## _External_ ## STRUCTTYPE, \ FIELD, BUFFER, TYPE, VAL) /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value. */ #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD, \ TYPE, VAL) \ ((CLASS) == ELFCLASS32 \ ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \ TYPE, VAL) \ : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \ TYPE, VAL)) /* Private data for an simple_object_read. */ struct simple_object_elf_read { /* Type functions. */ const struct elf_type_functions* type_functions; /* Elf data. */ unsigned char ei_data; /* Elf class. */ unsigned char ei_class; /* ELF OS ABI. */ unsigned char ei_osabi; /* Elf machine number. */ unsigned short machine; /* Processor specific flags. */ unsigned int flags; /* File offset of section headers. */ ulong_type shoff; /* Number of sections. */ unsigned int shnum; /* Index of string table section header. */ unsigned int shstrndx; }; /* Private data for an simple_object_attributes. */ struct simple_object_elf_attributes { /* Type functions. */ const struct elf_type_functions* type_functions; /* Elf data. */ unsigned char ei_data; /* Elf class. */ unsigned char ei_class; /* ELF OS ABI. */ unsigned char ei_osabi; /* Elf machine number. */ unsigned short machine; /* Processor specific flags. */ unsigned int flags; }; /* Private data for an simple_object_write. */ struct simple_object_elf_write { struct simple_object_elf_attributes attrs; unsigned char *shdrs; }; /* See if we have an ELF file. */ 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) { unsigned char ei_data; unsigned char ei_class; const struct elf_type_functions *type_functions; unsigned char ehdr[sizeof (Elf64_External_Ehdr)]; struct simple_object_elf_read *eor; if (header[EI_MAG0] != ELFMAG0 || header[EI_MAG1] != ELFMAG1 || header[EI_MAG2] != ELFMAG2 || header[EI_MAG3] != ELFMAG3 || header[EI_VERSION] != EV_CURRENT) { *errmsg = NULL; *err = 0; return NULL; } ei_data = header[EI_DATA]; if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB) { *errmsg = "unknown ELF endianness"; *err = 0; return NULL; } ei_class = header[EI_CLASS]; switch (ei_class) { case ELFCLASS32: type_functions = (ei_data == ELFDATA2LSB ? &elf_little_32_functions : &elf_big_32_functions); break; case ELFCLASS64: #ifndef UNSIGNED_64BIT_TYPE *errmsg = "64-bit ELF objects not supported"; *err = 0; return NULL; #else type_functions = (ei_data == ELFDATA2LSB ? &elf_little_64_functions : &elf_big_64_functions); break; #endif default: *errmsg = "unrecognized ELF size"; *err = 0; return NULL; } if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr, errmsg, err)) return NULL; eor = XNEW (struct simple_object_elf_read); eor->type_functions = type_functions; eor->ei_data = ei_data; eor->ei_class = ei_class; eor->ei_osabi = header[EI_OSABI]; eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_machine, Elf_Half); eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_flags, Elf_Word); eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_shoff, Elf_Addr); eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_shnum, Elf_Half); eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr, e_shstrndx, Elf_Half);