[PATCH] x86-64: Generate R_X86_64_PLT32 for ".long foo@PLT - .L4"
"H.J. Lu" <[email protected]> Sat, 25 Jul 2026 10:35:20 +0800
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <CAMe9rOpFTW9DN_0ZjSEaL6rN0QM+RsKg7PAmwrys1gRgEoLzpA@mail.gmail.com> |
Add BFD_RELOC_X86_64_PLT32 and use it to generate R_X86_64_PLT32 for directives like ".long foo@PLT - .L4" so that PLT entries are used to resolve the PC32 relocation against function symbols for such directives. bfd/ PR gas/34423 * elf64-x86-64.c (x86_64_reloc_map): Add BFD_RELOC_X86_64_PLT32. * reloc.c (bfd_reloc_code_real): Add BFD_RELOC_X86_64_PLT32. * bfd-in2.h: Regenerated. * libbfd.h: Likewise. gas/ PR gas/34423 * config/tc-i386.c (x86_cons): Return BFD_RELOC_X86_64_PLT32 for directives like ".long foo@PLT - .L4". (tc_gen_reloc): Generate R_X86_64_PLT32 for BFD_RELOC_X86_64_PLT32 with addend computed like R_X86_64_PC32. * testsuite/gas/i386/reloc64.l: Updated. * testsuite/gas/i386/reloc64.s: Replace ".long xtrn@plt - ." with ".long xtrn@plt - _start". * testsuite/gas/i386/ilp32/reloc64.l: Updated. * testsuite/gas/i386/ilp32/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. * testsuite/gas/i386/ilp32/x86-64-jump-table.d: New file. 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. -- H.J.
0001-x86-64-Generate-R_X86_64_PLT32-for-.long-foo-PLT-.L4.patch
(text/x-patch, 13.2 KB)
From bf54e3d61bbfab91a860f43c93698d1c87f246f4 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <[email protected]> Date: Fri, 24 Jul 2026 07:01:35 +0800 Subject: [PATCH] x86-64: Generate R_X86_64_PLT32 for ".long foo@PLT - .L4" Add BFD_RELOC_X86_64_PLT32 and use it to generate R_X86_64_PLT32 for directives like ".long foo@PLT - .L4" so that PLT entries are used to resolve the PC32 relocation against function symbols for such directives. bfd/ PR gas/34423 * elf64-x86-64.c (x86_64_reloc_map): Add BFD_RELOC_X86_64_PLT32. * reloc.c (bfd_reloc_code_real): Add BFD_RELOC_X86_64_PLT32. * bfd-in2.h: Regenerated. * libbfd.h: Likewise. gas/ PR gas/34423 * config/tc-i386.c (x86_cons): Return BFD_RELOC_X86_64_PLT32 for directives like ".long foo@PLT - .L4". (tc_gen_reloc): Generate R_X86_64_PLT32 for BFD_RELOC_X86_64_PLT32 with addend computed like R_X86_64_PC32. * testsuite/gas/i386/reloc64.l: Updated. * testsuite/gas/i386/reloc64.s: Replace ".long xtrn@plt - ." with ".long xtrn@plt - _start". * testsuite/gas/i386/ilp32/reloc64.l: Updated. * testsuite/gas/i386/ilp32/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. * testsuite/gas/i386/ilp32/x86-64-jump-table.d: New file. 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 <[email protected]> --- bfd/bfd-in2.h | 1 + bfd/elf64-x86-64.c | 1 + bfd/libbfd.h | 1 + bfd/reloc.c | 2 + gas/config/tc-i386.c | 17 ++++++- gas/testsuite/gas/i386/ilp32/reloc64.l | 1 + gas/testsuite/gas/i386/ilp32/reloc64.s | 2 +- .../gas/i386/ilp32/x86-64-jump-table.d | 4 ++ gas/testsuite/gas/i386/reloc64.l | 1 + 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 +++++++ 16 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 gas/testsuite/gas/i386/ilp32/x86-64-jump-table.d create mode 100644 gas/testsuite/gas/i386/x86-64-jump-table.d create mode 100644 gas/testsuite/gas/i386/x86-64-jump-table.s create mode 100644 ld/testsuite/ld-x86-64/pr34423.c create mode 100644 ld/testsuite/ld-x86-64/x86-64-jump-table.s diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index e49d67316f3..033ca41cc74 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3919,6 +3919,7 @@ enum bfd_reloc_code_real /* x86-64/elf relocations. */ BFD_RELOC_X86_64_GOT32, BFD_RELOC_X86_64_GOTPCREL, + BFD_RELOC_X86_64_PLT32, BFD_RELOC_X86_64_32S, BFD_RELOC_X86_64_DTPMOD64, BFD_RELOC_X86_64_DTPOFF64, diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 575995d4957..98988cfae35 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -270,6 +270,7 @@ static const struct elf_reloc_map x86_64_reloc_map[] = { BFD_RELOC_IRELATIVE, R_X86_64_IRELATIVE, }, { BFD_RELOC_X86_64_PC32_BND, R_X86_64_PC32_BND, }, { BFD_RELOC_X86_64_PLT32_BND, R_X86_64_PLT32_BND, }, + { BFD_RELOC_X86_64_PLT32, R_X86_64_PLT32, }, { BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, }, { BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, }, { BFD_RELOC_X86_64_CODE_4_GOTPCRELX, R_X86_64_CODE_4_GOTPCRELX, }, diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 27bc0875cf6..dcfc0b98337 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1448,6 +1448,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_386_GOT32X", "BFD_RELOC_X86_64_GOT32", "BFD_RELOC_X86_64_GOTPCREL", + "BFD_RELOC_X86_64_PLT32", "BFD_RELOC_X86_64_32S", "BFD_RELOC_X86_64_DTPMOD64", "BFD_RELOC_X86_64_DTPOFF64", diff --git a/bfd/reloc.c b/bfd/reloc.c index 6b9e00da5d6..995522876b0 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2358,6 +2358,8 @@ ENUM BFD_RELOC_X86_64_GOT32 ENUMX BFD_RELOC_X86_64_GOTPCREL +ENUMX + BFD_RELOC_X86_64_PLT32 ENUMX BFD_RELOC_X86_64_32S ENUMX diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index d1ef80ce6d1..432c9f11c33 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -13549,6 +13549,12 @@ x86_cons (expressionS *exp, int size) as_bad (_("missing or invalid expression `%s'"), save); *input_line_pointer = c; } + else if (got_reloc == BFD_RELOC_32_PLT_PCREL + && size == 4 + && exp->X_op == O_subtract + && S_IS_LOCAL (exp->X_op_symbol)) + /* Allow directives like ".long foo@PLT - .L4". */ + got_reloc = BFD_RELOC_X86_64_PLT32; else if ((got_reloc == BFD_RELOC_386_PLT32 || got_reloc == BFD_RELOC_32_PLT_PCREL) && exp->X_op != O_symbol) @@ -18626,7 +18632,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) } /* Fall through. */ default: - if (fixp->fx_pcrel) + if (fixp->fx_r_type == BFD_RELOC_X86_64_PLT32) + code = BFD_RELOC_X86_64_PLT32; + else if (fixp->fx_pcrel) { switch (fixp->fx_size) { @@ -18751,6 +18759,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_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/ilp32/reloc64.l b/gas/testsuite/gas/i386/ilp32/reloc64.l index 14a111d763f..6435ae1a0be 100644 --- a/gas/testsuite/gas/i386/ilp32/reloc64.l +++ b/gas/testsuite/gas/i386/ilp32/reloc64.l @@ -113,6 +113,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/reloc64.l b/gas/testsuite/gas/i386/reloc64.l index c60c45d139a..28bdc823be4 100644 --- a/gas/testsuite/gas/i386/reloc64.l +++ b/gas/testsuite/gas/i386/reloc64.l @@ -165,3 +165,4 @@ .*: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 [email protected] + .long [email protected] + .long .Lbar2-.L4 + .long [email protected] + .long [email protected] + .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 [email protected] + .long [email protected] + .long .Lbar2-.L4 + .long [email protected] + .long [email protected] + .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. -- 2.55.0