On 11/02/2018 05:35 PM, Sam Tebbs wrote:
> Hi all,
>
> This patch adds support for the Armv8.3-A pointer authentication instructions
> that use the B-key (pacib*, autib* and retab). This required adding builtins
> for
> pacib1716 and autib1716, adding the "b-key" feature to the -mbranch-protection
> option, and required emitting a new CFI directive ".cfi_b_key_frame" which
> causes GAS to add 'B' to the CIE augmentation string. I also had to add a new
> hook called ASM_POST_CFI_STARTPROC which is triggered when the .cfi_startproc
> directive is emitted.
>
> The libgcc stack unwinder has been amended to authenticate return addresses
> with the B key when the function has been signed with the B key.
>
> The previous patch in this series is here:
> https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00104.html
>
> Bootstrapped successfully and regression tested on aarch64-none-elf.
>
> OK for trunk?
>
> gcc/
> 2018-11-02 Sam Tebbs <[email protected]>
>
> * config/aarch64/aarch64-builtins.c (aarch64_builtins): Add
> AARCH64_PAUTH_BUILTIN_AUTIB1716 and AARCH64_PAUTH_BUILTIN_PACIB1716.
> * config/aarch64/aarch64-builtins.c (aarch64_init_pauth_hint_builtins):
> Add autib1716 and pacib1716 initialisation.
> * config/aarch64/aarch64-builtins.c (aarch64_expand_builtin): Add checks
> for autib1716 and pacib1716.
> * config/aarch64/aarch64-protos.h (aarch64_key_type,
> aarch64_post_cfi_startproc): Define.
> * config/aarch64/aarch64-protos.h (aarch64_ra_sign_key): Define extern.
> * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled): Add
> check for b-key, remove frame.laid_out assertion.
> * config/aarch64/aarch64.c (aarch64_ra_sign_key,
> aarch64_post_cfi_startproc, aarch64_handle_pac_ret_b_key): Define.
> * config/aarch64/aarch64.h (TARGET_ASM_POST_CFI_STARTPROC): Define.
> * config/aarch64/aarch64.c (aarch64_pac_ret_subtypes): Add "b-key".
> * config/aarch64/aarch64.md (unspec): Add UNSPEC_AUTIA1716,
> UNSPEC_AUTIB1716, UNSPEC_AUTIASP, UNSPEC_AUTIBSP, UNSPEC_PACIA1716,
> UNSPEC_PACIB1716, UNSPEC_PACIASP, UNSPEC_PACIBSP.
> * config/aarch64/aarch64.md (do_return): Add check for b-key.
> * config/aarch64/aarch64.md (<pauth_mnem_prefix>sp): Add check for
> signing key and scope selected.
> * config/aarch64/aarch64.md (<pauth_mnem_prefix>1716): Add check for
> signing key and scope selected.
> * config/aarch64/aarch64.opt (msign-return-address=): Deprecate.
> * config/aarch64/iterators.md (PAUTH_LR_SP): Add UNSPEC_AUTIASP,
> UNSPEC_AUTIBSP, UNSPEC_PACIASP, UNSPEC_PACIBSP.
> * config/aarch64/iterators.md (PAUTH_17_16): Add UNSPEC_AUTIA1716,
> UNSPEC_AUTIB1716, UNSPEC_PACIA1716, UNSPEC_PACIB1716.
> * config/aarch64/iterators.md (pauth_mnem_prefix): Add UNSPEC_AUTIA1716,
> UNSPEC_AUTIB1716, UNSPEC_PACIA1716, UNSPEC_PACIB1716, UNSPEC_AUTIASP,
> UNSPEC_AUTIBSP, UNSPEC_PACIASP, UNSPEC_PACIBSP.
> * config/aarch64/iterators.md (pauth_hint_num_a): Replace
> UNSPEC_PACI1716 and UNSPEC_AUTI1716 with UNSPEC_PACIA1716 and
> UNSPEC_AUTIA1716 respectively.
> * config/aarch64/iterators.md (pauth_hint_num_b): New int attribute.
>
> gcc/testsuite
> 2018-11-02 Sam Tebbs <[email protected]>
>
> * gcc.target/aarch64/return_address_sign_1.c (dg-final): Replace
> "autiasp" and "paciasp" with "hint\t29 // autisp" and
> "hint\t25 // pacisp" respectively.
> * gcc.target/aarch64/return_address_sign_2.c (dg-final): Replace
> "paciasp" with "hint\t25 // pacisp".
> * gcc.target/aarch64/return_address_sign_3.c (dg-final): Replace
> "paciasp" and "autiasp" with "pacisp" and "autisp" respectively.
> * gcc.target/aarch64/return_address_sign_b_1.c: New file.
> * gcc.target/aarch64/return_address_sign_b_2.c: New file.
> * gcc.target/aarch64/return_address_sign_b_3.c: New file.
> * gcc.target/aarch64/return_address_sign_b_exception.c: New file.
> * gcc.target/aarch64/return_address_sign_builtin.c: New file
>
> libgcc/
> 2018-11-02 Sam Tebbs <[email protected]>
>
> * config/aarch64/aarch64-unwind.h (aarch64_cie_signed_with_b_key): New
> function.
> * config/aarch64/aarch64-unwind.h (aarch64_post_extract_frame_addr,
> aarch64_post_frob_eh_handler_addr): Add check for b-key.
> * unwind-dw2-fde.c (get_cie_encoding): Add check for 'B' in augmentation
> string.
> * unwind-dw2.c (extract_cie_info): Add check for 'B' in augmentation
> string.
Attached is an updated patch rebased on an improvement to the
-mbranch-protection option documentation.
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 8cced94..d676f36 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -398,6 +398,8 @@ enum aarch64_builtins
/* ARMv8.3-A Pointer Authentication Builtins. */
AARCH64_PAUTH_BUILTIN_AUTIA1716,
AARCH64_PAUTH_BUILTIN_PACIA1716,
+ AARCH64_PAUTH_BUILTIN_AUTIB1716,
+ AARCH64_PAUTH_BUILTIN_PACIB1716,
AARCH64_PAUTH_BUILTIN_XPACLRI,
AARCH64_BUILTIN_MAX
};
@@ -971,6 +973,14 @@ aarch64_init_pauth_hint_builtins (void)
= add_builtin_function ("__builtin_aarch64_pacia1716", ftype_pointer_auth,
AARCH64_PAUTH_BUILTIN_PACIA1716, BUILT_IN_MD, NULL,
NULL_TREE);
+ aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIB1716]
+ = add_builtin_function ("__builtin_aarch64_autib1716", ftype_pointer_auth,
+ AARCH64_PAUTH_BUILTIN_AUTIB1716, BUILT_IN_MD, NULL,
+ NULL_TREE);
+ aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIB1716]
+ = add_builtin_function ("__builtin_aarch64_pacib1716", ftype_pointer_auth,
+ AARCH64_PAUTH_BUILTIN_PACIB1716, BUILT_IN_MD, NULL,
+ NULL_TREE);
aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
= add_builtin_function ("__builtin_aarch64_xpaclri", ftype_pointer_strip,
AARCH64_PAUTH_BUILTIN_XPACLRI, BUILT_IN_MD, NULL,
@@ -1360,6 +1370,8 @@ aarch64_expand_builtin (tree exp,
case AARCH64_PAUTH_BUILTIN_AUTIA1716:
case AARCH64_PAUTH_BUILTIN_PACIA1716:
+ case AARCH64_PAUTH_BUILTIN_AUTIB1716:
+ case AARCH64_PAUTH_BUILTIN_PACIB1716:
case AARCH64_PAUTH_BUILTIN_XPACLRI:
arg0 = CALL_EXPR_ARG (exp, 0);
op0 = force_reg (Pmode, expand_normal (arg0));
@@ -1383,8 +1395,24 @@ aarch64_expand_builtin (tree exp,
{
tree arg1 = CALL_EXPR_ARG (exp, 1);
rtx op1 = force_reg (Pmode, expand_normal (arg1));
- icode = (fcode == AARCH64_PAUTH_BUILTIN_PACIA1716
- ? CODE_FOR_paci1716 : CODE_FOR_auti1716);
+ switch (fcode)
+ {
+ case AARCH64_PAUTH_BUILTIN_AUTIA1716:
+ icode = CODE_FOR_autia1716;
+ break;
+ case AARCH64_PAUTH_BUILTIN_AUTIB1716:
+ icode = CODE_FOR_autib1716;
+ break;
+ case AARCH64_PAUTH_BUILTIN_PACIA1716:
+ icode = CODE_FOR_pacia1716;
+ break;
+ case AARCH64_PAUTH_BUILTIN_PACIB1716:
+ icode = CODE_FOR_pacib1716;
+ break;
+ default:
+ icode = 0;
+ gcc_unreachable ();
+ }
rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 1fe1a50..2893cdc 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -392,8 +392,17 @@ enum simd_immediate_check {
AARCH64_CHECK_MOV = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
};
+/* The key type that -msign-return-address should use. */
+enum aarch64_key_type {
+ AARCH64_KEY_A,
+ AARCH64_KEY_B
+};
+
+extern enum aarch64_key_type aarch64_ra_sign_key;
+
extern struct tune_params aarch64_tune_params;
+void aarch64_post_cfi_startproc (void);
poly_int64 aarch64_initial_elimination_offset (unsigned, unsigned);
int aarch64_get_condition_code (rtx);
bool aarch64_address_valid_for_prefetch_p (rtx, bool);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 121348d..f129e4f 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1091,6 +1091,8 @@ static const struct processor *selected_arch;
static const struct processor *selected_cpu;
static const struct processor *selected_tune;
+enum aarch64_key_type aarch64_ra_sign_key = AARCH64_KEY_A;
+
/* The current tuning set. */
struct tune_params aarch64_tune_params = generic_tunings;
@@ -1151,6 +1153,7 @@ aarch64_handle_standard_branch_protection (char* str ATTRIBUTE_UNUSED,
char* rest ATTRIBUTE_UNUSED)
{
aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
+ aarch64_ra_sign_key = AARCH64_KEY_A;
if (rest)
{
error ("unexpected %<%s%> after %<%s%>", rest, str);
@@ -1164,6 +1167,7 @@ aarch64_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED,
char* rest ATTRIBUTE_UNUSED)
{
aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
+ aarch64_ra_sign_key = AARCH64_KEY_A;
return AARCH64_PARSE_OK;
}
@@ -1175,8 +1179,17 @@ aarch64_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED,
return AARCH64_PARSE_OK;
}
+static enum aarch64_parse_opt_result
+aarch64_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED,
+ char* rest ATTRIBUTE_UNUSED)
+{
+ aarch64_ra_sign_key = AARCH64_KEY_B;
+ return AARCH64_PARSE_OK;
+}
+
static const struct aarch64_branch_protec_type aarch64_pac_ret_subtypes[] = {
{ "leaf", aarch64_handle_pac_ret_leaf, NULL, 0 },
+ { "b-key", aarch64_handle_pac_ret_b_key, NULL, 0 },
{ NULL, NULL, NULL, 0 }
};
@@ -4590,11 +4603,10 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
bool
aarch64_return_address_signing_enabled (void)
{
- /* This function should only be called after frame laid out. */
- gcc_assert (cfun->machine->frame.laid_out);
-
/* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
- if it's LR is pushed onto stack. */
+ if its LR is pushed onto stack. */
+ if (aarch64_ra_sign_scope == AARCH64_FUNCTION_NONE)
+ return false;
return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
|| (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
&& cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));
@@ -5344,7 +5356,17 @@ aarch64_expand_prologue (void)
/* Sign return address for functions. */
if (aarch64_return_address_signing_enabled ())
{
- insn = emit_insn (gen_pacisp ());
+ switch (aarch64_ra_sign_key)
+ {
+ case AARCH64_KEY_A:
+ insn = emit_insn (gen_paciasp ());
+ break;
+ case AARCH64_KEY_B:
+ insn = emit_insn (gen_pacibsp ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -5576,7 +5598,17 @@ aarch64_expand_epilogue (bool for_sibcall)
if (aarch64_return_address_signing_enabled ()
&& (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
{
- insn = emit_insn (gen_autisp ());
+ switch (aarch64_ra_sign_key)
+ {
+ case AARCH64_KEY_A:
+ insn = emit_insn (gen_autiasp ());
+ break;
+ case AARCH64_KEY_B:
+ insn = emit_insn (gen_autibsp ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -11898,8 +11930,7 @@ aarch64_handle_attr_cpu (const char *str)
attribute");
break;
case AARCH64_PARSE_INVALID_ARG:
- error ("invalid protection type (\"%s\") in %<target(\"branch-protection\
- =\")%> pragma or attribute", err_str);
+ error ("invalid protection type (\"%s\") in %<target(\"branch-protection=\")%> pragma or attribute", err_str);
aarch64_print_hint_for_core (str);
break;
case AARCH64_PARSE_OK:
@@ -14820,6 +14851,18 @@ aarch64_declare_function_name (FILE *stream, const char* name,
ASM_OUTPUT_LABEL (stream, name);
}
+/* Triggered after a .cfi_startproc directive is emitted into the assembly file.
+ Used to output the .cfi_b_key_frame directive when signing the current
+ function with the B key. */
+
+void
+aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED)
+{
+ if (aarch64_return_address_signing_enabled ()
+ && aarch64_ra_sign_key == AARCH64_KEY_B)
+ asm_fprintf (f, "\t.cfi_b_key_frame\n");
+}
+
/* Implements TARGET_ASM_FILE_START. Output the assembly header. */
static void
@@ -18543,6 +18586,9 @@ aarch64_libgcc_floating_mode_supported_p
#define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
#endif /* #if CHECKING_P */
+#undef TARGET_ASM_POST_CFI_STARTPROC
+#define TARGET_ASM_POST_CFI_STARTPROC aarch64_post_cfi_startproc
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-aarch64.h"
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index ada623b..84d5015 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -118,8 +118,10 @@
)
(define_c_enum "unspec" [
- UNSPEC_AUTI1716
- UNSPEC_AUTISP
+ UNSPEC_AUTIA1716
+ UNSPEC_AUTIB1716
+ UNSPEC_AUTIASP
+ UNSPEC_AUTIBSP
UNSPEC_CASESI
UNSPEC_CRC32B
UNSPEC_CRC32CB
@@ -162,8 +164,10 @@
UNSPEC_LD4_LANE
UNSPEC_MB
UNSPEC_NOP
- UNSPEC_PACI1716
- UNSPEC_PACISP
+ UNSPEC_PACIA1716
+ UNSPEC_PACIB1716
+ UNSPEC_PACIASP
+ UNSPEC_PACIBSP
UNSPEC_PRLG_STK
UNSPEC_REV
UNSPEC_RBIT
@@ -711,8 +715,12 @@
if (aarch64_return_address_signing_enabled ()
&& TARGET_ARMV8_3
&& !crtl->calls_eh_return)
- return "retaa";
-
+ {
+ if (aarch64_ra_sign_key == AARCH64_KEY_B)
+ return "retab";
+ else
+ return "retaa";
+ }
return "ret";
}
[(set_attr "type" "branch")]
@@ -6481,7 +6489,13 @@
[(set (reg:DI R30_REGNUM)
(unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
""
- "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
+ {
+ enum aarch64_key_type key = <pauth_key>;
+ if (key == AARCH64_KEY_B)
+ return "hint\t<pauth_hint_num_b> // <pauth_mnem_prefix>sp";
+ else
+ return "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>sp";
+ }
)
;; Signing/Authenticating X17 using X16 as the salt.
@@ -6490,7 +6504,13 @@
[(set (reg:DI R17_REGNUM)
(unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
""
- "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
+ {
+ enum aarch64_key_type key = <pauth_key>;
+ if (key == AARCH64_KEY_B)
+ return "hint\t<pauth_hint_num_b> // <pauth_mnem_prefix>1716";
+ else
+ return "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>1716";
+ }
)
;; Stripping the signature in R30.
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 524e4e6..799f9d5 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -1482,9 +1482,11 @@
(define_int_iterator FMAXMIN_UNS [UNSPEC_FMAX UNSPEC_FMIN
UNSPEC_FMAXNM UNSPEC_FMINNM])
-(define_int_iterator PAUTH_LR_SP [UNSPEC_PACISP UNSPEC_AUTISP])
+(define_int_iterator PAUTH_LR_SP [UNSPEC_PACIASP UNSPEC_AUTIASP
+ UNSPEC_PACIBSP UNSPEC_AUTIBSP])
-(define_int_iterator PAUTH_17_16 [UNSPEC_PACI1716 UNSPEC_AUTI1716])
+(define_int_iterator PAUTH_17_16 [UNSPEC_PACIA1716 UNSPEC_AUTIA1716
+ UNSPEC_PACIB1716 UNSPEC_AUTIB1716])
(define_int_iterator VQDMULH [UNSPEC_SQDMULH UNSPEC_SQRDMULH])
@@ -1755,16 +1757,35 @@
(UNSPEC_FCVTZU "fcvtzu")])
;; Pointer authentication mnemonic prefix.
-(define_int_attr pauth_mnem_prefix [(UNSPEC_PACISP "paci")
- (UNSPEC_AUTISP "auti")
- (UNSPEC_PACI1716 "paci")
- (UNSPEC_AUTI1716 "auti")])
+(define_int_attr pauth_mnem_prefix [(UNSPEC_PACIASP "pacia")
+ (UNSPEC_PACIBSP "pacib")
+ (UNSPEC_PACIA1716 "pacia")
+ (UNSPEC_PACIB1716 "pacib")
+ (UNSPEC_AUTIASP "autia")
+ (UNSPEC_AUTIBSP "autib")
+ (UNSPEC_AUTIA1716 "autia")
+ (UNSPEC_AUTIB1716 "autib")])
+
+(define_int_attr pauth_key [(UNSPEC_PACIASP "AARCH64_KEY_A")
+ (UNSPEC_PACIBSP "AARCH64_KEY_B")
+ (UNSPEC_PACIA1716 "AARCH64_KEY_A")
+ (UNSPEC_PACIB1716 "AARCH64_KEY_B")
+ (UNSPEC_AUTIASP "AARCH64_KEY_A")
+ (UNSPEC_AUTIBSP "AARCH64_KEY_B")
+ (UNSPEC_AUTIA1716 "AARCH64_KEY_A")
+ (UNSPEC_AUTIB1716 "AARCH64_KEY_B")])
;; Pointer authentication HINT number for NOP space instructions using A Key.
-(define_int_attr pauth_hint_num_a [(UNSPEC_PACISP "25")
- (UNSPEC_AUTISP "29")
- (UNSPEC_PACI1716 "8")
- (UNSPEC_AUTI1716 "12")])
+(define_int_attr pauth_hint_num_a [(UNSPEC_PACIASP "25")
+ (UNSPEC_AUTIASP "29")
+ (UNSPEC_PACIA1716 "8")
+ (UNSPEC_AUTIA1716 "12")])
+
+;; Pointer authentication HINT number for NOP space instructions using B Key.
+(define_int_attr pauth_hint_num_b [(UNSPEC_PACIBSP "27")
+ (UNSPEC_AUTIBSP "31")
+ (UNSPEC_PACIB1716 "10")
+ (UNSPEC_AUTIB1716 "14")])
(define_int_attr perm_insn [(UNSPEC_ZIP1 "zip") (UNSPEC_ZIP2 "zip")
(UNSPEC_TRN1 "trn") (UNSPEC_TRN2 "trn")
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 07cfe69..5bd8232 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -622,7 +622,8 @@ Objective-C and Objective-C++ Dialects}.
-mlow-precision-recip-sqrt -mlow-precision-sqrt -mlow-precision-div @gol
-mpc-relative-literal-loads @gol
-msign-return-address=@var{scope} @gol
--mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}] @gol
+-mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}
++@var{b-key}] @gol
-march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol
-moverride=@var{string} -mverbose-cost-dump -mtrack-speculation}
@@ -15222,7 +15223,8 @@ accessed using a single instruction and emitted after each function. This
limits the maximum size of functions to 1MB. This is enabled by default for
@option{-mcmodel=tiny}.
-@item -mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}]
+@item -mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}
++@var{b-key}]
@opindex mbranch-protection
Select the branch protection features to use.
@samp{none} is the default and turns off all types of branch protection.
@@ -15233,7 +15235,8 @@ level.
level: signing functions that save the return address to memory (non-leaf
functions will practically always do this) using the a-key. The optional
argument @samp{leaf} can be used to extend the signing to include leaf
-functions.
+functions. The optional argument @samp{b-key} can be used to sign the functions
+with the B-key instead of the A-key.
@item -msve-vector-bits=@var{bits}
@opindex msve-vector-bits
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
index 0140bee..0f52b91 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
@@ -48,5 +48,5 @@ func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
return;
}
-/* { dg-final { scan-assembler-times "autiasp" 4 } } */
-/* { dg-final { scan-assembler-times "paciasp" 4 } } */
+/* { dg-final { scan-assembler-times "hint\t29 // autiasp" 4 } } */
+/* { dg-final { scan-assembler-times "hint\t25 // paciasp" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
index a4bc5b4..d5d10aa 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
@@ -14,5 +14,5 @@ func1 (int a, int b, int c)
/* retaa */
}
-/* { dg-final { scan-assembler-times "paciasp" 1 } } */
+/* { dg-final { scan-assembler-times "hint\t25 // paciasp" 1 } } */
/* { dg-final { scan-assembler-times "retaa" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_ab_exception.cpp b/gcc/testsuite/gcc.target/aarch64/return_address_sign_ab_exception.cpp
new file mode 100644
index 0000000..41f0c47
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_ab_exception.cpp
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "--save-temps" } */
+
+__attribute__((target("branch-protection=pac-ret+leaf")))
+int foo_a () {
+ throw 22;
+}
+
+__attribute__((target("branch-protection=pac-ret+leaf+b-key")))
+int foo_b () {
+ throw 22;
+}
+
+int main (int argc, char** argv) {
+ try {
+ foo_a ()
+ } catch (...) {
+ try {
+ foo_b ();
+ } catch (...) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* { dg-final { scan-assembler-times "\t\thint 25" 1 } } */
+/* { dg-final { scan-assembler-times "\t\thint 27" 1 } } */
+/* { dg-final { scan-assembler-times "\t\t.cfi_b_key_frame" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
new file mode 100644
index 0000000..b2e7092
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
@@ -0,0 +1,52 @@
+/* Testing return address signing where no combined instructions used. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf+b-key" } */
+/* { dg-require-effective-target lp64 } */
+
+int foo (int);
+
+/* sibcall only. */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b)
+{
+ /* pacibsp */
+ return foo (a + b);
+ /* autibsp */
+}
+
+/* non-leaf function with sibcall. */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func2 (int a, int b)
+{
+ /* pacibsp */
+ if (a < b)
+ return b;
+
+ a = foo (b);
+
+ return foo (a);
+ /* autibsp */
+}
+
+/* non-leaf function, legacy arch. */
+int __attribute__ ((target ("arch=armv8.2-a")))
+func3 (int a, int b, int c)
+{
+ /* pacibsp */
+ return a + foo (b) + c;
+ /* autibsp */
+}
+
+/* eh_return. */
+void __attribute__ ((target ("arch=armv8.3-a")))
+func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
+{
+ /* pacibsp */
+ *ptr = imm1 + foo (imm1) + imm2;
+ __builtin_eh_return (offset, handler);
+ /* autibsp */
+ return;
+}
+
+/* { dg-final { scan-assembler-times "hint\t27 // pacibsp" 4 } } */
+/* { dg-final { scan-assembler-times "hint\t31 // autibsp" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c
new file mode 100644
index 0000000..7ba2a36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c
@@ -0,0 +1,18 @@
+/* Testing return address signing where combined instructions used. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf+b-key" } */
+/* { dg-require-effective-target lp64 } */
+
+int foo (int);
+int bar (int, int);
+
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b, int c)
+{
+ /* pacibsp */
+ return a + foo (b) + c;
+ /* retab */
+}
+
+/* { dg-final { scan-assembler-times "hint\t27 // pacibsp" 1 } } */
+/* { dg-final { scan-assembler-times "retab" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_3.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_3.c
new file mode 100644
index 0000000..111a30e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_3.c
@@ -0,0 +1,22 @@
+/* Testing the disable of return address signing. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf+b-key" } */
+/* { dg-require-effective-target lp64 } */
+
+int bar (int, int);
+
+int __attribute__ ((target ("arch=armv8.3-a, branch-protection=pac-ret+b-key")))
+func1_leaf (int a, int b, int c, int d)
+{
+ return a + b + c + d;
+}
+
+int __attribute__ ((target ("arch=armv8.3-a, branch-protection=none")))
+func2_none (int a, int b, int c, int d)
+{
+ return c + bar (a, b) + d;
+}
+
+/* { dg-final { scan-assembler-not "pacibsp" } } */
+/* { dg-final { scan-assembler-not "autibsp" } } */
+/* { dg-final { scan-assembler-not "retab" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_exception.cpp b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_exception.cpp
new file mode 100644
index 0000000..44dcfee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_exception.cpp
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-mbranch-protection=pac-ret+leaf+b-key"} */
+
+int foo () {
+ throw 22;
+}
+
+int main (int argc, char** argv) {
+ try {
+ foo()
+ } catch (...) {
+ return 0;
+ }
+ return 1;
+}
+
+/* { dg-final { scan-assembler-times ".cfi_b_key_frame" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_builtin.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_builtin.c
new file mode 100644
index 0000000..f21064d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_builtin.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mbranch-protection=pac-ret+leaf+b-key" } */
+
+/* The correct pauth instruction should be generated no matter the return
+ address signing key/scope specified in the options. */
+
+int foo() {
+ /* { dg-final { scan-assembler-times "hint\t8 // pacia1716" 1 } } */
+ __builtin_aarch64_pacia1716(0, 0);
+ /* { dg-final { scan-assembler-times "hint\t10 // pacib1716" 1 } } */
+ __builtin_aarch64_pacib1716(0, 0);
+ /* { dg-final { scan-assembler-times "hint\t12 // autia1716" 1 } } */
+ __builtin_aarch64_autia1716(0, 0);
+ /* { dg-final { scan-assembler-times "hint\t14 // autib1716" 1 } } */
+ __builtin_aarch64_autib1716(0, 0);
+}
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
index ff05226..5e7bf64 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -35,6 +35,23 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define MD_FROB_UPDATE_CONTEXT(context, fs) \
aarch64_frob_update_context (context, fs)
+static inline int
+aarch64_cie_signed_with_b_key (struct _Unwind_Context *context)
+{
+ const struct dwarf_fde *fde = _Unwind_Find_FDE (context->bases.func,
+ &context->bases);
+ if (fde != NULL)
+ {
+ const struct dwarf_cie *cie = get_cie (fde);
+ if (cie != NULL)
+ {
+ char *aug_str = cie->augmentation;
+ return strchr (aug_str, 'B') == NULL ? 0 : 1;
+ }
+ }
+ return 0;
+}
+
/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
unwind frame info FS. If ADDR is signed, we do address authentication on it
using CFA of current frame. */
@@ -43,9 +60,11 @@ static inline void *
aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
_Unwind_FrameState *fs, void *addr)
{
- if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+ if (context->flags & RA_SIGNED_BIT)
{
_Unwind_Word salt = (_Unwind_Word) context->cfa;
+ if (aarch64_cie_signed_with_b_key (context) != 0)
+ return __builtin_aarch64_autib1716 (addr, salt);
return __builtin_aarch64_autia1716 (addr, salt);
}
else
@@ -62,9 +81,14 @@ aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
ATTRIBUTE_UNUSED,
void *handler_addr)
{
- if (current->flags & RA_A_SIGNED_BIT)
- return __builtin_aarch64_pacia1716 (handler_addr,
+ if (current->flags & RA_SIGNED_BIT)
+ {
+ if (aarch64_cie_signed_with_b_key (current))
+ return __builtin_aarch64_pacib1716 (handler_addr,
+ (_Unwind_Word) current->cfa);
+ return __builtin_aarch64_pacia1716 (handler_addr,
(_Unwind_Word) current->cfa);
+ }
else
return handler_addr;
}
@@ -79,7 +103,7 @@ aarch64_frob_update_context (struct _Unwind_Context *context,
{
if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
/* The flag is used for re-authenticating EH handler's address. */
- context->flags |= RA_A_SIGNED_BIT;
+ context->flags |= RA_SIGNED_BIT;
return;
}
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
index 0d52b7a..9b45427 100644
--- a/libgcc/unwind-dw2-fde.c
+++ b/libgcc/unwind-dw2-fde.c
@@ -334,6 +334,9 @@ get_cie_encoding (const struct dwarf_cie *cie)
/* LSDA encoding. */
else if (*aug == 'L')
p++;
+ /* aarch64 b-key pointer authentication. */
+ else if (*aug == 'B')
+ p++;
/* Otherwise end of string, or unknown augmentation. */
else
return DW_EH_PE_absptr;
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index de9310f..f2b1cfd 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -136,8 +136,9 @@ struct _Unwind_Context
#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
/* Context which has version/args_size/by_value fields. */
#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
- /* Bit reserved on AArch64, return address has been signed with A key. */
-#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
+ /* Bit reserved on AArch64, return address has been signed with A or B
+ key. */
+#define RA_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
_Unwind_Word flags;
/* 0 for now, can be increased when further fields are added to
struct _Unwind_Context. */
@@ -502,6 +503,11 @@ extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
fs->signal_frame = 1;
aug += 1;
}
+ /* aarch64 B-key pointer authentication. */
+ else if (aug[0] == 'B')
+ {
+ aug += 1;
+ }
/* Otherwise we have an unknown augmentation string.
Bail unless we saw a 'z' prefix. */