---
gcc/config.in | 6 +
gcc/config/aarch64/aarch64-dwarf-metadata.h | 206 ++++++++++++++++++
gcc/config/aarch64/aarch64-protos.h | 1 +
gcc/config/aarch64/aarch64.cc | 49 ++++-
gcc/configure | 37 ++++
gcc/configure.ac | 9 +
.../aarch64-build-attributes.exp | 35 +++
.../build-attributes/build-attribute-bti.c | 11 +
.../build-attributes/build-attribute-gcs.c | 11 +
.../build-attributes/build-attribute-pac.c | 11 +
.../build-attribute-standard.c | 13 ++
.../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 | 15 ++
16 files changed, 443 insertions(+), 9 deletions(-)
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-bti.c
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-pac.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 a79c51adb2b..ab62c1566cb 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-dwarf-metadata.h
b/gcc/config/aarch64/aarch64-dwarf-metadata.h
index ab28283aecb..a5827943714 100644
--- a/gcc/config/aarch64/aarch64-dwarf-metadata.h
+++ b/gcc/config/aarch64/aarch64-dwarf-metadata.h
@@ -21,6 +21,8 @@
#ifndef GCC_AARCH64_DWARF_METADATA_H
#define GCC_AARCH64_DWARF_METADATA_H
+#include "vec.h"
+
namespace aarch64 {
class section_note_gnu_property
@@ -42,6 +44,210 @@ class section_note_gnu_property
unsigned m_feature_1_and;
};
+enum subsection_optionality : uint8_t
+{
+ required = 0x0,
+ optional = 0x1,
+};
+
+enum subsection_val_type : uint8_t
+{
+ uleb128 = 0x0,
+ ntbs = 0x1,
+};
+
+enum BA_TagFeature_t : uint8_t
+{
+ Tag_Feature_BTI = 0,
+ Tag_Feature_PAC = 1,
+ Tag_Feature_GCS = 2,
+};
+
+template <typename T_tag, typename T_val>
+struct aeabi_attribute
+{
+ T_tag tag;
+ T_val value;
+};
+
+template <typename T_tag, typename T_val>
+aeabi_attribute<T_tag, T_val>
+make_aeabi_attribute (T_tag tag, T_val val)
+{
+ return aeabi_attribute<T_tag, T_val>{tag, val};
+}
+
+namespace details {
+
+constexpr const char *
+to_c_str (bool b)
+{
+ return b ? "true" : "false";
+}
+
+constexpr const char *
+to_c_str (const char *s)
+{
+ return s;
+}
+
+constexpr const char *
+to_c_str (subsection_optionality v)
+{
+ return (v == optional ? "optional"
+ : v == required ? "required"
+ : nullptr);
+}
+
+constexpr const char *
+to_c_str (subsection_val_type v)
+{
+ return (v == uleb128 ? "ULEB128"
+ : v == ntbs ? "NTBS"
+ : nullptr);
+}
+
+constexpr const char *
+to_c_str (BA_TagFeature_t feature)
+{
+ return (feature == Tag_Feature_BTI ? "Tag_Feature_BTI"
+ : feature == Tag_Feature_PAC ? "Tag_Feature_PAC"
+ : feature == Tag_Feature_GCS ? "Tag_Feature_GCS"
+ : nullptr);
+}
+
+template <
+ typename T,
+ typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
+>
+constexpr const char *
+aeabi_attr_str_fmt (T)
+{
+ return "\t.aeabi_attribute %s, %u";
+}
+
+constexpr const char *
+aeabi_attr_str_fmt (const char *)
+{
+ return "\t.aeabi_attribute %s, \"%s\"";
+}
+
+template <
+ typename T,
+ typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
+>
+constexpr uint8_t
+aeabi_attr_val_for_fmt (T value)
+{
+ return static_cast<uint8_t>(value);
+}
+
+constexpr const char *
+aeabi_attr_val_for_fmt (const char *s)
+{
+ return s;
+}
+
+template <typename T_tag, typename T_val>
+void
+write (FILE *out_file, aeabi_attribute<T_tag, T_val> const &attr)
+{
+ asm_fprintf (out_file, aeabi_attr_str_fmt (T_val{}),
+ to_c_str (attr.tag), aeabi_attr_val_for_fmt (attr.value));
+ if (flag_debug_asm)
+ asm_fprintf (out_file, "\t%s %s: %s", ASM_COMMENT_START,
+ to_c_str (attr.tag), to_c_str (attr.value));
+ asm_fprintf (out_file, "\n");
+}
+
+template <
+ typename T,
+ typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
+>
+constexpr subsection_val_type
+deduce_attr_av_type (T)
+{
+ return subsection_val_type::uleb128;
+}
+
+constexpr subsection_val_type
+deduce_attr_av_type (const char *)
+{
+ return subsection_val_type::ntbs;
+}
+
+} // namespace details
+
+/* AEABI subsections can be public or private. A subsection is public if it is
+ prefixed with "aeabi", private otherwise. The header of an AEABI subsection
+ is composed of a name (usually a vendor name), an optionality status
(optional
+ or required), and the expected type of its associated attributes (ULEB128 or
+ NTBS). Note: The attributes in the same subsection have all the same type.
+ An attribute is composed of a tag identifier (ULEB128), and its value
(ULEB128
+ or NTBS).
+
+ Syntax:
+ .aeabi_subsection NameOfTheSubsection: string (=NTBS),
+ Optional: boolean (=ULEB128),
+ AttributeValueType: enum{ULEB128, NTBS} (=ULEB128)
+ [
+ .aeabi_attribute TagIdentifier: ULEB128,
+ TagValue: Variant[ULEB128|NTBS]
+ ]*
+
+ Example:
+ .aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
+ .aeabi_attribute Tag_Feature_GCS, 1 // Tag_Feature_GCS: true
+
+ Note: The textual representations of the tag and its value are emitted as a
+ comment along their numerical representations to annotate the assembler
+ output when the developer flag '-dA' is provided. */
+template <
+ typename T_tag, /* The type of a tag. */
+ typename T_val, /* The type of a value. */
+ size_t N = 0 /* The number of expected attributes if we know it. */
+>
+class aeabi_subsection
+{
+ public:
+ aeabi_subsection (const char *name, bool optional)
+ : m_name (name),
+ m_optionality (optional
+ ? subsection_optionality::optional
+ : subsection_optionality::required),
+ m_avtype (details::deduce_attr_av_type (T_val{}))
+ {}
+
+ /* Append an attribute to the subsection. */
+ void append (aeabi_attribute<T_tag, T_val> &&attr)
+ {
+ m_attributes.quick_push (std::move (attr));
+ }
+
+ /* Write the data to the assembly file. */
+ void write (FILE *out_file) const
+ {
+ asm_fprintf (out_file, "\n\t.aeabi_subsection %s, %s, %s\n",
+ m_name, details::to_c_str (m_optionality),
+ details::to_c_str (m_avtype));
+
+ for (auto const &attr : m_attributes)
+ details::write (out_file, attr);
+ }
+
+ /* Indicate if the subsection is empty. */
+ bool empty () const
+ {
+ return m_attributes.is_empty ();
+ }
+
+ private:
+ const char *m_name;
+ subsection_optionality m_optionality;
+ subsection_val_type m_avtype;
+ auto_vec<aeabi_attribute<T_tag, T_val>, N> m_attributes;
+};
+
} // namespace aarch64
#endif /* GCC_AARCH64_DWARF_METADATA_H */
diff --git a/gcc/config/aarch64/aarch64-protos.h
b/gcc/config/aarch64/aarch64-protos.h
index 8f37e56d440..b1ce42fc396 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -1267,6 +1267,7 @@ void aarch64_expand_reversed_crc_using_pmull
(scalar_mode, scalar_mode, rtx *);
void aarch64_expand_fp_spaceship (rtx, rtx, rtx, rtx);
+extern bool aarch64_pacret_enabled ();
extern bool aarch64_gcs_enabled ();
extern unsigned aarch64_data_alignment (const_tree exp, unsigned align);
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index fe5f2c1250f..99981e6024c 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.
@@ -8757,6 +8761,13 @@ aarch_bti_j_insn_p (rtx_insn *insn)
return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_BTI_J;
}
+/* Return TRUE if Pointer Authentication for the return address is enabled. */
+bool
+aarch64_pacret_enabled (void)
+{
+ return (aarch_ra_sign_scope != AARCH_FUNCTION_NONE);
+}
+
/* Return TRUE if Guarded Control Stack is enabled. */
bool
aarch64_gcs_enabled (void)
@@ -25356,7 +25367,6 @@ aarch64_start_file (void)
}
/* Emit load exclusive. */
-
static void
aarch64_emit_load_exclusive (machine_mode mode, rtx rval,
rtx mem, rtx model_rtx)
@@ -29992,16 +30002,37 @@ aarch64_file_end_indicate_exec_stack ()
{
file_end_indicate_exec_stack ();
- aarch64::section_note_gnu_property gnu_properties;
+ /* Check whether the current assembler supports AEABI build attributes, if
+ not fallback to .note.gnu.property section. */
+ if (HAVE_AS_AEABI_BUILD_ATTRIBUTES)
+ {
+ using namespace aarch64;
+ aeabi_subsection<BA_TagFeature_t, bool, 3>
+ aeabi_subsec ("aeabi_feature_and_bits", true);
- if (aarch_bti_enabled ())
- gnu_properties.bti_enabled ();
- if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
- gnu_properties.pac_enabled ();
- if (aarch64_gcs_enabled ())
- gnu_properties.gcs_enabled ();
+ aeabi_subsec.append (
+ make_aeabi_attribute (Tag_Feature_BTI, aarch_bti_enabled ()));
+ aeabi_subsec.append (
+ make_aeabi_attribute (Tag_Feature_PAC, aarch64_pacret_enabled ()));
+ aeabi_subsec.append (
+ make_aeabi_attribute (Tag_Feature_GCS, aarch64_gcs_enabled ()));
- gnu_properties.write ();
+ if (!aeabi_subsec.empty ())
+ aeabi_subsec.write (asm_out_file);
+ }
+ else
+ {
+ aarch64::section_note_gnu_property gnu_properties;
+
+ if (aarch_bti_enabled ())
+ gnu_properties.bti_enabled ();
+ if (aarch64_pacret_enabled ())
+ gnu_properties.pac_enabled ();
+ if (aarch64_gcs_enabled ())
+ gnu_properties.gcs_enabled ();
+
+ gnu_properties.write ();
+ }
}
/* Helper function for straight line speculation.
diff --git a/gcc/configure b/gcc/configure
index 776b0628c60..f056cfe9677 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -28247,6 +28247,43 @@ 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 '
+ .aeabi_subsection aeabi_feature_and_bits, optional, ULEB128
+ .aeabi_attribute Tag_Feature_BTI, 1
+ .aeabi_attribute Tag_Feature_PAC, 1
+ .aeabi_attribute Tag_Feature_GCS, 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 b6db9edfc83..58bf63f8be9 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -4467,6 +4467,15 @@ 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,,
+ [
+ .aeabi_subsection aeabi_feature_and_bits, optional, ULEB128
+ .aeabi_attribute Tag_Feature_BTI, 1
+ .aeabi_attribute Tag_Feature_PAC, 1
+ .aeabi_attribute Tag_Feature_GCS, 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-bti.c
b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-bti.c
new file mode 100644
index 00000000000..363a6de56ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-bti.c
@@ -0,0 +1,11 @@
+/* { 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 "\.aeabi_subsection aeabi_feature_and_bits,
optional, ULEB128" } } */
+/* { dg-final { scan-assembler "\.aeabi_attribute Tag_Feature_BTI, 1\t\/\/
Tag_Feature_BTI: true" } } */
+/* { dg-final { scan-assembler-not "\.section\t\.note\.gnu\.property" } } */
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..5368915a133
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-gcs.c
@@ -0,0 +1,11 @@
+/* { 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,
optional, ULEB128" } } */
+/* { dg-final { scan-assembler "\.aeabi_attribute Tag_Feature_GCS, 1\t\/\/
Tag_Feature_GCS: true" } } */
+/* { dg-final { scan-assembler-not "\.section\t\.note\.gnu\.property" } } */
diff --git
a/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-pac.c
b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-pac.c
new file mode 100644
index 00000000000..79d36c1af2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-pac.c
@@ -0,0 +1,11 @@
+/* { 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 "\.aeabi_subsection aeabi_feature_and_bits,
optional, ULEB128" } } */
+/* { dg-final { scan-assembler "\.aeabi_attribute Tag_Feature_PAC, 1\t\/\/
Tag_Feature_PAC: true" } } */
+/* { dg-final { scan-assembler-not "\.section\t\.note\.gnu\.property" } } */
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..7ffa717c63c
--- /dev/null
+++
b/gcc/testsuite/gcc.target/aarch64/build-attributes/build-attribute-standard.c
@@ -0,0 +1,13 @@
+/* { 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,
optional, ULEB128" } } */
+/* { dg-final { scan-assembler "\.aeabi_attribute Tag_Feature_BTI, 1\t\/\/
Tag_Feature_BTI: true" } } */
+/* { dg-final { scan-assembler "\.aeabi_attribute Tag_Feature_PAC, 1\t\/\/
Tag_Feature_PAC: true" } } */
+/* { dg-final { scan-assembler "\.aeabi_attribute Tag_Feature_GCS, 1\t\/\/
Tag_Feature_GCS: true" } } */
+/* { dg-final { scan-assembler-not "\.section\t\.note\.gnu\.property" } } */
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 dfffe3adfbd..82e5c31e499 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -12442,6 +12442,21 @@ 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 */
+ .aeabi_subsection aeabi_feature_and_bits, optional, ULEB128
+ .aeabi_attribute Tag_Feature_BTI, 1
+ .aeabi_attribute Tag_Feature_PAC, 1
+ .aeabi_attribute Tag_Feature_GCS, 1
+ }]
+}
+
# Create functions to check that the AArch64 assembler supports the
# various architecture extensions via the .arch_extension pseudo-op.