From: Robert Pengelly Date: Mon, 15 Jun 2026 08:45:20 +0000 (+0100) Subject: Relocation fixes X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=229ed8ea7c4382a1b9788f45ddade3c0317065c4;p=sasm.git Relocation fixes --- diff --git a/intel.c b/intel.c index 5ceff06..8315ffe 100644 --- a/intel.c +++ b/intel.c @@ -5189,12 +5189,32 @@ static const struct reg_entry *build_modrm (void) { if (bits == 64) { - /* In 64 bit mode default addressing is %rip relative addressing - * instead of absolute addresing. */ - instruction.modrm.regmem = MODRM_REGMEM_TWO_BYTE_ADDRESSING; - instruction.sib.base = SIB_BASE_NO_BASE_REGISTER; - instruction.sib.index = SIB_INDEX_NO_INDEX_REGISTER; - instruction.types[operand].disp32 = 1; + /* + * In 64-bit mode, a plain symbolic memory operand such as + * [foo] + * should be encoded as RIP-relative. The old code used the + * SIB no-base form here, which is an absolute disp32 memory + * reference in long mode. That made COFF emit AMD64_ADDR32 + * relocations for normal data references, and the PE linker + * then had to create HIGHLOW base relocs in a PE32+ image. + * + * Keep absolute disp32 only for numeric constants like [1234]. + * Non-constant expressions are symbols and should become REL32. + */ + if (instruction.disp_operands != 0 && instruction.disps[operand] && instruction.disps[operand]->type != EXPR_TYPE_CONSTANT) { + + instruction.modrm.regmem = SIB_BASE_NO_BASE_REGISTER; + instruction.types[operand].disp32 = 1; + instruction.special_types[operand] |= OPERAND_PCREL; + + } else { + + instruction.modrm.regmem = MODRM_REGMEM_TWO_BYTE_ADDRESSING; + instruction.sib.base = SIB_BASE_NO_BASE_REGISTER; + instruction.sib.index = SIB_INDEX_NO_INDEX_REGISTER; + instruction.types[operand].disp32 = 1; + + } } else if ((bits == 16) ^ (instruction.prefixes[ADDR_PREFIX] != 0)) {