Commit e5e8646d authored by Moritz Angermann's avatar Moritz Angermann Committed by Ben Gamari

[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
parent 1d66f105
......@@ -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; };
......
......@@ -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;
......
#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 */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment