diff options
author | Moritz Angermann <moritz.angermann@gmail.com> | 2017-04-23 10:02:02 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-04-23 11:05:48 -0400 |
commit | e5e8646d3c6af82549b55fbee6764b087144a7ec (patch) | |
tree | 7f9afbe3dfb7a24c6d34e8db56f2581d7045fdf0 /rts | |
parent | 1d66f1051933ca3dedbf04da9ce38687dbfd8f05 (diff) | |
download | haskell-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
Diffstat (limited to 'rts')
-rw-r--r-- | rts/LinkerInternals.h | 15 | ||||
-rw-r--r-- | rts/linker/Elf.c | 95 | ||||
-rw-r--r-- | rts/linker/ElfTypes.h | 171 |
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 */ |