From 4b23c4da09db8e18d907a1ee22f3c6c439259819 Mon Sep 17 00:00:00 2001 From: chrg6 Date: Wed, 11 Nov 2026 17:30:30 -0500 Subject: [PATCH] Add a JUMP_SLOT relocation's addend when it binds a guest function, and log one on a host function. The loader added the addend for ABS64 and GLOB_DAT and always dropped it for JUMP_SLOT, though the AArch64 ELF ABI gives S + A for all three. A JUMP_SLOT that binds a guest function now gets its addend too; one that binds a host function (an override or an observer, where an offset into the trampoline means nothing) drops it and logs the relocation, so a module that ever carries one shows up in the log instead of jumping to the wrong place. Checked: the runtime compiles. The game's three modules hold 11,698 JUMP_SLOT relocations, none with a nonzero addend (read from the 1.1.1 ExeFS), so nothing changes for this game. Co-Authored-By: Claude Opus 5.5 --- runtime/loader.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/runtime/loader.c b/runtime/loader.c index fcc00653..c5becee6 100644 --- a/runtime/loader.c +++ b/runtime/loader.c @@ -365,7 +365,17 @@ static void relocate_table(Mod *m, const Elf64Rela *r, uint64_t n) { if (sym_defined(m, si)) m->sym_own++; else m->sym_import++; Res s = resolve(m, si, type == R_JUMP_SLOT); - v = s.kind == RES_WEAK ? 0 : s.value + (type == R_JUMP_SLOT ? 0 : (uint64_t)r[i].addend); + // S + A for every symbolic type (the AArch64 ELF ABI), JUMP_SLOT included where the symbol is a guest + // function; linkers write 0 there. A host function's address takes no addend (an offset into a host + // trampoline means nothing), so such an addend is logged and dropped, as is one on an unresolved weak symbol + // (address 0, the guest's own test for an absent function). + int64_t a = r[i].addend; + if (type == R_JUMP_SLOT && a && s.kind != RES_GUEST) { + rt_log("loader: %s JUMP_SLOT relocation %llu for %s carries addend %lld on a host function: left out", + m->pub.name, (unsigned long long)i, sym_name(m, si), (long long)a); + a = 0; + } + v = s.kind == RES_WEAK ? 0 : s.value + (uint64_t)a; } ST64(base + r[i].off, v); }