[PATCH] x86: keep PLT32 relocation for local symbols instead of converting to PC32

Jan Beulich jbeulich@suse.com
Wed Feb 18 09:36:08 GMT 2026


On 17.02.2026 19:12, Fangrui Song wrote:
> On Tue, Feb 17, 2026 at 1:04 AM Jan Beulich <jbeulich@suse.com> wrote:
>> On 16.02.2026 22:54, Fangrui Song wrote:
>>> On Tue, Feb 10, 2026 at 12:24 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>> On 10.02.2026 06:16, Fangrui Song wrote:
>>>>> On Mon, Feb 9, 2026 at 1:03 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>> On 09.02.2026 09:46, Fangrui Song wrote:
>>>>>>> On Mon, Feb 9, 2026 at 12:23 AM Jan Beulich <jbeulich@suse.com> wrote:
>>>>>>>> On 09.02.2026 00:26, Fangrui Song wrote:
>>>>>>>>> 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").
>>>>>>>>>
>>>>>>>>> PLT32 is a branch relocation type where the symbol address is
>>>>>>>>> insignificant (similar to R_AARCH64_CALL26 and R_PPC64_REL24).
>>>>>>>>
>>>>>>>> I fear I don't understand this wording: The (ultimate) symbol address is
>>>>>>>> very much relevant, or else the wrong contents will be put in the PLT?
>>>>>>>
>>>>>>> The x86-64 PLT32 relocation type is a branch relocation type, which
>>>>>>> can be used to make a function call but not by taking the address
>>>>>>> (pointer escape).
>>>>>>> The name is a misnomer (therefore on arm/aarch64/ppc they are not
>>>>>>> called "R_*_PLT*") - if the target symbol is non-preemptible, the
>>>>>>> linker resolves the relocation as a direct PC-relative one.
>>>>>>
>>>>>> Taking Arm64 as example, can you even compare with that? I couldn't spot
>>>>>> any relocation using L in the "Operation" column.
>>>>>
>>>>> While its Operation column contains
>>>>>
>>>>> R_<CLS>_JUMP26  S+A-P
>>>>> R_<CLS>_CALL26  S+A-P
>>>>>
>>>>> There is some information at
>>>>> https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst#577call-and-jump-relocations
>>>>>
>>>>>> A linker may use a veneer (a sequence of instructions) to implement a relocated branch if the relocation is either
>>>>>>
>>>>>> R_<CLS>_CALL26, R_<CLS>_JUMP26 or R_<CLS>_PLT32 and:
>>>>>>
>>>>>> The target symbol has type STT_FUNC.
>>>>>> Or, the target symbol and relocated place are in separate sections input to the linker.
>>>>>> Or, the target symbol is undefined (external to the link unit).         <----------- this is the PLT case
>>>>
>>>> Is it, really? Nothing is said (afaics) that such veneers then need to live
>>>> in a construct named PLT. They could be scattered around, and there's not
>>>> even a requirement to allocate a PLT entry.
>>>
>>> Right - no PLT needs to be allocated.
>>> The relocation type tells the linker to "transfer control there by any means".
>>> The linker may resolve it directly (if non-preemptible (STB_LOCAL,
>>> hidden/protected visibility, defined in executable of -Bsymbolic
>>> shared objects, etc)),
>>> route it through a PLT entry, or insert a veneer (arm,aarch64,powerpc,etc).
>>>
>>> This is why I said R_X86_64_PLT32 was a misnomer. It functions as a
>>> generic call relocation.
>>> It would have been clearer if we had named it R_X86_64_CALL32.
>>
>> It could have been done that way, but we need to live with what we've got.
>> Which mandates the setting up of a PLT entry, omitting of which is only
>> an optimization (which should be possible to suppress, especially if
>> someone actively used @plt in assembly, in the expectation to have a PLT
>> entry allocated no matter what).
> 
> Hi Jan, I don't think omitting a PLT entry is an optional optimization.
> `.globl foo: call foo` in assembly, used in static linking builds, is
> expected to resolve the PLT32 directly without creating a PLT entry.

You're again resorting to an example where there is no talk of PLT in the
source. In that case the assembler (appropriately or not) using PLT32
kind of implies that the linker do its best to avoid creating a PLT entry.
For "call foo@plt", otoh, it is an optimization, which in principle users
should opt in to.

> Actually, GNU ld, gold, lld/ELF, and mold resolve PLT32 directly for
> non-preemptible symbols.
> 
> We should accept that the @plt notation in assembly and the PLT32
> relocation type names are misleading. They suggest that a PLT entry is
> involved, but that is often not the case.

Effectively what you're suggesting is that we deprecate @plt, properly
documenting that its absence on CALL/JMP operands still means PLT32 will be
used as relocation. That'll need properly spelling out in the doc then.
Which may be not as easy as it sounds, as it looks as if none of the @...
operand modifiers were documented anywhere.

>>>>> This patch disables PLT32->PC32 conversion. If there is still
>>>>> uncertainty regarding the i386 linker bug, I can leave the i386
>>>>> behavior unchanged.
>>>>
>>>> This would imo be worse. There shouldn't be differences in handing like
>>>> this, except when the psABI-s really differ in certain aspects. I don't
>>>> think they do here. (There are other differences which I don't really
>>>> understand. One of them I explicitly called out in [1], but sadly no-one
>>>> cared to clarify this.)
>>>
>>> The patch applies the same policy to both i386 and x86-64: both keep
>>> PLT32 against section symbols, both remove the PLT32-to-PC32
>>> conversion in i386_validate_fix, both use the same
>>> tc_i386_fix_adjustable change. The handling is identical.
>>
>> Just to clarify - my earlier response was to "I can leave the i386
>> behavior unchanged", i.e. you suggesting to make the behavior further
>> different.
> 
> Well, the patch applies the same change to both i386 and x86-64: both
> keep PLT32 against section symbols. No behavioral divergence.
> 
> Without this patch `call .text1@plt` and `local: call local@plt` generate PC32.

Yes, that bug I have on my list to address. Certainly nice if it gets addressed
by other means.

Jan


More information about the Binutils mailing list