From 65e4798d49afe18c20acd5f5830e706b175ba844 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 10 Apr 2026 08:43:22 +0200 Subject: [PATCH] x86/AT&T: make GOT-relative expressions work The expressions used in intel-got{32,64}.s should equally work (or not) in AT&T mode. Changing the Intel syntax parser such that O_symbol wouldn't happen to be wrapped around such expressions breaks it there, too. It really isn't correct to limit this to just O_symbol. Permitting O_add and O_subtract as well requires taking care of the other operand as well then. (Strictly speaking non-zero offsets aren't very useful here, but then at least with an equate of 0 this ought to work. The non-zero offset in the testcase helps demonstrate that this offset isn't lost.) --- gas/config/tc-i386.c | 15 ++++++++++++++- gas/testsuite/gas/i386/x86-64-gotpcrel-2.d | 2 ++ gas/testsuite/gas/i386/x86-64-gotpcrel-2.s | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 2a2d95bdd26..bc759b2573a 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -15083,13 +15083,26 @@ i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp, || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL || i.reloc[this_operand] == BFD_RELOC_64_GOTOFF) { - if (exp->X_op != O_symbol) + if (exp->X_op != O_symbol + && exp->X_op != O_add + && exp->X_op != O_subtract) goto inv_disp; if (S_IS_LOCAL (exp->X_add_symbol) && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section && S_GET_SEGMENT (exp->X_add_symbol) != expr_section) section_symbol (S_GET_SEGMENT (exp->X_add_symbol)); + + if (exp->X_op != O_symbol) + { + if (S_IS_LOCAL (exp->X_op_symbol) + && S_GET_SEGMENT (exp->X_op_symbol) != undefined_section + && S_GET_SEGMENT (exp->X_op_symbol) != expr_section) + section_symbol (S_GET_SEGMENT (exp->X_op_symbol)); + + exp->X_add_symbol = make_expr_symbol (exp); + } + exp->X_op = O_subtract; exp->X_op_symbol = GOT_symbol; if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel-2.d b/gas/testsuite/gas/i386/x86-64-gotpcrel-2.d index 3d07631bd6a..3e9d46eaca7 100644 --- a/gas/testsuite/gas/i386/x86-64-gotpcrel-2.d +++ b/gas/testsuite/gas/i386/x86-64-gotpcrel-2.d @@ -8,4 +8,6 @@ Disassembly of section .text: 0+ : +[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 7 3: R_X86_64_GOTPCREL foo-0x4 + +[a-f0-9]+: ff 35 00 00 00 00 push 0x0\(%rip\) # .* 9: R_X86_64_GOTPCREL foo\+0x4 + +[a-f0-9]+: ff 35 00 00 00 00 push 0x0\(%rip\) # .* f: R_X86_64_GOTPCREL foo-0xc #pass diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel-2.s b/gas/testsuite/gas/i386/x86-64-gotpcrel-2.s index db5ddf579a0..2706272b5eb 100644 --- a/gas/testsuite/gas/i386/x86-64-gotpcrel-2.s +++ b/gas/testsuite/gas/i386/x86-64-gotpcrel-2.s @@ -1,3 +1,7 @@ .text foo: movq foo@GOTPCREL(%rip), %rax + push foo@GOTPCREL + eight(%rip) + push foo@GOTPCREL - eight(%rip) + + .equ eight, 8 -- 2.47.3