[v2] x86: Generate PLT32 relocation for ".long foo@PLT - .L4"

Message ID CAMe9rOoQR-AGCqWqfL5vHw45bBVZ03MQhQygKf-AvULkZ2p65w@mail.gmail.com
State New
Headers
Series [v2] x86: Generate PLT32 relocation for ".long foo@PLT - .L4" |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

H.J. Lu July 27, 2026, 3:47 a.m. UTC
  On Sat, Jul 25, 2026 at 10:35 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> 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.
>

Add i386 support like LLVM assembler in the v2 patch.
  

Comments

Fangrui Song July 27, 2026, 7:04 a.m. UTC | #1
On Sun, Jul 26, 2026 at 8:51 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sat, Jul 25, 2026 at 10:35 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > 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.
> >
>
> Add i386 support like LLVM assembler in the v2 patch.
>
>
> --
> H.J.
> ---
> 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 - ptr".
> * testsuite/gas/i386/ilp32/x86-64-jump-table.d: New file.
> * testsuite/gas/i386/plt.d: New file.
> * testsuite/gas/i386/plt.s: Likewise.
> * testsuite/gas/i386/reloc32.s: Replace ".long xtrn@plt - ."
> with ".long xtrn@plt - ptr".
> * testsuite/gas/i386/reloc64.l: Updated.
> * testsuite/gas/i386/reloc64.s: Replace ".long xtrn@plt - ." with
> ".long xtrn@plt - _start".
> * 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.

Note, the fact that LLVM integrated assembler's x86 port supports
`.long foo@plt - .` is not really an official decision.
Having a subtrahend in the expression is awkward to support in assemblers.

In LLVM's aarch64 and riscv ports %pltpcrel(foo)   is used.

https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers

AArch64 uses :specifier:expr, yet PAuth ABI (.quad (g + 7)@AUTH(ia,0))
cannot use : after data directives due to parsing ambiguity.
R_AARCH64_PLT32, R_AARCH64_GOTPCREL32, and R_AARCH64_FUNCINIT were
fixed in llvm/llvm-project#155776 to use %pltpcrel(foo) and
%gotpcrel(foo) instead of the unofficial foo@plt - . / foo@gotpcrel
forms.
  
H.J. Lu July 27, 2026, 7:15 a.m. UTC | #2
On Mon, Jul 27, 2026 at 3:04 PM Fangrui Song <i@maskray.me> wrote:
>
> On Sun, Jul 26, 2026 at 8:51 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Sat, Jul 25, 2026 at 10:35 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > 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.
> > >
> >
> > Add i386 support like LLVM assembler in the v2 patch.
> >
> >
> > --
> > H.J.
> > ---
> > 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 - ptr".
> > * testsuite/gas/i386/ilp32/x86-64-jump-table.d: New file.
> > * testsuite/gas/i386/plt.d: New file.
> > * testsuite/gas/i386/plt.s: Likewise.
> > * testsuite/gas/i386/reloc32.s: Replace ".long xtrn@plt - ."
> > with ".long xtrn@plt - ptr".
> > * testsuite/gas/i386/reloc64.l: Updated.
> > * testsuite/gas/i386/reloc64.s: Replace ".long xtrn@plt - ." with
> > ".long xtrn@plt - _start".
> > * 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.
>
> Note, the fact that LLVM integrated assembler's x86 port supports
> `.long foo@plt - .` is not really an official decision.
> Having a subtrahend in the expression is awkward to support in assemblers.

GNU assembler change is small.  This feature is used to fold tail calls
into PIC jump table as in

ld/testsuite/ld-x86-64/x86-64-jump-table.s

> In LLVM's aarch64 and riscv ports %pltpcrel(foo)   is used.
>
> https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers
>
> AArch64 uses :specifier:expr, yet PAuth ABI (.quad (g + 7)@AUTH(ia,0))
> cannot use : after data directives due to parsing ambiguity.
> R_AARCH64_PLT32, R_AARCH64_GOTPCREL32, and R_AARCH64_FUNCINIT were
> fixed in llvm/llvm-project#155776 to use %pltpcrel(foo) and
> %gotpcrel(foo) instead of the unofficial foo@plt - . / foo@gotpcrel
> forms.
  
Jan Beulich July 27, 2026, 7:46 a.m. UTC | #3
On 27.07.2026 05:47, H.J. Lu wrote:
> On Sat, Jul 25, 2026 at 10:35 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> 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.
> 
> Add i386 support like LLVM assembler in the v2 patch.

