[Patch] LoongArch: Restore pointer_equality_needed for GOT data relocations

Yanjun Yang <[email protected]> Thu, 30 Jul 2026 17:34:43 +0800
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
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.

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

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
+	     to ensure correct GOT layout.  Function symbols are excluded
+	     to avoid breaking function pointer equality (PR 29655).  */
+	  if (h && h->type != STT_FUNC)
+	    h->pointer_equality_needed = 1;
 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
 							   r_symndx,
 							   GOT_NORMAL,
-- 
2.55.0