OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-dev/] [fsf-gcc-snapshot-1-mar-12/] [or1k-gcc/] [libiberty/] [simple-object-elf.c] - Diff between revs 736 and 783

Only display areas with differences | Details | Blame | View Log

Rev 736 Rev 783
/* simple-object-elf.c -- routines to manipulate ELF object files.
/* simple-object-elf.c -- routines to manipulate ELF object files.
   Copyright 2010 Free Software Foundation, Inc.
   Copyright 2010 Free Software Foundation, Inc.
   Written by Ian Lance Taylor, Google.
   Written by Ian Lance Taylor, Google.
 
 
This program is free software; you can redistribute it and/or modify it
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
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
Free Software Foundation; either version 2, or (at your option) any
later version.
later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, 51 Franklin Street - Fifth Floor,
Foundation, 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA.  */
Boston, MA 02110-1301, USA.  */
 
 
#include "config.h"
#include "config.h"
#include "libiberty.h"
#include "libiberty.h"
#include "simple-object.h"
#include "simple-object.h"
 
 
#include <errno.h>
#include <errno.h>
#include <stddef.h>
#include <stddef.h>
 
 
#ifdef HAVE_STDLIB_H
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#include <stdlib.h>
#endif
#endif
 
 
#ifdef HAVE_STDINT_H
#ifdef HAVE_STDINT_H
#include <stdint.h>
#include <stdint.h>
#endif
#endif
 
 
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#endif
#endif
 
 
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#endif
 
 
#include "simple-object-common.h"
#include "simple-object-common.h"
 
 
/* ELF structures and constants.  */
/* ELF structures and constants.  */
 
 
/* 32-bit ELF file header.  */
/* 32-bit ELF file header.  */
 
 
typedef struct {
typedef struct {
  unsigned char e_ident[16];            /* ELF "magic number" */
  unsigned char e_ident[16];            /* ELF "magic number" */
  unsigned char e_type[2];              /* Identifies object file type */
  unsigned char e_type[2];              /* Identifies object file type */
  unsigned char e_machine[2];           /* Specifies required architecture */
  unsigned char e_machine[2];           /* Specifies required architecture */
  unsigned char e_version[4];           /* Identifies object file version */
  unsigned char e_version[4];           /* Identifies object file version */
  unsigned char e_entry[4];             /* Entry point virtual address */
  unsigned char e_entry[4];             /* Entry point virtual address */
  unsigned char e_phoff[4];             /* Program header table file offset */
  unsigned char e_phoff[4];             /* Program header table file offset */
  unsigned char e_shoff[4];             /* Section 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_flags[4];             /* Processor-specific flags */
  unsigned char e_ehsize[2];            /* ELF header size in bytes */
  unsigned char e_ehsize[2];            /* ELF header size in bytes */
  unsigned char e_phentsize[2];         /* Program header table entry size */
  unsigned char e_phentsize[2];         /* Program header table entry size */
  unsigned char e_phnum[2];             /* Program header table entry count */
  unsigned char e_phnum[2];             /* Program header table entry count */
  unsigned char e_shentsize[2];         /* Section header table entry size */
  unsigned char e_shentsize[2];         /* Section header table entry size */
  unsigned char e_shnum[2];             /* Section header table entry count */
  unsigned char e_shnum[2];             /* Section header table entry count */
  unsigned char e_shstrndx[2];          /* Section header string table index */
  unsigned char e_shstrndx[2];          /* Section header string table index */
} Elf32_External_Ehdr;
} Elf32_External_Ehdr;
 
 
/* 64-bit ELF file header.  */
/* 64-bit ELF file header.  */
 
 
typedef struct {
typedef struct {
  unsigned char e_ident[16];            /* ELF "magic number" */
  unsigned char e_ident[16];            /* ELF "magic number" */
  unsigned char e_type[2];              /* Identifies object file type */
  unsigned char e_type[2];              /* Identifies object file type */
  unsigned char e_machine[2];           /* Specifies required architecture */
  unsigned char e_machine[2];           /* Specifies required architecture */
  unsigned char e_version[4];           /* Identifies object file version */
  unsigned char e_version[4];           /* Identifies object file version */
  unsigned char e_entry[8];             /* Entry point virtual address */
  unsigned char e_entry[8];             /* Entry point virtual address */
  unsigned char e_phoff[8];             /* Program header table file offset */
  unsigned char e_phoff[8];             /* Program header table file offset */
  unsigned char e_shoff[8];             /* Section 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_flags[4];             /* Processor-specific flags */
  unsigned char e_ehsize[2];            /* ELF header size in bytes */
  unsigned char e_ehsize[2];            /* ELF header size in bytes */
  unsigned char e_phentsize[2];         /* Program header table entry size */
  unsigned char e_phentsize[2];         /* Program header table entry size */
  unsigned char e_phnum[2];             /* Program header table entry count */
  unsigned char e_phnum[2];             /* Program header table entry count */
  unsigned char e_shentsize[2];         /* Section header table entry size */
  unsigned char e_shentsize[2];         /* Section header table entry size */
  unsigned char e_shnum[2];             /* Section header table entry count */
  unsigned char e_shnum[2];             /* Section header table entry count */
  unsigned char e_shstrndx[2];          /* Section header string table index */
  unsigned char e_shstrndx[2];          /* Section header string table index */
} Elf64_External_Ehdr;
} Elf64_External_Ehdr;
 
 
/* Indexes and values in e_ident field of Ehdr.  */
/* Indexes and values in e_ident field of Ehdr.  */
 
 
#define EI_MAG0         0        /* File identification byte 0 index */
#define EI_MAG0         0        /* File identification byte 0 index */
#define ELFMAG0            0x7F /* Magic number byte 0 */
#define ELFMAG0            0x7F /* Magic number byte 0 */
 
 
#define EI_MAG1         1       /* File identification byte 1 index */
#define EI_MAG1         1       /* File identification byte 1 index */
#define ELFMAG1             'E' /* Magic number byte 1 */
#define ELFMAG1             'E' /* Magic number byte 1 */
 
 
#define EI_MAG2         2       /* File identification byte 2 index */
#define EI_MAG2         2       /* File identification byte 2 index */
#define ELFMAG2             'L' /* Magic number byte 2 */
#define ELFMAG2             'L' /* Magic number byte 2 */
 
 
#define EI_MAG3         3       /* File identification byte 3 index */
#define EI_MAG3         3       /* File identification byte 3 index */
#define ELFMAG3             'F' /* Magic number byte 3 */
#define ELFMAG3             'F' /* Magic number byte 3 */
 
 
#define EI_CLASS        4       /* File class */
#define EI_CLASS        4       /* File class */
#define ELFCLASSNONE          0 /* Invalid class */
#define ELFCLASSNONE          0 /* Invalid class */
#define ELFCLASS32            1 /* 32-bit objects */
#define ELFCLASS32            1 /* 32-bit objects */
#define ELFCLASS64            2 /* 64-bit objects */
#define ELFCLASS64            2 /* 64-bit objects */
 
 
#define EI_DATA         5       /* Data encoding */
#define EI_DATA         5       /* Data encoding */
#define ELFDATANONE           0 /* Invalid data encoding */
#define ELFDATANONE           0 /* Invalid data encoding */
#define ELFDATA2LSB           1 /* 2's complement, little endian */
#define ELFDATA2LSB           1 /* 2's complement, little endian */
#define ELFDATA2MSB           2 /* 2's complement, big endian */
#define ELFDATA2MSB           2 /* 2's complement, big endian */
 
 
#define EI_VERSION      6       /* File version */
#define EI_VERSION      6       /* File version */
#define EV_CURRENT      1               /* Current version */
#define EV_CURRENT      1               /* Current version */
 
 
#define EI_OSABI        7       /* Operating System/ABI indication */
#define EI_OSABI        7       /* Operating System/ABI indication */
 
 
/* Values for e_type field of Ehdr.  */
/* Values for e_type field of Ehdr.  */
 
 
#define ET_REL          1       /* Relocatable file */
#define ET_REL          1       /* Relocatable file */
 
 
/* Values for e_machine field of Ehdr.  */
/* Values for e_machine field of Ehdr.  */
 
 
#define EM_SPARC          2     /* SUN SPARC */
#define EM_SPARC          2     /* SUN SPARC */
#define EM_SPARC32PLUS   18     /* Sun's "v8plus" */
#define EM_SPARC32PLUS   18     /* Sun's "v8plus" */
 
 
/* Special section index values.  */
/* Special section index values.  */
 
 
#define SHN_LORESERVE   0xFF00          /* Begin range of reserved indices */
#define SHN_LORESERVE   0xFF00          /* Begin range of reserved indices */
#define SHN_XINDEX      0xFFFF          /* Section index is held elsewhere */
#define SHN_XINDEX      0xFFFF          /* Section index is held elsewhere */
 
 
/* 32-bit ELF program header.  */
/* 32-bit ELF program header.  */
 
 
typedef struct {
typedef struct {
  unsigned char p_type[4];              /* Identifies program segment type */
  unsigned char p_type[4];              /* Identifies program segment type */
  unsigned char p_offset[4];            /* Segment file offset */
  unsigned char p_offset[4];            /* Segment file offset */
  unsigned char p_vaddr[4];             /* Segment virtual address */
  unsigned char p_vaddr[4];             /* Segment virtual address */
  unsigned char p_paddr[4];             /* Segment physical address */
  unsigned char p_paddr[4];             /* Segment physical address */
  unsigned char p_filesz[4];            /* Segment size in file */
  unsigned char p_filesz[4];            /* Segment size in file */
  unsigned char p_memsz[4];             /* Segment size in memory */
  unsigned char p_memsz[4];             /* Segment size in memory */
  unsigned char p_flags[4];             /* Segment flags */
  unsigned char p_flags[4];             /* Segment flags */
  unsigned char p_align[4];             /* Segment alignment, file & memory */
  unsigned char p_align[4];             /* Segment alignment, file & memory */
} Elf32_External_Phdr;
} Elf32_External_Phdr;
 
 
/* 64-bit ELF program header.  */
/* 64-bit ELF program header.  */
 
 
typedef struct {
typedef struct {
  unsigned char p_type[4];              /* Identifies program segment type */
  unsigned char p_type[4];              /* Identifies program segment type */
  unsigned char p_flags[4];             /* Segment flags */
  unsigned char p_flags[4];             /* Segment flags */
  unsigned char p_offset[8];            /* Segment file offset */
  unsigned char p_offset[8];            /* Segment file offset */
  unsigned char p_vaddr[8];             /* Segment virtual address */
  unsigned char p_vaddr[8];             /* Segment virtual address */
  unsigned char p_paddr[8];             /* Segment physical address */
  unsigned char p_paddr[8];             /* Segment physical address */
  unsigned char p_filesz[8];            /* Segment size in file */
  unsigned char p_filesz[8];            /* Segment size in file */
  unsigned char p_memsz[8];             /* Segment size in memory */
  unsigned char p_memsz[8];             /* Segment size in memory */
  unsigned char p_align[8];             /* Segment alignment, file & memory */
  unsigned char p_align[8];             /* Segment alignment, file & memory */
} Elf64_External_Phdr;
} Elf64_External_Phdr;
 
 
/* 32-bit ELF section header */
/* 32-bit ELF section header */
 
 
typedef struct {
typedef struct {
  unsigned char sh_name[4];             /* Section name, index in string tbl */
  unsigned char sh_name[4];             /* Section name, index in string tbl */
  unsigned char sh_type[4];             /* Type of section */
  unsigned char sh_type[4];             /* Type of section */
  unsigned char sh_flags[4];            /* Miscellaneous section attributes */
  unsigned char sh_flags[4];            /* Miscellaneous section attributes */
  unsigned char sh_addr[4];             /* Section virtual addr at execution */
  unsigned char sh_addr[4];             /* Section virtual addr at execution */
  unsigned char sh_offset[4];           /* Section file offset */
  unsigned char sh_offset[4];           /* Section file offset */
  unsigned char sh_size[4];             /* Size of section in bytes */
  unsigned char sh_size[4];             /* Size of section in bytes */
  unsigned char sh_link[4];             /* Index of another section */
  unsigned char sh_link[4];             /* Index of another section */
  unsigned char sh_info[4];             /* Additional section information */
  unsigned char sh_info[4];             /* Additional section information */
  unsigned char sh_addralign[4];        /* Section alignment */
  unsigned char sh_addralign[4];        /* Section alignment */
  unsigned char sh_entsize[4];          /* Entry size if section holds table */
  unsigned char sh_entsize[4];          /* Entry size if section holds table */
} Elf32_External_Shdr;
} Elf32_External_Shdr;
 
 
/* 64-bit ELF section header.  */
/* 64-bit ELF section header.  */
 
 
typedef struct {
typedef struct {
  unsigned char sh_name[4];             /* Section name, index in string tbl */
  unsigned char sh_name[4];             /* Section name, index in string tbl */
  unsigned char sh_type[4];             /* Type of section */
  unsigned char sh_type[4];             /* Type of section */
  unsigned char sh_flags[8];            /* Miscellaneous section attributes */
  unsigned char sh_flags[8];            /* Miscellaneous section attributes */
  unsigned char sh_addr[8];             /* Section virtual addr at execution */
  unsigned char sh_addr[8];             /* Section virtual addr at execution */
  unsigned char sh_offset[8];           /* Section file offset */
  unsigned char sh_offset[8];           /* Section file offset */
  unsigned char sh_size[8];             /* Size of section in bytes */
  unsigned char sh_size[8];             /* Size of section in bytes */
  unsigned char sh_link[4];             /* Index of another section */
  unsigned char sh_link[4];             /* Index of another section */
  unsigned char sh_info[4];             /* Additional section information */
  unsigned char sh_info[4];             /* Additional section information */
  unsigned char sh_addralign[8];        /* Section alignment */
  unsigned char sh_addralign[8];        /* Section alignment */
  unsigned char sh_entsize[8];          /* Entry size if section holds table */
  unsigned char sh_entsize[8];          /* Entry size if section holds table */
} Elf64_External_Shdr;
} Elf64_External_Shdr;
 
 
/* Values for sh_type field.  */
/* Values for sh_type field.  */
 
 
#define SHT_PROGBITS    1               /* Program data */
#define SHT_PROGBITS    1               /* Program data */
#define SHT_STRTAB      3               /* A string table */
#define SHT_STRTAB      3               /* A string table */
 
 
/* Functions to fetch and store different ELF types, depending on the
/* Functions to fetch and store different ELF types, depending on the
   endianness and size.  */
   endianness and size.  */
 
 
