From: Xi Ruoyao Date: Fri, 7 Nov 2025 15:49:22 +0000 (+0800) Subject: LoongArch: Call elf_ifunc_invoke for R_LARCH_IRELATIVE in elf_machine_rela X-Git-Tag: glibc-2.43~235 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f5e68dea9deeb1b0a6bc9ffc84d5e45af445e36;p=thirdparty%2Fglibc.git LoongArch: Call elf_ifunc_invoke for R_LARCH_IRELATIVE in elf_machine_rela When R_LARCH_IRELATIVE is resolved by apply_irel, the ifunc resolver is called via elf_ifunc_invoke so it can read HWCAP from the __ifunc_arg_t argument. But when R_LARCH_IRELATIVE is resolved by elf_machine_rela (it will happen if we dlopen() a shared object containing R_LARCH_IRELATIVE), the ifunc resolver is invoked directly with no or different argument. This causes a segfault if the resolver uses the __ifunc_arg_t. Despite the LoongArch psABI does not specify this argument, IMO it's more convenient to have this argument IMO and per hyrum's rule there may be objects in wild which already relies on this argument (they just didn't blow up because they are not dlopen()ed yet). So make the behavior handling R_LARCH_IRELATIVE of elf_machine_rela same as apply_irel. This fixes BZ #33610. Signed-off-by: Xi Ruoyao --- diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h index a956590ea9..b01d9339a4 100644 --- a/sysdeps/loongarch/dl-machine.h +++ b/sysdeps/loongarch/dl-machine.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -179,7 +180,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], && __glibc_unlikely (ELFW (ST_TYPE) (sym->st_info) == STT_GNU_IFUNC) && __glibc_likely (sym->st_shndx != SHN_UNDEF) && __glibc_likely (!skip_ifunc)) - value = ((ElfW (Addr) (*) (int)) value) (GLRO (dl_hwcap)); + value = elf_ifunc_invoke (value); switch (r_type) { @@ -273,7 +274,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], case R_LARCH_IRELATIVE: value = map->l_addr + reloc->r_addend; if (__glibc_likely (!skip_ifunc)) - value = ((ElfW (Addr) (*) (void)) value) (); + value = elf_ifunc_invoke (value); *addr_field = value; break;