[binutils-gdb] x86: Generate PLT32 relocation for ".long foo@PLT - .L4"
H.J. Lu
hjl@sourceware.org
Wed Jul 29 21:44:35 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=53902b30c66ad5edc95db93e8d5c1cb3c29d684d
commit 53902b30c66ad5edc95db93e8d5c1cb3c29d684d
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Fri Jul 24 07:01:35 2026 +0800
x86: Generate PLT32 relocation for ".long foo@PLT - .L4"
LLVM assembler supports directives like ".long foo@PLT - .L4" for i386
and x86-64. Implement the same feature to generate PLT32 relocation
for directives like ".long foo@PLT - .L4" so that PLT entries are used
to resolve the PC32 relocation against function symbols.
bfd/
PR gas/34423
* elf32-i386.c (elf_i386_reloc_type_lookup): Handle
BFD_RELOC_386_PC32_TO_PLT32.
* elf64-x86-64.c (x86_64_reloc_map): Add
BFD_RELOC_X86_64_PC32_TO_PLT32.
* reloc.c (bfd_reloc_code_real): Add BFD_RELOC_386_PC32_TO_PLT32
and BFD_RELOC_X86_64_PC32_TO_PLT32.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
gas/
PR gas/34423
* config/tc-i386.c (x86_cons): Return
BFD_RELOC_X86_64_PC32_TO_PLT32 or BFD_RELOC_386_PC32_TO_PLT32
for directives like ".long foo@PLT - .L4".
(md_apply_fix): Compute addend for BFD_RELOC_386_PC32_TO_PLT32.
(tc_gen_reloc): Handle BFD_RELOC_X86_64_PC32_TO_PLT32 and
BFD_RELOC_386_PC32_TO_PLT32. Compute addend like
BFD_RELOC_32_PCREL for BFD_RELOC_X86_64_PC32_TO_PLT32.
* testsuite/gas/i386/i386.exp: Run plt test.
* testsuite/gas/i386/ilp32/reloc64.l: Updated.
* testsuite/gas/i386/ilp32/reloc64.s: Replace ".long xtrn@plt - ."
with ".long xtrn@plt - _start".
* testsuite/gas/i386/ilp32/x86-64-jump-table.d: New file.
* testsuite/gas/i386/plt.d: Likewise.
* testsuite/gas/i386/plt.s: Likewise.
* testsuite/gas/i386/reloc32.l: Updated.
* testsuite/gas/i386/reloc32.s: Replace ".long xtrn@plt - ."
with ".long xtrn@plt - _start".
* testsuite/gas/i386/reloc64.l: Updated.
* testsuite/gas/i386/reloc64.s: Replace ".long xtrn@plt - ." with
".long xtrn@plt - ptr".
* testsuite/gas/i386/x86-64-jump-table.d: New file.
* testsuite/gas/i386/x86-64-jump-table.d: Likewise.
* testsuite/gas/i386/x86-64-jump-table.s: Likewise.
* testsuite/gas/i386/x86-64.exp: Run x86-64-jump-table.
ld/
PR gas/34423
* testsuite/ld-x86-64/pr34423.c: New file.
* testsuite/ld-x86-64/x86-64-jump-table.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run gas/34423 tests.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Diff:
---
bfd/bfd-in2.h | 2 ++
bfd/elf32-i386.c | 4 +++
bfd/elf64-x86-64.c | 1 +
bfd/libbfd.h | 2 ++
bfd/reloc.c | 4 +++
gas/config/tc-i386.c | 33 ++++++++++++++---
gas/testsuite/gas/i386/i386.exp | 2 ++
gas/testsuite/gas/i386/ilp32/reloc64.l | 3 +-
gas/testsuite/gas/i386/ilp32/reloc64.s | 2 +-
gas/testsuite/gas/i386/ilp32/x86-64-jump-table.d | 4 +++
gas/testsuite/gas/i386/plt.d | 14 ++++++++
gas/testsuite/gas/i386/plt.s | 7 ++++
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.d | 29 +++++++++++++++
gas/testsuite/gas/i386/x86-64-jump-table.s | 31 ++++++++++++++++
gas/testsuite/gas/i386/x86-64.exp | 2 ++
ld/testsuite/ld-x86-64/pr34423.c | 46 ++++++++++++++++++++++++
ld/testsuite/ld-x86-64/x86-64-jump-table.s | 30 ++++++++++++++++
ld/testsuite/ld-x86-64/x86-64.exp | 16 +++++++++
22 files changed, 230 insertions(+), 13 deletions(-)
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index e49d67316f3..e55bde7b129 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3899,6 +3899,7 @@ enum bfd_reloc_code_real
/* i386/elf relocations. */
BFD_RELOC_386_GOT32,
BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_PC32_TO_PLT32,
BFD_RELOC_386_TLS_TPOFF,
BFD_RELOC_386_TLS_IE,
BFD_RELOC_386_TLS_GOTIE,
@@ -3937,6 +3938,7 @@ enum bfd_reloc_code_real
BFD_RELOC_X86_64_TLSDESC,
BFD_RELOC_X86_64_PC32_BND,
BFD_RELOC_X86_64_PLT32_BND,
+ BFD_RELOC_X86_64_PC32_TO_PLT32,
BFD_RELOC_X86_64_GOTPCRELX,
BFD_RELOC_X86_64_REX_GOTPCRELX,
BFD_RELOC_X86_64_CODE_4_GOTPCRELX,
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 954803fcc3f..ae9276cff06 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -331,6 +331,10 @@ elf_i386_reloc_type_lookup (bfd *abfd,
TRACE ("BFD_RELOC_386_GOT32X");
return &elf_howto_table[R_386_GOT32X - R_386_tls_offset];
+ case BFD_RELOC_386_PC32_TO_PLT32:
+ TRACE ("BFD_RELOC_X86_PC32_TO_PLT32");
+ return &elf_howto_table[R_386_PLT32];
+
case BFD_RELOC_VTABLE_INHERIT:
TRACE ("BFD_RELOC_VTABLE_INHERIT");
return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 575995d4957..ade6613b62a 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -281,6 +281,7 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
{ BFD_RELOC_X86_64_CODE_6_GOTPCRELX, R_X86_64_CODE_6_GOTPCRELX, },
{ BFD_RELOC_X86_64_CODE_6_GOTTPOFF, R_X86_64_CODE_6_GOTTPOFF, },
{ BFD_RELOC_X86_64_CODE_6_GOTPC32_TLSDESC, R_X86_64_CODE_6_GOTPC32_TLSDESC, },
+ { BFD_RELOC_X86_64_PC32_TO_PLT32, R_X86_64_PLT32, },
{ BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, },
{ BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, },
};
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 27bc0875cf6..6e737e468df 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1430,6 +1430,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_MN10300_TLS_TPOFF",
"BFD_RELOC_386_GOT32",
"BFD_RELOC_386_PLT32",
+ "BFD_RELOC_386_PC32_TO_PLT32",
"BFD_RELOC_386_TLS_TPOFF",
"BFD_RELOC_386_TLS_IE",
"BFD_RELOC_386_TLS_GOTIE",
@@ -1466,6 +1467,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_X86_64_TLSDESC",
"BFD_RELOC_X86_64_PC32_BND",
"BFD_RELOC_X86_64_PLT32_BND",
+ "BFD_RELOC_X86_64_PC32_TO_PLT32",
"BFD_RELOC_X86_64_GOTPCRELX",
"BFD_RELOC_X86_64_REX_GOTPCRELX",
"BFD_RELOC_X86_64_CODE_4_GOTPCRELX",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 6b9e00da5d6..29288f8099d 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2319,6 +2319,8 @@ ENUM
BFD_RELOC_386_GOT32
ENUMX
BFD_RELOC_386_PLT32
+ENUMX
+ BFD_RELOC_386_PC32_TO_PLT32
ENUMX
BFD_RELOC_386_TLS_TPOFF
ENUMX
@@ -2394,6 +2396,8 @@ ENUMX
BFD_RELOC_X86_64_PC32_BND
ENUMX
BFD_RELOC_X86_64_PLT32_BND
+ENUMX
+ BFD_RELOC_X86_64_PC32_TO_PLT32
ENUMX
BFD_RELOC_X86_64_GOTPCRELX
ENUMX
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index d1ef80ce6d1..67badd29298 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -13553,10 +13553,20 @@ x86_cons (expressionS *exp, int size)
|| got_reloc == BFD_RELOC_32_PLT_PCREL)
&& exp->X_op != O_symbol)
{
- char c = *input_line_pointer;
- *input_line_pointer = 0;
- as_bad (_("invalid PLT expression `%s'"), save);
- *input_line_pointer = c;
+ /* Allow directives like ".long 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)
+ got_reloc = (object_64bit
+ ? BFD_RELOC_X86_64_PC32_TO_PLT32
+ : BFD_RELOC_386_PC32_TO_PLT32);
+ else
+ {
+ char c = *input_line_pointer;
+ *input_line_pointer = 0;
+ as_bad (_("invalid PLT expression `%s'"), save);
+ *input_line_pointer = c;
+ }
}
}
}
@@ -16781,6 +16791,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
value = -4;
break;
+ case BFD_RELOC_386_PC32_TO_PLT32:
+ /* Set the implicit addend. */
+ value = (seg->vma - fixP->fx_size + fixP->fx_addnumber
+ + md_pcrel_from (fixP));
+ break;
+
case BFD_RELOC_386_TLS_GD:
case BFD_RELOC_386_TLS_LDM:
case BFD_RELOC_386_TLS_IE_32:
@@ -18586,6 +18602,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_386_TLS_LE:
case BFD_RELOC_386_TLS_GOTDESC:
case BFD_RELOC_386_TLS_DESC_CALL:
+ case BFD_RELOC_386_PC32_TO_PLT32:
case BFD_RELOC_X86_64_TLSGD:
case BFD_RELOC_X86_64_TLSLD:
case BFD_RELOC_X86_64_DTPOFF32:
@@ -18608,6 +18625,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_CODE_5_GOTPC32_TLSDESC:
case BFD_RELOC_X86_64_CODE_6_GOTPC32_TLSDESC:
case BFD_RELOC_X86_64_TLSDESC_CALL:
+ case BFD_RELOC_X86_64_PC32_TO_PLT32:
case BFD_RELOC_RVA:
case BFD_RELOC_VTABLE_ENTRY:
case BFD_RELOC_VTABLE_INHERIT:
@@ -18751,6 +18769,13 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_TLSDESC_CALL:
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".
+ Generate R_X86_64_PLT32 with addend computed like
+ R_X86_64_PC32 so that PLT entry is used to resolve
+ this PC32 relocation. */
+ code = BFD_RELOC_32_PLT_PCREL;
+ /* Fall through. */
default:
rel->addend = (section->vma
- fixp->fx_size
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index e27bca0f69c..22fd3412d53 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -792,6 +792,8 @@ if [gas_32_check] then {
run_dump_test "no-got"
+ run_dump_test "plt"
+
run_dump_test "gotx-default"
run_dump_test "no-gotx-default"
diff --git a/gas/testsuite/gas/i386/ilp32/reloc64.l b/gas/testsuite/gas/i386/ilp32/reloc64.l
index 14a111d763f..08c2702cdb7 100644
--- a/gas/testsuite/gas/i386/ilp32/reloc64.l
+++ b/gas/testsuite/gas/i386/ilp32/reloc64.l
@@ -103,8 +103,6 @@
.*: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 .*
@@ -113,6 +111,7 @@
.*: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 db2d2acdf5d..a4ccdb29916 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 - .
+bad .long xtrn@plt - _start
.text
bad add $x+0x123456789, %rax
diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-jump-table.d b/gas/testsuite/gas/i386/ilp32/x86-64-jump-table.d
new file mode 100644
index 00000000000..2cff87d4445
--- /dev/null
+++ b/gas/testsuite/gas/i386/ilp32/x86-64-jump-table.d
@@ -0,0 +1,4 @@
+#source: ../x86-64-jump-table.s
+#readelf: -rsW
+#name: x86-64 (ILP32) PIC jump table
+#dump: ../x86-64-jump-table.d
diff --git a/gas/testsuite/gas/i386/plt.d b/gas/testsuite/gas/i386/plt.d
new file mode 100644
index 00000000000..e4af0d20c87
--- /dev/null
+++ b/gas/testsuite/gas/i386/plt.d
@@ -0,0 +1,14 @@
+#as:
+#readelf: -x .rodata -r
+
+Relocation section '.rel.rodata' at offset 0xd4 contains 4 entries:
+ Offset Info Type Sym.Value Sym. Name
+0+ 00000104 R_386_PLT32 00000000 foo1
+0+4 00000204 R_386_PLT32 00000000 foo2
+0+8 00000304 R_386_PLT32 00000000 foo3
+0+c 00000404 R_386_PLT32 00000000 foo4
+
+Hex dump of section '.rodata':
+ NOTE: This section has relocations against it, but these have NOT been applied to this dump.
+ 0x00000000 00000000 04000000 08000000 0c000000 ................
+#pass
diff --git a/gas/testsuite/gas/i386/plt.s b/gas/testsuite/gas/i386/plt.s
new file mode 100644
index 00000000000..c854c3fe739
--- /dev/null
+++ b/gas/testsuite/gas/i386/plt.s
@@ -0,0 +1,7 @@
+
+ .section .rodata
+.L4:
+ .long foo1@PLT - .L4
+ .long foo2@PLT - .L4
+ .long foo3@PLT - .L4
+ .long foo4@PLT - .L4
diff --git a/gas/testsuite/gas/i386/reloc32.l b/gas/testsuite/gas/i386/reloc32.l
index 71c65212dc9..31c71a0be28 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: .*
-.*:3: Error: .*
-.*:164: Info: .*
+.*:56: Error: .*
+.*:164: Error: .*
#pass
diff --git a/gas/testsuite/gas/i386/reloc32.s b/gas/testsuite/gas/i386/reloc32.s
index 5616cd57e3f..0ba69eae4d0 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 - .
+bad .long xtrn@plt - _start
.text
movl $ptr@PLT, %eax
diff --git a/gas/testsuite/gas/i386/reloc64.l b/gas/testsuite/gas/i386/reloc64.l
index c60c45d139a..d84d9042958 100644
--- a/gas/testsuite/gas/i386/reloc64.l
+++ b/gas/testsuite/gas/i386/reloc64.l
@@ -163,5 +163,4 @@
.*:219: Info: .*
.*:3: Error: .*
.*:220: Info: .*
-.*:3: Error: .*
-.*:227: Info: .*
+.*:227: Error: can't resolve xtrn - ptr
diff --git a/gas/testsuite/gas/i386/reloc64.s b/gas/testsuite/gas/i386/reloc64.s
index 5c0f4136a09..f248964813f 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 - .
+bad .long xtrn@plt - ptr
.text
movabs $ptr@GOT, %rax
diff --git a/gas/testsuite/gas/i386/x86-64-jump-table.d b/gas/testsuite/gas/i386/x86-64-jump-table.d
new file mode 100644
index 00000000000..32c957b6ba6
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-jump-table.d
@@ -0,0 +1,29 @@
+#as:
+#readelf: -rsW
+#name: x86-64 PIC jump table
+#notarget: *-*-solaris*
+
+#...
+Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+0+8 0+40+2 +R_X86_64_PC32 +0+ +bar0 - 4
+0+f 0+20+2 +R_X86_64_PC32 +0+ +.rodata - 4
+0+20 0+50+4 +R_X86_64_PLT32 +0+ +bar2 - 4
+#...
+Relocation section '.rela.rodata' at offset 0x[0-9a-f]+ contains 5 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+0+ 0+40+4 +R_X86_64_PLT32 +0+ +bar0 \+ 0
+0+4 0+60+4 +R_X86_64_PLT32 +0+ +bar1 \+ 4
+0+8 0+10+2 +R_X86_64_PC32 +0+ +.text \+ 27
+0+c 0+70+4 +R_X86_64_PLT32 +0+ +bar3 \+ c
+0+10+ 0+80+4 +R_X86_64_PLT32 +0+ +bar4 \+ 10
+#...
+ +[0-9]+: 0+ +0 SECTION LOCAL +DEFAULT +1 .text
+ +[0-9]+: 0+ +0 SECTION LOCAL +DEFAULT +5 .rodata
+ +[0-9]+: 0+ +36 FUNC +GLOBAL +DEFAULT +1 foo
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND bar0
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND bar2
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND bar1
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND bar3
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND bar4
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-jump-table.s b/gas/testsuite/gas/i386/x86-64-jump-table.s
new file mode 100644
index 00000000000..aefffad8f65
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-jump-table.s
@@ -0,0 +1,31 @@
+# Check R_X86_64_PLT32 relocation in jump table.
+
+ .text
+ .p2align 4
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ cmpl $4, %edi
+ ja .L1
+ leaq bar0(%rip), %rdx
+ leaq .L4(%rip), %rdx
+ movl %edi, %edi
+ movslq (%rdx,%rdi,4), %rax
+ addq %rdx, %rax
+ jmp *%rax
+.L1:
+ ret
+.Lbar2:
+ jmp bar2
+ .cfi_endproc
+ .size foo, .-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
+ .section .note.GNU-stack,"",@progbits
diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp
index 58382b55e31..710f749a8dc 100644
--- a/gas/testsuite/gas/i386/x86-64.exp
+++ b/gas/testsuite/gas/i386/x86-64.exp
@@ -778,6 +778,8 @@ if [is_elf_format] then {
run_dump_test "reloc-section-sym-all"
run_dump_test "reloc-section-sym-internal"
run_dump_test "reloc-section-sym-none"
+
+ run_dump_test "x86-64-jump-table"
}
run_dump_test pr27198
run_dump_test pr29483
diff --git a/ld/testsuite/ld-x86-64/pr34423.c b/ld/testsuite/ld-x86-64/pr34423.c
new file mode 100644
index 00000000000..fc5a943a54a
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr34423.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+
+int
+bar0 (void)
+{
+ return 0;
+}
+
+int
+bar1 (void)
+{
+ return 1;
+}
+
+int
+bar2 (void)
+{
+ return 2;
+}
+
+int
+bar3 (void)
+{
+ return 3;
+}
+
+int
+bar4 (void)
+{
+ return 4;
+}
+
+extern int foo (int);
+
+int
+main ()
+{
+ if (foo (1) == 1
+ && foo (3) == 3
+ && foo (4) == 4
+ && foo (2) == 2
+ && foo (0) == 0)
+ printf ("PASS\n");
+
+ return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/x86-64-jump-table.s b/ld/testsuite/ld-x86-64/x86-64-jump-table.s
new file mode 100644
index 00000000000..bd06f714469
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/x86-64-jump-table.s
@@ -0,0 +1,30 @@
+# Check R_X86_64_PLT32 relocation in jump table.
+
+ .text
+ .p2align 4
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ cmpl $4, %edi
+ ja .L1
+ leaq .L4(%rip), %rdx
+ movl %edi, %edi
+ movslq (%rdx,%rdi,4), %rax
+ addq %rdx, %rax
+ jmp *%rax
+.L1:
+ ret
+.Lbar2:
+ jmp bar2@PLT
+ .cfi_endproc
+ .size foo, .-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
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 07607810d15..985d96dcfba 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -1523,6 +1523,14 @@ if { [isnative] && [check_compiler_available] } {
{} \
"pr32067" \
] \
+ [list \
+ "Build libjump-table.so" \
+ "-shared" \
+ "" \
+ { x86-64-jump-table.s } \
+ {} \
+ "libjump-table.so" \
+ ] \
]
if {[istarget "x86_64-*-linux*-gnux32"]} {
@@ -2046,6 +2054,14 @@ if { [isnative] && [check_compiler_available] } {
"plt3" \
"pass.out" \
] \
+ [list \
+ "Run pr34423" \
+ "-Wl,--no-as-needed tmpdir/libjump-table.so" \
+ "" \
+ { pr34423.c } \
+ "pr34423" \
+ "pass.out" \
+ ] \
]
# Run-time tests which require working ifunc attribute support.
More information about the Binutils-cvs
mailing list