This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[4/9][AArch64] Return address protection on AArch64


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<jiong.wang@arm.com>

        * 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<jiong.wang@arm.com>

        * 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 } } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]