+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
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
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. */
}
}
+/* 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. */
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;
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)
{
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))
{ "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____ }
};
)
(define_c_enum "unspec" [
+ UNSPEC_AUTI1716
+ UNSPEC_AUTISP
UNSPEC_CASESI
UNSPEC_CRC32B
UNSPEC_CRC32CB
UNSPEC_LD4_LANE
UNSPEC_MB
UNSPEC_NOP
+ UNSPEC_PACI1716
+ UNSPEC_PACISP
UNSPEC_PRLG_STK
UNSPEC_RBIT
UNSPEC_SCVTF
UNSPEC_RSQRTE
UNSPEC_RSQRTS
UNSPEC_NZCV
+ UNSPEC_XPACLRI
])
(define_c_enum "unspecv" [
(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")]
)
[(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.
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
(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])
(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")])
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:
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
+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
--- /dev/null
+/* 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 } } */
--- /dev/null
+/* 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 } } */
--- /dev/null
+/* 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" } } */