From bc4bc1650b03da18d933eed6524eea474083d98d Mon Sep 17 00:00:00 2001 From: Yury Khrustalev Date: Mon, 24 Nov 2025 11:20:57 +0000 Subject: [PATCH] aarch64: make GCS configure checks aarch64-only We only need to enable GCS tests on AArch64 targets, however previously the configure checks for GCS support in compiler and linker were added for all targets which was not efficient. To enable tests for GCS we need 4 things to be true: - Compiler supports GCS branch protection. - Test compiler supports GCS branch protection. - Linker supports GCS marking of binaries. - The CRT objects provided by the toolchain have GCS marking. To check for the latter, we add new macro to aclocal.m4 that allows to grep output from readelf. We check all four and then put the result in one make variable to simplify checks in makefiles. Reviewed-by: Wilco Dijkstra --- aclocal.m4 | 28 +++++ configure | 98 --------------- configure.ac | 17 --- sysdeps/aarch64/configure | 144 +++++++++++++++++++++++ sysdeps/aarch64/configure.ac | 36 ++++++ sysdeps/unix/sysv/linux/aarch64/Makefile | 4 +- 6 files changed, 210 insertions(+), 117 deletions(-) diff --git a/aclocal.m4 b/aclocal.m4 index cfe9c0b538..5c25a71d8f 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -497,3 +497,31 @@ LIBC_CHECK_TEST_CXX( [LIBC_TRY_CXX_OPTION([$2], [$4], [$5])]) ) ]) + +dnl Check if toolchain supports generating binaries with the required +dnl ELF marking as checked by readelf. +dnl LIBC_CHECK_ELF_PROPERTY([message], [pattern], [action-if-true], [action-if-false]) +AC_DEFUN([LIBC_CHECK_ELF_PROPERTY], +[AC_MSG_CHECKING([$1]) +libc_elf_property=no +cat > conftest.c <&AS_MESSAGE_LOG_FD]) +then + if AC_TRY_COMMAND([LC_ALL=C $READELF -n --wide conftest.so | grep "$2" 1>&AS_MESSAGE_LOG_FD]) + then + libc_elf_property=yes + else + libc_elf_property=no + fi +fi +rm -f conftest* +if test $libc_elf_property = yes; then + $3 +else + $4 +fi +AC_MSG_RESULT($libc_elf_property)]) diff --git a/configure b/configure index d2d83b40c0..09ac6ff760 100755 --- a/configure +++ b/configure @@ -9148,68 +9148,6 @@ printf "%s\n" "$libc_linker_feature" >&6; } config_vars="$config_vars load-address-ldflag = $libc_cv_load_address_ldflag" -# Check if compilers support GCS in branch protection: - -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs" >&5 -printf %s "checking if compiler supports -mbranch-protection=gcs... " >&6; } -if test ${libc_cv_cc_gcs+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; } -then : - libc_cv_cc_gcs=yes -else case e in #( - e) libc_cv_cc_gcs=no ;; -esac -fi ;; -esac -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_gcs" >&5 -printf "%s\n" "$libc_cv_cc_gcs" >&6; } -if test "$TEST_CC" = "$CC"; then - libc_cv_test_cc_gcs=$libc_cv_cc_gcs -else - -saved_CC="$CC" -CC="$TEST_CC" -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs in testing" >&5 -printf %s "checking if compiler supports -mbranch-protection=gcs in testing... " >&6; } -if test ${libc_cv_test_cc_gcs+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; } -then : - libc_cv_test_cc_gcs=yes -else case e in #( - e) libc_cv_test_cc_gcs=no ;; -esac -fi ;; -esac -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_gcs" >&5 -printf "%s\n" "$libc_cv_test_cc_gcs" >&6; } - -CC="$saved_CC" - -fi - -config_vars="$config_vars -have-cc-gcs = $libc_cv_cc_gcs" -config_vars="$config_vars -have-test-cc-gcs = $libc_cv_test_cc_gcs" - # Check if compiler supports -fno-fp-int-builtin-inexact { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -fno-fp-int-builtin-inexact" >&5 @@ -9270,42 +9208,6 @@ fi config_vars="$config_vars config-cflags-no-fp-builtin-inexact = $libc_cv_cc_no_fp_builtin_inexact" -# Check if linker supports GCS marking -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z gcs=always" >&5 -printf %s "checking for linker that supports -z gcs=always... " >&6; } -libc_linker_feature=no -cat > conftest.c <&5 - (eval $ac_try) 2>&5 - ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; } -then - if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-z,gcs=always -nostdlib \ - -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \ - | grep "warning: -z gcs=always ignored" > /dev/null 2>&1; then - true - else - libc_linker_feature=yes - fi -fi -rm -f conftest* -if test $libc_linker_feature = yes; then - libc_cv_ld_gcs=yes -else - libc_cv_ld_gcs=no -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 -printf "%s\n" "$libc_linker_feature" >&6; } -config_vars="$config_vars -have-ld-gcs = $libc_cv_ld_gcs" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports --undefined-version" >&5 printf %s "checking for linker that supports --undefined-version... " >&6; } diff --git a/configure.ac b/configure.ac index 3b9f3688f1..73176840cc 100644 --- a/configure.ac +++ b/configure.ac @@ -2049,18 +2049,6 @@ LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address], [libc_cv_load_address_ldflag=]) LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address_ldflag]) -# Check if compilers support GCS in branch protection: -LIBC_TRY_CC_AND_TEST_CC_OPTION([if compiler supports -mbranch-protection=gcs], - [-Werror -mbranch-protection=gcs], - libc_cv_cc_gcs, - [libc_cv_cc_gcs=yes], - [libc_cv_cc_gcs=no], - libc_cv_test_cc_gcs, - [libc_cv_test_cc_gcs=yes], - [libc_cv_test_cc_gcs=no]) -LIBC_CONFIG_VAR([have-cc-gcs], [$libc_cv_cc_gcs]) -LIBC_CONFIG_VAR([have-test-cc-gcs], [$libc_cv_test_cc_gcs]) - # Check if compiler supports -fno-fp-int-builtin-inexact LIBC_TRY_CC_AND_TEST_CC_OPTION([if compiler supports -fno-fp-int-builtin-inexact], [-Werror -fno-fp-int-builtin-inexact], @@ -2072,11 +2060,6 @@ LIBC_TRY_CC_AND_TEST_CC_OPTION([if compiler supports -fno-fp-int-builtin-inexact [libc_cv_test_cc_no_fp_builtin_inexact=]) LIBC_CONFIG_VAR([config-cflags-no-fp-builtin-inexact], [$libc_cv_cc_no_fp_builtin_inexact]) -# Check if linker supports GCS marking -LIBC_LINKER_FEATURE([-z gcs=always], [-Wl,-z,gcs=always], - [libc_cv_ld_gcs=yes], [libc_cv_ld_gcs=no]) -LIBC_CONFIG_VAR([have-ld-gcs], [$libc_cv_ld_gcs]) - LIBC_LINKER_FEATURE([--undefined-version], [-Wl,--undefined-version], [libc_cv_ld_undefined_version=-Wl,--undefined-version], diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure index f364e65fe7..eecdd324b2 100755 --- a/sysdeps/aarch64/configure +++ b/sysdeps/aarch64/configure @@ -196,3 +196,147 @@ fi libc_cv_support_sframe=yes +# Check if compilers support GCS in branch protection: + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs" >&5 +printf %s "checking if compiler supports -mbranch-protection=gcs... " >&6; } +if test ${libc_cv_cc_gcs+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + libc_cv_cc_gcs=yes +else case e in #( + e) libc_cv_cc_gcs=no ;; +esac +fi ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_gcs" >&5 +printf "%s\n" "$libc_cv_cc_gcs" >&6; } +if test "$TEST_CC" = "$CC"; then + libc_cv_test_cc_gcs=$libc_cv_cc_gcs +else + +saved_CC="$CC" +CC="$TEST_CC" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs in testing" >&5 +printf %s "checking if compiler supports -mbranch-protection=gcs in testing... " >&6; } +if test ${libc_cv_test_cc_gcs+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + libc_cv_test_cc_gcs=yes +else case e in #( + e) libc_cv_test_cc_gcs=no + ;; +esac +fi ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_gcs" >&5 +printf "%s\n" "$libc_cv_test_cc_gcs" >&6; } + +CC="$saved_CC" + +fi + + +# Check if linker supports GCS marking +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z gcs=always" >&5 +printf %s "checking for linker that supports -z gcs=always... " >&6; } +libc_linker_feature=no +cat > conftest.c <&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-z,gcs=always -nostdlib \ + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \ + | grep "warning: -z gcs=always ignored" > /dev/null 2>&1; then + true + else + libc_linker_feature=yes + fi +fi +rm -f conftest* +if test $libc_linker_feature = yes; then + libc_cv_ld_gcs=yes +else + libc_cv_ld_gcs=no + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +printf "%s\n" "$libc_linker_feature" >&6; } + +# Check if toolchain is enabled to support GCS +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if toolchain is enabled to support GCS" >&5 +printf %s "checking if toolchain is enabled to support GCS... " >&6; } +libc_elf_property=no +cat > conftest.c <&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then + if { ac_try='LC_ALL=C $READELF -n --wide conftest.so | grep "AArch64 feature: .*GCS" 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + libc_elf_property=yes + else + libc_elf_property=no + fi +fi +rm -f conftest* +if test $libc_elf_property = yes; then + libc_cv_gcs_supported=yes +else + libc_cv_gcs_supported=no + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_elf_property" >&5 +printf "%s\n" "$libc_elf_property" >&6; } + +if test $libc_cv_cc_gcs = yes && \ + test $libc_cv_test_cc_gcs = yes && \ + test $libc_cv_ld_gcs = yes && \ + test $libc_cv_gcs_supported = yes +then + config_vars="$config_vars +have-test-gcs = yes" +else + config_vars="$config_vars +have-test-gcs = no" +fi + diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac index a9a1b747f1..8b01aa843d 100644 --- a/sysdeps/aarch64/configure.ac +++ b/sysdeps/aarch64/configure.ac @@ -33,3 +33,39 @@ if test $build_mathvec = no; then fi libc_cv_support_sframe=yes + +# Check if compilers support GCS in branch protection: +LIBC_TRY_CC_AND_TEST_CC_OPTION( + [if compiler supports -mbranch-protection=gcs], + [-Werror -mbranch-protection=gcs], + libc_cv_cc_gcs, + [libc_cv_cc_gcs=yes], + [libc_cv_cc_gcs=no], + libc_cv_test_cc_gcs, + [libc_cv_test_cc_gcs=yes], + [libc_cv_test_cc_gcs=no] +) + +# Check if linker supports GCS marking +LIBC_LINKER_FEATURE( + [-z gcs=always], [-Wl,-z,gcs=always], + [libc_cv_ld_gcs=yes], [libc_cv_ld_gcs=no] +) + +# Check if toolchain is enabled to support GCS +LIBC_CHECK_ELF_PROPERTY( + [if toolchain is enabled to support GCS], + [AArch64 feature: .*GCS], + [libc_cv_gcs_supported=yes], + [libc_cv_gcs_supported=no] +) + +if test $libc_cv_cc_gcs = yes && \ + test $libc_cv_test_cc_gcs = yes && \ + test $libc_cv_ld_gcs = yes && \ + test $libc_cv_gcs_supported = yes +then + LIBC_CONFIG_VAR([have-test-gcs], [yes]) +else + LIBC_CONFIG_VAR([have-test-gcs], [no]) +fi diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile index e0b5b7d5b2..6741f8ec00 100644 --- a/sysdeps/unix/sysv/linux/aarch64/Makefile +++ b/sysdeps/unix/sysv/linux/aarch64/Makefile @@ -17,7 +17,7 @@ tests += \ tst-aarch64-pkey \ # tests -ifneq (no,$(findstring no,$(have-cc-gcs) $(have-test-cc-gcs) $(have-ld-gcs))) +ifeq (yes,$(have-test-gcs)) gcs-tests-dynamic = \ tst-gcs-disabled \ @@ -141,7 +141,7 @@ LDFLAGS-tst-gcs-noreturn = -Wl,-z,gcs=always tst-gcs-noreturn-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0 -endif # ifeq ($(have-test-cc-gcs),yes) +endif # ifeq ($(have-test-gcs),yes) endif # ifeq ($(subdir),misc)