diff options
author | Jiong Wang <jiong.wang@arm.com> | 2017-01-20 00:03:20 +0000 |
---|---|---|
committer | Jiong Wang <jiwang@gcc.gnu.org> | 2017-01-20 00:03:20 +0000 |
commit | db58fd8954f5dfd868dbed110f2c8a04bb4b0753 (patch) | |
tree | 37f06bdc0b1b1122a695d6a56a818ba288394b1f /gcc | |
parent | c9038c70bde89e7023d21fe8752b9d6f0b0e3779 (diff) | |
download | gcc-db58fd8954f5dfd868dbed110f2c8a04bb4b0753.zip gcc-db58fd8954f5dfd868dbed110f2c8a04bb4b0753.tar.gz gcc-db58fd8954f5dfd868dbed110f2c8a04bb4b0753.tar.bz2 |
[AArch64][1/4] Support Return address protection on AArch64
gcc/
* config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
* config/aarch64/aarch64-protos.h
(aarch64_return_address_signing_enabled): New declaration.
* config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
New function.
(aarch64_expand_prologue): Sign return address before it's pushed onto
stack.
(aarch64_expand_epilogue): Authenticate return address fetched from
stack.
(aarch64_override_options): Sanity check for ILP32 and ISA level.
(aarch64_attributes): New function attributes for "sign-return-address".
* config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
("*do_return"): Generate combined instructions according to key index.
("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
* config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer
iterators.
(pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
* config/aarch64/aarch64.opt (msign-return-address=): New.
* doc/extend.texi (AArch64 Function Attributes): Documents
"sign-return-address=".
* doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".
gcc/testsuite/
* gcc.target/aarch64/return_address_sign_1.c: New testcase for no
combined instructions.
* gcc.target/aarch64/return_address_sign_2.c: New testcase for combined
instructions.
* gcc.target/aarch64/return_address_sign_3.c: New testcase for disable
of pointer authentication.
From-SVN: r244666
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 25 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-opts.h | 10 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 44 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.md | 47 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.opt | 17 | ||||
-rw-r--r-- | gcc/config/aarch64/iterators.md | 16 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 6 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c | 51 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c | 21 |
13 files changed, 271 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index affd2f5..1f959bb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2017-01-19 Jiong Wang <jiong.wang@arm.com> + + * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum. + * config/aarch64/aarch64-protos.h + (aarch64_return_address_signing_enabled): New declaration. + * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled): + New function. + (aarch64_expand_prologue): Sign return address before it's pushed onto + stack. + (aarch64_expand_epilogue): Authenticate return address fetched from + stack. + (aarch64_override_options): Sanity check for ILP32 and ISA level. + (aarch64_attributes): New function attributes for "sign-return-address". + * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP, + UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs. + ("*do_return"): Generate combined instructions according to key index. + ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New. + * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer + iterators. + (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes. + * config/aarch64/aarch64.opt (msign-return-address=): New. + * doc/extend.texi (AArch64 Function Attributes): Documents + "sign-return-address=". + * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=". + 2017-01-19 Matthew Fortune <matthew.fortune@imgtec.com> * doc/invoke.texi: Add missing -mlxc1-sxc1 options to diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h index 9f37b9b..ba5d052 100644 --- a/gcc/config/aarch64/aarch64-opts.h +++ b/gcc/config/aarch64/aarch64-opts.h @@ -71,4 +71,14 @@ enum aarch64_code_model { AARCH64_CMODEL_LARGE }; +/* 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 7a9a21ea..f55d4ba 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -386,6 +386,7 @@ void aarch64_emit_call_insn (rtx); void aarch64_register_pragmas (void); void aarch64_relayout_simd_types (void); void aarch64_reset_previous_fndecl (void); +bool aarch64_return_address_signing_enabled (void); void aarch64_save_restore_target_globals (tree); /* Initialize builtins for SIMD intrinsics. */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 4432cae..62baf58 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3123,6 +3123,22 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2, } } +/* Return TRUE if return address signing should be enabled for the current + function, otherwise return FALSE. */ + +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. */ + return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL + || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF + && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0)); +} + /* Emit code to save the callee-saved registers from register number START to LIMIT to the stack at the location starting at offset START_OFFSET, skipping any write-back candidates if SKIP_WB is true. */ @@ -3541,6 +3557,10 @@ aarch64_expand_prologue (void) unsigned reg2 = cfun->machine->frame.wb_candidate2; rtx_insn *insn; + /* Sign return address for functions. */ + if (aarch64_return_address_signing_enabled ()) + emit_insn (gen_pacisp ()); + if (flag_stack_usage_info) current_function_static_stack_size = frame_size; @@ -3677,6 +3697,25 @@ aarch64_expand_epilogue (bool for_sibcall) RTX_FRAME_RELATED_P (insn) = 1; } + /* We prefer to emit the combined return/authenticate instruction RETAA, + however there are three cases in which we must instead emit an explicit + authentication instruction. + + 1) Sibcalls don't return in a normal way, so if we're about to call one + we must authenticate. + + 2) The RETAA instruction is not available before ARMv8.3-A, so if we are + generating code for !TARGET_ARMV8_3 we can't use it and must + explicitly authenticate. + + 3) On an eh_return path we make extra stack adjustments to update the + canonical frame address to be the exception handler's CFA. We want + to authenticate using the CFA of the function which calls eh_return. + */ + if (aarch64_return_address_signing_enabled () + && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return)) + emit_insn (gen_autisp ()); + /* Stack adjustment for exception handler. */ if (crtl->calls_eh_return) { @@ -8889,6 +8928,9 @@ aarch64_override_options (void) error ("Assembler does not support -mabi=ilp32"); #endif + if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32) + sorry ("Return address signing is only supported for -mabi=lp64"); + /* Make sure we properly set up the explicit options. */ if ((aarch64_cpu_string && valid_cpu) || (aarch64_tune_string && valid_tune)) @@ -9272,6 +9314,8 @@ 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_ }, { NULL, aarch64_attr_custom, false, NULL, OPT____ } }; diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index a3be2b9..a693a3b 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -67,6 +67,8 @@ ) (define_c_enum "unspec" [ + UNSPEC_AUTI1716 + UNSPEC_AUTISP UNSPEC_CASESI UNSPEC_CRC32B UNSPEC_CRC32CB @@ -106,6 +108,8 @@ UNSPEC_LD4_LANE UNSPEC_MB UNSPEC_NOP + UNSPEC_PACI1716 + UNSPEC_PACISP UNSPEC_PRLG_STK UNSPEC_RBIT UNSPEC_SCVTF @@ -135,6 +139,7 @@ UNSPEC_RSQRTE UNSPEC_RSQRTS UNSPEC_NZCV + UNSPEC_XPACLRI ]) (define_c_enum "unspecv" [ @@ -575,7 +580,14 @@ (define_insn "*do_return" [(return)] "" - "ret" + { + if (aarch64_return_address_signing_enabled () + && TARGET_ARMV8_3 + && !crtl->calls_eh_return) + return "retaa"; + + return "ret"; + } [(set_attr "type" "branch")] ) @@ -5322,6 +5334,39 @@ [(set_attr "length" "0")] ) +;; Pointer authentication patterns are always provided. In architecture +;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs. +;; This lets the user write portable software which authenticates pointers +;; when run on something which implements ARMv8.3-A, and which runs +;; correctly, but does not authenticate pointers, where ARMv8.3-A is not +;; implemented. + +;; Signing/Authenticating R30 using SP as the salt. + +(define_insn "<pauth_mnem_prefix>sp" + [(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"; +) + +;; Signing/Authenticating X17 using X16 as the salt. + +(define_insn "<pauth_mnem_prefix>1716" + [(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"; +) + +;; Stripping the signature in R30. + +(define_insn "xpaclri" + [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))] + "" + "hint\t7 // xpaclri" +) + ;; 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 56b920d..5436884 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -149,6 +149,23 @@ 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) + 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/iterators.md b/gcc/config/aarch64/iterators.md index e2377c1..c59d31e 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -1032,6 +1032,10 @@ (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_17_16 [UNSPEC_PACI1716 UNSPEC_AUTI1716]) + (define_int_iterator VQDMULH [UNSPEC_SQDMULH UNSPEC_SQRDMULH]) (define_int_iterator USSUQADD [UNSPEC_SUQADD UNSPEC_USQADD]) @@ -1218,6 +1222,18 @@ (UNSPEC_FCVTZS "fcvtzs") (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")]) + +;; 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 perm_insn [(UNSPEC_ZIP1 "zip") (UNSPEC_ZIP2 "zip") (UNSPEC_TRN1 "trn") (UNSPEC_TRN2 "trn") (UNSPEC_UZP1 "uzp") (UNSPEC_UZP2 "uzp")]) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 67846ef..a3fbec0 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3513,6 +3513,12 @@ 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 on which return address signing will be applied. The +behaviour and permissible arguments are the same as for the command-line option +@option{-msign-return-address=}. The default value is @code{none}. + @end table The above target attributes can be specified as follows: diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 06e84fc..79a40f1 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -14100,6 +14100,14 @@ 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 on which return address signing will be applied. +Permissible values are @samp{none}, which disables return address signing, +@samp{non-leaf}, which enables pointer signing for functions which are not leaf +functions, and @samp{all}, which enables pointer signing for all functions. The +default value is @samp{none}. + @end table @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0f1de62..c868ea7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2017-01-19 Jiong Wang <jiong.wang@arm.com> + + * gcc.target/aarch64/return_address_sign_1.c: New testcase for no + combined instructions. + * gcc.target/aarch64/return_address_sign_2.c: New testcase for combined + instructions. + * gcc.target/aarch64/return_address_sign_3.c: New testcase for disable + of pointer authentication. + 2017-01-19 Michael Meissner <meissner@linux.vnet.ibm.com> * gcc.target/powerpc/float128-hw.c: Do not require IEEE 128-bit 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..fda72a4 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c @@ -0,0 +1,51 @@ +/* Testing return address signing where no combined instructions used. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msign-return-address=all" } */ + +int foo (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 */ +} + +/* eh_return. */ +void __attribute__ ((target ("arch=armv8.3-a"))) +func4 (long offset, void *handler, int *ptr, int imm1, int imm2) +{ + /* paciasp */ + *ptr = imm1 + foo (imm1) + imm2; + __builtin_eh_return (offset, handler); + /* autiasp */ + return; +} + +/* { dg-final { scan-assembler-times "autiasp" 4 } } */ +/* { dg-final { scan-assembler-times "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 new file mode 100644 index 0000000..54fe47a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c @@ -0,0 +1,17 @@ +/* Testing return address signing where combined instructions used. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msign-return-address=all" } */ + +int foo (int); +int bar (int, int); + +int __attribute__ ((target ("arch=armv8.3-a"))) +func1 (int a, int b, int c) +{ + /* paciasp */ + return a + foo (b) + c; + /* retaa */ +} + +/* { dg-final { scan-assembler-times "paciasp" 1 } } */ +/* { dg-final { scan-assembler-times "retaa" 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c new file mode 100644 index 0000000..adc5eff --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c @@ -0,0 +1,21 @@ +/* Testing the disable of return address signing. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msign-return-address=all" } */ + +int bar (int, int); + +int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=non-leaf"))) +func1_leaf (int a, int b, int c, int d) +{ + return a + b + c + d; +} + +int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none"))) +func2_none (int a, int b, int c, int d) +{ + return c + bar (a, b) + d; +} + +/* { dg-final { scan-assembler-not "paciasp" } } */ +/* { dg-final { scan-assembler-not "autiasp" } } */ +/* { dg-final { scan-assembler-not "retaa" } } */ |