[PATCH] x86: Properly handle relocation against hidden ABS symbol

H.J. Lu hjl.tools@gmail.com
Thu May 15 04:53:47 GMT 2025


On Thu, May 15, 2025, 12:41 PM Fangrui Song <i@maskray.me> wrote:

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

The GOT entry isn't needed in this case if there is no overflow.
Since we know the value, we can keep the GOT entry if there is an overflow.
I will update my patch to do that.

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

We are discussing hidden ABS symbol here.  I will update my patch to check
overflow.
For this case, linker will issue an error if there is an overflow.
I will change my patch.

(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.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/binutils/attachments/20250515/0bf1862b/attachment.htm>


More information about the Binutils mailing list