[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
This commit is contained in:
parent
c9038c70bd
commit
db58fd8954
13 changed files with 271 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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____ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")])
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
51
gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
Normal file
51
gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
Normal file
|
@ -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 } } */
|
17
gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
Normal file
17
gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
Normal file
|
@ -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 } } */
|
21
gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
Normal file
21
gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
Normal file
|
@ -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" } } */
|
Loading…
Add table
Reference in a new issue