struct elf_type_functions
struct elf_type_functions
{
{
  unsigned short (*fetch_Elf_Half) (const unsigned char *);
  unsigned short (*fetch_Elf_Half) (const unsigned char *);
  unsigned int (*fetch_Elf_Word) (const unsigned char *);
  unsigned int (*fetch_Elf_Word) (const unsigned char *);
  ulong_type (*fetch_Elf_Addr) (const unsigned char *);
  ulong_type (*fetch_Elf_Addr) (const unsigned char *);
  void (*set_Elf_Half) (unsigned char *, unsigned short);
  void (*set_Elf_Half) (unsigned char *, unsigned short);
  void (*set_Elf_Word) (unsigned char *, unsigned int);
  void (*set_Elf_Word) (unsigned char *, unsigned int);
  void (*set_Elf_Addr) (unsigned char *, ulong_type);
  void (*set_Elf_Addr) (unsigned char *, ulong_type);
};
};
 
 
static const struct elf_type_functions elf_big_32_functions =
static const struct elf_type_functions elf_big_32_functions =
{
{
  simple_object_fetch_big_16,
  simple_object_fetch_big_16,
  simple_object_fetch_big_32,
  simple_object_fetch_big_32,
  simple_object_fetch_big_32_ulong,
  simple_object_fetch_big_32_ulong,
  simple_object_set_big_16,
  simple_object_set_big_16,
  simple_object_set_big_32,
  simple_object_set_big_32,
  simple_object_set_big_32_ulong
  simple_object_set_big_32_ulong
};
};
 
 
static const struct elf_type_functions elf_little_32_functions =
static const struct elf_type_functions elf_little_32_functions =
{
{
  simple_object_fetch_little_16,
  simple_object_fetch_little_16,
  simple_object_fetch_little_32,
  simple_object_fetch_little_32,
  simple_object_fetch_little_32_ulong,
  simple_object_fetch_little_32_ulong,
  simple_object_set_little_16,
  simple_object_set_little_16,
  simple_object_set_little_32,
  simple_object_set_little_32,
  simple_object_set_little_32_ulong
  simple_object_set_little_32_ulong
};
};
 
 
#ifdef UNSIGNED_64BIT_TYPE
#ifdef UNSIGNED_64BIT_TYPE
 
 
static const struct elf_type_functions elf_big_64_functions =
static const struct elf_type_functions elf_big_64_functions =
{
{
  simple_object_fetch_big_16,
  simple_object_fetch_big_16,
  simple_object_fetch_big_32,
  simple_object_fetch_big_32,
  simple_object_fetch_big_64,
  simple_object_fetch_big_64,
  simple_object_set_big_16,
  simple_object_set_big_16,
  simple_object_set_big_32,
  simple_object_set_big_32,
  simple_object_set_big_64
  simple_object_set_big_64
};
};
 
 
static const struct elf_type_functions elf_little_64_functions =
static const struct elf_type_functions elf_little_64_functions =
{
{
  simple_object_fetch_little_16,
  simple_object_fetch_little_16,
  simple_object_fetch_little_32,
  simple_object_fetch_little_32,
  simple_object_fetch_little_64,
  simple_object_fetch_little_64,
  simple_object_set_little_16,
  simple_object_set_little_16,
  simple_object_set_little_32,
  simple_object_set_little_32,
  simple_object_set_little_64
  simple_object_set_little_64
};
};
 
 
#endif
#endif
 
 
/* Hideous macro to fetch the value of a field from an external ELF
/* Hideous macro to fetch the value of a field from an external ELF
   struct of some sort.  TYPEFUNCS is the set of type functions.
   struct of some sort.  TYPEFUNCS is the set of type functions.
   BUFFER points to the external data.  STRUCTTYPE is the appropriate
   BUFFER points to the external data.  STRUCTTYPE is the appropriate
   struct type.  FIELD is a field within the struct.  TYPE is the type
   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.  */
   of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr.  */
 
 
