Skip to content

Commit 98f5547

Browse files
Matthieu Longosripar01
andcommitted
aarch64: add support for AEABI Build Attributes
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]: ARM-software/abi-aa#230 gcc/ChangeLog: * config.in: Regenerate. * config/aarch64/aarch64-elf-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): Indent. * 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.parvathaneni@arm.com>
1 parent 0b4a3c1 commit 98f5547

16 files changed

+443
-9
lines changed

gcc/config.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,12 @@
355355
#endif
356356

357357

358+
/* Define if your assembler supports AEABI build attributes. */
359+
#ifndef USED_FOR_TARGET
360+
#undef HAVE_AS_AEABI_BUILD_ATTRIBUTES
361+
#endif
362+
363+
358364
/* Define if your assembler supports architecture modifiers. */
359365
#ifndef USED_FOR_TARGET
360366
#undef HAVE_AS_ARCHITECTURE_MODIFIERS

gcc/config/aarch64/aarch64-elf-metadata.h

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#ifndef GCC_AARCH64_ELF_METADATA_H
2222
#define GCC_AARCH64_ELF_METADATA_H
2323

24+
#include "vec.h"
25+
2426
namespace aarch64 {
2527

2628
class section_note_gnu_property
@@ -42,6 +44,210 @@ class section_note_gnu_property
4244
unsigned m_feature_1_and;
4345
};
4446

47+
enum subsection_optionality : uint8_t
48+
{
49+
required = 0x0,
50+
optional = 0x1,
51+
};
52+
53+
enum subsection_val_type : uint8_t
54+
{
55+
uleb128 = 0x0,
56+
ntbs = 0x1,
57+
};
58+
59+
enum BA_TagFeature_t : uint8_t
60+
{
61+
Tag_Feature_BTI = 0,
62+
Tag_Feature_PAC = 1,
63+
Tag_Feature_GCS = 2,
64+
};
65+
66+
template <typename T_tag, typename T_val>
67+
struct aeabi_attribute
68+
{
69+
T_tag tag;
70+
T_val value;
71+
};
72+
73+
template <typename T_tag, typename T_val>
74+
aeabi_attribute<T_tag, T_val>
75+
make_aeabi_attribute (T_tag tag, T_val val)
76+
{
77+
return aeabi_attribute<T_tag, T_val>{tag, val};
78+
}
79+
80+
namespace details {
81+
82+
constexpr const char *
83+
to_c_str (bool b)
84+
{
85+
return b ? "true" : "false";
86+
}
87+
88+
constexpr const char *
89+
to_c_str (const char *s)
90+
{
91+
return s;
92+
}
93+
94+
constexpr const char *
95+
to_c_str (subsection_optionality v)
96+
{
97+
return (v == optional ? "optional"
98+
: v == required ? "required"
99+
: nullptr);
100+
}
101+
102+
constexpr const char *
103+
to_c_str (subsection_val_type v)
104+
{
105+
return (v == uleb128 ? "ULEB128"
106+
: v == ntbs ? "NTBS"
107+
: nullptr);
108+
}
109+
110+
constexpr const char *
111+
to_c_str (BA_TagFeature_t feature)
112+
{
113+
return (feature == Tag_Feature_BTI ? "Tag_Feature_BTI"
114+
: feature == Tag_Feature_PAC ? "Tag_Feature_PAC"
115+
: feature == Tag_Feature_GCS ? "Tag_Feature_GCS"
116+
: nullptr);
117+
}
118+
119+
template <
120+
typename T,
121+
typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
122+
>
123+
constexpr const char *
124+
aeabi_attr_str_fmt (T)
125+
{
126+
return "\t.aeabi_attribute %s, %u";
127+
}
128+
129+
constexpr const char *
130+
aeabi_attr_str_fmt (const char *)
131+
{
132+
return "\t.aeabi_attribute %s, \"%s\"";
133+
}
134+
135+
template <
136+
typename T,
137+
typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
138+
>
139+
constexpr uint8_t
140+
aeabi_attr_val_for_fmt (T value)
141+
{
142+
return static_cast<uint8_t>(value);
143+
}
144+
145+
constexpr const char *
146+
aeabi_attr_val_for_fmt (const char *s)
147+
{
148+
return s;
149+
}
150+
151+
template <typename T_tag, typename T_val>
152+
void
153+
write (FILE *out_file, aeabi_attribute<T_tag, T_val> const &attr)
154+
{
155+
asm_fprintf (out_file, aeabi_attr_str_fmt (T_val{}),
156+
to_c_str (attr.tag), aeabi_attr_val_for_fmt (attr.value));
157+
if (flag_debug_asm)
158+
asm_fprintf (out_file, "\t%s %s: %s", ASM_COMMENT_START,
159+
to_c_str (attr.tag), to_c_str (attr.value));
160+
asm_fprintf (out_file, "\n");
161+
}
162+
163+
template <
164+
typename T,
165+
typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
166+
>
167+
constexpr subsection_val_type
168+
deduce_attr_av_type (T)
169+
{
170+
return subsection_val_type::uleb128;
171+
}
172+
173+
constexpr subsection_val_type
174+
deduce_attr_av_type (const char *)
175+
{
176+
return subsection_val_type::ntbs;
177+
}
178+
179+
} // namespace details
180+
181+
/* AEABI subsections can be public or private. A subsection is public if it is
182+
prefixed with "aeabi", private otherwise. The header of an AEABI subsection
183+
is composed of a name (usually a vendor name), an optionality status (optional
184+
or required), and the expected type of its associated attributes (ULEB128 or
185+
NTBS). Note: The attributes in the same subsection have all the same type.
186+
An attribute is composed of a tag identifier (ULEB128), and its value (ULEB128
187+
or NTBS).
188+
189+
Syntax:
190+
.aeabi_subsection NameOfTheSubsection: string (=NTBS),
191+
Optional: boolean (=ULEB128),
192+
AttributeValueType: enum{ULEB128, NTBS} (=ULEB128)
193+
[
194+
.aeabi_attribute TagIdentifier: ULEB128,
195+
TagValue: Variant[ULEB128|NTBS]
196+
]*
197+
198+
Example:
199+
.aeabi_subsection .aeabi-feature-and-bits, optional, ULEB128
200+
.aeabi_attribute Tag_Feature_GCS, 1 // Tag_Feature_GCS: true
201+
202+
Note: The textual representations of the tag and its value are emitted as a
203+
comment along their numerical representations to annotate the assembler
204+
output when the developer flag '-dA' is provided. */
205+
template <
206+
typename T_tag, /* The type of a tag. */
207+
typename T_val, /* The type of a value. */
208+
size_t N = 0 /* The number of expected attributes if we know it. */
209+
>
210+
class aeabi_subsection
211+
{
212+
public:
213+
aeabi_subsection (const char *name, bool optional)
214+
: m_name (name),
215+
m_optionality (optional
216+
? subsection_optionality::optional
217+
: subsection_optionality::required),
218+
m_avtype (details::deduce_attr_av_type (T_val{}))
219+
{}
220+
221+
/* Append an attribute to the subsection. */
222+
void append (aeabi_attribute<T_tag, T_val> &&attr)
223+
{
224+
m_attributes.quick_push (std::move (attr));
225+
}
226+
227+
/* Write the data to the assembly file. */
228+
void write (FILE *out_file) const
229+
{
230+
asm_fprintf (out_file, "\n\t.aeabi_subsection %s, %s, %s\n",
231+
m_name, details::to_c_str (m_optionality),
232+
details::to_c_str (m_avtype));
233+
234+
for (auto const &attr : m_attributes)
235+
details::write (out_file, attr);
236+
}
237+
238+
/* Indicate if the subsection is empty. */
239+
bool empty () const
240+
{
241+
return m_attributes.is_empty ();
242+
}
243+
244+
private:
245+
const char *m_name;
246+
subsection_optionality m_optionality;
247+
subsection_val_type m_avtype;
248+
auto_vec<aeabi_attribute<T_tag, T_val>, N> m_attributes;
249+
};
250+
45251
} // namespace aarch64
46252

