diff options
author | Tamar Christina <tamar@zhox.com> | 2017-02-14 09:44:53 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-02-14 10:53:01 -0500 |
commit | 2f1017b924740e66f093b0baba62ac0b1528abf8 (patch) | |
tree | 31bd89a27f0fc968719640e5fb7ed5c6caf8661e /rts/linker/PEi386.c | |
parent | 04f67c9970c0e2599e0b2a29353b1acec72dacf0 (diff) | |
download | haskell-2f1017b924740e66f093b0baba62ac0b1528abf8.tar.gz |
Fix ExtraSymbols jump table on Windows.
This corrects the `jump islands` calculations for Windows. The code was
incorrectly creating a new entry for every `usage` of a symbol instead
of every used symbol. e.g. if a symbol is used 5 times it used to create
5 jump islands. This is incorrect and not in line with what the `ELF`
and `Mach-O` linkers do. Also since we allocate `n` spaces where `n` is
number of symbols, we would quickly run out of space and abort.
Test Plan: ./validate
Reviewers: simonmar, hvr, erikd, bgamari, austin
Reviewed By: bgamari
Subscribers: thomie, #ghc_windows_task_force
Differential Revision: https://phabricator.haskell.org/D3026
Diffstat (limited to 'rts/linker/PEi386.c')
-rw-r--r-- | rts/linker/PEi386.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c index bfac34f501..b62f1eb14b 100644 --- a/rts/linker/PEi386.c +++ b/rts/linker/PEi386.c @@ -73,6 +73,7 @@ static uint8_t* cstring_from_COFF_symbol_name( #if defined(x86_64_HOST_ARCH) static size_t makeSymbolExtra_PEi386( ObjectCode* oc, + uint64_t index, size_t s, SymbolName* symbol); #endif @@ -346,7 +347,7 @@ bool removeLibrarySearchPath_PEi386(HsPtr dll_path_index) } } - return result == 0; + return !result; } @@ -869,8 +870,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc ) rel->VirtualAddress ); sym = (COFF_symbol*) myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex ); - /* Hmm..mysterious looking offset - what's it for? SOF */ - printName ( sym->N.ShortName, strtab -10 ); + printName ( sym->N.ShortName, strtab ); debugBelch("'\n" ); } @@ -1185,24 +1185,25 @@ ocAllocateSymbolExtras_PEi386 ( ObjectCode* oc ) } static size_t -makeSymbolExtra_PEi386( ObjectCode* oc, size_t s, char* symbol ) +makeSymbolExtra_PEi386( ObjectCode* oc, uint64_t index, size_t s, char* symbol ) { unsigned int curr_thunk; SymbolExtra *extra; - - curr_thunk = oc->first_symbol_extra; - if (curr_thunk >= oc->n_symbol_extras) { - barf("Can't allocate thunk for %s", symbol); + curr_thunk = oc->first_symbol_extra + index; + if (index >= oc->n_symbol_extras) { + IF_DEBUG(linker, debugBelch("makeSymbolExtra first:%d, num:%lu, member:%s, index:%llu\n", curr_thunk, oc->n_symbol_extras, oc->archiveMemberName, index)); + barf("Can't allocate thunk for `%s' in `%" PATH_FMT "' with member `%s'", symbol, oc->fileName, oc->archiveMemberName); } extra = oc->symbol_extras + curr_thunk; - // jmp *-14(%rip) - static uint8_t jmp[] = { 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF }; - extra->addr = (uint64_t)s; - memcpy(extra->jumpIsland, jmp, 6); - - oc->first_symbol_extra++; + if (!extra->addr) + { + // jmp *-14(%rip) + static uint8_t jmp[] = { 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF }; + extra->addr = (uint64_t)s; + memcpy(extra->jumpIsland, jmp, 6); + } return (size_t)extra->jumpIsland; } @@ -1313,6 +1314,10 @@ ocResolve_PEi386 ( ObjectCode* oc ) sym = (COFF_symbol*) myindex ( sizeof_COFF_symbol, symtab, reltab_j->SymbolTableIndex ); + uint64_t symIndex = ((uint64_t)myindex(sizeof_COFF_symbol, symtab, + reltab_j->SymbolTableIndex) + - (uint64_t)symtab) / sizeof_COFF_symbol; + IF_DEBUG(linker, debugBelch( "reloc sec %2d num %3d: type 0x%-4x " @@ -1389,7 +1394,7 @@ ocResolve_PEi386 ( ObjectCode* oc ) v = S + ((size_t)A); if (v >> 32) { copyName ( sym->N.ShortName, strtab, symbol, 1000-1 ); - S = makeSymbolExtra_PEi386(oc, S, (char *)symbol); + S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol); /* And retry */ v = S + ((size_t)A); if (v >> 32) { @@ -1407,7 +1412,7 @@ ocResolve_PEi386 ( ObjectCode* oc ) if ((v >> 32) && ((-v) >> 32)) { /* Make the trampoline then */ copyName ( sym->N.ShortName, strtab, symbol, 1000-1 ); - S = makeSymbolExtra_PEi386(oc, S, (char *)symbol); + S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol); /* And retry */ v = ((intptr_t)S) + ((intptr_t)(int32_t)A) - ((intptr_t)pP) - 4; if ((v >> 32) && ((-v) >> 32)) { |