#define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
#define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
  ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
  ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
 
 
/* Even more hideous macro to fetch the value of FIELD from BUFFER.
/* 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
   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
   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,
   the struct.  TYPE is the type of the field in the struct: Elf_Half,
   Elf_Word, or Elf_Addr.  */
   Elf_Word, or Elf_Addr.  */
 
 
#define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER,      \
#define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER,      \
                              FIELD, TYPE)                              \
                              FIELD, TYPE)                              \
  ELF_FETCH_STRUCT_FIELD (TYPEFUNCS,                                    \
  ELF_FETCH_STRUCT_FIELD (TYPEFUNCS,                                    \
                          Elf ## SIZE ## _External_ ## STRUCTTYPE,      \
                          Elf ## SIZE ## _External_ ## STRUCTTYPE,      \
                          FIELD, BUFFER, TYPE)
                          FIELD, BUFFER, TYPE)
 
 
/* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value.  */
/* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value.  */
 
 
#define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER,           \
#define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER,           \
                        FIELD, TYPE)                                    \
                        FIELD, TYPE)                                    \
  ((CLASS) == ELFCLASS32                                                \
  ((CLASS) == ELFCLASS32                                                \
    ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,  \
    ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,  \
                             TYPE)                                      \
                             TYPE)                                      \
    : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,  \
    : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,  \
                             TYPE))
                             TYPE))
 
 
/* Hideous macro to set the value of a field in an external ELF
/* Hideous macro to set the value of a field in an external ELF
   structure to VAL.  TYPEFUNCS is the set of type functions.  BUFFER
   structure to VAL.  TYPEFUNCS is the set of type functions.  BUFFER
   points to the external data.  STRUCTTYPE is the appropriate
   points to the external data.  STRUCTTYPE is the appropriate
   structure type.  FIELD is a field within the struct.  TYPE is the
   structure type.  FIELD is a field within the struct.  TYPE is the
   type of the field in the struct: Elf_Half, Elf_Word, or
   type of the field in the struct: Elf_Half, Elf_Word, or
   Elf_Addr.  */
   Elf_Addr.  */
 
 
#define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
#define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
  (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
  (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
 
 
/* Even more hideous macro to set the value of FIELD in BUFFER to 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
   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
   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,
   the struct.  TYPE is the type of the field in the struct: Elf_Half,
   Elf_Word, or Elf_Addr.  */
   Elf_Word, or Elf_Addr.  */
 
 
#define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
#define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
                            TYPE, VAL)                                  \
                            TYPE, VAL)                                  \
  ELF_SET_STRUCT_FIELD (TYPEFUNCS,                                      \
  ELF_SET_STRUCT_FIELD (TYPEFUNCS,                                      \
                        Elf ## SIZE ## _External_ ## STRUCTTYPE,        \
                        Elf ## SIZE ## _External_ ## STRUCTTYPE,        \
                        FIELD, BUFFER, TYPE, VAL)
                        FIELD, BUFFER, TYPE, VAL)
 
 
/* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value.  */
/* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value.  */
 
 
#define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD,      \
#define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD,      \
                      TYPE, VAL)                                        \
                      TYPE, VAL)                                        \
  ((CLASS) == ELFCLASS32                                                \
  ((CLASS) == ELFCLASS32                                                \
    ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,    \
    ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,    \
                           TYPE, VAL)                                   \
                           TYPE, VAL)                                   \
    : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,    \
    : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,    \
                           TYPE, VAL))
                           TYPE, VAL))
 
 
/* Private data for an simple_object_read.  */
/* Private data for an simple_object_read.  */
 
 
struct simple_object_elf_read
struct simple_object_elf_read
{
{
  /* Type functions.  */
  /* Type functions.  */
  const struct elf_type_functions* type_functions;
  const struct elf_type_functions* type_functions;
  /* Elf data.  */
  /* Elf data.  */
  unsigned char ei_data;
  unsigned char ei_data;
  /* Elf class.  */
  /* Elf class.  */
  unsigned char ei_class;
  unsigned char ei_class;
  /* ELF OS ABI.  */
  /* ELF OS ABI.  */
  unsigned char ei_osabi;
  unsigned char ei_osabi;
  /* Elf machine number.  */
  /* Elf machine number.  */
  unsigned short machine;
  unsigned short machine;
  /* Processor specific flags.  */
  /* Processor specific flags.  */
  unsigned int flags;
  unsigned int flags;
  /* File offset of section headers.  */
  /* File offset of section headers.  */
  ulong_type shoff;
  ulong_type shoff;
  /* Number of sections.  */
  /* Number of sections.  */
  unsigned int shnum;
  unsigned int shnum;
  /* Index of string table section header.  */
  /* Index of string table section header.  */
  unsigned int shstrndx;
  unsigned int shstrndx;
};
};
 
 
/* Private data for an simple_object_attributes.  */
/* Private data for an simple_object_attributes.  */
 
 
struct simple_object_elf_attributes
struct simple_object_elf_attributes
{
{
  /* Type functions.  */
  /* Type functions.  */
  const struct elf_type_functions* type_functions;
  const struct elf_type_functions* type_functions;
  /* Elf data.  */
  /* Elf data.  */
  unsigned char ei_data;
  unsigned char ei_data;
  /* Elf class.  */
  /* Elf class.  */
  unsigned char ei_class;
  unsigned char ei_class;
  /* ELF OS ABI.  */
  /* ELF OS ABI.  */
  unsigned char ei_osabi;
  unsigned char ei_osabi;
  /* Elf machine number.  */
  /* Elf machine number.  */
  unsigned short machine;
  unsigned short machine;
  /* Processor specific flags.  */
  /* Processor specific flags.  */
  unsigned int flags;
  unsigned int flags;
};
};
 
 
/* See if we have an ELF file.  */
/* See if we have an ELF file.  */
 
 
static void *
static void *
simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
                         int descriptor, off_t offset,
                         int descriptor, off_t offset,
                         const char *segment_name ATTRIBUTE_UNUSED,
                         const char *segment_name ATTRIBUTE_UNUSED,
                         const char **errmsg, int *err)
                         const char **errmsg, int *err)
{
{
  unsigned char ei_data;
  unsigned char ei_data;
  unsigned char ei_class;
  unsigned char ei_class;
  const struct elf_type_functions *type_functions;
  const struct elf_type_functions *type_functions;
  unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
  unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
  struct simple_object_elf_read *eor;
  struct simple_object_elf_read *eor;
 
 
  if (header[EI_MAG0] != ELFMAG0
  if (header[EI_MAG0] != ELFMAG0
      || header[EI_MAG1] != ELFMAG1
      || header[EI_MAG1] != ELFMAG1
      || header[EI_MAG2] != ELFMAG2
      || header[EI_MAG2] != ELFMAG2
      || header[EI_MAG3] != ELFMAG3
      || header[EI_MAG3] != ELFMAG3
      || header[EI_VERSION] != EV_CURRENT)
      || header[EI_VERSION] != EV_CURRENT)
    {
    {
      *errmsg = NULL;
      *errmsg = NULL;
      *err = 0;
      *err = 0;
      return NULL;
      return NULL;
    }
    }
 
 
  ei_data = header[EI_DATA];
  ei_data = header[EI_DATA];
  if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
  if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
    {
    {
      *errmsg = "unknown ELF endianness";
      *errmsg = "unknown ELF endianness";
      *err = 0;
      *err = 0;
      return NULL;
      return NULL;
    }
    }
 
 
  ei_class = header[EI_CLASS];
  ei_class = header[EI_CLASS];
  switch (ei_class)
  switch (ei_class)
    {
    {
    case ELFCLASS32:
    case ELFCLASS32:
      type_functions = (ei_data == ELFDATA2LSB
      type_functions = (ei_data == ELFDATA2LSB
                        ? &elf_little_32_functions
                        ? &elf_little_32_functions
                        : &elf_big_32_functions);
                        : &elf_big_32_functions);
      break;
      break;
 
 
    case ELFCLASS64:
    case ELFCLASS64:
#ifndef UNSIGNED_64BIT_TYPE
#ifndef UNSIGNED_64BIT_TYPE
      *errmsg = "64-bit ELF objects not supported";
      *errmsg = "64-bit ELF objects not supported";
      *err = 0;
      *err = 0;
      return NULL;
      return NULL;
#else
#else
      type_functions = (ei_data == ELFDATA2LSB
      type_functions = (ei_data == ELFDATA2LSB
                        ? &elf_little_64_functions
                        ? &elf_little_64_functions
                        : &elf_big_64_functions);
                        : &elf_big_64_functions);
      break;
      break;
#endif
#endif
 
 
    default:
    default:
      *errmsg = "unrecognized ELF size";
      *errmsg = "unrecognized ELF size";
      *err = 0;
      *err = 0;
      return NULL;
      return NULL;
    }
    }
 
 
  if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr,
  if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr,
                                    errmsg, err))
                                    errmsg, err))
    return NULL;
    return NULL;
 
 
  eor = XNEW (struct simple_object_elf_read);
  eor = XNEW (struct simple_object_elf_read);
  eor->type_functions = type_functions;
  eor->type_functions = type_functions;
  eor->ei_data = ei_data;
  eor->ei_data = ei_data;
  eor->ei_class = ei_class;
  eor->ei_class = ei_class;
  eor->ei_osabi = header[EI_OSABI];
  eor->ei_osabi = header[EI_OSABI];
  eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
  eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
                                  e_machine, Elf_Half);
                                  e_machine, Elf_Half);
  eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
  eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
                                e_flags, Elf_Word);
                                e_flags, Elf_Word);
  eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
  eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
                                e_shoff, Elf_Addr);
                                e_shoff, Elf_Addr);
  eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
  eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
                                e_shnum, Elf_Half);
                                e_shnum, Elf_Half);
  eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
  eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
                                   e_shstrndx, Elf_Half);
                                   e_shstrndx, Elf_Half);
 
 
  if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
  if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
      && eor->shoff != 0)
      && eor->shoff != 0)
    {
    {
      unsigned char shdr[sizeof (Elf64_External_Shdr)];
      unsigned char shdr[sizeof (Elf64_External_Shdr)];
 
 
      /* Object file has more than 0xffff sections.  */
      /* Object file has more than 0xffff sections.  */
 
 
      if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr,
      if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr,
                                        (ei_class == ELFCLASS32
                                        (ei_class == ELFCLASS32
                                         ? sizeof (Elf32_External_Shdr)
                                         ? sizeof (Elf32_External_Shdr)
                                         : sizeof (Elf64_External_Shdr)),
                                         : sizeof (Elf64_External_Shdr)),
                                        errmsg, err))
                                        errmsg, err))
        {
        {
          XDELETE (eor);
          XDELETE (eor);
          return NULL;
          return NULL;
        }
        }
 
 
      if (eor->shnum == 0)
      if (eor->shnum == 0)
        eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
        eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                      shdr, sh_size, Elf_Addr);
                                      shdr, sh_size, Elf_Addr);
 
 
      if (eor->shstrndx == SHN_XINDEX)
      if (eor->shstrndx == SHN_XINDEX)
        {
        {
          eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
          eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                           shdr, sh_link, Elf_Word);
                                           shdr, sh_link, Elf_Word);
 
 
          /* Versions of the GNU binutils between 2.12 and 2.18 did
          /* Versions of the GNU binutils between 2.12 and 2.18 did
             not handle objects with more than SHN_LORESERVE sections
             not handle objects with more than SHN_LORESERVE sections
             correctly.  All large section indexes were offset by
             correctly.  All large section indexes were offset by
             0x100.  There is more information at
             0x100.  There is more information at
             http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
             http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
             Fortunately these object files are easy to detect, as the
             Fortunately these object files are easy to detect, as the
             GNU binutils always put the section header string table
             GNU binutils always put the section header string table
             near the end of the list of sections.  Thus if the
             near the end of the list of sections.  Thus if the
             section header string table index is larger than the
             section header string table index is larger than the
             number of sections, then we know we have to subtract
             number of sections, then we know we have to subtract
             0x100 to get the real section index.  */
             0x100 to get the real section index.  */
          if (eor->shstrndx >= eor->shnum
          if (eor->shstrndx >= eor->shnum
              && eor->shstrndx >= SHN_LORESERVE + 0x100)
              && eor->shstrndx >= SHN_LORESERVE + 0x100)
            eor->shstrndx -= 0x100;
            eor->shstrndx -= 0x100;
        }
        }
    }
    }
 
 
  if (eor->shstrndx >= eor->shnum)
  if (eor->shstrndx >= eor->shnum)
    {
    {
      *errmsg = "invalid ELF shstrndx >= shnum";
      *errmsg = "invalid ELF shstrndx >= shnum";
      *err = 0;
      *err = 0;
      XDELETE (eor);
      XDELETE (eor);
      return NULL;
      return NULL;
    }
    }
 
 
  return (void *) eor;
  return (void *) eor;
}
}
 
 
/* Find all sections in an ELF file.  */
/* Find all sections in an ELF file.  */
 
 
static const char *
static const char *
simple_object_elf_find_sections (simple_object_read *sobj,
simple_object_elf_find_sections (simple_object_read *sobj,
                                 int (*pfn) (void *, const char *,
                                 int (*pfn) (void *, const char *,
                                             off_t offset, off_t length),
                                             off_t offset, off_t length),
                                 void *data,
                                 void *data,
                                 int *err)
                                 int *err)
{
{
  struct simple_object_elf_read *eor =
  struct simple_object_elf_read *eor =
    (struct simple_object_elf_read *) sobj->data;
    (struct simple_object_elf_read *) sobj->data;
  const struct elf_type_functions *type_functions = eor->type_functions;
  const struct elf_type_functions *type_functions = eor->type_functions;
  unsigned char ei_class = eor->ei_class;
  unsigned char ei_class = eor->ei_class;
  size_t shdr_size;
  size_t shdr_size;
  unsigned int shnum;
  unsigned int shnum;
  unsigned char *shdrs;
  unsigned char *shdrs;
  const char *errmsg;
  const char *errmsg;
  unsigned char *shstrhdr;
  unsigned char *shstrhdr;
  size_t name_size;
  size_t name_size;
  off_t shstroff;
  off_t shstroff;
  unsigned char *names;
  unsigned char *names;
  unsigned int i;
  unsigned int i;
 
 
  shdr_size = (ei_class == ELFCLASS32
  shdr_size = (ei_class == ELFCLASS32
               ? sizeof (Elf32_External_Shdr)
               ? sizeof (Elf32_External_Shdr)
               : sizeof (Elf64_External_Shdr));
               : sizeof (Elf64_External_Shdr));
 
 
  /* Read the section headers.  We skip section 0, which is not a
  /* Read the section headers.  We skip section 0, which is not a
     useful section.  */
     useful section.  */
 
 
  shnum = eor->shnum;
  shnum = eor->shnum;
  shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
  shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
 
 
  if (!simple_object_internal_read (sobj->descriptor,
  if (!simple_object_internal_read (sobj->descriptor,
                                    sobj->offset + eor->shoff + shdr_size,
                                    sobj->offset + eor->shoff + shdr_size,
                                    shdrs,
                                    shdrs,
                                    shdr_size * (shnum - 1),
                                    shdr_size * (shnum - 1),
                                    &errmsg, err))
                                    &errmsg, err))
    {
    {
      XDELETEVEC (shdrs);
      XDELETEVEC (shdrs);
      return errmsg;
      return errmsg;
    }
    }
 
 
  /* Read the section names.  */
  /* Read the section names.  */
 
 
  shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
  shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
  name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
  name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                               shstrhdr, sh_size, Elf_Addr);
                               shstrhdr, sh_size, Elf_Addr);
  shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
  shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                              shstrhdr, sh_offset, Elf_Addr);
                              shstrhdr, sh_offset, Elf_Addr);
  names = XNEWVEC (unsigned char, name_size);
  names = XNEWVEC (unsigned char, name_size);
  if (!simple_object_internal_read (sobj->descriptor,
  if (!simple_object_internal_read (sobj->descriptor,
                                    sobj->offset + shstroff,
                                    sobj->offset + shstroff,
                                    names, name_size, &errmsg, err))
                                    names, name_size, &errmsg, err))
    {
    {
      XDELETEVEC (names);
      XDELETEVEC (names);
      XDELETEVEC (shdrs);
      XDELETEVEC (shdrs);
      return errmsg;
      return errmsg;
    }
    }
 
 
  for (i = 1; i < shnum; ++i)
  for (i = 1; i < shnum; ++i)
    {
    {
      unsigned char *shdr;
      unsigned char *shdr;
      unsigned int sh_name;
      unsigned int sh_name;
      const char *name;
      const char *name;
      off_t offset;
      off_t offset;
      off_t length;
      off_t length;
 
 
      shdr = shdrs + (i - 1) * shdr_size;
      shdr = shdrs + (i - 1) * shdr_size;
      sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
      sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                 shdr, sh_name, Elf_Word);
                                 shdr, sh_name, Elf_Word);
      if (sh_name >= name_size)
      if (sh_name >= name_size)
        {
        {
          *err = 0;
          *err = 0;
          XDELETEVEC (names);
          XDELETEVEC (names);
          XDELETEVEC (shdrs);
          XDELETEVEC (shdrs);
          return "ELF section name out of range";
          return "ELF section name out of range";
        }
        }
 
 
      name = (const char *) names + sh_name;
      name = (const char *) names + sh_name;
      offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
      offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                shdr, sh_offset, Elf_Addr);
                                shdr, sh_offset, Elf_Addr);
      length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
      length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                shdr, sh_size, Elf_Addr);
                                shdr, sh_size, Elf_Addr);
 
 
      if (!(*pfn) (data, name, offset, length))
      if (!(*pfn) (data, name, offset, length))
        break;
        break;
    }
    }
 
 
  XDELETEVEC (names);
  XDELETEVEC (names);
  XDELETEVEC (shdrs);
  XDELETEVEC (shdrs);
 
 
  return NULL;
  return NULL;
}
}
 
 
/* Fetch the attributes for an simple_object_read.  */
/* Fetch the attributes for an simple_object_read.  */
 
 
static void *
static void *
simple_object_elf_fetch_attributes (simple_object_read *sobj,
simple_object_elf_fetch_attributes (simple_object_read *sobj,
                                    const char **errmsg ATTRIBUTE_UNUSED,
                                    const char **errmsg ATTRIBUTE_UNUSED,
                                    int *err ATTRIBUTE_UNUSED)
                                    int *err ATTRIBUTE_UNUSED)
{
{
  struct simple_object_elf_read *eor =
  struct simple_object_elf_read *eor =
    (struct simple_object_elf_read *) sobj->data;
    (struct simple_object_elf_read *) sobj->data;
  struct simple_object_elf_attributes *ret;
  struct simple_object_elf_attributes *ret;
 
 
  ret = XNEW (struct simple_object_elf_attributes);
  ret = XNEW (struct simple_object_elf_attributes);
  ret->type_functions = eor->type_functions;
  ret->type_functions = eor->type_functions;
  ret->ei_data = eor->ei_data;
  ret->ei_data = eor->ei_data;
  ret->ei_class = eor->ei_class;
  ret->ei_class = eor->ei_class;
  ret->ei_osabi = eor->ei_osabi;
  ret->ei_osabi = eor->ei_osabi;
  ret->machine = eor->machine;
  ret->machine = eor->machine;
  ret->flags = eor->flags;
  ret->flags = eor->flags;
  return ret;
  return ret;
}
}
 
 
/* Release the privata data for an simple_object_read.  */
/* Release the privata data for an simple_object_read.  */
 
 
static void
static void
simple_object_elf_release_read (void *data)
simple_object_elf_release_read (void *data)
{
{
  XDELETE (data);
  XDELETE (data);
}
}
 
 
/* Compare two attributes structures.  */
/* Compare two attributes structures.  */
 
 
static const char *
static const char *
simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
{
{
  struct simple_object_elf_attributes *to =
  struct simple_object_elf_attributes *to =
    (struct simple_object_elf_attributes *) todata;
    (struct simple_object_elf_attributes *) todata;
  struct simple_object_elf_attributes *from =
  struct simple_object_elf_attributes *from =
    (struct simple_object_elf_attributes *) fromdata;
    (struct simple_object_elf_attributes *) fromdata;
 
 
  if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
  if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
    {
    {
      *err = 0;
      *err = 0;
      return "ELF object format mismatch";
      return "ELF object format mismatch";
    }
    }
 
 
  if (to->machine != from->machine)
  if (to->machine != from->machine)
    {
    {
      int ok;
      int ok;
 
 
      /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
      /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
         output of EM_SPARC32PLUS.  */
         output of EM_SPARC32PLUS.  */
      ok = 0;
      ok = 0;
      switch (to->machine)
      switch (to->machine)
        {
        {
        case EM_SPARC:
        case EM_SPARC:
          if (from->machine == EM_SPARC32PLUS)
          if (from->machine == EM_SPARC32PLUS)
            {
            {
              to->machine = from->machine;
              to->machine = from->machine;
              ok = 1;
              ok = 1;
            }
            }
          break;
          break;
 
 
        case EM_SPARC32PLUS:
        case EM_SPARC32PLUS:
          if (from->machine == EM_SPARC)
          if (from->machine == EM_SPARC)
            ok = 1;
            ok = 1;
          break;
          break;
 
 
        default:
        default:
          break;
          break;
        }
        }
 
 
      if (!ok)
      if (!ok)
        {
        {
          *err = 0;
          *err = 0;
          return "ELF machine number mismatch";
          return "ELF machine number mismatch";
        }
        }
    }
    }
 
 
  return NULL;
  return NULL;
}
}
 
 
/* Release the private data for an attributes structure.  */
/* Release the private data for an attributes structure.  */
 
 
static void
static void
simple_object_elf_release_attributes (void *data)
simple_object_elf_release_attributes (void *data)
{
{
  XDELETE (data);
  XDELETE (data);
}
}
 
 
/* Prepare to write out a file.  */
/* Prepare to write out a file.  */
 
 
static void *
static void *
simple_object_elf_start_write (void *attributes_data,
simple_object_elf_start_write (void *attributes_data,
                               const char **errmsg ATTRIBUTE_UNUSED,
                               const char **errmsg ATTRIBUTE_UNUSED,
                               int *err ATTRIBUTE_UNUSED)
                               int *err ATTRIBUTE_UNUSED)
{
{
  struct simple_object_elf_attributes *attrs =
  struct simple_object_elf_attributes *attrs =
    (struct simple_object_elf_attributes *) attributes_data;
    (struct simple_object_elf_attributes *) attributes_data;
  struct simple_object_elf_attributes *ret;
  struct simple_object_elf_attributes *ret;
 
 
  /* We're just going to record the attributes, but we need to make a
  /* We're just going to record the attributes, but we need to make a
     copy because the user may delete them.  */
     copy because the user may delete them.  */
  ret = XNEW (struct simple_object_elf_attributes);
  ret = XNEW (struct simple_object_elf_attributes);
  *ret = *attrs;
  *ret = *attrs;
  return ret;
  return ret;
}
}
 
 
/* Write out an ELF ehdr.  */
/* Write out an ELF ehdr.  */
 
 
static int
static int
simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
                              const char **errmsg, int *err)
                              const char **errmsg, int *err)
{
{
  struct simple_object_elf_attributes *attrs =
  struct simple_object_elf_attributes *attrs =
    (struct simple_object_elf_attributes *) sobj->data;
    (struct simple_object_elf_attributes *) sobj->data;
  const struct elf_type_functions* fns;
  const struct elf_type_functions* fns;
  unsigned char cl;
  unsigned char cl;
  size_t ehdr_size;
  size_t ehdr_size;
  unsigned char buf[sizeof (Elf64_External_Ehdr)];
  unsigned char buf[sizeof (Elf64_External_Ehdr)];
  simple_object_write_section *section;
  simple_object_write_section *section;
  unsigned int shnum;
  unsigned int shnum;
 
 
  fns = attrs->type_functions;
  fns = attrs->type_functions;
  cl = attrs->ei_class;
  cl = attrs->ei_class;
 
 
  shnum = 0;
  shnum = 0;
  for (section = sobj->sections; section != NULL; section = section->next)
  for (section = sobj->sections; section != NULL; section = section->next)
    ++shnum;
    ++shnum;
  if (shnum > 0)
  if (shnum > 0)
    {
    {
      /* Add a section header for the dummy section and one for
      /* Add a section header for the dummy section and one for
         .shstrtab.  */
         .shstrtab.  */
      shnum += 2;
      shnum += 2;
    }
    }
 
 
  ehdr_size = (cl == ELFCLASS32
  ehdr_size = (cl == ELFCLASS32
               ? sizeof (Elf32_External_Ehdr)
               ? sizeof (Elf32_External_Ehdr)
               : sizeof (Elf64_External_Ehdr));
               : sizeof (Elf64_External_Ehdr));
  memset (buf, 0, sizeof (Elf64_External_Ehdr));
  memset (buf, 0, sizeof (Elf64_External_Ehdr));
 
 
  buf[EI_MAG0] = ELFMAG0;
  buf[EI_MAG0] = ELFMAG0;
  buf[EI_MAG1] = ELFMAG1;
  buf[EI_MAG1] = ELFMAG1;
  buf[EI_MAG2] = ELFMAG2;
  buf[EI_MAG2] = ELFMAG2;
  buf[EI_MAG3] = ELFMAG3;
  buf[EI_MAG3] = ELFMAG3;
  buf[EI_CLASS] = cl;
  buf[EI_CLASS] = cl;
  buf[EI_DATA] = attrs->ei_data;
  buf[EI_DATA] = attrs->ei_data;
  buf[EI_VERSION] = EV_CURRENT;
  buf[EI_VERSION] = EV_CURRENT;
  buf[EI_OSABI] = attrs->ei_osabi;
  buf[EI_OSABI] = attrs->ei_osabi;
 
 
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
  /* e_entry left as zero.  */
  /* e_entry left as zero.  */
  /* e_phoff left as zero.  */
  /* e_phoff left as zero.  */
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
                 (cl == ELFCLASS32
                 (cl == ELFCLASS32
                  ? sizeof (Elf32_External_Phdr)
                  ? sizeof (Elf32_External_Phdr)
                  : sizeof (Elf64_External_Phdr)));
                  : sizeof (Elf64_External_Phdr)));
  /* e_phnum left as zero.  */
  /* e_phnum left as zero.  */
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
                 (cl == ELFCLASS32
                 (cl == ELFCLASS32
                  ? sizeof (Elf32_External_Shdr)
                  ? sizeof (Elf32_External_Shdr)
                  : sizeof (Elf64_External_Shdr)));
                  : sizeof (Elf64_External_Shdr)));
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, shnum);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, shnum);
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half,
  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half,
                 shnum == 0 ? 0 : shnum - 1);
                 shnum == 0 ? 0 : shnum - 1);
 
 
  return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
  return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
                                       errmsg, err);
                                       errmsg, err);
}
}
 
 
/* Write out an ELF shdr.  */
/* Write out an ELF shdr.  */
 
 
static int
static int
simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
                              off_t offset, unsigned int sh_name,
                              off_t offset, unsigned int sh_name,
                              unsigned int sh_type, unsigned int sh_flags,
                              unsigned int sh_type, unsigned int sh_flags,
                              unsigned int sh_offset, unsigned int sh_size,
                              unsigned int sh_offset, unsigned int sh_size,
                              unsigned int sh_addralign, const char **errmsg,
                              unsigned int sh_addralign, const char **errmsg,
                              int *err)
                              int *err)
{
{
  struct simple_object_elf_attributes *attrs =
  struct simple_object_elf_attributes *attrs =
    (struct simple_object_elf_attributes *) sobj->data;
    (struct simple_object_elf_attributes *) sobj->data;
  const struct elf_type_functions* fns;
  const struct elf_type_functions* fns;
  unsigned char cl;
  unsigned char cl;
  size_t shdr_size;
  size_t shdr_size;
  unsigned char buf[sizeof (Elf64_External_Shdr)];
  unsigned char buf[sizeof (Elf64_External_Shdr)];
 
 
  fns = attrs->type_functions;
  fns = attrs->type_functions;
  cl = attrs->ei_class;
  cl = attrs->ei_class;
 
 
  shdr_size = (cl == ELFCLASS32
  shdr_size = (cl == ELFCLASS32
               ? sizeof (Elf32_External_Shdr)
               ? sizeof (Elf32_External_Shdr)
               : sizeof (Elf64_External_Shdr));
               : sizeof (Elf64_External_Shdr));
  memset (buf, 0, sizeof (Elf64_External_Shdr));
  memset (buf, 0, sizeof (Elf64_External_Shdr));
 
 
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
  /* sh_link left as zero.  */
  /* sh_link left as zero.  */
  /* sh_info left as zero.  */
  /* sh_info left as zero.  */
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
  /* sh_entsize left as zero.  */
  /* sh_entsize left as zero.  */
 
 
  return simple_object_internal_write (descriptor, offset, buf, shdr_size,
  return simple_object_internal_write (descriptor, offset, buf, shdr_size,
                                       errmsg, err);
                                       errmsg, err);
}
}
 
 
/* Write out a complete ELF file.
/* Write out a complete ELF file.
   Ehdr
   Ehdr
   initial dummy Shdr
   initial dummy Shdr
   user-created Shdrs
   user-created Shdrs
   .shstrtab Shdr
   .shstrtab Shdr
   user-created section data
   user-created section data
   .shstrtab data  */
   .shstrtab data  */
 
 
