From ee1a066d1b41d82c2e6a67fc749fef7c2e8868bf Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Fri, 31 Jul 2026 07:00:52 +0800
Subject: [PATCH] x86: Disallow ".long foo@PLT - .L4" for PLT32 relocation

Disallow ".long foo@PLT - .L4" and only allow ".slong foo@PLT - .L4" for
PLT32 relocation.

gas/

	PR gas/34423
	* config/tc-i386.c (cons_slong): New.
	(x86_cons): Return BFD_RELOC_X86_64_PC32_TO_PLT32 or
	BFD_RELOC_386_PC32_TO_PLT32 only if cons_slong is true.
	(signed_cons): Set cons_slong to true before calling cons and
	set it to false afterwards.
	(tc_gen_reloc): Update BFD_RELOC_X86_64_PC32_TO_PLT32 comments.
	* testsuite/gas/i386/ilp32/reloc64.l: Revert commit 53902b30c66.
	* testsuite/gas/i386/ilp32/reloc64.s: Likewise.
	* testsuite/gas/i386/reloc32.l: Likewise.
	* testsuite/gas/i386/reloc32.s: Likewise.
	* testsuite/gas/i386/reloc64.l: Likewise.
	* testsuite/gas/i386/plt.s: Replace .long with .slong.
	* testsuite/gas/i386/x86-64-jump-table.s: Likewise.

ld/

	PR gas/34423
	* testsuite/ld-x86-64/x86-64-jump-table.s: Replace .long with
	.slong.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 gas/config/tc-i386.c                       | 12 +++++++++---
 gas/testsuite/gas/i386/ilp32/reloc64.l     |  3 ++-
 gas/testsuite/gas/i386/ilp32/reloc64.s     |  2 +-
 gas/testsuite/gas/i386/plt.s               |  8 ++++----
 gas/testsuite/gas/i386/reloc32.l           |  4 ++--
 gas/testsuite/gas/i386/reloc32.s           |  2 +-
 gas/testsuite/gas/i386/reloc64.l           |  3 ++-
 gas/testsuite/gas/i386/reloc64.s           |  2 +-
 gas/testsuite/gas/i386/x86-64-jump-table.s | 10 +++++-----
 ld/testsuite/ld-x86-64/x86-64-jump-table.s | 10 +++++-----
 10 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 67badd29298..b61e1eb49e6 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -13374,6 +13374,10 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off)
    reloc is needed.  We use this hook to get the correct .got reloc.  */
 static int cons_sign = -1;
 
+/* This hook is used by x86_cons to allow ".slong foo@PLT - .L4", but
+   not ".long foo@PLT - .L4".  */
+static bool cons_slong = false;
+
 void
 x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len,
 		  expressionS *exp, bfd_reloc_code_real_type r)
