Bug 32196 - R_X86_64_32 relocation generated, expecting R_X86_64_PLT32
Summary: R_X86_64_32 relocation generated, expecting R_X86_64_PLT32
Status: REOPENED
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.43
: P2 normal
Target Milestone: 2.44
Assignee: H.J. Lu
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-09-21 23:03 UTC by Felix Potthast
Modified: 2026-02-11 08:16 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2024-09-22 00:00:00
Project(s) to access:
ssh public key:


Attachments
Test case (123 bytes, text/plain)
2024-09-21 23:03 UTC, Felix Potthast
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Felix Potthast 2024-09-21 23:03:25 UTC
Created attachment 15711 [details]
Test case

I expect gas to generate a R_X86_64_PLT32 when writing:
movq $foo@PLT, %rax

However, a R_X86_64_32 is generated instead.

Assembling the attached file with:
as test.s -o test.o

And linking with:
ld -static test.o -o test

leads to the executable generating a segfault when running.
When assembling with clang and then linking, the generated executable exits without an error.
Comment 1 Sourceware Commits 2024-09-22 19:54:30 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1b714c14e40f37ea8ea02a4998c4d95f25aff7f3

commit 1b714c14e40f37ea8ea02a4998c4d95f25aff7f3
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sun Sep 22 17:06:45 2024 +0800

    x86: Turn PLT32 to PC32 only for PC-relative relocations
    
    commit 292676c15a615b5a95bede9ee91004d3f7ee7dfd
    Author: H.J. Lu <hjl.tools@gmail.com>
    Date:   Thu Feb 13 13:44:17 2020 -0800
    
        x86: Resolve PLT32 reloc aganst local symbol to section
    
    resolved PLT32 relocation against local symbol to section and
    
    commit 2585b7a5ce5830e60a089aa2316a329558902f0c
    Author: H.J. Lu <hjl.tools@gmail.com>
    Date:   Sun Jul 19 06:51:19 2020 -0700
    
        x86: Change PLT32 reloc against section to PC32
    
    turned PLT32 relocation against section into PC32 relocation.  But these
    transformations are valid only for PC-relative relocations.  Add fx_pcrel
    check for PC-relative relocations when performing these transformations
    to keep PLT32 relocation in `movq $foo@PLT, %rax`.
    
    gas/
    
            PR gas/32196
            * config/tc-i386.c (tc_i386_fix_adjustable): Return fixP->fx_pcrel
            for PLT32 relocations.
            (i386_validate_fix): Turn PLT32 relocation into PC32 relocation
            only if fixp->fx_pcrel is set.
            * testsuite/gas/i386/reloc32.d: Updated.
            * testsuite/gas/i386/reloc64.d: Likewise.
            * testsuite/gas/i386/reloc32.s: Add PR gas/32196 test.
            * testsuite/gas/i386/reloc64.s: Likewise.
    
    ld/
    
            PR gas/32196
            * testsuite/ld-x86-64/plt3.s: New file.
            * testsuite/ld-x86-64/x86-64.exp: Run plt3.
    
    Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Comment 2 Sourceware Commits 2024-09-25 23:23:14 UTC
The binutils-2_43-branch branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ad2ce1e6457c6026de0bdce1391705445769581d

commit ad2ce1e6457c6026de0bdce1391705445769581d
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sun Sep 22 17:06:45 2024 +0800

    x86: Turn PLT32 to PC32 only for PC-relative relocations
    
    commit 292676c15a615b5a95bede9ee91004d3f7ee7dfd
    Author: H.J. Lu <hjl.tools@gmail.com>
    Date:   Thu Feb 13 13:44:17 2020 -0800
    
        x86: Resolve PLT32 reloc aganst local symbol to section
    
    resolved PLT32 relocation against local symbol to section and
    
    commit 2585b7a5ce5830e60a089aa2316a329558902f0c
    Author: H.J. Lu <hjl.tools@gmail.com>
    Date:   Sun Jul 19 06:51:19 2020 -0700
    
        x86: Change PLT32 reloc against section to PC32
    
    turned PLT32 relocation against section into PC32 relocation.  But these
    transformations are valid only for PC-relative relocations.  Add fx_pcrel
    check for PC-relative relocations when performing these transformations
    to keep PLT32 relocation in `movq $foo@PLT, %rax`.
    
    gas/
    
            PR gas/32196
            * config/tc-i386.c (tc_i386_fix_adjustable): Return fixP->fx_pcrel
            for PLT32 relocations.
            (i386_validate_fix): Turn PLT32 relocation into PC32 relocation
            only if fixp->fx_pcrel is set.
            * testsuite/gas/i386/reloc32.d: Updated.
            * testsuite/gas/i386/reloc64.d: Likewise.
            * testsuite/gas/i386/reloc32.s: Add PR gas/32196 test.
            * testsuite/gas/i386/reloc64.s: Likewise.
    
    ld/
    
            PR gas/32196
            * testsuite/ld-x86-64/plt3.s: New file.
            * testsuite/ld-x86-64/x86-64.exp: Run plt3.
    
    Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
    (cherry picked from commit 1b714c14e40f37ea8ea02a4998c4d95f25aff7f3)
Comment 3 H.J. Lu 2024-09-25 23:24:13 UTC
Fixed for 2.44 and 2.43 branch.
Comment 4 Fangrui Song 2025-05-24 22:43:22 UTC
With the latest change, call local@plt doesn't generate a relocation when the symbol is a local symbol in the same section. However, movq $local@PLT, %rax generates a relocation, which is redundant.