47253
#endif /* GCC_AARCH64_ELF_METADATA_H */

gcc/config/aarch64/aarch64-protos.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,7 @@ void aarch64_expand_reversed_crc_using_pmull (scalar_mode, scalar_mode, rtx *);
12671267

12681268
void aarch64_expand_fp_spaceship (rtx, rtx, rtx, rtx);
12691269

1270+
extern bool aarch64_pacret_enabled ();
12701271
extern bool aarch64_gcs_enabled ();
12711272

12721273
extern unsigned aarch64_data_alignment (const_tree exp, unsigned align);

gcc/config/aarch64/aarch64.cc

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@
109109
and 1 MOVI/DUP (same size as a call). */
110110
#define MAX_SET_SIZE(speed) (speed ? 256 : 96)
111111

112+
#ifndef HAVE_AS_AEABI_BUILD_ATTRIBUTES
113+
#define HAVE_AS_AEABI_BUILD_ATTRIBUTES 0
114+
#endif
115+
112116
/* Flags that describe how a function shares certain architectural state
113117
with its callers.
114118

@@ -8757,6 +8761,13 @@ aarch_bti_j_insn_p (rtx_insn *insn)
87578761
return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_BTI_J;
87588762
}
87598763

8764+
/* Return TRUE if Pointer Authentication for the return address is enabled. */
8765+
bool
8766+
aarch64_pacret_enabled (void)
8767+
{
8768+
return (aarch_ra_sign_scope != AARCH_FUNCTION_NONE);
8769+
}
8770+
87608771
/* Return TRUE if Guarded Control Stack is enabled. */
87618772
bool
87628773
aarch64_gcs_enabled (void)
@@ -25334,7 +25345,6 @@ aarch64_start_file (void)
2533425345
}
2533525346

2533625347
/* Emit load exclusive. */
25337-
2533825348
static void
2533925349
aarch64_emit_load_exclusive (machine_mode mode, rtx rval,
2534025350
rtx mem, rtx model_rtx)
@@ -29970,16 +29980,37 @@ aarch64_file_end_indicate_exec_stack ()
2997029980
{
2997129981
file_end_indicate_exec_stack ();
2997229982

29973-
aarch64::section_note_gnu_property gnu_properties;
29983+
/* Check whether the current assembler supports AEABI build attributes, if
29984+
not fallback to .note.gnu.property section. */
29985+
if (HAVE_AS_AEABI_BUILD_ATTRIBUTES)
29986+
{
29987+
using namespace aarch64;
29988+
aeabi_subsection<BA_TagFeature_t, bool, 3>
29989+
aeabi_subsec ("aeabi_feature_and_bits", true);
2997429990

29975-
if (aarch_bti_enabled ())
29976-
gnu_properties.bti_enabled ();
29977-
if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
29978-
gnu_properties.pac_enabled ();
29979-
if (aarch64_gcs_enabled ())
29980-
gnu_properties.gcs_enabled ();
29991+
aeabi_subsec.append (
29992+
make_aeabi_attribute (Tag_Feature_BTI, aarch_bti_enabled ()));
29993+
aeabi_subsec.append (
29994+
make_aeabi_attribute (Tag_Feature_PAC, aarch64_pacret_enabled ()));
29995+
aeabi_subsec.append (
29996+
make_aeabi_attribute (Tag_Feature_GCS, aarch64_gcs_enabled ()));
2998129997

29982-
gnu_properties.write ();
29998+
if (!aeabi_subsec.empty ())
29999+
aeabi_subsec.write (asm_out_file);
30000+
}
30001+
else
30002+
{
30003+
aarch64::section_note_gnu_property gnu_properties;
30004+
30005+
if (aarch_bti_enabled ())
30006+
gnu_properties.bti_enabled ();
30007+
if (aarch64_pacret_enabled ())
30008+
gnu_properties.pac_enabled ();
30009+
if (aarch64_gcs_enabled ())
30010+
gnu_properties.gcs_enabled ();
30011+
30012+
gnu_properties.write ();
30013+
}
2998330014
}
2998430015

