[PATCH] x86: Properly handle relocation against hidden ABS symbol
Fangrui Song
i@maskray.me
Thu May 15 04:41:57 GMT 2025
On Wed, May 14, 2025 at 7:02 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> With PIC on x86-64,
>
> movq symbol@GOTPCREL(%rip), %rax
>
> is used to get the symbol address via GOT. If the symbol turns out to
> be a hidden symbol, linker normally converts it into
>
> leaq symbol(%rip), %rax
>
> But if the symbol is an ABS symbol, RAX won't have the correct value at
> run-time and it will have the symbol value + load address. If the symbol
> is declared as hidden, compiler will generate
>
> leaq symbol(%rip), %rax
>
> to get the symbol address. If the hidden symbol is an ABS symbol, RAX
> will have the same incorrect value at run-time. On i386,
>
> movl symbol@GOT(%reg1), %reg2
>
> is used to get the symbol address via GOT. If the symbol turns out to
> be a hidden symbol, linker normally converts it into
>
> leal symbol@GOTOFF(%reg1), %reg2
>
> If the symbol is declared as hidden, compiler will generate
>
> leal symbol@GOTOFF(%reg1), %reg2
>
> In both cases, if the hidden symbol is an ABS symbol, REG2 will have the
> same incorrect value at run-time. This patch changes the x86-64 linker
> to convert
>
> movq symbol@GOTPCREL(%rip), %rax
> and
> leaq symbol(%rip), %rax
> to
> movq $symbol, %rax
For the instruction `movq symbol@GOTPCREL(%rip), %rax`, where a
R_X86_64_REX_GOTPCRELX relocation references a SHN_ABS symbol (e.g.,
42),
the transformation should be disabled, and the GOT entry should
contain the constant value 42.
(This behavir aligns with all lld/ELF ports that support GOT
indirection to PC-relative optimization (x86-64, AArch64,
SystemZ(s390x))
https://maskray.me/blog/2021-08-29-all-about-global-offset-table#got-optimization
)
For the instruction `leaq symbol(%rip), %rax`, where a R_X86_64_PC32
relocation references a SHN_ABS symbol (e.g., 42),
I don't think we can do code transformation.
Although this may link successfully in -no-pie mode if the
displacement fits within a 32-bit range, it should be rejected in -pie
and -shared modes, as the displacement is not a run-time constant.
(Unless we decide to support text relocations and -z notext is
specified - we shouldn't)
Accessing a SHN_ABS value from C code requires delicate code
construct, but I think it's acceptable.
To generate a GOT-based code sequence, the user should either use
* a STB_WEAK symbol with -fpic or -fpie
* or a STB_GLOBAL symbol with -fpic or -fpie (exception: gcc
HAVE_LD_PIE_COPYRELOC builds's -fpie doesn't work)
```
// -fno-pic: R_X86_64_PC32
// -fpie: R_X86_64_REX_GOTPCRELX in clang, but R_X86_64_PC32 in GCC
(as almost all builds set HAVE_LD_PIE_COPYRELOC)
// -fpic: R_X86_64_REX_GOTPCRELX
extern int def __attribute__((visibility("default")));
extern int hid __attribute__((visibility("hidden")));
// guaranteed R_X86_64_REX_GOTPCRELX
extern int hid_w __attribute__((weak, visibility("hidden")));
int *r_def() { return &def; }
int *r_hid() { return &hid; }
int *r_hid_w() { return &hid_w; }
```
To align GCC x86-64's behavior with other GCC ports and Clang, I hope
that we can take this HAVE_LD_PIE_COPYRELOC removal patch
https://gcc.gnu.org/pipermail/gcc-patches/2021-May/570139.html :)
> and changes the i386 linker to convert
>
> movl symbol@GOT(%reg1), %reg2
> and
> leal symbol@GOTOFF(%reg1), %reg2
> to
> movl $symbol, %reg2
>
> for hidden ABS symbols.
>
> bfd/
>
> PR ld/32443
> * elf32-i386.c (elf_i386_convert_load_reloc): Skip relocation
> against linker-script hidden absolute symbol in PIC.
> (elf_i386_finish_dynamic_symbol): Don't generate dynamic
> relocation against inker-script hidden absolute symbol.
> * elf64-x86-64.c (elf_x86_64_convert_load_reloc): Skip
> relocation against linker-script hidden absolute symbol in PIC.
> (elf_x86_64_finish_dynamic_symbol): Don't generate dynamic
> relocation against inker-script hidden absolute symbol.
> * elfxx-x86.c (elf_x86_allocate_dynrelocs): Don't allocate
> dynamic relocation against inker-script hidden absolute symbol.
> * elfxx-x86.h (HIDDEN_ABS_SYMBOL_P): New.
>
> ld/
>
> PR ld/32443
> * testsuite/ld-elf/linux-x86.exp: Run PR ld/32443 tests. Allow
> PC32 relocation against hidden ABS symbol in PIE.
> * testsuite/ld-elf/pr32443-hidden.rd: New file.
> * testsuite/ld-elf/pr32443-hidden.t: Likewise.
> * testsuite/ld-elf/pr32443.t: Likewise.
> * testsuite/ld-elf/pr32443a.c: Likewise.
> * testsuite/ld-elf/pr32443b.c: Likewise.
> * testsuite/ld-i386/i386.exp: Run lea2, mov4a and mov4b.
> * testsuite/ld-i386/lea2.d: New file.
> * testsuite/ld-i386/lea2.s: Likewise.
> * testsuite/ld-i386/mov4.s: Likewise.
> * testsuite/ld-i386/mov4a.d: Likewise.
> * testsuite/ld-i386/mov4b.d: Likewise.
> * testsuite/ld-x86-64/lea2-x32.d: Likewise.
> * testsuite/ld-x86-64/lea2.d: Likewise.
> * testsuite/ld-x86-64/lea2.s: Likewise.
> * testsuite/ld-x86-64/mov3.s: Likewise.
> * testsuite/ld-x86-64/mov3a-x32.d: Likewise.
> * testsuite/ld-x86-64/mov3a.d: Likewise.
> * testsuite/ld-x86-64/mov3b-x32.d: Likewise.
> * testsuite/ld-x86-64/mov3b.d: Likewise.
> * testsuite/ld-x86-64/x86-64.exp: Run lea2, lea2-x32, mov3a,
> mov3a-x32, mov3b and mov3b-x32.
>
> --
> H.J.
More information about the Binutils
mailing list