@@ -13553,10 +13557,10 @@ x86_cons (expressionS *exp, int size)
 		    || got_reloc == BFD_RELOC_32_PLT_PCREL)
 		   && exp->X_op != O_symbol)
 	    {
-	    /* Allow directives like ".long foo@PLT - .L4".
+	    /* Allow directives like ".slong foo@PLT - .L4".
 	       BFD_RELOC_X86_64_PC32_TO_PLT32 has an explicit addend and
 	       BFD_RELOC_386_PC32_TO_PLT32 has an implicit addend.  */
-	      if (size == 4 && exp->X_op == O_subtract)
+	      if (cons_slong && size == 4 && exp->X_op == O_subtract)
 		got_reloc = (object_64bit
 			     ? BFD_RELOC_X86_64_PC32_TO_PLT32
 			     : BFD_RELOC_386_PC32_TO_PLT32);
@@ -13592,7 +13596,9 @@ signed_cons (int size)
 {
   if (object_64bit)
     cons_sign = 1;
+  cons_slong = true;
   cons (size);
+  cons_slong = false;
   cons_sign = -1;
 }
 
@@ -18770,7 +18776,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 	    rel->addend = fixp->fx_offset - fixp->fx_size;
 	    break;
 	  case BFD_RELOC_X86_64_PC32_TO_PLT32:
-	    /* This came from a directive like ".long foo@PLT - .L4".
+	    /* This came from a directive like ".slong foo@PLT - .L4".
 	       Generate R_X86_64_PLT32 with addend computed like
 	       R_X86_64_PC32 so that PLT entry is used to resolve
 	       this PC32 relocation.   */
diff --git a/gas/testsuite/gas/i386/ilp32/reloc64.l b/gas/testsuite/gas/i386/ilp32/reloc64.l
index 08c2702cdb7..14a111d763f 100644
--- a/gas/testsuite/gas/i386/ilp32/reloc64.l
+++ b/gas/testsuite/gas/i386/ilp32/reloc64.l
@@ -103,6 +103,8 @@
 .*:176:  Info: .*
 .*:3: Error: .*
 .*:177:  Info: .*
+.*:3: Error: .*
+.*:190:  Info: .*
 .*:193: Error: .* too large for field of 4 bytes at .*
 .*:194: Error: .* too large for field of 4 bytes at .*
 .*:195: Error: .* too large for field of 4 bytes at .*
@@ -111,7 +113,6 @@
 .*:197: Error: .* too large for field of 1 byte at .*
 .*:198: Error: .* too large for field of 2 bytes at .*
 .*:198: Error: .* too large for field of 1 byte at .*
-.*:190: Error: can't resolve xtrn - _start
 .*:201: Error: .* too large for field of 4 bytes at .*
 .*:202: Error: .* too large for field of 2 bytes at .*
 .*:203: Error: .* too large for field of 2 bytes at .*
diff --git a/gas/testsuite/gas/i386/ilp32/reloc64.s b/gas/testsuite/gas/i386/ilp32/reloc64.s
index a4ccdb29916..db2d2acdf5d 100644
--- a/gas/testsuite/gas/i386/ilp32/reloc64.s
+++ b/gas/testsuite/gas/i386/ilp32/reloc64.s
@@ -187,7 +187,7 @@ bad	.byte	xtrn@tpoff
 	.quad	xtrn - 0x80000000
 	.long	xtrn@got - 4
 	.long	xtrn@got + 4
-bad	.long	xtrn@plt - _start
+bad	.long	xtrn@plt - .
 
 	.text
 bad	add	$x+0x123456789, %rax
diff --git a/gas/testsuite/gas/i386/plt.s b/gas/testsuite/gas/i386/plt.s
index c854c3fe739..5274b6c5a5f 100644
--- a/gas/testsuite/gas/i386/plt.s
+++ b/gas/testsuite/gas/i386/plt.s
@@ -1,7 +1,7 @@
 
 	.section .rodata
 .L4:
-        .long	foo1@PLT - .L4
-        .long	foo2@PLT - .L4
-        .long	foo3@PLT - .L4
-        .long	foo4@PLT - .L4
+        .slong	foo1@PLT - .L4
+        .slong	foo2@PLT - .L4
+        .slong	foo3@PLT - .L4
+        .slong	foo4@PLT - .L4
diff --git a/gas/testsuite/gas/i386/reloc32.l b/gas/testsuite/gas/i386/reloc32.l
index 31c71a0be28..71c65212dc9 100644
--- a/gas/testsuite/gas/i386/reloc32.l
+++ b/gas/testsuite/gas/i386/reloc32.l
@@ -131,6 +131,6 @@
 .*:160:  Info: .*
 .*:3: Error: .*
 .*:161:  Info: .*
-.*:56: Error: .*
-.*:164: Error: .*
+.*:3: Error: .*
+.*:164:  Info: .*
 #pass
diff --git a/gas/testsuite/gas/i386/reloc32.s b/gas/testsuite/gas/i386/reloc32.s
index 0ba69eae4d0..5616cd57e3f 100644
--- a/gas/testsuite/gas/i386/reloc32.s
+++ b/gas/testsuite/gas/i386/reloc32.s
@@ -161,7 +161,7 @@ bad	.byte	xtrn@ntpoff
 bad	.byte	xtrn@tpoff
 	.long	xtrn@got + 4
 	.long	xtrn@got - 4
-bad	.long	xtrn@plt - _start
+bad	.long	xtrn@plt - .
 
 	.text
 	movl	$ptr@PLT, %eax
diff --git a/gas/testsuite/gas/i386/reloc64.l b/gas/testsuite/gas/i386/reloc64.l
index d84d9042958..c60c45d139a 100644
--- a/gas/testsuite/gas/i386/reloc64.l
+++ b/gas/testsuite/gas/i386/reloc64.l
@@ -163,4 +163,5 @@
 .*:219:  Info: .*
 .*:3: Error: .*
 .*:220:  Info: .*
-.*:227: Error: can't resolve xtrn - ptr
+.*:3: Error: .*
+.*:227:  Info: .*
diff --git a/gas/testsuite/gas/i386/reloc64.s b/gas/testsuite/gas/i386/reloc64.s
index f248964813f..5c0f4136a09 100644
--- a/gas/testsuite/gas/i386/reloc64.s
+++ b/gas/testsuite/gas/i386/reloc64.s
@@ -224,7 +224,7 @@ bad	.byte	xtrn@gotplt
 	mov	xtrn(,%ebx), %eax
 	vgatherdps %xmm2, xtrn(,%xmm1), %xmm0
 	addr32 vgatherdps %xmm2, xtrn(,%xmm1), %xmm0
-bad	.long	xtrn@plt - ptr
+bad	.long	xtrn@plt - .
 
 	.text
 	movabs	$ptr@GOT, %rax
diff --git a/gas/testsuite/gas/i386/x86-64-jump-table.s b/gas/testsuite/gas/i386/x86-64-jump-table.s
index aefffad8f65..f9957630b38 100644
--- a/gas/testsuite/gas/i386/x86-64-jump-table.s
+++ b/gas/testsuite/gas/i386/x86-64-jump-table.s
@@ -23,9 +23,9 @@ foo:
         .section	.rodata
         .p2align 2
 .L4:
-        .long	bar0@plt-.L4
-        .long	bar1@PLT-.L4
-        .long	.Lbar2-.L4
-        .long	bar3@PLT-.L4
-        .long	bar4@plt-.L4
+        .slong	bar0@plt-.L4
+        .slong	bar1@PLT-.L4
+        .slong	.Lbar2-.L4
+        .slong	bar3@PLT-.L4
+        .slong	bar4@plt-.L4
         .section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/x86-64-jump-table.s b/ld/testsuite/ld-x86-64/x86-64-jump-table.s
index bd06f714469..84049d879bf 100644
--- a/ld/testsuite/ld-x86-64/x86-64-jump-table.s
+++ b/ld/testsuite/ld-x86-64/x86-64-jump-table.s
@@ -22,9 +22,9 @@ foo:
         .section	.rodata
         .p2align 2
 .L4:
-        .long	bar0@plt-.L4
-        .long	bar1@PLT-.L4
-        .long	.Lbar2-.L4
-        .long	bar3@PLT-.L4
-        .long	bar4@plt-.L4
+        .slong	bar0@plt-.L4
+        .slong	bar1@PLT-.L4
+        .slong	.Lbar2-.L4
+        .slong	bar3@PLT-.L4
+        .slong	bar4@plt-.L4
         .section	.note.GNU-stack,"",@progbits
-- 
2.55.0

