Commit db58fd89 by Jiong Wang Committed by Jiong Wang

[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
parent c9038c70
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> 2017-01-19 Matthew Fortune <matthew.fortune@imgtec.com>
* doc/invoke.texi: Add missing -mlxc1-sxc1 options to * doc/invoke.texi: Add missing -mlxc1-sxc1 options to
......
...@@ -71,4 +71,14 @@ enum aarch64_code_model { ...@@ -71,4 +71,14 @@ enum aarch64_code_model {
AARCH64_CMODEL_LARGE 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 #endif
...@@ -386,6 +386,7 @@ void aarch64_emit_call_insn (rtx); ...@@ -386,6 +386,7 @@ void aarch64_emit_call_insn (rtx);
void aarch64_register_pragmas (void); void aarch64_register_pragmas (void);
void aarch64_relayout_simd_types (void); void aarch64_relayout_simd_types (void);
void aarch64_reset_previous_fndecl (void); void aarch64_reset_previous_fndecl (void);
bool aarch64_return_address_signing_enabled (void);
void aarch64_save_restore_target_globals (tree); void aarch64_save_restore_target_globals (tree);
/* Initialize builtins for SIMD intrinsics. */ /* Initialize builtins for SIMD intrinsics. */
......
...@@ -3123,6 +3123,22 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2, ...@@ -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 /* 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, to LIMIT to the stack at the location starting at offset START_OFFSET,
skipping any write-back candidates if SKIP_WB is true. */ skipping any write-back candidates if SKIP_WB is true. */
...@@ -3541,6 +3557,10 @@ aarch64_expand_prologue (void) ...@@ -3541,6 +3557,10 @@ aarch64_expand_prologue (void)
unsigned reg2 = cfun->machine->frame.wb_candidate2; unsigned reg2 = cfun->machine->frame.wb_candidate2;
rtx_insn *insn; rtx_insn *insn;
/* Sign return address for functions. */
if (aarch64_return_address_signing_enabled ())
emit_insn (gen_pacisp ());
if (flag_stack_usage_info) if (flag_stack_usage_info)
current_function_static_stack_size = frame_size; current_function_static_stack_size = frame_size;
...@@ -3677,6 +3697,25 @@ aarch64_expand_epilogue (bool for_sibcall) ...@@ -3677,6 +3697,25 @@ aarch64_expand_epilogue (bool for_sibcall)
RTX_FRAME_RELATED_P (insn) = 1; 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. */ /* Stack adjustment for exception handler. */
if (crtl->calls_eh_return) if (crtl->calls_eh_return)
{ {
...@@ -8889,6 +8928,9 @@ aarch64_override_options (void) ...@@ -8889,6 +8928,9 @@ aarch64_override_options (void)
error ("Assembler does not support -mabi=ilp32"); error ("Assembler does not support -mabi=ilp32");
#endif #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. */ /* Make sure we properly set up the explicit options. */
if ((aarch64_cpu_string && valid_cpu) if ((aarch64_cpu_string && valid_cpu)
|| (aarch64_tune_string && valid_tune)) || (aarch64_tune_string && valid_tune))
...@@ -9272,6 +9314,8 @@ static const struct aarch64_attribute_info aarch64_attributes[] = ...@@ -9272,6 +9314,8 @@ static const struct aarch64_attribute_info aarch64_attributes[] =
{ "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ }, { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ },
{ "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune, { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune,
OPT_mtune_ }, OPT_mtune_ },
{ "sign-return-address", aarch64_attr_enum, false, NULL,
OPT_msign_return_address_ },
{ NULL, aarch64_attr_custom, false, NULL, OPT____ } { NULL, aarch64_attr_custom, false, NULL, OPT____ }
}; };
......
...@@ -67,6 +67,8 @@ ...@@ -67,6 +67,8 @@
) )
(define_c_enum "unspec" [ (define_c_enum "unspec" [
UNSPEC_AUTI1716
UNSPEC_AUTISP
UNSPEC_CASESI UNSPEC_CASESI
UNSPEC_CRC32B UNSPEC_CRC32B
UNSPEC_CRC32CB UNSPEC_CRC32CB
...@@ -106,6 +108,8 @@ ...@@ -106,6 +108,8 @@
UNSPEC_LD4_LANE UNSPEC_LD4_LANE
UNSPEC_MB UNSPEC_MB
UNSPEC_NOP UNSPEC_NOP
UNSPEC_PACI1716
UNSPEC_PACISP
UNSPEC_PRLG_STK UNSPEC_PRLG_STK
UNSPEC_RBIT UNSPEC_RBIT
UNSPEC_SCVTF UNSPEC_SCVTF
...@@ -135,6 +139,7 @@ ...@@ -135,6 +139,7 @@
UNSPEC_RSQRTE UNSPEC_RSQRTE
UNSPEC_RSQRTS UNSPEC_RSQRTS
UNSPEC_NZCV UNSPEC_NZCV
UNSPEC_XPACLRI
]) ])
(define_c_enum "unspecv" [ (define_c_enum "unspecv" [
...@@ -575,7 +580,14 @@ ...@@ -575,7 +580,14 @@
(define_insn "*do_return" (define_insn "*do_return"
[(return)] [(return)]
"" ""
"ret" {
if (aarch64_return_address_signing_enabled ()
&& TARGET_ARMV8_3
&& !crtl->calls_eh_return)
return "retaa";
return "ret";
}
[(set_attr "type" "branch")] [(set_attr "type" "branch")]
) )
...@@ -5322,6 +5334,39 @@ ...@@ -5322,6 +5334,39 @@
[(set_attr "length" "0")] [(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 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point. ;; all of memory. This blocks insns from being moved across this point.
......
...@@ -149,6 +149,23 @@ mpc-relative-literal-loads ...@@ -149,6 +149,23 @@ mpc-relative-literal-loads
Target Report Save Var(pcrelative_literal_loads) Init(2) Save Target Report Save Var(pcrelative_literal_loads) Init(2) Save
PC relative literal loads. 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 mlow-precision-recip-sqrt
Common Var(flag_mrecip_low_precision_sqrt) Optimization Common Var(flag_mrecip_low_precision_sqrt) Optimization
Enable the reciprocal square root approximation. Enabling this reduces Enable the reciprocal square root approximation. Enabling this reduces
......
...@@ -1032,6 +1032,10 @@ ...@@ -1032,6 +1032,10 @@
(define_int_iterator FMAXMIN_UNS [UNSPEC_FMAX UNSPEC_FMIN (define_int_iterator FMAXMIN_UNS [UNSPEC_FMAX UNSPEC_FMIN
UNSPEC_FMAXNM UNSPEC_FMINNM]) 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 VQDMULH [UNSPEC_SQDMULH UNSPEC_SQRDMULH])
(define_int_iterator USSUQADD [UNSPEC_SUQADD UNSPEC_USQADD]) (define_int_iterator USSUQADD [UNSPEC_SUQADD UNSPEC_USQADD])
...@@ -1218,6 +1222,18 @@ ...@@ -1218,6 +1222,18 @@
(UNSPEC_FCVTZS "fcvtzs") (UNSPEC_FCVTZS "fcvtzs")
(UNSPEC_FCVTZU "fcvtzu")]) (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") (define_int_attr perm_insn [(UNSPEC_ZIP1 "zip") (UNSPEC_ZIP2 "zip")
(UNSPEC_TRN1 "trn") (UNSPEC_TRN2 "trn") (UNSPEC_TRN1 "trn") (UNSPEC_TRN2 "trn")
(UNSPEC_UZP1 "uzp") (UNSPEC_UZP2 "uzp")]) (UNSPEC_UZP1 "uzp") (UNSPEC_UZP2 "uzp")])
......
...@@ -3513,6 +3513,12 @@ Specifies the core for which to tune the performance of this function and also ...@@ -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 whose architectural features to use. The behavior and valid arguments are the
same as for the @option{-mcpu=} command-line option. 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 @end table
The above target attributes can be specified as follows: The above target attributes can be specified as follows:
......
...@@ -14100,6 +14100,14 @@ accessed using a single instruction and emitted after each function. This ...@@ -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 limits the maximum size of functions to 1MB. This is enabled by default for
@option{-mcmodel=tiny}. @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 @end table
@subsubsection @option{-march} and @option{-mcpu} Feature Modifiers @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
......
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> 2017-01-19 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc.target/powerpc/float128-hw.c: Do not require IEEE 128-bit * gcc.target/powerpc/float128-hw.c: Do not require IEEE 128-bit
......
/* 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 } } */
/* 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 } } */
/* 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" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment