[binutils-gdb] x86/AT&T: make GOT-relative expressions work

Jan Beulich via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=65e4798d49afe18c20acd5f5830e706b175ba844

commit 65e4798d49afe18c20acd5f5830e706b175ba844
Author: Jan Beulich <[email protected]>
Date:   Fri Apr 10 08:43:22 2026 +0200

    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.)

Diff:
---
 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+ <foo>:
  +[a-f0-9]+:	48 8b 05 00 00 00 00 	mov    0x0\(%rip\),%rax        # 7 <foo\+0x7>	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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.