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

H.J. Lu hjl.tools@gmail.com
Fri Oct 17 22:34:17 GMT 2025


On Sat, Oct 18, 2025 at 3:53 AM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
> clang does correctly propagate the no_stack_protector attribute for

Did you mean "does" or "doesn't"?

> 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
>


-- 
H.J.


More information about the Libc-alpha mailing list