@@ -328,7 +328,7 @@ aarch64*-*-*)
c_target_objs="aarch64-c.o"
cxx_target_objs="aarch64-c.o"
d_target_objs="aarch64-d.o"
- extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o aarch64-cc-fusion.o"
+ extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch-bti-insert.o aarch64-cc-fusion.o"
target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c \$(srcdir)/config/aarch64/aarch64-sve-builtins.h \$(srcdir)/config/aarch64/aarch64-sve-builtins.cc"
target_has_targetm_common=yes
;;
@@ -352,7 +352,7 @@ arc*-*-*)
;;
arm*-*-*)
cpu_type=arm
- extra_objs="arm-builtins.o aarch-common.o"
+ extra_objs="arm-builtins.o aarch-common.o aarch-bti-insert.o"
extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
target_type_format_char='%'
c_target_objs="arm-c.o"
@@ -179,7 +179,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
aarch64_def_or_undef (TARGET_RNG, "__ARM_FEATURE_RNG", pfile);
aarch64_def_or_undef (TARGET_MEMTAG, "__ARM_FEATURE_MEMORY_TAGGING", pfile);
- aarch64_def_or_undef (aarch64_bti_enabled (),
+ aarch64_def_or_undef (aarch_bti_enabled (),
"__ARM_FEATURE_BTI_DEFAULT", pfile);
cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT");
@@ -876,7 +876,6 @@ void aarch64_register_pragmas (void);
void aarch64_relayout_simd_types (void);
void aarch64_reset_previous_fndecl (void);
bool aarch64_return_address_signing_enabled (void);
-bool aarch64_bti_enabled (void);
void aarch64_save_restore_target_globals (tree);
void aarch64_addti_scratch_regs (rtx, rtx, rtx *,
rtx *, rtx *,
@@ -7705,11 +7705,61 @@ aarch64_return_address_signing_enabled (void)
/* Return TRUE if Branch Target Identification Mechanism is enabled. */
bool
-aarch64_bti_enabled (void)
+aarch_bti_enabled (void)
{
return (aarch_enable_bti == 1);
}
+/* Check if INSN is a BTI J insn. */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+ if (!insn || !INSN_P (insn))
+ return false;
+
+ rtx pat = PATTERN (insn);
+ return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_BTI_J;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction. */
+bool
+aarch_pac_insn_p (rtx x)
+{
+ if (!INSN_P (x))
+ return false;
+
+ subrtx_var_iterator::array_type array;
+ FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (x), ALL)
+ {
+ rtx sub = *iter;
+ if (sub && GET_CODE (sub) == UNSPEC)
+ {
+ int unspec_val = XINT (sub, 1);
+ switch (unspec_val)
+ {
+ case UNSPEC_PACIASP:
+ case UNSPEC_PACIBSP:
+ return true;
+
+ default:
+ return false;
+ }
+ iter.skip_subrtxes ();
+ }
+ }
+ return false;
+}
+
+rtx aarch_gen_bti_c (void)
+{
+ return gen_bti_c ();
+}
+
+rtx aarch_gen_bti_j (void)
+{
+ return gen_bti_j ();
+}
+
/* The caller is going to use ST1D or LD1D to save or restore an SVE
register in mode MODE at BASE_RTX + OFFSET, where OFFSET is in
the range [1, 16] * GET_MODE_SIZE (MODE). Prepare for this by:
@@ -9072,7 +9122,7 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
rtx_insn *insn;
const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
- if (aarch64_bti_enabled ())
+ if (aarch_bti_enabled ())
emit_insn (gen_bti_c());
reload_completed = 1;
@@ -21227,7 +21277,7 @@ aarch64_print_patchable_function_entry (FILE *file,
bool record_p)
{
if (cfun->machine->label_is_assembled
- && aarch64_bti_enabled ()
+ && aarch_bti_enabled ()
&& !cgraph_node::get (cfun->decl)->only_called_directly_p ())
{
/* Remove the BTI that follows the patch area and insert a new BTI
@@ -25371,7 +25421,7 @@ aarch64_file_end_indicate_exec_stack ()
file_end_indicate_exec_stack ();
unsigned feature_1_and = 0;
- if (aarch64_bti_enabled ())
+ if (aarch_bti_enabled ())
feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
@@ -149,14 +149,14 @@ falkor-tag-collision-avoidance.o: \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/aarch64/falkor-tag-collision-avoidance.c
-aarch64-bti-insert.o: $(srcdir)/config/aarch64/aarch64-bti-insert.c \
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.c \
$(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
$(CONTEXT_H) $(TREE_PASS_H) regrename.h \
$(srcdir)/config/aarch64/aarch64-protos.h
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/aarch64/aarch64-bti-insert.c
+ $(srcdir)/config/arm/aarch-bti-insert.c
aarch64-cc-fusion.o: $(srcdir)/config/aarch64/aarch64-cc-fusion.cc \
$(CONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(BACKEND_H) $(RTL_H) $(DF_H) \
similarity index 80%
rename from gcc/config/aarch64/aarch64-bti-insert.c
rename to gcc/config/arm/aarch-bti-insert.c
@@ -1,4 +1,4 @@
-/* Branch Target Identification for AArch64 architecture.
+/* Branch Target Identification for Arm/AArch64 architecture.
Copyright (C) 2019-2021 Free Software Foundation, Inc.
Contributed by Arm Ltd.
@@ -42,10 +42,11 @@
#include "tree-pass.h"
#include "cgraph.h"
-/* This pass enables the support for Branch Target Identification Mechanism
- for AArch64. This is a new security feature introduced in ARMv8.5-A
- archtitecture. A BTI instruction is used to guard against the execution
- of instructions which are not the intended target of an indirect branch.
+/* This pass enables the support for Branch Target Identification Mechanism for
+ Arm/AArch64. This is a security feature introduced in ARMv8.5-A
+ architecture and ARMv8.1-M. A BTI instruction is used to guard against the
+ execution of instructions which are not the intended target of an indirect
+ branch.
Outside of a guarded memory region, a BTI instruction executes as a NOP.
Within a guarded memory region any target of an indirect branch must be
@@ -90,47 +91,6 @@ const pass_data pass_data_insert_bti =
0, /* todo_flags_finish. */
};
-/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction. */
-static bool
-aarch64_pac_insn_p (rtx x)
-{
- if (!INSN_P (x))
- return false;
-
- subrtx_var_iterator::array_type array;
- FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (x), ALL)
- {
- rtx sub = *iter;
- if (sub && GET_CODE (sub) == UNSPEC)
- {
- int unspec_val = XINT (sub, 1);
- switch (unspec_val)
- {
- case UNSPEC_PACIASP:
- /* fall-through. */
- case UNSPEC_PACIBSP:
- return true;
-
- default:
- return false;
- }
- iter.skip_subrtxes ();
- }
- }
- return false;
-}
-
-/* Check if INSN is a BTI J insn. */
-static bool
-aarch64_bti_j_insn_p (rtx_insn *insn)
-{
- if (!insn || !INSN_P (insn))
- return false;
-
- rtx pat = PATTERN (insn);
- return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_BTI_J;
-}
-
/* Insert the BTI instruction. */
/* This is implemented as a late RTL pass that runs before branch
shortening and does the following. */
@@ -155,7 +115,7 @@ rest_of_insert_bti (void)
&& (LABEL_PRESERVE_P (insn)
|| bb->flags & BB_NON_LOCAL_GOTO_TARGET))
{
- bti_insn = gen_bti_j ();
+ bti_insn = aarch_gen_bti_j ();
emit_insn_after (bti_insn, insn);
continue;
}
@@ -177,10 +137,10 @@ rest_of_insert_bti (void)
{
label = as_a <rtx_insn *> (XEXP (RTVEC_ELT (vec, j), 0));
rtx_insn *next = next_nonnote_nondebug_insn (label);
- if (aarch64_bti_j_insn_p (next))
+ if (aarch_bti_j_insn_p (next))
continue;
- bti_insn = gen_bti_j ();
+ bti_insn = aarch_gen_bti_j ();
emit_insn_after (bti_insn, label);
}
}
@@ -191,7 +151,7 @@ rest_of_insert_bti (void)
will return. */
if (CALL_P (insn) && (find_reg_note (insn, REG_SETJMP, NULL)))
{
- bti_insn = gen_bti_j ();
+ bti_insn = aarch_gen_bti_j ();
emit_insn_after (bti_insn, insn);
continue;
}
@@ -207,9 +167,9 @@ rest_of_insert_bti (void)
{
bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
insn = BB_HEAD (bb);
- if (!aarch64_pac_insn_p (get_first_nonnote_insn ()))
+ if (!aarch_pac_insn_p (get_first_nonnote_insn ()))
{
- bti_insn = gen_bti_c ();
+ bti_insn = aarch_gen_bti_c ();
emit_insn_before (bti_insn, insn);
}
}
@@ -229,7 +189,7 @@ public:
/* opt_pass methods: */
virtual bool gate (function *)
{
- return aarch64_bti_enabled ();
+ return aarch_bti_enabled ();
}
virtual unsigned int execute (function *)
@@ -42,6 +42,11 @@ extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
extern int arm_no_early_mul_dep (rtx, rtx);
extern int arm_no_early_store_addr_dep (rtx, rtx);
extern bool arm_rtx_shift_left_p (rtx);
+extern bool aarch_bti_enabled (void);
+extern bool aarch_bti_j_insn_p (rtx_insn *);
+extern bool aarch_pac_insn_p (rtx);
+extern rtx aarch_gen_bti_c (void);
+extern rtx aarch_gen_bti_j (void);
/* RTX cost table definitions. These are used when tuning for speed rather
than for size and should reflect the _additional_ cost over the cost
new file mode 100644
@@ -0,0 +1,21 @@
+/* Arm-specific passes declarations.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ Contributed by Arm Ltd.
+
+ This file is part of GCC.
+
+ GCC 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, or (at your option)
+ any later version.
+
+ GCC 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/>. */
+
+INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);
@@ -24,6 +24,8 @@
#include "sbitmap.h"
+rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
+
extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *);
extern int use_return_insn (int, rtx);
extern bool use_simple_return_p (void);
@@ -32887,6 +32887,56 @@ arm_pac_enabled_for_curr_function_p (void)
&& !crtl->is_leaf);
}
+/* Return TRUE if Branch Target Identification Mechanism is enabled. */
+bool
+aarch_bti_enabled (void)
+{
+ return aarch_enable_bti == 1;
+}
+
+/* Check if INSN is a BTI J insn. */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+ if (!insn || !INSN_P (insn))
+ return false;
+
+ rtx pat = PATTERN (insn);
+ return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_BTI;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction. */
+bool
+aarch_pac_insn_p (rtx x)
+{
+ if (!x || !INSN_P (x))
+ return false;
+
+ rtx pat = PATTERN (x);
+
+ if (GET_CODE (pat) == SET)
+ {
+ rtx tmp = XEXP (pat, 1);
+ if (tmp
+ && GET_CODE (tmp) == UNSPEC
+ && (XINT (tmp, 1) == UNSPEC_PAC_IP_LR_SP
+ || XINT (tmp, 1) == UNSPEC_PACBTI_IP_LR_SP))
+ return true;
+ }
+
+ return false;
+}
+
+rtx aarch_gen_bti_c (void)
+{
+ return gen_bti ();
+}
+
+rtx aarch_gen_bti_j (void)
+{
+ return gen_bti ();
+}
+
/* Implement TARGET_SCHED_CAN_SPECULATE_INSN. Return true if INSN can be
scheduled for speculative execution. Reject the long-running division
and square-root instructions. */
@@ -12843,6 +12843,12 @@
""
"aut\tr12, lr, sp")
+(define_insn "bti"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BTI)]
+ ""
+ "bti"
+ [(set_attr "type" "mov_reg")])
+
;; Vector bits common to IWMMXT, Neon and MVE
(include "vec-common.md")
;; Load the Intel Wireless Multimedia Extension patterns
@@ -165,3 +165,13 @@ arm-d.o: $(srcdir)/config/arm/arm-d.c
arm-common.o: arm-cpu-cdata.h
driver-arm.o: arm-native.h
+
+PASSES_EXTRA += $(srcdir)/config/arm/arm-passes.def
+
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.c \
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+ dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+ output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+ $(CONTEXT_H) $(TREE_PASS_H) regrename.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/arm/aarch-bti-insert.c
@@ -162,6 +162,7 @@
UNSPEC_PAC_IP_LR_SP ; Represents PAC signing LR
UNSPEC_PACBTI_IP_LR_SP ; Represents PAC signing LR + valid landing pad
UNSPEC_AUT_IP_LR_SP ; Represents PAC verifying LR
+ UNSPECV_BTI ; Represent BTI
])
new file mode 100644
@@ -0,0 +1,12 @@
+/* Check that GCC does bti instruction. */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mbranch-protection=bti --save-temps" } */
+
+int
+main (void)
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler "bti" } } */
new file mode 100644
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* -Os to create jump table. */
+/* { dg-options "-Os" } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mbranch-protection=bti --save-temps" } */
+
+extern int f1 (void);
+extern int f2 (void);
+extern int f3 (void);
+extern int f4 (void);
+extern int f5 (void);
+extern int f6 (void);
+extern int f7 (void);
+extern int f8 (void);
+extern int f9 (void);
+extern int f10 (void);
+
+int (*ptr) (void);
+
+int
+f_jump_table (int y, int n)
+{
+ int i;
+ for (i = 0; i < n ;i ++)
+ {
+ switch (y)
+ {
+ case 0 : ptr = f1; break;
+ case 1 : ptr = f2; break;
+ case 2 : ptr = f3; break;
+ case 3 : ptr = f4; break;
+ case 4 : ptr = f5; break;
+ case 5 : ptr = f6; break;
+ case 6 : ptr = f7; break;
+ case 7 : ptr = f8; break;
+ case 8 : ptr = f9; break;
+ case 9 : ptr = f10; break;
+ default: break;
+ }
+ y += ptr ();
+ }
+ return (y == 0)? y+1:4;
+}
+
+int
+f_label_address ()
+{
+ static void * addr = &&lab1;
+ goto *addr;
+lab1:
+ addr = &&lab2;
+ return 1;
+lab2:
+ addr = &&lab1;
+ return 2;
+}
+
+/* { dg-final { scan-assembler-times "bti" 15 } } */