From 34f06334025521c2440ebedb0237697fbcc3c6de Mon Sep 17 00:00:00 2001 From: Moritz Angermann <moritz.angermann@gmail.com> Date: Sat, 21 Oct 2023 14:35:12 +0800 Subject: [PATCH] [PEi386] Mask SYM_TYPE_DUP_DISCARD in makeSymbolExtra 48e391952c17ff7eab10b0b1456e3f2a2af28a9b introduced `SYM_TYPE_DUP_DISCARD` to the bitfield. The linker however, failed to mask the `SYM_TYPE_DUP_DISCARD` value. Thus `== SYM_TYPE_CODE` comparisons easily failed. This lead to us relocating DATA lookups (GOT) into E8 (call) and E9 (jump) instructions. --- rts/linker/PEi386.c | 49 ++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c index 4ede63c1d35c..843f2a2c6445 100644 --- a/rts/linker/PEi386.c +++ b/rts/linker/PEi386.c @@ -1939,29 +1939,32 @@ static size_t makeSymbolExtra_PEi386( ObjectCode* oc, uint64_t index STG_UNUSED, size_t s, char* symbol STG_UNUSED, SymType type ) { SymbolExtra *extra; - - if (type == SYM_TYPE_CODE) { - // jmp *-14(%rip) - extra = m32_alloc(oc->rx_m32, sizeof(SymbolExtra), 8); - CHECK(extra); - extra->addr = (uint64_t)s; - static uint8_t jmp[] = { 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF }; - memcpy(extra->jumpIsland, jmp, 6); - IF_DEBUG(linker_verbose, debugBelch("makeSymbolExtra(code): %s -> %p\n", symbol, &extra->jumpIsland)); - return (size_t)&extra->jumpIsland; - } else if (type == SYM_TYPE_INDIRECT_DATA) { - extra = m32_alloc(oc->rw_m32, sizeof(SymbolExtra), 8); - CHECK(extra); - void *v = *(void**) s; - extra->addr = (uint64_t)v; - IF_DEBUG(linker_verbose, debugBelch("makeSymbolExtra(data): %s -> %p\n", symbol, &extra->addr)); - return (size_t)&extra->addr; - } else { - extra = m32_alloc(oc->rw_m32, sizeof(SymbolExtra), 8); - CHECK(extra); - extra->addr = (uint64_t)s; - IF_DEBUG(linker_verbose, debugBelch("makeSymbolExtra(indirect-data): %s -> %p\n", symbol, &extra->addr)); - return (size_t)&extra->addr; + switch(type & ~SYM_TYPE_DUP_DISCARD) { + case SYM_TYPE_CODE: { + // jmp *-14(%rip) + extra = m32_alloc(oc->rx_m32, sizeof(SymbolExtra), 8); + CHECK(extra); + extra->addr = (uint64_t)s; + static uint8_t jmp[] = { 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF }; + memcpy(extra->jumpIsland, jmp, 6); + IF_DEBUG(linker_verbose, debugBelch("makeSymbolExtra(code): %s -> %p\n", symbol, &extra->jumpIsland)); + return (size_t)&extra->jumpIsland; + } + case SYM_TYPE_INDIRECT_DATA: { + extra = m32_alloc(oc->rw_m32, sizeof(SymbolExtra), 8); + CHECK(extra); + void *v = *(void**) s; + extra->addr = (uint64_t)v; + IF_DEBUG(linker_verbose, debugBelch("makeSymbolExtra(data): %s -> %p\n", symbol, &extra->addr)); + return (size_t)&extra->addr; + } + default: { + extra = m32_alloc(oc->rw_m32, sizeof(SymbolExtra), 8); + CHECK(extra); + extra->addr = (uint64_t)s; + IF_DEBUG(linker_verbose, debugBelch("makeSymbolExtra(indirect-data): %s -> %p\n", symbol, &extra->addr)); + return (size_t)&extra->addr; + } } } -- GitLab