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

Message ID CAMe9rOq9nDvw0uqwma+8mKLfYmiF6zK3mHFz656ySdARKYE69Q@mail.gmail.com
State New
Headers
Series [v3] x86: Generate PLT32 relocation for ".long foo@PLT - .L4" |

Checks

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

Commit Message

H.J. Lu July 27, 2026, 8:44 a.m. UTC
  On Mon, Jul 27, 2026 at 3:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> 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.

Removed in v3.

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

Comments are added in v3.  The difference is explicit addend and implicit
addend.

Here is the v3 patch.
  

Comments

H.J. Lu July 29, 2026, 2:30 a.m. UTC | #1
On Mon, Jul 27, 2026 at 4:44 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Jul 27, 2026 at 3:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > 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.
>
> Removed in v3.
>
> > > 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.
>
> Comments are added in v3.  The difference is explicit addend and implicit
> addend.
>
> Here is the v3 patch.

I will check it in this week.


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



--
H.J.
  
Jan Beulich July 30, 2026, 7:13 a.m. UTC | #2
On 27.07.2026 10:44, H.J. Lu wrote:
> On Mon, Jul 27, 2026 at 3:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>> 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.
> 
> Removed in v3.
> 
>>> 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.
> 
> Comments are added in v3.  The difference is explicit addend and implicit
> addend.
> 
> Here is the v3 patch.

Thanks, but once again I have to ask: Why did this need rushing in? I asked
before that you please allow at least a week between submission and
committing. Perhaps except when a change is entirely uncontroversial, or
really urgent to fix e.g. recently introduced breakage (neither of which is
the case here).

As to the change itself: We have had support for .slong for a long time.
Imo

	.long foo@PLT - .L4

is a bogus construct on 64-bit, and

	.slong foo@PLT - .L4

should be demanded there.

Then: Why do gas/testsuite/gas/i386/reloc{32,64}.s need fiddling with? .
should be as suitable to use there as _start / ptr.

Jan
  
H.J. Lu July 30, 2026, 7:30 a.m. UTC | #3
On Thu, Jul 30, 2026 at 3:14 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 27.07.2026 10:44, H.J. Lu wrote:
> > On Mon, Jul 27, 2026 at 3:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >> 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.
> >
> > Removed in v3.
> >
> >>> 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.
> >
> > Comments are added in v3.  The difference is explicit addend and implicit
> > addend.
> >
> > Here is the v3 patch.
>
> Thanks, but once again I have to ask: Why did this need rushing in? I asked

We can get real usage today.

> before that you please allow at least a week between submission and
> committing. Perhaps except when a change is entirely uncontroversial, or
> really urgent to fix e.g. recently introduced breakage (neither of which is
> the case here).
>
> As to the change itself: We have had support for .slong for a long time.
> Imo
>
>         .long foo@PLT - .L4
>
> is a bogus construct on 64-bit, and
>
>         .slong foo@PLT - .L4

We have

.long foo - .L4

It is natural to add

.long foo@PLT - .L4

> should be demanded there.
>
> Then: Why do gas/testsuite/gas/i386/reloc{32,64}.s need fiddling with? .
> should be as suitable to use there as _start / ptr.

Since

.long xtrn@plt - .

works now.  I change it to " .long xtrn@plt - _start" and added
new working ones in plt.s

> Jan
  
Jan Beulich July 30, 2026, 7:52 a.m. UTC | #4
On 30.07.2026 09:30, H.J. Lu wrote:
> On Thu, Jul 30, 2026 at 3:14 PM Jan Beulich <jbeulich@suse.com> wrote:
>> On 27.07.2026 10:44, H.J. Lu wrote:
>>> Here is the v3 patch.
>>
>> Thanks, but once again I have to ask: Why did this need rushing in? I asked
> 
> We can get real usage today.

Well, we could have 10 years ago. No reason to rush.

>> before that you please allow at least a week between submission and
>> committing. Perhaps except when a change is entirely uncontroversial, or
>> really urgent to fix e.g. recently introduced breakage (neither of which is
>> the case here).
>>
>> As to the change itself: We have had support for .slong for a long time.
>> Imo
>>
>>         .long foo@PLT - .L4
>>
>> is a bogus construct on 64-bit, and
>>
>>         .slong foo@PLT - .L4
> 
> We have
> 
> .long foo - .L4
> 
> It is natural to add
> 
> .long foo@PLT - .L4

As we add support for a construct previously rejected, imo we'd better
demand a well-formed construct there. We can't remove support for bogus
constructs we have always been accepting, so demanding

	.slong foo - .L4

simply isn't possible.

