Wolfgang Thallergcc16 merge934c3885 months agoHistory
1684 lines · 51.0 KB · C
RawDownload
/* 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t