summaryrefslogtreecommitdiff
path: root/rts/linker
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-02-04 08:53:27 -0500
committerBen Gamari <ben@smart-cactus.org>2022-04-06 16:25:25 -0400
commite689e9d5d058dbe05890038c28abdf3301679d7b (patch)
treecc45413a703faf8aecaa54ce1993b6f7de6ff62c /rts/linker
parentd286a55caebca8a4e5e73bbfeeb766e333271a09 (diff)
downloadhaskell-e689e9d5d058dbe05890038c28abdf3301679d7b.tar.gz
rts/PEi386: Fix relocation overflow behavior
This fixes handling of overflowed relocations on PEi386 targets: * Refuse to create jump islands for relocations of data symbols * Correctly handle the `__imp___acrt_iob_func` symbol, which is an new type of symbol: `SYM_TYPE_INDIRECT_DATA`
Diffstat (limited to 'rts/linker')
-rw-r--r--rts/linker/PEi386.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 00c28a959d..b8bcc8abec 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -1780,16 +1780,24 @@ ocAllocateExtras_PEi386 ( ObjectCode* oc )
}
static size_t
-makeSymbolExtra_PEi386( ObjectCode* oc, uint64_t index STG_UNUSED, size_t s, char* symbol STG_UNUSED )
+makeSymbolExtra_PEi386( ObjectCode* oc, uint64_t index STG_UNUSED, size_t s, char* symbol STG_UNUSED, SymType type )
{
SymbolExtra *extra = m32_alloc(oc->rx_m32, sizeof(SymbolExtra), 8);
- // 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;
+ if (type == SYM_TYPE_CODE) {
+ // jmp *-14(%rip)
+ extra->addr = (uint64_t)s;
+ static uint8_t jmp[] = { 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF };
+ memcpy(extra->jumpIsland, jmp, 6);
+ return (size_t)&extra->jumpIsland;
+ } else if (type == SYM_TYPE_INDIRECT_DATA) {
+ void *v = *(void**) s;
+ extra->addr = (uint64_t)v;
+ return (size_t)&extra->addr;
+ } else {
+ extra->addr = (uint64_t)s;
+ return (size_t)&extra->addr;
+ }
}
void ocProtectExtras(ObjectCode* oc STG_UNUSED) { }
@@ -1842,6 +1850,8 @@ ocResolve_PEi386 ( ObjectCode* oc )
uint64_t symIndex = reloc->SymbolTableIndex;
sym = &oc->info->symbols[symIndex];
+ SymType sym_type;
+
IF_DEBUG(linker_verbose,
debugBelch(
"reloc sec %2d num %3d: type 0x%-4x "
@@ -1859,7 +1869,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
} else {
copyName ( getSymShortName (info, sym), oc, symbol,
sizeof(symbol)-1 );
- S = (size_t) lookupDependentSymbol( (char*)symbol, oc, NULL );
+ S = (size_t) lookupDependentSymbol( (char*)symbol, oc, &sym_type );
if ((void*)S == NULL) {
errorBelch(" | %" PATH_FMT ": unknown symbol `%s'", oc->fileName, symbol);
releaseOcInfo (oc);
@@ -1927,7 +1937,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
if (((int64_t) v > (int64_t) INT32_MAX) || ((int64_t) v < (int64_t) INT32_MIN)) {
copyName (getSymShortName (info, sym), oc,
symbol, sizeof(symbol)-1);
- S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol);
+ S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol, sym_type);
/* And retry */
v = S + A;
@@ -1951,7 +1961,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
/* Make the trampoline then */
copyName (getSymShortName (info, sym),
oc, symbol, sizeof(symbol)-1);
- S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol);
+ S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol, sym_type);
/* And retry */
v = S + (int32_t)A - ((intptr_t)pP) - 4;
if ((v > (int64_t) INT32_MAX) || (v < (int64_t) INT32_MIN)) {