[PATCH] aarch64: Fix static PIE CPU feature detection (BZ 34205)
Adhemerval Zanella
adhemerval.zanella@linaro.org
Fri Jun 5 13:43:17 GMT 2026
ARCH_INIT_CPU_FEATURES is called from __libc_start_main before
_dl_relocate_static_pie, so any code it runs must not rely on
relocations being applied yet. Two issues break this under static PIE:
1. The cpu_list table held 'const char *name' members, whose
addresses are not link-time constants under PIE and thus require
base-relative relocations that are not yet in place. Replace the
array of structs with a flat NUL-separated name string and a
parallel midr array, removing the pointer relocations.
2. tunable_strcmp pulls in memcmp, which is an IFUNC and is likewise
unresolved at this point. Redirect memcmp to __memcmp_generic in
the aarch64 dl-symbol-redir-ifunc.h and include it from
csu/libc-start.c.
Checked on aarch64-linux-gnu.
---
csu/libc-start.c | 1 +
.../aarch64/multiarch/dl-symbol-redir-ifunc.h | 1 +
sysdeps/unix/sysv/linux/aarch64/Makefile | 10 ++++++
.../unix/sysv/linux/aarch64/cpu-features.c | 35 ++++++++++---------
.../aarch64/tst-cpu-tunable-static-pie.c | 26 ++++++++++++++
5 files changed, 57 insertions(+), 16 deletions(-)
create mode 100644 sysdeps/unix/sysv/linux/aarch64/tst-cpu-tunable-static-pie.c
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 03d770ef15..28af53f7db 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -59,6 +59,7 @@ uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
#ifndef SHARED
# include <link.h>
# include <dl-irel.h>
+# include <dl-symbol-redir-ifunc.h>
# ifdef ELF_MACHINE_IRELA
# define IREL_T ElfW(Rela)
diff --git a/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h
index 26fcd1977e..0910e321d2 100644
--- a/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h
+++ b/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h
@@ -24,6 +24,7 @@ asm ("strlen = __strlen_generic");
#ifndef SHARED
asm ("memcpy = __memcpy_generic");
asm ("memmove = __memmove_generic");
+asm ("memcmp = __memcmp_generic");
#endif
#endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile
index 7e17e7741f..d1fcb48aa2 100644
--- a/sysdeps/unix/sysv/linux/aarch64/Makefile
+++ b/sysdeps/unix/sysv/linux/aarch64/Makefile
@@ -9,6 +9,16 @@ modules-names += \
LDFLAGS-tst-tlsdesc-pac = -rdynamic
$(objpfx)tst-tlsdesc-pac.out: $(objpfx)tst-tlsdesc-pac-mod.so
+
+ifeq (yes,$(enable-static-pie))
+tests += \
+ tst-cpu-tunable-static-pie \
+ # tests
+tests-static += \
+ tst-cpu-tunable-static-pie \
+ # tests-static
+tst-cpu-tunable-static-pie-TUNABLES = glibc.cpu.name=generic
+endif
endif
ifeq ($(subdir),misc)
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
index 0bc4addb2a..9a87332ac4 100644
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
@@ -33,29 +33,32 @@
to see when pointer have been correctly tagged. */
#define MTE_ALLOWED_TAGS (0xfffe << PR_MTE_TAG_SHIFT)
-struct cpu_list
-{
- const char *name;
- size_t len;
- uint64_t midr;
+static const char cpu_list_name[] = {
+ "kunpeng920\0"
+ "kunpeng950\0"
+ "a64fx\0"
+ "generic\0",
};
-static const struct cpu_list cpu_list[] =
-{
-#define CPU_LIST_ENTRY(__str, __num) { __str, sizeof (__str) - 1, __num }
- CPU_LIST_ENTRY ("kunpeng920", 0x481FD010),
- CPU_LIST_ENTRY ("kunpeng950", 0x480FD060),
- CPU_LIST_ENTRY ("a64fx", 0x460F0010),
- CPU_LIST_ENTRY ("generic", 0x0),
+static const uint64_t cpu_list_midr[] = {
+ 0x481FD010,
+ 0x480FD060,
+ 0x460F0010,
+ 0x0,
};
static uint64_t
get_midr_from_mcpu (const struct tunable_str_t *mcpu)
{
- for (int i = 0; i < array_length (cpu_list); i++)
- if (tunable_strcmp (mcpu, cpu_list[i].name, cpu_list[i].len))
- return cpu_list[i].midr;
-
+ const char *name = cpu_list_name;
+ size_t offset = 0;
+ for (int i = 0; i < array_length (cpu_list_midr); i++)
+ {
+ size_t len = strlen (name);
+ if (tunable_strcmp (mcpu, cpu_list_name + offset, len))
+ return cpu_list_midr[i];
+ offset += len;
+ }
return UINT64_MAX;
}
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-cpu-tunable-static-pie.c b/sysdeps/unix/sysv/linux/aarch64/tst-cpu-tunable-static-pie.c
new file mode 100644
index 0000000000..561eaf3bdb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-cpu-tunable-static-pie.c
@@ -0,0 +1,26 @@
+/* Test that the glibc.cpu.name tunable is parsed correctly during early
+ startup of a static PIE binary (bug 34205).
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+static int
+do_test (void)
+{
+ return 0;
+}
+
+#include <support/test-driver.c>
--
2.43.0
More information about the Libc-alpha
mailing list