[PATCH 31/59] x86: Use __always_inline on ifunc auxiliary functions

Adhemerval Zanella adhemerval.zanella@linaro.org
Fri Oct 17 19:13:06 GMT 2025


clang does correctly propagate the no_stack_protector attribute for
inline function used in ifunc selectors.  For instance, the exp function
is expanded as:

  static inline void *
  ieee754_exp_ifunc_selector (void)
  {
    [...]
  }

  extern __typeof (__redirect_ieee754_exp) __ieee754_exp
    __attribute__ ((ifunc ("__ieee754_exp" "_ifunc")));

  static __attribute__((no_stack_protector)) __typeof (__redirect_ieee754_exp) *i
  __ieee754_exp_ifunc (void)
  {
    __typeof (__redirect_ieee754_exp) *res = ieee754_exp_ifunc_selector ();
    return res;
  };

The ifunc selection ended being compiled with -fstack-protector, and
with debug function set to the ifunc selector
(ieee754_exp_ifunc_selector) auxiliary function instead of the
selector itself.

The ifunc selector are called early, before TCB is setup, which
causes SIGSEGV for statically linked binaries.

To fix it use __always_inline instead of inline.  It should not change
code generation on gcc and it fixes the code generation issue on
clang.  It also fixes function debug information.
---
 sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h | 2 +-
 sysdeps/x86_64/fpu/multiarch/ifunc-fma.h      | 2 +-
 sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h     | 2 +-
 sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h   | 2 +-
 sysdeps/x86_64/multiarch/ifunc-avx2.h         | 2 +-
 sysdeps/x86_64/multiarch/ifunc-evex.h         | 2 +-
 sysdeps/x86_64/multiarch/ifunc-memcmp.h       | 2 +-
 sysdeps/x86_64/multiarch/ifunc-memmove.h      | 2 +-
 sysdeps/x86_64/multiarch/ifunc-memset.h       | 2 +-
 sysdeps/x86_64/multiarch/ifunc-sse4_2.h       | 2 +-
 sysdeps/x86_64/multiarch/ifunc-strcasecmp.h   | 2 +-
 sysdeps/x86_64/multiarch/ifunc-strcpy.h       | 2 +-
 sysdeps/x86_64/multiarch/ifunc-strncpy.h      | 2 +-
 sysdeps/x86_64/multiarch/ifunc-wcs.h          | 1 +
 sysdeps/x86_64/multiarch/ifunc-wcslen.h       | 1 +
 sysdeps/x86_64/multiarch/ifunc-wmemset.h      | 1 +
 sysdeps/x86_64/multiarch/strchr.c             | 2 +-
 sysdeps/x86_64/multiarch/strcmp.c             | 2 +-
 sysdeps/x86_64/multiarch/strncmp.c            | 2 +-
 sysdeps/x86_64/multiarch/strstr.c             | 2 +-
 sysdeps/x86_64/multiarch/wcscpy.c             | 2 +-
 21 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h b/sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h
index 4c1a851cff..0e0e06050c 100644
--- a/sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h
+++ b/sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h
@@ -24,7 +24,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (avx) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (fma) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (fma4) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features* cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-fma.h b/sysdeps/x86_64/fpu/multiarch/ifunc-fma.h
index 750c8ce2bf..63201a70cd 100644
--- a/sysdeps/x86_64/fpu/multiarch/ifunc-fma.h
+++ b/sysdeps/x86_64/fpu/multiarch/ifunc-fma.h
@@ -21,7 +21,7 @@
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (fma) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features* cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h b/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h
index 724b235cbb..76297ce048 100644
--- a/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h
+++ b/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h
@@ -23,7 +23,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (fma) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (fma4) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features* cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h b/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h
index 6292879112..77f30b7429 100644
--- a/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h
+++ b/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h
@@ -21,7 +21,7 @@
 extern __typeof (REDIRECT_NAME) OPTIMIZE (c) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse41) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features* cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-avx2.h b/sysdeps/x86_64/multiarch/ifunc-avx2.h
index 47d2f67c1a..b8efd11446 100644
--- a/sysdeps/x86_64/multiarch/ifunc-avx2.h
+++ b/sysdeps/x86_64/multiarch/ifunc-avx2.h
@@ -30,7 +30,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2_rtm) attribute_hidden;
 
 extern __typeof (REDIRECT_NAME) OPTIMIZE (GENERIC) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-evex.h b/sysdeps/x86_64/multiarch/ifunc-evex.h
index 49afda099e..406da1fd3a 100644
--- a/sysdeps/x86_64/multiarch/ifunc-evex.h
+++ b/sysdeps/x86_64/multiarch/ifunc-evex.h
@@ -27,7 +27,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2_rtm) attribute_hidden;
 
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-memcmp.h b/sysdeps/x86_64/multiarch/ifunc-memcmp.h
index fdf74b6975..697d25b087 100644
--- a/sysdeps/x86_64/multiarch/ifunc-memcmp.h
+++ b/sysdeps/x86_64/multiarch/ifunc-memcmp.h
@@ -26,7 +26,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2_movbe_rtm) attribute_hidden;
 
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-memmove.h b/sysdeps/x86_64/multiarch/ifunc-memmove.h
index de0ac73a2a..f8e134d4af 100644
--- a/sysdeps/x86_64/multiarch/ifunc-memmove.h
+++ b/sysdeps/x86_64/multiarch/ifunc-memmove.h
@@ -48,7 +48,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2_unaligned)
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2_unaligned_erms)
   attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-memset.h b/sysdeps/x86_64/multiarch/ifunc-memset.h
