git: 5eec3531204b - main - libc/csu: Pass HWCAP flags to ifunc resolver functions

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

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

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

    libc/csu: 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:    andrew
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D54599
---
 lib/libc/csu/aarch64/reloc.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/lib/libc/csu/aarch64/reloc.c b/lib/libc/csu/aarch64/reloc.c
index 4ba7920bcb07..77e8a38176ce 100644
--- a/lib/libc/csu/aarch64/reloc.c
+++ b/lib/libc/csu/aarch64/reloc.c
@@ -25,17 +25,42 @@
  */
 
 #include <sys/cdefs.h>
+#include <machine/ifunc.h>
+
+static __ifunc_arg_t ifunc_arg;
 
 static void
-ifunc_init(const Elf_Auxinfo *aux __unused)
+ifunc_init(const Elf_Auxinfo *aux)
 {
+	ifunc_arg._size = sizeof(ifunc_arg);
+	ifunc_arg._hwcap = 0;
+	ifunc_arg._hwcap2 = 0;
+	ifunc_arg._hwcap3 = 0;
+	ifunc_arg._hwcap4 = 0;
+
+	for (;  aux->a_type != AT_NULL; aux++) {
+		switch (aux->a_type) {
+		case AT_HWCAP:
+			ifunc_arg._hwcap = aux->a_un.a_val | _IFUNC_ARG_HWCAP;
+			break;
+		case AT_HWCAP2:
+			ifunc_arg._hwcap2 = aux->a_un.a_val;
+			break;
+		case AT_HWCAP3:
+			ifunc_arg._hwcap3 = aux->a_un.a_val;
+			break;
+		case AT_HWCAP4:
+			ifunc_arg._hwcap4 = aux->a_un.a_val;
+			break;
+		}
+	}
 }
 
 static void
 crt1_handle_rela(const Elf_Rela *r)
 {
 	typedef Elf_Addr (*ifunc_resolver_t)(
-	    uint64_t, uint64_t, uint64_t, uint64_t,
+	    uint64_t, const __ifunc_arg_t *, uint64_t, uint64_t,
 	    uint64_t, uint64_t, uint64_t, uint64_t);
 	Elf_Addr *ptr, *where, target;
 
@@ -43,7 +68,7 @@ crt1_handle_rela(const Elf_Rela *r)
 	case R_AARCH64_IRELATIVE:
 		ptr = (Elf_Addr *)r->r_addend;
 		where = (Elf_Addr *)r->r_offset;
-		target = ((ifunc_resolver_t)ptr)(0, 0, 0, 0, 0, 0, 0, 0);
+		target = ((ifunc_resolver_t)ptr)(ifunc_arg._hwcap, &ifunc_arg, 0, 0, 0, 0, 0, 0);
 		*where = target;
 		break;
 	}