[PATCH 12/15] arm: implement bti injection

Hi all,

this patch enables Branch Target Identification Armv8.1-M Mechanism
[1].

This is achieved by using the bti pass made common with Aarch64.

The pass iterates through the instructions and adds the necessary BTI
instructions at the beginning of every function and at every landing
pads targeted by indirect jumps.

Best Regards

  Andrea

[1]
<https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* config.gcc (arm*-*-*): Add 'aarch-bti-insert.o' object.
	* config/arm/arm-protos.h: Update.
	* config/arm/aarch-common-protos.h: Declare
	'aarch_bti_arch_check'.
	* config/arm/arm.cc (aarch_bti_enabled) Update.
	(aarch_bti_j_insn_p, aarch_pac_insn_p, aarch_gen_bti_c)
	(aarch_gen_bti_j, aarch_bti_arch_check): New functions.
	* config/arm/arm.md (bti_nop): New insn.
	* config/arm/t-arm (PASSES_EXTRA): Add 'arm-passes.def'.
	(aarch-bti-insert.o): New target.
	* config/arm/unspecs.md (VUNSPEC_BTI_NOP): New unspec.
	* config/arm/aarch-bti-insert.cc (rest_of_insert_bti): Verify arch
	compatibility.
	(gate): Make use of 'aarch_bti_arch_check'.
	* config/arm/arm-passes.def: New file.
	* config/aarch64/aarch64.cc (aarch_bti_arch_check): New function.

gcc/testsuite/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/bti-1.c: New testcase.
	* gcc.target/arm/bti-2.c: Likewise.
This commit is contained in:
Andrea Corallo 2022-04-07 11:51:56 +02:00
parent f7ad35a3ff
commit db6b9a9ddb
12 changed files with 182 additions and 5 deletions

View file

@ -362,7 +362,7 @@ arc*-*-*)
;;
arm*-*-*)
cpu_type=arm
extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
extra_objs="arm-builtins.o arm-mve-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"

View file

@ -8933,6 +8933,10 @@ aarch64_return_address_signing_enabled (void)
&& known_ge (cfun->machine->frame.reg_offset[LR_REGNUM], 0)));
}
/* Only used by the arm backend. */
void aarch_bti_arch_check (void)
{}
/* Return TRUE if Branch Target Identification Mechanism is enabled. */
bool
aarch_bti_enabled (void)

View file

@ -190,7 +190,12 @@ public:
/* opt_pass methods: */
virtual bool gate (function *)
{
return aarch_bti_enabled ();
if (aarch_bti_enabled ())
{
aarch_bti_arch_check ();
return true;
}
return false;
}
virtual unsigned int execute (function *)

View file

@ -42,6 +42,7 @@ 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 void aarch_bti_arch_check (void);
extern bool aarch_bti_enabled (void);
extern bool aarch_bti_j_insn_p (rtx_insn *);
extern bool aarch_pac_insn_p (rtx);

View file

@ -0,0 +1,21 @@
/* Arm-specific passes declarations.
Copyright (C) 2022 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);

View file

@ -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);

View file

@ -33122,13 +33122,69 @@ arm_current_function_pac_enabled_p (void)
&& !crtl->is_leaf));
}
/* Return TRUE if Branch Target Identification Mechanism is enabled. */
static bool
aarch_bti_enabled ()
/* Raise an error if the current target arch is not bti compatible. */
void aarch_bti_arch_check (void)
{
if (!arm_arch8m_main)
error ("This architecture does not support branch protection instructions");
}
/* Return TRUE if Branch Target Identification Mechanism is enabled. */
bool
aarch_bti_enabled (void)
{
return aarch_enable_bti != 0;
}
/* 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) == VUNSPEC_BTI_NOP;
}
/* 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_NOP)
|| (GET_CODE (tmp) == UNSPEC_VOLATILE
&& XINT (tmp, 1) == VUNSPEC_PACBTI_NOP)))
return true;
}
return false;
}
/* Target specific mapping for aarch_gen_bti_c and aarch_gen_bti_j.
For Arm, both of these map to a simple BTI instruction. */
rtx
aarch_gen_bti_c (void)
{
return gen_bti_nop ();
}
rtx
aarch_gen_bti_j (void)
{
return gen_bti_nop ();
}
/* 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. */

View file

@ -13009,6 +13009,13 @@
"aut\t%|ip, %|lr, %|sp"
[(set_attr "conds" "unconditional")])
(define_insn "bti_nop"
[(unspec_volatile [(const_int 0)] VUNSPEC_BTI_NOP)]
"arm_arch8m_main"
"bti"
[(set_attr "conds" "unconditional")
(set_attr "type" "nop")])
;; Vector bits common to IWMMXT, Neon and MVE
(include "vec-common.md")
;; Load the Intel Wireless Multimedia Extension patterns

View file

@ -175,3 +175,13 @@ arm-d.o: $(srcdir)/config/arm/arm-d.cc
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.cc \
$(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.cc

View file

@ -257,6 +257,7 @@
; instruction.
VUNSPEC_PACBTI_NOP ; Represents PAC signing LR + valid landing pad
VUNSPEC_AUT_NOP ; Represents PAC verifying LR
VUNSPEC_BTI_NOP ; Represent BTI
])
;; Enumerators for NEON unspecs.

View file

@ -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 -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
int
main (void)
{
return 0;
}
/* { dg-final { scan-assembler "bti" } } */

View file

@ -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 -mfloat-abi=softfp -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 } } */