Relocation fixes
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 15 Jun 2026 08:45:20 +0000 (09:45 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 15 Jun 2026 08:45:20 +0000 (09:45 +0100)
intel.c

diff --git a/intel.c b/intel.c
index 5ceff067b4e04e773ca22e1347f86eb2d610bbbd..8315ffe402bb3156482099a9cc97172eeff846b3 100644 (file)
--- 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)) {