Home | History | Annotate | Line # | Download | only in libiberty
simple-object-elf.c revision 1.1.1.1
      1  1.1  christos /* simple-object-elf.c -- routines to manipulate ELF object files.
      2  1.1  christos    Copyright 2010 Free Software Foundation, Inc.
      3  1.1  christos    Written by Ian Lance Taylor, Google.
      4  1.1  christos 
      5  1.1  christos This program is free software; you can redistribute it and/or modify it
      6  1.1  christos under the terms of the GNU General Public License as published by the
      7  1.1  christos Free Software Foundation; either version 2, or (at your option) any
      8  1.1  christos later version.
      9  1.1  christos 
     10  1.1  christos This program is distributed in the hope that it will be useful,
     11  1.1  christos but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  1.1  christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1  christos GNU General Public License for more details.
     14  1.1  christos 
     15  1.1  christos You should have received a copy of the GNU General Public License
     16  1.1  christos along with this program; if not, write to the Free Software
     17  1.1  christos Foundation, 51 Franklin Street - Fifth Floor,
     18  1.1  christos Boston, MA 02110-1301, USA.  */
     19  1.1  christos 
     20  1.1  christos #include "config.h"
     21  1.1  christos #include "libiberty.h"
     22  1.1  christos #include "simple-object.h"
     23  1.1  christos 
     24  1.1  christos #include <errno.h>
     25  1.1  christos #include <stddef.h>
     26  1.1  christos 
     27  1.1  christos #ifdef HAVE_STDLIB_H
     28  1.1  christos #include <stdlib.h>
     29  1.1  christos #endif
     30  1.1  christos 
     31  1.1  christos #ifdef HAVE_STDINT_H
     32  1.1  christos #include <stdint.h>
     33  1.1  christos #endif
     34  1.1  christos 
     35  1.1  christos #ifdef HAVE_STRING_H
     36  1.1  christos #include <string.h>
     37  1.1  christos #endif
     38  1.1  christos 
     39  1.1  christos #ifdef HAVE_INTTYPES_H
     40  1.1  christos #include <inttypes.h>
     41  1.1  christos #endif
     42  1.1  christos 
     43  1.1  christos #include "simple-object-common.h"
     44  1.1  christos 
     45  1.1  christos /* ELF structures and constants.  */
     46  1.1  christos 
     47  1.1  christos /* 32-bit ELF file header.  */
     48  1.1  christos 
     49  1.1  christos typedef struct {
     50  1.1  christos   unsigned char	e_ident[16];		/* ELF "magic number" */
     51  1.1  christos   unsigned char	e_type[2];		/* Identifies object file type */
     52  1.1  christos   unsigned char	e_machine[2];		/* Specifies required architecture */
     53  1.1  christos   unsigned char	e_version[4];		/* Identifies object file version */
     54  1.1  christos   unsigned char	e_entry[4];		/* Entry point virtual address */
     55  1.1  christos   unsigned char	e_phoff[4];		/* Program header table file offset */
     56  1.1  christos   unsigned char	e_shoff[4];		/* Section header table file offset */
     57  1.1  christos   unsigned char	e_flags[4];		/* Processor-specific flags */
     58  1.1  christos   unsigned char	e_ehsize[2];		/* ELF header size in bytes */
     59  1.1  christos   unsigned char	e_phentsize[2];		/* Program header table entry size */
     60  1.1  christos   unsigned char	e_phnum[2];		/* Program header table entry count */
     61  1.1  christos   unsigned char	e_shentsize[2];		/* Section header table entry size */
     62  1.1  christos   unsigned char	e_shnum[2];		/* Section header table entry count */
     63  1.1  christos   unsigned char	e_shstrndx[2];		/* Section header string table index */
     64  1.1  christos } Elf32_External_Ehdr;
     65  1.1  christos 
     66  1.1  christos /* 64-bit ELF file header.  */
     67  1.1  christos 
     68  1.1  christos typedef struct {
     69  1.1  christos   unsigned char	e_ident[16];		/* ELF "magic number" */
     70  1.1  christos   unsigned char	e_type[2];		/* Identifies object file type */
     71  1.1  christos   unsigned char	e_machine[2];		/* Specifies required architecture */
     72  1.1  christos   unsigned char	e_version[4];		/* Identifies object file version */
     73  1.1  christos   unsigned char	e_entry[8];		/* Entry point virtual address */
     74  1.1  christos   unsigned char	e_phoff[8];		/* Program header table file offset */
     75  1.1  christos   unsigned char	e_shoff[8];		/* Section header table file offset */
     76  1.1  christos   unsigned char	e_flags[4];		/* Processor-specific flags */
     77  1.1  christos   unsigned char	e_ehsize[2];		/* ELF header size in bytes */
     78  1.1  christos   unsigned char	e_phentsize[2];		/* Program header table entry size */
     79  1.1  christos   unsigned char	e_phnum[2];		/* Program header table entry count */
     80  1.1  christos   unsigned char	e_shentsize[2];		/* Section header table entry size */
     81  1.1  christos   unsigned char	e_shnum[2];		/* Section header table entry count */
     82  1.1  christos   unsigned char	e_shstrndx[2];		/* Section header string table index */
     83  1.1  christos } Elf64_External_Ehdr;
     84  1.1  christos 
     85  1.1  christos /* Indexes and values in e_ident field of Ehdr.  */
     86  1.1  christos 
     87  1.1  christos #define EI_MAG0		0	/* File identification byte 0 index */
     88  1.1  christos #define ELFMAG0		   0x7F	/* Magic number byte 0 */
     89  1.1  christos 
     90  1.1  christos #define EI_MAG1		1	/* File identification byte 1 index */
     91  1.1  christos #define ELFMAG1		    'E'	/* Magic number byte 1 */
     92  1.1  christos 
     93  1.1  christos #define EI_MAG2		2	/* File identification byte 2 index */
     94  1.1  christos #define ELFMAG2		    'L'	/* Magic number byte 2 */
     95  1.1  christos 
     96  1.1  christos #define EI_MAG3		3	/* File identification byte 3 index */
     97  1.1  christos #define ELFMAG3		    'F'	/* Magic number byte 3 */
     98  1.1  christos 
     99  1.1  christos #define EI_CLASS	4	/* File class */
    100  1.1  christos #define ELFCLASSNONE	      0	/* Invalid class */
    101  1.1  christos #define ELFCLASS32	      1	/* 32-bit objects */
    102  1.1  christos #define ELFCLASS64	      2	/* 64-bit objects */
    103  1.1  christos 
    104  1.1  christos #define EI_DATA		5	/* Data encoding */
    105  1.1  christos #define ELFDATANONE	      0	/* Invalid data encoding */
    106  1.1  christos #define ELFDATA2LSB	      1	/* 2's complement, little endian */
    107  1.1  christos #define ELFDATA2MSB	      2	/* 2's complement, big endian */
    108  1.1  christos 
    109  1.1  christos #define EI_VERSION	6	/* File version */
    110  1.1  christos #define EV_CURRENT	1		/* Current version */
    111  1.1  christos 
    112  1.1  christos #define EI_OSABI	7	/* Operating System/ABI indication */
    113  1.1  christos 
    114  1.1  christos /* Values for e_type field of Ehdr.  */
    115  1.1  christos 
    116  1.1  christos #define ET_REL		1	/* Relocatable file */
    117  1.1  christos 
    118  1.1  christos /* Values for e_machine field of Ehdr.  */
    119  1.1  christos 
    120  1.1  christos #define EM_SPARC	  2	/* SUN SPARC */
    121  1.1  christos #define EM_SPARC32PLUS	 18	/* Sun's "v8plus" */
    122  1.1  christos 
    123  1.1  christos /* Special section index values.  */
    124  1.1  christos 
    125  1.1  christos #define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
    126  1.1  christos #define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
    127  1.1  christos 
    128  1.1  christos /* 32-bit ELF program header.  */
    129  1.1  christos 
    130  1.1  christos typedef struct {
    131  1.1  christos   unsigned char	p_type[4];		/* Identifies program segment type */
    132  1.1  christos   unsigned char	p_offset[4];		/* Segment file offset */
    133  1.1  christos   unsigned char	p_vaddr[4];		/* Segment virtual address */
    134  1.1  christos   unsigned char	p_paddr[4];		/* Segment physical address */
    135  1.1  christos   unsigned char	p_filesz[4];		/* Segment size in file */
    136  1.1  christos   unsigned char	p_memsz[4];		/* Segment size in memory */
    137  1.1  christos   unsigned char	p_flags[4];		/* Segment flags */
    138  1.1  christos   unsigned char	p_align[4];		/* Segment alignment, file & memory */
    139  1.1  christos } Elf32_External_Phdr;
    140  1.1  christos 
    141  1.1  christos /* 64-bit ELF program header.  */
    142  1.1  christos 
    143  1.1  christos typedef struct {
    144  1.1  christos   unsigned char	p_type[4];		/* Identifies program segment type */
    145  1.1  christos   unsigned char	p_flags[4];		/* Segment flags */
    146  1.1  christos   unsigned char	p_offset[8];		/* Segment file offset */
    147  1.1  christos   unsigned char	p_vaddr[8];		/* Segment virtual address */
    148  1.1  christos   unsigned char	p_paddr[8];		/* Segment physical address */
    149  1.1  christos   unsigned char	p_filesz[8];		/* Segment size in file */
    150  1.1  christos   unsigned char	p_memsz[8];		/* Segment size in memory */
    151  1.1  christos   unsigned char	p_align[8];		/* Segment alignment, file & memory */
    152  1.1  christos } Elf64_External_Phdr;
    153  1.1  christos 
    154  1.1  christos /* 32-bit ELF section header */
    155  1.1  christos 
    156  1.1  christos typedef struct {
    157  1.1  christos   unsigned char	sh_name[4];		/* Section name, index in string tbl */
    158  1.1  christos   unsigned char	sh_type[4];		/* Type of section */
    159  1.1  christos   unsigned char	sh_flags[4];		/* Miscellaneous section attributes */
    160  1.1  christos   unsigned char	sh_addr[4];		/* Section virtual addr at execution */
    161  1.1  christos   unsigned char	sh_offset[4];		/* Section file offset */
    162  1.1  christos   unsigned char	sh_size[4];		/* Size of section in bytes */
    163  1.1  christos   unsigned char	sh_link[4];		/* Index of another section */
    164  1.1  christos   unsigned char	sh_info[4];		/* Additional section information */
    165  1.1  christos   unsigned char	sh_addralign[4];	/* Section alignment */
    166  1.1  christos   unsigned char	sh_entsize[4];		/* Entry size if section holds table */
    167  1.1  christos } Elf32_External_Shdr;
    168  1.1  christos 
    169  1.1  christos /* 64-bit ELF section header.  */
    170  1.1  christos 
    171  1.1  christos typedef struct {
    172  1.1  christos   unsigned char	sh_name[4];		/* Section name, index in string tbl */
    173  1.1  christos   unsigned char	sh_type[4];		/* Type of section */
    174  1.1  christos   unsigned char	sh_flags[8];		/* Miscellaneous section attributes */
    175  1.1  christos   unsigned char	sh_addr[8];		/* Section virtual addr at execution */
    176  1.1  christos   unsigned char	sh_offset[8];		/* Section file offset */
    177  1.1  christos   unsigned char	sh_size[8];		/* Size of section in bytes */
    178  1.1  christos   unsigned char	sh_link[4];		/* Index of another section */
    179  1.1  christos   unsigned char	sh_info[4];		/* Additional section information */
    180  1.1  christos   unsigned char	sh_addralign[8];	/* Section alignment */
    181  1.1  christos   unsigned char	sh_entsize[8];		/* Entry size if section holds table */
    182  1.1  christos } Elf64_External_Shdr;
    183  1.1  christos 
    184  1.1  christos /* Values for sh_type field.  */
    185  1.1  christos 
    186  1.1  christos #define SHT_PROGBITS	1		/* Program data */
    187  1.1  christos #define SHT_STRTAB	3		/* A string table */
    188  1.1  christos 
    189  1.1  christos /* Functions to fetch and store different ELF types, depending on the
    190  1.1  christos    endianness and size.  */
    191  1.1  christos 
    192  1.1  christos struct elf_type_functions
    193  1.1  christos {
    194  1.1  christos   unsigned short (*fetch_Elf_Half) (const unsigned char *);
    195  1.1  christos   unsigned int (*fetch_Elf_Word) (const unsigned char *);
    196  1.1  christos   ulong_type (*fetch_Elf_Addr) (const unsigned char *);
    197  1.1  christos   void (*set_Elf_Half) (unsigned char *, unsigned short);
    198  1.1  christos   void (*set_Elf_Word) (unsigned char *, unsigned int);
    199  1.1  christos   void (*set_Elf_Addr) (unsigned char *, ulong_type);
    200  1.1  christos };
    201  1.1  christos 
    202  1.1  christos static const struct elf_type_functions elf_big_32_functions =
    203  1.1  christos {
    204  1.1  christos   simple_object_fetch_big_16,
    205  1.1  christos   simple_object_fetch_big_32,
    206  1.1  christos   simple_object_fetch_big_32_ulong,
    207  1.1  christos   simple_object_set_big_16,
    208  1.1  christos   simple_object_set_big_32,
    209  1.1  christos   simple_object_set_big_32_ulong
    210  1.1  christos };
    211  1.1  christos 
    212  1.1  christos static const struct elf_type_functions elf_little_32_functions =
    213  1.1  christos {
    214  1.1  christos   simple_object_fetch_little_16,
    215  1.1  christos   simple_object_fetch_little_32,
    216  1.1  christos   simple_object_fetch_little_32_ulong,
    217  1.1  christos   simple_object_set_little_16,
    218  1.1  christos   simple_object_set_little_32,
    219  1.1  christos   simple_object_set_little_32_ulong
    220  1.1  christos };
    221  1.1  christos 
    222  1.1  christos #ifdef UNSIGNED_64BIT_TYPE
    223  1.1  christos 
    224  1.1  christos static const struct elf_type_functions elf_big_64_functions =
    225  1.1  christos {
    226  1.1  christos   simple_object_fetch_big_16,
    227  1.1  christos   simple_object_fetch_big_32,
    228  1.1  christos   simple_object_fetch_big_64,
    229  1.1  christos   simple_object_set_big_16,
    230  1.1  christos   simple_object_set_big_32,
    231  1.1  christos   simple_object_set_big_64
    232  1.1  christos };
    233  1.1  christos 
    234  1.1  christos static const struct elf_type_functions elf_little_64_functions =
    235  1.1  christos {
    236  1.1  christos   simple_object_fetch_little_16,
    237  1.1  christos   simple_object_fetch_little_32,
    238  1.1  christos   simple_object_fetch_little_64,
    239  1.1  christos   simple_object_set_little_16,
    240  1.1  christos   simple_object_set_little_32,
    241  1.1  christos   simple_object_set_little_64
    242  1.1  christos };
    243  1.1  christos 
    244  1.1  christos #endif
    245  1.1  christos 
    246  1.1  christos /* Hideous macro to fetch the value of a field from an external ELF
    247  1.1  christos    struct of some sort.  TYPEFUNCS is the set of type functions.
    248  1.1  christos    BUFFER points to the external data.  STRUCTTYPE is the appropriate
    249  1.1  christos    struct type.  FIELD is a field within the struct.  TYPE is the type
    250  1.1  christos    of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr.  */
    251  1.1  christos 
    252  1.1  christos #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
    253  1.1  christos   ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
    254  1.1  christos 
    255  1.1  christos /* Even more hideous macro to fetch the value of FIELD from BUFFER.
    256  1.1  christos    SIZE is 32 or 64.  STRUCTTYPE is the name of the struct from
    257  1.1  christos    elf/external.h: Ehdr, Shdr, etc.  FIELD is the name of a field in
    258  1.1  christos    the struct.  TYPE is the type of the field in the struct: Elf_Half,
    259  1.1  christos    Elf_Word, or Elf_Addr.  */
    260  1.1  christos 
    261  1.1  christos #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER,	\
    262  1.1  christos 			      FIELD, TYPE)				\
    263  1.1  christos   ELF_FETCH_STRUCT_FIELD (TYPEFUNCS,					\
    264  1.1  christos 			  Elf ## SIZE ## _External_ ## STRUCTTYPE,	\
    265  1.1  christos 			  FIELD, BUFFER, TYPE)
    266  1.1  christos 
    267  1.1  christos /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value.  */
    268  1.1  christos 
    269  1.1  christos #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER,		\
    270  1.1  christos 			FIELD, TYPE)					\
    271  1.1  christos   ((CLASS) == ELFCLASS32						\
    272  1.1  christos     ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,	\
    273  1.1  christos 			     TYPE)					\
    274  1.1  christos     : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,	\
    275  1.1  christos 			     TYPE))
    276  1.1  christos 
    277  1.1  christos /* Hideous macro to set the value of a field in an external ELF
    278  1.1  christos    structure to VAL.  TYPEFUNCS is the set of type functions.  BUFFER
    279  1.1  christos    points to the external data.  STRUCTTYPE is the appropriate
    280  1.1  christos    structure type.  FIELD is a field within the struct.  TYPE is the
    281  1.1  christos    type of the field in the struct: Elf_Half, Elf_Word, or
    282  1.1  christos    Elf_Addr.  */
    283  1.1  christos 
    284  1.1  christos #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
    285  1.1  christos   (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
    286  1.1  christos 
    287  1.1  christos /* Even more hideous macro to set the value of FIELD in BUFFER to VAL.
    288  1.1  christos    SIZE is 32 or 64.  STRUCTTYPE is the name of the struct from
    289  1.1  christos    elf/external.h: Ehdr, Shdr, etc.  FIELD is the name of a field in
    290  1.1  christos    the struct.  TYPE is the type of the field in the struct: Elf_Half,
    291  1.1  christos    Elf_Word, or Elf_Addr.  */
    292  1.1  christos 
    293  1.1  christos #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
    294  1.1  christos 			    TYPE, VAL)					\
    295  1.1  christos   ELF_SET_STRUCT_FIELD (TYPEFUNCS,					\
    296  1.1  christos 			Elf ## SIZE ## _External_ ## STRUCTTYPE,	\
    297  1.1  christos 			FIELD, BUFFER, TYPE, VAL)
    298  1.1  christos 
    299  1.1  christos /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value.  */
    300  1.1  christos 
    301  1.1  christos #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD,	\
    302  1.1  christos 		      TYPE, VAL)					\
    303  1.1  christos   ((CLASS) == ELFCLASS32						\
    304  1.1  christos     ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,	\
    305  1.1  christos 			   TYPE, VAL)					\
    306  1.1  christos     : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,	\
    307  1.1  christos 			   TYPE, VAL))
    308  1.1  christos 
    309  1.1  christos /* Private data for an simple_object_read.  */
    310  1.1  christos 
    311  1.1  christos struct simple_object_elf_read
    312  1.1  christos {
    313  1.1  christos   /* Type functions.  */
    314  1.1  christos   const struct elf_type_functions* type_functions;
    315  1.1  christos   /* Elf data.  */
    316  1.1  christos   unsigned char ei_data;
    317  1.1  christos   /* Elf class.  */
    318  1.1  christos   unsigned char ei_class;
    319  1.1  christos   /* ELF OS ABI.  */
    320  1.1  christos   unsigned char ei_osabi;
    321  1.1  christos   /* Elf machine number.  */
    322  1.1  christos   unsigned short machine;
    323  1.1  christos   /* Processor specific flags.  */
    324  1.1  christos   unsigned int flags;
    325  1.1  christos   /* File offset of section headers.  */
    326  1.1  christos   ulong_type shoff;
    327  1.1  christos   /* Number of sections.  */
    328  1.1  christos   unsigned int shnum;
    329  1.1  christos   /* Index of string table section header.  */
    330  1.1  christos   unsigned int shstrndx;
    331  1.1  christos };
    332  1.1  christos 
    333  1.1  christos /* Private data for an simple_object_attributes.  */
    334  1.1  christos 
    335  1.1  christos struct simple_object_elf_attributes
    336  1.1  christos {
    337  1.1  christos   /* Type functions.  */
    338  1.1  christos   const struct elf_type_functions* type_functions;
    339  1.1  christos   /* Elf data.  */
    340  1.1  christos   unsigned char ei_data;
    341  1.1  christos   /* Elf class.  */
    342  1.1  christos   unsigned char ei_class;
    343  1.1  christos   /* ELF OS ABI.  */
    344  1.1  christos   unsigned char ei_osabi;
    345  1.1  christos   /* Elf machine number.  */
    346  1.1  christos   unsigned short machine;
    347  1.1  christos   /* Processor specific flags.  */
    348  1.1  christos   unsigned int flags;
    349  1.1  christos };
    350  1.1  christos 
    351  1.1  christos /* See if we have an ELF file.  */
    352  1.1  christos 
    353  1.1  christos static void *
    354  1.1  christos simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
    355  1.1  christos 			 int descriptor, off_t offset,
    356  1.1  christos 			 const char *segment_name ATTRIBUTE_UNUSED,
    357  1.1  christos 			 const char **errmsg, int *err)
    358  1.1  christos {
    359  1.1  christos   unsigned char ei_data;
    360  1.1  christos   unsigned char ei_class;
    361  1.1  christos   const struct elf_type_functions *type_functions;
    362  1.1  christos   unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
    363  1.1  christos   struct simple_object_elf_read *eor;
    364  1.1  christos 
    365  1.1  christos   if (header[EI_MAG0] != ELFMAG0
    366  1.1  christos       || header[EI_MAG1] != ELFMAG1
    367  1.1  christos       || header[EI_MAG2] != ELFMAG2
    368  1.1  christos       || header[EI_MAG3] != ELFMAG3
    369  1.1  christos       || header[EI_VERSION] != EV_CURRENT)
    370  1.1  christos     {
    371  1.1  christos       *errmsg = NULL;
    372  1.1  christos       *err = 0;
    373  1.1  christos       return NULL;
    374  1.1  christos     }
    375  1.1  christos 
    376  1.1  christos   ei_data = header[EI_DATA];
    377  1.1  christos   if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
    378  1.1  christos     {
    379  1.1  christos       *errmsg = "unknown ELF endianness";
    380  1.1  christos       *err = 0;
    381  1.1  christos       return NULL;
    382  1.1  christos     }
    383  1.1  christos 
    384  1.1  christos   ei_class = header[EI_CLASS];
    385  1.1  christos   switch (ei_class)
    386  1.1  christos     {
    387  1.1  christos     case ELFCLASS32:
    388  1.1  christos       type_functions = (ei_data == ELFDATA2LSB
    389  1.1  christos 			? &elf_little_32_functions
    390  1.1  christos 			: &elf_big_32_functions);
    391  1.1  christos       break;
    392  1.1  christos 
    393  1.1  christos     case ELFCLASS64:
    394  1.1  christos #ifndef UNSIGNED_64BIT_TYPE
    395  1.1  christos       *errmsg = "64-bit ELF objects not supported";
    396  1.1  christos       *err = 0;
    397  1.1  christos       return NULL;
    398  1.1  christos #else
    399  1.1  christos       type_functions = (ei_data == ELFDATA2LSB
    400  1.1  christos 			? &elf_little_64_functions
    401  1.1  christos 			: &elf_big_64_functions);
    402  1.1  christos       break;
    403  1.1  christos #endif
    404  1.1  christos 
    405  1.1  christos     default:
    406  1.1  christos       *errmsg = "unrecognized ELF size";
    407  1.1  christos       *err = 0;
    408  1.1  christos       return NULL;
    409  1.1  christos     }
    410  1.1  christos 
    411  1.1  christos   if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr,
    412  1.1  christos 				    errmsg, err))
    413  1.1  christos     return NULL;
    414  1.1  christos 
    415  1.1  christos   eor = XNEW (struct simple_object_elf_read);
    416  1.1  christos   eor->type_functions = type_functions;
    417  1.1  christos   eor->ei_data = ei_data;
    418  1.1  christos   eor->ei_class = ei_class;
    419  1.1  christos   eor->ei_osabi = header[EI_OSABI];
    420  1.1  christos   eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
    421  1.1  christos 				  e_machine, Elf_Half);
    422  1.1  christos   eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
    423  1.1  christos 				e_flags, Elf_Word);
    424  1.1  christos   eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
    425  1.1  christos 				e_shoff, Elf_Addr);
    426  1.1  christos   eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
    427  1.1  christos 				e_shnum, Elf_Half);
    428  1.1  christos   eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
    429  1.1  christos 				   e_shstrndx, Elf_Half);
    430  1.1  christos 
    431  1.1  christos   if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
    432  1.1  christos       && eor->shoff != 0)
    433  1.1  christos     {
    434  1.1  christos       unsigned char shdr[sizeof (Elf64_External_Shdr)];
    435  1.1  christos 
    436  1.1  christos       /* Object file has more than 0xffff sections.  */
    437  1.1  christos 
    438  1.1  christos       if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr,
    439  1.1  christos 					(ei_class == ELFCLASS32
    440  1.1  christos 					 ? sizeof (Elf32_External_Shdr)
    441  1.1  christos 					 : sizeof (Elf64_External_Shdr)),
    442  1.1  christos 					errmsg, err))
    443  1.1  christos 	{
    444  1.1  christos 	  XDELETE (eor);
    445  1.1  christos 	  return NULL;
    446  1.1  christos 	}
    447  1.1  christos 
    448  1.1  christos       if (eor->shnum == 0)
    449  1.1  christos 	eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
    450  1.1  christos 				      shdr, sh_size, Elf_Addr);
    451  1.1  christos 
    452  1.1  christos       if (eor->shstrndx == SHN_XINDEX)
    453  1.1  christos 	{
    454  1.1  christos 	  eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
    455  1.1  christos 					   shdr, sh_link, Elf_Word);
    456  1.1  christos 
    457  1.1  christos 	  /* Versions of the GNU binutils between 2.12 and 2.18 did
    458  1.1  christos 	     not handle objects with more than SHN_LORESERVE sections
    459  1.1  christos 	     correctly.  All large section indexes were offset by
    460  1.1  christos 	     0x100.  There is more information at
    461  1.1  christos 	     http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
    462  1.1  christos 	     Fortunately these object files are easy to detect, as the
    463  1.1  christos 	     GNU binutils always put the section header string table
    464  1.1  christos 	     near the end of the list of sections.  Thus if the
    465  1.1  christos 	     section header string table index is larger than the
    466  1.1  christos 	     number of sections, then we know we have to subtract
    467  1.1  christos 	     0x100 to get the real section index.  */
    468  1.1  christos 	  if (eor->shstrndx >= eor->shnum
    469  1.1  christos 	      && eor->shstrndx >= SHN_LORESERVE + 0x100)
    470  1.1  christos 	    eor->shstrndx -= 0x100;
    471  1.1  christos 	}
    472  1.1  christos     }
    473  1.1  christos 
    474  1.1  christos   if (eor->shstrndx >= eor->shnum)
    475  1.1  christos     {
    476  1.1  christos       *errmsg = "invalid ELF shstrndx >= shnum";
    477  1.1  christos       *err = 0;
    478  1.1  christos       XDELETE (eor);
    479  1.1  christos       return NULL;
    480  1.1  christos     }
    481  1.1  christos 
    482  1.1  christos   return (void *) eor;
    483  1.1  christos }
    484  1.1  christos 
    485  1.1  christos /* Find all sections in an ELF file.  */
    486  1.1  christos 
    487  1.1  christos static const char *
    488  1.1  christos simple_object_elf_find_sections (simple_object_read *sobj,
    489  1.1  christos 				 int (*pfn) (void *, const char *,
    490  1.1  christos 					     off_t offset, off_t length),
    491  1.1  christos 				 void *data,
    492  1.1  christos 				 int *err)
    493  1.1  christos {
    494  1.1  christos   struct simple_object_elf_read *eor =
    495  1.1  christos     (struct simple_object_elf_read *) sobj->data;
    496  1.1  christos   const struct elf_type_functions *type_functions = eor->type_functions;
    497  1.1  christos   unsigned char ei_class = eor->ei_class;
    498  1.1  christos   size_t shdr_size;
    499  1.1  christos   unsigned int shnum;
    500  1.1  christos   unsigned char *shdrs;
    501  1.1  christos   const char *errmsg;
    502  1.1  christos   unsigned char *shstrhdr;
    503  1.1  christos   size_t name_size;
    504  1.1  christos   off_t shstroff;
    505  1.1  christos   unsigned char *names;
    506  1.1  christos   unsigned int i;
    507  1.1  christos 
    508  1.1  christos   shdr_size = (ei_class == ELFCLASS32
    509  1.1  christos 	       ? sizeof (Elf32_External_Shdr)
    510  1.1  christos 	       : sizeof (Elf64_External_Shdr));
    511  1.1  christos 
    512  1.1  christos   /* Read the section headers.  We skip section 0, which is not a
    513  1.1  christos      useful section.  */
    514  1.1  christos 
    515  1.1  christos   shnum = eor->shnum;
    516  1.1  christos   shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
    517  1.1  christos 
    518  1.1  christos   if (!simple_object_internal_read (sobj->descriptor,
    519  1.1  christos 				    sobj->offset + eor->shoff + shdr_size,
    520  1.1  christos 				    shdrs,
    521  1.1  christos 				    shdr_size * (shnum - 1),
    522  1.1  christos 				    &errmsg, err))
    523  1.1  christos     {
    524  1.1  christos       XDELETEVEC (shdrs);
    525  1.1  christos       return errmsg;
    526  1.1  christos     }
    527  1.1  christos 
    528  1.1  christos   /* Read the section names.  */
    529  1.1  christos 
    530  1.1  christos   shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
    531  1.1  christos   name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
    532  1.1  christos 			       shstrhdr, sh_size, Elf_Addr);
    533  1.1  christos   shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
    534  1.1  christos 			      shstrhdr, sh_offset, Elf_Addr);
    535  1.1  christos   names = XNEWVEC (unsigned char, name_size);
    536  1.1  christos   if (!simple_object_internal_read (sobj->descriptor,
    537  1.1  christos 				    sobj->offset + shstroff,
    538  1.1  christos 				    names, name_size, &errmsg, err))
    539  1.1  christos     {
    540  1.1  christos       XDELETEVEC (names);
    541  1.1  christos       XDELETEVEC (shdrs);
    542  1.1  christos       return errmsg;
    543  1.1  christos     }
    544  1.1  christos 
    545  1.1  christos   for (i = 1; i < shnum; ++i)
    546  1.1  christos     {
    547  1.1  christos       unsigned char *shdr;
    548  1.1  christos       unsigned int sh_name;
    549  1.1  christos       const char *name;
    550  1.1  christos       off_t offset;
    551  1.1  christos       off_t length;
    552  1.1  christos 
    553  1.1  christos       shdr = shdrs + (i - 1) * shdr_size;
    554  1.1  christos       sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
    555  1.1  christos 				 shdr, sh_name, Elf_Word);
    556  1.1  christos       if (sh_name >= name_size)
    557  1.1  christos 	{
    558  1.1  christos 	  *err = 0;
    559  1.1  christos 	  XDELETEVEC (names);
    560  1.1  christos 	  XDELETEVEC (shdrs);
    561  1.1  christos 	  return "ELF section name out of range";
    562  1.1  christos 	}
    563  1.1  christos 
    564  1.1  christos       name = (const char *) names + sh_name;
    565  1.1  christos       offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
    566  1.1  christos 				shdr, sh_offset, Elf_Addr);
    567  1.1  christos       length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
    568  1.1  christos 				shdr, sh_size, Elf_Addr);
    569  1.1  christos 
    570  1.1  christos       if (!(*pfn) (data, name, offset, length))
    571  1.1  christos 	break;
    572  1.1  christos     }
    573  1.1  christos 
    574  1.1  christos   XDELETEVEC (names);
    575  1.1  christos   XDELETEVEC (shdrs);
    576  1.1  christos 
    577  1.1  christos   return NULL;
    578  1.1  christos }
    579  1.1  christos 
    580  1.1  christos /* Fetch the attributes for an simple_object_read.  */
    581  1.1  christos 
    582  1.1  christos static void *
    583  1.1  christos simple_object_elf_fetch_attributes (simple_object_read *sobj,
    584  1.1  christos 				    const char **errmsg ATTRIBUTE_UNUSED,
    585  1.1  christos 				    int *err ATTRIBUTE_UNUSED)
    586  1.1  christos {
    587  1.1  christos   struct simple_object_elf_read *eor =
    588  1.1  christos     (struct simple_object_elf_read *) sobj->data;
    589  1.1  christos   struct simple_object_elf_attributes *ret;
    590  1.1  christos 
    591  1.1  christos   ret = XNEW (struct simple_object_elf_attributes);
    592  1.1  christos   ret->type_functions = eor->type_functions;
    593  1.1  christos   ret->ei_data = eor->ei_data;
    594  1.1  christos   ret->ei_class = eor->ei_class;
    595  1.1  christos   ret->ei_osabi = eor->ei_osabi;
    596  1.1  christos   ret->machine = eor->machine;
    597  1.1  christos   ret->flags = eor->flags;
    598  1.1  christos   return ret;
    599  1.1  christos }
    600  1.1  christos 
    601  1.1  christos /* Release the privata data for an simple_object_read.  */
    602  1.1  christos 
    603  1.1  christos static void
    604  1.1  christos simple_object_elf_release_read (void *data)
    605  1.1  christos {
    606  1.1  christos   XDELETE (data);
    607  1.1  christos }
    608  1.1  christos 
    609  1.1  christos /* Compare two attributes structures.  */
    610  1.1  christos 
    611  1.1  christos static const char *
    612  1.1  christos simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
    613  1.1  christos {
    614  1.1  christos   struct simple_object_elf_attributes *to =
    615  1.1  christos     (struct simple_object_elf_attributes *) todata;
    616  1.1  christos   struct simple_object_elf_attributes *from =
    617  1.1  christos     (struct simple_object_elf_attributes *) fromdata;
    618  1.1  christos 
    619  1.1  christos   if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
    620  1.1  christos     {
    621  1.1  christos       *err = 0;
    622  1.1  christos       return "ELF object format mismatch";
    623  1.1  christos     }
    624  1.1  christos 
    625  1.1  christos   if (to->machine != from->machine)
    626  1.1  christos     {
    627  1.1  christos       int ok;
    628  1.1  christos 
    629  1.1  christos       /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
    630  1.1  christos 	 output of EM_SPARC32PLUS.  */
    631  1.1  christos       ok = 0;
    632  1.1  christos       switch (to->machine)
    633  1.1  christos 	{
    634  1.1  christos 	case EM_SPARC:
    635  1.1  christos 	  if (from->machine == EM_SPARC32PLUS)
    636  1.1  christos 	    {
    637  1.1  christos 	      to->machine = from->machine;
    638  1.1  christos 	      ok = 1;
    639  1.1  christos 	    }
    640  1.1  christos 	  break;
    641  1.1  christos 
    642  1.1  christos 	case EM_SPARC32PLUS:
    643  1.1  christos 	  if (from->machine == EM_SPARC)
    644  1.1  christos 	    ok = 1;
    645  1.1  christos 	  break;
    646  1.1  christos 
    647  1.1  christos 	default:
    648  1.1  christos 	  break;
    649  1.1  christos 	}
    650  1.1  christos 
    651  1.1  christos       if (!ok)
    652  1.1  christos 	{
    653  1.1  christos 	  *err = 0;
    654  1.1  christos 	  return "ELF machine number mismatch";
    655  1.1  christos 	}
    656  1.1  christos     }
    657  1.1  christos 
    658  1.1  christos   return NULL;
    659  1.1  christos }
    660  1.1  christos 
    661  1.1  christos /* Release the private data for an attributes structure.  */
    662  1.1  christos 
    663  1.1  christos static void
    664  1.1  christos simple_object_elf_release_attributes (void *data)
    665  1.1  christos {
    666  1.1  christos   XDELETE (data);
    667  1.1  christos }
    668  1.1  christos 
    669  1.1  christos /* Prepare to write out a file.  */
    670  1.1  christos 
    671  1.1  christos static void *
    672  1.1  christos simple_object_elf_start_write (void *attributes_data,
    673  1.1  christos 			       const char **errmsg ATTRIBUTE_UNUSED,
    674  1.1  christos 			       int *err ATTRIBUTE_UNUSED)
    675  1.1  christos {
    676  1.1  christos   struct simple_object_elf_attributes *attrs =
    677  1.1  christos     (struct simple_object_elf_attributes *) attributes_data;
    678  1.1  christos   struct simple_object_elf_attributes *ret;
    679  1.1  christos 
    680  1.1  christos   /* We're just going to record the attributes, but we need to make a
    681  1.1  christos      copy because the user may delete them.  */
    682  1.1  christos   ret = XNEW (struct simple_object_elf_attributes);
    683  1.1  christos   *ret = *attrs;
    684  1.1  christos   return ret;
    685  1.1  christos }
    686  1.1  christos 
    687  1.1  christos /* Write out an ELF ehdr.  */
    688  1.1  christos 
    689  1.1  christos static int
    690  1.1  christos simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
    691  1.1  christos 			      const char **errmsg, int *err)
    692  1.1  christos {
    693  1.1  christos   struct simple_object_elf_attributes *attrs =
    694  1.1  christos     (struct simple_object_elf_attributes *) sobj->data;
    695  1.1  christos   const struct elf_type_functions* fns;
    696  1.1  christos   unsigned char cl;
    697  1.1  christos   size_t ehdr_size;
    698  1.1  christos   unsigned char buf[sizeof (Elf64_External_Ehdr)];
    699  1.1  christos   simple_object_write_section *section;
    700  1.1  christos   unsigned int shnum;
    701  1.1  christos 
    702  1.1  christos   fns = attrs->type_functions;
    703  1.1  christos   cl = attrs->ei_class;
    704  1.1  christos 
    705  1.1  christos   shnum = 0;
    706  1.1  christos   for (section = sobj->sections; section != NULL; section = section->next)
    707  1.1  christos     ++shnum;
    708  1.1  christos   if (shnum > 0)
    709  1.1  christos     {
    710  1.1  christos       /* Add a section header for the dummy section and one for
    711  1.1  christos 	 .shstrtab.  */
    712  1.1  christos       shnum += 2;
    713  1.1  christos     }
    714  1.1  christos 
    715  1.1  christos   ehdr_size = (cl == ELFCLASS32
    716  1.1  christos 	       ? sizeof (Elf32_External_Ehdr)
    717  1.1  christos 	       : sizeof (Elf64_External_Ehdr));
    718  1.1  christos   memset (buf, 0, sizeof (Elf64_External_Ehdr));
    719  1.1  christos 
    720  1.1  christos   buf[EI_MAG0] = ELFMAG0;
    721  1.1  christos   buf[EI_MAG1] = ELFMAG1;
    722  1.1  christos   buf[EI_MAG2] = ELFMAG2;
    723  1.1  christos   buf[EI_MAG3] = ELFMAG3;
    724  1.1  christos   buf[EI_CLASS] = cl;
    725  1.1  christos   buf[EI_DATA] = attrs->ei_data;
    726  1.1  christos   buf[EI_VERSION] = EV_CURRENT;
    727  1.1  christos   buf[EI_OSABI] = attrs->ei_osabi;
    728  1.1  christos 
    729  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
    730  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
    731  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
    732  1.1  christos   /* e_entry left as zero.  */
    733  1.1  christos   /* e_phoff left as zero.  */
    734  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
    735  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
    736  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
    737  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
    738  1.1  christos 		 (cl == ELFCLASS32
    739  1.1  christos 		  ? sizeof (Elf32_External_Phdr)
    740  1.1  christos 		  : sizeof (Elf64_External_Phdr)));
    741  1.1  christos   /* e_phnum left as zero.  */
    742  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
    743  1.1  christos 		 (cl == ELFCLASS32
    744  1.1  christos 		  ? sizeof (Elf32_External_Shdr)
    745  1.1  christos 		  : sizeof (Elf64_External_Shdr)));
    746  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, shnum);
    747  1.1  christos   ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half,
    748  1.1  christos 		 shnum == 0 ? 0 : shnum - 1);
    749  1.1  christos 
    750  1.1  christos   return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
    751  1.1  christos 				       errmsg, err);
    752  1.1  christos }
    753  1.1  christos 
    754  1.1  christos /* Write out an ELF shdr.  */
    755  1.1  christos 
    756  1.1  christos static int
    757  1.1  christos simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
    758  1.1  christos 			      off_t offset, unsigned int sh_name,
    759  1.1  christos 			      unsigned int sh_type, unsigned int sh_flags,
    760  1.1  christos 			      unsigned int sh_offset, unsigned int sh_size,
    761  1.1  christos 			      unsigned int sh_addralign, const char **errmsg,
    762  1.1  christos 			      int *err)
    763  1.1  christos {
    764  1.1  christos   struct simple_object_elf_attributes *attrs =
    765  1.1  christos     (struct simple_object_elf_attributes *) sobj->data;
    766  1.1  christos   const struct elf_type_functions* fns;
    767  1.1  christos   unsigned char cl;
    768  1.1  christos   size_t shdr_size;
    769  1.1  christos   unsigned char buf[sizeof (Elf64_External_Shdr)];
    770  1.1  christos 
    771  1.1  christos   fns = attrs->type_functions;
    772  1.1  christos   cl = attrs->ei_class;
    773  1.1  christos 
    774  1.1  christos   shdr_size = (cl == ELFCLASS32
    775  1.1  christos 	       ? sizeof (Elf32_External_Shdr)
    776  1.1  christos 	       : sizeof (Elf64_External_Shdr));
    777  1.1  christos   memset (buf, 0, sizeof (Elf64_External_Shdr));
    778  1.1  christos 
    779  1.1  christos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
    780  1.1  christos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
    781  1.1  christos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
    782  1.1  christos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
    783  1.1  christos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
    784  1.1  christos   /* sh_link left as zero.  */
    785  1.1  christos   /* sh_info left as zero.  */
    786  1.1  christos   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
    787  1.1  christos   /* sh_entsize left as zero.  */
    788  1.1  christos 
    789  1.1  christos   return simple_object_internal_write (descriptor, offset, buf, shdr_size,
    790  1.1  christos 				       errmsg, err);
    791  1.1  christos }
    792  1.1  christos 
    793  1.1  christos /* Write out a complete ELF file.
    794  1.1  christos    Ehdr
    795  1.1  christos    initial dummy Shdr
    796  1.1  christos    user-created Shdrs
    797  1.1  christos    .shstrtab Shdr
    798  1.1  christos    user-created section data
    799  1.1  christos    .shstrtab data  */
    800  1.1  christos 
    801  1.1  christos static const char *
    802  1.1  christos simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
    803  1.1  christos 				 int *err)
    804  1.1  christos {
    805  1.1  christos   struct simple_object_elf_attributes *attrs =
    806  1.1  christos     (struct simple_object_elf_attributes *) sobj->data;
    807  1.1  christos   unsigned char cl;
    808  1.1  christos   size_t ehdr_size;
    809  1.1  christos   size_t shdr_size;
    810  1.1  christos   const char *errmsg;
    811  1.1  christos   simple_object_write_section *section;
    812  1.1  christos   unsigned int shnum;
    813  1.1  christos   size_t shdr_offset;
    814  1.1  christos   size_t sh_offset;
    815  1.1  christos   size_t sh_name;
    816  1.1  christos   unsigned char zero;
    817  1.1  christos 
    818  1.1  christos   if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
    819  1.1  christos     return errmsg;
    820  1.1  christos 
    821  1.1  christos   cl = attrs->ei_class;
    822  1.1  christos   if (cl == ELFCLASS32)
    823  1.1  christos     {
    824  1.1  christos       ehdr_size = sizeof (Elf32_External_Ehdr);
    825  1.1  christos       shdr_size = sizeof (Elf32_External_Shdr);
    826  1.1  christos     }
    827  1.1  christos   else
    828  1.1  christos     {
    829  1.1  christos       ehdr_size = sizeof (Elf64_External_Ehdr);
    830  1.1  christos       shdr_size = sizeof (Elf64_External_Shdr);
    831  1.1  christos     }
    832  1.1  christos 
    833  1.1  christos   shnum = 0;
    834  1.1  christos   for (section = sobj->sections; section != NULL; section = section->next)
    835  1.1  christos     ++shnum;
    836  1.1  christos   if (shnum == 0)
    837  1.1  christos     return NULL;
    838  1.1  christos 
    839  1.1  christos   /* Add initial dummy Shdr and .shstrtab.  */
    840  1.1  christos   shnum += 2;
    841  1.1  christos 
    842  1.1  christos   shdr_offset = ehdr_size;
    843  1.1  christos   sh_offset = shdr_offset + shnum * shdr_size;
    844  1.1  christos 
    845  1.1  christos   if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
    846  1.1  christos 				     0, 0, 0, 0, 0, 0, &errmsg, err))
    847  1.1  christos     return errmsg;
    848  1.1  christos 
    849  1.1  christos   shdr_offset += shdr_size;
    850  1.1  christos 
    851  1.1  christos   sh_name = 1;
    852  1.1  christos   for (section = sobj->sections; section != NULL; section = section->next)
    853  1.1  christos     {
    854  1.1  christos       size_t mask;
    855  1.1  christos       size_t new_sh_offset;
    856  1.1  christos       size_t sh_size;
    857  1.1  christos       struct simple_object_write_section_buffer *buffer;
    858  1.1  christos 
    859  1.1  christos       mask = (1U << section->align) - 1;
    860  1.1  christos       new_sh_offset = sh_offset + mask;
    861  1.1  christos       new_sh_offset &= ~ mask;
    862  1.1  christos       while (new_sh_offset > sh_offset)
    863  1.1  christos 	{
    864  1.1  christos 	  unsigned char zeroes[16];
    865  1.1  christos 	  size_t write;
    866  1.1  christos 
    867  1.1  christos 	  memset (zeroes, 0, sizeof zeroes);
    868  1.1  christos 	  write = new_sh_offset - sh_offset;
    869  1.1  christos 	  if (write > sizeof zeroes)
    870  1.1  christos 	    write = sizeof zeroes;
    871  1.1  christos 	  if (!simple_object_internal_write (descriptor, sh_offset, zeroes,
    872  1.1  christos 					     write, &errmsg, err))
    873  1.1  christos 	    return errmsg;
    874  1.1  christos 	  sh_offset += write;
    875  1.1  christos 	}
    876  1.1  christos 
    877  1.1  christos       sh_size = 0;
    878  1.1  christos       for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
    879  1.1  christos 	{
    880  1.1  christos 	  if (!simple_object_internal_write (descriptor, sh_offset + sh_size,
    881  1.1  christos 					     ((const unsigned char *)
    882  1.1  christos 					      buffer->buffer),
    883  1.1  christos 					     buffer->size, &errmsg, err))
    884  1.1  christos 	    return errmsg;
    885  1.1  christos 	  sh_size += buffer->size;
    886  1.1  christos 	}
    887  1.1  christos 
    888  1.1  christos       if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
    889  1.1  christos 					 sh_name, SHT_PROGBITS, 0, sh_offset,
    890  1.1  christos 					 sh_size, 1U << section->align,
    891  1.1  christos 					 &errmsg, err))
    892  1.1  christos 	return errmsg;
    893  1.1  christos 
    894  1.1  christos       shdr_offset += shdr_size;
    895  1.1  christos       sh_name += strlen (section->name) + 1;
    896  1.1  christos       sh_offset += sh_size;
    897  1.1  christos     }
    898  1.1  christos 
    899  1.1  christos   if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
    900  1.1  christos 				     sh_name, SHT_STRTAB, 0, sh_offset,
    901  1.1  christos 				     sh_name + strlen (".shstrtab") + 1,
    902  1.1  christos 				     1, &errmsg, err))
    903  1.1  christos     return errmsg;
    904  1.1  christos 
    905  1.1  christos   /* .shstrtab has a leading zero byte.  */
    906  1.1  christos   zero = 0;
    907  1.1  christos   if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
    908  1.1  christos 				     &errmsg, err))
    909  1.1  christos     return errmsg;
    910  1.1  christos   ++sh_offset;
    911  1.1  christos 
    912  1.1  christos   for (section = sobj->sections; section != NULL; section = section->next)
    913  1.1  christos     {
    914  1.1  christos       size_t len;
    915  1.1  christos 
    916  1.1  christos       len = strlen (section->name) + 1;
    917  1.1  christos       if (!simple_object_internal_write (descriptor, sh_offset,
    918  1.1  christos 					 (const unsigned char *) section->name,
    919  1.1  christos 					 len, &errmsg, err))
    920  1.1  christos 	return errmsg;
    921  1.1  christos       sh_offset += len;
    922  1.1  christos     }
    923  1.1  christos 
    924  1.1  christos   if (!simple_object_internal_write (descriptor, sh_offset,
    925  1.1  christos 				     (const unsigned char *) ".shstrtab",
    926  1.1  christos 				     strlen (".shstrtab") + 1, &errmsg, err))
    927  1.1  christos     return errmsg;
    928  1.1  christos 
    929  1.1  christos   return NULL;
    930  1.1  christos }
    931  1.1  christos 
    932  1.1  christos /* Release the private data for an simple_object_write structure.  */
    933  1.1  christos 
    934  1.1  christos static void
    935  1.1  christos simple_object_elf_release_write (void *data)
    936  1.1  christos {
    937  1.1  christos   XDELETE (data);
    938  1.1  christos }
    939  1.1  christos 
    940  1.1  christos /* The ELF functions.  */
    941  1.1  christos 
    942  1.1  christos const struct simple_object_functions simple_object_elf_functions =
    943  1.1  christos {
    944  1.1  christos   simple_object_elf_match,
    945  1.1  christos   simple_object_elf_find_sections,
    946  1.1  christos   simple_object_elf_fetch_attributes,
    947  1.1  christos   simple_object_elf_release_read,
    948  1.1  christos   simple_object_elf_attributes_merge,
    949  1.1  christos   simple_object_elf_release_attributes,
    950  1.1  christos   simple_object_elf_start_write,
    951  1.1  christos   simple_object_elf_write_to_file,
    952  1.1  christos   simple_object_elf_release_write
    953  1.1  christos };
    954