summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoritz Angermann <moritz.angermann@gmail.com>2017-04-23 10:02:02 -0400
committerBen Gamari <ben@smart-cactus.org>2017-04-23 11:05:48 -0400
commite5e8646d3c6af82549b55fbee6764b087144a7ec (patch)
tree7f9afbe3dfb7a24c6d34e8db56f2581d7045fdf0
parent1d66f1051933ca3dedbf04da9ce38687dbfd8f05 (diff)
downloadhaskell-e5e8646d3c6af82549b55fbee6764b087144a7ec.tar.gz
[linker] Adds ElfTypes
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
-rw-r--r--rts/LinkerInternals.h15
-rw-r--r--rts/linker/Elf.c95
-rw-r--r--rts/linker/ElfTypes.h171
3 files changed, 195 insertions, 86 deletions
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 65b95f757c..c33be05112 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -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; };
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index e41c066644..5b67548a1b 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -17,13 +17,13 @@
#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)
@@ -73,14 +73,7 @@
# 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)
@@ -136,60 +129,6 @@
# 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
index 0000000000..a9f4a023c4
--- /dev/null
+++ b/rts/linker/ElfTypes.h
@@ -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 */