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 <xry111@xry111.site>
#include <sys/asm.h>
#include <dl-tlsdesc.h>
#include <dl-static-tls.h>
+#include <dl-irel.h>
#include <dl-machine-rel.h>
#include <cpu-features.c>
&& __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)
{
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;