From b5f794b47bc09930e3a05b64de0890d315631436 Mon Sep 17 00:00:00 2001 From: Sudakshina Das Date: Wed, 9 Jan 2019 14:21:22 +0000 Subject: [PATCH] [AArch64, 5/6] Enable BTI : Add new pass for BTI. This patch is part of a series that enables ARMv8.5-A in GCC and adds Branch Target Identification Mechanism. This patch adds a new pass called "bti" which is triggered by the command line argument -mbranch-protection whenever "bti" is turned on. The pass iterates through the instructions and adds appropriated BTI instructions based on the following: * Add a new "BTI C" at the beginning of a function, unless its already protected by a "PACIASP". We exempt the functions that are only called directly. * Add a new "BTI J" for every target of an indirect jump, jump table targets, non-local goto targets or labels that might be referenced by variables, constant pools, etc (NOTE_INSN_DELETED_LABEL). Since we have already changed the use of indirect tail calls to only x16 and x17, we do not have to use "BTI JC". (check patch 3/6). *** gcc/ChangeLog *** 2018-01-09 Sudakshina Das Ramana Radhakrishnan * config.gcc (aarch64*-*-*): Add aarch64-bti-insert.o. * gcc/config/aarch64/aarch64.h: Update comment for TRAMPOLINE_SIZE. * config/aarch64/aarch64.c (aarch64_asm_trampoline_template): Update if bti is enabled. * config/aarch64/aarch64-bti-insert.c: New file. * config/aarch64/aarch64-passes.def (INSERT_PASS_BEFORE): Insert bti pass. * config/aarch64/aarch64-protos.h (make_pass_insert_bti): Declare the new bti pass. * config/aarch64/aarch64.md (unspecv): Add UNSPECV_BTI_NOARG, UNSPECV_BTI_C, UNSPECV_BTI_J and UNSPECV_BTI_JC. (bti_noarg, bti_j, bti_c, bti_jc): New define_insns. * config/aarch64/t-aarch64: Add rule for aarch64-bti-insert.o. *** gcc/testsuite/ChangeLog *** 2018-01-09 Sudakshina Das * gcc.target/aarch64/bti-1.c: New test. * gcc.target/aarch64/bti-2.c: New test. * gcc.target/aarch64/bti-3.c: New test. * lib/target-supports.exp (check_effective_target_aarch64_bti_hw): Add new check for BTI hw. Co-Authored-By: Ramana Radhakrishnan From-SVN: r267769 --- gcc/ChangeLog | 17 ++ gcc/config.gcc | 2 +- gcc/config/aarch64/aarch64-bti-insert.c | 235 +++++++++++++++++++++++ gcc/config/aarch64/aarch64-passes.def | 1 + gcc/config/aarch64/aarch64-protos.h | 1 + gcc/config/aarch64/aarch64.c | 28 ++- gcc/config/aarch64/aarch64.h | 2 +- gcc/config/aarch64/aarch64.md | 33 ++++ gcc/config/aarch64/t-aarch64 | 9 + gcc/testsuite/ChangeLog | 8 + gcc/testsuite/gcc.target/aarch64/bti-1.c | 59 ++++++ gcc/testsuite/gcc.target/aarch64/bti-2.c | 34 ++++ gcc/testsuite/gcc.target/aarch64/bti-3.c | 52 +++++ gcc/testsuite/lib/target-supports.exp | 16 ++ 14 files changed, 490 insertions(+), 7 deletions(-) create mode 100644 gcc/config/aarch64/aarch64-bti-insert.c create mode 100644 gcc/testsuite/gcc.target/aarch64/bti-1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/bti-2.c create mode 100644 gcc/testsuite/gcc.target/aarch64/bti-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0bc36756e4a..e19b1aecf9b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2018-01-09 Sudakshina Das + Ramana Radhakrishnan + + * config.gcc (aarch64*-*-*): Add aarch64-bti-insert.o. + * gcc/config/aarch64/aarch64.h: Update comment for TRAMPOLINE_SIZE. + * config/aarch64/aarch64.c (aarch64_asm_trampoline_template): Update + if bti is enabled. + * config/aarch64/aarch64-bti-insert.c: New file. + * config/aarch64/aarch64-passes.def (INSERT_PASS_BEFORE): Insert bti + pass. + * config/aarch64/aarch64-protos.h (make_pass_insert_bti): Declare the + new bti pass. + * config/aarch64/aarch64.md (unspecv): Add UNSPECV_BTI_NOARG, + UNSPECV_BTI_C, UNSPECV_BTI_J and UNSPECV_BTI_JC. + (bti_noarg, bti_j, bti_c, bti_jc): New define_insns. + * config/aarch64/t-aarch64: Add rule for aarch64-bti-insert.o. + 2018-01-09 Sudakshina Das * config/aarch64/aarch64-protos.h (aarch64_bti_enabled): Declare. diff --git a/gcc/config.gcc b/gcc/config.gcc index 3f5a37dc8db..f7ddb120ee2 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -318,7 +318,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 cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o" + extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o" target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c" target_has_targetm_common=yes ;; diff --git a/gcc/config/aarch64/aarch64-bti-insert.c b/gcc/config/aarch64/aarch64-bti-insert.c new file mode 100644 index 00000000000..e519a0f0ac1 --- /dev/null +++ b/gcc/config/aarch64/aarch64-bti-insert.c @@ -0,0 +1,235 @@ +/* Branch Target Identification for AArch64 architecture. + Copyright (C) 2019 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 + . */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#define INCLUDE_STRING +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "target.h" +#include "rtl.h" +#include "tree.h" +#include "memmodel.h" +#include "gimple.h" +#include "tm_p.h" +#include "stringpool.h" +#include "attribs.h" +#include "emit-rtl.h" +#include "gimplify.h" +#include "gimple-iterator.h" +#include "dumpfile.h" +#include "rtl-iter.h" +#include "cfgrtl.h" +#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. + + 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 + a compatible BTI or BRK, HLT, PACIASP, PACIBASP instruction (even if the + branch is triggered in a non-guarded memory region). An incompatibility + generates a Branch Target Exception. + + The compatibility of the BTI instruction is as follows: + BTI j : Can be a target of any indirect jump (BR Xn). + BTI c : Can be a target of any indirect call (BLR Xn and BR X16/X17). + BTI jc: Can be a target of any indirect call or indirect jump. + BTI : Can not be a target of any indirect call or indirect jump. + + In order to enable this mechanism, this pass iterates through the + control flow of the code and adds appropriate BTI instructions : + * Add a new "BTI C" at the beginning of a function, unless its already + protected by a "PACIASP/PACIBSP". We exempt the functions that are only + called directly. + * Add a new "BTI J" for every target of an indirect jump, jump table targets, + non-local goto targets or labels that might be referenced by variables, + constant pools, etc (NOTE_INSN_DELETED_LABEL) + + Since we have already changed the use of indirect tail calls to only x16 + and x17, we do not have to use "BTI JC". + + This pass is triggered by the command line option -mbranch-protection=bti or + -mbranch-protection=standard. Since all the BTI instructions are in the HINT + space, this pass does not require any minimum architecture version. */ + +namespace { + +const pass_data pass_data_insert_bti = +{ + RTL_PASS, /* type. */ + "bti", /* name. */ + OPTGROUP_NONE, /* optinfo_flags. */ + TV_MACH_DEP, /* tv_id. */ + 0, /* properties_required. */ + 0, /* properties_provided. */ + 0, /* properties_destroyed. */ + 0, /* todo_flags_start. */ + 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 x; + + 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_PACISP: + return true; + + default: + return false; + } + iter.skip_subrtxes (); + } + } + return false; +} + +/* Insert the BTI instruction. */ +/* This is implemented as a late RTL pass that runs before branch + shortening and does the following. */ +static unsigned int +rest_of_insert_bti (void) +{ + timevar_push (TV_MACH_DEP); + + rtx bti_insn; + rtx_insn *insn; + basic_block bb; + + /* Since a Branch Target Exception can only be triggered by an indirect call, + we exempt function that are only called directly. We also exempt + functions that are already protected by Return Address Signing (PACIASP/ + PACIBSP). For all other cases insert a BTI C at the beginning of the + function. */ + if (!cgraph_node::get (cfun->decl)->only_called_directly_p ()) + { + bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; + insn = BB_HEAD (bb); + if (!aarch64_pac_insn_p (get_first_nonnote_insn ())) + { + bti_insn = gen_bti_c (); + emit_insn_before (bti_insn, insn); + } + } + + bb = 0; + FOR_EACH_BB_FN (bb, cfun) + { + for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); + insn = NEXT_INSN (insn)) + { + /* If a label is marked to be preserved or can be a non-local goto + target, it must be protected with a BTI J. The same applies to + NOTE_INSN_DELETED_LABEL since they are basically labels that might + be referenced via variables or constant pool. */ + if ((LABEL_P (insn) + && (LABEL_PRESERVE_P (insn) + || bb->flags & BB_NON_LOCAL_GOTO_TARGET)) + || (NOTE_P (insn) + && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)) + { + bti_insn = gen_bti_j (); + emit_insn_after (bti_insn, insn); + continue; + } + + /* There could still be more labels that are valid targets of a + BTI J instuction. To find them we start looking through the + JUMP_INSN. If it jumps to a jump table, then we find all labels + of the jump table to protect with a BTI J. */ + if (JUMP_P (insn)) + { + rtx_jump_table_data *table; + if (tablejump_p (insn, NULL, &table)) + { + rtvec vec = table->get_labels (); + int j; + rtx_insn *label; + + for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j) + { + label = as_a (XEXP (RTVEC_ELT (vec, j), 0)); + bti_insn = gen_bti_j (); + emit_insn_after (bti_insn, label); + } + } + } + + /* Also look for calls to setjmp () which would be marked with + REG_SETJMP note and put a BTI J after. This is where longjump () + will return. */ + if (CALL_P (insn) && (find_reg_note (insn, REG_SETJMP, NULL))) + { + bti_insn = gen_bti_j (); + emit_insn_after (bti_insn, insn); + continue; + } + } + } + + timevar_pop (TV_MACH_DEP); + return 0; +} + + +class pass_insert_bti : public rtl_opt_pass +{ +public: + pass_insert_bti (gcc::context *ctxt) + : rtl_opt_pass (pass_data_insert_bti, ctxt) + {} + + /* opt_pass methods: */ + virtual bool gate (function *) + { + return aarch64_bti_enabled (); + } + + virtual unsigned int execute (function *) + { + return rest_of_insert_bti (); + } + +}; // class pass_insert_bti + +} // anon namespace + +rtl_opt_pass * +make_pass_insert_bti (gcc::context *ctxt) +{ + return new pass_insert_bti (ctxt); +} diff --git a/gcc/config/aarch64/aarch64-passes.def b/gcc/config/aarch64/aarch64-passes.def index d554c8b7312..12d1ad6ba39 100644 --- a/gcc/config/aarch64/aarch64-passes.def +++ b/gcc/config/aarch64/aarch64-passes.def @@ -21,3 +21,4 @@ INSERT_PASS_AFTER (pass_regrename, 1, pass_fma_steering); INSERT_PASS_BEFORE (pass_reorder_blocks, 1, pass_track_speculation); INSERT_PASS_AFTER (pass_machine_reorg, 1, pass_tag_collision_avoidance); +INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti); diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 3e3ad14d323..b035e35f33b 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -633,6 +633,7 @@ extern void aarch64_d_target_versions (void); rtl_opt_pass *make_pass_fma_steering (gcc::context *); rtl_opt_pass *make_pass_track_speculation (gcc::context *); rtl_opt_pass *make_pass_tag_collision_avoidance (gcc::context *); +rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt); poly_uint64 aarch64_regmode_natural_size (machine_mode); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 47569b841f9..d5e140dd08a 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -8250,18 +8250,36 @@ aarch64_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) static void aarch64_asm_trampoline_template (FILE *f) { + int offset1 = 16; + int offset2 = 20; + + if (aarch64_bti_enabled ()) + { + asm_fprintf (f, "\thint\t34 // bti c\n"); + offset1 -= 4; + offset2 -= 4; + } + if (TARGET_ILP32) { - asm_fprintf (f, "\tldr\tw%d, .+16\n", IP1_REGNUM - R0_REGNUM); - asm_fprintf (f, "\tldr\tw%d, .+16\n", STATIC_CHAIN_REGNUM - R0_REGNUM); + asm_fprintf (f, "\tldr\tw%d, .+%d\n", IP1_REGNUM - R0_REGNUM, offset1); + asm_fprintf (f, "\tldr\tw%d, .+%d\n", STATIC_CHAIN_REGNUM - R0_REGNUM, + offset1); } else { - asm_fprintf (f, "\tldr\t%s, .+16\n", reg_names [IP1_REGNUM]); - asm_fprintf (f, "\tldr\t%s, .+20\n", reg_names [STATIC_CHAIN_REGNUM]); + asm_fprintf (f, "\tldr\t%s, .+%d\n", reg_names [IP1_REGNUM], offset1); + asm_fprintf (f, "\tldr\t%s, .+%d\n", reg_names [STATIC_CHAIN_REGNUM], + offset2); } asm_fprintf (f, "\tbr\t%s\n", reg_names [IP1_REGNUM]); - assemble_aligned_integer (4, const0_rtx); + + /* The trampoline needs an extra padding instruction. In case if BTI is + enabled the padding instruction is replaced by the BTI instruction at + the beginning. */ + if (!aarch64_bti_enabled ()) + assemble_aligned_integer (4, const0_rtx); + assemble_aligned_integer (POINTER_BYTES, const0_rtx); assemble_aligned_integer (POINTER_BYTES, const0_rtx); } diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index e401ffb1962..63f3be7fff4 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -918,7 +918,7 @@ typedef struct #define RETURN_ADDR_RTX aarch64_return_addr -/* 3 insns + padding + 2 pointer-sized entries. */ +/* BTI c + 3 insns + 2 pointer-sized entries. */ #define TRAMPOLINE_SIZE (TARGET_ILP32 ? 24 : 32) /* Trampolines contain dwords, so must be dword aligned. */ diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 1d8226d3efa..513aec1872a 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -237,6 +237,10 @@ UNSPECV_BLOCKAGE ; Represent a blockage UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing. UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier. + UNSPECV_BTI_NOARG ; Represent BTI. + UNSPECV_BTI_C ; Represent BTI c. + UNSPECV_BTI_J ; Represent BTI j. + UNSPECV_BTI_JC ; Represent BTI jc. ] ) @@ -6939,6 +6943,35 @@ [(set_attr "type" "csel")] ) +;; BTI instructions +(define_insn "bti_noarg" + [(unspec_volatile [(const_int 0)] UNSPECV_BTI_NOARG)] + "" + "hint\t32 // bti" + [(set_attr "type" "no_insn")] +) + +(define_insn "bti_c" + [(unspec_volatile [(const_int 0)] UNSPECV_BTI_C)] + "" + "hint\t34 // bti c" + [(set_attr "type" "no_insn")] +) + +(define_insn "bti_j" + [(unspec_volatile [(const_int 0)] UNSPECV_BTI_J)] + "" + "hint\t36 // bti j" + [(set_attr "type" "no_insn")] +) + +(define_insn "bti_jc" + [(unspec_volatile [(const_int 0)] UNSPECV_BTI_JC)] + "" + "hint\t38 // bti jc" + [(set_attr "type" "no_insn")] +) + ;; Helper for aarch64.c code. (define_expand "set_clobber_cc" [(parallel [(set (match_operand 0) diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64 index caae1f671f2..ee471f8983f 100644 --- a/gcc/config/aarch64/t-aarch64 +++ b/gcc/config/aarch64/t-aarch64 @@ -91,6 +91,15 @@ 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 \ + $(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 + comma=, MULTILIB_OPTIONS = $(subst $(comma),/, $(patsubst %, mabi=%, $(subst $(comma),$(comma)mabi=,$(TM_MULTILIB_CONFIG)))) MULTILIB_DIRNAMES = $(subst $(comma), ,$(TM_MULTILIB_CONFIG)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d3d73f54eae..b55a7abd83e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2018-01-09 Sudakshina Das + + * gcc.target/aarch64/bti-1.c: New test. + * gcc.target/aarch64/bti-2.c: New test. + * gcc.target/aarch64/bti-3.c: New test. + * lib/target-supports.exp + (check_effective_target_aarch64_bti_hw): Add new check for BTI hw. + 2018-01-09 Sudakshina Das * gcc.target/aarch64/test_frame_17.c: Update to check for EP0_REGNUM diff --git a/gcc/testsuite/gcc.target/aarch64/bti-1.c b/gcc/testsuite/gcc.target/aarch64/bti-1.c new file mode 100644 index 00000000000..575d01a5411 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/bti-1.c @@ -0,0 +1,59 @@ +/* { dg-do compile } */ +/* -Os to create jump table. */ +/* { dg-options "-Os -mbranch-protection=standard" } */ + +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; +} +/* f_jump_table should have PACIASP and AUTIASP. */ +/* { dg-final { scan-assembler-times "hint\t25" 1 } } */ +/* { dg-final { scan-assembler-times "hint\t29" 1 } } */ + +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 "hint\t34" 1 } } */ +/* { dg-final { scan-assembler-times "hint\t36" 12 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/bti-2.c b/gcc/testsuite/gcc.target/aarch64/bti-2.c new file mode 100644 index 00000000000..e50eef15c89 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/bti-2.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-require-effective-target aarch64_bti_hw } */ +/* { dg-options "-mbranch-protection=standard" } */ + +#include + +typedef int FP (int); + +int +f1 (FP fp, int n) +{ + return (fp) (n); +} + +int +f2 (int n, FP fp) +{ + return (fp) (n); +} + +int __attribute__ ((noinline)) +func (int x) +{ + return x+1; +} + +int main () +{ + int s = 0; + s += f1 (func, 10); + s += f2 (s, func); + printf ("S: %d\n", s); + return !(s == 23); +} diff --git a/gcc/testsuite/gcc.target/aarch64/bti-3.c b/gcc/testsuite/gcc.target/aarch64/bti-3.c new file mode 100644 index 00000000000..97cf5d37f42 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/bti-3.c @@ -0,0 +1,52 @@ +/* This is a copy of gcc/testsuite/gcc.c-torture/execute/pr56982.c to test the + setjmp case of the bti pass. */ +/* { dg-do run } */ +/* { dg-require-effective-target aarch64_bti_hw } */ +/* { dg-options "--save-temps -mbranch-protection=standard" } */ + +#include + +extern void abort (void); +extern void exit (int); + +static jmp_buf env; + +void baz (void) +{ + __asm__ volatile ("" : : : "memory"); +} + +static inline int g(int x) +{ + if (x) + { + baz(); + return 0; + } + else + { + baz(); + return 1; + } +} + +int f(int *e) +{ + if (*e) + return 1; + + int x = setjmp(env); + int n = g(x); + if (n == 0) + exit(0); + if (x) + abort(); + longjmp(env, 42); +} +/* { dg-final { scan-assembler "hint\t36" } } */ + +int main(int argc, char** argv) +{ + int v = 0; + return f(&v); +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index a9bb6b3bdc6..d694f495493 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -4313,6 +4313,22 @@ proc check_effective_target_arm_neonv2_hw { } { } [add_options_for_arm_neonv2 ""]] } +# ID_AA64PFR1_EL1.BT using bits[3:0] == 1 implies BTI implimented. +proc check_effective_target_aarch64_bti_hw { } { + if { ![istarget aarch64*-*-*] } { + return 0 + } + return [check_runtime aarch64_bti_hw_available { + int + main (void) + { + int a; + asm volatile ("mrs %0, id_aa64pfr1_el1" : "=r" (a)); + return !((a & 0xf) == 1); + } + } "-O2" ] +} + # Return 1 if the target supports the ARMv8.1 Adv.SIMD extension, 0 # otherwise. The test is valid for AArch64 and ARM. Record the command # line options needed. -- 2.30.2