From patchwork Fri Nov 11 18:34:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiong Wang X-Patchwork-Id: 81886 Delivered-To: patch@linaro.org Received: by 10.140.97.165 with SMTP id m34csp1404971qge; Fri, 11 Nov 2016 10:34:50 -0800 (PST) X-Received: by 10.99.181.86 with SMTP id u22mr6835568pgo.24.1478889289940; Fri, 11 Nov 2016 10:34:49 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id t67si11511932pfk.141.2016.11.11.10.34.49 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 11 Nov 2016 10:34:49 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-441177-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-441177-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-441177-patch=linaro.org@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:references:cc:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=Qaj4dzDq32qx2LAg1 x94QAjE2+TOoNbEtJPeaPIdDX1CBE/oDU1nG2FtyJxgUCFqT9RYL+golnWFPKqt3 RgoZil7vBZoNLaxKXuyz2zoBKG4BcBJWgJ1hWwoNHM6qKuYYB71jBirarJ8ahpix 5P5jiZKMp38yOvCqvoPAiFI/Ms= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:references:cc:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=RSJW5sTi4SaQrHSh0st8nAr r8no=; b=d3smBk7h9fropabrrzBBgR2MVjKRAf2m5ct0Lle9VDh5TxdKZUNDSKd PsEkmxIbV097cj7uZ1GIHR3eER4JVqRJ00WucwHbeZ1Ezo/rJg0kHAh77u/7gJv5 73KF2qa7S/U+bbiCy38btlWpu3/VeSbYOgjlvsJCu0O6Ygj3X5Zs= Received: (qmail 82381 invoked by alias); 11 Nov 2016 18:34:34 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 81543 invoked by uid 89); 11 Nov 2016 18:34:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.8 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=retaa, retab, fetched, handlers X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 11 Nov 2016 18:34:23 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 140C916; Fri, 11 Nov 2016 10:34:22 -0800 (PST) Received: from [10.2.206.198] (e104437-lin.cambridge.arm.com [10.2.206.198]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6FCA83F24D; Fri, 11 Nov 2016 10:34:21 -0800 (PST) From: Jiong Wang Subject: [4/9][AArch64] Return address protection on AArch64 To: gcc-patches References: <72418e98-a400-c503-e8ce-c3fbe1ecc4a7@foss.arm.com> <64dd1b38-ff0a-5df0-1d3c-2fbf083e2697@foss.arm.com> Cc: "Richard Earnshaw (lists)" , James Greenhalgh Message-ID: Date: Fri, 11 Nov 2016 18:34:20 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes As described in the cover letter, this patch implements return address signing for AArch64, it's controlled by the new option: -msign-return-address=[none | non-leaf | all] "none" means don't do return address signing at all on any function. "non-leaf" means only sign non-leaf function. "all" means sign all functions. Return address signing is currently disabled on ILP32. I haven't tested it. The instructions added in the architecture are of 2 kinds. * In the NOP instruction space, which allows binaries to run without any traps on older versions of the architecture. This doesn't give any additional protection on older hardware but allows for the same binary to be used on earlier versions of the architecture and newer versions of the architecture. * New instructions that are only valid for v8.3 and will trap if used on earlier versions of the architecture. At default, once return address signing is enabled, it will only generates NOP instruction. While if -march=armv8.3-a specified, GCC will try to use the most efficient pointer authentication instruction as it can. The architecture has 2 user invisible system keys for signing and creating signed addresses as part of these instructions. For some use case, the user might want to use difference key for different functions. The new option "-msign-return-address-key=key_name" let GCC select the key used for return address signing. Permissible values are "a_key" for A key and "b_key" for B key, and this option are supported by function target attribute and LTO will hopefully just work. gcc/ 2016-11-09 Jiong Wang * config/aarch64/aarch64-opts.h (aarch64_pauth_key_index): New enum. (aarch64_function_type): New enum. * config/aarch64/aarch64-protos.h (aarch64_output_sign_auth_reg): New declaration. * config/aarch64/aarch64.c (aarch64_expand_prologue): Sign return address before it's pushed onto stack. (aarch64_expand_epilogue): Authenticate return address fetched from stack. (aarch64_output_sign_auth_reg): New function. (aarch64_override_options): Sanity check for ILP32 and ISA level. (aarch64_attributes): New function attributes for "sign-return-address", "pauth-key". * config/aarch64/aarch64.md (UNSPEC_AUTH_REG, UNSPEC_AUTH_REG1716, UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN, UNSPEC_STRIP_X30_SIGN): New unspecs. ("*do_return"): Generate combined instructions according to key index. ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716", "strip_reg_sign", "strip_lr_sign"): New. * config/aarch64/aarch64.opt (msign-return-address, mpauth-key): New. * config/aarch64/predicates.md (aarch64_const0_const1): New predicate. * doc/extend.texi (AArch64 Function Attributes): Documents "sign-return-address=", "pauth-key". * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=", "-pauth-key". gcc/testsuite/ 2016-11-09 Jiong Wang * gcc.target/aarch64/return_address_sign_1.c: New testcase. * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase. diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h index c550a74..41c14b3 100644 --- a/gcc/config/aarch64/aarch64-opts.h +++ b/gcc/config/aarch64/aarch64-opts.h @@ -73,4 +73,30 @@ enum aarch64_code_model { AARCH64_CMODEL_LARGE }; +/* AArch64 pointer authentication key indexes. "key_array" in + aarch64_output_sign_auth_reg depends on the order of this enum. */ +enum aarch64_pauth_key_index +{ + /* A key for instruction pointer. */ + AARCH64_PAUTH_IKEY_A = 0, + /* B key for instruction pointer. */ + AARCH64_PAUTH_IKEY_B, + /* A key for data pointer. */ + AARCH64_PAUTH_DKEY_A, + /* B key for data pointer. */ + AARCH64_PAUTH_DKEY_B, + /* A key for general pointer. */ + AARCH64_PAUTH_GKEY_A +}; + +/* Function types -msign-return-address should sign. */ +enum aarch64_function_type { + /* Don't sign any function. */ + AARCH64_FUNCTION_NONE, + /* Non-leaf functions. */ + AARCH64_FUNCTION_NON_LEAF, + /* All functions. */ + AARCH64_FUNCTION_ALL +}; + #endif diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 3cdd69b..fa6d16b 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -329,6 +329,7 @@ rtx aarch64_reverse_mask (enum machine_mode); bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT); char *aarch64_output_scalar_simd_mov_immediate (rtx, machine_mode); char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned); +const char *aarch64_output_sign_auth_reg (rtx *, bool, bool); bool aarch64_pad_arg_upward (machine_mode, const_tree); bool aarch64_pad_reg_upward (machine_mode, const_tree, bool); bool aarch64_regno_ok_for_base_p (int, bool); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 3e663eb..8401fa4 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3204,6 +3204,13 @@ aarch64_expand_prologue (void) unsigned reg2 = cfun->machine->frame.wb_candidate2; rtx_insn *insn; + if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN) + emit_insn (gen_sign_reg (gen_rtx_REG (Pmode, LR_REGNUM), + gen_rtx_REG (Pmode, LR_REGNUM), + stack_pointer_rtx, + GEN_INT (aarch64_pauth_key), + const0_rtx)); + if (flag_stack_usage_info) current_function_static_stack_size = frame_size; @@ -3340,6 +3347,20 @@ aarch64_expand_epilogue (bool for_sibcall) RTX_FRAME_RELATED_P (insn) = 1; } + /* sibcall won't generate normally return, therefore we need to authenticate + at here. TARGET_PAUTH will allow GCC to use combined authentication + instruction which we prefer, eh_return path can't do combined + authentication, as the following stack adjustment will update CFA to + handler's CFA while we want to use the CFA of the function which calls + __builtin_eh_return. */ + if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN + && (for_sibcall || !TARGET_PAUTH || crtl->calls_eh_return)) + emit_insn (gen_auth_reg (gen_rtx_REG (Pmode, LR_REGNUM), + gen_rtx_REG (Pmode, LR_REGNUM), + stack_pointer_rtx, + GEN_INT (aarch64_pauth_key), + const0_rtx)); + /* Stack adjustment for exception handler. */ if (crtl->calls_eh_return) { @@ -5434,6 +5455,74 @@ aarch64_output_casesi (rtx *operands) return ""; } +/* Output ARMv8.3-A pointer sign instructions when SIGN_P be TRUE or + authentication instructions when it's FALSE. X1716_P is TRUE if this + function is called from fixed register patterns, i.e sign_reg1716 or + auth_reg1716. */ + +const char* +aarch64_output_sign_auth_reg (rtx *operands, bool sign_p, bool x1716_p) +{ + char buf[64]; + const char *action = sign_p ? "pac" : "aut"; + /* Assembler suffix for key, this array should be synced with + "enum aarch64_pauth_key_index" in aarch64-opts.h. */ + const char key_array[5] = {'a', 'b', 'a', 'b', 'a'}; + char key_char + = key_array[x1716_p ? INTVAL (operands[0]) : INTVAL (operands[3])]; + char type + = (x1716_p ? INTVAL (operands[1]) : INTVAL (operands[4])) ? 'd' : 'i'; + unsigned FM = ((sign_p ? 0 : 1) << 2 /* F bit. */ + | ((key_char == 'a' ? 0 : 1) << 1)); /* M bit. */ + + if (x1716_p + || (REGNO (operands[0]) == R17_REGNUM + && REG_P (operands[2]) && REGNO (operands[2]) == R16_REGNUM)) + { + /* PAC*1716/AUT*1716 only support code pointer. */ + gcc_assert (type == 'i'); + unsigned CRm = 0x1; + unsigned FMS = (FM /* F and M bits. */ + | 0); /* S bit. */ + snprintf (buf, sizeof (buf), "hint\t%d %s%s%c1716", (CRm << 3) | FMS, + ASM_COMMENT_START, action, key_char); + } + else if (REGNO (operands[0]) == LR_REGNUM + && REG_P (operands[2]) && REGNO (operands[2]) == SP_REGNUM) + { + /* PAC*SP/AUT*SP only support code pointer. */ + gcc_assert (type == 'i'); + unsigned CRm = 0x3; + unsigned FMS = (FM /* F and M bits. */ + | 1); /* S bit. */ + snprintf (buf, sizeof (buf), "hint\t%d %s%si%csp", (CRm << 3) | FMS, + ASM_COMMENT_START, action, key_char); + } + else if (REGNO (operands[0]) == LR_REGNUM && operands[2] == const0_rtx) + { + /* PAC*Z/AUT*Z only support code pointer. */ + gcc_assert (type == 'i'); + unsigned CRm = 0x3; + unsigned FMS = (FM /* F and M bits. */ + | 0); /* S bit. */ + snprintf (buf, sizeof (buf), "hint\t%d %s%si%cz", (CRm << 3) | FMS, + ASM_COMMENT_START, action, key_char); + } + else if (operands[2] == const0_rtx) + { + /* General format PAC* Xd, Xn/AUT* Xd, Xn. */ + snprintf (buf, sizeof (buf), "%s%cz%c %%0", action, type, key_char); + } + else + { + /* General format PAC*Z* Xd, Xn/AUT*Z* Xd, Xn. */ + snprintf (buf, sizeof (buf), "%s%c%c %%0, %%2", action, type, key_char); + } + + output_asm_insn (buf, operands); + + return ""; +} /* Return size in bits of an arithmetic operand which is shifted/scaled and masked such that it is suitable for a UXTB, UXTH, or UXTW extend @@ -8466,6 +8555,9 @@ aarch64_override_options (void) error ("Assembler does not support -mabi=ilp32"); #endif + if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32) + error ("Return address signing is only supported on LP64"); + /* Make sure we properly set up the explicit options. */ if ((aarch64_cpu_string && valid_cpu) || (aarch64_tune_string && valid_tune)) @@ -8849,6 +8941,10 @@ static const struct aarch64_attribute_info aarch64_attributes[] = { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ }, { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune, OPT_mtune_ }, + { "sign-return-address", aarch64_attr_enum, false, NULL, + OPT_msign_return_address_ }, + { "pauth-key", aarch64_attr_enum, false, NULL, + OPT_mpauth_key_ }, { NULL, aarch64_attr_custom, false, NULL, OPT____ } }; diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 70efbe9..4bfadb5 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -963,4 +963,11 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); extern tree aarch64_fp16_type_node; extern tree aarch64_fp16_ptr_type_node; +/* Return address signing is enabled for AARCH64_FUNCTION_ALL, or for + AARCH64_FUNCTION_NON_LEAF. */ +#define AARCH64_ENABLE_RETURN_ADDRESS_SIGN \ + (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL \ + || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF \ + && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0)) + #endif /* GCC_AARCH64_H */ diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index c95258b..754ea00 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -66,6 +66,8 @@ ) (define_c_enum "unspec" [ + UNSPEC_AUTH_REG + UNSPEC_AUTH_REG1716 UNSPEC_CASESI UNSPEC_CRC32B UNSPEC_CRC32CB @@ -108,6 +110,8 @@ UNSPEC_PRLG_STK UNSPEC_RBIT UNSPEC_SCVTF + UNSPEC_SIGN_REG + UNSPEC_SIGN_REG1716 UNSPEC_SISD_NEG UNSPEC_SISD_SSHL UNSPEC_SISD_USHL @@ -119,6 +123,8 @@ UNSPEC_ST2_LANE UNSPEC_ST3_LANE UNSPEC_ST4_LANE + UNSPEC_STRIP_REG_SIGN + UNSPEC_STRIP_X30_SIGN UNSPEC_TLS UNSPEC_TLSDESC UNSPEC_TLSLE12 @@ -574,7 +580,21 @@ (define_insn "*do_return" [(return)] "" - "ret" + { + if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN + && TARGET_PAUTH + && !crtl->calls_eh_return) + { + if (aarch64_pauth_key == AARCH64_PAUTH_IKEY_A) + return "retaa"; + else if (aarch64_pauth_key == AARCH64_PAUTH_IKEY_B) + return "retab"; + + gcc_unreachable (); + } + + return "ret"; + } [(set_attr "type" "branch")] ) @@ -5210,6 +5230,114 @@ [(set_attr "length" "0")] ) +;; ARMv8.3-A pointer authentication support +;; OPERANDS[0] - Result. +;; OPERANDS[1] - The value we want to sign or authenticate. +;; OPERANDS[2] - The salt used for signing or authentication. +;; OPERANDS[3] - Key index. See aarch64_pauth_key_type in aarch64-opts.h. +;; OPERANDS[4] - Pointer type. 0 for code, 1 for data. +;; +;; These patterns are available for all architectures. For architectures +;; without TARGET_PAUTH, they will become nop, this let the user write portable +;; software which can get pointer authentication on new hardware while still +;; runs OK on old hardware. + +(define_insn "sign_reg" + [(set (match_operand:DI 0 "register_operand" "=rk") + (unspec:DI [(match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "aarch64_reg_or_zero" "rkZ") + (match_operand:DI 3 "aarch64_const0_const1" "i") + (match_operand:DI 4 "aarch64_const0_const1" "i")] + UNSPEC_SIGN_REG))] + "" + { + return aarch64_output_sign_auth_reg (operands, /* sign_p */true, + /* x1716_p */false); + } +) + +(define_insn "sign_reg1716" + [(set (reg:DI R17_REGNUM) + (unspec:DI [(reg:DI R17_REGNUM) + (reg:DI R16_REGNUM) + (match_operand:DI 0 "aarch64_const0_const1" "i") + (match_operand:DI 1 "aarch64_const0_const1" "i")] + UNSPEC_SIGN_REG1716))] + "" + { + return aarch64_output_sign_auth_reg (operands, /* sign_p */true, + /* x1716_p */true); + } +) + +(define_insn "auth_reg" + [(set (match_operand:DI 0 "register_operand" "=rk") + (unspec:DI [(match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "aarch64_reg_or_zero" "rkZ") + (match_operand:DI 3 "aarch64_const0_const1" "i") + (match_operand:DI 4 "aarch64_const0_const1" "i")] + UNSPEC_AUTH_REG))] + "" + { + return aarch64_output_sign_auth_reg (operands, /* sign_p */false, + /* x1716_p */false); + } +) + +(define_insn "auth_reg1716" + [(set (reg:DI R17_REGNUM) + (unspec:DI [(reg:DI R17_REGNUM) + (reg:DI R16_REGNUM) + (match_operand:DI 0 "aarch64_const0_const1" "i") + (match_operand:DI 1 "aarch64_const0_const1" "i")] + UNSPEC_AUTH_REG1716))] + "" + { + return aarch64_output_sign_auth_reg (operands, /* sign_p */false, + /* x1716_p */true); + } +) + +(define_insn "strip_reg_sign" + [(set (match_operand:DI 0 "register_operand" "=rk") + (unspec:DI [(match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "immediate_operand" "i")] + UNSPEC_STRIP_REG_SIGN))] + "" + { + if (REGNO (operands[1]) == LR_REGNUM) + { + if (INTVAL (operands[2]) == 0) + return "xpaclri"; + else + /* LR can't be used for data strip. */ + gcc_unreachable (); + } + else + { + if (INTVAL (operands[2]) == 0) + return "xpaci\t%0"; + else + return "xpacd\t%0"; + } + } +) + +(define_insn "strip_lr_sign" + [(set (reg:DI R30_REGNUM) + (unspec:DI [(reg:DI R30_REGNUM) + (match_operand:DI 0 "immediate_operand" "i")] + UNSPEC_STRIP_X30_SIGN))] + "" + { + if (INTVAL (operands[0]) == 0) + return "xpaclri"; + else + /* LR can't be used for data strip. */ + gcc_unreachable (); + } +) + ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and ;; all of memory. This blocks insns from being moved across this point. diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 82e9f5b..15fac36 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -149,6 +149,37 @@ mpc-relative-literal-loads Target Report Save Var(pcrelative_literal_loads) Init(2) Save PC relative literal loads. +msign-return-address= +Target RejectNegative Report Joined Enum(aarch64_ra_sign_scope_t) Var(aarch64_ra_sign_scope) Init(AARCH64_FUNCTION_NONE) Save +Select return address signing scope + +Enum +Name(aarch64_ra_sign_scope_t) Type(enum aarch64_function_type) +Supported AArch64 return address signing scope (for use with -msign-return-address= option): + +EnumValue +Enum(aarch64_ra_sign_scope_t) String(none) Value(AARCH64_FUNCTION_NONE) + +EnumValue +Enum(aarch64_ra_sign_scope_t) String(non-leaf) Value(AARCH64_FUNCTION_NON_LEAF) + +EnumValue +Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL) + +mpauth-key= +Target RejectNegative Report Joined Enum(aarch64_pauth_key_t) Var(aarch64_pauth_key) Init(AARCH64_PAUTH_IKEY_A) Save +Select pointer authentication key + +Enum +Name(aarch64_pauth_key_t) Type(enum aarch64_pauth_key_index) +Known AArch64 pointer authentication keys (for use with the -mpauth-key= option): + +EnumValue +Enum(aarch64_pauth_key_t) String(a_key) Value(AARCH64_PAUTH_IKEY_A) + +EnumValue +Enum(aarch64_pauth_key_t) String(b_key) Value(AARCH64_PAUTH_IKEY_B) + mlow-precision-recip-sqrt Common Var(flag_mrecip_low_precision_sqrt) Optimization Enable the reciprocal square root approximation. Enabling this reduces diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index ebda6d8..73a66d5 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -35,6 +35,10 @@ (and (match_code "const_int") (match_test "op == CONST0_RTX (mode)"))) +(define_predicate "aarch64_const0_const1" + (ior (match_test "op == const0_rtx") + (match_test "op == const1_rtx"))) + (define_predicate "aarch64_ccmp_immediate" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), -31, 31)"))) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 8cb93ab..204cf45 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3509,6 +3509,18 @@ Specifies the core for which to tune the performance of this function and also whose architectural features to use. The behavior and valid arguments are the same as for the @option{-mcpu=} command-line option. +@item sign-return-address +@cindex @code{sign-return-address} function attribute, AArch64 +Select the function scope we want to do return address signing on. The behavior +and permissible arguments are the same as for the command-line option +@option{-msign-return-address=}. The default value is @code{none} + +@item pauth-key +@cindex @code{pauth-key} function attribute, AArch64 +Specify the key used for return address signing for this function. The behavior +and permissible arguments are the same as for the command-line option +@option{-mpauth-key=}. The default key is @code{a_key}. + @end table The above target attributes can be specified as follows: diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 18ab6d9..e7f842f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -13344,6 +13344,19 @@ 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 -msign-return-address=@var{scope} +@opindex msign-return-address +Select the function scope we want to do return address signing on. Permissible +values are @samp{none}, @samp{none-leaf} and @samp{all}. @samp{none} means +return address signing is disabled. @samp{non-leaf} enables it for non-leaf +functions. @samp{all} for all functions and is the default value. + +@item -mpauth-key=@var{key_name} +@opindex mpauth-key +Select the key used for return address signing. Permissible values are +@samp{a_key} for A key and @samp{b_key} for B key. @samp{a_key} is the default +value. + @end table @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c new file mode 100644 index 0000000..b786b09 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c @@ -0,0 +1,57 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msign-return-address=all" } */ + +int foo (int); +int bar (int, int); + +/* sibcall only. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func1 (int a, int b) +{ + /* paciasp */ + return foo (a + b); + /* autiasp */ +} + +/* non-leaf function with sibcall. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func2 (int a, int b) +{ + /* paciasp */ + if (a < b) + return b; + + a = foo (b); + + return foo (a); + /* autiasp */ +} + +/* non-leaf function, legacy arch. */ +int __attribute__ ((target ("arch=armv8.2-a"))) +func3 (int a, int b, int c) +{ + /* paciasp */ + return a + foo (b) + c; + /* autiasp */ +} + +/* non-leaf function. */ +int __attribute__ ((target ("arch=armv8.3-a, pauth-key=b_key"))) +func4 (int a, int b, int c) +{ + /* paciasp */ + return a + foo (b) + c; + /* retab */ +} + +int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none"))) +func4_disable (int a, int b, int c, int d) +{ + return c + bar (a, b) + d; +} + +/* { dg-final { scan-assembler-times "autiasp" 3 } } */ +/* { dg-final { scan-assembler-times "paciasp" 3 } } */ +/* { dg-final { scan-assembler-times "pacibsp" 1 } } */ +/* { dg-final { scan-assembler-times "retab" 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c new file mode 100644 index 0000000..f44644d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c @@ -0,0 +1,57 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msign-return-address=non-leaf" } */ + +int foo (int); +int bar (int, int); + +/* sibcall only. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func1 (int a, int b) +{ + /* No authentication. */ + return foo (a + b); +} + +/* non-leaf function with sibcall. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func2 (int a, int b) +{ + /* paciasp */ + if (a < b) + return b; + + a = foo (b); + + return foo (a); + /* autiasp */ +} + +/* non-leaf function, legacy arch. */ +int __attribute__ ((target ("arch=armv8.2-a, pauth-key=b_key"))) +func3 (int a, int b, int c) +{ + /* pacibsp */ + return a + foo (b) + c; + /* autibsp */ +} + +/* non-leaf function. */ +int __attribute__ ((target ("arch=armv8.3-a, pauth-key=b_key"))) +func4 (int a, int b, int c) +{ + /* pacibsp */ + return a + foo (b) + c; + /* retab */ +} + +int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none"))) +func4_disable (int a, int b, int c, int d) +{ + return c + bar (a, b) + d; +} + +/* { dg-final { scan-assembler-times "paciasp" 1 } } */ +/* { dg-final { scan-assembler-times "autiasp" 1 } } */ +/* { dg-final { scan-assembler-times "pacibsp" 2 } } */ +/* { dg-final { scan-assembler-times "autibsp" 1 } } */ +/* { dg-final { scan-assembler-times "retab" 1 } } */