>> should be demanded there.
>>
>> Then: Why do gas/testsuite/gas/i386/reloc{32,64}.s need fiddling with? .
>> should be as suitable to use there as _start / ptr.
> 
> Since
> 
> .long xtrn@plt - .
> 
> works now.

In which case it should imo be kept, with the "bad" prefix removed. And
the new failure case would be added in addition.

Jan
  
H.J. Lu July 30, 2026, 7:58 a.m. UTC | #5
On Thu, Jul 30, 2026 at 3:52 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 30.07.2026 09:30, H.J. Lu wrote:
> > On Thu, Jul 30, 2026 at 3:14 PM Jan Beulich <jbeulich@suse.com> wrote:
> >> On 27.07.2026 10:44, H.J. Lu wrote:
> >>> Here is the v3 patch.
> >>
> >> Thanks, but once again I have to ask: Why did this need rushing in? I asked
> >
> > We can get real usage today.
>
> Well, we could have 10 years ago. No reason to rush.
>
> >> before that you please allow at least a week between submission and
> >> committing. Perhaps except when a change is entirely uncontroversial, or
> >> really urgent to fix e.g. recently introduced breakage (neither of which is
> >> the case here).
> >>
> >> As to the change itself: We have had support for .slong for a long time.
> >> Imo
> >>
> >>         .long foo@PLT - .L4
> >>
> >> is a bogus construct on 64-bit, and
> >>
> >>         .slong foo@PLT - .L4
> >
> > We have
> >
> > .long foo - .L4
> >
> > It is natural to add
> >
> > .long foo@PLT - .L4
>
> As we add support for a construct previously rejected, imo we'd better
> demand a well-formed construct there. We can't remove support for bogus

It is no longer bogus after so many years.

> constructs we have always been accepting, so demanding
>
>         .slong foo - .L4
>
> simply isn't possible.

Not supporting ".long foo@PLT - .L4" while supporting
".long foo - .L4" is very strange.  Also llvm-mc supports
".long foo@PLT - .L4".

> >> should be demanded there.
> >>
> >> Then: Why do gas/testsuite/gas/i386/reloc{32,64}.s need fiddling with? .
> >> should be as suitable to use there as _start / ptr.
> >
> > Since
> >
> > .long xtrn@plt - .
> >
> > works now.
>
> In which case it should imo be kept, with the "bad" prefix removed. And
> the new failure case would be added in addition.
>

I much prefer to place the working one in a new file.
  
Fangrui Song July 30, 2026, 8:24 a.m. UTC | #6
On Thu, Jul 30, 2026 at 12:59 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Thu, Jul 30, 2026 at 3:52 PM Jan Beulich <jbeulich@suse.com> wrote:
> >
> > On 30.07.2026 09:30, H.J. Lu wrote:
> > > On Thu, Jul 30, 2026 at 3:14 PM Jan Beulich <jbeulich@suse.com> wrote:
> > >> On 27.07.2026 10:44, H.J. Lu wrote:
> > >>> Here is the v3 patch.
> > >>
> > >> Thanks, but once again I have to ask: Why did this need rushing in? I asked
> > >
> > > We can get real usage today.
> >
> > Well, we could have 10 years ago. No reason to rush.
> >
> > >> before that you please allow at least a week between submission and
> > >> committing. Perhaps except when a change is entirely uncontroversial, or
> > >> really urgent to fix e.g. recently introduced breakage (neither of which is
> > >> the case here).
> > >>
> > >> As to the change itself: We have had support for .slong for a long time.
> > >> Imo
> > >>
> > >>         .long foo@PLT - .L4
> > >>
> > >> is a bogus construct on 64-bit, and
> > >>
> > >>         .slong foo@PLT - .L4
> > >
> > > We have
> > >
> > > .long foo - .L4
> > >
> > > It is natural to add
> > >
> > > .long foo@PLT - .L4
> >
> > As we add support for a construct previously rejected, imo we'd better
> > demand a well-formed construct there. We can't remove support for bogus
>
> It is no longer bogus after so many years.
>
> > constructs we have always been accepting, so demanding
> >
> >         .slong foo - .L4
> >
> > simply isn't possible.
>
> Not supporting ".long foo@PLT - .L4" while supporting
> ".long foo - .L4" is very strange.  Also llvm-mc supports
> ".long foo@PLT - .L4".

I'd rather we not add `.long foo@plt - .`. R_X86_64_PLT32 is L + A -
P: the PC-relativity is intrinsic to the relocation type, and gas
already emits it from the bare spelling in some cases (e.g. `.globl
foo; .long foo@plt - .`).
There is a real @plt bug worth fixing instead. For a defined local
symbol we drop the specifier and emit an absolute relocation,
silently. `.long foo@plt - .`