static const char *
static const char *
simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
                                 int *err)
                                 int *err)
{
{
  struct simple_object_elf_attributes *attrs =
  struct simple_object_elf_attributes *attrs =
    (struct simple_object_elf_attributes *) sobj->data;
    (struct simple_object_elf_attributes *) sobj->data;
  unsigned char cl;
  unsigned char cl;
  size_t ehdr_size;
  size_t ehdr_size;
  size_t shdr_size;
  size_t shdr_size;
  const char *errmsg;
  const char *errmsg;
  simple_object_write_section *section;
  simple_object_write_section *section;
  unsigned int shnum;
  unsigned int shnum;
  size_t shdr_offset;
  size_t shdr_offset;
  size_t sh_offset;
  size_t sh_offset;
  size_t sh_name;
  size_t sh_name;
  unsigned char zero;
  unsigned char zero;
 
 
  if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
  if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
    return errmsg;
    return errmsg;
 
 
  cl = attrs->ei_class;
  cl = attrs->ei_class;
  if (cl == ELFCLASS32)
  if (cl == ELFCLASS32)
    {
    {
      ehdr_size = sizeof (Elf32_External_Ehdr);
      ehdr_size = sizeof (Elf32_External_Ehdr);
      shdr_size = sizeof (Elf32_External_Shdr);
      shdr_size = sizeof (Elf32_External_Shdr);
    }
    }
  else
  else
    {
    {
      ehdr_size = sizeof (Elf64_External_Ehdr);
      ehdr_size = sizeof (Elf64_External_Ehdr);
      shdr_size = sizeof (Elf64_External_Shdr);
      shdr_size = sizeof (Elf64_External_Shdr);
    }
    }
 
 
  shnum = 0;
  shnum = 0;
  for (section = sobj->sections; section != NULL; section = section->next)
  for (section = sobj->sections; section != NULL; section = section->next)
    ++shnum;
    ++shnum;
  if (shnum == 0)
  if (shnum == 0)
    return NULL;
    return NULL;
 
 
  /* Add initial dummy Shdr and .shstrtab.  */
  /* Add initial dummy Shdr and .shstrtab.  */
  shnum += 2;
  shnum += 2;
 
 
  shdr_offset = ehdr_size;
  shdr_offset = ehdr_size;
  sh_offset = shdr_offset + shnum * shdr_size;
  sh_offset = shdr_offset + shnum * shdr_size;
 
 
  if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
  if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
                                     0, 0, 0, 0, 0, 0, &errmsg, err))
                                     0, 0, 0, 0, 0, 0, &errmsg, err))
    return errmsg;
    return errmsg;
 
 
  shdr_offset += shdr_size;
  shdr_offset += shdr_size;
 
 
  sh_name = 1;
  sh_name = 1;
  for (section = sobj->sections; section != NULL; section = section->next)
  for (section = sobj->sections; section != NULL; section = section->next)
    {
    {
      size_t mask;
      size_t mask;
      size_t new_sh_offset;
      size_t new_sh_offset;
      size_t sh_size;
      size_t sh_size;
      struct simple_object_write_section_buffer *buffer;
      struct simple_object_write_section_buffer *buffer;
 
 
      mask = (1U << section->align) - 1;
      mask = (1U << section->align) - 1;
      new_sh_offset = sh_offset + mask;
      new_sh_offset = sh_offset + mask;
      new_sh_offset &= ~ mask;
      new_sh_offset &= ~ mask;
      while (new_sh_offset > sh_offset)
      while (new_sh_offset > sh_offset)
        {
        {
          unsigned char zeroes[16];
          unsigned char zeroes[16];
          size_t write;
          size_t write;
 
 
          memset (zeroes, 0, sizeof zeroes);
          memset (zeroes, 0, sizeof zeroes);
          write = new_sh_offset - sh_offset;
          write = new_sh_offset - sh_offset;
          if (write > sizeof zeroes)
          if (write > sizeof zeroes)
            write = sizeof zeroes;
            write = sizeof zeroes;
          if (!simple_object_internal_write (descriptor, sh_offset, zeroes,
          if (!simple_object_internal_write (descriptor, sh_offset, zeroes,
                                             write, &errmsg, err))
                                             write, &errmsg, err))
            return errmsg;
            return errmsg;
          sh_offset += write;
          sh_offset += write;
        }
        }
 
 
      sh_size = 0;
      sh_size = 0;
      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
        {
        {
          if (!simple_object_internal_write (descriptor, sh_offset + sh_size,
          if (!simple_object_internal_write (descriptor, sh_offset + sh_size,
                                             ((const unsigned char *)
                                             ((const unsigned char *)
                                              buffer->buffer),
                                              buffer->buffer),
                                             buffer->size, &errmsg, err))
                                             buffer->size, &errmsg, err))
            return errmsg;
            return errmsg;
          sh_size += buffer->size;
          sh_size += buffer->size;
        }
        }
 
 
      if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
      if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
                                         sh_name, SHT_PROGBITS, 0, sh_offset,
                                         sh_name, SHT_PROGBITS, 0, sh_offset,
                                         sh_size, 1U << section->align,
                                         sh_size, 1U << section->align,
                                         &errmsg, err))
                                         &errmsg, err))
        return errmsg;
        return errmsg;
 
 
      shdr_offset += shdr_size;
      shdr_offset += shdr_size;
      sh_name += strlen (section->name) + 1;
      sh_name += strlen (section->name) + 1;
      sh_offset += sh_size;
      sh_offset += sh_size;
    }
    }
 
 
  if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
  if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
                                     sh_name, SHT_STRTAB, 0, sh_offset,
                                     sh_name, SHT_STRTAB, 0, sh_offset,
                                     sh_name + strlen (".shstrtab") + 1,
                                     sh_name + strlen (".shstrtab") + 1,
                                     1, &errmsg, err))
                                     1, &errmsg, err))
    return errmsg;
    return errmsg;
 
 
  /* .shstrtab has a leading zero byte.  */
  /* .shstrtab has a leading zero byte.  */
  zero = 0;
  zero = 0;
  if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
  if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
                                     &errmsg, err))
                                     &errmsg, err))
    return errmsg;
    return errmsg;
  ++sh_offset;
  ++sh_offset;
 
 
  for (section = sobj->sections; section != NULL; section = section->next)
  for (section = sobj->sections; section != NULL; section = section->next)
    {
    {
      size_t len;
      size_t len;
 
 
      len = strlen (section->name) + 1;
      len = strlen (section->name) + 1;
      if (!simple_object_internal_write (descriptor, sh_offset,
      if (!simple_object_internal_write (descriptor, sh_offset,
                                         (const unsigned char *) section->name,
                                         (const unsigned char *) section->name,
                                         len, &errmsg, err))
                                         len, &errmsg, err))
        return errmsg;
        return errmsg;
      sh_offset += len;
      sh_offset += len;
    }
    }
 
 
  if (!simple_object_internal_write (descriptor, sh_offset,
  if (!simple_object_internal_write (descriptor, sh_offset,
                                     (const unsigned char *) ".shstrtab",
                                     (const unsigned char *) ".shstrtab",
                                     strlen (".shstrtab") + 1, &errmsg, err))
                                     strlen (".shstrtab") + 1, &errmsg, err))
    return errmsg;
    return errmsg;
 
 
  return NULL;
  return NULL;
}
}
 
 
/* Release the private data for an simple_object_write structure.  */
/* Release the private data for an simple_object_write structure.  */
 
 
static void
static void
simple_object_elf_release_write (void *data)
simple_object_elf_release_write (void *data)
{
{
  XDELETE (data);
  XDELETE (data);
}
}
 
 
/* The ELF functions.  */
/* The ELF functions.  */
 
 
const struct simple_object_functions simple_object_elf_functions =
const struct simple_object_functions simple_object_elf_functions =
{
{
  simple_object_elf_match,
  simple_object_elf_match,
  simple_object_elf_find_sections,
  simple_object_elf_find_sections,
  simple_object_elf_fetch_attributes,
  simple_object_elf_fetch_attributes,
  simple_object_elf_release_read,
  simple_object_elf_release_read,
  simple_object_elf_attributes_merge,
  simple_object_elf_attributes_merge,
  simple_object_elf_release_attributes,
  simple_object_elf_release_attributes,
  simple_object_elf_start_write,
  simple_object_elf_start_write,
  simple_object_elf_write_to_file,
  simple_object_elf_write_to_file,
  simple_object_elf_release_write
  simple_object_elf_release_write
};
};
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.