diff options
author | Moritz Angermann <moritz.angermann@gmail.com> | 2017-05-01 11:18:14 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-05-01 11:18:23 -0400 |
commit | e25017819b58efd0a4c45796fa8ab8af6cc5db93 (patch) | |
tree | 2b9f316acf95381e53f0d39da370608f2d1546c8 /rts/linker | |
parent | 5c602d2228d28530621cc6c94fbb736b13f474fb (diff) | |
download | haskell-e25017819b58efd0a4c45796fa8ab8af6cc5db93.tar.gz |
[linker] Add ocInit/ocDeinit for ELF
This fills out the extended `info` structs, and will be subsequently
used in the arm and arm64 linker for elf.
Depends on: D3446, D3459
Reviewers: bgamari, austin, erikd, simonmar
Reviewed By: simonmar
Subscribers: rwbarton, thomie
Differential Revision: https://phabricator.haskell.org/D3447
Diffstat (limited to 'rts/linker')
-rw-r--r-- | rts/linker/Elf.c | 166 | ||||
-rw-r--r-- | rts/linker/Elf.h | 4 | ||||
-rw-r--r-- | rts/linker/LoadArchive.c | 5 |
3 files changed, 171 insertions, 4 deletions
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c index 9d60b393a0..c1caf9af23 100644 --- a/rts/linker/Elf.c +++ b/rts/linker/Elf.c @@ -155,6 +155,160 @@ get_shndx_table(Elf_Ehdr* ehdr) #endif /* + * ocInit and ocDeinit + */ + +void +ocInit_ELF(ObjectCode * oc) +{ + oc->info = (ObjectCodeFormatInfo*)stgCallocBytes( + 1, sizeof(ObjectCodeFormatInfo), + "ocInit_Elf(ObjectCodeFormatInfo)"); + // TODO: fill info + oc->info->elfHeader = (Elf_Ehdr *)oc->image; + oc->info->programHeader = (Elf_Phdr *) ((uint8_t*)oc->image + + oc->info->elfHeader->e_phoff); + oc->info->sectionHeader = (Elf_Shdr *) ((uint8_t*)oc->image + + oc->info->elfHeader->e_shoff); + + oc->n_sections = elf_shnum(oc->info->elfHeader); + + /* get the symbol table(s) */ + for(int i=0; i < oc->n_sections; i++) { + if(SHT_REL == oc->info->sectionHeader[i].sh_type) { + ElfRelocationTable *relTab = (ElfRelocationTable *)stgCallocBytes( + 1, sizeof(ElfRelocationTable), + "ocInit_Elf(ElfRelocationTable"); + relTab->index = i; + + relTab->relocations = + (Elf_Rel*) ((uint8_t*)oc->info->elfHeader + + oc->info->sectionHeader[i].sh_offset); + relTab->n_relocations = oc->info->sectionHeader[i].sh_size + / sizeof(Elf_Rel); + relTab->targetSectionIndex = oc->info->sectionHeader[i].sh_info; + + relTab->sectionHeader = &oc->info->sectionHeader[i]; + + if(oc->info->relTable == NULL) { + oc->info->relTable = relTab; + } else { + ElfRelocationTable * tail = oc->info->relTable; + while(tail->next != NULL) tail = tail->next; + tail->next = relTab; + } + + } else if(SHT_RELA == oc->info->sectionHeader[i].sh_type) { + ElfRelocationATable *relTab = (ElfRelocationATable *)stgCallocBytes( + 1, sizeof(ElfRelocationATable), + "ocInit_Elf(ElfRelocationTable"); + relTab->index = i; + + relTab->relocations = + (Elf_Rela*) ((uint8_t*)oc->info->elfHeader + + oc->info->sectionHeader[i].sh_offset); + relTab->n_relocations = oc->info->sectionHeader[i].sh_size + / sizeof(Elf_Rela); + relTab->targetSectionIndex = oc->info->sectionHeader[i].sh_info; + + relTab->sectionHeader = &oc->info->sectionHeader[i]; + + if(oc->info->relaTable == NULL) { + oc->info->relaTable = relTab; + } else { + ElfRelocationATable * tail = oc->info->relaTable; + while(tail->next != NULL) tail = tail->next; + tail->next = relTab; + } + + } else if(SHT_SYMTAB == oc->info->sectionHeader[i].sh_type) { + + ElfSymbolTable *symTab = (ElfSymbolTable *)stgCallocBytes( + 1, sizeof(ElfSymbolTable), + "ocInit_Elf(ElfSymbolTable"); + + symTab->index = i; /* store the original index, so we can later + * find or assert that we are dealing with the + * correct symbol table */ + + Elf_Sym *stab = (Elf_Sym*)((uint8_t*)oc->info->elfHeader + + oc->info->sectionHeader[i].sh_offset); + symTab->n_symbols = oc->info->sectionHeader[i].sh_size + / sizeof(Elf_Sym); + symTab->symbols = (ElfSymbol *)stgCallocBytes( + symTab->n_symbols, sizeof(ElfSymbol), + "ocInit_Elf(ElfSymbol)"); + + /* get the strings table */ + size_t lnkIdx = oc->info->sectionHeader[i].sh_link; + symTab->names = (char*)(uint8_t*)oc->info->elfHeader + + oc->info->sectionHeader[lnkIdx].sh_offset; + + /* build the ElfSymbols from the symbols */ + for(size_t j=0; j < symTab->n_symbols; j++) { + + symTab->symbols[j].name = stab[j].st_name == 0 + ? "(noname)" + : symTab->names + stab[j].st_name; + symTab->symbols[j].elf_sym = &stab[j]; + /* we don't have an address for this symbol yet; this will be + * populated during ocGetNames. hence addr = NULL. + */ + symTab->symbols[j].addr = NULL; + symTab->symbols[j].got_addr = NULL; + } + + /* append the ElfSymbolTable */ + if(oc->info->symbolTables == NULL) { + oc->info->symbolTables = symTab; + } else { + ElfSymbolTable * tail = oc->info->symbolTables; + while(tail->next != NULL) tail = tail->next; + tail->next = symTab; + } + } + } +} + +void +ocDeinit_ELF(ObjectCode * oc) +{ + /* free all ElfSymbolTables, and their associated + * ElfSymbols + */ + if(oc->info != NULL) { + ElfSymbolTable * last = oc->info->symbolTables; + + while(last != NULL) { + ElfSymbolTable * t = last; + last = last->next; + stgFree(t->symbols); + stgFree(t); + } + + { + ElfRelocationTable *last = oc->info->relTable; + while (last != NULL) { + ElfRelocationTable *t = last; + last = last->next; + stgFree(t); + } + } + + { + ElfRelocationATable *last = oc->info->relaTable; + while (last != NULL) { + ElfRelocationATable *t = last; + last = last->next; + stgFree(t); + } + } + + stgFree(oc->info); + } +} + +/* * Generic ELF functions */ @@ -1074,7 +1228,8 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, #if defined(SHN_XINDEX) 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) +#if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ + || defined(x86_64_HOST_ARCH) /* This #if def only serves to avoid unused-var warnings. */ Elf_Addr targ = (Elf_Addr) oc->sections[target_shndx].start; #endif @@ -1092,13 +1247,15 @@ 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) +#if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ + || defined(x86_64_HOST_ARCH) /* 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; #endif -#if defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) +#if defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ + || defined(x86_64_HOST_ARCH) Elf_Addr value; #endif Elf_Addr info = rtab[j].r_info; @@ -1153,7 +1310,8 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, checkProddableBlock(oc, (void*)P, sizeof(Elf_Word)); #endif -#if defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) +#if defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ + || defined(x86_64_HOST_ARCH) value = S + A; #endif diff --git a/rts/linker/Elf.h b/rts/linker/Elf.h index 57ec46e146..42548a0249 100644 --- a/rts/linker/Elf.h +++ b/rts/linker/Elf.h @@ -5,6 +5,10 @@ #include "BeginPrivate.h" +#include "ElfTypes.h" + +void ocInit_ELF ( ObjectCode* oc ); +void ocDeinit_ELF ( ObjectCode* oc ); int ocVerifyImage_ELF ( ObjectCode* oc ); int ocGetNames_ELF ( ObjectCode* oc ); int ocResolve_ELF ( ObjectCode* oc ); diff --git a/rts/linker/LoadArchive.c b/rts/linker/LoadArchive.c index 97546c2457..06a143e056 100644 --- a/rts/linker/LoadArchive.c +++ b/rts/linker/LoadArchive.c @@ -15,6 +15,8 @@ # include <regex.h> # include <mach/machine.h> # include <mach-o/fat.h> +#elif defined(OBJFORMAT_ELF) +#include "linker/Elf.h" #endif #include <string.h> @@ -540,6 +542,9 @@ static HsInt loadArchive_ (pathchar *path) #if defined(OBJFORMAT_MACHO) ocInit_MachO( oc ); #endif +#if defined(OBJFORMAT_ELF) + ocInit_ELF( oc ); +#endif stgFree(archiveMemberName); |