index 9f265fe5c5..1316396e86 100644
--- a/sysdeps/x86_64/multiarch/ifunc-memset.h
+++ b/sysdeps/x86_64/multiarch/ifunc-memset.h
@@ -53,7 +53,7 @@ prefer_erms_nt_impl (const struct cpu_features *cpu_features)
 	 || !CPU_FEATURES_ARCH_P (cpu_features, Avoid_Non_Temporal_Memset);
 }
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-sse4_2.h b/sysdeps/x86_64/multiarch/ifunc-sse4_2.h
index 1cea833c99..c7866d7fb9 100644
--- a/sysdeps/x86_64/multiarch/ifunc-sse4_2.h
+++ b/sysdeps/x86_64/multiarch/ifunc-sse4_2.h
@@ -22,7 +22,7 @@
 extern __typeof (REDIRECT_NAME) OPTIMIZE (generic) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse42) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features* cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
index d9b217d2d5..1da1aa8258 100644
--- a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
+++ b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
@@ -28,7 +28,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (sse42) attribute_hidden;
 
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-strcpy.h b/sysdeps/x86_64/multiarch/ifunc-strcpy.h
index c1bb546acf..48875d409d 100644
--- a/sysdeps/x86_64/multiarch/ifunc-strcpy.h
+++ b/sysdeps/x86_64/multiarch/ifunc-strcpy.h
@@ -30,7 +30,7 @@ extern __typeof (REDIRECT_NAME)
 
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-strncpy.h b/sysdeps/x86_64/multiarch/ifunc-strncpy.h
index fa0a2bcd41..271223d2e8 100644
--- a/sysdeps/x86_64/multiarch/ifunc-strncpy.h
+++ b/sysdeps/x86_64/multiarch/ifunc-strncpy.h
@@ -27,7 +27,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2_rtm) attribute_hidden;
 extern __typeof (REDIRECT_NAME)
     OPTIMIZE (sse2_unaligned) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-wcs.h b/sysdeps/x86_64/multiarch/ifunc-wcs.h
index c644cf34c1..2771b54ae2 100644
--- a/sysdeps/x86_64/multiarch/ifunc-wcs.h
+++ b/sysdeps/x86_64/multiarch/ifunc-wcs.h
@@ -32,6 +32,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (GENERIC) attribute_hidden;
 
 static inline void *
+inhibit_stack_protector
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-wcslen.h b/sysdeps/x86_64/multiarch/ifunc-wcslen.h
index 5a5f6ce0c0..ddda3f54fb 100644
--- a/sysdeps/x86_64/multiarch/ifunc-wcslen.h
+++ b/sysdeps/x86_64/multiarch/ifunc-wcslen.h
@@ -33,6 +33,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (sse4_1) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (GENERIC) attribute_hidden;
 
 static inline void *
+inhibit_stack_protector
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/ifunc-wmemset.h b/sysdeps/x86_64/multiarch/ifunc-wmemset.h
index f95cca6ae5..6abe6fafc2 100644
--- a/sysdeps/x86_64/multiarch/ifunc-wmemset.h
+++ b/sysdeps/x86_64/multiarch/ifunc-wmemset.h
@@ -29,6 +29,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2_unaligned_rtm)
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2_unaligned) attribute_hidden;
 
 static inline void *
+inhibit_stack_protector
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/strchr.c b/sysdeps/x86_64/multiarch/strchr.c
index 59ceacd57d..735aeffd53 100644
--- a/sysdeps/x86_64/multiarch/strchr.c
+++ b/sysdeps/x86_64/multiarch/strchr.c
@@ -34,7 +34,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2_rtm) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2_no_bsf) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/strcmp.c b/sysdeps/x86_64/multiarch/strcmp.c
index 451a2ce388..fd43b916ab 100644
--- a/sysdeps/x86_64/multiarch/strcmp.c
+++ b/sysdeps/x86_64/multiarch/strcmp.c
@@ -39,7 +39,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 
 
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/strncmp.c b/sysdeps/x86_64/multiarch/strncmp.c
index d3c36d4890..24d368b276 100644
--- a/sysdeps/x86_64/multiarch/strncmp.c
+++ b/sysdeps/x86_64/multiarch/strncmp.c
@@ -35,7 +35,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (sse42) attribute_hidden;
 
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/strstr.c b/sysdeps/x86_64/multiarch/strstr.c
index 339e7b8501..b92f752402 100644
--- a/sysdeps/x86_64/multiarch/strstr.c
+++ b/sysdeps/x86_64/multiarch/strstr.c
@@ -37,7 +37,7 @@ extern __typeof (__redirect_strstr) __strstr_sse2_unaligned attribute_hidden;
 
 #include "init-arch.h"
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/multiarch/wcscpy.c b/sysdeps/x86_64/multiarch/wcscpy.c
index 90f3382ce1..460e0e268f 100644
--- a/sysdeps/x86_64/multiarch/wcscpy.c
+++ b/sysdeps/x86_64/multiarch/wcscpy.c
@@ -34,7 +34,7 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (ssse3) attribute_hidden;
 
 extern __typeof (REDIRECT_NAME) OPTIMIZE (generic) attribute_hidden;
 
-static inline void *
+static __always_inline void *
 IFUNC_SELECTOR (void)
 {
   const struct cpu_features* cpu_features = __get_cpu_features ();
-- 
2.43.0



More information about the Libc-alpha mailing list