2998530016
/* Helper function for straight line speculation.

gcc/configure

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28247,6 +28247,43 @@ if test $gcc_cv_as_aarch64_picreloc = yes; then
2824728247

2824828248
$as_echo "#define HAVE_AS_SMALL_PIC_RELOCS 1" >>confdefs.h
2824928249

28250+
fi
28251+
28252+
# Check if we have binutils support for AEABI build attributes.
28253+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for support of AEABI build attributes" >&5
28254+
$as_echo_n "checking assembler for support of AEABI build attributes... " >&6; }
28255+
if ${gcc_cv_as_aarch64_aeabi_build_attributes+:} false; then :
28256+
$as_echo_n "(cached) " >&6
28257+
else
28258+
gcc_cv_as_aarch64_aeabi_build_attributes=no
28259+
if test x$gcc_cv_as != x; then
28260+
$as_echo '
28261+
.aeabi_subsection aeabi_feature_and_bits, optional, ULEB128
28262+
.aeabi_attribute Tag_Feature_BTI, 1
28263+
.aeabi_attribute Tag_Feature_PAC, 1
28264+
.aeabi_attribute Tag_Feature_GCS, 1
28265+
' > conftest.s
28266+
if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
28267+
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
28268+
(eval $ac_try) 2>&5
28269+
ac_status=$?
28270+
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
28271+
test $ac_status = 0; }; }
28272+
then
28273+
gcc_cv_as_aarch64_aeabi_build_attributes=yes
28274+
else
28275+
echo "configure: failed program was" >&5
28276+
cat conftest.s >&5
28277+
fi
28278+
rm -f conftest.o conftest.s
28279+
fi
28280+
fi
28281+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_aarch64_aeabi_build_attributes" >&5
28282+
$as_echo "$gcc_cv_as_aarch64_aeabi_build_attributes" >&6; }
28283+
if test $gcc_cv_as_aarch64_aeabi_build_attributes = yes; then
28284+
28285+
$as_echo "#define HAVE_AS_AEABI_BUILD_ATTRIBUTES 1" >>confdefs.h
28286+
2825028287
fi
2825128288

2825228289
# Enable Branch Target Identification Mechanism and Return Address

gcc/configure.ac

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4467,6 +4467,15 @@ case "$target" in
44674467
ldr x0, [[x2, #:gotpage_lo15:globalsym]]
44684468
],,[AC_DEFINE(HAVE_AS_SMALL_PIC_RELOCS, 1,
44694469
[Define if your assembler supports relocs needed by -fpic.])])
4470+
# Check if we have binutils support for AEABI build attributes.
4471+
gcc_GAS_CHECK_FEATURE([support of AEABI build attributes], gcc_cv_as_aarch64_aeabi_build_attributes,,
4472+
[
4473+
.aeabi_subsection aeabi_feature_and_bits, optional, ULEB128
4474+
.aeabi_attribute Tag_Feature_BTI, 1
4475+
.aeabi_attribute Tag_Feature_PAC, 1
4476+
.aeabi_attribute Tag_Feature_GCS, 1
4477+
],,[AC_DEFINE(HAVE_AS_AEABI_BUILD_ATTRIBUTES, 1,
4478+
[Define if your assembler supports AEABI build attributes.])])
44704479
# Enable Branch Target Identification Mechanism and Return Address
44714480
# Signing by default.
44724481
AC_ARG_ENABLE(standard-branch-protection,

0 commit comments

Comments
 (0)