git: a652357fb59f - main - rtld-elf: Pass HWCAP flags to ifunc resolver functions

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Tue, 13 Jan 2026 17:00:50 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=a652357fb59f03bee85d61814002f9c60ea52340

commit a652357fb59f03bee85d61814002f9c60ea52340
Author:     Sarah Walker <sarah.walker2@arm.com>
AuthorDate: 2026-01-13 14:23:03 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-01-13 15:28:04 +0000

    rtld-elf: Pass HWCAP flags to ifunc resolver functions
    
    Function arguments are based on Section 9.4.1 "GNU C Library IFUNC interface"
    from "System V ABI for the Arm 64-bit Architecture (AArch64)", 2025Q1.
    (https://github.com/ARM-software/abi-aa/releases/download/2025Q1/sysvabi64.pdf)
    
    Reviewed by:    kib, andrew
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D54559
---
 libexec/rtld-elf/aarch64/reloc.c        | 15 +++++++++++++--
 libexec/rtld-elf/aarch64/rtld_machdep.h | 10 +++++++---
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c
index 62d664f8fb80..85f7c1b4022a 100644
--- a/libexec/rtld-elf/aarch64/reloc.c
+++ b/libexec/rtld-elf/aarch64/reloc.c
@@ -444,10 +444,21 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
 	return (target);
 }
 
+__ifunc_arg_t ifunc_arg = {
+	._size = sizeof(__ifunc_arg_t)
+};
+
 void
-ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)] __unused)
+ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)])
 {
-
+	ifunc_arg._hwcap = aux_info[AT_HWCAP] != NULL ?
+	    (aux_info[AT_HWCAP]->a_un.a_val | _IFUNC_ARG_HWCAP) : 0;
+	ifunc_arg._hwcap2 = aux_info[AT_HWCAP2] != NULL ?
+	    aux_info[AT_HWCAP2]->a_un.a_val : 0;
+	ifunc_arg._hwcap3 = aux_info[AT_HWCAP3] != NULL ?
+	    aux_info[AT_HWCAP3]->a_un.a_val : 0;
+	ifunc_arg._hwcap4 = aux_info[AT_HWCAP4] != NULL ?
+	    aux_info[AT_HWCAP4]->a_un.a_val : 0;
 }
 
 /*
diff --git a/libexec/rtld-elf/aarch64/rtld_machdep.h b/libexec/rtld-elf/aarch64/rtld_machdep.h
index d689ae354c49..4b5ad523ee87 100644
--- a/libexec/rtld-elf/aarch64/rtld_machdep.h
+++ b/libexec/rtld-elf/aarch64/rtld_machdep.h
@@ -33,6 +33,7 @@
 
 #include <sys/types.h>
 #include <machine/atomic.h>
+#include <machine/ifunc.h>
 #include <machine/tls.h>
 
 struct Struct_Obj_Entry;
@@ -67,6 +68,8 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
 #define	call_init_pointer(obj, target) \
 	(((InitArrFunc)(target))(main_argc, main_argv, environ))
 
+extern struct __ifunc_arg_t ifunc_arg;
+
 /*
  * Pass zeros into the ifunc resolver so we can change them later. The first
  * 8 arguments on arm64 are passed in registers so make them known values
@@ -74,9 +77,10 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
  * no arguments are passed in, and if this changes later will be able to
  * compare the argument with 0 to see if it is set.
  */
-#define	call_ifunc_resolver(ptr) \
-	(((Elf_Addr (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, \
-	    uint64_t, uint64_t, uint64_t))ptr)(0, 0, 0, 0, 0, 0, 0, 0))
+#define	call_ifunc_resolver(ptr)					      \
+	(((Elf_Addr (*)(uint64_t, const struct __ifunc_arg_t *, uint64_t,     \
+	    uint64_t, uint64_t, uint64_t, uint64_t, uint64_t))ptr)(	      \
+	    ifunc_arg._hwcap, &ifunc_arg, 0, 0, 0, 0, 0, 0))
 
 #define	round(size, align)				\
 	(((size) + (align) - 1) & ~((align) - 1))