[glibc] elf: Defer arch PLT IFUNC relocations in the two-phase relocation split

Adhemerval Zanella via Glibc-cvs <[email protected]> Thu, 16 Jul 2026 20:20:52 +0000 (GMT)
Newsgroups gmane.comp.lib.glibc.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=82a0bf8d33f4be557b36218b446231644d5790e5

commit 82a0bf8d33f4be557b36218b446231644d5790e5
Author: Adhemerval Zanella <[email protected]>
Date:   Tue Jul 14 10:39:57 2026 -0300

    elf: Defer arch PLT IFUNC relocations in the two-phase relocation split
    
    The split introduced by commit 63b31c05a8a does not handle sparc
    and (R_SPARC_JMP_IREL) powerpc64 (ELFv1, R_PPC64_JMP_IREL), which
    are emited in some constructions.  Handle such cases on
    elf_dynamic_is_Rel_irelative.
    
    It fixes elf/tst-ifunc-fault-bindnow and elf/tst-ifunc-fault-lazy on
    sparc64 (powerpc64 emits R_PPC64_IRELATIVE in both cases,
    R_PPC64_JMP_IREL is emitted only when the ifunc is called, not just
    referenced).
    
    Checked with the elf tests on qemu sparc64 and powerpc64.
    
    Tested-by: Andreas K. Hüttel <[email protected]>

Diff:
---
 elf/do-rel.h                           | 8 +++++++-
 sysdeps/powerpc/powerpc64/dl-machine.h | 1 +
 sysdeps/sparc/sparc32/dl-machine.h     | 1 +
 sysdeps/sparc/sparc64/dl-machine.h     | 1 +
 4 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/elf/do-rel.h b/elf/do-rel.h
index c7a8be368f..7702244734 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -45,7 +45,13 @@ elf_dynamic_is_Rel_irelative (const ElfW(Rel) *reloc, const ElfW(Sym) *sym)
   return ((sym != NULL
 	   && ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC
 	   && sym->st_shndx != SHN_UNDEF)
-	  || r_type == ELF_MACHINE_IRELATIVE);
+	  || r_type == ELF_MACHINE_IRELATIVE
+# ifdef ELF_MACHINE_IRELATIVE_PLT
+	  /* Some ports resolve an IFUNC PLT slot for a local resolver with a
+	     dedicated reloc that carries no symboli.  */
+	  || r_type == ELF_MACHINE_IRELATIVE_PLT
+# endif
+	  );
 #else
   return false;
 #endif
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 1f5d7a0170..f1ce639843 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -305,6 +305,7 @@ BODY_PREFIX "_dl_start_user:\n"						\
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT	R_PPC64_JMP_SLOT
 #define ELF_MACHINE_IRELATIVE	R_PPC64_IRELATIVE
+#define ELF_MACHINE_IRELATIVE_PLT R_PPC64_JMP_IREL
 
 /* We define an initialization function to initialize HWCAP/HWCAP2 and
    platform data so it can be copied into the TCB later.  This is called
diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h
index 3771339a04..540e7d24e2 100644
--- a/sysdeps/sparc/sparc32/dl-machine.h
+++ b/sysdeps/sparc/sparc32/dl-machine.h
@@ -157,6 +157,7 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT	R_SPARC_JMP_SLOT
 #define ELF_MACHINE_IRELATIVE	R_SPARC_IRELATIVE
+#define ELF_MACHINE_IRELATIVE_PLT R_SPARC_JMP_IREL
 
 /* Undo the sub %sp, 6*4, %sp; add %sp, 22*4, %o0 below to get at the
    value we want in __libc_stack_end.  */
diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h
index 8a1a38d170..0885f4dc91 100644
--- a/sysdeps/sparc/sparc64/dl-machine.h
+++ b/sysdeps/sparc/sparc64/dl-machine.h
@@ -120,6 +120,7 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT	R_SPARC_JMP_SLOT
 #define ELF_MACHINE_IRELATIVE	R_SPARC_IRELATIVE
+#define ELF_MACHINE_IRELATIVE_PLT R_SPARC_JMP_IREL
 
 /* Set up the loaded object described by L so its unrelocated PLT
    entries will jump to the on-demand fixup code in dl-runtime.c.  */