% cat g.s
movq $local@PLT, %rax
call local@plt

movq $.data@PLT, %rax
call .data@plt

local:

.data

% ~/Dev/binutils-gdb/out/debug/gas/as-new g.s -o g.o
% objdump -dr g.o

g.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <local-0x18>:
   0:   48 c7 c0 00 00 00 00    mov    $0x0,%rax
                        3: R_X86_64_PLT32       local
   7:   e8 0c 00 00 00          call   18 <local>
   c:   48 c7 c0 00 00 00 00    mov    $0x0,%rax
                        f: R_X86_64_PLT32       .data
  13:   e8 00 00 00 00          call   18 <local>
                        14: R_X86_64_PC32       .data-0x4
Comment 5 Jan Beulich 2025-09-01 06:35:19 UTC
(In reply to Fangrui Song from comment #4)
> With the latest change, call local@plt doesn't generate a relocation when
> the symbol is a local symbol in the same section. However, movq $local@PLT,
> %rax generates a relocation, which is redundant.

Whether it's "redundant" can only be known by inspecting subsequent code. In fact, the programmer writing @PLT (or any other @...) ought to result in exactly what is asked for. Zapping the PLT reloc (ro, again, any other one) may be done as an optimization, but like for any other optimizations that shouldn't be active by default.

The code change done also looks wrong to me, as does the related error raised by x86_cons(): Both R_386_PLT32 and R_X86_64_PLT32 are clearly specified as PC-relative. There cannot be non-PC-relative forms, and hence plain uses of symbol@PLT are valid only in PC-relative context (CALL, JMP, Jcc, XBEGIN, and %rip-relative addressing). Other uses need to be spelled out as PC-relative (symbol@PLT - .) to be valid.

Note also that while the check in x86_cons() rejects e.g.

	.slong plt32@plt - .

all of

	mov	$plt32@plt, %eax
	mov	$plt32@plt - ., %eax

(32-bit) and

	mov	$plt32@plt, %rax
	mov	$plt32@plt - ., %rax

(64-bit) are accepted, the respectively former yielding the code + relocation that the respectively latter should yield ("plt32" being a local symbol).
Comment 6 Fangrui Song 2026-02-08 07:44:53 UTC
We should revisit the resolution to PR25551 and PR32196.

I raised PR25551 due to an unneeded .symtab entry .Lprintk$local .
The resolution changed R_X86_64_PLT32 to R_X86_64_PC32, which is less desirable, and required an amendment for this issue.

PLT32 is a branch relocation type, which means the symbol address is insignificant (similar to R_AARCH64_CALL26 / R_PPC64_REL24).
In a modified large code model, we could instruct the linker to create a range extension thunk if the target symbol is out of reach of +-2GiB.

	.section	.init.text,"ax",@progbits
	call	.Lprintk$local
                                        # -- End function
	.text
	.globl	printk                  # -- Begin function printk
	.type	printk,@function
printk:                                 # @printk
.Lprintk$local:
 ret

Using PC32 means the symbol address is significant, and we cannot safely redirect the relocation (without disassembling the instruction) to a thunk.

For this assembly sequence, LLVM integrated assembler generates the desired R_X86_64_PLT32 relocation referencing .text - 4, which allows range extension thunks.


(Meta Platforms engineers want to implement range extension thunks for https://groups.google.com/g/x86-64-abi/c/RsJDf06xMJ0
I mentioned that "we should have at least some basic agreement on x86-64-abi (gitlab.com/x86-psABIs/x86-64-ABI) before moving in this direction - and I recalled this gas issue.)
Comment 7 Fangrui Song 2026-02-08 23:31:18 UTC
(In reply to Fangrui Song from comment #6)
> We should revisit the resolution to PR25551 and PR32196.
> 
> I raised PR25551 due to an unneeded .symtab entry .Lprintk$local .
> The resolution changed R_X86_64_PLT32 to R_X86_64_PC32, which is less
> desirable, and required an amendment for this issue.
> 
> PLT32 is a branch relocation type, which means the symbol address is
> insignificant (similar to R_AARCH64_CALL26 / R_PPC64_REL24).
> In a modified large code model, we could instruct the linker to create a
> range extension thunk if the target symbol is out of reach of +-2GiB.
> 
> 	.section	.init.text,"ax",@progbits
> 	call	.Lprintk$local
>                                         # -- End function
> 	.text
> 	.globl	printk                  # -- Begin function printk
> 	.type	printk,@function
> printk:                                 # @printk
> .Lprintk$local:
>  ret
> 
> Using PC32 means the symbol address is significant, and we cannot safely
> redirect the relocation (without disassembling the instruction) to a thunk.
> 
> For this assembly sequence, LLVM integrated assembler generates the desired
> R_X86_64_PLT32 relocation referencing .text - 4, which allows range
> extension thunks.

We can simply revert the PLT32-to-PC32 conversions introduced by commits 2585b7a5ce58     ("x86: Change PLT32 reloc against section to PC32") and ad2ce1e6457c     ("x86: Turn PLT32 to PC32 only for PC-relative relocations").

https://sourceware.org/pipermail/binutils/2026-February/148154.html

The patch does not change the behavior of

        # 64-bit
        mov     $plt32@plt, %rax  # PLT32, plt32+0
        mov     $plt32@plt - ., %rax  # PLT32, plt32-4