Re: [Patch] LoongArch: Restore pointer_equality_needed for GOT data relocations
Yanjun Yang <[email protected]> Mon, 3 Aug 2026 15:35:14 +0800
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
On Sun, Aug 02, 2026 at 07:26:13AM +0800, Xi Ruoyao wrote: > On Thu, 2026-07-30 at 17:34 +0800, Yanjun Yang wrote: > > From: Pluto Yang <[email protected]> > > > > 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). 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. 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 != STT_FUNC). 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. > You are right, and thank you for the analysis. I bisected the regression and found commit 7f9d6d6ead5 ("LoongArch: Fix Build pr29655") was the first bad commit, which removed the pointer_equality_needed = 1 for GOT relocations. Based on that, I incorrectly assumed the removal itself was the problem. > > This bug was discovered when building GCC for loongarch64: the > > libstdc++ configure script tests TLS support by running a statically > > linked program. The corrupted GOT caused the test to crash, leading > > to gcc_cv_have_tls=no, 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=yes in config.log files. But maybe this test case: > This is likely a difference in the build environment. I hit this when packaging GCC 16.1.1 for Arch Linux on loongarch64. The chroot has binutils 2.47-1, where the libstdc++ configure TLS test runs a statically linked program that crashed due to the .got.plt bug, resulting in gcc_cv_have_tls=no. > int f1() { return 42; } > int f2() { return 47; } > > void *fx() { return f1; } > > [[gnu::ifunc("fx")]] int f(); > > int main() { int (*p)() = 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. Yes, it is the same bug, and your ifunc_got_off patch (from: [PATCH] LoongArch: fix .got.plt dislocation in static PDE) is the proper fix. I have applied it on top of my tree and verified GCC libstdc++ configure TLS test now passes. Best regards, Yanjun Yang > > > Signed-off-by: Pluto Yang <[email protected]> > > --- > > bfd/elfnn-loongarch.c | 5 +++++ > > 1 file changed, 5 insertions(+) > > > > 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, > > case R_LARCH_GOT_PCADD_HI20: > > case R_LARCH_GOT_HI20: > > case R_LARCH_SOP_PUSH_GPREL: > > + /* For la.global: set pointer_equality_needed for data > > symbols > > This line especially makes no sense... > > > + to ensure correct GOT layout. Function symbols are > > excluded > > + to avoid breaking function pointer equality (PR 29655). > > */ > > + if (h && h->type != STT_FUNC) > > So, maybe just h->type == STT_GNU_IFUNC? > > > + h->pointer_equality_needed = 1; > > if (!loongarch_elf_record_tls_and_got_reference (abfd, > > info, h, > > r_symndx, > > > > GOT_NORMAL, > > -- > Xi Ruoyao <[email protected]>