The only reason llvm-mc assembles `.long foo@plt - .`  is an
implementation accident from Clang's relative C++ vtables support, and
should be fixed.
I've switched aarch64 to `%pltpcrel(foo)` - there is no risk of
breaking user code - no user assembly at all.

In addition, `.long foo@plt - bar` has unclear semantics: shall we
fold `foo-bar` to a constant if both are in the same section, even not
the current section?

> > >> should be demanded there.
> > >>
> > >> Then: Why do gas/testsuite/gas/i386/reloc{32,64}.s need fiddling with? .
> > >> should be as suitable to use there as _start / ptr.
> > >
> > > Since
> > >
> > > .long xtrn@plt - .
> > >
> > > works now.
> >
> > In which case it should imo be kept, with the "bad" prefix removed. And
> > the new failure case would be added in addition.
> >
>
> I much prefer to place the working one in a new file.
>
> --
> H.J.
  
H.J. Lu July 30, 2026, 8:34 a.m. UTC | #7
On Thu, Jul 30, 2026 at 4:24 PM Fangrui Song <i@maskray.me> wrote:
>
> On Thu, Jul 30, 2026 at 12:59 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Thu, Jul 30, 2026 at 3:52 PM Jan Beulich <jbeulich@suse.com> wrote:
> > >
> > > On 30.07.2026 09:30, H.J. Lu wrote:
> > > > On Thu, Jul 30, 2026 at 3:14 PM Jan Beulich <jbeulich@suse.com> wrote:
> > > >> On 27.07.2026 10:44, H.J. Lu wrote:
> > > >>> Here is the v3 patch.
> > > >>
> > > >> Thanks, but once again I have to ask: Why did this need rushing in? I asked
> > > >
> > > > We can get real usage today.
> > >
> > > Well, we could have 10 years ago. No reason to rush.
> > >
> > > >> before that you please allow at least a week between submission and
> > > >> committing. Perhaps except when a change is entirely uncontroversial, or
> > > >> really urgent to fix e.g. recently introduced breakage (neither of which is
> > > >> the case here).
> > > >>
> > > >> As to the change itself: We have had support for .slong for a long time.
> > > >> Imo
> > > >>
> > > >>         .long foo@PLT - .L4
> > > >>
> > > >> is a bogus construct on 64-bit, and
> > > >>
> > > >>         .slong foo@PLT - .L4
> > > >
> > > > We have
> > > >
> > > > .long foo - .L4
> > > >
> > > > It is natural to add
> > > >
> > > > .long foo@PLT - .L4
> > >
> > > As we add support for a construct previously rejected, imo we'd better
> > > demand a well-formed construct there. We can't remove support for bogus
> >
> > It is no longer bogus after so many years.
> >
> > > constructs we have always been accepting, so demanding
> > >
> > >         .slong foo - .L4
> > >
> > > simply isn't possible.
> >
> > Not supporting ".long foo@PLT - .L4" while supporting
> > ".long foo - .L4" is very strange.  Also llvm-mc supports
> > ".long foo@PLT - .L4".
>
> I'd rather we not add `.long foo@plt - .`. R_X86_64_PLT32 is L + A -
> P: the PC-relativity is intrinsic to the relocation type, and gas
> already emits it from the bare spelling in some cases (e.g. `.globl
> foo; .long foo@plt - .`).
> There is a real @plt bug worth fixing instead. For a defined local
> symbol we drop the specifier and emit an absolute relocation,
> silently. `.long foo@plt - .`

OK. I will change it to ".slong foo@PLT - .L4".

>
> The only reason llvm-mc assembles `.long foo@plt - .`  is an
> implementation accident from Clang's relative C++ vtables support, and
> should be fixed.
> I've switched aarch64 to `%pltpcrel(foo)` - there is no risk of
> breaking user code - no user assembly at all.
>
> In addition, `.long foo@plt - bar` has unclear semantics: shall we
> fold `foo-bar` to a constant if both are in the same section, even not
> the current section?
>
> > > >> should be demanded there.
> > > >>
> > > >> Then: Why do gas/testsuite/gas/i386/reloc{32,64}.s need fiddling with? .
> > > >> should be as suitable to use there as _start / ptr.
> > > >
> > > > Since
> > > >
> > > > .long xtrn@plt - .
> > > >
> > > > works now.
> > >
> > > In which case it should imo be kept, with the "bad" prefix removed. And
> > > the new failure case would be added in addition.
> > >
> >
> > I much prefer to place the working one in a new file.
> >
> > --
> > H.J.
  

Patch

From 9db0968238eff7aef0efb014acfeafc9e5e7e30f 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 v3] 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>
---
 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/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(-)
 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..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.
-- 
2.55.0