Re: [Patch] LoongArch: Restore pointer_equality_needed for GOT data relocations
Xi Ruoyao via Binutils <[email protected]> Sun, 02 Aug 2026 07:26:13 +0800
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 2026-07-30 at 17:34 +0800, Yanjun Yang wrote: > From: Pluto Yang <[email protected]> >=20 > Commit 7f9d6d6ead5 ("LoongArch: Fix Build pr29655") removed the > setting of pointer_equality_needed for GOT relocations > (R_LARCH_GOT_PC_HI20, R_LARCH_GOT_PCADD_HI20, R_LARCH_GOT_HI20, > R_LARCH_SOP_PUSH_GPREL).=C2=A0 This was correct for function symbols to > fix PR 29655 (function pointer equality in PIE executables), but it > had an unintended side effect: the CRT startup code uses > R_LARCH_GOT_PC_HI20 to access data symbols like __environ, > __rela_iplt_start, __rela_iplt_end, and _dl_ns.=C2=A0 Without > pointer_equality_needed, the GOT layout for these data symbols is > altered, corrupting the static binary and causing runtime segfaults. This does not make sense to me. Global data symbols are accessed via R_LARCH_GOT_PC_HI20 everywhere, not only the CRT startup code. Thus if accessing data symbols with R_LARCH_GOT_PC_HI20 is broken we'd have a much more wide-spreading breakage. > Restore pointer_equality_needed for GOT relocations, but only for > non-function symbols (h->type !=3D STT_FUNC).=C2=A0 This preserves the > PR 29655 fix for function symbols while fixing static executables > that use data symbols accessed via GOT relocations. This again does not make sense to me. Pointer equality matters because if you end up comparing the address of the PLT stub and the address of the real function you'd break pointer equality. You cannot use a PLT stub for data symbols so pointer equality has nothing to do with data symbols. > This bug was discovered when building GCC for loongarch64: the > libstdc++ configure script tests TLS support by running a statically > linked program.=C2=A0 The corrupted GOT caused the test to crash, leading > to gcc_cv_have_tls=3Dno, which disabled TLS support in libstdc++ and > broke ABI compatibility with system libraries. I cannot reproduce the issue by building GCC: GCC builds fine with gcc_cv_have_tls=3Dyes in config.log files. But maybe this test case: int f1() { return 42; } int f2() { return 47; } void *fx() { return f1; } [[gnu::ifunc("fx")]] int f(); int main() { int (*p)() =3D f; asm("":"+r"(p)); return p();} This thing indeed crashes with ld-2.47 and -static: debugger shows the value of p is now __strrchr_lasx in glibc (!!!) which will definitely not work at the place of f1(). It "works" with ld-2.46 but the value of p is the address of the PLT entry, not the address of f1. On x86 it behaves the same way but on aarch64 we get the address of f1. I don't know which way is better yet. And I'm also unsure if the malfunction demonstrated with the test case above is the same "GOT corruption" in your case. > Signed-off-by: Pluto Yang <[email protected]> > --- > =C2=A0bfd/elfnn-loongarch.c | 5 +++++ > =C2=A01 file changed, 5 insertions(+) >=20 > diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c > index 4bdc3f26285..1c643c587f2 100644 > --- a/bfd/elfnn-loongarch.c > +++ b/bfd/elfnn-loongarch.c > @@ -1249,6 +1249,11 @@ loongarch_elf_check_relocs (bfd *abfd, struct > bfd_link_info *info, > =C2=A0 case R_LARCH_GOT_PCADD_HI20: > =C2=A0 case R_LARCH_GOT_HI20: > =C2=A0 case R_LARCH_SOP_PUSH_GPREL: > + =C2=A0 /* For la.global: set pointer_equality_needed for data > symbols This line especially makes no sense... > + =C2=A0=C2=A0=C2=A0=C2=A0 to ensure correct GOT layout.=C2=A0 Function s= ymbols are > excluded > + =C2=A0=C2=A0=C2=A0=C2=A0 to avoid breaking function pointer equality (P= R 29655).=C2=A0 > */ > + =C2=A0 if (h && h->type !=3D STT_FUNC) So, maybe just h->type =3D=3D STT_GNU_IFUNC? > + =C2=A0=C2=A0=C2=A0 h->pointer_equality_needed =3D 1; > =C2=A0 =C2=A0 if (!loongarch_elf_record_tls_and_got_reference (abfd, > info, h, > =C2=A0 =C2=A0=C2=A0 r_symndx, > =C2=A0 =C2=A0=C2=A0 > GOT_NORMAL, --=20 Xi Ruoyao <[email protected]>