From: Srinath Parvathaneni <srinath.parvathan...@arm.com> GCS (Guarded Control Stack, an Armv9.4-a extension) requires some caution at runtime. The runtime linker needs to reason about the compatibility of a set of relocable object files that might not have been compiled with the same compiler. Up until now, GNU properties are stored in a ELF section (.note.gnu.property) and have been used for the previously mentioned runtime checks performed by the linker. However, GNU properties are limited in their expressibility, and a long-term commmitment was taken in the ABI for the Arm architecture [1] to provide build attributes.
This patch adds a first support for AArch64 GCS build attributes. This support includes generating two new assembler directives: .aeabi_subsection and .aeabi_attribute. These directives are generated as per the syntax mentioned in spec "Build Attributes for the ArmĀ® 64-bit Architecture (AArch64)" available at [1]. gcc/configure.ac now includes a new check to test whether the assembler being used to build the toolchain supports these new directives. Two behaviors can be observed when -mbranch-protection=[gcs|standard] is passed: - If the assembler support them, the assembly directives are emitted along the .note.gnu.property section for backward compatibility. - If the assembler does not support them, only .note.gnu.property section will contain the relevant information. This patch needs to be applied on top of GCC's GCS patch series [2]. Bootstrapped on aarch64-none-linux-gnu, and no regression found. [1]: https://github.com/ARM-software/abi-aa/pull/230 [2]: https://gcc.gnu.org/git/?p=gcc.git;a=shortlog;h=refs/vendors/ARM/heads/gcs gcc/ChangeLog: * config.in: Regenerated * config/aarch64/aarch64.cc (HAVE_AS_AEABI_BUILD_ATTRIBUTES): New definition. (aarch64_emit_aeabi_attribute): New function declaration. (aarch64_emit_aeabi_subsection): Likewise. (aarch64_start_file): Emit GCS build attributes. (aarch64_file_end_indicate_exec_stack): Update GCS bit in note.gnu.property section. * configure: Regenerated. * configure.ac: Add a configure check for gcc. gcc/testsuite/ChangeLog: * lib/target-supports.exp: (check_effective_target_aarch64_gas_has_build_attributes): New. * gcc.target/aarch64/build-attributes/build-attribute-gcs.c: New test. * gcc.target/aarch64/build-attributes/build-attribute-standard.c: New test. * gcc.target/aarch64/build-attributes/aarch64-build-attributes.exp: New DejaGNU file. * gcc.target/aarch64/build-attributes/no-build-attribute-bti.c: New test. * gcc.target/aarch64/build-attributes/no-build-attribute-gcs.c: New test. * gcc.target/aarch64/build-attributes/no-build-attribute-pac.c: New test. * gcc.target/aarch64/build-attributes/no-build-attribute-standard.c: New test. Co-Authored-By: Matthieu Longo <matthieu.lo...@arm.com> --- gcc/config.in | 6 +++ gcc/config/aarch64/aarch64.cc | 41 +++++++++++++++++++ gcc/configure | 38 +++++++++++++++++ gcc/configure.ac | 10 +++++ .../aarch64-build-attributes.exp | 35 ++++++++++++++++ .../build-attributes/build-attribute-gcs.c | 12 ++++++ .../build-attribute-standard.c | 12 ++++++ .../build-attributes/no-build-attribute-bti.c | 12 ++++++ .../build-attributes/no-build-attribute-gcs.c | 12 ++++++ .../build-attributes/no-build-attribute-pac.c | 12 ++++++ .../no-build-attribute-standard.c | 12 ++++++ gcc/testsuite/lib/target-supports.exp | 16 ++++++++ 12 files changed, 218 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/build-attributes/aarch64-build-attributes.exp create mode 100644 gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-gcs.c create mode 100644 gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-standard.c create mode 100644 gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-bti.c create mode 100644 gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-gcs.c create mode 100644 gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-pac.c create mode 100644 gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-standard.c diff --git a/gcc/config.in b/gcc/config.in index 7fcabbe5061..0d54141ce30 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -355,6 +355,12 @@ #endif +/* Define if your assembler supports AEABI build attributes. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_AEABI_BUILD_ATTRIBUTES +#endif + + /* Define if your assembler supports architecture modifiers. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_ARCHITECTURE_MODIFIERS diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 0466d6d11eb..90aba0fff88 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -109,6 +109,10 @@ and 1 MOVI/DUP (same size as a call). */ #define MAX_SET_SIZE(speed) (speed ? 256 : 96) +#ifndef HAVE_AS_AEABI_BUILD_ATTRIBUTES +#define HAVE_AS_AEABI_BUILD_ATTRIBUTES 0 +#endif + /* Flags that describe how a function shares certain architectural state with its callers. @@ -24783,6 +24787,33 @@ aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED) asm_fprintf (f, "\t.cfi_b_key_frame\n"); } +/* This function is used to emit an AEABI attribute with tag and its associated + value. We emit the numerical value of the tag and the textual tags as + comment so that anyone reading the assembler output will know which tag is + being set. + example: .aeabi_attribute 3, 1 // Tag_Feature_GCS */ + +void +aarch64_emit_aeabi_attribute (const char *name, uint8_t num, uint8_t val) +{ + asm_fprintf (asm_out_file, "\t.aeabi_attribute %u, %u", num, val); + if (flag_debug_asm) + asm_fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, name); + asm_fprintf (asm_out_file, "\n"); +} + +/* This function is used to emit an AEABI subsection with vendor name, + optional status and value type. + example: .aeabi_subsection .aeabi-feature-and-bits, 1, 0 */ + +void +aarch64_emit_aeabi_subsection (const char *name, uint8_t num, uint8_t val) +{ + asm_fprintf (asm_out_file, "\t.aeabi_subsection %s, %u, %u\n", + name, num, val); +} + + /* Implements TARGET_ASM_FILE_START. Output the assembly header. */ static void @@ -24803,6 +24834,16 @@ aarch64_start_file (void) asm_fprintf (asm_out_file, "\t.arch %s\n", aarch64_last_printed_arch_string.c_str ()); + /* Check whether the current assembly supports gcs build attributes, if not + fallback to .note.gnu.property section. */ +#if (HAVE_AS_AEABI_BUILD_ATTRIBUTES) + if (aarch64_gcs_enabled ()) + { + aarch64_emit_aeabi_subsection (".aeabi-feature-and-bits", 1, 0); + aarch64_emit_aeabi_attribute ("Tag_Feature_GCS", 3, 1); + } +#endif + default_file_start (); } diff --git a/gcc/configure b/gcc/configure index 8ed47b4dadb..62d9ba4fdab 100755 --- a/gcc/configure +++ b/gcc/configure @@ -28035,6 +28035,44 @@ if test $gcc_cv_as_aarch64_picreloc = yes; then $as_echo "#define HAVE_AS_SMALL_PIC_RELOCS 1" >>confdefs.h +fi + + # Check if we have binutils support for AEABI build attributes. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for support of AEABI build attributes" >&5 +$as_echo_n "checking assembler for support of AEABI build attributes... " >&6; } +if ${gcc_cv_as_aarch64_aeabi_build_attributes+:} false; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_as_aarch64_aeabi_build_attributes=no + if test x$gcc_cv_as != x; then + $as_echo ' + .set ATTR_TYPE_uleb128, 0 + .set ATTR_TYPE_asciz, 1 + .set Tag_Feature_foo, 1 + .aeabi_subsection .aeabi-feature-and-bits, 1, ATTR_TYPE_uleb128 + .aeabi_attribute Tag_Feature_foo, 1 + ' > conftest.s + if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + gcc_cv_as_aarch64_aeabi_build_attributes=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_aarch64_aeabi_build_attributes" >&5 +$as_echo "$gcc_cv_as_aarch64_aeabi_build_attributes" >&6; } +if test $gcc_cv_as_aarch64_aeabi_build_attributes = yes; then + +$as_echo "#define HAVE_AS_AEABI_BUILD_ATTRIBUTES 1" >>confdefs.h + fi # Enable Branch Target Identification Mechanism and Return Address diff --git a/gcc/configure.ac b/gcc/configure.ac index 8a5fed516b3..f4b1343ca70 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -4387,6 +4387,16 @@ case "$target" in ldr x0, [[x2, #:gotpage_lo15:globalsym]] ],,[AC_DEFINE(HAVE_AS_SMALL_PIC_RELOCS, 1, [Define if your assembler supports relocs needed by -fpic.])]) + # Check if we have binutils support for AEABI build attributes. + gcc_GAS_CHECK_FEATURE([support of AEABI build attributes], gcc_cv_as_aarch64_aeabi_build_attributes,, + [ + .set ATTR_TYPE_uleb128, 0 + .set ATTR_TYPE_asciz, 1 + .set Tag_Feature_foo, 1 + .aeabi_subsection .aeabi-feature-and-bits, 1, ATTR_TYPE_uleb128 + .aeabi_attribute Tag_Feature_foo, 1 + ],,[AC_DEFINE(HAVE_AS_AEABI_BUILD_ATTRIBUTES, 1, + [Define if your assembler supports AEABI build attributes.])]) # Enable Branch Target Identification Mechanism and Return Address # Signing by default. AC_ARG_ENABLE(standard-branch-protection, diff --git a/gcc/testsuite/gcc.target/aarch64/build-attributes/aarch64-build-attributes.exp b/gcc/testsuite/gcc.target/aarch64/build-attributes/aarch64-build-attributes.exp new file mode 100644 index 00000000000..d0caf81c0cf --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/aarch64-build-attributes.exp @@ -0,0 +1,35 @@ +# Copyright (C) 2024 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't an AArch64 target. +if ![istarget aarch64*-*-*] then { + return +} + +# Load support procs. +load_lib gcc-dg.exp + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ + "" "" + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-gcs.c b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-gcs.c new file mode 100644 index 00000000000..26938d84dab --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-gcs.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target { aarch64*-*-linux* && { aarch64_gas_has_build_attributes } } } } */ +/* { dg-options "-mbranch-protection=gcs -dA" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler "\.aeabi_subsection \.aeabi-feature-and-bits, 1, 0" } } */ +/* { dg-final { scan-assembler "\.aeabi_attribute 3, 1\t\/\/ Tag_Feature_GCS" } } */ +/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" } } */ +/* { dg-final { scan-assembler "\.word\t0x4\t\/\/ GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(GCS\\)" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-standard.c b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-standard.c new file mode 100644 index 00000000000..6a41b52d298 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-standard.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target { aarch64*-*-linux* && aarch64_gas_has_build_attributes } } } */ +/* { dg-options "-mbranch-protection=standard -dA" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler "\.aeabi_subsection \.aeabi-feature-and-bits, 1, 0" } } */ +/* { dg-final { scan-assembler "\.aeabi_attribute 3, 1\t\/\/ Tag_Feature_GCS" } } */ +/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" } } */ +/* { dg-final { scan-assembler "\.word\t0x7\t\/\/ GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(BTI, PAC, GCS\\)" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-bti.c b/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-bti.c new file mode 100644 index 00000000000..013c76e5a2a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-bti.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target { aarch64*-*-linux* && { ! aarch64_gas_has_build_attributes } } } } */ +/* { dg-options "-mbranch-protection=bti -dA" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler-not "\.aeabi_subsection" } } */ +/* { dg-final { scan-assembler-not "\.aeabi_attribute" } } */ +/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" } } */ +/* { dg-final { scan-assembler "\.word\t0x1\t\/\/ GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(BTI\\)" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-gcs.c b/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-gcs.c new file mode 100644 index 00000000000..954bf3ac8c3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-gcs.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target { aarch64*-*-linux* && { ! aarch64_gas_has_build_attributes } } } } */ +/* { dg-options "-mbranch-protection=gcs -dA" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler-not "\.aeabi_subsection" } } */ +/* { dg-final { scan-assembler-not "\.aeabi_attribute" } } */ +/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" } } */ +/* { dg-final { scan-assembler "\.word\t0x4\t\/\/ GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(GCS\\)" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-pac.c b/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-pac.c new file mode 100644 index 00000000000..10195ecdbd9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-pac.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target { aarch64*-*-linux* && { ! aarch64_gas_has_build_attributes } } } } */ +/* { dg-options "-mbranch-protection=pac-ret -dA" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler-not "\.aeabi_subsection" } } */ +/* { dg-final { scan-assembler-not "\.aeabi_attribute" } } */ +/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" } } */ +/* { dg-final { scan-assembler "\.word\t0x2\t\/\/ GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(PAC\\)" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-standard.c b/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-standard.c new file mode 100644 index 00000000000..52cad2863f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/no-build-attribute-standard.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target { aarch64*-*-linux* && { ! aarch64_gas_has_build_attributes } } } } */ +/* { dg-options "-mbranch-protection=standard -dA" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler-not "\.aeabi_subsection" } } */ +/* { dg-final { scan-assembler-not "\.aeabi_attribute" } } */ +/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" } } */ +/* { dg-final { scan-assembler "\.word\t0x7\t\/\/ GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(BTI, PAC, GCS\\)" } } */ \ No newline at end of file diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index d113a08dff7..457aa71e860 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -12031,6 +12031,22 @@ proc check_effective_target_aarch64_tiny { } { } } +# Return 1 if Gas supports AEABI build attributes on AArch64 target +proc check_effective_target_aarch64_gas_has_build_attributes { } { + if { ![istarget aarch64*-*-*] } { + return 0 + } + + return [check_no_compiler_messages aarch64_gas_has_build_attributes object { + /* Assembly */ + .set ATTR_TYPE_uleb128, 0 + .set ATTR_TYPE_asciz, 1 + .set Tag_Feature_foo, 1 + .aeabi_subsection .aeabi-feature-and-bits, 1, ATTR_TYPE_uleb128 + .aeabi_attribute Tag_Feature_foo, 1 + }] +} + # Create functions to check that the AArch64 assembler supports the # various architecture extensions via the .arch_extension pseudo-op. -- 2.47.0