Why would S_IS_LOCAL() be the criteria? There isn't anything wrong with a
global, at the very least a hidden/protected one, is there? Instead don't
you want to verify that the subtrahend is in the current section (which
of course we may not know until after having parsed all input)?

Surprising code like

+      if (fixp->fx_r_type == BFD_RELOC_X86_64_PC32_TO_PLT32)
+	code = BFD_RELOC_X86_64_PC32_TO_PLT32;
+      else if (fixp->fx_r_type == BFD_RELOC_386_PC32_TO_PLT32)
+	code = BFD_RELOC_386_PLT32;

imo wants at least a brief comment as to the different behavior for i386
vs x86-64.

Jan
  
H.J. Lu July 27, 2026, 7:58 a.m. UTC | #4
On Mon, Jul 27, 2026 at 3:46 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 27.07.2026 05:47, H.J. Lu wrote:
> > On Sat, Jul 25, 2026 at 10:35 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >>
> >> 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.
> >
> > Add i386 support like LLVM assembler in the v2 patch.
>
> Why would S_IS_LOCAL() be the criteria? There isn't anything wrong with a

I will remove it.

> global, at the very least a hidden/protected one, is there? Instead don't
> you want to verify that the subtrahend is in the current section (which
> of course we may not know until after having parsed all input)?

It will be reverified later :

[hjl@gnu-tgl-3 pic-1]$ cat bar.s
        .section .rodata
        .p2align 2
.L4:
        .long foo1@PLT - bar
[hjl@gnu-tgl-3 pic-1]$ ./as  -o bar.o bar.s
bar.s: Assembler messages:
bar.s:4: Error: can't resolve foo1 - bar
[hjl@gnu-tgl-3 pic-1]$

> Surprising code like
>
> +      if (fixp->fx_r_type == BFD_RELOC_X86_64_PC32_TO_PLT32)
> +       code = BFD_RELOC_X86_64_PC32_TO_PLT32;
> +      else if (fixp->fx_r_type == BFD_RELOC_386_PC32_TO_PLT32)
> +       code = BFD_RELOC_386_PLT32;
>
> imo wants at least a brief comment as to the different behavior for i386
> vs x86-64.
>

I will add some comments.
  

Patch

From 2c841f491165f631e591c12d331b6c4f0e8d2b2a Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Fri, 24 Jul 2026 07:01:35 +0800
Subject: [PATCH v2] 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 - ptr".
	* testsuite/gas/i386/ilp32/x86-64-jump-table.d: New file.
	* testsuite/gas/i386/plt.d: New file.
	* testsuite/gas/i386/plt.s: Likewise.
	* testsuite/gas/i386/reloc32.s: Replace ".long xtrn@plt - ."
	with ".long xtrn@plt - ptr".
	* testsuite/gas/i386/reloc64.l: Updated.
	* testsuite/gas/i386/reloc64.s: Replace ".long xtrn@plt - ." with
	".long xtrn@plt - _start".
	* 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>
---
 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                          | 36 +++++++++++++--
 gas/testsuite/gas/i386/i386.exp               |  2 +
 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/plt.d                  | 14 ++++++
 gas/testsuite/gas/i386/plt.s                  |  7 +++
 gas/testsuite/gas/i386/reloc32.s              |  2 +-
 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 +++++++
 21 files changed, 230 insertions(+), 8 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/ilp32/x86-64-jump-table.d
 create mode 100644 gas/testsuite/gas/i386/plt.d
 create mode 100644 gas/testsuite/gas/i386/plt.s
 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..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..41e65913abd 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".  */
+	      if (size == 4
+		  && exp->X_op == O_subtract
+		  && S_IS_LOCAL (exp->X_op_symbol))
+		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,11 @@  md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	  value = -4;
 	break;
 
+      case BFD_RELOC_386_PC32_TO_PLT32:
+	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:
@@ -18626,7 +18641,11 @@  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_PC32_TO_PLT32)
+	code = BFD_RELOC_X86_64_PC32_TO_PLT32;
+      else if (fixp->fx_r_type == BFD_RELOC_386_PC32_TO_PLT32)
+	code = BFD_RELOC_386_PLT32;
+      else if (fixp->fx_pcrel)
 	{
 	  switch (fixp->fx_size)
 	    {
@@ -18751,6 +18770,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..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/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.s b/gas/testsuite/gas/i386/reloc32.s
index 5616cd57e3f..405cf4ccb5f 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 - ptr
 
 	.text
 	movl	$ptr@PLT, %eax
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	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.
-- 
2.55.0