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, those metadata, used for the previously mentioned
runtime checks, have been provided to the runtime linker via GNU
properties which are stored in the ELF section ".note.gnu.property".
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 (a.k.a. BAs).

This patch adds the support for emitting AArch64 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=[standard|...]
is passed:
- If the assembler support BAs, GCC emits the BAs directives and
no GNU properties.  Note: the static linker will derive the values
of GNU properties from the BAs, and will emit both BAs and GNU
properties into the output object.
- If the assembler do not support them, only .note.gnu.property
section will contain the relevant information.

Bootstrapped on aarch64-none-linux-gnu, and no regression found.

[1]: https://github.com/ARM-software/abi-aa/pull/230

gcc/ChangeLog:

        * config.in: Regenerate.
        * config/aarch64/aarch64-dwarf-metadata.h
        (class aeabi_subsection): New class for BAs.
        * config/aarch64/aarch64-protos.h
        (aarch64_pacret_enabled): New function.
        * config/aarch64/aarch64.cc
        (HAVE_AS_AEABI_BUILD_ATTRIBUTES): New definition.
        (aarch64_file_end_indicate_exec_stack): Emit BAss.
        (aarch64_pacret_enabled): New function.
        (aarch64_start_file):
        * configure: Regenerate.
        * configure.ac: New configure check for BAs support in binutils.

gcc/testsuite/ChangeLog:

        * lib/target-supports.exp:
        (check_effective_target_aarch64_gas_has_build_attributes): New checker.
        * gcc.target/aarch64/build-attributes/aarch64-build-attributes.exp: New 
DejaGNU file.
        * gcc.target/aarch64/build-attributes/build-attribute-bti.c: New test.
        * gcc.target/aarch64/build-attributes/build-attribute-gcs.c: New test.
        * gcc.target/aarch64/build-attributes/build-attribute-pac.c: New test.
        * gcc.target/aarch64/build-attributes/build-attribute-standard.c: New 
test.
        * 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: Srinath Parvathaneni <srinath.parvathan...@arm.com>
---
 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.
 
-- 
2.49.0


Reply via email to