[linker] Adds ElfTypes
authorMoritz Angermann <moritz.angermann@gmail.com>
Sun, 23 Apr 2017 14:02:02 +0000 (10:02 -0400)
committerBen Gamari <ben@smart-cactus.org>
Sun, 23 Apr 2017 15:05:48 +0000 (11:05 -0400)
This diff introduces ElfTypes similar to provide the linker
code with a richer data structure, similar to the approach
taken for mach-o already.

Reviewers: bgamari, austin, erikd, simonmar

Reviewed By: simonmar

Subscribers: rwbarton, thomie

Differential Revision: https://phabricator.haskell.org/D3445

rts/LinkerInternals.h
rts/linker/Elf.c
rts/linker/ElfTypes.h [new file with mode: 0644]

index 65b95f7..c33be05 100644 (file)
@@ -101,17 +101,17 @@ typedef struct ForeignExportStablePtr_ {
  * address relocations on the PowerPC, x86_64 and ARM.
  */
 typedef struct {
-#ifdef powerpc_HOST_ARCH
+#if defined(powerpc_HOST_ARCH)
     struct {
         short lis_r12, hi_addr;
         short ori_r12_r12, lo_addr;
         long mtctr_r12;
         long bctr;
     } jumpIsland;
-#elif x86_64_HOST_ARCH
+#elif defined(x86_64_HOST_ARCH)
     uint64_t    addr;
     uint8_t     jumpIsland[6];
-#elif arm_HOST_ARCH
+#elif defined(arm_HOST_ARCH)
     uint8_t     jumpIsland[16];
 #endif
 } SymbolExtra;
@@ -167,7 +167,7 @@ typedef struct _ObjectCode {
        outside one of these is an error in the linker. */
     ProddableBlock* proddables;
 
-#ifdef ia64_HOST_ARCH
+#if defined(ia64_HOST_ARCH)
     /* Procedure Linkage Table for this object */
     void *plt;
     unsigned int pltIndex;
@@ -196,7 +196,7 @@ typedef struct _ObjectCode {
 extern ObjectCode *objects;
 extern ObjectCode *unloaded_objects;
 
-#ifdef THREADED_RTS
+#if defined(THREADED_RTS)
 extern Mutex linker_mutex;
 extern Mutex linker_unloaded_mutex;
 #endif
@@ -282,7 +282,7 @@ ObjectCode* mkOc( pathchar *path, char *image, int imageSize,
                   int misalignment
                   );
 
-#if defined (mingw32_HOST_OS)
+#if defined(mingw32_HOST_OS)
 /* We use myindex to calculate array addresses, rather than
    simply doing the normal subscript thing.  That's because
    some of the above structs have sizes which are not
@@ -317,8 +317,7 @@ char *cstring_from_section_name(
 || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) \
 || defined(openbsd_HOST_OS) || defined(gnu_HOST_OS)
 #  define OBJFORMAT_ELF
-struct _SectionFormatInfo { void* placeholder; };
-struct _ObjectCodeFormatInfo { void* placeholder; };
+#  include "linker/ElfTypes.h"
 #elif defined (mingw32_HOST_OS)
 #  define OBJFORMAT_PEi386
 struct _SectionFormatInfo { void* placeholder; };
index e41c066..5b67548 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_SYS_STAT_H
+#if defined(HAVE_SYS_STAT_H)
 #include <sys/stat.h>
 #endif
-#ifdef HAVE_SYS_TYPES_H
+#if defined(HAVE_SYS_TYPES_H)
 #include <sys/types.h>
 #endif
-#ifdef HAVE_FCNTL_H
+#if defined(HAVE_FCNTL_H)
 #include <fcntl.h>
 #endif
 #if defined(dragonfly_HOST_OS)
 #  define ELF_TARGET_386    /* Used inside <elf.h> */
 #elif defined(x86_64_HOST_ARCH)
 #  define ELF_TARGET_X64_64
-#  define ELF_64BIT
 #  define ELF_TARGET_AMD64 /* Used inside <elf.h> on Solaris 11 */
-#elif defined(powerpc64_HOST_ARCH) || defined(powerpc64le_HOST_ARCH)
-#  define ELF_64BIT
-#elif defined(ia64_HOST_ARCH)
-#  define ELF_64BIT
-#elif defined(aarch64_HOST_ARCH)
-#  define ELF_64BIT
 #endif
 
 #if !defined(openbsd_HOST_OS)
 #  define R_ARM_THM_JUMP8      103
 #endif
 
-/*
- * Define a set of types which can be used for both ELF32 and ELF64
- */
-
-#ifdef ELF_64BIT
-#define ELFCLASS    ELFCLASS64
-#define Elf_Addr    Elf64_Addr
-#define Elf_Word    Elf64_Word
-#define Elf_Sword   Elf64_Sword
-#define Elf_Half    Elf64_Half
-#define Elf_Ehdr    Elf64_Ehdr
-#define Elf_Phdr    Elf64_Phdr
-#define Elf_Shdr    Elf64_Shdr
-#define Elf_Sym     Elf64_Sym
-#define Elf_Rel     Elf64_Rel
-#define Elf_Rela    Elf64_Rela
-#ifndef ELF_ST_TYPE
-#define ELF_ST_TYPE ELF64_ST_TYPE
-#endif
-#ifndef ELF_ST_BIND
-#define ELF_ST_BIND ELF64_ST_BIND
-#endif
-#ifndef ELF_R_TYPE
-#define ELF_R_TYPE  ELF64_R_TYPE
-#endif
-#ifndef ELF_R_SYM
-#define ELF_R_SYM   ELF64_R_SYM
-#endif
-#else
-#define ELFCLASS    ELFCLASS32
-#define Elf_Addr    Elf32_Addr
-#define Elf_Word    Elf32_Word
-#define Elf_Sword   Elf32_Sword
-#define Elf_Half    Elf32_Half
-#define Elf_Ehdr    Elf32_Ehdr
-#define Elf_Phdr    Elf32_Phdr
-#define Elf_Shdr    Elf32_Shdr
-#define Elf_Sym     Elf32_Sym
-#define Elf_Rel     Elf32_Rel
-#define Elf_Rela    Elf32_Rela
-#ifndef ELF_ST_TYPE
-#define ELF_ST_TYPE ELF32_ST_TYPE
-#endif
-#ifndef ELF_ST_BIND
-#define ELF_ST_BIND ELF32_ST_BIND
-#endif
-#ifndef ELF_R_TYPE
-#define ELF_R_TYPE  ELF32_R_TYPE
-#endif
-#ifndef ELF_R_SYM
-#define ELF_R_SYM   ELF32_R_SYM
-#endif
-#endif
-
 
 
 /*
@@ -301,25 +240,25 @@ ocVerifyImage_ELF ( ObjectCode* oc )
 
    IF_DEBUG(linker,debugBelch( "Architecture is " ));
    switch (ehdr->e_machine) {
-#ifdef EM_ARM
+#if defined(EM_ARM)
       case EM_ARM:   IF_DEBUG(linker,debugBelch( "arm" )); break;
 #endif
       case EM_386:   IF_DEBUG(linker,debugBelch( "x86" )); break;
-#ifdef EM_SPARC32PLUS
+#if defined(EM_SPARC32PLUS)
       case EM_SPARC32PLUS:
 #endif
       case EM_SPARC: IF_DEBUG(linker,debugBelch( "sparc" )); break;
-#ifdef EM_IA_64
+#if defined(EM_IA_64)
       case EM_IA_64: IF_DEBUG(linker,debugBelch( "ia64" )); break;
 #endif
       case EM_PPC:   IF_DEBUG(linker,debugBelch( "powerpc32" )); break;
-#ifdef EM_PPC64
+#if defined(EM_PPC64)
       case EM_PPC64: IF_DEBUG(linker,debugBelch( "powerpc64" ));
           errorBelch("%s: RTS linker not implemented on PowerPC 64-bit",
                      oc->fileName);
           return 0;
 #endif
-#ifdef EM_X86_64
+#if defined(EM_X86_64)
       case EM_X86_64: IF_DEBUG(linker,debugBelch( "x86_64" )); break;
 #elif defined(EM_AMD64)
       case EM_AMD64: IF_DEBUG(linker,debugBelch( "amd64" )); break;
@@ -527,7 +466,7 @@ static int getSectionKind_ELF( Elf_Shdr *hdr, int *is_bss )
         /* .rodata-style section */
         return SECTIONKIND_CODE_OR_RODATA;
     }
-#ifdef SHT_INIT_ARRAY
+#if defined(SHT_INIT_ARRAY)
     if (hdr->sh_type == SHT_INIT_ARRAY
         && (hdr->sh_flags & SHF_ALLOC) && (hdr->sh_flags & SHF_WRITE)) {
        /* .init_array section */
@@ -733,7 +672,7 @@ ocGetNames_ELF ( ObjectCode* oc )
                isLocal = true;
                isWeak = false;
             } else { /* STB_GLOBAL or STB_WEAK */
-#ifdef ELF_FUNCTION_DESC
+#if defined(ELF_FUNCTION_DESC)
                /* dlsym() and the initialisation table both give us function
                 * descriptors, so to be consistent we store function descriptors
                 * in the symbol table */
@@ -803,7 +742,7 @@ end:
    return result;
 }
 
-#ifdef arm_HOST_ARCH
+#if defined(arm_HOST_ARCH)
 // TODO: These likely belong in a library somewhere
 
 // Signed extend a number to a 32-bit int.
@@ -861,10 +800,10 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
 #endif
       Elf_Addr  S;
       void*     S_tmp;
-#ifdef i386_HOST_ARCH
+#if defined(i386_HOST_ARCH)
       Elf_Addr  value;
 #endif
-#ifdef arm_HOST_ARCH
+#if defined(arm_HOST_ARCH)
       int is_target_thm=0, T=0;
 #endif
 
@@ -901,7 +840,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
          }
          IF_DEBUG(linker,debugBelch( "`%s' resolves to %p\n", symbol, (void*)S ));
 
-#ifdef arm_HOST_ARCH
+#if defined(arm_HOST_ARCH)
           /*
            * 4.5.3 Symbol Values
            *
@@ -941,7 +880,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
                              (void*)P, (void*)S, (void*)A, reloc_type ));
       checkProddableBlock ( oc, pP, sizeof(Elf_Word) );
 
-#ifdef i386_HOST_ARCH
+#if defined(i386_HOST_ARCH)
       value = S + A;
 #endif
 
@@ -1176,7 +1115,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
    Elf_Word* shndx_table = get_shndx_table((Elf_Ehdr*)ehdrC);
 #endif
 #if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)
-   /* This #ifdef only serves to avoid unused-var warnings. */
+   /* This #if def only serves to avoid unused-var warnings. */
    Elf_Addr targ = (Elf_Addr) oc->sections[target_shndx].start;
 #endif
 
@@ -1194,7 +1133,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
 
    for (j = 0; j < nent; j++) {
 #if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)
-      /* This #ifdef only serves to avoid unused-var warnings. */
+      /* This #if def only serves to avoid unused-var warnings. */
       Elf_Addr  offset = rtab[j].r_offset;
       Elf_Addr  P      = targ + offset;
       Elf_Addr  A      = rtab[j].r_addend;
diff --git a/rts/linker/ElfTypes.h b/rts/linker/ElfTypes.h
new file mode 100644 (file)
index 0000000..a9f4a02
--- /dev/null
@@ -0,0 +1,171 @@
+#ifndef ElfTypes_h
+#define ElfTypes_h
+
+#if defined(OBJFORMAT_ELF)
+
+#include "ghcplatform.h"
+
+#include <elf.h>
+
+/*
+ * Define a set of types which can be used for both ELF32 and ELF64
+ */
+
+#  define ELF_TARGET_AMD64 /* Used inside <elf.h> on Solaris 11 */
+#if defined(powerpc64_HOST_ARCH) || defined(powerpc64le_HOST_ARCH) \
+ || defined(ia64_HOST_ARCH) || defined(aarch64_HOST_ARCH) \
+ || defined(x86_64_HOST_ARCH)
+#  define ELF_64BIT
+#elif defined(sparc_HOST_ARCH) || defined(i386_HOST_ARCH) \
+ || defined(arm_HOST_ARCH)
+#  define ELF_32BIT
+#else
+#  error "Unsupported arch!"
+#endif
+
+#if defined(ELF_64BIT)
+#define ELFCLASS    ELFCLASS64
+#define Elf_Addr    Elf64_Addr
+#define Elf_Word    Elf64_Word
+#define Elf_Sword   Elf64_Sword
+#define Elf_Half    Elf64_Half
+#define Elf_Ehdr    Elf64_Ehdr
+#define Elf_Phdr    Elf64_Phdr
+#define Elf_Shdr    Elf64_Shdr
+#define Elf_Sym     Elf64_Sym
+#define Elf_Rel     Elf64_Rel
+#define Elf_Rela    Elf64_Rela
+#if !defined(ELF_ST_TYPE)
+#define ELF_ST_TYPE ELF64_ST_TYPE
+#endif
+#if !defined(ELF_ST_BIND)
+#define ELF_ST_BIND ELF64_ST_BIND
+#endif
+#if !defined(ELF_R_TYPE)
+#define ELF_R_TYPE  ELF64_R_TYPE
+#endif
+#if !defined(ELF_R_SYM)
+#define ELF_R_SYM   ELF64_R_SYM
+#endif
+#else
+#define ELFCLASS    ELFCLASS32
+#define Elf_Addr    Elf32_Addr
+#define Elf_Word    Elf32_Word
+#define Elf_Sword   Elf32_Sword
+#define Elf_Half    Elf32_Half
+#define Elf_Ehdr    Elf32_Ehdr
+#define Elf_Phdr    Elf32_Phdr
+#define Elf_Shdr    Elf32_Shdr
+#define Elf_Sym     Elf32_Sym
+#define Elf_Rel     Elf32_Rel
+#define Elf_Rela    Elf32_Rela
+#if !defined(ELF_ST_TYPE)
+#define ELF_ST_TYPE ELF32_ST_TYPE
+#endif /* ELF_ST_TYPE */
+#if !defined(ELF_ST_BIND)
+#define ELF_ST_BIND ELF32_ST_BIND
+#endif /* ELF_ST_BIND */
+#if !defined(ELF_R_TYPE)
+#define ELF_R_TYPE  ELF32_R_TYPE
+#endif /* ELF_R_TYPE */
+#if !defined(ELF_R_SYM)
+#define ELF_R_SYM   ELF32_R_SYM
+#endif /* ELF_R_SYM */
+#endif /* ELF_64BIT */
+
+typedef struct _ElfSymbol {
+    SymbolName * name;  /* the name of the symbol. */
+    SymbolAddr * addr;  /* the final resting place of the symbol */
+    void * got_addr;    /* address of the got slot for this symbol, if any */
+    Elf_Sym * elf_sym;  /* the elf symbol entry */
+} ElfSymbol;
+
+typedef struct _ElfSymbolTable {
+    unsigned  index;               /* the index of the underlying symtab */
+    ElfSymbol * symbols;
+    size_t n_symbols;
+    char * names;                  /* strings table for this symbol table */
+    struct _ElfSymbolTable * next; /* there may be multiple symbol tables */
+} ElfSymbolTable;
+
+typedef struct _ElfRelocationTable {
+    unsigned index;
+    unsigned targetSectionIndex;
+    Elf_Shdr *sectionHeader;
+    Elf_Rel  *relocations;
+    size_t n_relocations;
+    struct _ElfRelocationTable *next;
+} ElfRelocationTable;
+
+typedef struct _ElfRelocationATable {
+    unsigned index;
+    unsigned targetSectionIndex;
+    Elf_Shdr *sectionHeader;
+    Elf_Rela  *relocations;
+    size_t n_relocations;
+    struct _ElfRelocationATable *next;
+} ElfRelocationATable;
+
+/*
+ * Just a quick ELF recap:
+ *
+ * .-----------------.
+ * | ELF Header      |
+ * |-----------------|
+ * | Program Header  |
+ * |-----------------|   .
+ * | Section 1       |   |
+ * |-----------------|   | Segment 1
+ * | Section 2       |   |
+ * |-----------------|   :
+ * | ...             |   |
+ * |-----------------|   | Segment n
+ * | Section n       |   '
+ * |-----------------|
+ * | Section Header  |
+ * '-----------------'
+ *
+ *
+ * The Program Header will inform us about the Segments.  Whereas the Section
+ * Header provides Information about the sections.
+ *
+ */
+typedef struct _ObjectCodeFormatInfo {
+    Elf_Ehdr             *elfHeader;
+    Elf_Phdr             *programHeader;
+    Elf_Shdr             *sectionHeader;
+    char                 *sectionHeaderStrtab;
+
+    ElfSymbolTable       *symbolTables;
+    ElfRelocationTable   *relTable;
+    ElfRelocationATable  *relaTable;
+
+
+    /* pointer to the global offset table */
+    void *                got_start;
+    size_t                got_size;
+
+} ObjectCodeFormatInfo;
+
+typedef
+struct _Stub {
+    void * addr;
+    void * target;
+    struct _Stub * next;
+} Stub;
+
+typedef struct _SectionFormatInfo {
+    /*
+     * The following fields are relevant for stubs next to sections only.
+     */
+    void * stub_offset;
+    size_t stub_size;
+    size_t nstubs;
+    Stub * stubs;
+
+    char * name;
+
+    Elf_Shdr *sectionHeader;
+} SectionFormatInfo;
+#endif /* OBJECTFORMAT_ELF */
+#endif /* ElfTypes_h */