#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
#ifndef GCC_AARCH64_ELF_METADATA_H
#define GCC_AARCH64_ELF_METADATA_H
+#include "vec.h"
+
namespace aarch64 {
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_ELF_METADATA_H */
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);
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.
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)
}
/* Emit load exclusive. */
-
static void
aarch64_emit_load_exclusive (machine_mode mode, rtx rval,
rtx mem, rtx model_rtx)
{
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.
$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
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,
--- /dev/null
+# Copyright (C) 2024-2025 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
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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
--- /dev/null
+/* { 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
--- /dev/null
+/* { 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
--- /dev/null
+/* { 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
}
}
+# 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.