summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamar Christina <tamar@zhox.com>2017-02-14 09:44:53 -0500
committerBen Gamari <ben@smart-cactus.org>2017-02-14 10:53:01 -0500
commit2f1017b924740e66f093b0baba62ac0b1528abf8 (patch)
tree31bd89a27f0fc968719640e5fb7ed5c6caf8661e
parent04f67c9970c0e2599e0b2a29353b1acec72dacf0 (diff)
downloadhaskell-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
-rw-r--r--rts/linker/PEi386.c37
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)) {