public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M
@ 2022-08-12 14:26 Andrea Corallo
  2022-08-12 15:14 ` [PATCH 1/15] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
                   ` (14 more replies)
  0 siblings, 15 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 14:26 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, Richard Earnshaw, Kyrylo.Tkachov

Hi all,

as I respinned few patches, dropped one and added another, I'm reposting
this series thant enables return address verification and branch target
identification based on Armv8.1-M Pointer Authentication and Branch
Target Identification Extension [1] for Arm Cortex-M.

This feature is controlled by the newly introduced '-mbranch-protection'
option, contextually the Armv8.1-M Mainline target feature '+pacbti' is
added.

Best Regards

  Andrea

[1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 1/15] arm: Make mbranch-protection opts parsing common to AArch32/64
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
@ 2022-08-12 15:14 ` Andrea Corallo
  2022-12-22 17:04   ` [PATCH 1/15 V2] " Andrea Corallo
  2022-08-12 15:15 ` [PATCH 2/15] arm: Add Armv8.1-M Mainline target feature +pacbti Andrea Corallo
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:14 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 2413 bytes --]

Hi all,

This change refactors all the mbranch-protection option parsing code and
types to make it common to both AArch32 and AArch64 backends.

This change also pulls in some supporting types from AArch64 to make
it common (aarch_parse_opt_result).

The significant changes in this patch are the movement of all branch
protection parsing routines from aarch64.c to aarch-common.c and
supporting data types and static data structures.

This patch also pre-declares variables and types required in the
aarch32 back-end for moved variables for function sign scope and key
to prepare for the impending series of patches that support parsing
the feature mbranch-protection in the aarch32 back-end.

Approved here
<https://gcc.gnu.org/pipermail/gcc-patches/2022-July/597607.html>

gcc/ChangeLog:

	* common/config/aarch64/aarch64-common.cc: Include aarch-common.h.
	(all_architectures): Fix comment.
	(aarch64_parse_extension): Rename return type, enum value names.
	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Rename
	factored out aarch_ra_sign_scope and aarch_ra_sign_key variables.
	Also rename corresponding enum values.
	* config/aarch64/aarch64-opts.h (aarch64_function_type): Factor
	out aarch64_function_type and move it to common code as
	aarch_function_type in aarch-common.h.
	* config/aarch64/aarch64-protos.h: Include common types header,
	move out types aarch64_parse_opt_result and aarch64_key_type to
	aarch-common.h
	* config/aarch64/aarch64.cc: Move mbranch-protection parsing types
	and functions out into aarch-common.h and aarch-common.cc.  Fix up
	all the name changes resulting from the move.
	* config/aarch64/aarch64.md: Fix up aarch64_ra_sign_key type name change
	and enum value.
	* config/aarch64/aarch64.opt: Include aarch-common.h to import
	type move.  Fix up name changes from factoring out common code and
	data.
	* config/arm/aarch-common-protos.h: Export factored out routines to both
	backends.
	* config/arm/aarch-common.cc: Include newly factored out types.  Move all
	mbranch-protection code and data structures from aarch64.cc.
	* config/arm/aarch-common.h: New header that declares types shared
	between aarch32 and aarch64 backends.
	* config/arm/arm-protos.h: Declare types and variables that are
	made common to aarch64 and aarch32 backends - aarch_ra_sign_key,
	aarch_ra_sign_scope and aarch_enable_bti.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>


[-- Attachment #2: 1-15.patch --]
[-- Type: text/plain, Size: 45025 bytes --]

diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
index dfda5b8372a..70a5cf98b75 100644
--- a/gcc/common/config/aarch64/aarch64-common.cc
+++ b/gcc/common/config/aarch64/aarch64-common.cc
@@ -30,6 +30,7 @@
 #include "opts.h"
 #include "flags.h"
 #include "diagnostic.h"
+#include "config/arm/aarch-common.h"
 
 #ifdef  TARGET_BIG_ENDIAN_DEFAULT
 #undef  TARGET_DEFAULT_TARGET_FLAGS
@@ -192,11 +193,11 @@ static const struct arch_to_arch_name all_architectures[] =
 
 /* Parse the architecture extension string STR and update ISA_FLAGS
    with the architecture features turned on or off.  Return a
-   aarch64_parse_opt_result describing the result.
+   aarch_parse_opt_result describing the result.
    When the STR string contains an invalid extension,
    a copy of the string is created and stored to INVALID_EXTENSION.  */
 
-enum aarch64_parse_opt_result
+enum aarch_parse_opt_result
 aarch64_parse_extension (const char *str, uint64_t *isa_flags,
 			 std::string *invalid_extension)
 {
@@ -229,7 +230,7 @@ aarch64_parse_extension (const char *str, uint64_t *isa_flags,
 	adding_ext = 1;
 
       if (len == 0)
-	return AARCH64_PARSE_MISSING_ARG;
+	return AARCH_PARSE_MISSING_ARG;
 
 
       /* Scan over the extensions table trying to find an exact match.  */
@@ -251,13 +252,13 @@ aarch64_parse_extension (const char *str, uint64_t *isa_flags,
 	  /* Extension not found in list.  */
 	  if (invalid_extension)
 	    *invalid_extension = std::string (str, len);
-	  return AARCH64_PARSE_INVALID_FEATURE;
+	  return AARCH_PARSE_INVALID_FEATURE;
 	}
 
       str = ext;
     };
 
-  return AARCH64_PARSE_OK;
+  return AARCH_PARSE_OK;
 }
 
 /* Append all architecture extension candidates to the CANDIDATES vector.  */
diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
index caf8e332ea0..b0c5a4fd6b6 100644
--- a/gcc/config/aarch64/aarch64-c.cc
+++ b/gcc/config/aarch64/aarch64-c.cc
@@ -183,14 +183,14 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
 			"__ARM_FEATURE_BTI_DEFAULT", pfile);
 
   cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT");
-  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE)
+  if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
     {
       int v = 0;
-      if (aarch64_ra_sign_key == AARCH64_KEY_A)
+      if (aarch_ra_sign_key == AARCH_KEY_A)
 	v |= 1;
-      if (aarch64_ra_sign_key == AARCH64_KEY_B)
+      if (aarch_ra_sign_key == AARCH_KEY_B)
 	v |= 2;
-      if (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL)
+      if (aarch_ra_sign_scope == AARCH_FUNCTION_ALL)
 	v |= 4;
       builtin_define_with_int_value ("__ARM_FEATURE_PAC_DEFAULT", v);
     }
diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
index 93572fe8330..694d1738374 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -71,16 +71,6 @@ 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
-};
-
 /* SVE vector register sizes.  */
 enum aarch64_sve_vector_bits_enum {
   SVE_SCALABLE,
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 46bade28ed6..fe2180e95ea 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -23,6 +23,7 @@
 #define GCC_AARCH64_PROTOS_H
 
 #include "input.h"
+#include "config/arm/aarch-common.h"
 
 /* SYMBOL_SMALL_ABSOLUTE: Generate symbol accesses through
    high and lo relocs that calculate the base address using a PC
@@ -650,18 +651,6 @@ enum aarch64_extra_tuning_flags
   AARCH64_EXTRA_TUNE_ALL = (1u << AARCH64_EXTRA_TUNE_index_END) - 1
 };
 
-/* Enum describing the various ways that the
-   aarch64_parse_{arch,tune,cpu,extension} functions can fail.
-   This way their callers can choose what kind of error to give.  */
-
-enum aarch64_parse_opt_result
-{
-  AARCH64_PARSE_OK,			/* Parsing was successful.  */
-  AARCH64_PARSE_MISSING_ARG,		/* Missing argument.  */
-  AARCH64_PARSE_INVALID_FEATURE,	/* Invalid feature modifier.  */
-  AARCH64_PARSE_INVALID_ARG		/* Invalid arch, tune, cpu arg.  */
-};
-
 /* Enum to distinguish which type of check is to be done in
    aarch64_simd_valid_immediate.  This is used as a bitmask where
    AARCH64_CHECK_MOV has both bits set.  Thus AARCH64_CHECK_MOV will
@@ -672,13 +661,7 @@ enum simd_immediate_check {
   AARCH64_CHECK_MOV  = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
 };
 
-/* The key type that -msign-return-address should use.  */
-enum aarch64_key_type {
-  AARCH64_KEY_A,
-  AARCH64_KEY_B
-};
-
-extern enum aarch64_key_type aarch64_ra_sign_key;
+extern enum aarch_key_type aarch_ra_sign_key;
 
 extern struct tune_params aarch64_tune_params;
 
@@ -1029,9 +1012,9 @@ extern bool aarch64_classify_address (struct aarch64_address_info *, rtx,
 bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
 			     const struct cl_decoded_option *, location_t);
 const char *aarch64_rewrite_selected_cpu (const char *name);
-enum aarch64_parse_opt_result aarch64_parse_extension (const char *,
-						       uint64_t *,
-						       std::string *);
+enum aarch_parse_opt_result aarch64_parse_extension (const char *,
+						     uint64_t *,
+						     std::string *);
 void aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates);
 std::string aarch64_get_extension_string_for_isa_flags (uint64_t, uint64_t);
 
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 18f80499079..eec743024c1 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -81,6 +81,8 @@
 #include "rtlanal.h"
 #include "tree-dfa.h"
 #include "asan.h"
+#include "config/arm/aarch-common.h"
+#include "config/arm/aarch-common-protos.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -321,12 +323,8 @@ bool aarch64_pcrelative_literal_loads;
 /* Global flag for whether frame pointer is enabled.  */
 bool aarch64_use_frame_pointer;
 
-#define BRANCH_PROTECT_STR_MAX 255
 char *accepted_branch_protection_string = NULL;
 
-static enum aarch64_parse_opt_result
-aarch64_parse_branch_protection (const char*, char**);
-
 /* Support for command line parsing of boolean flags in the tuning
    structures.  */
 struct aarch64_flag_desc
@@ -2711,7 +2709,7 @@ static const struct processor *selected_arch;
 static const struct processor *selected_cpu;
 static const struct processor *selected_tune;
 
-enum aarch64_key_type aarch64_ra_sign_key = AARCH64_KEY_A;
+enum aarch_key_type aarch_ra_sign_key = AARCH_KEY_A;
 
 /* The current tuning set.  */
 struct tune_params aarch64_tune_params = generic_tunings;
@@ -2780,100 +2778,6 @@ aarch64_cc;
 
 #define AARCH64_INVERSE_CONDITION_CODE(X) ((aarch64_cc) (((int) X) ^ 1))
 
-struct aarch64_branch_protect_type
-{
-  /* The type's name that the user passes to the branch-protection option
-    string.  */
-  const char* name;
-  /* Function to handle the protection type and set global variables.
-    First argument is the string token corresponding with this type and the
-    second argument is the next token in the option string.
-    Return values:
-    * AARCH64_PARSE_OK: Handling was sucessful.
-    * AARCH64_INVALID_ARG: The type is invalid in this context and the caller
-      should print an error.
-    * AARCH64_INVALID_FEATURE: The type is invalid and the handler prints its
-      own error.  */
-  enum aarch64_parse_opt_result (*handler)(char*, char*);
-  /* A list of types that can follow this type in the option string.  */
-  const aarch64_branch_protect_type* subtypes;
-  unsigned int num_subtypes;
-};
-
-static enum aarch64_parse_opt_result
-aarch64_handle_no_branch_protection (char* str, char* rest)
-{
-  aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE;
-  aarch64_enable_bti = 0;
-  if (rest)
-    {
-      error ("unexpected %<%s%> after %<%s%>", rest, str);
-      return AARCH64_PARSE_INVALID_FEATURE;
-    }
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_standard_branch_protection (char* str, char* rest)
-{
-  aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
-  aarch64_ra_sign_key = AARCH64_KEY_A;
-  aarch64_enable_bti = 1;
-  if (rest)
-    {
-      error ("unexpected %<%s%> after %<%s%>", rest, str);
-      return AARCH64_PARSE_INVALID_FEATURE;
-    }
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED,
-				    char* rest ATTRIBUTE_UNUSED)
-{
-  aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
-  aarch64_ra_sign_key = AARCH64_KEY_A;
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED,
-			      char* rest ATTRIBUTE_UNUSED)
-{
-  aarch64_ra_sign_scope = AARCH64_FUNCTION_ALL;
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED,
-			      char* rest ATTRIBUTE_UNUSED)
-{
-  aarch64_ra_sign_key = AARCH64_KEY_B;
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_bti_protection (char* str ATTRIBUTE_UNUSED,
-				    char* rest ATTRIBUTE_UNUSED)
-{
-  aarch64_enable_bti = 1;
-  return AARCH64_PARSE_OK;
-}
-
-static const struct aarch64_branch_protect_type aarch64_pac_ret_subtypes[] = {
-  { "leaf", aarch64_handle_pac_ret_leaf, NULL, 0 },
-  { "b-key", aarch64_handle_pac_ret_b_key, NULL, 0 },
-  { NULL, NULL, NULL, 0 }
-};
-
-static const struct aarch64_branch_protect_type aarch64_branch_protect_types[] = {
-  { "none", aarch64_handle_no_branch_protection, NULL, 0 },
-  { "standard", aarch64_handle_standard_branch_protection, NULL, 0 },
-  { "pac-ret", aarch64_handle_pac_ret_protection, aarch64_pac_ret_subtypes,
-    ARRAY_SIZE (aarch64_pac_ret_subtypes) },
-  { "bti", aarch64_handle_bti_protection, NULL, 0 },
-  { NULL, NULL, NULL, 0 }
-};
 
 /* The condition codes of the processor, and the inverse function.  */
 static const char * const aarch64_condition_codes[] =
@@ -8621,10 +8525,10 @@ aarch64_return_address_signing_enabled (void)
   if (crtl->calls_eh_return)
     return false;
 
-  /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
+  /* If signing scope is AARCH_FUNCTION_NON_LEAF, we only sign a leaf function
      if its LR is pushed onto stack.  */
-  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
-	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
+  return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+	  || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
 	      && known_ge (cfun->machine->frame.reg_offset[LR_REGNUM], 0)));
 }
 
@@ -8632,7 +8536,7 @@ aarch64_return_address_signing_enabled (void)
 bool
 aarch64_bti_enabled (void)
 {
-  return (aarch64_enable_bti == 1);
+  return (aarch_enable_bti == 1);
 }
 
 /* The caller is going to use ST1D or LD1D to save or restore an SVE
@@ -9624,12 +9528,12 @@ aarch64_expand_prologue (void)
   /* Sign return address for functions.  */
   if (aarch64_return_address_signing_enabled ())
     {
-      switch (aarch64_ra_sign_key)
+      switch (aarch_ra_sign_key)
 	{
-	  case AARCH64_KEY_A:
+	  case AARCH_KEY_A:
 	    insn = emit_insn (gen_paciasp ());
 	    break;
-	  case AARCH64_KEY_B:
+	  case AARCH_KEY_B:
 	    insn = emit_insn (gen_pacibsp ());
 	    break;
 	  default:
@@ -9930,12 +9834,12 @@ aarch64_expand_epilogue (bool for_sibcall)
   if (aarch64_return_address_signing_enabled ()
       && (for_sibcall || !TARGET_ARMV8_3))
     {
-      switch (aarch64_ra_sign_key)
+      switch (aarch_ra_sign_key)
 	{
-	  case AARCH64_KEY_A:
+	  case AARCH_KEY_A:
 	    insn = emit_insn (gen_autiasp ());
 	    break;
-	  case AARCH64_KEY_B:
+	  case AARCH_KEY_B:
 	    insn = emit_insn (gen_autibsp ());
 	    break;
 	  default:
@@ -17077,12 +16981,12 @@ static void initialize_aarch64_code_model (struct gcc_options *);
 
 /* Parse the TO_PARSE string and put the architecture struct that it
    selects into RES and the architectural features into ISA_FLAGS.
-   Return an aarch64_parse_opt_result describing the parse result.
+   Return an aarch_parse_opt_result describing the parse result.
    If there is an error parsing, RES and ISA_FLAGS are left unchanged.
    When the TO_PARSE string contains an invalid extension,
    a copy of the string is created and stored to INVALID_EXTENSION.  */
 
-static enum aarch64_parse_opt_result
+static enum aarch_parse_opt_result
 aarch64_parse_arch (const char *to_parse, const struct processor **res,
 		    uint64_t *isa_flags, std::string *invalid_extension)
 {
@@ -17098,7 +17002,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
     len = strlen (to_parse);
 
   if (len == 0)
-    return AARCH64_PARSE_MISSING_ARG;
+    return AARCH_PARSE_MISSING_ARG;
 
 
   /* Loop through the list of supported ARCHes to find a match.  */
@@ -17112,32 +17016,32 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
 	  if (ext != NULL)
 	    {
 	      /* TO_PARSE string contains at least one extension.  */
-	      enum aarch64_parse_opt_result ext_res
+	      enum aarch_parse_opt_result ext_res
 		= aarch64_parse_extension (ext, &isa_temp, invalid_extension);
 
-	      if (ext_res != AARCH64_PARSE_OK)
+	      if (ext_res != AARCH_PARSE_OK)
 		return ext_res;
 	    }
 	  /* Extension parsing was successful.  Confirm the result
 	     arch and ISA flags.  */
 	  *res = arch;
 	  *isa_flags = isa_temp;
-	  return AARCH64_PARSE_OK;
+	  return AARCH_PARSE_OK;
 	}
     }
 
   /* ARCH name not found in list.  */
-  return AARCH64_PARSE_INVALID_ARG;
+  return AARCH_PARSE_INVALID_ARG;
 }
 
 /* Parse the TO_PARSE string and put the result tuning in RES and the
-   architecture flags in ISA_FLAGS.  Return an aarch64_parse_opt_result
+   architecture flags in ISA_FLAGS.  Return an aarch_parse_opt_result
    describing the parse result.  If there is an error parsing, RES and
    ISA_FLAGS are left unchanged.
    When the TO_PARSE string contains an invalid extension,
    a copy of the string is created and stored to INVALID_EXTENSION.  */
 
-static enum aarch64_parse_opt_result
+static enum aarch_parse_opt_result
 aarch64_parse_cpu (const char *to_parse, const struct processor **res,
 		   uint64_t *isa_flags, std::string *invalid_extension)
 {
@@ -17153,7 +17057,7 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
     len = strlen (to_parse);
 
   if (len == 0)
-    return AARCH64_PARSE_MISSING_ARG;
+    return AARCH_PARSE_MISSING_ARG;
 
 
   /* Loop through the list of supported CPUs to find a match.  */
@@ -17167,29 +17071,29 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
 	  if (ext != NULL)
 	    {
 	      /* TO_PARSE string contains at least one extension.  */
-	      enum aarch64_parse_opt_result ext_res
+	      enum aarch_parse_opt_result ext_res
 		= aarch64_parse_extension (ext, &isa_temp, invalid_extension);
 
-	      if (ext_res != AARCH64_PARSE_OK)
+	      if (ext_res != AARCH_PARSE_OK)
 		return ext_res;
 	    }
 	  /* Extension parsing was successfull.  Confirm the result
 	     cpu and ISA flags.  */
 	  *res = cpu;
 	  *isa_flags = isa_temp;
-	  return AARCH64_PARSE_OK;
+	  return AARCH_PARSE_OK;
 	}
     }
 
   /* CPU name not found in list.  */
-  return AARCH64_PARSE_INVALID_ARG;
+  return AARCH_PARSE_INVALID_ARG;
 }
 
 /* Parse the TO_PARSE string and put the cpu it selects into RES.
-   Return an aarch64_parse_opt_result describing the parse result.
+   Return an aarch_parse_opt_result describing the parse result.
    If the parsing fails the RES does not change.  */
 
-static enum aarch64_parse_opt_result
+static enum aarch_parse_opt_result
 aarch64_parse_tune (const char *to_parse, const struct processor **res)
 {
   const struct processor *cpu;
@@ -17200,12 +17104,12 @@ aarch64_parse_tune (const char *to_parse, const struct processor **res)
       if (strcmp (cpu->name, to_parse) == 0)
 	{
 	  *res = cpu;
-	  return AARCH64_PARSE_OK;
+	  return AARCH_PARSE_OK;
 	}
     }
 
   /* CPU name not found in list.  */
-  return AARCH64_PARSE_INVALID_ARG;
+  return AARCH_PARSE_INVALID_ARG;
 }
 
 /* Parse TOKEN, which has length LENGTH to see if it is an option
@@ -17783,22 +17687,22 @@ aarch64_validate_mcpu (const char *str, const struct processor **res,
 		       uint64_t *isa_flags)
 {
   std::string invalid_extension;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_cpu (str, res, isa_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     return true;
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing cpu name in %<-mcpu=%s%>", str);
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("unknown value %qs for %<-mcpu%>", str);
 	aarch64_print_hint_for_core (str);
 	break;
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %qs in %<-mcpu=%s%>",
 	       invalid_extension.c_str (), str);
 	aarch64_print_hint_for_extensions (invalid_extension);
@@ -17883,110 +17787,6 @@ aarch64_validate_sls_mitigation (const char *const_str)
   free (str_root);
 }
 
-/* Parses CONST_STR for branch protection features specified in
-   aarch64_branch_protect_types, and set any global variables required.  Returns
-   the parsing result and assigns LAST_STR to the last processed token from
-   CONST_STR so that it can be used for error reporting.  */
-
-static enum
-aarch64_parse_opt_result aarch64_parse_branch_protection (const char *const_str,
-							  char** last_str)
-{
-  char *str_root = xstrdup (const_str);
-  char* token_save = NULL;
-  char *str = strtok_r (str_root, "+", &token_save);
-  enum aarch64_parse_opt_result res = AARCH64_PARSE_OK;
-  if (!str)
-    res = AARCH64_PARSE_MISSING_ARG;
-  else
-    {
-      char *next_str = strtok_r (NULL, "+", &token_save);
-      /* Reset the branch protection features to their defaults.  */
-      aarch64_handle_no_branch_protection (NULL, NULL);
-
-      while (str && res == AARCH64_PARSE_OK)
-	{
-	  const aarch64_branch_protect_type* type = aarch64_branch_protect_types;
-	  bool found = false;
-	  /* Search for this type.  */
-	  while (type && type->name && !found && res == AARCH64_PARSE_OK)
-	    {
-	      if (strcmp (str, type->name) == 0)
-		{
-		  found = true;
-		  res = type->handler (str, next_str);
-		  str = next_str;
-		  next_str = strtok_r (NULL, "+", &token_save);
-		}
-	      else
-		type++;
-	    }
-	  if (found && res == AARCH64_PARSE_OK)
-	    {
-	      bool found_subtype = true;
-	      /* Loop through each token until we find one that isn't a
-		 subtype.  */
-	      while (found_subtype)
-		{
-		  found_subtype = false;
-		  const aarch64_branch_protect_type *subtype = type->subtypes;
-		  /* Search for the subtype.  */
-		  while (str && subtype && subtype->name && !found_subtype
-			  && res == AARCH64_PARSE_OK)
-		    {
-		      if (strcmp (str, subtype->name) == 0)
-			{
-			  found_subtype = true;
-			  res = subtype->handler (str, next_str);
-			  str = next_str;
-			  next_str = strtok_r (NULL, "+", &token_save);
-			}
-		      else
-			subtype++;
-		    }
-		}
-	    }
-	  else if (!found)
-	    res = AARCH64_PARSE_INVALID_ARG;
-	}
-    }
-  /* Copy the last processed token into the argument to pass it back.
-    Used by option and attribute validation to print the offending token.  */
-  if (last_str)
-    {
-      if (str) strcpy (*last_str, str);
-      else *last_str = NULL;
-    }
-  if (res == AARCH64_PARSE_OK)
-    {
-      /* If needed, alloc the accepted string then copy in const_str.
-	Used by override_option_after_change_1.  */
-      if (!accepted_branch_protection_string)
-	accepted_branch_protection_string = (char *) xmalloc (
-						      BRANCH_PROTECT_STR_MAX
-							+ 1);
-      strncpy (accepted_branch_protection_string, const_str,
-		BRANCH_PROTECT_STR_MAX + 1);
-      /* Forcibly null-terminate.  */
-      accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0';
-    }
-  return res;
-}
-
-static bool
-aarch64_validate_mbranch_protection (const char *const_str)
-{
-  char *str = (char *) xmalloc (strlen (const_str));
-  enum aarch64_parse_opt_result res =
-    aarch64_parse_branch_protection (const_str, &str);
-  if (res == AARCH64_PARSE_INVALID_ARG)
-    error ("invalid argument %<%s%> for %<-mbranch-protection=%>", str);
-  else if (res == AARCH64_PARSE_MISSING_ARG)
-    error ("missing argument for %<-mbranch-protection=%>");
-  free (str);
-  return res == AARCH64_PARSE_OK;
-}
-
 /* Validate a command-line -march option.  Parse the arch and extensions
    (if any) specified in STR and throw errors if appropriate.  Put the
    results, if they are valid, in RES and ISA_FLAGS.  Return whether the
@@ -17997,22 +17797,22 @@ aarch64_validate_march (const char *str, const struct processor **res,
 			 uint64_t *isa_flags)
 {
   std::string invalid_extension;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_arch (str, res, isa_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     return true;
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing arch name in %<-march=%s%>", str);
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("unknown value %qs for %<-march%>", str);
 	aarch64_print_hint_for_arch (str);
 	break;
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %qs in %<-march=%s%>",
 	       invalid_extension.c_str (), str);
 	aarch64_print_hint_for_extensions (invalid_extension);
@@ -18032,18 +17832,18 @@ aarch64_validate_march (const char *str, const struct processor **res,
 static bool
 aarch64_validate_mtune (const char *str, const struct processor **res)
 {
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_tune (str, res);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     return true;
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing cpu name in %<-mtune=%s%>", str);
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("unknown value %qs for %<-mtune%>", str);
 	aarch64_print_hint_for_core (str);
 	break;
@@ -18131,7 +17931,7 @@ aarch64_override_options (void)
     aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
 
   if (aarch64_branch_protection_string)
-    aarch64_validate_mbranch_protection (aarch64_branch_protection_string);
+    aarch_validate_mbranch_protection (aarch64_branch_protection_string);
 
   /* -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU.
      If either of -march or -mtune is given, they override their
@@ -18209,12 +18009,12 @@ aarch64_override_options (void)
   if (!selected_tune)
     selected_tune = selected_cpu;
 
-  if (aarch64_enable_bti == 2)
+  if (aarch_enable_bti == 2)
     {
 #ifdef TARGET_ENABLE_BTI
-      aarch64_enable_bti = 1;
+      aarch_enable_bti = 1;
 #else
-      aarch64_enable_bti = 0;
+      aarch_enable_bti = 0;
 #endif
     }
 
@@ -18224,9 +18024,9 @@ aarch64_override_options (void)
   if (!TARGET_ILP32 && accepted_branch_protection_string == NULL)
     {
 #ifdef TARGET_ENABLE_PAC_RET
-      aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
+      aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
 #else
-      aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE;
+      aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
 #endif
     }
 
@@ -18240,7 +18040,7 @@ aarch64_override_options (void)
   /* Convert -msve-vector-bits to a VG count.  */
   aarch64_sve_vg = aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits);
 
-  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
+  if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE && TARGET_ILP32)
     sorry ("return address signing is only supported for %<-mabi=lp64%>");
 
   /* Make sure we properly set up the explicit options.  */
@@ -18367,7 +18167,7 @@ aarch64_option_restore (struct gcc_options *opts,
     = ptr->x_aarch64_branch_protection_string;
   if (opts->x_aarch64_branch_protection_string)
     {
-      aarch64_parse_branch_protection (opts->x_aarch64_branch_protection_string,
+      aarch_parse_branch_protection (opts->x_aarch64_branch_protection_string,
 					NULL);
     }
 
@@ -18491,10 +18291,10 @@ aarch64_handle_attr_arch (const char *str)
 {
   const struct processor *tmp_arch = NULL;
   std::string invalid_extension;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_arch (str, &tmp_arch, &aarch64_isa_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     {
       gcc_assert (tmp_arch);
       selected_arch = tmp_arch;
@@ -18504,14 +18304,14 @@ aarch64_handle_attr_arch (const char *str)
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing name in %<target(\"arch=\")%> pragma or attribute");
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("invalid name %qs in %<target(\"arch=\")%> pragma or attribute", str);
 	aarch64_print_hint_for_arch (str);
 	break;
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %s of value %qs in "
 	       "%<target()%> pragma or attribute", invalid_extension.c_str (), str);
 	aarch64_print_hint_for_extensions (invalid_extension);
@@ -18530,10 +18330,10 @@ aarch64_handle_attr_cpu (const char *str)
 {
   const struct processor *tmp_cpu = NULL;
   std::string invalid_extension;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_cpu (str, &tmp_cpu, &aarch64_isa_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     {
       gcc_assert (tmp_cpu);
       selected_tune = tmp_cpu;
@@ -18546,14 +18346,14 @@ aarch64_handle_attr_cpu (const char *str)
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing name in %<target(\"cpu=\")%> pragma or attribute");
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("invalid name %qs in %<target(\"cpu=\")%> pragma or attribute", str);
 	aarch64_print_hint_for_core (str);
 	break;
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %qs of value %qs in "
 	       "%<target()%> pragma or attribute", invalid_extension.c_str (), str);
 	aarch64_print_hint_for_extensions (invalid_extension);
@@ -18571,23 +18371,23 @@ aarch64_handle_attr_cpu (const char *str)
  aarch64_handle_attr_branch_protection (const char* str)
  {
   char *err_str = (char *) xmalloc (strlen (str) + 1);
-  enum aarch64_parse_opt_result res = aarch64_parse_branch_protection (str,
-								      &err_str);
+  enum aarch_parse_opt_result res = aarch_parse_branch_protection (str,
+								   &err_str);
   bool success = false;
   switch (res)
     {
-     case AARCH64_PARSE_MISSING_ARG:
+     case AARCH_PARSE_MISSING_ARG:
        error ("missing argument to %<target(\"branch-protection=\")%> pragma or"
 	      " attribute");
        break;
-     case AARCH64_PARSE_INVALID_ARG:
+     case AARCH_PARSE_INVALID_ARG:
        error ("invalid protection type %qs in %<target(\"branch-protection"
 	      "=\")%> pragma or attribute", err_str);
        break;
-     case AARCH64_PARSE_OK:
+     case AARCH_PARSE_OK:
        success = true;
       /* Fall through.  */
-     case AARCH64_PARSE_INVALID_FEATURE:
+     case AARCH_PARSE_INVALID_FEATURE:
        break;
      default:
        gcc_unreachable ();
@@ -18602,10 +18402,10 @@ static bool
 aarch64_handle_attr_tune (const char *str)
 {
   const struct processor *tmp_tune = NULL;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_tune (str, &tmp_tune);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     {
       gcc_assert (tmp_tune);
       selected_tune = tmp_tune;
@@ -18615,7 +18415,7 @@ aarch64_handle_attr_tune (const char *str)
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("invalid name %qs in %<target(\"tune=\")%> pragma or attribute", str);
 	aarch64_print_hint_for_core (str);
 	break;
@@ -18634,7 +18434,7 @@ aarch64_handle_attr_tune (const char *str)
 static bool
 aarch64_handle_attr_isa_flags (char *str)
 {
-  enum aarch64_parse_opt_result parse_res;
+  enum aarch_parse_opt_result parse_res;
   uint64_t isa_flags = aarch64_isa_flags;
 
   /* We allow "+nothing" in the beginning to clear out all architectural
@@ -18648,7 +18448,7 @@ aarch64_handle_attr_isa_flags (char *str)
   std::string invalid_extension;
   parse_res = aarch64_parse_extension (str, &isa_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     {
       aarch64_isa_flags = isa_flags;
       return true;
@@ -18656,11 +18456,11 @@ aarch64_handle_attr_isa_flags (char *str)
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing value in %<target()%> pragma or attribute");
 	break;
 
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %qs of value %qs in "
 	       "%<target()%> pragma or attribute", invalid_extension.c_str (), str);
 	break;
@@ -18909,10 +18709,10 @@ aarch64_process_target_attr (tree args)
 	     leading '+'.  */
 	  uint64_t isa_temp = 0;
 	  auto with_plus = std::string ("+") + token;
-	  enum aarch64_parse_opt_result ext_res
+	  enum aarch_parse_opt_result ext_res
 	    = aarch64_parse_extension (with_plus.c_str (), &isa_temp, nullptr);
 
-	  if (ext_res == AARCH64_PARSE_OK)
+	  if (ext_res == AARCH_PARSE_OK)
 	    error ("arch extension %<%s%> should be prefixed by %<+%>",
 		   token);
 	  else
@@ -22606,7 +22406,7 @@ void
 aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED)
 {
   if (cfun->machine->frame.laid_out && aarch64_return_address_signing_enabled ()
-      && aarch64_ra_sign_key == AARCH64_KEY_B)
+      && aarch_ra_sign_key == AARCH_KEY_B)
 	asm_fprintf (f, "\t.cfi_b_key_frame\n");
 }
 
@@ -26892,7 +26692,7 @@ aarch64_file_end_indicate_exec_stack ()
   if (aarch64_bti_enabled ())
     feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
 
-  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE)
+  if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
     feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
 
   if (feature_1_and)
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index c98525075a0..072264b89d8 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -890,7 +890,7 @@
     if (aarch64_return_address_signing_enabled ()
 	&& (TARGET_PAUTH))
       {
-	if (aarch64_ra_sign_key == AARCH64_KEY_B)
+	if (aarch_ra_sign_key == AARCH_KEY_B)
 	  ret = "retab";
 	else
 	  ret = "retaa";
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 92220b26ee2..61937fb92cf 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -21,6 +21,9 @@
 HeaderInclude
 config/aarch64/aarch64-opts.h
 
+HeaderInclude
+config/arm/aarch-common.h
+
 TargetVariable
 enum aarch64_processor explicit_tune_core = aarch64_none
 
@@ -34,7 +37,7 @@ TargetVariable
 uint64_t aarch64_isa_flags = 0
 
 TargetVariable
-unsigned aarch64_enable_bti = 2
+unsigned aarch_enable_bti = 2
 
 ; The TLS dialect names to use with -mtls-dialect.
 
@@ -161,21 +164,21 @@ Target RejectNegative Joined Var(aarch64_branch_protection_string) Save
 Use branch-protection features.
 
 msign-return-address=
-Target WarnRemoved RejectNegative Joined Enum(aarch64_ra_sign_scope_t) Var(aarch64_ra_sign_scope) Init(AARCH64_FUNCTION_NONE) Save
+Target WarnRemoved RejectNegative Joined Enum(aarch_ra_sign_scope_t) Var(aarch_ra_sign_scope) Init(AARCH_FUNCTION_NONE) Save
 Select return address signing scope.
 
 Enum
-Name(aarch64_ra_sign_scope_t) Type(enum aarch64_function_type)
+Name(aarch_ra_sign_scope_t) Type(enum aarch_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)
+Enum(aarch_ra_sign_scope_t) String(none) Value(AARCH_FUNCTION_NONE)
 
 EnumValue
-Enum(aarch64_ra_sign_scope_t) String(non-leaf) Value(AARCH64_FUNCTION_NON_LEAF)
+Enum(aarch_ra_sign_scope_t) String(non-leaf) Value(AARCH_FUNCTION_NON_LEAF)
 
 EnumValue
-Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL)
+Enum(aarch_ra_sign_scope_t) String(all) Value(AARCH_FUNCTION_ALL)
 
 mlow-precision-recip-sqrt
 Target Var(flag_mrecip_low_precision_sqrt) Optimization
diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
index ae0465159f7..17a369f7e99 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -153,4 +153,10 @@ rtx_insn *arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
 			     vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
 			     location_t loc);
 
+/* Parsing routine for branch-protection common to AArch64 and Arm.  */
+enum aarch_parse_opt_result aarch_parse_branch_protection (const char*, char**);
+
+/* Validation routine for branch-protection common to AArch64 and Arm.  */
+bool aarch_validate_mbranch_protection (const char *);
+
 #endif /* GCC_AARCH_COMMON_PROTOS_H */
diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
index 04a53d75093..6d254101f6a 100644
--- a/gcc/config/arm/aarch-common.cc
+++ b/gcc/config/arm/aarch-common.cc
@@ -36,6 +36,7 @@
 #include "expr.h"
 #include "function.h"
 #include "emit-rtl.h"
+#include "aarch-common.h"
 
 /* Return TRUE if X is either an arithmetic shift left, or
    is a multiplication by a power of two.  */
@@ -657,3 +658,187 @@ arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
 
   return saw_asm_flag ? seq : NULL;
 }
+
+#define BRANCH_PROTECT_STR_MAX 255
+extern char *accepted_branch_protection_string;
+extern enum aarch_key_type aarch_ra_sign_key;
+
+static enum aarch_parse_opt_result
+aarch_handle_no_branch_protection (char* str, char* rest)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
+  aarch_enable_bti = 0;
+  if (rest)
+    {
+      error ("unexpected %<%s%> after %<%s%>", rest, str);
+      return AARCH_PARSE_INVALID_FEATURE;
+    }
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_standard_branch_protection (char* str, char* rest)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch_ra_sign_key = AARCH_KEY_A;
+  aarch_enable_bti = 1;
+  if (rest)
+    {
+      error ("unexpected %<%s%> after %<%s%>", rest, str);
+      return AARCH_PARSE_INVALID_FEATURE;
+    }
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED,
+				 char* rest ATTRIBUTE_UNUSED)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch_ra_sign_key = AARCH_KEY_A;
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED,
+			   char* rest ATTRIBUTE_UNUSED)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_ALL;
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED,
+			    char* rest ATTRIBUTE_UNUSED)
+{
+  aarch_ra_sign_key = AARCH_KEY_B;
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_bti_protection (char* str ATTRIBUTE_UNUSED,
+			     char* rest ATTRIBUTE_UNUSED)
+{
+  aarch_enable_bti = 1;
+  return AARCH_PARSE_OK;
+}
+
+static const struct aarch_branch_protect_type aarch_pac_ret_subtypes[] = {
+  { "leaf", aarch_handle_pac_ret_leaf, NULL, 0 },
+  { "b-key", aarch_handle_pac_ret_b_key, NULL, 0 },
+  { NULL, NULL, NULL, 0 }
+};
+
+static const struct aarch_branch_protect_type aarch_branch_protect_types[] = {
+  { "none", aarch_handle_no_branch_protection, NULL, 0 },
+  { "standard", aarch_handle_standard_branch_protection, NULL, 0 },
+  { "pac-ret", aarch_handle_pac_ret_protection, aarch_pac_ret_subtypes,
+    ARRAY_SIZE (aarch_pac_ret_subtypes) },
+  { "bti", aarch_handle_bti_protection, NULL, 0 },
+  { NULL, NULL, NULL, 0 }
+};
+
+/* Parses CONST_STR for branch protection features specified in
+   aarch64_branch_protect_types, and set any global variables required.  Returns
+   the parsing result and assigns LAST_STR to the last processed token from
+   CONST_STR so that it can be used for error reporting.  */
+
+enum aarch_parse_opt_result
+aarch_parse_branch_protection (const char *const_str, char** last_str)
+{
+  char *str_root = xstrdup (const_str);
+  char* token_save = NULL;
+  char *str = strtok_r (str_root, "+", &token_save);
+  enum aarch_parse_opt_result res = AARCH_PARSE_OK;
+  if (!str)
+    res = AARCH_PARSE_MISSING_ARG;
+  else
+    {
+      char *next_str = strtok_r (NULL, "+", &token_save);
+      /* Reset the branch protection features to their defaults.  */
+      aarch_handle_no_branch_protection (NULL, NULL);
+
+      while (str && res == AARCH_PARSE_OK)
+	{
+	  const aarch_branch_protect_type* type = aarch_branch_protect_types;
+	  bool found = false;
+	  /* Search for this type.  */
+	  while (type && type->name && !found && res == AARCH_PARSE_OK)
+	    {
+	      if (strcmp (str, type->name) == 0)
+		{
+		  found = true;
+		  res = type->handler (str, next_str);
+		  str = next_str;
+		  next_str = strtok_r (NULL, "+", &token_save);
+		}
+	      else
+		type++;
+	    }
+	  if (found && res == AARCH_PARSE_OK)
+	    {
+	      bool found_subtype = true;
+	      /* Loop through each token until we find one that isn't a
+		 subtype.  */
+	      while (found_subtype)
+		{
+		  found_subtype = false;
+		  const aarch_branch_protect_type *subtype = type->subtypes;
+		  /* Search for the subtype.  */
+		  while (str && subtype && subtype->name && !found_subtype
+			  && res == AARCH_PARSE_OK)
+		    {
+		      if (strcmp (str, subtype->name) == 0)
+			{
+			  found_subtype = true;
+			  res = subtype->handler (str, next_str);
+			  str = next_str;
+			  next_str = strtok_r (NULL, "+", &token_save);
+			}
+		      else
+			subtype++;
+		    }
+		}
+	    }
+	  else if (!found)
+	    res = AARCH_PARSE_INVALID_ARG;
+	}
+    }
+  /* Copy the last processed token into the argument to pass it back.
+    Used by option and attribute validation to print the offending token.  */
+  if (last_str)
+    {
+      if (str)
+	strcpy (*last_str, str);
+      else
+	*last_str = NULL;
+    }
+
+  if (res == AARCH_PARSE_OK)
+    {
+      /* If needed, alloc the accepted string then copy in const_str.
+	Used by override_option_after_change_1.  */
+      if (!accepted_branch_protection_string)
+	accepted_branch_protection_string
+	  = (char *) xmalloc (BRANCH_PROTECT_STR_MAX + 1);
+      strncpy (accepted_branch_protection_string, const_str,
+	       BRANCH_PROTECT_STR_MAX + 1);
+      /* Forcibly null-terminate.  */
+      accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0';
+    }
+  return res;
+}
+
+bool
+aarch_validate_mbranch_protection (const char *const_str)
+{
+  char *str = (char *) xmalloc (strlen (const_str));
+  enum aarch_parse_opt_result res =
+    aarch_parse_branch_protection (const_str, &str);
+  if (res == AARCH_PARSE_INVALID_ARG)
+    error ("invalid argument %<%s%> for %<-mbranch-protection=%>", str);
+  else if (res == AARCH_PARSE_MISSING_ARG)
+    error ("missing argument for %<-mbranch-protection=%>");
+  free (str);
+  return res == AARCH_PARSE_OK;
+}
diff --git a/gcc/config/arm/aarch-common.h b/gcc/config/arm/aarch-common.h
new file mode 100644
index 00000000000..b5591d60c5a
--- /dev/null
+++ b/gcc/config/arm/aarch-common.h
@@ -0,0 +1,73 @@
+/* Types shared between arm and aarch64.
+
+   Copyright (C) 2009-2021 Free Software Foundation, Inc.
+   Contributed by Arm Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_AARCH_COMMON_H
+#define GCC_AARCH_COMMON_H
+
+/* Enum describing the various ways that the
+   aarch*_parse_{arch,tune,cpu,extension} functions can fail.
+   This way their callers can choose what kind of error to give.  */
+
+enum aarch_parse_opt_result
+{
+  AARCH_PARSE_OK,			/* Parsing was successful.  */
+  AARCH_PARSE_MISSING_ARG,		/* Missing argument.  */
+  AARCH_PARSE_INVALID_FEATURE,	/* Invalid feature modifier.  */
+  AARCH_PARSE_INVALID_ARG		/* Invalid arch, tune, cpu arg.  */
+};
+
+/* Function types -msign-return-address should sign.  */
+enum aarch_function_type {
+  /* Don't sign any function.  */
+  AARCH_FUNCTION_NONE,
+  /* Non-leaf functions.  */
+  AARCH_FUNCTION_NON_LEAF,
+  /* All functions.  */
+  AARCH_FUNCTION_ALL
+};
+
+/* The key type that -msign-return-address should use.  */
+enum aarch_key_type {
+  AARCH_KEY_A,
+  AARCH_KEY_B
+};
+
+struct aarch_branch_protect_type
+{
+  /* The type's name that the user passes to the branch-protection option
+     string.  */
+  const char* name;
+  /* Function to handle the protection type and set global variables.
+     First argument is the string token corresponding with this type and the
+     second argument is the next token in the option string.
+     Return values:
+     * AARCH_PARSE_OK: Handling was sucessful.
+     * AARCH_INVALID_ARG: The type is invalid in this context and the caller
+     should print an error.
+     * AARCH_INVALID_FEATURE: The type is invalid and the handler prints its
+     own error.  */
+  enum aarch_parse_opt_result (*handler)(char*, char*);
+  /* A list of types that can follow this type in the option string.  */
+  const struct aarch_branch_protect_type* subtypes;
+  unsigned int num_subtypes;
+};
+
+#endif /* GCC_AARCH_COMMON_H */
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 9d142096cb6..cff7ff1da2a 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -586,6 +586,8 @@ struct cpu_option
 extern const arch_option all_architectures[];
 extern const cpu_option all_cores[];
 
+extern enum aarch_key_type aarch_ra_sign_key;
+
 const cpu_option *arm_parse_cpu_option_name (const cpu_option *, const char *,
 					     const char *, bool = true);
 const arch_option *arm_parse_arch_option_name (const arch_option *,
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 14e2fdfeafa..60f3eae82a4 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -72,6 +72,8 @@
 #include "selftest.h"
 #include "tree-vectorizer.h"
 #include "opts.h"
+#include "aarch-common.h"
+#include "aarch-common-protos.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -2417,6 +2419,11 @@ const struct tune_params arm_fa726te_tune =
   tune_params::SCHED_AUTOPREF_OFF
 };
 
+/* Key type for Pointer Authentication extension.  */
+enum aarch_key_type aarch_ra_sign_key = AARCH_KEY_A;
+
+char *accepted_branch_protection_string = NULL;
+
 /* Auto-generated CPU, FPU and architecture tables.  */
 #include "arm-cpu-data.h"
 
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index 3209b6c623b..f54ec8356c3 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -21,6 +21,15 @@
 HeaderInclude
 config/arm/arm-opts.h
 
+HeaderInclude
+config/arm/aarch-common.h
+
+TargetVariable
+enum aarch_function_type aarch_ra_sign_scope = AARCH_FUNCTION_NONE
+
+TargetVariable
+unsigned aarch_enable_bti = 2
+
 Enum
 Name(tls_type) Type(enum arm_tls_type)
 TLS dialect to use:

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 2/15] arm: Add Armv8.1-M Mainline target feature +pacbti
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  2022-08-12 15:14 ` [PATCH 1/15] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
@ 2022-08-12 15:15 ` Andrea Corallo
  2022-08-12 15:21 ` [PATCH 3/15] arm: Add option -mbranch-protection Andrea Corallo
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:15 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 469 bytes --]

This patch adds the -march feature +pacbti to Armv8.1-M Mainline.
This feature enables pointer signing and authentication instructions
on M-class architectures.

Pre-approved here
<https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586144.html>.

gcc/Changelog:

	* config/arm/arm.h (TARGET_HAVE_PACBTI): New macro.
	* config/arm/arm-cpus.in (pacbti): New feature.
	* doc/invoke.texi (Arm Options): Document it.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>


[-- Attachment #2: 2-15.patch --]
[-- Type: text/plain, Size: 2107 bytes --]

diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
index 0d3082b569f..9502a34fa97 100644
--- a/gcc/config/arm/arm-cpus.in
+++ b/gcc/config/arm/arm-cpus.in
@@ -229,6 +229,10 @@ define feature cdecp5
 define feature cdecp6
 define feature cdecp7
 
+# M-profile control flow integrity extensions (PAC/AUT/BTI).
+# Optional from Armv8.1-M Mainline.
+define feature pacbti
+
 # Feature groups.  Conventionally all (or mostly) upper case.
 # ALL_FPU lists all the feature bits associated with the floating-point
 # unit; these will all be removed if the floating-point unit is disabled
@@ -743,6 +747,7 @@ begin arch armv8.1-m.main
  isa ARMv8_1m_main
 # fp => FPv5-sp-d16; fp.dp => FPv5-d16
  option dsp add armv7em
+ option pacbti add pacbti
  option fp add FPv5 fp16
  option fp.dp add FPv5 FP_DBL fp16
  option nofp remove ALL_FP
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index f479540812a..3495ab857ea 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -335,6 +335,12 @@ emission of floating point pcs attributes.  */
 						isa_bit_mve_float) \
 			       && !TARGET_GENERAL_REGS_ONLY)
 
+/* Non-zero if this target supports Armv8.1-M Mainline pointer-signing
+   extension.  */
+#define TARGET_HAVE_PACBTI (arm_arch8_1m_main \
+			    && bitmap_bit_p (arm_active_target.isa, \
+					     isa_bit_pacbti))
+
 /* MVE have few common instructions as VFP, like VLDM alias VPOP, VLDR, VSTM
    alia VPUSH, VSTR and VMOV, VMSR and VMRS.  In the same manner it updates few
    registers such as FPCAR, FPCCR, FPDSCR, FPSCR, MVFR0, MVFR1 and MVFR2.  All
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 3936aef69d0..079e34ed98c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -21002,6 +21002,9 @@ Disable the floating-point extension.
 @item +cdecp0, +cdecp1, ... , +cdecp7
 Enable the Custom Datapath Extension (CDE) on selected coprocessors according
 to the numbers given in the options in the range 0 to 7.
+
+@item +pacbti
+Enable the Pointer Authentication and Branch Target Identification Extension.
 @end table
 
 @item  armv8-m.main

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 3/15] arm: Add option -mbranch-protection
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  2022-08-12 15:14 ` [PATCH 1/15] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
  2022-08-12 15:15 ` [PATCH 2/15] arm: Add Armv8.1-M Mainline target feature +pacbti Andrea Corallo
@ 2022-08-12 15:21 ` Andrea Corallo
  2022-08-12 15:22 ` [PATCH 4/15] arm: Add testsuite library support for PACBTI target Andrea Corallo
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:21 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 631 bytes --]

Hi all,

this adds -mbranch-protection option.  This option enables the
code-generation of pointer signing and authentication instructions in
function prologues and epilogues.

gcc/ChangeLog:

	* config/arm/arm.c (arm_configure_build_target): Parse and validate
	-mbranch-protection option and initialize appropriate data structures.
	* config/arm/arm.opt (-mbranch-protection): New option.
	* doc/invoke.texi (Arm Options): Document it.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>
Co-Authored-By: Richard Earnshaw <Richard.Earnshaw@arm.com>

Approved here <https://gcc.gnu.org/pipermail/gcc-patches/2022-July/597756.html>


[-- Attachment #2: 3-15.patch --]
[-- Type: text/plain, Size: 3690 bytes --]

diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 60f3eae82a4..0068817b0f2 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -3263,6 +3263,17 @@ arm_configure_build_target (struct arm_build_target *target,
       tune_opts = strchr (opts->x_arm_tune_string, '+');
     }
 
+  if (opts->x_arm_branch_protection_string)
+    {
+      aarch_validate_mbranch_protection (opts->x_arm_branch_protection_string);
+
+      if (aarch_ra_sign_key != AARCH_KEY_A)
+	{
+	  warning (0, "invalid key type for %<-mbranch-protection=%>");
+	  aarch_ra_sign_key = AARCH_KEY_A;
+	}
+    }
+
   if (arm_selected_arch)
     {
       arm_initialize_isa (target->isa, arm_selected_arch->common.isa_bits);
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index f54ec8356c3..d292e23ea11 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -323,6 +323,10 @@ mbranch-cost=
 Target RejectNegative Joined UInteger Var(arm_branch_cost) Init(-1)
 Cost to assume for a branch insn.
 
+mbranch-protection=
+Target RejectNegative Joined Var(arm_branch_protection_string) Save
+Use branch-protection features.
+
 mgeneral-regs-only
 Target RejectNegative Mask(GENERAL_REGS_ONLY) Save
 Generate code which uses the core registers only (r0-r14).
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 079e34ed98c..a2be3446594 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -825,7 +825,9 @@ Objective-C and Objective-C++ Dialects}.
 -mcmse @gol
 -mfix-cmse-cve-2021-35465 @gol
 -mstack-protector-guard=@var{guard} -mstack-protector-guard-offset=@var{offset} @gol
--mfdpic}
+-mfdpic @gol
+-mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}]
+[+@var{bti}]|@var{bti}[+@var{pac-ret}[+@var{leaf}]]}
 
 @emph{AVR Options}
 @gccoptlist{-mmcu=@var{mcu}  -mabsdata  -maccumulate-args @gol
@@ -21521,6 +21523,40 @@ The opposite @option{-mno-fdpic} option is useful (and required) to
 build the Linux kernel using the same (@code{arm-*-uclinuxfdpiceabi})
 toolchain as the one used to build the userland programs.
 
+@item
+-mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}][+@var{bti}]|@var{bti}[+@var{pac-ret}[+@var{leaf}]]
+@opindex mbranch-protection
+Enable branch protection features (armv8.1-m.main only).
+@samp{none} generate code without branch protection or return address
+signing.
+@samp{standard[+@var{leaf}]} generate code with all branch protection
+features enabled at their standard level.
+@samp{pac-ret[+@var{leaf}]} generate code with return address signing
+set to its standard level, which is to sign all functions that save
+the return address to memory.
+@samp{leaf} When return address signing is enabled, also sign leaf
+functions even if they do not write the return address to memory.
++@samp{bti} Add landing-pad instructions at the permitted targets of
+indirect branch instructions.
+
+If the @samp{+pacbti} architecture extension is not enabled, then all
+branch protection and return address signing operations are
+constrained to use only the instructions defined in the
+architectural-NOP space. The generated code will remain
+backwards-compatible with earlier versions of the architecture, but
+the additional security can be enabled at run time on processors that
+support the @samp{PACBTI} extension.
+
+Branch target enforcement using BTI can only be enabled at runtime if
+all code in the application has been compiled with at least
+@samp{-mbranch-protection=bti}.
+
+Any setting other than @samp{none} is supported only on armv8-m.main
+or later.
+
+The default is to generate code without branch protection or return
+address signing.
+
 @end table
 
 @node AVR Options

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 4/15] arm: Add testsuite library support for PACBTI target
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (2 preceding siblings ...)
  2022-08-12 15:21 ` [PATCH 3/15] arm: Add option -mbranch-protection Andrea Corallo
@ 2022-08-12 15:22 ` Andrea Corallo
  2022-08-12 15:26 ` [PATCH 5/15] arm: Implement target feature macros for PACBTI Andrea Corallo
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:22 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 411 bytes --]

Hi all,

this adds targeting-checking entities for PACBTI in testsuite
framework.

Pre-approved with the requested changes here
<https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586331.html>.

gcc/testsuite/ChangeLog:

	* testsuite/lib/target-supports.exp:
	(check_effective_target_arm_pacbti_hw): New.
	* doc/sourcebuild.texi: Document arm_pacbti_hw.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>


[-- Attachment #2: 4-15.patch --]
[-- Type: text/plain, Size: 1974 bytes --]

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 613ac29967b..a3f60e9c0cb 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2167,6 +2167,10 @@ ARM target supports options to generate instructions from ARMv8.1-M with
 the Custom Datapath Extension (CDE) and M-Profile Vector Extension (MVE).
 Some multilibs may be incompatible with these options.
 
+@item arm_pacbti_hw
+Test system supports executing Pointer Authentication and Branch Target
+Identification instructions.
+
 @item arm_prefer_ldrd_strd
 ARM target prefers @code{LDRD} and @code{STRD} instructions over
 @code{LDM} and @code{STM} instructions.
@@ -2256,6 +2260,12 @@ ARM target generates Thumb-2 code for @code{-mthumb} but does not
 support executing the Armv8.1-M Mainline Low Overhead Loop
 instructions @code{DLS} and @code{LE}.
 
+@item mbranch_protection_ok
+ARM target supporting @code{-mbranch-protection=standard}.
+
+@item arm_pacbti_hw
+Test system supports for executing non nop pacbti instructions.
+
 @end table
 
 @subsubsection AArch64-specific attributes
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ff8edbd3e17..aa828bd3a07 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -5090,6 +5090,22 @@ proc check_effective_target_arm_cmse_clear_ok {} {
     } "-mcmse"];
 }
 
+# Return 1 if the target supports executing PACBTI instructions, 0
+# otherwise.
+
+proc check_effective_target_arm_pacbti_hw {} {
+    return [check_runtime arm_pacbti_hw_available {
+	__attribute__ ((naked)) int
+	main (void)
+	{
+	  asm ("pac r12, lr, sp");
+	  asm ("mov r0, #0");
+	  asm ("autg r12, lr, sp");
+	  asm ("bx lr");
+	}
+    } "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=standard -mthumb -mfloat-abi=hard"]
+}
+
 # Return 1 if this compilation turns on string_ops_prefer_neon on.
 
 proc check_effective_target_arm_tune_string_ops_prefer_neon { } {

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 5/15] arm: Implement target feature macros for PACBTI
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (3 preceding siblings ...)
  2022-08-12 15:22 ` [PATCH 4/15] arm: Add testsuite library support for PACBTI target Andrea Corallo
@ 2022-08-12 15:26 ` Andrea Corallo
  2022-08-12 15:29 ` [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime Andrea Corallo
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:26 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 1270 bytes --]

This patch implements target feature macros when PACBTI is enabled
through the -march option or -mbranch-protection.  The target feature
macros __ARM_FEATURE_PAC_DEFAULT and __ARM_FEATURE_BTI_DEFAULT are
specified in ARM ACLE
<https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros?lang=en>
__ARM_FEATURE_PAUTH and __ARM_FEATURE_BTI are specified in the
pull-request <https://github.com/ARM-software/acle/pull/55>.

Approved here
<https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586334.html>.

gcc/

	* config/arm/arm-c.c (arm_cpu_builtins): Define
	__ARM_FEATURE_BTI_DEFAULT, __ARM_FEATURE_PAC_DEFAULT,
	__ARM_FEATURE_PAUTH and __ARM_FEATURE_BTI.

gcc/testsuite/

	* lib/target-supports.exp
	(check_effective_target_mbranch_protection_ok): New function.
	* gcc.target/arm/acle/pacbti-m-predef-2.c: New test.
	* gcc.target/arm/acle/pacbti-m-predef-4.c: Likewise.
	* gcc.target/arm/acle/pacbti-m-predef-5.c: Likewise.
	* gcc.target/arm/acle/pacbti-m-predef-8.c: Likewise.
	* gcc.target/arm/acle/pacbti-m-predef-9.c: Likewise.
	* gcc.target/arm/acle/pacbti-m-predef-10.c: Likewise.
	* gcc.target/arm/acle/pacbti-m-predef-11.c: Likewise.
	* gcc.target/arm/acle/pacbti-m-predef-12.c: Likewise.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>


[-- Attachment #2: 5-15.patch --]
[-- Type: text/plain, Size: 8011 bytes --]

diff --git a/gcc/config/arm/arm-c.cc b/gcc/config/arm/arm-c.cc
index a8697b8c62f..190099b2c37 100644
--- a/gcc/config/arm/arm-c.cc
+++ b/gcc/config/arm/arm-c.cc
@@ -212,6 +212,24 @@ arm_cpu_builtins (struct cpp_reader* pfile)
   def_or_undef_macro (pfile, "__ARM_FEATURE_COMPLEX", TARGET_COMPLEX);
   def_or_undef_macro (pfile, "__ARM_32BIT_STATE", TARGET_32BIT);
 
+  def_or_undef_macro (pfile, "__ARM_FEATURE_PAUTH", TARGET_HAVE_PACBTI);
+  def_or_undef_macro (pfile, "__ARM_FEATURE_BTI", TARGET_HAVE_PACBTI);
+  def_or_undef_macro (pfile, "__ARM_FEATURE_BTI_DEFAULT",
+		      aarch_enable_bti == 1);
+
+  cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT");
+  if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
+  {
+    unsigned int pac = 1;
+
+    gcc_assert (aarch_ra_sign_key == AARCH_KEY_A);
+
+    if (aarch_ra_sign_scope == AARCH_FUNCTION_ALL)
+      pac |= 0x4;
+
+    builtin_define_with_int_value ("__ARM_FEATURE_PAC_DEFAULT", pac);
+  }
+
   cpp_undef (pfile, "__ARM_FEATURE_MVE");
   if (TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT)
     {
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
new file mode 100644
index 00000000000..52d18238109
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-additional-options "-march=armv8.1-m.main+fp -mbranch-protection=bti+pac-ret -mfloat-abi=hard" } */
+
+#if (__ARM_FEATURE_BTI_DEFAULT != 1)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be defined to 1."
+#endif
+
+#if !defined (__ARM_FEATURE_PAC_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be defined."
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c
new file mode 100644
index 00000000000..9f2711097ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" "-mfloat-abi=*" } } */
+/* { dg-options "-march=armv8.1-m.main+pacbti" } */
+
+#if (__ARM_FEATURE_BTI != 1)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be defined to 1."
+#endif
+
+#if (__ARM_FEATURE_PAUTH != 1)
+#error "Feature test macro __ARM_FEATURE__PAUTH should be defined to 1."
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-12.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-12.c
new file mode 100644
index 00000000000..db40b17c3b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-12.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8-m.main+fp -mfloat-abi=softfp" } */
+
+#if defined (__ARM_FEATURE_BTI)
+#error "Feature test macro __ARM_FEATURE_BTI should not be defined."
+#endif
+
+#if defined (__ARM_FEATURE_PAUTH)
+#error "Feature test macro __ARM_FEATURE_PAUTH should not be defined."
+#endif
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c
new file mode 100644
index 00000000000..cd418ce0c7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard" } */
+
+#if !defined (__ARM_FEATURE_BTI_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be defined."
+#endif
+
+#if !defined (__ARM_FEATURE_PAC_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be defined."
+#endif
+
+int
+main()
+{
+  if (__ARM_FEATURE_BTI_DEFAULT != 1)
+    __builtin_abort ();
+
+  if (__ARM_FEATURE_PAC_DEFAULT != 5)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-4.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-4.c
new file mode 100644
index 00000000000..ce4b45ab464
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-4.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard" } */
+
+#if !defined (__ARM_FEATURE_PAC_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be defined."
+#endif
+
+#if defined (__ARM_FEATURE_BTI_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be undefined."
+#endif
+
+int
+main()
+{
+  if (__ARM_FEATURE_PAC_DEFAULT != 1)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
new file mode 100644
index 00000000000..6d48b7c31a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-skip-if "do not override march" { *-*-* } { "-march=*" } { "-march=armv8.1-m.main" } } */
+/* { dg-additional-options "-march=armv8.1-m.main -mbranch-protection=bti+pac-ret" } */
+
+#if !defined (__ARM_FEATURE_BTI_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be defined."
+#endif
+
+#if !defined (__ARM_FEATURE_PAC_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be defined."
+#endif
+
+int
+main()
+{
+  if (__ARM_FEATURE_BTI_DEFAULT != 1)
+    __builtin_abort ();
+
+  if (__ARM_FEATURE_PAC_DEFAULT != 1)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-8.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-8.c
new file mode 100644
index 00000000000..3538c186397
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-8.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-additional-options "-march=armv8.1-m.main+fp -mbranch-protection=bti+pac-ret+leaf -mfloat-abi=hard" } */
+
+#if (__ARM_FEATURE_BTI_DEFAULT != 1)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be defined to 1."
+#endif
+
+#if (__ARM_FEATURE_PAC_DEFAULT != 5)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be defined to 5."
+#endif
+
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-9.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-9.c
new file mode 100644
index 00000000000..27c1c8f521c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-9.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-additional-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret -mfloat-abi=hard" } */
+
+#if (__ARM_FEATURE_PAC_DEFAULT != 1)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be defined to 1."
+#endif
+
+#if defined (__ARM_FEATURE_BTI_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be undefined."
+#endif
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index aa828bd3a07..c98cb1c8303 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -5090,6 +5090,16 @@ proc check_effective_target_arm_cmse_clear_ok {} {
     } "-mcmse"];
 }
 
+# Return 1 if this is an ARM target supporting
+# -mbranch-protection=standard, 0 otherwise.
+
+proc check_effective_target_mbranch_protection_ok {} {
+
+    return [check_no_compiler_messages mbranch_protection_ok object {
+	int main (void) { return 0; }
+    } "-mbranch-protection=standard"]
+}
+
 # Return 1 if the target supports executing PACBTI instructions, 0
 # otherwise.
 

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (4 preceding siblings ...)
  2022-08-12 15:26 ` [PATCH 5/15] arm: Implement target feature macros for PACBTI Andrea Corallo
@ 2022-08-12 15:29 ` Andrea Corallo
  2022-08-12 15:30 ` [PATCH 7/15] arm: Emit build attributes for PACBTI target feature Andrea Corallo
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:29 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 1471 bytes --]

Hi all,

this patch adds authentication for when the stack is unwound when an
exception is taken.  All the changes here are done to the runtime code
in libgcc's unwinder code for Arm target. All the changes are guarded
under defined (__ARM_FEATURE_PAC_DEFAULT) and activated only if the
+pacbti feature is switched on for the architecture. This means that
switching on the target feature via -march or -mcpu is sufficient and
-mbranch-protection need not be enabled. This ensures that the
unwinder is authenticated only if the PACBTI instructions are
available in the non-NOP space as it uses AUTG.  Just generating
PAC/AUT instructions using -mbranch-protection will not enable
authentication on the unwinder.

Arroved here:
<https://gcc.gnu.org/pipermail/gcc-patches/2022-July/597637.html>

gcc/ChangeLog:

	* ginclude/unwind-arm-common.h (_Unwind_VRS_RegClass): Introduce
	new pseudo register class _UVRSC_PAC.
	* libgcc/config/arm/pr-support.c (__gnu_unwind_execute): Decode
	exception opcode (0xb4) for saving RA_AUTH_CODE and authenticate
	with AUTG if found.
	* libgcc/config/arm/unwind-arm.c (struct pseudo_regs): New.
	(phase1_vrs): Introduce new field to store pseudo-reg state.
	(phase2_vrs): Likewise.
	(_Unwind_VRS_Get): Load pseudo register state from virtual reg set.
	(_Unwind_VRS_Set): Store pseudo register state to virtual reg set.
	(_Unwind_VRS_Pop): Load pseudo register value from stack into VRS.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>


[-- Attachment #2: 6-15.patch --]
[-- Type: text/plain, Size: 4473 bytes --]

diff --git a/gcc/ginclude/unwind-arm-common.h b/gcc/ginclude/unwind-arm-common.h
index d3831f6c60a..f26702e8c6c 100644
--- a/gcc/ginclude/unwind-arm-common.h
+++ b/gcc/ginclude/unwind-arm-common.h
@@ -127,7 +127,8 @@ extern "C" {
       _UVRSC_VFP = 1,       /* vfp */
       _UVRSC_FPA = 2,       /* fpa */
       _UVRSC_WMMXD = 3,     /* Intel WMMX data register */
-      _UVRSC_WMMXC = 4      /* Intel WMMX control register */
+      _UVRSC_WMMXC = 4,     /* Intel WMMX control register */
+      _UVRSC_PAC = 5        /* Armv8.1-M Mainline PAC/AUTH pseudo-register */
     }
   _Unwind_VRS_RegClass;
 
diff --git a/libgcc/config/arm/pr-support.c b/libgcc/config/arm/pr-support.c
index 2de96c2a447..e48854587c6 100644
--- a/libgcc/config/arm/pr-support.c
+++ b/libgcc/config/arm/pr-support.c
@@ -106,6 +106,7 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
 {
   _uw op;
   int set_pc;
+  int set_pac = 0;
   _uw reg;
 
   set_pc = 0;
@@ -114,6 +115,27 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
       op = next_unwind_byte (uws);
       if (op == CODE_FINISH)
 	{
+	  /* When we reach end, we have to authenticate R12 we just popped
+	     earlier.
+
+	     Note: while the check provides additional security against a
+	     corrupted unwind chain, it isn't essential for correct unwinding
+	     of an uncorrupted chain.  */
+#if defined(TARGET_HAVE_PACBTI)
+	  if (set_pac)
+	    {
+	      _uw sp;
+	      _uw lr;
+	      _uw pac;
+	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &sp);
+	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32, &lr);
+	      _Unwind_VRS_Get (context, _UVRSC_PAC, R_IP,
+			       _UVRSD_UINT32, &pac);
+	      __asm__ __volatile__
+		("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);
+	    }
+#endif
+
 	  /* If we haven't already set pc then copy it from lr.  */
 	  if (!set_pc)
 	    {
@@ -227,6 +249,16 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
 		return _URC_FAILURE;
 	      continue;
 	    }
+	  /* Pop PAC off the stack into VRS pseudo.pac.  */
+	  if (op == 0xb4)
+	    {
+	      if (_Unwind_VRS_Pop (context, _UVRSC_PAC, 0, _UVRSD_UINT32)
+		  != _UVRSR_OK)
+		return _URC_FAILURE;
+	      set_pac = 1;
+	      continue;
+	    }
+
 	  if ((op & 0xfc) == 0xb4)  /* Obsolete FPA.  */
 	    return _URC_FAILURE;
 
diff --git a/libgcc/config/arm/unwind-arm.c b/libgcc/config/arm/unwind-arm.c
index 386406564af..89f945d047e 100644
--- a/libgcc/config/arm/unwind-arm.c
+++ b/libgcc/config/arm/unwind-arm.c
@@ -64,6 +64,12 @@ struct wmmxc_regs
   _uw wc[4];
 };
 
+/*  Holds value of pseudo registers eg. PAC.  */
+struct pseudo_regs
+{
+  _uw pac;
+};
+
 /* The ABI specifies that the unwind routines may only use core registers,
    except when actually manipulating coprocessor state.  This allows
    us to write one implementation that works on all platforms by
@@ -78,6 +84,9 @@ typedef struct
   /* The first fields must be the same as a phase2_vrs.  */
   _uw demand_save_flags;
   struct core_regs core;
+  /* Armv8.1-M Mainline PAC/AUTH values.  This field should be in the same field
+     order as phase2_vrs.  */
+  struct pseudo_regs pseudo;
   _uw prev_sp; /* Only valid during forced unwinding.  */
   struct vfp_regs vfp;
   struct vfpv3_regs vfp_regs_16_to_31;
@@ -99,6 +108,7 @@ typedef struct
 {
   _uw demand_save_flags;
   struct core_regs core;
+  struct pseudo_regs pac;
 } phase2_vrs;
 
 /* Coprocessor register state manipulation functions.  */
@@ -175,6 +185,10 @@ _Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
     case _UVRSC_WMMXC:
       return _UVRSR_NOT_IMPLEMENTED;
 
+    case _UVRSC_PAC:
+      *(_uw *) valuep = vrs->pseudo.pac;
+      return _UVRSR_OK;
+
     default:
       return _UVRSR_FAILED;
     }
@@ -206,6 +220,10 @@ _Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
     case _UVRSC_WMMXC:
       return _UVRSR_NOT_IMPLEMENTED;
 
+    case _UVRSC_PAC:
+      vrs->pseudo.pac = *(_uw *) valuep;
+      return _UVRSR_OK;
+
     default:
       return _UVRSR_FAILED;
     }
@@ -246,6 +264,14 @@ _Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
       }
       return _UVRSR_OK;
 
+    case _UVRSC_PAC:
+      {
+	if (discriminator != 0)
+	  return _UVRSR_FAILED;
+	vrs->pseudo.pac = *(_uw *) vrs->core.r[R_SP];
+	return _UVRSR_OK;
+      }
+
     case _UVRSC_VFP:
       {
 	_uw start = discriminator >> 16;

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 7/15] arm: Emit build attributes for PACBTI target feature
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (5 preceding siblings ...)
  2022-08-12 15:29 ` [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime Andrea Corallo
@ 2022-08-12 15:30 ` Andrea Corallo
  2022-09-05 16:53   ` Andrea Corallo
                     ` (2 more replies)
  2022-08-12 15:33 ` [PATCH 8/15] arm: Introduce multilibs " Andrea Corallo
                   ` (7 subsequent siblings)
  14 siblings, 3 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:30 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 611 bytes --]

This patch emits assembler directives for PACBTI build attributes as
defined by the
ABI.

<https://github.com/ARM-software/abi-aa/releases/download/2021Q1/addenda32.pdf>

gcc/ChangeLog:

	* config/arm/arm.c (arm_file_start): Emit EABI attributes for
	Tag_PAC_extension, Tag_BTI_extension, TAG_BTI_use, TAG_PACRET_use.

gcc/testsuite/ChangeLog:

	* gcc.target/arm/acle/pacbti-m-predef-1.c: New test.
	* gcc.target/arm/acle/pacbti-m-predef-3: Likewise.
	* gcc.target/arm/acle/pacbti-m-predef-6.c: Likewise.
	* gcc.target/arm/acle/pacbti-m-predef-7.c: Likewise.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>


[-- Attachment #2: 7-15.patch --]
[-- Type: text/plain, Size: 5316 bytes --]

diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 0068817b0f2..ceec14f84b6 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -28349,6 +28349,8 @@ static void
 arm_file_start (void)
 {
   int val;
+  bool pac = (aarch_ra_sign_scope != AARCH_FUNCTION_NONE);
+  bool bti = (aarch_enable_bti == 1);
 
   arm_print_asm_arch_directives
     (asm_out_file, TREE_TARGET_OPTION (target_option_default_node));
@@ -28419,6 +28421,22 @@ arm_file_start (void)
 	arm_emit_eabi_attribute ("Tag_ABI_FP_16bit_format", 38,
 			     (int) arm_fp16_format);
 
+      if (TARGET_HAVE_PACBTI)
+	{
+	  arm_emit_eabi_attribute ("Tag_PAC_extension", 50, 2);
+	  arm_emit_eabi_attribute ("Tag_BTI_extension", 52, 2);
+	}
+      else if (pac || bti)
+	{
+	  arm_emit_eabi_attribute ("Tag_PAC_extension", 50, 1);
+	  arm_emit_eabi_attribute ("Tag_BTI_extension", 52, 1);
+	}
+
+      if (bti)
+        arm_emit_eabi_attribute ("TAG_BTI_use", 74, 1);
+      if (pac)
+	arm_emit_eabi_attribute ("TAG_PACRET_use", 76, 1);
+
       if (arm_lang_output_object_attributes_hook)
 	arm_lang_output_object_attributes_hook();
     }
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-1.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-1.c
new file mode 100644
index 00000000000..122f7a762a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+bti -mfloat-abi=hard --save-temps" } */
+
+#if !defined (__ARM_FEATURE_BTI_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be defined."
+#endif
+
+#if !defined (__ARM_FEATURE_PAC_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be defined."
+#endif
+
+/* { dg-final { scan-assembler-not "\.arch_extension pacbti" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 50, 1" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 52, 1" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 74, 1" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 76, 1" } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-3.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-3.c
new file mode 100644
index 00000000000..b94f3447ad9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mfloat-abi=hard --save-temps" } */
+
+#if defined (__ARM_FEATURE_BTI_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be undefined."
+#endif
+
+#if !defined (__ARM_FEATURE_PAC_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be defined."
+#endif
+
+/* { dg-final { scan-assembler-not "\.arch_extension pacbti" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 50, 1" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 52, 1" } } */
+/* { dg-final { scan-assembler-not "\.eabi_attribute 74" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 76, 1" } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-6.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-6.c
new file mode 100644
index 00000000000..ed52afc83c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-6.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-additional-options "-march=armv8.1-m.main+fp -mbranch-protection=bti -mfloat-abi=hard --save-temps" } */
+
+#if !defined (__ARM_FEATURE_BTI_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be defined."
+#endif
+
+#if defined (__ARM_FEATURE_PAC_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be undefined."
+#endif
+/* { dg-final { scan-assembler-not "\.arch_extension pacbti" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 50, 1" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 52, 1" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 74, 1" } } */
+/* { dg-final { scan-assembler-not "\.eabi_attribute 76" } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-7.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-7.c
new file mode 100644
index 00000000000..1b25907635e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-7.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-additional-options "-march=armv8.1-m.main+pacbti+fp --save-temps -mfloat-abi=hard" } */
+
+#if defined (__ARM_FEATURE_BTI_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_BTI_DEFAULT should be undefined."
+#endif
+
+#if defined (__ARM_FEATURE_PAC_DEFAULT)
+#error "Feature test macro __ARM_FEATURE_PAC_DEFAULT should be undefined."
+#endif
+
+/* { dg-final { scan-assembler "\.arch_extension pacbti" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 50, 2" } } */
+/* { dg-final { scan-assembler "\.eabi_attribute 52, 2" } } */
+/* { dg-final { scan-assembler-not "\.eabi_attribute 74" } } */
+/* { dg-final { scan-assembler-not "\.eabi_attribute 76" } } */

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 8/15] arm: Introduce multilibs for PACBTI target feature
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (6 preceding siblings ...)
  2022-08-12 15:30 ` [PATCH 7/15] arm: Emit build attributes for PACBTI target feature Andrea Corallo
@ 2022-08-12 15:33 ` Andrea Corallo
  2022-08-12 15:34 ` [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary Andrea Corallo
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:33 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 1187 bytes --]

This patch add the following new multilibs.

thumb/v8.1-m.main+pacbti/mbranch-protection/nofp
thumb/v8.1-m.main+pacbti+dp/mbranch-protection/soft
thumb/v8.1-m.main+pacbti+dp/mbranch-protection/hard
thumb/v8.1-m.main+pacbti+fp/mbranch-protection/soft
thumb/v8.1-m.main+pacbti+fp/mbranch-protection/hard
thumb/v8.1-m.main+pacbti+mve/mbranch-protection/hard

Triggering the following compiler flags:

-mthumb -march=armv8.1-m.main+pacbti -mbranch-protection=standard -mfloat-abi=soft
-mthumb -march=armv8.1-m.main+pacbti+fp -mbranch-protection=standard -mfloat-abi=softfp
-mthumb -march=armv8.1-m.main+pacbti+fp -mbranch-protection=standard -mfloat-abi=hard
-mthumb -march=armv8.1-m.main+pacbti+fp.dp -mbranch-protection=standard -mfloat-abi=softfp
-mthumb -march=armv8.1-m.main+pacbti+fp.dp -mbranch-protection=standard -mfloat-abi=hard
-mthumb -march=armv8.1-m.main+pacbti+mve -mbranch-protection=standard -mfloat-abi=hard

Approved here:
<https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598657.html>

gcc/

	* config/arm/t-rmprofile: Add multilib rules for march +pacbti
          and mbranch-protection.

gcc/testsuite/

	* gcc.target/arm/multilib.exp: Add pacbti related entries.


[-- Attachment #2: 8-15.patch --]
[-- Type: text/plain, Size: 5546 bytes --]

diff --git a/gcc/config/arm/t-rmprofile b/gcc/config/arm/t-rmprofile
index eb321e832f1..fe46a1efa1a 100644
--- a/gcc/config/arm/t-rmprofile
+++ b/gcc/config/arm/t-rmprofile
@@ -27,8 +27,11 @@
 
 # Arch and FPU variants to build libraries with
 
-MULTI_ARCH_OPTS_RM	= march=armv6s-m/march=armv7-m/march=armv7e-m/march=armv7e-m+fp/march=armv7e-m+fp.dp/march=armv8-m.base/march=armv8-m.main/march=armv8-m.main+fp/march=armv8-m.main+fp.dp/march=armv8.1-m.main+mve
-MULTI_ARCH_DIRS_RM	= v6-m v7-m v7e-m v7e-m+fp v7e-m+dp v8-m.base v8-m.main v8-m.main+fp v8-m.main+dp v8.1-m.main+mve
+MULTI_ARCH_OPTS_RM	= march=armv6s-m/march=armv7-m/march=armv7e-m/march=armv7e-m+fp/march=armv7e-m+fp.dp/march=armv8-m.base/march=armv8-m.main/march=armv8-m.main+fp/march=armv8-m.main+fp.dp/march=armv8.1-m.main+mve/march=armv8.1-m.main+pacbti/march=armv8.1-m.main+pacbti+fp/march=armv8.1-m.main+pacbti+fp.dp/march=armv8.1-m.main+pacbti+mve
+MULTI_ARCH_DIRS_RM	= v6-m v7-m v7e-m v7e-m+fp v7e-m+dp v8-m.base v8-m.main v8-m.main+fp v8-m.main+dp v8.1-m.main+mve v8.1-m.main+pacbti v8.1-m.main+pacbti+fp v8.1-m.main+pacbti+dp v8.1-m.main+pacbti+mve
+
+MULTI_ARCH_OPTS_RM	+= mbranch-protection=standard
+MULTI_ARCH_DIRS_RM	+= mbranch-protection
 
 # Base M-profile (no fp)
 MULTILIB_REQUIRED	+= mthumb/march=armv6s-m/mfloat-abi=soft
@@ -50,6 +53,13 @@ MULTILIB_REQUIRED	+= mthumb/march=armv8-m.main+fp.dp/mfloat-abi=hard
 MULTILIB_REQUIRED	+= mthumb/march=armv8-m.main+fp.dp/mfloat-abi=softfp
 MULTILIB_REQUIRED	+= mthumb/march=armv8.1-m.main+mve/mfloat-abi=hard
 
+MULTILIB_REQUIRED	+= mthumb/march=armv8.1-m.main+pacbti/mbranch-protection=standard/mfloat-abi=soft
+MULTILIB_REQUIRED	+= mthumb/march=armv8.1-m.main+pacbti+fp/mbranch-protection=standard/mfloat-abi=softfp
+MULTILIB_REQUIRED	+= mthumb/march=armv8.1-m.main+pacbti+fp/mbranch-protection=standard/mfloat-abi=hard
+MULTILIB_REQUIRED	+= mthumb/march=armv8.1-m.main+pacbti+fp.dp/mbranch-protection=standard/mfloat-abi=softfp
+MULTILIB_REQUIRED	+= mthumb/march=armv8.1-m.main+pacbti+fp.dp/mbranch-protection=standard/mfloat-abi=hard
+MULTILIB_REQUIRED	+= mthumb/march=armv8.1-m.main+pacbti+mve/mbranch-protection=standard/mfloat-abi=hard
+
 # Arch Matches
 MULTILIB_MATCHES	+= march?armv6s-m=march?armv6-m
 
@@ -87,9 +97,23 @@ MULTILIB_MATCHES += $(foreach FP, $(v8_1m_sp_variants), \
 MULTILIB_MATCHES += $(foreach FP, $(v8_1m_dp_variants), \
 			     march?armv8-m.main+fp.dp=mlibarch?armv8.1-m.main$(FP))
 
+# Map all mbranch-protection values other than 'none' to 'standard'.
+MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?bti
+MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?pac-ret
+MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?pac-ret+leaf
+MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?pac-ret+bti
+MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?pac-ret+leaf+bti
+MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?bti+pac-ret
+MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?bti+pac-ret+leaf
+MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?standard+leaf
+
 # For all the MULTILIB_REQUIRED for v8-m and above, add MULTILIB_MATCHES which
 # maps mlibarch with march for multilib linking.
 MULTILIB_MATCHES	+= march?armv8-m.main=mlibarch?armv8-m.main
 MULTILIB_MATCHES	+= march?armv8-m.main+fp=mlibarch?armv8-m.main+fp
 MULTILIB_MATCHES	+= march?armv8-m.main+fp.dp=mlibarch?armv8-m.main+fp.dp
 MULTILIB_MATCHES	+= march?armv8.1-m.main+mve=mlibarch?armv8.1-m.main+mve
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti=mlibarch?armv8.1-m.main+pacbti
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+fp=mlibarch?armv8.1-m.main+pacbti+fp
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+fp.dp=mlibarch?armv8.1-m.main+pacbti+fp.dp
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+mve=mlibarch?armv8.1-m.main+pacbti+mve
diff --git a/gcc/testsuite/gcc.target/arm/multilib.exp b/gcc/testsuite/gcc.target/arm/multilib.exp
index ddbb4439314..52e67446453 100644
--- a/gcc/testsuite/gcc.target/arm/multilib.exp
+++ b/gcc/testsuite/gcc.target/arm/multilib.exp
@@ -832,6 +832,12 @@ if {[multilib_config "rmprofile"] } {
 	{-march=armv8.1-m.main+mve.fp+fp.dp -mfpu=auto -mfloat-abi=softfp} "thumb/v8-m.main+dp/softfp"
 	{-march=armv8.1-m.main+mve+fp.dp -mfpu=auto -mfloat-abi=hard} "thumb/v8-m.main+dp/hard"
 	{-march=armv8.1-m.main+mve.fp+fp.dp -mfpu=auto -mfloat-abi=hard} "thumb/v8-m.main+dp/hard"
+	{-march=armv8.1-m.main+pacbti -mbranch-protection=standard -mfloat-abi=soft} "thumb/v8.1-m.main+pacbti/mbranch-protection/nofp"
+	{-march=armv8.1-m.main+pacbti+fp -mbranch-protection=standard -mfloat-abi=softfp} "thumb/v8.1-m.main+pacbti+fp/mbranch-protection/soft"
+	{-march=armv8.1-m.main+pacbti+fp -mbranch-protection=standard -mfloat-abi=hard} "thumb/v8.1-m.main+pacbti+fp/mbranch-protection/hard"
+	{-march=armv8.1-m.main+pacbti+fp.dp -mbranch-protection=standard -mfloat-abi=softfp} "thumb/v8.1-m.main+pacbti+dp/mbranch-protection/soft"
+	{-march=armv8.1-m.main+pacbti+fp.dp -mbranch-protection=standard -mfloat-abi=hard} "thumb/v8.1-m.main+pacbti+dp/mbranch-protection/hard"
+	{-march=armv8.1-m.main+pacbti+mve -mbranch-protection=standard -mfloat-abi=hard} "thumb/v8.1-m.main+pacbti+mve/mbranch-protection/hard"
 	{-mcpu=cortex-m55+nomve -mfpu=auto -mfloat-abi=soft} "thumb/v8-m.main/nofp"
 	{-mcpu=cortex-m55+nomve -mfpu=auto -mfloat-abi=softfp} "thumb/v8-m.main+dp/softfp"
 	{-mcpu=cortex-m55+nomve -mfpu=auto -mfloat-abi=hard} "thumb/v8-m.main+dp/hard"

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (7 preceding siblings ...)
  2022-08-12 15:33 ` [PATCH 8/15] arm: Introduce multilibs " Andrea Corallo
@ 2022-08-12 15:34 ` Andrea Corallo
  2022-09-05 16:52   ` Andrea Corallo
  2022-09-27  9:03   ` Kyrylo Tkachov
  2022-08-12 15:36 ` [PATCH 10/15] arm: Implement cortex-M return signing address codegen Andrea Corallo
                   ` (5 subsequent siblings)
  14 siblings, 2 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:34 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 272 bytes --]

Hi all,

this patch enables 'arm_emit_multi_reg_pop' to set again the stack
pointer as CFA reg when popping if this is necessary.

/gcc/

	* config/arm/arm.cc (arm_emit_multi_reg_pop): If the frame pointer
	was set define again the stack pointer as CFA reg when popping.


[-- Attachment #2: 9-15.patch --]
[-- Type: text/plain, Size: 910 bytes --]

diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index ceec14f84b6..a5cf4225aa2 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -22303,8 +22303,18 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
 
   REG_NOTES (par) = dwarf;
   if (!return_in_pc)
-    arm_add_cfa_adjust_cfa_note (par, UNITS_PER_WORD * num_regs,
-				 stack_pointer_rtx, stack_pointer_rtx);
+    {
+      /* If the frame pointer was set define again the stack pointer
+         as CFA reg.  */
+      if (frame_pointer_needed)
+        {
+          RTX_FRAME_RELATED_P (par) = 1;
+          add_reg_note (par, REG_CFA_DEF_CFA, stack_pointer_rtx);
+        }
+      else
+        arm_add_cfa_adjust_cfa_note (par, UNITS_PER_WORD * num_regs,
+                                     stack_pointer_rtx, stack_pointer_rtx);
+    }
 }
 
 /* Generate and emit an insn pattern that we will recognize as a pop_multi

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 10/15] arm: Implement cortex-M return signing address codegen
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (8 preceding siblings ...)
  2022-08-12 15:34 ` [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary Andrea Corallo
@ 2022-08-12 15:36 ` Andrea Corallo
  2022-09-05 16:55   ` Andrea Corallo
  2022-09-14 14:20   ` [PATCH 10/15 V2] " Andrea Corallo
  2022-08-12 15:40 ` [PATCH 11/15] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
                   ` (4 subsequent siblings)
  14 siblings, 2 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:36 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 2487 bytes --]

Hi all,

this patch enables address return signature and verification based on
Armv8.1-M Pointer Authentication [1].

To sign the return address, we use the PAC R12, LR, SP instruction
upon function entry.  This is signing LR using SP and storing the
result in R12.  R12 will be pushed into the stack.

During function epilogue R12 will be popped and AUT R12, LR, SP will
be used to verify that the content of LR is still valid before return.

Here an example of PAC instrumented function prologue and epilogue:

void foo (void);

int main()
{
  foo ();
  return 0;
}

Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
-mthumb' translates into:

main:
	pac	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

The patch also takes care of generating a PACBTI instruction in place
of the sequence BTI+PAC when Branch Target Identification is enabled
contextually.

Ex. the previous example compiled with '-march=armv8.1-m.main
-mbranch-protection=pac-ret+bti -mthumb' translates into:

main:
	pacbti	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

As part of previous upstream suggestions a test for varargs has been
added and '-mtpcs-frame' is deemed being incompatible with this return
signing address feature being introduced.

[1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* config/arm/arm.c: (arm_compute_frame_layout)
	(arm_expand_prologue, thumb2_expand_return, arm_expand_epilogue)
	(arm_conditional_register_usage): Update for pac codegen.
	(arm_current_function_pac_enabled_p): New function.
	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
	Add new patterns.
	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.

gcc/testsuite/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/pac.h : New file.
	* gcc.target/arm/pac-1.c : New test case.
	* gcc.target/arm/pac-2.c : Likewise.
	* gcc.target/arm/pac-3.c : Likewise.
	* gcc.target/arm/pac-4.c : Likewise.
	* gcc.target/arm/pac-5.c : Likewise.
	* gcc.target/arm/pac-6.c : Likewise.
	* gcc.target/arm/pac-7.c : Likewise.
	* gcc.target/arm/pac-8.c : Likewise.


[-- Attachment #2: 10-15.patch --]
[-- Type: text/plain, Size: 14112 bytes --]

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index cff7ff1da2a..84764bf27ce 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -379,6 +379,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index a5cf4225aa2..31c6bcdea55 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -3209,6 +3209,9 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p () && !(arm_arch7 && arm_arch_cmse))
+    error ("This architecture does not support branch protection instructions");
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -21139,6 +21142,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23362,6 +23368,12 @@ output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Generate the prologue instructions for entry into an ARM or Thumb-2
    function.  */
 void
@@ -23440,12 +23452,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || (arm_current_function_pac_enabled_p ())));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23521,6 +23534,14 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (aarch_bti_enabled ())
+	emit_insn (gen_pacbti_nop ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27309,7 +27330,7 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (num_regs == 1 && !arm_current_function_pac_enabled_p ())
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27324,10 +27345,20 @@ thumb2_expand_return (bool simple_return)
         }
       else
         {
-          saved_regs_mask &= ~ (1 << LR_REGNUM);
-          saved_regs_mask |=   (1 << PC_REGNUM);
-          arm_emit_multi_reg_pop (saved_regs_mask);
-        }
+	  if (arm_current_function_pac_enabled_p ())
+	    {
+              gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	      emit_insn (gen_aut_nop ());
+	      emit_jump_insn (simple_return_rtx);
+	    }
+	  else
+	    {
+	      saved_regs_mask &= ~ (1 << LR_REGNUM);
+	      saved_regs_mask |=   (1 << PC_REGNUM);
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	    }
+	}
     }
   else
     {
@@ -27733,7 +27764,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27847,6 +27879,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -32941,6 +32976,15 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+    || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+	&& !crtl->is_leaf);
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 60468f6182c..92269a7819a 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -11518,7 +11518,7 @@
      arm_expand_prologue ();
    else
      thumb1_expand_prologue ();
-  DONE;
+   DONE;
   "
 )
 
@@ -12890,6 +12890,29 @@
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PAC_NOP))]
+  "arm_arch7 && arm_arch_cmse"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PACBTI_NOP))]
+  "arm_arch7 && arm_arch_cmse"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+              UNSPEC_AUT_NOP)]
+  "arm_arch7 && arm_arch_cmse"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..dbe243a03f6 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,9 @@
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
+  UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  UNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..6cd64dbd014
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,12 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 11/15] aarch64: Make bti pass generic so it can be used by the arm backend
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (9 preceding siblings ...)
  2022-08-12 15:36 ` [PATCH 10/15] arm: Implement cortex-M return signing address codegen Andrea Corallo
@ 2022-08-12 15:40 ` Andrea Corallo
  2022-09-05 16:56   ` Andrea Corallo
  2022-09-27  9:10   ` Kyrylo Tkachov
  2022-08-12 15:41 ` [PATCH 12/15] arm: implement bti injection Andrea Corallo
                   ` (3 subsequent siblings)
  14 siblings, 2 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:40 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 1088 bytes --]

Hi all,

this patch splits and restructures the aarch64 bti pass code in order
to have it usable by the arm backend as well.  These changes have no
functional impact.

The original patch was approved here:
<https://gcc.gnu.org/pipermail/gcc-patches/2022-May/594172.html>.

After that Richard E. noted that was better to move the new pass
definition for arm in the following patch and so I did.

Best Regards

  Andrea

gcc/Changelog

	* config.gcc (aarch64*-*-*): Rename 'aarch64-bti-insert.o' into
	'aarch-bti-insert.o'.
	* config/aarch64/aarch64-protos.h: Remove 'aarch64_bti_enabled'
	proto.
	* config/aarch64/aarch64.cc (aarch_bti_enabled): Rename.
	(aarch_bti_j_insn_p, aarch_pac_insn_p): New functions.
	(aarch64_output_mi_thunk)
	(aarch64_print_patchable_function_entry)
	(aarch64_file_end_indicate_exec_stack): Update renamed function
	calls to renamed functions.
	* config/aarch64/t-aarch64 (aarch-bti-insert.o): Update target.
	* config/arm/aarch-bti-insert.cc: New file including and
	generalizing code from aarch64-bti-insert.cc.
	* config/arm/aarch-common-protos.h: Update.


[-- Attachment #2: 11-15.patch --]
[-- Type: text/plain, Size: 10995 bytes --]

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 7b58e1314ff..2021bdf9d2f 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -329,7 +329,7 @@ aarch64*-*-*)
 	c_target_objs="aarch64-c.o"
 	cxx_target_objs="aarch64-c.o"
 	d_target_objs="aarch64-d.o"
-	extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o aarch64-cc-fusion.o"
+	extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch-bti-insert.o aarch64-cc-fusion.o"
 	target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.cc \$(srcdir)/config/aarch64/aarch64-sve-builtins.h \$(srcdir)/config/aarch64/aarch64-sve-builtins.cc"
 	target_has_targetm_common=yes
 	;;
diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
index b0c5a4fd6b6..a9aad3abdc2 100644
--- a/gcc/config/aarch64/aarch64-c.cc
+++ b/gcc/config/aarch64/aarch64-c.cc
@@ -179,7 +179,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
   aarch64_def_or_undef (TARGET_RNG, "__ARM_FEATURE_RNG", pfile);
   aarch64_def_or_undef (TARGET_MEMTAG, "__ARM_FEATURE_MEMORY_TAGGING", pfile);
 
-  aarch64_def_or_undef (aarch64_bti_enabled (),
+  aarch64_def_or_undef (aarch_bti_enabled (),
 			"__ARM_FEATURE_BTI_DEFAULT", pfile);
 
   cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT");
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index fe2180e95ea..9fdf7f9cc9c 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -891,7 +891,6 @@ void aarch64_register_pragmas (void);
 void aarch64_relayout_simd_types (void);
 void aarch64_reset_previous_fndecl (void);
 bool aarch64_return_address_signing_enabled (void);
-bool aarch64_bti_enabled (void);
 void aarch64_save_restore_target_globals (tree);
 void aarch64_addti_scratch_regs (rtx, rtx, rtx *,
 				 rtx *, rtx *,
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index eec743024c1..2f67f3872f6 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -8534,11 +8534,61 @@ aarch64_return_address_signing_enabled (void)
 
 /* Return TRUE if Branch Target Identification Mechanism is enabled.  */
 bool
-aarch64_bti_enabled (void)
+aarch_bti_enabled (void)
 {
   return (aarch_enable_bti == 1);
 }
 
+/* Check if INSN is a BTI J insn.  */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+  if (!insn || !INSN_P (insn))
+    return false;
+
+  rtx pat = PATTERN (insn);
+  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_BTI_J;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
+bool
+aarch_pac_insn_p (rtx x)
+{
+  if (!INSN_P (x))
+    return false;
+
+  subrtx_var_iterator::array_type array;
+  FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (x), ALL)
+    {
+      rtx sub = *iter;
+      if (sub && GET_CODE (sub) == UNSPEC)
+	{
+	  int unspec_val = XINT (sub, 1);
+	  switch (unspec_val)
+	    {
+	    case UNSPEC_PACIASP:
+            case UNSPEC_PACIBSP:
+	      return true;
+
+	    default:
+	      return false;
+	    }
+	  iter.skip_subrtxes ();
+	}
+    }
+  return false;
+}
+
+rtx aarch_gen_bti_c (void)
+{
+  return gen_bti_c ();
+}
+
+rtx aarch_gen_bti_j (void)
+{
+  return gen_bti_j ();
+}
+
 /* The caller is going to use ST1D or LD1D to save or restore an SVE
    register in mode MODE at BASE_RTX + OFFSET, where OFFSET is in
    the range [1, 16] * GET_MODE_SIZE (MODE).  Prepare for this by:
@@ -9918,7 +9968,7 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
   rtx_insn *insn;
   const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
 
-  if (aarch64_bti_enabled ())
+  if (aarch_bti_enabled ())
     emit_insn (gen_bti_c());
 
   reload_completed = 1;
@@ -22360,7 +22410,7 @@ aarch64_print_patchable_function_entry (FILE *file,
 					bool record_p)
 {
   if (cfun->machine->label_is_assembled
-      && aarch64_bti_enabled ()
+      && aarch_bti_enabled ()
       && !cgraph_node::get (cfun->decl)->only_called_directly_p ())
     {
       /* Remove the BTI that follows the patch area and insert a new BTI
@@ -26689,7 +26739,7 @@ aarch64_file_end_indicate_exec_stack ()
   file_end_indicate_exec_stack ();
 
   unsigned feature_1_and = 0;
-  if (aarch64_bti_enabled ())
+  if (aarch_bti_enabled ())
     feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
 
   if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
index 75b463d2f03..eb6ad3db955 100644
--- a/gcc/config/aarch64/t-aarch64
+++ b/gcc/config/aarch64/t-aarch64
@@ -149,14 +149,14 @@ falkor-tag-collision-avoidance.o: \
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 		$(srcdir)/config/aarch64/falkor-tag-collision-avoidance.cc
 
-aarch64-bti-insert.o: $(srcdir)/config/aarch64/aarch64-bti-insert.cc \
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.cc \
     $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
     dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
     output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
     $(CONTEXT_H) $(TREE_PASS_H) regrename.h \
     $(srcdir)/config/aarch64/aarch64-protos.h
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-		$(srcdir)/config/aarch64/aarch64-bti-insert.cc
+		$(srcdir)/config/arm/aarch-bti-insert.cc
 
 aarch64-cc-fusion.o: $(srcdir)/config/aarch64/aarch64-cc-fusion.cc \
     $(CONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(BACKEND_H) $(RTL_H) $(DF_H) \
diff --git a/gcc/config/aarch64/aarch64-bti-insert.cc b/gcc/config/arm/aarch-bti-insert.cc
similarity index 80%
rename from gcc/config/aarch64/aarch64-bti-insert.cc
rename to gcc/config/arm/aarch-bti-insert.cc
index 7caed310bbc..2d1d2e334a9 100644
--- a/gcc/config/aarch64/aarch64-bti-insert.cc
+++ b/gcc/config/arm/aarch-bti-insert.cc
@@ -42,10 +42,11 @@
 #include "tree-pass.h"
 #include "cgraph.h"
 
-/* This pass enables the support for Branch Target Identification Mechanism
-   for AArch64.  This is a new security feature introduced in ARMv8.5-A
-   archtitecture.  A BTI instruction is used to guard against the execution
-   of instructions which are not the intended target of an indirect branch.
+/* This pass enables the support for Branch Target Identification Mechanism for
+   Arm/AArch64.  This is a security feature introduced in ARMv8.5-A
+   architecture and ARMv8.1-M.  A BTI instruction is used to guard against the
+   execution of instructions which are not the intended target of an indirect
+   branch.
 
    Outside of a guarded memory region, a BTI instruction executes as a NOP.
    Within a guarded memory region any target of an indirect branch must be
@@ -53,7 +54,8 @@
    branch is triggered in a non-guarded memory region).  An incompatibility
    generates a Branch Target Exception.
 
-   The compatibility of the BTI instruction is as follows:
+   The compatibility of the BTI instruction is as follows (AArch64
+   examples):
    BTI j : Can be a target of any indirect jump (BR Xn).
    BTI c : Can be a target of any indirect call (BLR Xn and BR X16/X17).
    BTI jc: Can be a target of any indirect call or indirect jump.
@@ -90,47 +92,6 @@ const pass_data pass_data_insert_bti =
   0, /* todo_flags_finish.  */
 };
 
-/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
-static bool
-aarch64_pac_insn_p (rtx x)
-{
-  if (!INSN_P (x))
-    return false;
-
-  subrtx_var_iterator::array_type array;
-  FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (x), ALL)
-    {
-      rtx sub = *iter;
-      if (sub && GET_CODE (sub) == UNSPEC)
-	{
-	  int unspec_val = XINT (sub, 1);
-	  switch (unspec_val)
-	    {
-	    case UNSPEC_PACIASP:
-            /* fall-through.  */
-            case UNSPEC_PACIBSP:
-	      return true;
-
-	    default:
-	      return false;
-	    }
-	  iter.skip_subrtxes ();
-	}
-    }
-  return false;
-}
-
-/* Check if INSN is a BTI J insn.  */
-static bool
-aarch64_bti_j_insn_p (rtx_insn *insn)
-{
-  if (!insn || !INSN_P (insn))
-    return false;
-
-  rtx pat = PATTERN (insn);
-  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_BTI_J;
-}
-
 /* Insert the BTI instruction.  */
 /* This is implemented as a late RTL pass that runs before branch
    shortening and does the following.  */
@@ -155,7 +116,7 @@ rest_of_insert_bti (void)
 	       && (LABEL_PRESERVE_P (insn)
 		   || bb->flags & BB_NON_LOCAL_GOTO_TARGET))
 	    {
-	      bti_insn = gen_bti_j ();
+	      bti_insn = aarch_gen_bti_j ();
 	      emit_insn_after (bti_insn, insn);
 	      continue;
 	    }
@@ -177,10 +138,10 @@ rest_of_insert_bti (void)
 		    {
 		      label = as_a <rtx_insn *> (XEXP (RTVEC_ELT (vec, j), 0));
 		      rtx_insn *next = next_nonnote_nondebug_insn (label);
-		      if (aarch64_bti_j_insn_p (next))
+		      if (aarch_bti_j_insn_p (next))
 			continue;
 
-		      bti_insn = gen_bti_j ();
+		      bti_insn = aarch_gen_bti_j ();
 		      emit_insn_after (bti_insn, label);
 		    }
 		}
@@ -191,7 +152,7 @@ rest_of_insert_bti (void)
 	     will return.  */
 	  if (CALL_P (insn) && (find_reg_note (insn, REG_SETJMP, NULL)))
 	    {
-	      bti_insn = gen_bti_j ();
+	      bti_insn = aarch_gen_bti_j ();
 	      emit_insn_after (bti_insn, insn);
 	      continue;
 	    }
@@ -207,9 +168,9 @@ rest_of_insert_bti (void)
     {
       bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
       insn = BB_HEAD (bb);
-      if (!aarch64_pac_insn_p (get_first_nonnote_insn ()))
+      if (!aarch_pac_insn_p (get_first_nonnote_insn ()))
 	{
-	  bti_insn = gen_bti_c ();
+	  bti_insn = aarch_gen_bti_c ();
 	  emit_insn_before (bti_insn, insn);
 	}
     }
@@ -229,7 +190,7 @@ public:
   /* opt_pass methods: */
   virtual bool gate (function *)
     {
-      return aarch64_bti_enabled ();
+      return aarch_bti_enabled ();
     }
 
   virtual unsigned int execute (function *)
diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
index 17a369f7e99..374982752ad 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -42,6 +42,11 @@ extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
 extern int arm_no_early_mul_dep (rtx, rtx);
 extern int arm_no_early_store_addr_dep (rtx, rtx);
 extern bool arm_rtx_shift_left_p (rtx);
+extern bool aarch_bti_enabled (void);
+extern bool aarch_bti_j_insn_p (rtx_insn *);
+extern bool aarch_pac_insn_p (rtx);
+extern rtx aarch_gen_bti_c (void);
+extern rtx aarch_gen_bti_j (void);
 
 /* RTX cost table definitions.  These are used when tuning for speed rather
    than for size and should reflect the _additional_ cost over the cost

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 12/15] arm: implement bti injection
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (10 preceding siblings ...)
  2022-08-12 15:40 ` [PATCH 11/15] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
@ 2022-08-12 15:41 ` Andrea Corallo
  2022-09-05 16:56   ` Andrea Corallo
  2022-09-27  9:18   ` Kyrylo Tkachov
  2022-08-12 16:44 ` [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (2 subsequent siblings)
  14 siblings, 2 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 15:41 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 1294 bytes --]

Hi all,

this patch enables Branch Target Identification Armv8.1-M Mechanism
[1].

This is achieved by using the bti pass made common with Aarch64.

The pass iterates through the instructions and adds the necessary BTI
instructions at the beginning of every function and at every landing
pads targeted by indirect jumps.

Best Regards

  Andrea

[1]
<https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* config.gcc (arm*-*-*): Add 'aarch-bti-insert.o' object.
	* config/arm/arm-protos.h: Update.
	* config/arm/arm.cc (aarch_bti_enabled, aarch_bti_j_insn_p)
	(aarch_pac_insn_p, aarch_gen_bti_c, aarch_gen_bti_j): New
	functions.
	* config/arm/arm.md (bti_nop): New insn.
	* config/arm/t-arm (PASSES_EXTRA): Add 'arm-passes.def'.
	(aarch-bti-insert.o): New target.
	* config/arm/unspecs.md (UNSPEC_BTI_NOP): New unspec.
	* config/arm/aarch-bti-insert.cc (rest_of_insert_bti): Update
	to verify arch compatibility.
	* config/arm/arm-passes.def: New file.

gcc/testsuite/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/bti-1.c: New testcase.
	* gcc.target/arm/bti-2.c: Likewise.


[-- Attachment #2: 12-15.patch --]
[-- Type: text/plain, Size: 7862 bytes --]

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 2021bdf9d2f..004e1dfa8d8 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -353,7 +353,7 @@ arc*-*-*)
 	;;
 arm*-*-*)
 	cpu_type=arm
-	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
+	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o aarch-bti-insert.o"
 	extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
 	target_type_format_char='%'
 	c_target_objs="arm-c.o"
diff --git a/gcc/config/arm/aarch-bti-insert.cc b/gcc/config/arm/aarch-bti-insert.cc
index 2d1d2e334a9..8f045c247bf 100644
--- a/gcc/config/arm/aarch-bti-insert.cc
+++ b/gcc/config/arm/aarch-bti-insert.cc
@@ -41,6 +41,7 @@
 #include "cfgrtl.h"
 #include "tree-pass.h"
 #include "cgraph.h"
+#include "diagnostic-core.h"
 
 /* This pass enables the support for Branch Target Identification Mechanism for
    Arm/AArch64.  This is a security feature introduced in ARMv8.5-A
diff --git a/gcc/config/arm/arm-passes.def b/gcc/config/arm/arm-passes.def
new file mode 100644
index 00000000000..71d6b563640
--- /dev/null
+++ b/gcc/config/arm/arm-passes.def
@@ -0,0 +1,21 @@
+/* Arm-specific passes declarations.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   Contributed by Arm Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 84764bf27ce..6befb6c4445 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -24,6 +24,8 @@
 
 #include "sbitmap.h"
 
+rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
+
 extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *);
 extern int use_return_insn (int, rtx);
 extern bool use_simple_return_p (void);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 31c6bcdea55..de5a679c92a 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -23368,12 +23368,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
-static bool
-aarch_bti_enabled ()
-{
-  return false;
-}
-
 /* Generate the prologue instructions for entry into an ARM or Thumb-2
    function.  */
 void
@@ -32985,6 +32979,58 @@ arm_current_function_pac_enabled_p (void)
 	&& !crtl->is_leaf);
 }
 
+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+bool
+aarch_bti_enabled (void)
+{
+  return aarch_enable_bti == 1;
+}
+
+/* Check if INSN is a BTI J insn.  */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+  if (!insn || !INSN_P (insn))
+    return false;
+
+  rtx pat = PATTERN (insn);
+  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPEC_BTI_NOP;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
+bool
+aarch_pac_insn_p (rtx x)
+{
+  if (!x || !INSN_P (x))
+    return false;
+
+  rtx pat = PATTERN (x);
+
+  if (GET_CODE (pat) == SET)
+    {
+      rtx tmp = XEXP (pat, 1);
+      if (tmp
+	  && GET_CODE (tmp) == UNSPEC
+	  && (XINT (tmp, 1) == UNSPEC_PAC_NOP
+	      || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
+	return true;
+    }
+
+  return false;
+}
+
+rtx
+aarch_gen_bti_c (void)
+{
+  return gen_bti_nop ();
+}
+
+rtx
+aarch_gen_bti_j (void)
+{
+  return gen_bti_nop ();
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 92269a7819a..90c8c1d66f5 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12913,6 +12913,13 @@
   "aut\t%|ip, %|lr, %|sp"
   [(set_attr "length" "4")])
 
+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
+  "arm_arch7 && arm_arch_cmse"
+  "bti"
+  [(set_attr "length" "4")
+   (set_attr "type" "mov_reg")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index 041cc6ec045..683342cb528 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -175,3 +175,13 @@ arm-d.o: $(srcdir)/config/arm/arm-d.cc
 arm-common.o: arm-cpu-cdata.h
 
 driver-arm.o: arm-native.h
+
+PASSES_EXTRA += $(srcdir)/config/arm/arm-passes.def
+
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.cc \
+    $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+    dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+    output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+    $(CONTEXT_H) $(TREE_PASS_H) regrename.h
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/arm/aarch-bti-insert.cc
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index dbe243a03f6..78e723a4b3c 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -162,6 +162,7 @@
   UNSPEC_PAC_NOP	; Represents PAC signing LR
   UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
   UNSPEC_AUT_NOP	; Represents PAC verifying LR
+  UNSPEC_BTI_NOP	; Represent BTI
 ])
 
 
diff --git a/gcc/testsuite/gcc.target/arm/bti-1.c b/gcc/testsuite/gcc.target/arm/bti-1.c
new file mode 100644
index 00000000000..230ebb5a1da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-1.c
@@ -0,0 +1,12 @@
+/* Check that GCC does bti instruction.  */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mbranch-protection=bti --save-temps" } */
+
+int
+main (void)
+{
+  return 0;
+}
+
+/* { dg-final { scan-assembler "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/bti-2.c b/gcc/testsuite/gcc.target/arm/bti-2.c
new file mode 100644
index 00000000000..35aef6992e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-2.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* -Os to create jump table.  */
+/* { dg-options "-Os" } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mbranch-protection=bti --save-temps" } */
+
+extern int f1 (void);
+extern int f2 (void);
+extern int f3 (void);
+extern int f4 (void);
+extern int f5 (void);
+extern int f6 (void);
+extern int f7 (void);
+extern int f8 (void);
+extern int f9 (void);
+extern int f10 (void);
+
+int (*ptr) (void);
+
+int
+f_jump_table (int y, int n)
+{
+  int i;
+  for (i = 0; i < n ;i ++)
+  {
+    switch (y)
+      {
+      case 0 : ptr = f1; break;
+      case 1 : ptr = f2; break;
+      case 2 : ptr = f3; break;
+      case 3 : ptr = f4; break;
+      case 4 : ptr = f5; break;
+      case 5 : ptr = f6; break;
+      case 6 : ptr = f7; break;
+      case 7 : ptr = f8; break;
+      case 8 : ptr = f9; break;
+      case 9 : ptr = f10; break;
+      default: break;
+      }
+    y += ptr ();
+  }
+  return (y == 0)? y+1:4;
+}
+
+int
+f_label_address ()
+{
+  static void * addr = &&lab1;
+  goto *addr;
+lab1:
+  addr = &&lab2;
+  return 1;
+lab2:
+  addr = &&lab1;
+  return 2;
+}
+
+/* { dg-final { scan-assembler-times "bti" 15 } } */

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (11 preceding siblings ...)
  2022-08-12 15:41 ` [PATCH 12/15] arm: implement bti injection Andrea Corallo
@ 2022-08-12 16:44 ` Andrea Corallo
  2022-08-12 17:10 ` [PATCH 13/15] arm: Add pacbti related multilib support for armv8.1-m.main Srinath Parvathaneni
  2022-09-21  8:07 ` [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  14 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-08-12 16:44 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:

> Hi all,
>
> as I respinned few patches, dropped one and added another, I'm reposting
> this series thant enables return address verification and branch target
> identification based on Armv8.1-M Pointer Authentication and Branch
> Target Identification Extension [1] for Arm Cortex-M.
>
> This feature is controlled by the newly introduced '-mbranch-protection'
> option, contextually the Armv8.1-M Mainline target feature '+pacbti' is
> added.
>
> Best Regards
>
>   Andrea
>
> [1]
> <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

Hi all,

FYI I've pushed these rebased on gcc-12 in 'endors/ARM/arm-12-m-pacbti'.

Best Regards

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 13/15] arm: Add pacbti related multilib support for armv8.1-m.main.
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (12 preceding siblings ...)
  2022-08-12 16:44 ` [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
@ 2022-08-12 17:10 ` Srinath Parvathaneni
  2022-10-21 13:00   ` Richard Earnshaw
  2022-09-21  8:07 ` [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  14 siblings, 1 reply; 66+ messages in thread
From: Srinath Parvathaneni @ 2022-08-12 17:10 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 932 bytes --]

 Hi,

This patch supports following -march/-mbranch-protection combination by linking them
to existing pacbti multilibs.

$ -march=armv8.1-m.main+pacbti+fp.dp+mve.fp -mbranch-protection=standard -mfloat-abi=hard -mthumb
$ -march=armv8.1-m.main+pacbti+fp.dp+mve -mbranch-protection=standard -mfloat-abi=hard -mthumb
$ -march=armv8.1-m.main+dsp+pacbti+fp.dp -mbranch-protection=standard -mfloat-abi=hard -mthumb

Regression tested on arm-none-eabi and bootstrapped on arm-none-linux-gnueabihf.

Ok for master?

Regards,
Srinath.

gcc/ChangeLog:

2022-08-12  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

        * config/arm/t-rmprofile: Add pacbti multililb variants.

gcc/testsuite/ChangeLog:

2022-08-12  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

        * gcc.target/arm/pac-10.c: New test.
        * gcc.target/arm/pac-11.c: Likewise.
        * gcc.target/arm/pac-12.c: Likewise.

[-- Attachment #2: patch_16143 --]
[-- Type: application/octet-stream, Size: 3097 bytes --]

diff --git a/gcc/config/arm/t-rmprofile b/gcc/config/arm/t-rmprofile
index fe46a1efa1a8b212e6f4051283573debfc386ff8..77e248e47feeddb2328a82aec6b485ff0f6fd62e 100644
--- a/gcc/config/arm/t-rmprofile
+++ b/gcc/config/arm/t-rmprofile
@@ -97,6 +97,13 @@ MULTILIB_MATCHES += $(foreach FP, $(v8_1m_sp_variants), \
 MULTILIB_MATCHES += $(foreach FP, $(v8_1m_dp_variants), \
 			     march?armv8-m.main+fp.dp=mlibarch?armv8.1-m.main$(FP))
 
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+fp.dp=march?armv8.1-m.main+pacbti+fp.dp+mve.fp
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+fp.dp=mlibarch?armv8.1-m.main+pacbti+fp.dp+mve.fp
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+fp.dp=march?armv8.1-m.main+pacbti+fp.dp+mve
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+fp.dp=mlibarch?armv8.1-m.main+pacbti+fp.dp+mve
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+fp.dp=march?armv8.1-m.main+dsp+pacbti+fp.dp
+MULTILIB_MATCHES	+= march?armv8.1-m.main+pacbti+fp.dp=mlibarch?armv8.1-m.main+dsp+pacbti+fp.dp
+
 # Map all mbranch-protection values other than 'none' to 'standard'.
 MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?bti
 MULTILIB_MATCHES	+= mbranch-protection?standard=mbranch-protection?pac-ret
diff --git a/gcc/testsuite/gcc.target/arm/pac-10.c b/gcc/testsuite/gcc.target/arm/pac-10.c
new file mode 100644
index 0000000000000000000000000000000000000000..faf836b2026607a707e9eac1c64680f0914b2938
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-10.c
@@ -0,0 +1,7 @@
+/* Testing PACBTI multilib matches.  */
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-skip-if "need fp instructions" { *-*-* } { "" } { "-mfloat-abi=hard" } } */
+/* { dg-options "-march=armv8.1-m.main+mve.fp+fp.dp+pacbti -mbranch-protection=standard -mthumb -mfloat-abi=hard" } */
+
+#include "pac.h"
diff --git a/gcc/testsuite/gcc.target/arm/pac-11.c b/gcc/testsuite/gcc.target/arm/pac-11.c
new file mode 100644
index 0000000000000000000000000000000000000000..51609b61c75b9712ce0344df78b3a9f7c8bc9d53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-11.c
@@ -0,0 +1,7 @@
+/* Testing PACBTI multilibs matches without mve float.  */
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-skip-if "need fp instructions" { *-*-* } { "" } { "-mfloat-abi=hard" } } */
+/* { dg-options "-march=armv8.1-m.main+mve+fp.dp+pacbti -mbranch-protection=standard -mthumb -mfloat-abi=hard" } */
+
+#include "pac.h"
diff --git a/gcc/testsuite/gcc.target/arm/pac-12.c b/gcc/testsuite/gcc.target/arm/pac-12.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e1295c834d02835f4fcf214294d5aa5f6cf92e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-12.c
@@ -0,0 +1,7 @@
+/* Testing PACBTI multilibs matches without mve.  */
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-skip-if "need fp instructions" { *-*-* } { "" } { "-mfloat-abi=hard" } } */
+/* { dg-options "-march=armv8.1-m.main+dsp+fp.dp+pacbti -mbranch-protection=standard -mthumb -mfloat-abi=hard" } */
+
+#include "pac.h"

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-08-12 15:34 ` [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary Andrea Corallo
@ 2022-09-05 16:52   ` Andrea Corallo
  2022-09-27  9:03   ` Kyrylo Tkachov
  1 sibling, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-09-05 16:52 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:

> Hi all,
>
> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
> pointer as CFA reg when popping if this is necessary.
>
> /gcc/
>
> 	* config/arm/arm.cc (arm_emit_multi_reg_pop): If the frame pointer
> 	was set define again the stack pointer as CFA reg when popping.

Ping

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 7/15] arm: Emit build attributes for PACBTI target feature
  2022-08-12 15:30 ` [PATCH 7/15] arm: Emit build attributes for PACBTI target feature Andrea Corallo
@ 2022-09-05 16:53   ` Andrea Corallo
  2022-10-20 14:47   ` Kyrylo Tkachov
  2022-10-21 12:19   ` Richard Earnshaw
  2 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-09-05 16:53 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:

> This patch emits assembler directives for PACBTI build attributes as
> defined by the
> ABI.
>
> <https://github.com/ARM-software/abi-aa/releases/download/2021Q1/addenda32.pdf>
>
> gcc/ChangeLog:
>
> 	* config/arm/arm.c (arm_file_start): Emit EABI attributes for
> 	Tag_PAC_extension, Tag_BTI_extension, TAG_BTI_use, TAG_PACRET_use.
>
> gcc/testsuite/ChangeLog:
>
> 	* gcc.target/arm/acle/pacbti-m-predef-1.c: New test.
> 	* gcc.target/arm/acle/pacbti-m-predef-3: Likewise.
> 	* gcc.target/arm/acle/pacbti-m-predef-6.c: Likewise.
> 	* gcc.target/arm/acle/pacbti-m-predef-7.c: Likewise.
>
> Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>

Ping

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 10/15] arm: Implement cortex-M return signing address codegen
  2022-08-12 15:36 ` [PATCH 10/15] arm: Implement cortex-M return signing address codegen Andrea Corallo
@ 2022-09-05 16:55   ` Andrea Corallo
  2022-09-14 14:20   ` [PATCH 10/15 V2] " Andrea Corallo
  1 sibling, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-09-05 16:55 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Ping

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 11/15] aarch64: Make bti pass generic so it can be used by the arm backend
  2022-08-12 15:40 ` [PATCH 11/15] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
@ 2022-09-05 16:56   ` Andrea Corallo
  2022-09-27  9:10   ` Kyrylo Tkachov
  1 sibling, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-09-05 16:56 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:

> Hi all,
>
> this patch splits and restructures the aarch64 bti pass code in order
> to have it usable by the arm backend as well.  These changes have no
> functional impact.
>
> The original patch was approved here:
> <https://gcc.gnu.org/pipermail/gcc-patches/2022-May/594172.html>.
>
> After that Richard E. noted that was better to move the new pass
> definition for arm in the following patch and so I did.

Ping

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 12/15] arm: implement bti injection
  2022-08-12 15:41 ` [PATCH 12/15] arm: implement bti injection Andrea Corallo
@ 2022-09-05 16:56   ` Andrea Corallo
  2022-09-27  9:18   ` Kyrylo Tkachov
  1 sibling, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-09-05 16:56 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:

> Hi all,
>
> this patch enables Branch Target Identification Armv8.1-M Mechanism
> [1].
>
> This is achieved by using the bti pass made common with Aarch64.
>
> The pass iterates through the instructions and adds the necessary BTI
> instructions at the beginning of every function and at every landing
> pads targeted by indirect jumps.
>
> Best Regards
>
>   Andrea
>
> [1]
> <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>
>
> gcc/ChangeLog
>
> 2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>
>
> 	* config.gcc (arm*-*-*): Add 'aarch-bti-insert.o' object.
> 	* config/arm/arm-protos.h: Update.
> 	* config/arm/arm.cc (aarch_bti_enabled, aarch_bti_j_insn_p)
> 	(aarch_pac_insn_p, aarch_gen_bti_c, aarch_gen_bti_j): New
> 	functions.
> 	* config/arm/arm.md (bti_nop): New insn.
> 	* config/arm/t-arm (PASSES_EXTRA): Add 'arm-passes.def'.
> 	(aarch-bti-insert.o): New target.
> 	* config/arm/unspecs.md (UNSPEC_BTI_NOP): New unspec.
> 	* config/arm/aarch-bti-insert.cc (rest_of_insert_bti): Update
> 	to verify arch compatibility.
> 	* config/arm/arm-passes.def: New file.
>
> gcc/testsuite/ChangeLog
>
> 2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>
>
> 	* gcc.target/arm/bti-1.c: New testcase.
> 	* gcc.target/arm/bti-2.c: Likewise.

Ping

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 10/15 V2] arm: Implement cortex-M return signing address codegen
  2022-08-12 15:36 ` [PATCH 10/15] arm: Implement cortex-M return signing address codegen Andrea Corallo
  2022-09-05 16:55   ` Andrea Corallo
@ 2022-09-14 14:20   ` Andrea Corallo
  2022-10-21 12:58     ` Richard Earnshaw
  1 sibling, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-09-14 14:20 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 2487 bytes --]

Hi all,

this patch enables address return signature and verification based on
Armv8.1-M Pointer Authentication [1].

To sign the return address, we use the PAC R12, LR, SP instruction
upon function entry.  This is signing LR using SP and storing the
result in R12.  R12 will be pushed into the stack.

During function epilogue R12 will be popped and AUT R12, LR, SP will
be used to verify that the content of LR is still valid before return.

Here an example of PAC instrumented function prologue and epilogue:

void foo (void);

int main()
{
  foo ();
  return 0;
}

Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
-mthumb' translates into:

main:
	pac	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

The patch also takes care of generating a PACBTI instruction in place
of the sequence BTI+PAC when Branch Target Identification is enabled
contextually.

Ex. the previous example compiled with '-march=armv8.1-m.main
-mbranch-protection=pac-ret+bti -mthumb' translates into:

main:
	pacbti	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

As part of previous upstream suggestions a test for varargs has been
added and '-mtpcs-frame' is deemed being incompatible with this return
signing address feature being introduced.

[1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* config/arm/arm.c: (arm_compute_frame_layout)
	(arm_expand_prologue, thumb2_expand_return, arm_expand_epilogue)
	(arm_conditional_register_usage): Update for pac codegen.
	(arm_current_function_pac_enabled_p): New function.
	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
	Add new patterns.
	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.

gcc/testsuite/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/pac.h : New file.
	* gcc.target/arm/pac-1.c : New test case.
	* gcc.target/arm/pac-2.c : Likewise.
	* gcc.target/arm/pac-3.c : Likewise.
	* gcc.target/arm/pac-4.c : Likewise.
	* gcc.target/arm/pac-5.c : Likewise.
	* gcc.target/arm/pac-6.c : Likewise.
	* gcc.target/arm/pac-7.c : Likewise.
	* gcc.target/arm/pac-8.c : Likewise.


[-- Attachment #2: 10-15.patch --]
[-- Type: text/plain, Size: 14546 bytes --]

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index cff7ff1da2a..84764bf27ce 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -379,6 +379,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index a5cf4225aa2..0ba9c0b9960 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -3209,6 +3209,9 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p () && !(arm_arch7 && arm_arch_cmse))
+    error ("This architecture does not support branch protection instructions");
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -21139,6 +21142,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23362,6 +23368,12 @@ output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Generate the prologue instructions for entry into an ARM or Thumb-2
    function.  */
 void
@@ -23440,12 +23452,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || (arm_current_function_pac_enabled_p ())));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23470,7 +23483,8 @@ arm_expand_prologue (void)
 	{
 	  rtx addr, dwarf;
 
-	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
+	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4
+                     || arm_current_function_pac_enabled_p ());
 	  saved_regs += 4;
 
 	  addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
@@ -23521,6 +23535,14 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (aarch_bti_enabled ())
+	emit_insn (gen_pacbti_nop ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27309,7 +27331,7 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (num_regs == 1 && !arm_current_function_pac_enabled_p ())
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27324,10 +27346,20 @@ thumb2_expand_return (bool simple_return)
         }
       else
         {
-          saved_regs_mask &= ~ (1 << LR_REGNUM);
-          saved_regs_mask |=   (1 << PC_REGNUM);
-          arm_emit_multi_reg_pop (saved_regs_mask);
-        }
+	  if (arm_current_function_pac_enabled_p ())
+	    {
+              gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	      emit_insn (gen_aut_nop ());
+	      emit_jump_insn (simple_return_rtx);
+	    }
+	  else
+	    {
+	      saved_regs_mask &= ~ (1 << LR_REGNUM);
+	      saved_regs_mask |=   (1 << PC_REGNUM);
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	    }
+	}
     }
   else
     {
@@ -27733,7 +27765,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27847,6 +27880,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -32941,6 +32977,15 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+    || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+	&& !crtl->is_leaf);
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 60468f6182c..92269a7819a 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -11518,7 +11518,7 @@ (define_expand "prologue"
      arm_expand_prologue ();
    else
      thumb1_expand_prologue ();
-  DONE;
+   DONE;
   "
 )
 
@@ -12890,6 +12890,29 @@ (define_insn "*speculation_barrier_insn"
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PAC_NOP))]
+  "arm_arch7 && arm_arch_cmse"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PACBTI_NOP))]
+  "arm_arch7 && arm_arch_cmse"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+              UNSPEC_AUT_NOP)]
+  "arm_arch7 && arm_arch_cmse"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..dbe243a03f6 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,9 @@ (define_c_enum "unspec" [
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
+  UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  UNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..6cd64dbd014
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,12 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M
  2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (13 preceding siblings ...)
  2022-08-12 17:10 ` [PATCH 13/15] arm: Add pacbti related multilib support for armv8.1-m.main Srinath Parvathaneni
@ 2022-09-21  8:07 ` Andrea Corallo
  2022-10-21 13:01   ` Richard Earnshaw
                     ` (2 more replies)
  14 siblings, 3 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-09-21  8:07 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Hi all,

ping^2 for patches 9/15 7/15 11/15 12/15 and 10/15 V2 of this series.

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-08-12 15:34 ` [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary Andrea Corallo
  2022-09-05 16:52   ` Andrea Corallo
@ 2022-09-27  9:03   ` Kyrylo Tkachov
  2022-09-27 10:05     ` Andrea Corallo
  1 sibling, 1 reply; 66+ messages in thread
From: Kyrylo Tkachov @ 2022-09-27  9:03 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Hi Andrea,

> -----Original Message-----
> From: Gcc-patches <gcc-patches-
> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
> Corallo via Gcc-patches
> Sent: Friday, August 12, 2022 4:34 PM
> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping
> if necessary
> 
> Hi all,
> 
> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
> pointer as CFA reg when popping if this is necessary.
> 

From what I can tell from similar functions this is correct, but could you elaborate on why this change is needed for my understanding please?
Thanks,
Kyrill

> /gcc/
> 
> 	* config/arm/arm.cc (arm_emit_multi_reg_pop): If the frame pointer
> 	was set define again the stack pointer as CFA reg when popping.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH 11/15] aarch64: Make bti pass generic so it can be used by the arm backend
  2022-08-12 15:40 ` [PATCH 11/15] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
  2022-09-05 16:56   ` Andrea Corallo
@ 2022-09-27  9:10   ` Kyrylo Tkachov
  1 sibling, 0 replies; 66+ messages in thread
From: Kyrylo Tkachov @ 2022-09-27  9:10 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Hi Andrea,

> -----Original Message-----
> From: Gcc-patches <gcc-patches-
> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
> Corallo via Gcc-patches
> Sent: Friday, August 12, 2022 4:40 PM
> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
> Subject: [PATCH 11/15] aarch64: Make bti pass generic so it can be used by
> the arm backend
> 
> Hi all,
> 
> this patch splits and restructures the aarch64 bti pass code in order
> to have it usable by the arm backend as well.  These changes have no
> functional impact.
> 
> The original patch was approved here:
> <https://gcc.gnu.org/pipermail/gcc-patches/2022-May/594172.html>.
> 
> After that Richard E. noted that was better to move the new pass
> definition for arm in the following patch and so I did.
> 

Ok. The renaming and splits look fine and as long as it builds without problems on arm and aarch64 it's all good.
Thanks,
Kyirll


> Best Regards
> 
>   Andrea
> 
> gcc/Changelog
> 
> 	* config.gcc (aarch64*-*-*): Rename 'aarch64-bti-insert.o' into
> 	'aarch-bti-insert.o'.
> 	* config/aarch64/aarch64-protos.h: Remove 'aarch64_bti_enabled'
> 	proto.
> 	* config/aarch64/aarch64.cc (aarch_bti_enabled): Rename.
> 	(aarch_bti_j_insn_p, aarch_pac_insn_p): New functions.
> 	(aarch64_output_mi_thunk)
> 	(aarch64_print_patchable_function_entry)
> 	(aarch64_file_end_indicate_exec_stack): Update renamed function
> 	calls to renamed functions.
> 	* config/aarch64/t-aarch64 (aarch-bti-insert.o): Update target.
> 	* config/arm/aarch-bti-insert.cc: New file including and
> 	generalizing code from aarch64-bti-insert.cc.
> 	* config/arm/aarch-common-protos.h: Update.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH 12/15] arm: implement bti injection
  2022-08-12 15:41 ` [PATCH 12/15] arm: implement bti injection Andrea Corallo
  2022-09-05 16:56   ` Andrea Corallo
@ 2022-09-27  9:18   ` Kyrylo Tkachov
  2022-09-29 15:45     ` [PATCH 12/15 V2] " Andrea Corallo
  1 sibling, 1 reply; 66+ messages in thread
From: Kyrylo Tkachov @ 2022-09-27  9:18 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Hi Andrea,

> -----Original Message-----
> From: Gcc-patches <gcc-patches-
> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
> Corallo via Gcc-patches
> Sent: Friday, August 12, 2022 4:42 PM
> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
> Subject: [PATCH 12/15] arm: implement bti injection
> 
> Hi all,
> 
> this patch enables Branch Target Identification Armv8.1-M Mechanism
> [1].
> 
> This is achieved by using the bti pass made common with Aarch64.
> 
> The pass iterates through the instructions and adds the necessary BTI
> instructions at the beginning of every function and at every landing
> pads targeted by indirect jumps.
> 
> Best Regards
> 
>   Andrea
> 
> [1]
> <https://community.arm.com/developer/ip-
> products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-
> authentication-and-branch-target-identification-extension>
> 
> gcc/ChangeLog
> 
> 2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>
> 
> 	* config.gcc (arm*-*-*): Add 'aarch-bti-insert.o' object.
> 	* config/arm/arm-protos.h: Update.
> 	* config/arm/arm.cc (aarch_bti_enabled, aarch_bti_j_insn_p)
> 	(aarch_pac_insn_p, aarch_gen_bti_c, aarch_gen_bti_j): New
> 	functions.
> 	* config/arm/arm.md (bti_nop): New insn.
> 	* config/arm/t-arm (PASSES_EXTRA): Add 'arm-passes.def'.
> 	(aarch-bti-insert.o): New target.
> 	* config/arm/unspecs.md (UNSPEC_BTI_NOP): New unspec.
> 	* config/arm/aarch-bti-insert.cc (rest_of_insert_bti): Update
> 	to verify arch compatibility.
> 	* config/arm/arm-passes.def: New file.
> 
> gcc/testsuite/ChangeLog
> 
> 2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>
> 
> 	* gcc.target/arm/bti-1.c: New testcase.
> 	* gcc.target/arm/bti-2.c: Likewise.

diff --git a/gcc/config/arm/aarch-bti-insert.cc b/gcc/config/arm/aarch-bti-insert.cc
index 2d1d2e334a9..8f045c247bf 100644
--- a/gcc/config/arm/aarch-bti-insert.cc
+++ b/gcc/config/arm/aarch-bti-insert.cc
@@ -41,6 +41,7 @@
 #include "cfgrtl.h"
 #include "tree-pass.h"
 #include "cgraph.h"
+#include "diagnostic-core.h"
 
This change doesn't seem to match what's in the ChangeLog and doesn't make sense to me.

@@ -32985,6 +32979,58 @@ arm_current_function_pac_enabled_p (void)
 	&& !crtl->is_leaf);
 }
 
+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+bool
+aarch_bti_enabled (void)
+{
+  return aarch_enable_bti == 1;
+}
+
+/* Check if INSN is a BTI J insn.  */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+  if (!insn || !INSN_P (insn))
+    return false;
+
+  rtx pat = PATTERN (insn);
+  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPEC_BTI_NOP;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */

The arm instructions are not PACIASP/PACIBSP.
This comment should be rewritten.

+bool
+aarch_pac_insn_p (rtx x)
+{

..........

+rtx
+aarch_gen_bti_c (void)
+{
+  return gen_bti_nop ();
+}
+
+rtx
+aarch_gen_bti_j (void)
+{
+  return gen_bti_nop ();
+}
+

A reader may be confused for why we have a bti_c and bti_j function that have identical functionality.
Please add function comments explaining the situation.

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 92269a7819a..90c8c1d66f5 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12913,6 +12913,13 @@
   "aut\t%|ip, %|lr, %|sp"
   [(set_attr "length" "4")])
 
+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
+  "arm_arch7 && arm_arch_cmse"

That seems like a copy-paste mistake. CMSE has nothing to do with this functionality?

+  "bti"
+  [(set_attr "length" "4")

The length of instructions in the arm backend is 4 by default, this set_attr can be omitted

+   (set_attr "type" "mov_reg")])
+
Probably better to use the "nop" attribute here?

Thanks,
Kyrill

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-09-27  9:03   ` Kyrylo Tkachov
@ 2022-09-27 10:05     ` Andrea Corallo
  2022-09-27 15:24       ` Kyrylo Tkachov
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-09-27 10:05 UTC (permalink / raw)
  To: Kyrylo Tkachov; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:

> Hi Andrea,
>
>> -----Original Message-----
>> From: Gcc-patches <gcc-patches-
>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>> Corallo via Gcc-patches
>> Sent: Friday, August 12, 2022 4:34 PM
>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping
>> if necessary
>> 
>> Hi all,
>> 
>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>> pointer as CFA reg when popping if this is necessary.
>> 
>
> From what I can tell from similar functions this is correct, but could you elaborate on why this change is needed for my understanding please?
> Thanks,
> Kyrill

Hi Kyrill,

sure, if the frame pointer was set, than it is the current CFA register.
If we request to adjust the current CFA register offset indicating it
being SP (while it's actually FP) that is indeed not correct and the
incoherence we will be detected by an assertion in the dwarf emission
machinery.

Best Regards

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-09-27 10:05     ` Andrea Corallo
@ 2022-09-27 15:24       ` Kyrylo Tkachov
  2022-10-21 12:30         ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Kyrylo Tkachov @ 2022-09-27 15:24 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd



> -----Original Message-----
> From: Andrea Corallo <andrea.corallo@arm.com>
> Sent: Tuesday, September 27, 2022 11:06 AM
> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
> popping if necessary
> 
> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
> 
> > Hi Andrea,
> >
> >> -----Original Message-----
> >> From: Gcc-patches <gcc-patches-
> >> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
> >> Corallo via Gcc-patches
> >> Sent: Friday, August 12, 2022 4:34 PM
> >> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
> >> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
> >> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
> popping
> >> if necessary
> >>
> >> Hi all,
> >>
> >> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
> >> pointer as CFA reg when popping if this is necessary.
> >>
> >
> > From what I can tell from similar functions this is correct, but could you
> elaborate on why this change is needed for my understanding please?
> > Thanks,
> > Kyrill
> 
> Hi Kyrill,
> 
> sure, if the frame pointer was set, than it is the current CFA register.
> If we request to adjust the current CFA register offset indicating it
> being SP (while it's actually FP) that is indeed not correct and the
> incoherence we will be detected by an assertion in the dwarf emission
> machinery.

Thanks,  the patch is ok
Kyrill

> 
> Best Regards
> 
>   Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 12/15 V2] arm: implement bti injection
  2022-09-27  9:18   ` Kyrylo Tkachov
@ 2022-09-29 15:45     ` Andrea Corallo
  2022-10-20 14:56       ` Kyrylo Tkachov
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-09-29 15:45 UTC (permalink / raw)
  To: Kyrylo Tkachov; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 2647 bytes --]

Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:

> Hi Andrea,

[...]

> diff --git a/gcc/config/arm/aarch-bti-insert.cc b/gcc/config/arm/aarch-bti-insert.cc
> index 2d1d2e334a9..8f045c247bf 100644
> --- a/gcc/config/arm/aarch-bti-insert.cc
> +++ b/gcc/config/arm/aarch-bti-insert.cc
> @@ -41,6 +41,7 @@
>  #include "cfgrtl.h"
>  #include "tree-pass.h"
>  #include "cgraph.h"
> +#include "diagnostic-core.h"
>
> This change doesn't seem to match what's in the ChangeLog and doesn't make sense to me.

Change removed thanks.

> @@ -32985,6 +32979,58 @@ arm_current_function_pac_enabled_p (void)
>  	&& !crtl->is_leaf);
>  }
>
> +/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
> +bool
> +aarch_bti_enabled (void)
> +{
> +  return aarch_enable_bti == 1;
> +}
> +
> +/* Check if INSN is a BTI J insn.  */
> +bool
> +aarch_bti_j_insn_p (rtx_insn *insn)
> +{
> +  if (!insn || !INSN_P (insn))
> +    return false;
> +
> +  rtx pat = PATTERN (insn);
> +  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPEC_BTI_NOP;
> +}
> +
> +/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
>
> The arm instructions are not PACIASP/PACIBSP.
> This comment should be rewritten.

This hunk belongs to aarch64.cc so it's aarch64 specific.

> +bool
> +aarch_pac_insn_p (rtx x)
> +{
>
> ..........
>
> +rtx
> +aarch_gen_bti_c (void)
> +{
> +  return gen_bti_nop ();
> +}
> +
> +rtx
> +aarch_gen_bti_j (void)
> +{
> +  return gen_bti_nop ();
> +}
> +
>
> A reader may be confused for why we have a bti_c and bti_j function that have identical functionality.
> Please add function comments explaining the situation.

Done

> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index 92269a7819a..90c8c1d66f5 100644
> --- a/gcc/config/arm/arm.md
> +++ b/gcc/config/arm/arm.md
> @@ -12913,6 +12913,13 @@
>    "aut\t%|ip, %|lr, %|sp"
>    [(set_attr "length" "4")])
>
> +(define_insn "bti_nop"
> +  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
> +  "arm_arch7 && arm_arch_cmse"
>
> That seems like a copy-paste mistake. CMSE has nothing to do with this functionality?

This is because we don't have arm_arch8m_main, but this is equivalent to
arm_arch7 && arm_arch_cmse.  IIUC it wasn't added becasue armv8-m is
basically just armv7-m + cmse.

Any other preferred way to express this?

> +  "bti"
> +  [(set_attr "length" "4")
>
> The length of instructions in the arm backend is 4 by default, this set_attr can be omitted
>
> +   (set_attr "type" "mov_reg")])
> +
> Probably better to use the "nop" attribute here?

Done

Thanks for reviewing, please find attached the updated version.

  Andrea


[-- Attachment #2: 0001-PATCH-12-15-arm-implement-bti-injection.patch --]
[-- Type: text/plain, Size: 9769 bytes --]

From 42f81b763c3a347f3452cd6ead056748d2830135 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 7 Apr 2022 11:51:56 +0200
Subject: [PATCH] [PATCH 12/15] arm: implement bti injection

Hi all,

this patch enables Branch Target Identification Armv8.1-M Mechanism
[1].

This is achieved by using the bti pass made common with Aarch64.

The pass iterates through the instructions and adds the necessary BTI
instructions at the beginning of every function and at every landing
pads targeted by indirect jumps.

Best Regards

  Andrea

[1]
<https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* config.gcc (arm*-*-*): Add 'aarch-bti-insert.o' object.
	* config/arm/arm-protos.h: Update.
	* config/arm/arm.cc (aarch_bti_enabled, aarch_bti_j_insn_p)
	(aarch_pac_insn_p, aarch_gen_bti_c, aarch_gen_bti_j): New
	functions.
	* config/arm/arm.md (bti_nop): New insn.
	* config/arm/t-arm (PASSES_EXTRA): Add 'arm-passes.def'.
	(aarch-bti-insert.o): New target.
	* config/arm/unspecs.md (UNSPEC_BTI_NOP): New unspec.
	* config/arm/aarch-bti-insert.cc (rest_of_insert_bti): Update
	to verify arch compatibility.
	* config/arm/arm-passes.def: New file.

gcc/testsuite/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/bti-1.c: New testcase.
	* gcc.target/arm/bti-2.c: Likewise.
---
 gcc/config.gcc                       |  2 +-
 gcc/config/arm/arm-passes.def        | 21 ++++++++++
 gcc/config/arm/arm-protos.h          |  2 +
 gcc/config/arm/arm.cc                | 61 +++++++++++++++++++++++++---
 gcc/config/arm/arm.md                |  6 +++
 gcc/config/arm/t-arm                 | 10 +++++
 gcc/config/arm/unspecs.md            |  1 +
 gcc/testsuite/gcc.target/arm/bti-1.c | 12 ++++++
 gcc/testsuite/gcc.target/arm/bti-2.c | 58 ++++++++++++++++++++++++++
 9 files changed, 166 insertions(+), 7 deletions(-)
 create mode 100644 gcc/config/arm/arm-passes.def
 create mode 100644 gcc/testsuite/gcc.target/arm/bti-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/bti-2.c

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 2021bdf9d2f..004e1dfa8d8 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -353,7 +353,7 @@ arc*-*-*)
 	;;
 arm*-*-*)
 	cpu_type=arm
-	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
+	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o aarch-bti-insert.o"
 	extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
 	target_type_format_char='%'
 	c_target_objs="arm-c.o"
diff --git a/gcc/config/arm/arm-passes.def b/gcc/config/arm/arm-passes.def
new file mode 100644
index 00000000000..71d6b563640
--- /dev/null
+++ b/gcc/config/arm/arm-passes.def
@@ -0,0 +1,21 @@
+/* Arm-specific passes declarations.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   Contributed by Arm Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 84764bf27ce..6befb6c4445 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -24,6 +24,8 @@
 
 #include "sbitmap.h"
 
+rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
+
 extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *);
 extern int use_return_insn (int, rtx);
 extern bool use_simple_return_p (void);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 0ba9c0b9960..a37fd20c090 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -23368,12 +23368,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
-static bool
-aarch_bti_enabled ()
-{
-  return false;
-}
-
 /* Generate the prologue instructions for entry into an ARM or Thumb-2
    function.  */
 void
@@ -32986,6 +32980,61 @@ arm_current_function_pac_enabled_p (void)
 	&& !crtl->is_leaf);
 }
 
+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+bool
+aarch_bti_enabled (void)
+{
+  return aarch_enable_bti == 1;
+}
+
+/* Check if INSN is a BTI J insn.  */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+  if (!insn || !INSN_P (insn))
+    return false;
+
+  rtx pat = PATTERN (insn);
+  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPEC_BTI_NOP;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
+bool
+aarch_pac_insn_p (rtx x)
+{
+  if (!x || !INSN_P (x))
+    return false;
+
+  rtx pat = PATTERN (x);
+
+  if (GET_CODE (pat) == SET)
+    {
+      rtx tmp = XEXP (pat, 1);
+      if (tmp
+	  && GET_CODE (tmp) == UNSPEC
+	  && (XINT (tmp, 1) == UNSPEC_PAC_NOP
+	      || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
+	return true;
+    }
+
+  return false;
+}
+
+/* The following two functions are for code compatibility with aarch64
+   code, this even if in arm we have only one bti instruction.  */
+
+rtx
+aarch_gen_bti_c (void)
+{
+  return gen_bti_nop ();
+}
+
+rtx
+aarch_gen_bti_j (void)
+{
+  return gen_bti_nop ();
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 92269a7819a..70a3d0a5013 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12913,6 +12913,12 @@ (define_insn "aut_nop"
   "aut\t%|ip, %|lr, %|sp"
   [(set_attr "length" "4")])
 
+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
+  "arm_arch7 && arm_arch_cmse"
+  "bti"
+  [(set_attr "type" "nop")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index 041cc6ec045..683342cb528 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -175,3 +175,13 @@ arm-d.o: $(srcdir)/config/arm/arm-d.cc
 arm-common.o: arm-cpu-cdata.h
 
 driver-arm.o: arm-native.h
+
+PASSES_EXTRA += $(srcdir)/config/arm/arm-passes.def
+
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.cc \
+    $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+    dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+    output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+    $(CONTEXT_H) $(TREE_PASS_H) regrename.h
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/arm/aarch-bti-insert.cc
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index dbe243a03f6..78e723a4b3c 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -162,6 +162,7 @@ (define_c_enum "unspec" [
   UNSPEC_PAC_NOP	; Represents PAC signing LR
   UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
   UNSPEC_AUT_NOP	; Represents PAC verifying LR
+  UNSPEC_BTI_NOP	; Represent BTI
 ])
 
 
diff --git a/gcc/testsuite/gcc.target/arm/bti-1.c b/gcc/testsuite/gcc.target/arm/bti-1.c
new file mode 100644
index 00000000000..230ebb5a1da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-1.c
@@ -0,0 +1,12 @@
+/* Check that GCC does bti instruction.  */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mbranch-protection=bti --save-temps" } */
+
+int
+main (void)
+{
+  return 0;
+}
+
+/* { dg-final { scan-assembler "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/bti-2.c b/gcc/testsuite/gcc.target/arm/bti-2.c
new file mode 100644
index 00000000000..35aef6992e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-2.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* -Os to create jump table.  */
+/* { dg-options "-Os" } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mbranch-protection=bti --save-temps" } */
+
+extern int f1 (void);
+extern int f2 (void);
+extern int f3 (void);
+extern int f4 (void);
+extern int f5 (void);
+extern int f6 (void);
+extern int f7 (void);
+extern int f8 (void);
+extern int f9 (void);
+extern int f10 (void);
+
+int (*ptr) (void);
+
+int
+f_jump_table (int y, int n)
+{
+  int i;
+  for (i = 0; i < n ;i ++)
+  {
+    switch (y)
+      {
+      case 0 : ptr = f1; break;
+      case 1 : ptr = f2; break;
+      case 2 : ptr = f3; break;
+      case 3 : ptr = f4; break;
+      case 4 : ptr = f5; break;
+      case 5 : ptr = f6; break;
+      case 6 : ptr = f7; break;
+      case 7 : ptr = f8; break;
+      case 8 : ptr = f9; break;
+      case 9 : ptr = f10; break;
+      default: break;
+      }
+    y += ptr ();
+  }
+  return (y == 0)? y+1:4;
+}
+
+int
+f_label_address ()
+{
+  static void * addr = &&lab1;
+  goto *addr;
+lab1:
+  addr = &&lab2;
+  return 1;
+lab2:
+  addr = &&lab1;
+  return 2;
+}
+
+/* { dg-final { scan-assembler-times "bti" 15 } } */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH 7/15] arm: Emit build attributes for PACBTI target feature
  2022-08-12 15:30 ` [PATCH 7/15] arm: Emit build attributes for PACBTI target feature Andrea Corallo
  2022-09-05 16:53   ` Andrea Corallo
@ 2022-10-20 14:47   ` Kyrylo Tkachov
  2022-10-20 15:15     ` Richard Earnshaw
  2022-10-21 12:19   ` Richard Earnshaw
  2 siblings, 1 reply; 66+ messages in thread
From: Kyrylo Tkachov @ 2022-10-20 14:47 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Hi Andrea,

> -----Original Message-----
> From: Gcc-patches <gcc-patches-
> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
> Corallo via Gcc-patches
> Sent: Friday, August 12, 2022 4:31 PM
> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
> Subject: [PATCH 7/15] arm: Emit build attributes for PACBTI target feature
> 
> This patch emits assembler directives for PACBTI build attributes as
> defined by the
> ABI.
> 
> <https://github.com/ARM-software/abi-
> aa/releases/download/2021Q1/addenda32.pdf>
> 
> gcc/ChangeLog:
> 
> 	* config/arm/arm.c (arm_file_start): Emit EABI attributes for
> 	Tag_PAC_extension, Tag_BTI_extension, TAG_BTI_use,
> TAG_PACRET_use.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/arm/acle/pacbti-m-predef-1.c: New test.
> 	* gcc.target/arm/acle/pacbti-m-predef-3: Likewise.
> 	* gcc.target/arm/acle/pacbti-m-predef-6.c: Likewise.
> 	* gcc.target/arm/acle/pacbti-m-predef-7.c: Likewise.
> 
> Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>

diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 0068817b0f2..ceec14f84b6 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -28349,6 +28349,8 @@ static void
 arm_file_start (void)
 {
   int val;
+  bool pac = (aarch_ra_sign_scope != AARCH_FUNCTION_NONE);
+  bool bti = (aarch_enable_bti == 1);
 
   arm_print_asm_arch_directives
     (asm_out_file, TREE_TARGET_OPTION (target_option_default_node));
@@ -28419,6 +28421,22 @@ arm_file_start (void)
 	arm_emit_eabi_attribute ("Tag_ABI_FP_16bit_format", 38,
 			     (int) arm_fp16_format);
 
+      if (TARGET_HAVE_PACBTI)
+	{
+	  arm_emit_eabi_attribute ("Tag_PAC_extension", 50, 2);
+	  arm_emit_eabi_attribute ("Tag_BTI_extension", 52, 2);
+	}
+      else if (pac || bti)
+	{
+	  arm_emit_eabi_attribute ("Tag_PAC_extension", 50, 1);
+	  arm_emit_eabi_attribute ("Tag_BTI_extension", 52, 1);
+	}

This hunk will set both Tag_PAC_extension and Tag_BTI_extension if only one of pac or bti is on. Is that intended?
Would it makes sense to instead set the two Tag_*_extension tags individually as in the hunk below?
+
+      if (bti)
+        arm_emit_eabi_attribute ("TAG_BTI_use", 74, 1);
+      if (pac)
+	arm_emit_eabi_attribute ("TAG_PACRET_use", 76, 1);
+
       if (arm_lang_output_object_attributes_hook)
 	arm_lang_output_object_attributes_hook();
     }

Thanks,
Kyrill


^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PATCH 12/15 V2] arm: implement bti injection
  2022-09-29 15:45     ` [PATCH 12/15 V2] " Andrea Corallo
@ 2022-10-20 14:56       ` Kyrylo Tkachov
  2022-10-28 16:40         ` [PATCH 12/15 V3] " Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Kyrylo Tkachov @ 2022-10-20 14:56 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd



> -----Original Message-----
> From: Andrea Corallo <andrea.corallo@arm.com>
> Sent: Thursday, September 29, 2022 4:46 PM
> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
> Subject: [PATCH 12/15 V2] arm: implement bti injection
> 
> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
> 
> > Hi Andrea,
> 
> [...]
> 
> > diff --git a/gcc/config/arm/aarch-bti-insert.cc b/gcc/config/arm/aarch-bti-
> insert.cc
> > index 2d1d2e334a9..8f045c247bf 100644
> > --- a/gcc/config/arm/aarch-bti-insert.cc
> > +++ b/gcc/config/arm/aarch-bti-insert.cc
> > @@ -41,6 +41,7 @@
> >  #include "cfgrtl.h"
> >  #include "tree-pass.h"
> >  #include "cgraph.h"
> > +#include "diagnostic-core.h"
> >
> > This change doesn't seem to match what's in the ChangeLog and doesn't
> make sense to me.
> 
> Change removed thanks.
> 
> > @@ -32985,6 +32979,58 @@ arm_current_function_pac_enabled_p (void)
> >  	&& !crtl->is_leaf);
> >  }
> >
> > +/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
> > +bool
> > +aarch_bti_enabled (void)
> > +{
> > +  return aarch_enable_bti == 1;
> > +}
> > +
> > +/* Check if INSN is a BTI J insn.  */
> > +bool
> > +aarch_bti_j_insn_p (rtx_insn *insn)
> > +{
> > +  if (!insn || !INSN_P (insn))
> > +    return false;
> > +
> > +  rtx pat = PATTERN (insn);
> > +  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) ==
> UNSPEC_BTI_NOP;
> > +}
> > +
> > +/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
> >
> > The arm instructions are not PACIASP/PACIBSP.
> > This comment should be rewritten.
> 
> This hunk belongs to aarch64.cc so it's aarch64 specific.
> 
> > +bool
> > +aarch_pac_insn_p (rtx x)
> > +{
> >
> > ..........
> >
> > +rtx
> > +aarch_gen_bti_c (void)
> > +{
> > +  return gen_bti_nop ();
> > +}
> > +
> > +rtx
> > +aarch_gen_bti_j (void)
> > +{
> > +  return gen_bti_nop ();
> > +}
> > +
> >
> > A reader may be confused for why we have a bti_c and bti_j function that
> have identical functionality.
> > Please add function comments explaining the situation.
> 
> Done
> 
> > diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> > index 92269a7819a..90c8c1d66f5 100644
> > --- a/gcc/config/arm/arm.md
> > +++ b/gcc/config/arm/arm.md
> > @@ -12913,6 +12913,13 @@
> >    "aut\t%|ip, %|lr, %|sp"
> >    [(set_attr "length" "4")])
> >
> > +(define_insn "bti_nop"
> > +  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
> > +  "arm_arch7 && arm_arch_cmse"
> >
> > That seems like a copy-paste mistake. CMSE has nothing to do with this
> functionality?
> 
> This is because we don't have arm_arch8m_main, but this is equivalent to
> arm_arch7 && arm_arch_cmse.  IIUC it wasn't added becasue armv8-m is
> basically just armv7-m + cmse.
> 
> Any other preferred way to express this?

I think I'd prefer if we added an explicit arm_arch8m_main. It would help readability

> 
> > +  "bti"
> > +  [(set_attr "length" "4")
> >
> > The length of instructions in the arm backend is 4 by default, this set_attr
> can be omitted
> >
> > +   (set_attr "type" "mov_reg")])
> > +
> > Probably better to use the "nop" attribute here?
> 
> Done

Thanks, and as in patch 10/12 I think we'll want to set the "conds" attribute here to "unconditional".
Looks good to me otherwise!
Kyrill

> 
> Thanks for reviewing, please find attached the updated version.
> 
>   Andrea


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 7/15] arm: Emit build attributes for PACBTI target feature
  2022-10-20 14:47   ` Kyrylo Tkachov
@ 2022-10-20 15:15     ` Richard Earnshaw
  0 siblings, 0 replies; 66+ messages in thread
From: Richard Earnshaw @ 2022-10-20 15:15 UTC (permalink / raw)
  To: Kyrylo Tkachov, Andrea Corallo, Andrea Corallo via Gcc-patches
  Cc: Richard Earnshaw, nd



On 20/10/2022 15:47, Kyrylo Tkachov via Gcc-patches wrote:
> Hi Andrea,
> 
>> -----Original Message-----
>> From: Gcc-patches <gcc-patches-
>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>> Corallo via Gcc-patches
>> Sent: Friday, August 12, 2022 4:31 PM
>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>> Subject: [PATCH 7/15] arm: Emit build attributes for PACBTI target feature
>>
>> This patch emits assembler directives for PACBTI build attributes as
>> defined by the
>> ABI.
>>
>> <https://github.com/ARM-software/abi-
>> aa/releases/download/2021Q1/addenda32.pdf>
>>
>> gcc/ChangeLog:
>>
>> 	* config/arm/arm.c (arm_file_start): Emit EABI attributes for
>> 	Tag_PAC_extension, Tag_BTI_extension, TAG_BTI_use,
>> TAG_PACRET_use.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 	* gcc.target/arm/acle/pacbti-m-predef-1.c: New test.
>> 	* gcc.target/arm/acle/pacbti-m-predef-3: Likewise.
>> 	* gcc.target/arm/acle/pacbti-m-predef-6.c: Likewise.
>> 	* gcc.target/arm/acle/pacbti-m-predef-7.c: Likewise.
>>
>> Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>
> 
> diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
> index 0068817b0f2..ceec14f84b6 100644
> --- a/gcc/config/arm/arm.cc
> +++ b/gcc/config/arm/arm.cc
> @@ -28349,6 +28349,8 @@ static void
>   arm_file_start (void)
>   {
>     int val;
> +  bool pac = (aarch_ra_sign_scope != AARCH_FUNCTION_NONE);
> +  bool bti = (aarch_enable_bti == 1);
>   
>     arm_print_asm_arch_directives
>       (asm_out_file, TREE_TARGET_OPTION (target_option_default_node));
> @@ -28419,6 +28421,22 @@ arm_file_start (void)
>   	arm_emit_eabi_attribute ("Tag_ABI_FP_16bit_format", 38,
>   			     (int) arm_fp16_format);
>   
> +      if (TARGET_HAVE_PACBTI)
> +	{
> +	  arm_emit_eabi_attribute ("Tag_PAC_extension", 50, 2);
> +	  arm_emit_eabi_attribute ("Tag_BTI_extension", 52, 2);
> +	}
> +      else if (pac || bti)
> +	{
> +	  arm_emit_eabi_attribute ("Tag_PAC_extension", 50, 1);
> +	  arm_emit_eabi_attribute ("Tag_BTI_extension", 52, 1);
> +	}
> 
> This hunk will set both Tag_PAC_extension and Tag_BTI_extension if only one of pac or bti is on. Is that intended?
> Would it makes sense to instead set the two Tag_*_extension tags individually as in the hunk below?

That's because they are one feature in armv8-m and these tags describe 
the presence of the feature in the architecture.

> +
> +      if (bti)
> +        arm_emit_eabi_attribute ("TAG_BTI_use", 74, 1);
> +      if (pac)
> +	arm_emit_eabi_attribute ("TAG_PACRET_use", 76, 1);
> +

But this describes /use/ by the code of each feature.

R.

>         if (arm_lang_output_object_attributes_hook)
>   	arm_lang_output_object_attributes_hook();
>       }
> 
> Thanks,
> Kyrill
> 

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 7/15] arm: Emit build attributes for PACBTI target feature
  2022-08-12 15:30 ` [PATCH 7/15] arm: Emit build attributes for PACBTI target feature Andrea Corallo
  2022-09-05 16:53   ` Andrea Corallo
  2022-10-20 14:47   ` Kyrylo Tkachov
@ 2022-10-21 12:19   ` Richard Earnshaw
  2 siblings, 0 replies; 66+ messages in thread
From: Richard Earnshaw @ 2022-10-21 12:19 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 12/08/2022 16:30, Andrea Corallo via Gcc-patches wrote:
> This patch emits assembler directives for PACBTI build attributes as
> defined by the
> ABI.
> 
> <https://github.com/ARM-software/abi-aa/releases/download/2021Q1/addenda32.pdf>
> 
> gcc/ChangeLog:
> 
> 	* config/arm/arm.c (arm_file_start): Emit EABI attributes for
> 	Tag_PAC_extension, Tag_BTI_extension, TAG_BTI_use, TAG_PACRET_use.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/arm/acle/pacbti-m-predef-1.c: New test.
> 	* gcc.target/arm/acle/pacbti-m-predef-3: Likewise.
> 	* gcc.target/arm/acle/pacbti-m-predef-6.c: Likewise.
> 	* gcc.target/arm/acle/pacbti-m-predef-7.c: Likewise.
> 
> Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>
> 

OK.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-09-27 15:24       ` Kyrylo Tkachov
@ 2022-10-21 12:30         ` Richard Earnshaw
  2022-10-26  8:49           ` Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-10-21 12:30 UTC (permalink / raw)
  To: Kyrylo Tkachov, Andrea Corallo
  Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
> 
> 
>> -----Original Message-----
>> From: Andrea Corallo <andrea.corallo@arm.com>
>> Sent: Tuesday, September 27, 2022 11:06 AM
>> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
>> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
>> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>> popping if necessary
>>
>> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
>>
>>> Hi Andrea,
>>>
>>>> -----Original Message-----
>>>> From: Gcc-patches <gcc-patches-
>>>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>>>> Corallo via Gcc-patches
>>>> Sent: Friday, August 12, 2022 4:34 PM
>>>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>>>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>> popping
>>>> if necessary
>>>>
>>>> Hi all,
>>>>
>>>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>>>> pointer as CFA reg when popping if this is necessary.
>>>>
>>>
>>>  From what I can tell from similar functions this is correct, but could you
>> elaborate on why this change is needed for my understanding please?
>>> Thanks,
>>> Kyrill
>>
>> Hi Kyrill,
>>
>> sure, if the frame pointer was set, than it is the current CFA register.
>> If we request to adjust the current CFA register offset indicating it
>> being SP (while it's actually FP) that is indeed not correct and the
>> incoherence we will be detected by an assertion in the dwarf emission
>> machinery.
> 
> Thanks,  the patch is ok
> Kyrill
> 
>>
>> Best Regards
>>
>>    Andrea

Hmm, wait.  Why would a multi-reg pop be updating the stack pointer? 
Please can you show a code sequence where this is needed.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 10/15 V2] arm: Implement cortex-M return signing address codegen
  2022-09-14 14:20   ` [PATCH 10/15 V2] " Andrea Corallo
@ 2022-10-21 12:58     ` Richard Earnshaw
  2022-10-26 15:48       ` Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-10-21 12:58 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 14/09/2022 15:20, Andrea Corallo via Gcc-patches wrote:
> Hi all,
> 
> this patch enables address return signature and verification based on
> Armv8.1-M Pointer Authentication [1].
> 
> To sign the return address, we use the PAC R12, LR, SP instruction
> upon function entry.  This is signing LR using SP and storing the
> result in R12.  R12 will be pushed into the stack.
> 
> During function epilogue R12 will be popped and AUT R12, LR, SP will
> be used to verify that the content of LR is still valid before return.
> 
> Here an example of PAC instrumented function prologue and epilogue:
> 
> void foo (void);
> 
> int main()
> {
>    foo ();
>    return 0;
> }
> 
> Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
> -mthumb' translates into:
> 
> main:
> 	pac	ip, lr, sp
> 	push	{r3, r7, ip, lr}
> 	add	r7, sp, #0
> 	bl	foo
> 	movs	r3, #0
> 	mov	r0, r3
> 	pop	{r3, r7, ip, lr}
> 	aut	ip, lr, sp
> 	bx	lr
> 
> The patch also takes care of generating a PACBTI instruction in place
> of the sequence BTI+PAC when Branch Target Identification is enabled
> contextually.
> 
> Ex. the previous example compiled with '-march=armv8.1-m.main
> -mbranch-protection=pac-ret+bti -mthumb' translates into:
> 
> main:
> 	pacbti	ip, lr, sp
> 	push	{r3, r7, ip, lr}
> 	add	r7, sp, #0
> 	bl	foo
> 	movs	r3, #0
> 	mov	r0, r3
> 	pop	{r3, r7, ip, lr}
> 	aut	ip, lr, sp
> 	bx	lr
> 
> As part of previous upstream suggestions a test for varargs has been
> added and '-mtpcs-frame' is deemed being incompatible with this return
> signing address feature being introduced.
> 
> [1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>
> 
> gcc/Changelog
> 
> 2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>
> 
> 	* config/arm/arm.c: (arm_compute_frame_layout)
> 	(arm_expand_prologue, thumb2_expand_return, arm_expand_epilogue)
> 	(arm_conditional_register_usage): Update for pac codegen.
> 	(arm_current_function_pac_enabled_p): New function.
> 	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
> 	Add new patterns.
> 	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
> 	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.
> 
> gcc/testsuite/Changelog
> 
> 2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>
> 
> 	* gcc.target/arm/pac.h : New file.
> 	* gcc.target/arm/pac-1.c : New test case.
> 	* gcc.target/arm/pac-2.c : Likewise.
> 	* gcc.target/arm/pac-3.c : Likewise.
> 	* gcc.target/arm/pac-4.c : Likewise.
> 	* gcc.target/arm/pac-5.c : Likewise.
> 	* gcc.target/arm/pac-6.c : Likewise.
> 	* gcc.target/arm/pac-7.c : Likewise.
> 	* gcc.target/arm/pac-8.c : Likewise.
> 

+  if (arm_current_function_pac_enabled_p () && !(arm_arch7 && 
arm_arch_cmse))
+    error ("This architecture does not support branch protection 
instructions");

This test feels wrong.  What does having cmse give us?  I suspect you 
want a test that ensures we have at least v8-m.main so that the NOP 
instructions are correctly defined as NOPs (or, in this case, PACBTI 
instructions) rather than unpredictable; but if that's the case then I 
think you really want to write the test that way here (perhaps in a 
macro) and then move this test into that so that it becomes 
self-documenting - but don't we have a v8-m.main test anyway?


+	  if (arm_current_function_pac_enabled_p ())
+	    {
+              gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	      emit_insn (gen_aut_nop ());
+	      emit_jump_insn (simple_return_rtx);
+	    }

The assert is using indents that are just spaces, but the other lines 
use tabs.  Please use tabs everywhere rather than mixing like this.

+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+    || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+	&& !crtl->is_leaf);
+}

This is a case where you should use parenthesis around the expression so 
that the continuation lines are correctly indented.

@@ -11518,7 +11518,7 @@ (define_expand "prologue"
       arm_expand_prologue ();
     else
       thumb1_expand_prologue ();
-  DONE;
+   DONE;
    "
  )

Although this is a trivial cleanup, it has nothing to do with this 
patch.  Please remove.

+  "arm_arch7 && arm_arch_cmse"

See my comments earlier about this test; the same applies here.

+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PAC_NOP))]
+
Again you have a mix of lines indented with tabs and lines indented with 
just spaces.  Similarly with pacbti_nop and aut_nop.

Do you have a test for the nested functions case (I can't see it, but 
perhaps I've missed it somewhere)?

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 13/15] arm: Add pacbti related multilib support for armv8.1-m.main.
  2022-08-12 17:10 ` [PATCH 13/15] arm: Add pacbti related multilib support for armv8.1-m.main Srinath Parvathaneni
@ 2022-10-21 13:00   ` Richard Earnshaw
  0 siblings, 0 replies; 66+ messages in thread
From: Richard Earnshaw @ 2022-10-21 13:00 UTC (permalink / raw)
  To: Srinath Parvathaneni, gcc-patches; +Cc: Richard Earnshaw, nd



On 12/08/2022 18:10, Srinath Parvathaneni via Gcc-patches wrote:
>   Hi,
> 
> This patch supports following -march/-mbranch-protection combination by linking them
> to existing pacbti multilibs.
> 
> $ -march=armv8.1-m.main+pacbti+fp.dp+mve.fp -mbranch-protection=standard -mfloat-abi=hard -mthumb
> $ -march=armv8.1-m.main+pacbti+fp.dp+mve -mbranch-protection=standard -mfloat-abi=hard -mthumb
> $ -march=armv8.1-m.main+dsp+pacbti+fp.dp -mbranch-protection=standard -mfloat-abi=hard -mthumb
> 
> Regression tested on arm-none-eabi and bootstrapped on arm-none-linux-gnueabihf.
> 
> Ok for master?
> 
> Regards,
> Srinath.
> 
> gcc/ChangeLog:
> 
> 2022-08-12  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>
> 
>          * config/arm/t-rmprofile: Add pacbti multililb variants.
> 
> gcc/testsuite/ChangeLog:
> 
> 2022-08-12  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>
> 
>          * gcc.target/arm/pac-10.c: New test.
>          * gcc.target/arm/pac-11.c: Likewise.
>          * gcc.target/arm/pac-12.c: Likewise.

Please resend with a correctly attached patch.  You've used octet-stream 
rather than a text format.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M
  2022-09-21  8:07 ` [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
@ 2022-10-21 13:01   ` Richard Earnshaw
  2022-10-21 13:32     ` Andrea Corallo
  2022-12-05 14:10   ` Andrea Corallo
  2023-01-23 10:50   ` [PATCH " Andrea Corallo
  2 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-10-21 13:01 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 21/09/2022 09:07, Andrea Corallo via Gcc-patches wrote:
> Hi all,
> 
> ping^2 for patches 9/15 7/15 11/15 12/15 and 10/15 V2 of this series.
> 
>    Andrea

Subject says xx/15, but I only see 1-12 from you.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M
  2022-10-21 13:01   ` Richard Earnshaw
@ 2022-10-21 13:32     ` Andrea Corallo
  0 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-10-21 13:32 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

> On 21/09/2022 09:07, Andrea Corallo via Gcc-patches wrote:
>> Hi all,
>> ping^2 for patches 9/15 7/15 11/15 12/15 and 10/15 V2 of this
>> series.
>>    Andrea
>
> Subject says xx/15, but I only see 1-12 from you.
>
> R.

Yeah, at the time Srinath asked me to leave space for three more patches
to add to the series, but then he posted only 13/15 I guess squashing
the code in one patch.

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-10-21 12:30         ` Richard Earnshaw
@ 2022-10-26  8:49           ` Andrea Corallo
  2022-11-08 14:57             ` Richard Earnshaw
  2023-01-09 14:58             ` Andrea Corallo
  0 siblings, 2 replies; 66+ messages in thread
From: Andrea Corallo @ 2022-10-26  8:49 UTC (permalink / raw)
  To: Richard Earnshaw
  Cc: Kyrylo Tkachov, Richard Earnshaw, nd, Andrea Corallo via Gcc-patches

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

> On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
>> 
>>> -----Original Message-----
>>> From: Andrea Corallo <andrea.corallo@arm.com>
>>> Sent: Tuesday, September 27, 2022 11:06 AM
>>> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
>>> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
>>> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>> popping if necessary
>>>
>>> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
>>>
>>>> Hi Andrea,
>>>>
>>>>> -----Original Message-----
>>>>> From: Gcc-patches <gcc-patches-
>>>>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>>>>> Corallo via Gcc-patches
>>>>> Sent: Friday, August 12, 2022 4:34 PM
>>>>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>>>>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>> popping
>>>>> if necessary
>>>>>
>>>>> Hi all,
>>>>>
>>>>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>>>>> pointer as CFA reg when popping if this is necessary.
>>>>>
>>>>
>>>>  From what I can tell from similar functions this is correct, but could you
>>> elaborate on why this change is needed for my understanding please?
>>>> Thanks,
>>>> Kyrill
>>>
>>> Hi Kyrill,
>>>
>>> sure, if the frame pointer was set, than it is the current CFA register.
>>> If we request to adjust the current CFA register offset indicating it
>>> being SP (while it's actually FP) that is indeed not correct and the
>>> incoherence we will be detected by an assertion in the dwarf emission
>>> machinery.
>> Thanks,  the patch is ok
>> Kyrill
>> 
>>>
>>> Best Regards
>>>
>>>    Andrea
>
> Hmm, wait.  Why would a multi-reg pop be updating the stack pointer?

Hi Richard,

not sure I understand, isn't any pop updating SP by definition?

BR

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 10/15 V2] arm: Implement cortex-M return signing address codegen
  2022-10-21 12:58     ` Richard Earnshaw
@ 2022-10-26 15:48       ` Andrea Corallo
  2022-10-28 16:34         ` [PATCH 10/15 V3] " Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-10-26 15:48 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

> On 14/09/2022 15:20, Andrea Corallo via Gcc-patches wrote:
>> Hi all,
>> 
>> this patch enables address return signature and verification based on
>> Armv8.1-M Pointer Authentication [1].
>> 
>> To sign the return address, we use the PAC R12, LR, SP instruction
>> upon function entry.  This is signing LR using SP and storing the
>> result in R12.  R12 will be pushed into the stack.
>> 
>> During function epilogue R12 will be popped and AUT R12, LR, SP will
>> be used to verify that the content of LR is still valid before return.
>> 
>> Here an example of PAC instrumented function prologue and epilogue:
>> 
>> void foo (void);
>> 
>> int main()
>> {
>>    foo ();
>>    return 0;
>> }
>> 
>> Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
>> -mthumb' translates into:
>> 
>> main:
>> 	pac	ip, lr, sp
>> 	push	{r3, r7, ip, lr}
>> 	add	r7, sp, #0
>> 	bl	foo
>> 	movs	r3, #0
>> 	mov	r0, r3
>> 	pop	{r3, r7, ip, lr}
>> 	aut	ip, lr, sp
>> 	bx	lr
>> 
>> The patch also takes care of generating a PACBTI instruction in place
>> of the sequence BTI+PAC when Branch Target Identification is enabled
>> contextually.
>> 
>> Ex. the previous example compiled with '-march=armv8.1-m.main
>> -mbranch-protection=pac-ret+bti -mthumb' translates into:
>> 
>> main:
>> 	pacbti	ip, lr, sp
>> 	push	{r3, r7, ip, lr}
>> 	add	r7, sp, #0
>> 	bl	foo
>> 	movs	r3, #0
>> 	mov	r0, r3
>> 	pop	{r3, r7, ip, lr}
>> 	aut	ip, lr, sp
>> 	bx	lr
>> 
>> As part of previous upstream suggestions a test for varargs has been
>> added and '-mtpcs-frame' is deemed being incompatible with this return
>> signing address feature being introduced.
>> 
>> [1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>
>> 
>> gcc/Changelog
>> 
>> 2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>
>> 
>> 	* config/arm/arm.c: (arm_compute_frame_layout)
>> 	(arm_expand_prologue, thumb2_expand_return, arm_expand_epilogue)
>> 	(arm_conditional_register_usage): Update for pac codegen.
>> 	(arm_current_function_pac_enabled_p): New function.
>> 	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
>> 	Add new patterns.
>> 	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
>> 	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.
>> 
>> gcc/testsuite/Changelog
>> 
>> 2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>
>> 
>> 	* gcc.target/arm/pac.h : New file.
>> 	* gcc.target/arm/pac-1.c : New test case.
>> 	* gcc.target/arm/pac-2.c : Likewise.
>> 	* gcc.target/arm/pac-3.c : Likewise.
>> 	* gcc.target/arm/pac-4.c : Likewise.
>> 	* gcc.target/arm/pac-5.c : Likewise.
>> 	* gcc.target/arm/pac-6.c : Likewise.
>> 	* gcc.target/arm/pac-7.c : Likewise.
>> 	* gcc.target/arm/pac-8.c : Likewise.
>> 
>
> +  if (arm_current_function_pac_enabled_p () && !(arm_arch7 && 
> arm_arch_cmse))
> +    error ("This architecture does not support branch protection 
> instructions");
>
> This test feels wrong.  What does having cmse give us?  I suspect you 
> want a test that ensures we have at least v8-m.main so that the NOP 
> instructions are correctly defined as NOPs (or, in this case, PACBTI 
> instructions) rather than unpredictable; but if that's the case then I 
> think you really want to write the test that way here (perhaps in a 
> macro) and then move this test into that so that it becomes 
> self-documenting - but don't we have a v8-m.main test anyway?

Yep

> +	  if (arm_current_function_pac_enabled_p ())
> +	    {
> +              gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
> +	      arm_emit_multi_reg_pop (saved_regs_mask);
> +	      emit_insn (gen_aut_nop ());
> +	      emit_jump_insn (simple_return_rtx);
> +	    }
>
> The assert is using indents that are just spaces, but the other lines 
> use tabs.  Please use tabs everywhere rather than mixing like this.

Ack.

> +/* Return TRUE if return address signing mechanism is enabled.  */
> +bool
> +arm_current_function_pac_enabled_p (void)
> +{
> +  return aarch_ra_sign_scope == AARCH_FUNCTION_ALL
> +    || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
> +	&& !crtl->is_leaf);
> +}
>
> This is a case where you should use parenthesis around the expression so 
> that the continuation lines are correctly indented.

Ack.

> @@ -11518,7 +11518,7 @@ (define_expand "prologue"
>        arm_expand_prologue ();
>      else
>        thumb1_expand_prologue ();
> -  DONE;
> +   DONE;
>     "
>   )
>
> Although this is a trivial cleanup, it has nothing to do with this 
> patch.  Please remove.

Okay.

> +  "arm_arch7 && arm_arch_cmse"
>
> See my comments earlier about this test; the same applies here.
>
> +	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
> +                   UNSPEC_PAC_NOP))]
> +
> Again you have a mix of lines indented with tabs and lines indented with 
> just spaces.  Similarly with pacbti_nop and aut_nop.
>
> Do you have a test for the nested functions case (I can't see it, but 
> perhaps I've missed it somewhere)?

We have gcc/testsuite/gcc.target/arm/pac-7.c added by this patch.

> R.

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 10/15 V3] arm: Implement cortex-M return signing address codegen
  2022-10-26 15:48       ` Andrea Corallo
@ 2022-10-28 16:34         ` Andrea Corallo
  2022-11-07  8:57           ` [PATCH 10/15 V4] " Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-10-28 16:34 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 101 bytes --]

Hi all,

the third iteration of this patch is attached addresing review comments.

Thanks

  Andrea


[-- Attachment #2: 0001-PATCH-10-15-arm-Implement-cortex-M-return-signing-ad.patch --]
[-- Type: text/plain, Size: 19985 bytes --]

From b42e28be75f374a4e1a5943c8c9002e07dbcc567 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 20 Jan 2022 15:36:23 +0100
Subject: [PATCH] [PATCH 10/15] arm: Implement cortex-M return signing address
 codegen

Hi all,

this patch enables address return signature and verification based on
Armv8.1-M Pointer Authentication [1].

To sign the return address, we use the PAC R12, LR, SP instruction
upon function entry.  This is signing LR using SP and storing the
result in R12.  R12 will be pushed into the stack.

During function epilogue R12 will be popped and AUT R12, LR, SP will
be used to verify that the content of LR is still valid before return.

Here an example of PAC instrumented function prologue and epilogue:

void foo (void);

int main()
{
  foo ();
  return 0;
}

Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
-mthumb' translates into:

main:
	pac	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

The patch also takes care of generating a PACBTI instruction in place
of the sequence BTI+PAC when Branch Target Identification is enabled
contextually.

Ex. the previous example compiled with '-march=armv8.1-m.main
-mbranch-protection=pac-ret+bti -mthumb' translates into:

main:
	pacbti	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

As part of previous upstream suggestions a test for varargs has been
added and '-mtpcs-frame' is deemed being incompatible with this return
signing address feature being introduced.

[1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* config/arm/arm.h (arm_arch8m_main): Declare it.
	* config/arm/arm.cc (arm_arch8m_main): Define it.
	(arm_option_reconfigure_globals): Set arm_arch8m_main.
	(arm_compute_frame_layout, arm_expand_prologue)
	(thumb2_expand_return, arm_expand_epilogue)
	(arm_conditional_register_usage): Update for pac codegen.
	(arm_current_function_pac_enabled_p): New function.
	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
	Add new patterns.
	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.

gcc/testsuite/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/pac.h : New file.
	* gcc.target/arm/pac-1.c : New test case.
	* gcc.target/arm/pac-2.c : Likewise.
	* gcc.target/arm/pac-3.c : Likewise.
	* gcc.target/arm/pac-4.c : Likewise.
	* gcc.target/arm/pac-5.c : Likewise.
	* gcc.target/arm/pac-6.c : Likewise.
	* gcc.target/arm/pac-7.c : Likewise.
	* gcc.target/arm/pac-8.c : Likewise.
---
 gcc/config/arm/arm-protos.h          |  1 +
 gcc/config/arm/arm.cc                | 77 +++++++++++++++++++++++-----
 gcc/config/arm/arm.h                 |  4 ++
 gcc/config/arm/arm.md                | 23 +++++++++
 gcc/config/arm/unspecs.md            |  3 ++
 gcc/testsuite/gcc.target/arm/pac-1.c | 12 +++++
 gcc/testsuite/gcc.target/arm/pac-2.c | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-3.c | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-4.c | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-5.c | 28 ++++++++++
 gcc/testsuite/gcc.target/arm/pac-6.c | 18 +++++++
 gcc/testsuite/gcc.target/arm/pac-7.c | 32 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac-8.c | 34 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac.h   | 17 ++++++
 14 files changed, 268 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-3.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-4.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-5.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-6.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-7.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-8.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac.h

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index cff7ff1da2a..84764bf27ce 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -379,6 +379,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index a5cf4225aa2..fa0f9a61498 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -927,6 +927,11 @@ int arm_arch8_3 = 0;
 
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 int arm_arch8_4 = 0;
+
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+int arm_arch8m_main = 0;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 int arm_arch8_1m_main = 0;
@@ -3209,6 +3214,9 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p () && !arm_arch8m_main)
+    error ("This architecture does not support branch protection instructions");
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -3855,6 +3863,7 @@ arm_option_reconfigure_globals (void)
   arm_arch_arm_hwdiv = bitmap_bit_p (arm_active_target.isa, isa_bit_adiv);
   arm_arch_crc = bitmap_bit_p (arm_active_target.isa, isa_bit_crc32);
   arm_arch_cmse = bitmap_bit_p (arm_active_target.isa, isa_bit_cmse);
+  arm_arch8m_main = arm_arch7 && arm_arch_cmse;
   arm_arch_lpae = bitmap_bit_p (arm_active_target.isa, isa_bit_lpae);
   arm_arch_i8mm = bitmap_bit_p (arm_active_target.isa, isa_bit_i8mm);
   arm_arch_bf16 = bitmap_bit_p (arm_active_target.isa, isa_bit_bf16);
@@ -21139,6 +21148,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23362,6 +23374,12 @@ output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Generate the prologue instructions for entry into an ARM or Thumb-2
    function.  */
 void
@@ -23440,12 +23458,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || (arm_current_function_pac_enabled_p ())));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23470,7 +23489,8 @@ arm_expand_prologue (void)
 	{
 	  rtx addr, dwarf;
 
-	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
+	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4
+                     || arm_current_function_pac_enabled_p ());
 	  saved_regs += 4;
 
 	  addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
@@ -23521,6 +23541,14 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (aarch_bti_enabled ())
+	emit_insn (gen_pacbti_nop ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27309,7 +27337,7 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (num_regs == 1 && !arm_current_function_pac_enabled_p ())
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27324,10 +27352,20 @@ thumb2_expand_return (bool simple_return)
         }
       else
         {
-          saved_regs_mask &= ~ (1 << LR_REGNUM);
-          saved_regs_mask |=   (1 << PC_REGNUM);
-          arm_emit_multi_reg_pop (saved_regs_mask);
-        }
+	  if (arm_current_function_pac_enabled_p ())
+	    {
+	      gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	      emit_insn (gen_aut_nop ());
+	      emit_jump_insn (simple_return_rtx);
+	    }
+	  else
+	    {
+	      saved_regs_mask &= ~ (1 << LR_REGNUM);
+	      saved_regs_mask |=   (1 << PC_REGNUM);
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	    }
+	}
     }
   else
     {
@@ -27733,7 +27771,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27847,6 +27886,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -32941,6 +32983,15 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+          || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+              && !crtl->is_leaf));
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 3495ab857ea..e33425bbf42 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -510,6 +510,10 @@ extern int arm_arch8_3;
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 extern int arm_arch8_4;
 
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+extern int arm_arch8m_main;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 extern int arm_arch8_1m_main;
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 60468f6182c..7255fa98f5d 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12890,6 +12890,29 @@ (define_insn "*speculation_barrier_insn"
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PAC_NOP))]
+  "arm_arch8m_main"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PACBTI_NOP))]
+  "arm_arch8m_main"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+	      UNSPEC_AUT_NOP)]
+  "arm_arch8m_main"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..dbe243a03f6 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,9 @@ (define_c_enum "unspec" [
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
+  UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  UNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..6cd64dbd014
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,12 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 12/15 V3] arm: implement bti injection
  2022-10-20 14:56       ` Kyrylo Tkachov
@ 2022-10-28 16:40         ` Andrea Corallo
  2022-12-05 17:02           ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-10-28 16:40 UTC (permalink / raw)
  To: Kyrylo Tkachov; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 110 bytes --]

Hi all,

please find attached the third iteration of this patch addresing review
comments.

Thanks

  Andrea


[-- Attachment #2: 0001-PATCH-12-15-arm-implement-bti-injection.patch --]
[-- Type: text/plain, Size: 9861 bytes --]

From e3001bd662b84dafeca200b52fc644b7bf81c4af Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 7 Apr 2022 11:51:56 +0200
Subject: [PATCH] [PATCH 12/15] arm: implement bti injection

Hi all,

this patch enables Branch Target Identification Armv8.1-M Mechanism
[1].

This is achieved by using the bti pass made common with Aarch64.

The pass iterates through the instructions and adds the necessary BTI
instructions at the beginning of every function and at every landing
pads targeted by indirect jumps.

Best Regards

  Andrea

[1]
<https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* config.gcc (arm*-*-*): Add 'aarch-bti-insert.o' object.
	* config/arm/arm-protos.h: Update.
	* config/arm/arm.cc (aarch_bti_enabled, aarch_bti_j_insn_p)
	(aarch_pac_insn_p, aarch_gen_bti_c, aarch_gen_bti_j): New
	functions.
	* config/arm/arm.md (bti_nop): New insn.
	* config/arm/t-arm (PASSES_EXTRA): Add 'arm-passes.def'.
	(aarch-bti-insert.o): New target.
	* config/arm/unspecs.md (UNSPEC_BTI_NOP): New unspec.
	* config/arm/aarch-bti-insert.cc (rest_of_insert_bti): Update
	to verify arch compatibility.
	* config/arm/arm-passes.def: New file.

gcc/testsuite/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/bti-1.c: New testcase.
	* gcc.target/arm/bti-2.c: Likewise.
---
 gcc/config.gcc                       |  2 +-
 gcc/config/arm/arm-passes.def        | 21 ++++++++++
 gcc/config/arm/arm-protos.h          |  2 +
 gcc/config/arm/arm.cc                | 61 +++++++++++++++++++++++++---
 gcc/config/arm/arm.md                |  7 ++++
 gcc/config/arm/t-arm                 | 10 +++++
 gcc/config/arm/unspecs.md            |  1 +
 gcc/testsuite/gcc.target/arm/bti-1.c | 12 ++++++
 gcc/testsuite/gcc.target/arm/bti-2.c | 58 ++++++++++++++++++++++++++
 9 files changed, 167 insertions(+), 7 deletions(-)
 create mode 100644 gcc/config/arm/arm-passes.def
 create mode 100644 gcc/testsuite/gcc.target/arm/bti-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/bti-2.c

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 2021bdf9d2f..004e1dfa8d8 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -353,7 +353,7 @@ arc*-*-*)
 	;;
 arm*-*-*)
 	cpu_type=arm
-	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
+	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o aarch-bti-insert.o"
 	extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
 	target_type_format_char='%'
 	c_target_objs="arm-c.o"
diff --git a/gcc/config/arm/arm-passes.def b/gcc/config/arm/arm-passes.def
new file mode 100644
index 00000000000..71d6b563640
--- /dev/null
+++ b/gcc/config/arm/arm-passes.def
@@ -0,0 +1,21 @@
+/* Arm-specific passes declarations.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   Contributed by Arm Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 84764bf27ce..6befb6c4445 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -24,6 +24,8 @@
 
 #include "sbitmap.h"
 
+rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
+
 extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *);
 extern int use_return_insn (int, rtx);
 extern bool use_simple_return_p (void);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index fa0f9a61498..26d4c1502f2 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -23374,12 +23374,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
-static bool
-aarch_bti_enabled ()
-{
-  return false;
-}
-
 /* Generate the prologue instructions for entry into an ARM or Thumb-2
    function.  */
 void
@@ -32992,6 +32986,61 @@ arm_current_function_pac_enabled_p (void)
               && !crtl->is_leaf));
 }
 
+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+bool
+aarch_bti_enabled (void)
+{
+  return aarch_enable_bti == 1;
+}
+
+/* Check if INSN is a BTI J insn.  */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+  if (!insn || !INSN_P (insn))
+    return false;
+
+  rtx pat = PATTERN (insn);
+  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPEC_BTI_NOP;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
+bool
+aarch_pac_insn_p (rtx x)
+{
+  if (!x || !INSN_P (x))
+    return false;
+
+  rtx pat = PATTERN (x);
+
+  if (GET_CODE (pat) == SET)
+    {
+      rtx tmp = XEXP (pat, 1);
+      if (tmp
+	  && GET_CODE (tmp) == UNSPEC
+	  && (XINT (tmp, 1) == UNSPEC_PAC_NOP
+	      || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
+	return true;
+    }
+
+  return false;
+}
+
+/* The following two functions are for code compatibility with aarch64
+   code, this even if in arm we have only one bti instruction.  */
+
+rtx
+aarch_gen_bti_c (void)
+{
+  return gen_bti_nop ();
+}
+
+rtx
+aarch_gen_bti_j (void)
+{
+  return gen_bti_nop ();
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 7255fa98f5d..6e86811ee05 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12913,6 +12913,13 @@ (define_insn "aut_nop"
   "aut\t%|ip, %|lr, %|sp"
   [(set_attr "conds" "unconditional")])
 
+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
+  "arm_arch8m_main"
+  "bti"
+  [(set_attr "conds" "unconditional")
+   (set_attr "type" "nop")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index 041cc6ec045..683342cb528 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -175,3 +175,13 @@ arm-d.o: $(srcdir)/config/arm/arm-d.cc
 arm-common.o: arm-cpu-cdata.h
 
 driver-arm.o: arm-native.h
+
+PASSES_EXTRA += $(srcdir)/config/arm/arm-passes.def
+
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.cc \
+    $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+    dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+    output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+    $(CONTEXT_H) $(TREE_PASS_H) regrename.h
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/arm/aarch-bti-insert.cc
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index dbe243a03f6..78e723a4b3c 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -162,6 +162,7 @@ (define_c_enum "unspec" [
   UNSPEC_PAC_NOP	; Represents PAC signing LR
   UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
   UNSPEC_AUT_NOP	; Represents PAC verifying LR
+  UNSPEC_BTI_NOP	; Represent BTI
 ])
 
 
diff --git a/gcc/testsuite/gcc.target/arm/bti-1.c b/gcc/testsuite/gcc.target/arm/bti-1.c
new file mode 100644
index 00000000000..79dd8010d2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-1.c
@@ -0,0 +1,12 @@
+/* Check that GCC does bti instruction.  */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
+
+int
+main (void)
+{
+  return 0;
+}
+
+/* { dg-final { scan-assembler "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/bti-2.c b/gcc/testsuite/gcc.target/arm/bti-2.c
new file mode 100644
index 00000000000..33910563849
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-2.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* -Os to create jump table.  */
+/* { dg-options "-Os" } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
+
+extern int f1 (void);
+extern int f2 (void);
+extern int f3 (void);
+extern int f4 (void);
+extern int f5 (void);
+extern int f6 (void);
+extern int f7 (void);
+extern int f8 (void);
+extern int f9 (void);
+extern int f10 (void);
+
+int (*ptr) (void);
+
+int
+f_jump_table (int y, int n)
+{
+  int i;
+  for (i = 0; i < n ;i ++)
+  {
+    switch (y)
+      {
+      case 0 : ptr = f1; break;
+      case 1 : ptr = f2; break;
+      case 2 : ptr = f3; break;
+      case 3 : ptr = f4; break;
+      case 4 : ptr = f5; break;
+      case 5 : ptr = f6; break;
+      case 6 : ptr = f7; break;
+      case 7 : ptr = f8; break;
+      case 8 : ptr = f9; break;
+      case 9 : ptr = f10; break;
+      default: break;
+      }
+    y += ptr ();
+  }
+  return (y == 0)? y+1:4;
+}
+
+int
+f_label_address ()
+{
+  static void * addr = &&lab1;
+  goto *addr;
+lab1:
+  addr = &&lab2;
+  return 1;
+lab2:
+  addr = &&lab1;
+  return 2;
+}
+
+/* { dg-final { scan-assembler-times "bti" 15 } } */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 10/15 V4] arm: Implement cortex-M return signing address codegen
  2022-10-28 16:34         ` [PATCH 10/15 V3] " Andrea Corallo
@ 2022-11-07  8:57           ` Andrea Corallo
  2022-12-05 16:38             ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-11-07  8:57 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd, Richard Earnshaw

[-- Attachment #1: Type: text/plain, Size: 150 bytes --]

Hi all,

please find attached the lastest version of this patch incorporating some
more improvents.  Feel free to ignore V3.

Best Regards

  Andrea


[-- Attachment #2: 0001-PATCH-10-15-arm-Implement-cortex-M-return-signing-ad.patch --]
[-- Type: text/plain, Size: 20180 bytes --]

From 869630801de2d3df03ce2f2551fd801dd59a640c Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 20 Jan 2022 15:36:23 +0100
Subject: [PATCH] [PATCH 10/15] arm: Implement cortex-M return signing address
 codegen

Hi all,

this patch enables address return signature and verification based on
Armv8.1-M Pointer Authentication [1].

To sign the return address, we use the PAC R12, LR, SP instruction
upon function entry.  This is signing LR using SP and storing the
result in R12.  R12 will be pushed into the stack.

During function epilogue R12 will be popped and AUT R12, LR, SP will
be used to verify that the content of LR is still valid before return.

Here an example of PAC instrumented function prologue and epilogue:

void foo (void);

int main()
{
  foo ();
  return 0;
}

Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
-mthumb' translates into:

main:
	pac	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

The patch also takes care of generating a PACBTI instruction in place
of the sequence BTI+PAC when Branch Target Identification is enabled
contextually.

Ex. the previous example compiled with '-march=armv8.1-m.main
-mbranch-protection=pac-ret+bti -mthumb' translates into:

main:
	pacbti	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

As part of previous upstream suggestions a test for varargs has been
added and '-mtpcs-frame' is deemed being incompatible with this return
signing address feature being introduced.

[1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* config/arm/arm.h (arm_arch8m_main): Declare it.
	* config/arm/arm.cc (arm_arch8m_main): Define it.
	(arm_option_reconfigure_globals): Set arm_arch8m_main.
	(arm_compute_frame_layout, arm_expand_prologue)
	(thumb2_expand_return, arm_expand_epilogue)
	(arm_conditional_register_usage): Update for pac codegen.
	(arm_current_function_pac_enabled_p): New function.
	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
	Add new patterns.
	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.

gcc/testsuite/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/pac.h : New file.
	* gcc.target/arm/pac-1.c : New test case.
	* gcc.target/arm/pac-2.c : Likewise.
	* gcc.target/arm/pac-3.c : Likewise.
	* gcc.target/arm/pac-4.c : Likewise.
	* gcc.target/arm/pac-5.c : Likewise.
	* gcc.target/arm/pac-6.c : Likewise.
	* gcc.target/arm/pac-7.c : Likewise.
	* gcc.target/arm/pac-8.c : Likewise.
---
 gcc/config/arm/arm-protos.h          |  1 +
 gcc/config/arm/arm.cc                | 80 +++++++++++++++++++++++-----
 gcc/config/arm/arm.h                 |  4 ++
 gcc/config/arm/arm.md                | 23 ++++++++
 gcc/config/arm/unspecs.md            |  3 ++
 gcc/testsuite/gcc.target/arm/pac-1.c | 12 +++++
 gcc/testsuite/gcc.target/arm/pac-2.c | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-3.c | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-4.c | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-5.c | 28 ++++++++++
 gcc/testsuite/gcc.target/arm/pac-6.c | 18 +++++++
 gcc/testsuite/gcc.target/arm/pac-7.c | 32 +++++++++++
 gcc/testsuite/gcc.target/arm/pac-8.c | 34 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac.h   | 17 ++++++
 14 files changed, 271 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-3.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-4.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-5.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-6.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-7.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-8.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac.h

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index cff7ff1da2a..84764bf27ce 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -379,6 +379,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index a5cf4225aa2..be5229ffd1d 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -927,6 +927,11 @@ int arm_arch8_3 = 0;
 
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 int arm_arch8_4 = 0;
+
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+int arm_arch8m_main = 0;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 int arm_arch8_1m_main = 0;
@@ -3209,6 +3214,9 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p () && !arm_arch8m_main)
+    error ("This architecture does not support branch protection instructions");
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -3855,6 +3863,7 @@ arm_option_reconfigure_globals (void)
   arm_arch_arm_hwdiv = bitmap_bit_p (arm_active_target.isa, isa_bit_adiv);
   arm_arch_crc = bitmap_bit_p (arm_active_target.isa, isa_bit_crc32);
   arm_arch_cmse = bitmap_bit_p (arm_active_target.isa, isa_bit_cmse);
+  arm_arch8m_main = arm_arch7 && arm_arch_cmse;
   arm_arch_lpae = bitmap_bit_p (arm_active_target.isa, isa_bit_lpae);
   arm_arch_i8mm = bitmap_bit_p (arm_active_target.isa, isa_bit_i8mm);
   arm_arch_bf16 = bitmap_bit_p (arm_active_target.isa, isa_bit_bf16);
@@ -21139,6 +21148,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23362,6 +23374,12 @@ output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Generate the prologue instructions for entry into an ARM or Thumb-2
    function.  */
 void
@@ -23440,12 +23458,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || (arm_current_function_pac_enabled_p ())));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23470,7 +23489,8 @@ arm_expand_prologue (void)
 	{
 	  rtx addr, dwarf;
 
-	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
+	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4
+                     || arm_current_function_pac_enabled_p ());
 	  saved_regs += 4;
 
 	  addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
@@ -23521,6 +23541,17 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      /* If IP was clobbered we only emit a PAC instruction as the BTI
+         one will be added before the push of the clobbered IP (if
+         necessary) by the bti pass.  */
+      if (aarch_bti_enabled () && !clobber_ip)
+	emit_insn (gen_pacbti_nop ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27309,7 +27340,7 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (num_regs == 1 && !arm_current_function_pac_enabled_p ())
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27324,10 +27355,20 @@ thumb2_expand_return (bool simple_return)
         }
       else
         {
-          saved_regs_mask &= ~ (1 << LR_REGNUM);
-          saved_regs_mask |=   (1 << PC_REGNUM);
-          arm_emit_multi_reg_pop (saved_regs_mask);
-        }
+	  if (arm_current_function_pac_enabled_p ())
+	    {
+	      gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	      emit_insn (gen_aut_nop ());
+	      emit_jump_insn (simple_return_rtx);
+	    }
+	  else
+	    {
+	      saved_regs_mask &= ~ (1 << LR_REGNUM);
+	      saved_regs_mask |=   (1 << PC_REGNUM);
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	    }
+	}
     }
   else
     {
@@ -27733,7 +27774,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27847,6 +27889,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -32941,6 +32986,15 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+          || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+              && !crtl->is_leaf));
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 3495ab857ea..e33425bbf42 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -510,6 +510,10 @@ extern int arm_arch8_3;
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 extern int arm_arch8_4;
 
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+extern int arm_arch8m_main;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 extern int arm_arch8_1m_main;
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 60468f6182c..7255fa98f5d 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12890,6 +12890,29 @@ (define_insn "*speculation_barrier_insn"
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PAC_NOP))]
+  "arm_arch8m_main"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PACBTI_NOP))]
+  "arm_arch8m_main"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+	      UNSPEC_AUT_NOP)]
+  "arm_arch8m_main"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..dbe243a03f6 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,9 @@ (define_c_enum "unspec" [
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
+  UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  UNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..6cd64dbd014
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,12 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-10-26  8:49           ` Andrea Corallo
@ 2022-11-08 14:57             ` Richard Earnshaw
  2023-01-09 14:58             ` Andrea Corallo
  1 sibling, 0 replies; 66+ messages in thread
From: Richard Earnshaw @ 2022-11-08 14:57 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: nd, Andrea Corallo via Gcc-patches, Richard Earnshaw



On 26/10/2022 09:49, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
>>>
>>>> -----Original Message-----
>>>> From: Andrea Corallo <andrea.corallo@arm.com>
>>>> Sent: Tuesday, September 27, 2022 11:06 AM
>>>> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
>>>> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
>>>> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>> popping if necessary
>>>>
>>>> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
>>>>
>>>>> Hi Andrea,
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Gcc-patches <gcc-patches-
>>>>>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>>>>>> Corallo via Gcc-patches
>>>>>> Sent: Friday, August 12, 2022 4:34 PM
>>>>>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>>>>>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>> popping
>>>>>> if necessary
>>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>>>>>> pointer as CFA reg when popping if this is necessary.
>>>>>>
>>>>>
>>>>>   From what I can tell from similar functions this is correct, but could you
>>>> elaborate on why this change is needed for my understanding please?
>>>>> Thanks,
>>>>> Kyrill
>>>>
>>>> Hi Kyrill,
>>>>
>>>> sure, if the frame pointer was set, than it is the current CFA register.
>>>> If we request to adjust the current CFA register offset indicating it
>>>> being SP (while it's actually FP) that is indeed not correct and the
>>>> incoherence we will be detected by an assertion in the dwarf emission
>>>> machinery.
>>> Thanks,  the patch is ok
>>> Kyrill
>>>
>>>>
>>>> Best Regards
>>>>
>>>>     Andrea
>>
>> Hmm, wait.  Why would a multi-reg pop be updating the stack pointer?
> 
> Hi Richard,
> 
> not sure I understand, isn't any pop updating SP by definition?

Yes, but the SP must already be the CFA before this instruction, since 
SP must be the base of the pop. So the reg note changing the CFA to SP 
can't be right.  I'm thinking there must be some earlier restore of SP 
that's missing a frame-related note.

R.

> 
> BR
> 
>    Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M
  2022-09-21  8:07 ` [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  2022-10-21 13:01   ` Richard Earnshaw
@ 2022-12-05 14:10   ` Andrea Corallo
  2022-12-05 14:19     ` Kyrylo Tkachov
  2023-01-23 10:50   ` [PATCH " Andrea Corallo
  2 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-12-05 14:10 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:

> Hi all,
>
> ping^2 for patches 9/15 7/15 11/15 12/15 and 10/15 V2 of this series.
>
>   Andrea

Hello all,

PING^3 for:
[PATCH 6/12 V2] arm: Add pointer authentication for stack-unwinding runtime
[PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
[PATCH 10/15 V4] arm: Implement cortex-M return signing address codegen
[PATCH 12/15 V3] arm: implement bti injection

which I believe are still pending for review.

Other option would be to declare the arm backend as unmaintained.

Thanks

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* RE: [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M
  2022-12-05 14:10   ` Andrea Corallo
@ 2022-12-05 14:19     ` Kyrylo Tkachov
  0 siblings, 0 replies; 66+ messages in thread
From: Kyrylo Tkachov @ 2022-12-05 14:19 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Hi Andrea,

> -----Original Message-----
> From: Gcc-patches <gcc-patches-
> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
> Corallo via Gcc-patches
> Sent: Monday, December 5, 2022 2:11 PM
> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
> Subject: Re: [PING][PATCH 0/15] arm: Enables return address verification and
> branch target identification on Cortex-M
> 
> Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> 
> > Hi all,
> >
> > ping^2 for patches 9/15 7/15 11/15 12/15 and 10/15 V2 of this series.
> >
> >   Andrea
> 
> Hello all,
> 
> PING^3 for:
> [PATCH 6/12 V2] arm: Add pointer authentication for stack-unwinding
> runtime
> [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if
> necessary
> [PATCH 10/15 V4] arm: Implement cortex-M return signing address codegen
> [PATCH 12/15 V3] arm: implement bti injection
> 
> which I believe are still pending for review.

Thanks for pinging these, it helps keep track of the patches needing attention.

> 
> Other option would be to declare the arm backend as unmaintained.

Apologies for the delays in this patch series. For patches such as PACBTI in particular it is important to be extra thorough in the review,
as this functionality has important security implications and as it will be deployed in deeply embedded M-profile systems
it would be hard to address bugs and vulnerabilities effectively after the fact. See, for example the many PAC and BTI bug reports we've had over the years for AArch64.
There are many things that can go wrong 😊

So it's important to get this right the first time.
Thank you for your patience.
Kyrill

> 
> Thanks
> 
>   Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 10/15 V4] arm: Implement cortex-M return signing address codegen
  2022-11-07  8:57           ` [PATCH 10/15 V4] " Andrea Corallo
@ 2022-12-05 16:38             ` Richard Earnshaw
  2022-12-09 14:16               ` [PATCH 10/15 V5] " Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-12-05 16:38 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 07/11/2022 08:57, Andrea Corallo via Gcc-patches wrote:
> Hi all,
> 
> please find attached the lastest version of this patch incorporating some
> more improvents.  Feel free to ignore V3.
> 
> Best Regards
> 
>    Andrea
> 

 > As part of previous upstream suggestions a test for varargs has been
 > added and '-mtpcs-frame' is deemed being incompatible with this return
 > signing address feature being introduced.

I don't see any check for the tpcs-frame incompatibility?  What happens 
if a user does combine the options?

gcc/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* config/arm/arm.h (arm_arch8m_main): Declare it.
	* config/arm/arm.cc (arm_arch8m_main): Define it.
	(arm_option_reconfigure_globals): Set arm_arch8m_main.
	(arm_compute_frame_layout, arm_expand_prologue)
	(thumb2_expand_return, arm_expand_epilogue)
	(arm_conditional_register_usage): Update for pac codegen.
	(arm_current_function_pac_enabled_p): New function.
	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
	Add new patterns.
	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.

You're missing an entry for aarch_bti_enabled () - yes I realize that's 
just a placeholder at present and will be fully defined in patch 12.

+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+

No comment on this function (and in patch 12 it moves to a different 
location).  It would be best to have it in the right place at this point 
in time.

+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && 
TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || (arm_current_function_pac_enabled_p ())));

Redundant parenthesis around arm_current_function_pac_enabled_p () call.

+	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4
+                     || arm_current_function_pac_enabled_p ());

I wonder if this assert is now really serving a useful purpose.  I'd 
consider removing it.

@@ -27309,7 +27340,7 @@ thumb2_expand_return (bool simple_return)
  	 to assert it for now to ensure that future code changes do not silently
  	 change this behavior.  */
        gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (num_regs == 1 && !arm_current_function_pac_enabled_p ())
          {
            rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
            rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27324,10 +27355,20 @@ thumb2_expand_return (bool simple_return)
          }
        else
          {
-          saved_regs_mask &= ~ (1 << LR_REGNUM);
-          saved_regs_mask |=   (1 << PC_REGNUM);
-          arm_emit_multi_reg_pop (saved_regs_mask);
-        }
+	  if (arm_current_function_pac_enabled_p ())
+	    {
+	      gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	      emit_insn (gen_aut_nop ());
+	      emit_jump_insn (simple_return_rtx);
+	    }
+	  else
+	    {
+	      saved_regs_mask &= ~ (1 << LR_REGNUM);
+	      saved_regs_mask |=   (1 << PC_REGNUM);
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	    }
+	}
      }
    else

The logic for these blocks would, I think, be better expressed as

    if (pac_enabled)
        ...
    else if (num_regs == 1)
      ...  // existing code
    else
      ...  // existing code

Also, I think (out of an abundance of caution) we really need a 
scheduling barrier placed before calls to gen_aut_nop() pattern is 
emitted, to ensure that the scheduler never tries to move this 
instruction away from the position we place it.  Use gen_blockage() for 
that (see TARGET_SCHED_PROLOG).  Alternatively, we could make the 
UNSPEC_PAC_NOP an unspec_volatile, which has the same effect (IIRC) 
without needing an additional insn - if you use this approach, then 
please make sure this is explained in a comment.

+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PACBTI_NOP))]
+  "arm_arch8m_main"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])

The additional side-effect of this being a BTI landing pad means that we 
mustn't move any other instruction before it.  So I think this needs to 
be an unspec_volatile as well.

On the tests, they are OK as they stand, but we lack anything that will 
be tested when suitable hardware is unavailable (all tests are "dg-do 
run").  Can we please have some compile-only tests as well?

R.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 12/15 V3] arm: implement bti injection
  2022-10-28 16:40         ` [PATCH 12/15 V3] " Andrea Corallo
@ 2022-12-05 17:02           ` Richard Earnshaw
  2022-12-14 16:40             ` [PATCH 12/15 V4] " Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-12-05 17:02 UTC (permalink / raw)
  To: Andrea Corallo, Kyrylo Tkachov
  Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 28/10/2022 17:40, Andrea Corallo via Gcc-patches wrote:
> Hi all,
> 
> please find attached the third iteration of this patch addresing review
> comments.
> 
> Thanks
> 
>    Andrea
> 

@@ -23374,12 +23374,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
    return "";
  }

-static bool
-aarch_bti_enabled ()
-{
-  return false;
-}
-
  /* Generate the prologue instructions for entry into an ARM or Thumb-2
     function.  */
  void
@@ -32992,6 +32986,61 @@ arm_current_function_pac_enabled_p (void)
                && !crtl->is_leaf));
  }

+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+bool
+aarch_bti_enabled (void)
+{
+  return aarch_enable_bti == 1;
+}

See comment in earlier patch about the location of this function moving. 
  Can aarch_enable_bti take values other than 0 and 1?  If not, then 
writing aarch_enable_bti != 0 is slightly more robust, but perhaps this 
should be replaced by a macro anyway, much like a number of other 
predicates used by the backend.

+  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == 
UNSPEC_BTI_NOP;

I'm not sure where this crept in, but UNSPEC and UNSPEC_VOLATILE have 
separate enums in the backend, so UNSPEC_BIT_NOP should really be 
VUNSPEC_BTI_NOP and defined in the enum "unspecv".

+aarch_pac_insn_p (rtx x)
+{
+  if (!x || !INSN_P (x))
+    return false;
+
+  rtx pat = PATTERN (x);
+
+  if (GET_CODE (pat) == SET)
+    {
+      rtx tmp = XEXP (pat, 1);
+      if (tmp
+	  && GET_CODE (tmp) == UNSPEC
+	  && (XINT (tmp, 1) == UNSPEC_PAC_NOP
+	      || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
+	return true;
+    }
+

This will also need updating (see review on earlier patch) because 
PACBTI needs to be unspec_volatile, while PAC doesn't.

+/* The following two functions are for code compatibility with aarch64
+   code, this even if in arm we have only one bti instruction.  */
+

I'd just write
  /* Target specific mapping for aarch_gen_bti_c and aarch_gen_bti_j. 
For Arm, both of these map to a simple BTI instruction.  */


@@ -162,6 +162,7 @@ (define_c_enum "unspec" [
    UNSPEC_PAC_NOP	; Represents PAC signing LR
    UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
    UNSPEC_AUT_NOP	; Represents PAC verifying LR
+  UNSPEC_BTI_NOP	; Represent BTI
  ])

BTI is an unspec volatile, so this should be in the "vunspec" enum and 
renamed accordingly (see above).

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 10/15 V5] arm: Implement cortex-M return signing address codegen
  2022-12-05 16:38             ` Richard Earnshaw
@ 2022-12-09 14:16               ` Andrea Corallo
  2022-12-12 10:53                 ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-12-09 14:16 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 5187 bytes --]

Hi Richard,

thanks for reviewing.

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

> On 07/11/2022 08:57, Andrea Corallo via Gcc-patches wrote:
>> Hi all,
>> please find attached the lastest version of this patch incorporating
>> some
>> more improvents.  Feel free to ignore V3.
>> Best Regards
>>    Andrea
>> 
>
>> As part of previous upstream suggestions a test for varargs has been
>> added and '-mtpcs-frame' is deemed being incompatible with this return
>> signing address feature being introduced.
>
> I don't see any check for the tpcs-frame incompatibility?  What
> happens if a user does combine the options?

Check added.

> gcc/Changelog
>
> 2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>
>
> 	* config/arm/arm.h (arm_arch8m_main): Declare it.
> 	* config/arm/arm.cc (arm_arch8m_main): Define it.
> 	(arm_option_reconfigure_globals): Set arm_arch8m_main.
> 	(arm_compute_frame_layout, arm_expand_prologue)
> 	(thumb2_expand_return, arm_expand_epilogue)
> 	(arm_conditional_register_usage): Update for pac codegen.
> 	(arm_current_function_pac_enabled_p): New function.
> 	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
> 	Add new patterns.
> 	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
> 	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.
>
> You're missing an entry for aarch_bti_enabled () - yes I realize
> that's just a placeholder at present and will be fully defined in
> patch 12.

Fixed

> +static bool
> +aarch_bti_enabled ()
> +{
> +  return false;
> +}
> +
>
> No comment on this function (and in patch 12 it moves to a different
> location).  It would be best to have it in the right place at this
> point in time.
>
> +  clobber_ip = (IS_NESTED (func_type)
> +                && (((TARGET_APCS_FRAME && frame_pointer_needed &&
> TARGET_ARM)
> +                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
> +                          || flag_stack_clash_protection)
> +                         && !df_regs_ever_live_p (LR_REGNUM)
> +                         && arm_r3_live_at_start_p ()))
> +                    || (arm_current_function_pac_enabled_p ())));
>
> Redundant parenthesis around arm_current_function_pac_enabled_p () call.

Fixed

> +	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4
> +                     || arm_current_function_pac_enabled_p ());
>
> I wonder if this assert is now really serving a useful purpose.  I'd
> consider removing it.

Removed

> @@ -27309,7 +27340,7 @@ thumb2_expand_return (bool simple_return)
>  	 to assert it for now to ensure that future code changes do not silently
>  	 change this behavior.  */
>        gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
> -      if (num_regs == 1)
> +      if (num_regs == 1 && !arm_current_function_pac_enabled_p ())
>          {
>            rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
>            rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
> @@ -27324,10 +27355,20 @@ thumb2_expand_return (bool simple_return)
>          }
>        else
>          {
> -          saved_regs_mask &= ~ (1 << LR_REGNUM);
> -          saved_regs_mask |=   (1 << PC_REGNUM);
> -          arm_emit_multi_reg_pop (saved_regs_mask);
> -        }
> +	  if (arm_current_function_pac_enabled_p ())
> +	    {
> +	      gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
> +	      arm_emit_multi_reg_pop (saved_regs_mask);
> +	      emit_insn (gen_aut_nop ());
> +	      emit_jump_insn (simple_return_rtx);
> +	    }
> +	  else
> +	    {
> +	      saved_regs_mask &= ~ (1 << LR_REGNUM);
> +	      saved_regs_mask |=   (1 << PC_REGNUM);
> +	      arm_emit_multi_reg_pop (saved_regs_mask);
> +	    }
> +	}
>      }
>    else
>
> The logic for these blocks would, I think, be better expressed as
>
>    if (pac_enabled)
>        ...
>    else if (num_regs == 1)
>      ...  // existing code
>    else
>      ...  // existing code

Done

> Also, I think (out of an abundance of caution) we really need a
> scheduling barrier placed before calls to gen_aut_nop() pattern is
> emitted, to ensure that the scheduler never tries to move this
> instruction away from the position we place it.  Use gen_blockage()
> for that (see TARGET_SCHED_PROLOG).  Alternatively, we could make the
> UNSPEC_PAC_NOP an unspec_volatile, which has the same effect (IIRC)
> without needing an additional insn - if you use this approach, then
> please make sure this is explained in a comment.
>
> +(define_insn "pacbti_nop"
> +  [(set (reg:SI IP_REGNUM)
> +	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
> +		   UNSPEC_PACBTI_NOP))]
> +  "arm_arch8m_main"
> +  "pacbti\t%|ip, %|lr, %|sp"
> +  [(set_attr "conds" "unconditional")])
>
> The additional side-effect of this being a BTI landing pad means that
> we mustn't move any other instruction before it.  So I think this
> needs to be an unspec_volatile as well.

Done

> On the tests, they are OK as they stand, but we lack anything that
> will be tested when suitable hardware is unavailable (all tests are
> "dg-do run").  Can we please have some compile-only tests as well?

Added three compile only tests.

Please find attached the latest version of the patch.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-10-15-arm-Implement-cortex-M-return-signing-ad.patch --]
[-- Type: text/plain, Size: 22306 bytes --]

From 56b7b3336142c0499826e43139a21483296467ef Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 20 Jan 2022 15:36:23 +0100
Subject: [PATCH] [PATCH 10/15] arm: Implement cortex-M return signing address
 codegen

Hi all,

this patch enables address return signature and verification based on
Armv8.1-M Pointer Authentication [1].

To sign the return address, we use the PAC R12, LR, SP instruction
upon function entry.  This is signing LR using SP and storing the
result in R12.  R12 will be pushed into the stack.

During function epilogue R12 will be popped and AUT R12, LR, SP will
be used to verify that the content of LR is still valid before return.

Here an example of PAC instrumented function prologue and epilogue:

void foo (void);

int main()
{
  foo ();
  return 0;
}

Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
-mthumb' translates into:

main:
	pac	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

The patch also takes care of generating a PACBTI instruction in place
of the sequence BTI+PAC when Branch Target Identification is enabled
contextually.

Ex. the previous example compiled with '-march=armv8.1-m.main
-mbranch-protection=pac-ret+bti -mthumb' translates into:

main:
	pacbti	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

As part of previous upstream suggestions a test for varargs has been
added and '-mtpcs-frame' is deemed being incompatible with this return
signing address feature being introduced.

[1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* config/arm/arm.h (arm_arch8m_main): Declare it.
	* config/arm/arm.cc (arm_arch8m_main): Define it.
	(arm_option_reconfigure_globals): Set arm_arch8m_main.
	(arm_compute_frame_layout, arm_expand_prologue)
	(thumb2_expand_return, arm_expand_epilogue)
	(arm_conditional_register_usage): Update for pac codegen.
	(arm_current_function_pac_enabled_p): New function.
	(aarch_bti_enabled) New function.
	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
	Add new patterns.
	* config/arm/unspecs.md (UNSPEC_PAC_NOP)
	(VUNSPEC_PACBTI_NOP, VUNSPEC_AUT_NOP): Add unspecs.

gcc/testsuite/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/pac.h : New file.
	* gcc.target/arm/pac-1.c : New test case.
	* gcc.target/arm/pac-2.c : Likewise.
	* gcc.target/arm/pac-3.c : Likewise.
	* gcc.target/arm/pac-4.c : Likewise.
	* gcc.target/arm/pac-5.c : Likewise.
	* gcc.target/arm/pac-6.c : Likewise.
	* gcc.target/arm/pac-7.c : Likewise.
	* gcc.target/arm/pac-8.c : Likewise.
	* gcc.target/arm/pac-9.c : Likewise.
	* gcc.target/arm/pac-10.c : Likewise.
	* gcc.target/arm/pac-11.c : Likewise.
---
 gcc/config/arm/arm-protos.h           |  1 +
 gcc/config/arm/arm.cc                 | 74 +++++++++++++++++++++++----
 gcc/config/arm/arm.h                  |  4 ++
 gcc/config/arm/arm.md                 | 23 +++++++++
 gcc/config/arm/unspecs.md             |  3 ++
 gcc/testsuite/gcc.target/arm/pac-1.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-10.c | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-11.c | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-2.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-3.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-4.c  | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-5.c  | 28 ++++++++++
 gcc/testsuite/gcc.target/arm/pac-6.c  | 18 +++++++
 gcc/testsuite/gcc.target/arm/pac-7.c  | 32 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac-8.c  | 34 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac-9.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac.h    | 17 ++++++
 17 files changed, 299 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-10.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-11.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-3.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-4.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-5.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-6.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-7.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-8.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-9.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac.h

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 6e6bf147e9c..d97a1c3bf56 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -378,6 +378,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 4ac42e58b90..705364ad13f 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -923,6 +923,11 @@ int arm_arch8_3 = 0;
 
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 int arm_arch8_4 = 0;
+
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+int arm_arch8m_main = 0;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 int arm_arch8_1m_main = 0;
@@ -3205,6 +3210,15 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (!arm_arch8m_main)
+        error ("This architecture does not support branch protection "
+               "instructions");
+      if (TARGET_TPCS_FRAME)
+        error ("Return address signing and %<-mtpcs-frame%> are incompatible.");
+    }
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -3851,6 +3865,7 @@ arm_option_reconfigure_globals (void)
   arm_arch_arm_hwdiv = bitmap_bit_p (arm_active_target.isa, isa_bit_adiv);
   arm_arch_crc = bitmap_bit_p (arm_active_target.isa, isa_bit_crc32);
   arm_arch_cmse = bitmap_bit_p (arm_active_target.isa, isa_bit_cmse);
+  arm_arch8m_main = arm_arch7 && arm_arch_cmse;
   arm_arch_lpae = bitmap_bit_p (arm_active_target.isa, isa_bit_lpae);
   arm_arch_i8mm = bitmap_bit_p (arm_active_target.isa, isa_bit_i8mm);
   arm_arch_bf16 = bitmap_bit_p (arm_active_target.isa, isa_bit_bf16);
@@ -21227,6 +21242,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23528,12 +23546,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || arm_current_function_pac_enabled_p ()));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23558,7 +23577,6 @@ arm_expand_prologue (void)
 	{
 	  rtx addr, dwarf;
 
-	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
 	  saved_regs += 4;
 
 	  addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
@@ -23609,6 +23627,17 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      /* If IP was clobbered we only emit a PAC instruction as the BTI
+         one will be added before the push of the clobbered IP (if
+         necessary) by the bti pass.  */
+      if (aarch_bti_enabled () && !clobber_ip)
+	emit_insn (gen_pacbti_nop ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27420,7 +27449,14 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (arm_current_function_pac_enabled_p ())
+        {
+          gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+          arm_emit_multi_reg_pop (saved_regs_mask);
+          emit_insn (gen_aut_nop ());
+          emit_jump_insn (simple_return_rtx);
+        }
+      else if (num_regs == 1)
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27844,7 +27880,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27958,6 +27995,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -33059,6 +33099,22 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+          || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+              && !crtl->is_leaf));
+}
+
+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index ff8452ea04a..5f7c40805d3 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -506,6 +506,10 @@ extern int arm_arch8_3;
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 extern int arm_arch8_4;
 
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+extern int arm_arch8m_main;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 extern int arm_arch8_1m_main;
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 69bf343fb0e..4c1bbcae850 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12978,6 +12978,29 @@ (define_insn "*speculation_barrier_insn"
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PAC_NOP))]
+  "arm_arch8m_main"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   VUNSPEC_PACBTI_NOP))]
+  "arm_arch8m_main"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+	      VUNSPEC_AUT_NOP)]
+  "arm_arch8m_main"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..370f0b12da1 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,7 @@ (define_c_enum "unspec" [
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
 ])
 
 
@@ -254,6 +255,8 @@ (define_c_enum "unspecv" [
 			; instruction.
   VUNSPEC_VLLDM		; Represent the lazy load multiple with vlldm
 			; instruction.
+  VUNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  VUNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..9b26f62b65f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-10.c b/gcc/testsuite/gcc.target/arm/pac-10.c
new file mode 100644
index 00000000000..a794195e8f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-10.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-11.c b/gcc/testsuite/gcc.target/arm/pac-11.c
new file mode 100644
index 00000000000..37ffc93b41b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-11.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-9.c b/gcc/testsuite/gcc.target/arm/pac-9.c
new file mode 100644
index 00000000000..ee2fad290b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-9.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 10/15 V5] arm: Implement cortex-M return signing address codegen
  2022-12-09 14:16               ` [PATCH 10/15 V5] " Andrea Corallo
@ 2022-12-12 10:53                 ` Richard Earnshaw
  2022-12-14 16:35                   ` [PATCH 10/15 V6] " Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-12-12 10:53 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd



On 09/12/2022 14:16, Andrea Corallo via Gcc-patches wrote:
> Hi Richard,
> 
> thanks for reviewing.
> 
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 07/11/2022 08:57, Andrea Corallo via Gcc-patches wrote:
>>> Hi all,
>>> please find attached the lastest version of this patch incorporating
>>> some
>>> more improvents.  Feel free to ignore V3.
>>> Best Regards
>>>     Andrea
>>>
>>
>>> As part of previous upstream suggestions a test for varargs has been
>>> added and '-mtpcs-frame' is deemed being incompatible with this return
>>> signing address feature being introduced.
>>
>> I don't see any check for the tpcs-frame incompatibility?  What
>> happens if a user does combine the options?
> 
> Check added.
> 
>> gcc/Changelog
>>
>> 2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>
>>
>> 	* config/arm/arm.h (arm_arch8m_main): Declare it.
>> 	* config/arm/arm.cc (arm_arch8m_main): Define it.
>> 	(arm_option_reconfigure_globals): Set arm_arch8m_main.
>> 	(arm_compute_frame_layout, arm_expand_prologue)
>> 	(thumb2_expand_return, arm_expand_epilogue)
>> 	(arm_conditional_register_usage): Update for pac codegen.
>> 	(arm_current_function_pac_enabled_p): New function.
>> 	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
>> 	Add new patterns.
>> 	* config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
>> 	(UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.
>>
>> You're missing an entry for aarch_bti_enabled () - yes I realize
>> that's just a placeholder at present and will be fully defined in
>> patch 12.
> 
> Fixed
> 
>> +static bool
>> +aarch_bti_enabled ()
>> +{
>> +  return false;
>> +}
>> +
>>
>> No comment on this function (and in patch 12 it moves to a different
>> location).  It would be best to have it in the right place at this
>> point in time.
>>
>> +  clobber_ip = (IS_NESTED (func_type)
>> +                && (((TARGET_APCS_FRAME && frame_pointer_needed &&
>> TARGET_ARM)
>> +                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
>> +                          || flag_stack_clash_protection)
>> +                         && !df_regs_ever_live_p (LR_REGNUM)
>> +                         && arm_r3_live_at_start_p ()))
>> +                    || (arm_current_function_pac_enabled_p ())));
>>
>> Redundant parenthesis around arm_current_function_pac_enabled_p () call.
> 
> Fixed
> 
>> +	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4
>> +                     || arm_current_function_pac_enabled_p ());
>>
>> I wonder if this assert is now really serving a useful purpose.  I'd
>> consider removing it.
> 
> Removed
> 
>> @@ -27309,7 +27340,7 @@ thumb2_expand_return (bool simple_return)
>>   	 to assert it for now to ensure that future code changes do not silently
>>   	 change this behavior.  */
>>         gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
>> -      if (num_regs == 1)
>> +      if (num_regs == 1 && !arm_current_function_pac_enabled_p ())
>>           {
>>             rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
>>             rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
>> @@ -27324,10 +27355,20 @@ thumb2_expand_return (bool simple_return)
>>           }
>>         else
>>           {
>> -          saved_regs_mask &= ~ (1 << LR_REGNUM);
>> -          saved_regs_mask |=   (1 << PC_REGNUM);
>> -          arm_emit_multi_reg_pop (saved_regs_mask);
>> -        }
>> +	  if (arm_current_function_pac_enabled_p ())
>> +	    {
>> +	      gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
>> +	      arm_emit_multi_reg_pop (saved_regs_mask);
>> +	      emit_insn (gen_aut_nop ());
>> +	      emit_jump_insn (simple_return_rtx);
>> +	    }
>> +	  else
>> +	    {
>> +	      saved_regs_mask &= ~ (1 << LR_REGNUM);
>> +	      saved_regs_mask |=   (1 << PC_REGNUM);
>> +	      arm_emit_multi_reg_pop (saved_regs_mask);
>> +	    }
>> +	}
>>       }
>>     else
>>
>> The logic for these blocks would, I think, be better expressed as
>>
>>     if (pac_enabled)
>>         ...
>>     else if (num_regs == 1)
>>       ...  // existing code
>>     else
>>       ...  // existing code
> 
> Done
> 
>> Also, I think (out of an abundance of caution) we really need a
>> scheduling barrier placed before calls to gen_aut_nop() pattern is
>> emitted, to ensure that the scheduler never tries to move this
>> instruction away from the position we place it.  Use gen_blockage()
>> for that (see TARGET_SCHED_PROLOG).  Alternatively, we could make the
>> UNSPEC_PAC_NOP an unspec_volatile, which has the same effect (IIRC)
>> without needing an additional insn - if you use this approach, then
>> please make sure this is explained in a comment.
>>
>> +(define_insn "pacbti_nop"
>> +  [(set (reg:SI IP_REGNUM)
>> +	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
>> +		   UNSPEC_PACBTI_NOP))]
>> +  "arm_arch8m_main"
>> +  "pacbti\t%|ip, %|lr, %|sp"
>> +  [(set_attr "conds" "unconditional")])
>>
>> The additional side-effect of this being a BTI landing pad means that
>> we mustn't move any other instruction before it.  So I think this
>> needs to be an unspec_volatile as well.
> 
> Done
> 
>> On the tests, they are OK as they stand, but we lack anything that
>> will be tested when suitable hardware is unavailable (all tests are
>> "dg-do run").  Can we please have some compile-only tests as well?
> 
> Added three compile only tests.
> 
> Please find attached the latest version of the patch.
> 
> BR
> 
>    Andrea
> 

+      if (TARGET_TPCS_FRAME)
+        error ("Return address signing and %<-mtpcs-frame%> are 
incompatible.");

So really this is 'not implemented' rather than not compatible - I don't 
see why we couldn't implement this if we really wanted to.  It's not 
worth implementing it because tpcs-frames are very much legacy these days.

So the message should use sorry() and say 'is not supported' rather than 
'are incompatible'.

+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   VUNSPEC_PACBTI_NOP))]

No, this needs to be unspec_volatile, not unspec.

+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+	      VUNSPEC_AUT_NOP)]

Similarly.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 10/15 V6] arm: Implement cortex-M return signing address codegen
  2022-12-12 10:53                 ` Richard Earnshaw
@ 2022-12-14 16:35                   ` Andrea Corallo
  2022-12-14 16:45                     ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-12-14 16:35 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 966 bytes --]

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

[...]

>
> +      if (TARGET_TPCS_FRAME)
> +        error ("Return address signing and %<-mtpcs-frame%> are
> incompatible.");
>
> So really this is 'not implemented' rather than not compatible - I
> don't see why we couldn't implement this if we really wanted to.  It's
> not worth implementing it because tpcs-frames are very much legacy
> these days.
>
> So the message should use sorry() and say 'is not supported' rather
> than 'are incompatible'.
>
> +(define_insn "pacbti_nop"
> +  [(set (reg:SI IP_REGNUM)
> +	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
> +		   VUNSPEC_PACBTI_NOP))]
>
> No, this needs to be unspec_volatile, not unspec.
>
> +(define_insn "aut_nop"
> +  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
> +	      VUNSPEC_AUT_NOP)]
>
> Similarly.
>
> R.


Hi Richard & all,

please find attached the updated patch implementing suggestions.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-10-15-arm-Implement-cortex-M-return-signing-ad.patch --]
[-- Type: text/plain, Size: 22325 bytes --]

From adabef75c4af91865b0639243d6d9aa03bf8ad68 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 20 Jan 2022 15:36:23 +0100
Subject: [PATCH] [PATCH 10/15] arm: Implement cortex-M return signing address
 codegen

Hi all,

this patch enables address return signature and verification based on
Armv8.1-M Pointer Authentication [1].

To sign the return address, we use the PAC R12, LR, SP instruction
upon function entry.  This is signing LR using SP and storing the
result in R12.  R12 will be pushed into the stack.

During function epilogue R12 will be popped and AUT R12, LR, SP will
be used to verify that the content of LR is still valid before return.

Here an example of PAC instrumented function prologue and epilogue:

void foo (void);

int main()
{
  foo ();
  return 0;
}

Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
-mthumb' translates into:

main:
	pac	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

The patch also takes care of generating a PACBTI instruction in place
of the sequence BTI+PAC when Branch Target Identification is enabled
contextually.

Ex. the previous example compiled with '-march=armv8.1-m.main
-mbranch-protection=pac-ret+bti -mthumb' translates into:

main:
	pacbti	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

As part of previous upstream suggestions a test for varargs has been
added and '-mtpcs-frame' is deemed being incompatible with this return
signing address feature being introduced.

[1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* config/arm/arm.h (arm_arch8m_main): Declare it.
	* config/arm/arm.cc (arm_arch8m_main): Define it.
	(arm_option_reconfigure_globals): Set arm_arch8m_main.
	(arm_compute_frame_layout, arm_expand_prologue)
	(thumb2_expand_return, arm_expand_epilogue)
	(arm_conditional_register_usage): Update for pac codegen.
	(arm_current_function_pac_enabled_p): New function.
	(aarch_bti_enabled) New function.
	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
	Add new patterns.
	* config/arm/unspecs.md (UNSPEC_PAC_NOP)
	(VUNSPEC_PACBTI_NOP, VUNSPEC_AUT_NOP): Add unspecs.

gcc/testsuite/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/pac.h : New file.
	* gcc.target/arm/pac-1.c : New test case.
	* gcc.target/arm/pac-2.c : Likewise.
	* gcc.target/arm/pac-3.c : Likewise.
	* gcc.target/arm/pac-4.c : Likewise.
	* gcc.target/arm/pac-5.c : Likewise.
	* gcc.target/arm/pac-6.c : Likewise.
	* gcc.target/arm/pac-7.c : Likewise.
	* gcc.target/arm/pac-8.c : Likewise.
	* gcc.target/arm/pac-9.c : Likewise.
	* gcc.target/arm/pac-10.c : Likewise.
	* gcc.target/arm/pac-11.c : Likewise.
---
 gcc/config/arm/arm-protos.h           |  1 +
 gcc/config/arm/arm.cc                 | 74 +++++++++++++++++++++++----
 gcc/config/arm/arm.h                  |  4 ++
 gcc/config/arm/arm.md                 | 23 +++++++++
 gcc/config/arm/unspecs.md             |  3 ++
 gcc/testsuite/gcc.target/arm/pac-1.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-10.c | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-11.c | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-2.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-3.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-4.c  | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-5.c  | 28 ++++++++++
 gcc/testsuite/gcc.target/arm/pac-6.c  | 18 +++++++
 gcc/testsuite/gcc.target/arm/pac-7.c  | 32 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac-8.c  | 34 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac-9.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac.h    | 17 ++++++
 17 files changed, 299 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-10.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-11.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-3.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-4.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-5.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-6.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-7.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-8.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-9.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac.h

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 6e6bf147e9c..d97a1c3bf56 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -378,6 +378,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 4ac42e58b90..4af809373e4 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -923,6 +923,11 @@ int arm_arch8_3 = 0;
 
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 int arm_arch8_4 = 0;
+
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+int arm_arch8m_main = 0;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 int arm_arch8_1m_main = 0;
@@ -3205,6 +3210,15 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (!arm_arch8m_main)
+        error ("This architecture does not support branch protection "
+               "instructions");
+      if (TARGET_TPCS_FRAME)
+        sorry ("Return address signing is not supported with %<-mtpcs-frame%>.");
+    }
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -3851,6 +3865,7 @@ arm_option_reconfigure_globals (void)
   arm_arch_arm_hwdiv = bitmap_bit_p (arm_active_target.isa, isa_bit_adiv);
   arm_arch_crc = bitmap_bit_p (arm_active_target.isa, isa_bit_crc32);
   arm_arch_cmse = bitmap_bit_p (arm_active_target.isa, isa_bit_cmse);
+  arm_arch8m_main = arm_arch7 && arm_arch_cmse;
   arm_arch_lpae = bitmap_bit_p (arm_active_target.isa, isa_bit_lpae);
   arm_arch_i8mm = bitmap_bit_p (arm_active_target.isa, isa_bit_i8mm);
   arm_arch_bf16 = bitmap_bit_p (arm_active_target.isa, isa_bit_bf16);
@@ -21227,6 +21242,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23528,12 +23546,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || arm_current_function_pac_enabled_p ()));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23558,7 +23577,6 @@ arm_expand_prologue (void)
 	{
 	  rtx addr, dwarf;
 
-	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
 	  saved_regs += 4;
 
 	  addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
@@ -23609,6 +23627,17 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      /* If IP was clobbered we only emit a PAC instruction as the BTI
+         one will be added before the push of the clobbered IP (if
+         necessary) by the bti pass.  */
+      if (aarch_bti_enabled () && !clobber_ip)
+	emit_insn (gen_pacbti_nop ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27420,7 +27449,14 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (arm_current_function_pac_enabled_p ())
+        {
+          gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+          arm_emit_multi_reg_pop (saved_regs_mask);
+          emit_insn (gen_aut_nop ());
+          emit_jump_insn (simple_return_rtx);
+        }
+      else if (num_regs == 1)
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27844,7 +27880,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27958,6 +27995,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -33059,6 +33099,22 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+          || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+              && !crtl->is_leaf));
+}
+
+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index ff8452ea04a..5f7c40805d3 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -506,6 +506,10 @@ extern int arm_arch8_3;
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 extern int arm_arch8_4;
 
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+extern int arm_arch8m_main;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 extern int arm_arch8_1m_main;
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 69bf343fb0e..c7a20e94139 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12978,6 +12978,29 @@ (define_insn "*speculation_barrier_insn"
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PAC_NOP))]
+  "arm_arch8m_main"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec_volatile:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   VUNSPEC_PACBTI_NOP))]
+  "arm_arch8m_main"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "aut_nop"
+  [(unspec_volatile:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+	      VUNSPEC_AUT_NOP)]
+  "arm_arch8m_main"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..370f0b12da1 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,7 @@ (define_c_enum "unspec" [
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
 ])
 
 
@@ -254,6 +255,8 @@ (define_c_enum "unspecv" [
 			; instruction.
   VUNSPEC_VLLDM		; Represent the lazy load multiple with vlldm
 			; instruction.
+  VUNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  VUNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..9b26f62b65f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-10.c b/gcc/testsuite/gcc.target/arm/pac-10.c
new file mode 100644
index 00000000000..a794195e8f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-10.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-11.c b/gcc/testsuite/gcc.target/arm/pac-11.c
new file mode 100644
index 00000000000..37ffc93b41b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-11.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-9.c b/gcc/testsuite/gcc.target/arm/pac-9.c
new file mode 100644
index 00000000000..ee2fad290b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-9.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 12/15 V4] arm: implement bti injection
  2022-12-05 17:02           ` Richard Earnshaw
@ 2022-12-14 16:40             ` Andrea Corallo
  2022-12-14 17:00               ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-12-14 16:40 UTC (permalink / raw)
  To: Richard Earnshaw
  Cc: Kyrylo Tkachov, Richard Earnshaw, nd, Andrea Corallo via Gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2535 bytes --]

Hi Richard,

thanks for reviewing.

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

> On 28/10/2022 17:40, Andrea Corallo via Gcc-patches wrote:
>> Hi all,
>> please find attached the third iteration of this patch addresing
>> review
>> comments.
>> Thanks
>>    Andrea
>> 
>
> @@ -23374,12 +23374,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
>    return "";
>  }
>
> -static bool
> -aarch_bti_enabled ()
> -{
> -  return false;
> -}
> -
>  /* Generate the prologue instructions for entry into an ARM or Thumb-2
>     function.  */
>  void
> @@ -32992,6 +32986,61 @@ arm_current_function_pac_enabled_p (void)
>                && !crtl->is_leaf));
>  }
>
> +/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
> +bool
> +aarch_bti_enabled (void)
> +{
> +  return aarch_enable_bti == 1;
> +}
>
> See comment in earlier patch about the location of this function
> moving.   Can aarch_enable_bti take values other than 0 and 1?

Yes default is 2.

[...]

> +  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) ==
> UNSPEC_BTI_NOP;
>
> I'm not sure where this crept in, but UNSPEC and UNSPEC_VOLATILE have
> separate enums in the backend, so UNSPEC_BIT_NOP should really be
> VUNSPEC_BTI_NOP and defined in the enum "unspecv".

Done

> +aarch_pac_insn_p (rtx x)
> +{
> +  if (!x || !INSN_P (x))
> +    return false;
> +
> +  rtx pat = PATTERN (x);
> +
> +  if (GET_CODE (pat) == SET)
> +    {
> +      rtx tmp = XEXP (pat, 1);
> +      if (tmp
> +	  && GET_CODE (tmp) == UNSPEC
> +	  && (XINT (tmp, 1) == UNSPEC_PAC_NOP
> +	      || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
> +	return true;
> +    }
> +
>
> This will also need updating (see review on earlier patch) because
> PACBTI needs to be unspec_volatile, while PAC doesn't.

Done

> +/* The following two functions are for code compatibility with aarch64
> +   code, this even if in arm we have only one bti instruction.  */
> +
>
> I'd just write
>  /* Target specific mapping for aarch_gen_bti_c and
>  aarch_gen_bti_j. For Arm, both of these map to a simple BTI
> instruction.  */

Done

>
> @@ -162,6 +162,7 @@ (define_c_enum "unspec" [
>    UNSPEC_PAC_NOP	; Represents PAC signing LR
>    UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
>    UNSPEC_AUT_NOP	; Represents PAC verifying LR
> +  UNSPEC_BTI_NOP	; Represent BTI
>  ])
>
> BTI is an unspec volatile, so this should be in the "vunspec" enum and
> renamed accordingly (see above).

Done.

Please find attached the updated version of this patch.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-12-15-arm-implement-bti-injection.patch --]
[-- Type: text/plain, Size: 9700 bytes --]

From 5823333b5e4e4fe089f6865cc3e0360afd1ff168 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 7 Apr 2022 11:51:56 +0200
Subject: [PATCH] [PATCH 12/15] arm: implement bti injection

Hi all,

this patch enables Branch Target Identification Armv8.1-M Mechanism
[1].

This is achieved by using the bti pass made common with Aarch64.

The pass iterates through the instructions and adds the necessary BTI
instructions at the beginning of every function and at every landing
pads targeted by indirect jumps.

Best Regards

  Andrea

[1]
<https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* config.gcc (arm*-*-*): Add 'aarch-bti-insert.o' object.
	* config/arm/arm-protos.h: Update.
	* config/arm/arm.cc (aarch_bti_enabled) Update.
	(aarch_bti_j_insn_p, aarch_pac_insn_p, aarch_gen_bti_c)
	(aarch_gen_bti_j): New functions.
	* config/arm/arm.md (bti_nop): New insn.
	* config/arm/t-arm (PASSES_EXTRA): Add 'arm-passes.def'.
	(aarch-bti-insert.o): New target.
	* config/arm/unspecs.md (VUNSPEC_BTI_NOP): New unspec.
	* config/arm/aarch-bti-insert.cc (rest_of_insert_bti): Verify arch
	compatibility.
	* config/arm/arm-passes.def: New file.

gcc/testsuite/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/bti-1.c: New testcase.
	* gcc.target/arm/bti-2.c: Likewise.
---
 gcc/config.gcc                       |  2 +-
 gcc/config/arm/arm-passes.def        | 21 ++++++++++
 gcc/config/arm/arm-protos.h          |  2 +
 gcc/config/arm/arm.cc                | 53 ++++++++++++++++++++++++-
 gcc/config/arm/arm.md                |  7 ++++
 gcc/config/arm/t-arm                 | 10 +++++
 gcc/config/arm/unspecs.md            |  1 +
 gcc/testsuite/gcc.target/arm/bti-1.c | 12 ++++++
 gcc/testsuite/gcc.target/arm/bti-2.c | 58 ++++++++++++++++++++++++++++
 9 files changed, 163 insertions(+), 3 deletions(-)
 create mode 100644 gcc/config/arm/arm-passes.def
 create mode 100644 gcc/testsuite/gcc.target/arm/bti-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/bti-2.c

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 86abcd26185..f578b88dd49 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -351,7 +351,7 @@ arc*-*-*)
 	;;
 arm*-*-*)
 	cpu_type=arm
-	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
+	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o aarch-bti-insert.o"
 	extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
 	target_type_format_char='%'
 	c_target_objs="arm-c.o"
diff --git a/gcc/config/arm/arm-passes.def b/gcc/config/arm/arm-passes.def
new file mode 100644
index 00000000000..71d6b563640
--- /dev/null
+++ b/gcc/config/arm/arm-passes.def
@@ -0,0 +1,21 @@
+/* Arm-specific passes declarations.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   Contributed by Arm Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index d97a1c3bf56..61c2bb7b526 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -24,6 +24,8 @@
 
 #include "sbitmap.h"
 
+rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
+
 extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *);
 extern int use_return_insn (int, rtx);
 extern bool use_simple_return_p (void);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 4af809373e4..e6ee9f433aa 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -33109,12 +33109,61 @@ arm_current_function_pac_enabled_p (void)
 }
 
 /* Return TRUE if Branch Target Identification Mechanism is enabled.  */
-static bool
-aarch_bti_enabled ()
+bool
+aarch_bti_enabled (void)
+{
+  return aarch_enable_bti == 1;
+}
+
+/* Check if INSN is a BTI J insn.  */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
 {
+  if (!insn || !INSN_P (insn))
+    return false;
+
+  rtx pat = PATTERN (insn);
+  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == VUNSPEC_BTI_NOP;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
+bool
+aarch_pac_insn_p (rtx x)
+{
+  if (!x || !INSN_P (x))
+    return false;
+
+  rtx pat = PATTERN (x);
+
+  if (GET_CODE (pat) == SET)
+    {
+      rtx tmp = XEXP (pat, 1);
+      if (tmp
+	  && ((GET_CODE (tmp) == UNSPEC
+               && XINT (tmp, 1) == UNSPEC_PAC_NOP)
+              || (GET_CODE (tmp) == UNSPEC_VOLATILE
+                  && XINT (tmp, 1) == VUNSPEC_PACBTI_NOP)))
+	return true;
+    }
+
   return false;
 }
 
+ /* Target specific mapping for aarch_gen_bti_c and aarch_gen_bti_j.
+    For Arm, both of these map to a simple BTI instruction.  */
+
+rtx
+aarch_gen_bti_c (void)
+{
+  return gen_bti_nop ();
+}
+
+rtx
+aarch_gen_bti_j (void)
+{
+  return gen_bti_nop ();
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index c7a20e94139..35c6be22eb1 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -13001,6 +13001,13 @@ (define_insn "aut_nop"
   "aut\t%|ip, %|lr, %|sp"
   [(set_attr "conds" "unconditional")])
 
+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] VUNSPEC_BTI_NOP)]
+  "arm_arch8m_main"
+  "bti"
+  [(set_attr "conds" "unconditional")
+   (set_attr "type" "nop")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index 041cc6ec045..683342cb528 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -175,3 +175,13 @@ arm-d.o: $(srcdir)/config/arm/arm-d.cc
 arm-common.o: arm-cpu-cdata.h
 
 driver-arm.o: arm-native.h
+
+PASSES_EXTRA += $(srcdir)/config/arm/arm-passes.def
+
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.cc \
+    $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+    dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+    output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+    $(CONTEXT_H) $(TREE_PASS_H) regrename.h
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/arm/aarch-bti-insert.cc
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 370f0b12da1..93447a8ce9d 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -257,6 +257,7 @@ (define_c_enum "unspecv" [
 			; instruction.
   VUNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
   VUNSPEC_AUT_NOP	; Represents PAC verifying LR
+  VUNSPEC_BTI_NOP	; Represent BTI
 ])
 
 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/bti-1.c b/gcc/testsuite/gcc.target/arm/bti-1.c
new file mode 100644
index 00000000000..79dd8010d2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-1.c
@@ -0,0 +1,12 @@
+/* Check that GCC does bti instruction.  */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
+
+int
+main (void)
+{
+  return 0;
+}
+
+/* { dg-final { scan-assembler "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/bti-2.c b/gcc/testsuite/gcc.target/arm/bti-2.c
new file mode 100644
index 00000000000..33910563849
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-2.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* -Os to create jump table.  */
+/* { dg-options "-Os" } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
+
+extern int f1 (void);
+extern int f2 (void);
+extern int f3 (void);
+extern int f4 (void);
+extern int f5 (void);
+extern int f6 (void);
+extern int f7 (void);
+extern int f8 (void);
+extern int f9 (void);
+extern int f10 (void);
+
+int (*ptr) (void);
+
+int
+f_jump_table (int y, int n)
+{
+  int i;
+  for (i = 0; i < n ;i ++)
+  {
+    switch (y)
+      {
+      case 0 : ptr = f1; break;
+      case 1 : ptr = f2; break;
+      case 2 : ptr = f3; break;
+      case 3 : ptr = f4; break;
+      case 4 : ptr = f5; break;
+      case 5 : ptr = f6; break;
+      case 6 : ptr = f7; break;
+      case 7 : ptr = f8; break;
+      case 8 : ptr = f9; break;
+      case 9 : ptr = f10; break;
+      default: break;
+      }
+    y += ptr ();
+  }
+  return (y == 0)? y+1:4;
+}
+
+int
+f_label_address ()
+{
+  static void * addr = &&lab1;
+  goto *addr;
+lab1:
+  addr = &&lab2;
+  return 1;
+lab2:
+  addr = &&lab1;
+  return 2;
+}
+
+/* { dg-final { scan-assembler-times "bti" 15 } } */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 10/15 V6] arm: Implement cortex-M return signing address codegen
  2022-12-14 16:35                   ` [PATCH 10/15 V6] " Andrea Corallo
@ 2022-12-14 16:45                     ` Richard Earnshaw
  2023-01-11  9:58                       ` [PATCH 10/15 V7] " Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-12-14 16:45 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd



On 14/12/2022 16:35, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
> [...]
> 
>>
>> +      if (TARGET_TPCS_FRAME)
>> +        error ("Return address signing and %<-mtpcs-frame%> are
>> incompatible.");
>>
>> So really this is 'not implemented' rather than not compatible - I
>> don't see why we couldn't implement this if we really wanted to.  It's
>> not worth implementing it because tpcs-frames are very much legacy
>> these days.
>>
>> So the message should use sorry() and say 'is not supported' rather
>> than 'are incompatible'.
>>
>> +(define_insn "pacbti_nop"
>> +  [(set (reg:SI IP_REGNUM)
>> +	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
>> +		   VUNSPEC_PACBTI_NOP))]
>>
>> No, this needs to be unspec_volatile, not unspec.
>>
>> +(define_insn "aut_nop"
>> +  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
>> +	      VUNSPEC_AUT_NOP)]
>>
>> Similarly.
>>
>> R.
> 
> 
> Hi Richard & all,
> 
> please find attached the updated patch implementing suggestions.
> 
> BR
> 
>    Andrea
> 
+	(unspec_volatile:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   VUNSPEC_PACBTI_NOP))]

Please fix the indentation of the VUNSPEC_...

+  [(unspec_volatile:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI 
LR_REGNUM)]
+	      VUNSPEC_AUT_NOP)]

And here.

Otherwise ok with that change.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 12/15 V4] arm: implement bti injection
  2022-12-14 16:40             ` [PATCH 12/15 V4] " Andrea Corallo
@ 2022-12-14 17:00               ` Richard Earnshaw
  2022-12-14 17:03                 ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-12-14 17:00 UTC (permalink / raw)
  To: Andrea Corallo
  Cc: Kyrylo Tkachov, Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 14/12/2022 16:40, Andrea Corallo via Gcc-patches wrote:
> Hi Richard,
> 
> thanks for reviewing.
> 
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 28/10/2022 17:40, Andrea Corallo via Gcc-patches wrote:
>>> Hi all,
>>> please find attached the third iteration of this patch addresing
>>> review
>>> comments.
>>> Thanks
>>>     Andrea
>>>
>>
>> @@ -23374,12 +23374,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
>>     return "";
>>   }
>>
>> -static bool
>> -aarch_bti_enabled ()
>> -{
>> -  return false;
>> -}
>> -
>>   /* Generate the prologue instructions for entry into an ARM or Thumb-2
>>      function.  */
>>   void
>> @@ -32992,6 +32986,61 @@ arm_current_function_pac_enabled_p (void)
>>                 && !crtl->is_leaf));
>>   }
>>
>> +/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
>> +bool
>> +aarch_bti_enabled (void)
>> +{
>> +  return aarch_enable_bti == 1;
>> +}
>>
>> See comment in earlier patch about the location of this function
>> moving.   Can aarch_enable_bti take values other than 0 and 1?
> 
> Yes default is 2.

It shouldn't be by this point, because, hopefully you've gone through 
the equivalent of this hunk (from aarch64) somewhere in 
arm_override_options:


    if (aarch_enable_bti == 2)
      {
  #ifdef TARGET_ENABLE_BTI
        aarch_enable_bti = 1;
  #else
        aarch_enable_bti = 0;
  #endif
      }

And after this point the '2' should never be seen again.  We use this 
trick to permit the user to force a default that differs from the 
configuration.

However, I don't see a hunk to do this in patch 3, so perhaps that needs 
updating to fix this.



> [...]
> 
>> +  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) ==
>> UNSPEC_BTI_NOP;
>>
>> I'm not sure where this crept in, but UNSPEC and UNSPEC_VOLATILE have
>> separate enums in the backend, so UNSPEC_BIT_NOP should really be
>> VUNSPEC_BTI_NOP and defined in the enum "unspecv".
> 
> Done
> 
>> +aarch_pac_insn_p (rtx x)
>> +{
>> +  if (!x || !INSN_P (x))
>> +    return false;
>> +
>> +  rtx pat = PATTERN (x);
>> +
>> +  if (GET_CODE (pat) == SET)
>> +    {
>> +      rtx tmp = XEXP (pat, 1);
>> +      if (tmp
>> +	  && GET_CODE (tmp) == UNSPEC
>> +	  && (XINT (tmp, 1) == UNSPEC_PAC_NOP
>> +	      || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
>> +	return true;
>> +    }
>> +
>>
>> This will also need updating (see review on earlier patch) because
>> PACBTI needs to be unspec_volatile, while PAC doesn't.
> 
> Done
> 
>> +/* The following two functions are for code compatibility with aarch64
>> +   code, this even if in arm we have only one bti instruction.  */
>> +
>>
>> I'd just write
>>   /* Target specific mapping for aarch_gen_bti_c and
>>   aarch_gen_bti_j. For Arm, both of these map to a simple BTI
>> instruction.  */
> 
> Done
> 
>>
>> @@ -162,6 +162,7 @@ (define_c_enum "unspec" [
>>     UNSPEC_PAC_NOP	; Represents PAC signing LR
>>     UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
>>     UNSPEC_AUT_NOP	; Represents PAC verifying LR
>> +  UNSPEC_BTI_NOP	; Represent BTI
>>   ])
>>
>> BTI is an unspec volatile, so this should be in the "vunspec" enum and
>> renamed accordingly (see above).
> 
> Done.
> 
> Please find attached the updated version of this patch.
> 
> BR
> 
>    Andrea
> 

Apart from that, this is OK.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 12/15 V4] arm: implement bti injection
  2022-12-14 17:00               ` Richard Earnshaw
@ 2022-12-14 17:03                 ` Richard Earnshaw
  2022-12-22 17:13                   ` [PATCH 12/15 V5] " Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2022-12-14 17:03 UTC (permalink / raw)
  To: Andrea Corallo
  Cc: Kyrylo Tkachov, Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 14/12/2022 17:00, Richard Earnshaw via Gcc-patches wrote:
> 
> 
> On 14/12/2022 16:40, Andrea Corallo via Gcc-patches wrote:
>> Hi Richard,
>>
>> thanks for reviewing.
>>
>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>
>>> On 28/10/2022 17:40, Andrea Corallo via Gcc-patches wrote:
>>>> Hi all,
>>>> please find attached the third iteration of this patch addresing
>>>> review
>>>> comments.
>>>> Thanks
>>>>     Andrea
>>>>
>>>
>>> @@ -23374,12 +23374,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
>>>     return "";
>>>   }
>>>
>>> -static bool
>>> -aarch_bti_enabled ()
>>> -{
>>> -  return false;
>>> -}
>>> -
>>>   /* Generate the prologue instructions for entry into an ARM or Thumb-2
>>>      function.  */
>>>   void
>>> @@ -32992,6 +32986,61 @@ arm_current_function_pac_enabled_p (void)
>>>                 && !crtl->is_leaf));
>>>   }
>>>
>>> +/* Return TRUE if Branch Target Identification Mechanism is 
>>> enabled.  */
>>> +bool
>>> +aarch_bti_enabled (void)
>>> +{
>>> +  return aarch_enable_bti == 1;
>>> +}
>>>
>>> See comment in earlier patch about the location of this function
>>> moving.   Can aarch_enable_bti take values other than 0 and 1?
>>
>> Yes default is 2.
> 
> It shouldn't be by this point, because, hopefully you've gone through 
> the equivalent of this hunk (from aarch64) somewhere in 
> arm_override_options:
> 
> 
>     if (aarch_enable_bti == 2)
>       {
>   #ifdef TARGET_ENABLE_BTI
>         aarch_enable_bti = 1;
>   #else
>         aarch_enable_bti = 0;
>   #endif
>       }
> 
> And after this point the '2' should never be seen again.  We use this 
> trick to permit the user to force a default that differs from the 
> configuration.
> 
> However, I don't see a hunk to do this in patch 3, so perhaps that needs 
> updating to fix this.

I've just remembered that the above is to support a configure-time 
option of the compiler to enable branch protection.  But perhaps we 
don't want to have that in AArch32, in which case it would be better not 
to have the default be 2 anyway, just default to off (0).

R.

> 
> 
> 
>> [...]
>>
>>> +  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) ==
>>> UNSPEC_BTI_NOP;
>>>
>>> I'm not sure where this crept in, but UNSPEC and UNSPEC_VOLATILE have
>>> separate enums in the backend, so UNSPEC_BIT_NOP should really be
>>> VUNSPEC_BTI_NOP and defined in the enum "unspecv".
>>
>> Done
>>
>>> +aarch_pac_insn_p (rtx x)
>>> +{
>>> +  if (!x || !INSN_P (x))
>>> +    return false;
>>> +
>>> +  rtx pat = PATTERN (x);
>>> +
>>> +  if (GET_CODE (pat) == SET)
>>> +    {
>>> +      rtx tmp = XEXP (pat, 1);
>>> +      if (tmp
>>> +      && GET_CODE (tmp) == UNSPEC
>>> +      && (XINT (tmp, 1) == UNSPEC_PAC_NOP
>>> +          || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
>>> +    return true;
>>> +    }
>>> +
>>>
>>> This will also need updating (see review on earlier patch) because
>>> PACBTI needs to be unspec_volatile, while PAC doesn't.
>>
>> Done
>>
>>> +/* The following two functions are for code compatibility with aarch64
>>> +   code, this even if in arm we have only one bti instruction.  */
>>> +
>>>
>>> I'd just write
>>>   /* Target specific mapping for aarch_gen_bti_c and
>>>   aarch_gen_bti_j. For Arm, both of these map to a simple BTI
>>> instruction.  */
>>
>> Done
>>
>>>
>>> @@ -162,6 +162,7 @@ (define_c_enum "unspec" [
>>>     UNSPEC_PAC_NOP    ; Represents PAC signing LR
>>>     UNSPEC_PACBTI_NOP    ; Represents PAC signing LR + valid landing pad
>>>     UNSPEC_AUT_NOP    ; Represents PAC verifying LR
>>> +  UNSPEC_BTI_NOP    ; Represent BTI
>>>   ])
>>>
>>> BTI is an unspec volatile, so this should be in the "vunspec" enum and
>>> renamed accordingly (see above).
>>
>> Done.
>>
>> Please find attached the updated version of this patch.
>>
>> BR
>>
>>    Andrea
>>
> 
> Apart from that, this is OK.
> 
> R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 1/15 V2] arm: Make mbranch-protection opts parsing common to AArch32/64
  2022-08-12 15:14 ` [PATCH 1/15] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
@ 2022-12-22 17:04   ` Andrea Corallo
  2023-01-11 10:48     ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-12-22 17:04 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 185 bytes --]

Hi all,

respinning this as a rebase was necessary, also now is setting
'aarch_enable_bti' to zero as default for arm as suggested during the
review of 12/15.

Best Regards

  Andrea



[-- Attachment #2: 0001-PATCH-1-15-arm-Make-mbranch-protection-opts-parsing-.patch --]
[-- Type: text/plain, Size: 48826 bytes --]

From 6c765818542cc7b40701e8adae2cbe077d5982cc Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Mon, 6 Dec 2021 11:34:35 +0100
Subject: [PATCH] [PATCH 1/15] arm: Make mbranch-protection opts parsing common
 to AArch32/64

Hi all,

This change refactors all the mbranch-protection option parsing code and
types to make it common to both AArch32 and AArch64 backends.

This change also pulls in some supporting types from AArch64 to make
it common (aarch_parse_opt_result).

The significant changes in this patch are the movement of all branch
protection parsing routines from aarch64.c to aarch-common.c and
supporting data types and static data structures.

This patch also pre-declares variables and types required in the
aarch32 back-end for moved variables for function sign scope and key
to prepare for the impending series of patches that support parsing
the feature mbranch-protection in the aarch32 back-end.

gcc/ChangeLog:

	* common/config/aarch64/aarch64-common.cc: Include aarch-common.h.
	(all_architectures): Fix comment.
	(aarch64_parse_extension): Rename return type, enum value names.
	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Rename
	factored out aarch_ra_sign_scope and aarch_ra_sign_key variables.
	Also rename corresponding enum values.
	* config/aarch64/aarch64-opts.h (aarch64_function_type): Factor
	out aarch64_function_type and move it to common code as
	aarch_function_type in aarch-common.h.
	* config/aarch64/aarch64-protos.h: Include common types header,
	move out types aarch64_parse_opt_result and aarch64_key_type to
	aarch-common.h
	* config/aarch64/aarch64.cc: Move mbranch-protection parsing types
	and functions out into aarch-common.h and aarch-common.cc.  Fix up
	all the name changes resulting from the move.
	* config/aarch64/aarch64.md: Fix up aarch64_ra_sign_key type name change
	and enum value.
	* config/aarch64/aarch64.opt: Include aarch-common.h to import
	type move.  Fix up name changes from factoring out common code and
	data.
	* config/arm/aarch-common-protos.h: Export factored out routines to both
	backends.
	* config/arm/aarch-common.cc: Include newly factored out types.
	Move all mbranch-protection code and data structures from
	aarch64.cc.
	* config/arm/aarch-common.h: New header that declares types shared
	between aarch32 and aarch64 backends.
	* config/arm/arm-protos.h: Declare types and variables that are
	made common to aarch64 and aarch32 backends - aarch_ra_sign_key,
	aarch_ra_sign_scope and aarch_enable_bti.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>
---
 gcc/common/config/aarch64/aarch64-common.cc |  13 +-
 gcc/config/aarch64/aarch64-c.cc             |   8 +-
 gcc/config/aarch64/aarch64-opts.h           |  10 -
 gcc/config/aarch64/aarch64-protos.h         |  21 +-
 gcc/config/aarch64/aarch64.cc               | 360 +++++---------------
 gcc/config/aarch64/aarch64.md               |   2 +-
 gcc/config/aarch64/aarch64.opt              |  15 +-
 gcc/config/arm/aarch-common-protos.h        |   6 +
 gcc/config/arm/aarch-common.cc              | 185 ++++++++++
 gcc/config/arm/aarch-common.h               |  73 ++++
 gcc/config/arm/arm-protos.h                 |   2 +
 gcc/config/arm/arm.cc                       |   7 +
 gcc/config/arm/arm.opt                      |   9 +
 13 files changed, 390 insertions(+), 321 deletions(-)
 create mode 100644 gcc/config/arm/aarch-common.h

diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
index 61007839d35..18b0b72c012 100644
--- a/gcc/common/config/aarch64/aarch64-common.cc
+++ b/gcc/common/config/aarch64/aarch64-common.cc
@@ -31,6 +31,7 @@
 #include "flags.h"
 #include "diagnostic.h"
 #include "config/aarch64/aarch64-feature-deps.h"
+#include "config/arm/aarch-common.h"
 
 #ifdef  TARGET_BIG_ENDIAN_DEFAULT
 #undef  TARGET_DEFAULT_TARGET_FLAGS
@@ -191,13 +192,13 @@ static constexpr arch_to_arch_name all_architectures[] =
 
 /* Parse the architecture extension string STR and update ISA_FLAGS
    with the architecture features turned on or off.  Return a
-   aarch64_parse_opt_result describing the result.
+   aarch_parse_opt_result describing the result.
    When the STR string contains an invalid extension,
    a copy of the string is created and stored to INVALID_EXTENSION.  */
 
-enum aarch64_parse_opt_result
+enum aarch_parse_opt_result
 aarch64_parse_extension (const char *str, aarch64_feature_flags *isa_flags,
-			 std::string *invalid_extension)
+                         std::string *invalid_extension)
 {
   /* The extension string is parsed left to right.  */
   const struct aarch64_option_extension *opt = NULL;
@@ -228,7 +229,7 @@ aarch64_parse_extension (const char *str, aarch64_feature_flags *isa_flags,
 	adding_ext = 1;
 
       if (len == 0)
-	return AARCH64_PARSE_MISSING_ARG;
+	return AARCH_PARSE_MISSING_ARG;
 
 
       /* Scan over the extensions table trying to find an exact match.  */
@@ -250,13 +251,13 @@ aarch64_parse_extension (const char *str, aarch64_feature_flags *isa_flags,
 	  /* Extension not found in list.  */
 	  if (invalid_extension)
 	    *invalid_extension = std::string (str, len);
-	  return AARCH64_PARSE_INVALID_FEATURE;
+	  return AARCH_PARSE_INVALID_FEATURE;
 	}
 
       str = ext;
     };
 
-  return AARCH64_PARSE_OK;
+  return AARCH_PARSE_OK;
 }
 
 /* Append all architecture extension candidates to the CANDIDATES vector.  */
diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
index e296c73350f..c8e4431ac56 100644
--- a/gcc/config/aarch64/aarch64-c.cc
+++ b/gcc/config/aarch64/aarch64-c.cc
@@ -183,14 +183,14 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
 			"__ARM_FEATURE_BTI_DEFAULT", pfile);
 
   cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT");
-  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE)
+  if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
     {
       int v = 0;
-      if (aarch64_ra_sign_key == AARCH64_KEY_A)
+      if (aarch_ra_sign_key == AARCH_KEY_A)
 	v |= 1;
-      if (aarch64_ra_sign_key == AARCH64_KEY_B)
+      if (aarch_ra_sign_key == AARCH_KEY_B)
 	v |= 2;
-      if (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL)
+      if (aarch_ra_sign_scope == AARCH_FUNCTION_ALL)
 	v |= 4;
       builtin_define_with_int_value ("__ARM_FEATURE_PAC_DEFAULT", v);
     }
diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
index ba23c90c411..71f834635b3 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -75,16 +75,6 @@ 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
-};
-
 /* SVE vector register sizes.  */
 enum aarch64_sve_vector_bits_enum {
   SVE_SCALABLE,
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index fcc3a66cdf2..f031bd7026c 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -23,6 +23,7 @@
 #define GCC_AARCH64_PROTOS_H
 
 #include "input.h"
+#include "config/arm/aarch-common.h"
 
 /* SYMBOL_SMALL_ABSOLUTE: Generate symbol accesses through
    high and lo relocs that calculate the base address using a PC
@@ -651,18 +652,6 @@ enum aarch64_extra_tuning_flags
   AARCH64_EXTRA_TUNE_ALL = (1u << AARCH64_EXTRA_TUNE_index_END) - 1
 };
 
-/* Enum describing the various ways that the
-   aarch64_parse_{arch,tune,cpu,extension} functions can fail.
-   This way their callers can choose what kind of error to give.  */
-
-enum aarch64_parse_opt_result
-{
-  AARCH64_PARSE_OK,			/* Parsing was successful.  */
-  AARCH64_PARSE_MISSING_ARG,		/* Missing argument.  */
-  AARCH64_PARSE_INVALID_FEATURE,	/* Invalid feature modifier.  */
-  AARCH64_PARSE_INVALID_ARG		/* Invalid arch, tune, cpu arg.  */
-};
-
 /* Enum to distinguish which type of check is to be done in
    aarch64_simd_valid_immediate.  This is used as a bitmask where
    AARCH64_CHECK_MOV has both bits set.  Thus AARCH64_CHECK_MOV will
@@ -673,6 +662,8 @@ enum simd_immediate_check {
   AARCH64_CHECK_MOV  = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
 };
 
+extern enum aarch_key_type aarch_ra_sign_key;
+
 extern struct tune_params aarch64_tune_params;
 
 /* The available SVE predicate patterns, known in the ACLE as "svpattern".  */
@@ -1038,9 +1029,9 @@ void aarch64_set_asm_isa_flags (gcc_options *, aarch64_feature_flags);
 bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
 			     const struct cl_decoded_option *, location_t);
 const char *aarch64_rewrite_selected_cpu (const char *name);
-enum aarch64_parse_opt_result aarch64_parse_extension (const char *,
-						       aarch64_feature_flags *,
-						       std::string *);
+enum aarch_parse_opt_result aarch64_parse_extension (const char *,
+                                                     aarch64_feature_flags *,
+                                                     std::string *);
 void aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates);
 std::string aarch64_get_extension_string_for_isa_flags (aarch64_feature_flags,
 							aarch64_feature_flags);
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 45d659a4a91..ffef5e6f32e 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -82,6 +82,8 @@
 #include "tree-dfa.h"
 #include "asan.h"
 #include "aarch64-feature-deps.h"
+#include "config/arm/aarch-common.h"
+#include "config/arm/aarch-common-protos.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -318,12 +320,8 @@ bool aarch64_pcrelative_literal_loads;
 /* Global flag for whether frame pointer is enabled.  */
 bool aarch64_use_frame_pointer;
 
-#define BRANCH_PROTECT_STR_MAX 255
 char *accepted_branch_protection_string = NULL;
 
-static enum aarch64_parse_opt_result
-aarch64_parse_branch_protection (const char*, char**);
-
 /* Support for command line parsing of boolean flags in the tuning
    structures.  */
 struct aarch64_flag_desc
@@ -2761,6 +2759,8 @@ static const struct processor all_cores[] =
   {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL}
 };
 
+enum aarch_key_type aarch_ra_sign_key = AARCH_KEY_A;
+
 /* The current tuning set.  */
 struct tune_params aarch64_tune_params = generic_tunings;
 
@@ -2826,100 +2826,6 @@ aarch64_cc;
 
 #define AARCH64_INVERSE_CONDITION_CODE(X) ((aarch64_cc) (((int) X) ^ 1))
 
-struct aarch64_branch_protect_type
-{
-  /* The type's name that the user passes to the branch-protection option
-    string.  */
-  const char* name;
-  /* Function to handle the protection type and set global variables.
-    First argument is the string token corresponding with this type and the
-    second argument is the next token in the option string.
-    Return values:
-    * AARCH64_PARSE_OK: Handling was sucessful.
-    * AARCH64_INVALID_ARG: The type is invalid in this context and the caller
-      should print an error.
-    * AARCH64_INVALID_FEATURE: The type is invalid and the handler prints its
-      own error.  */
-  enum aarch64_parse_opt_result (*handler)(char*, char*);
-  /* A list of types that can follow this type in the option string.  */
-  const aarch64_branch_protect_type* subtypes;
-  unsigned int num_subtypes;
-};
-
-static enum aarch64_parse_opt_result
-aarch64_handle_no_branch_protection (char* str, char* rest)
-{
-  aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE;
-  aarch64_enable_bti = 0;
-  if (rest)
-    {
-      error ("unexpected %<%s%> after %<%s%>", rest, str);
-      return AARCH64_PARSE_INVALID_FEATURE;
-    }
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_standard_branch_protection (char* str, char* rest)
-{
-  aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
-  aarch64_ra_sign_key = AARCH64_KEY_A;
-  aarch64_enable_bti = 1;
-  if (rest)
-    {
-      error ("unexpected %<%s%> after %<%s%>", rest, str);
-      return AARCH64_PARSE_INVALID_FEATURE;
-    }
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED,
-				    char* rest ATTRIBUTE_UNUSED)
-{
-  aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
-  aarch64_ra_sign_key = AARCH64_KEY_A;
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED,
-			      char* rest ATTRIBUTE_UNUSED)
-{
-  aarch64_ra_sign_scope = AARCH64_FUNCTION_ALL;
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED,
-			      char* rest ATTRIBUTE_UNUSED)
-{
-  aarch64_ra_sign_key = AARCH64_KEY_B;
-  return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_bti_protection (char* str ATTRIBUTE_UNUSED,
-				    char* rest ATTRIBUTE_UNUSED)
-{
-  aarch64_enable_bti = 1;
-  return AARCH64_PARSE_OK;
-}
-
-static const struct aarch64_branch_protect_type aarch64_pac_ret_subtypes[] = {
-  { "leaf", aarch64_handle_pac_ret_leaf, NULL, 0 },
-  { "b-key", aarch64_handle_pac_ret_b_key, NULL, 0 },
-  { NULL, NULL, NULL, 0 }
-};
-
-static const struct aarch64_branch_protect_type aarch64_branch_protect_types[] = {
-  { "none", aarch64_handle_no_branch_protection, NULL, 0 },
-  { "standard", aarch64_handle_standard_branch_protection, NULL, 0 },
-  { "pac-ret", aarch64_handle_pac_ret_protection, aarch64_pac_ret_subtypes,
-    ARRAY_SIZE (aarch64_pac_ret_subtypes) },
-  { "bti", aarch64_handle_bti_protection, NULL, 0 },
-  { NULL, NULL, NULL, 0 }
-};
 
 /* The condition codes of the processor, and the inverse function.  */
 static const char * const aarch64_condition_codes[] =
@@ -8893,10 +8799,10 @@ aarch64_return_address_signing_enabled (void)
   if (crtl->calls_eh_return)
     return false;
 
-  /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
+  /* If signing scope is AARCH_FUNCTION_NON_LEAF, we only sign a leaf function
      if its LR is pushed onto stack.  */
-  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
-	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
+  return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+	  || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
 	      && known_ge (cfun->machine->frame.reg_offset[LR_REGNUM], 0)));
 }
 
@@ -8904,7 +8810,7 @@ aarch64_return_address_signing_enabled (void)
 bool
 aarch64_bti_enabled (void)
 {
-  return (aarch64_enable_bti == 1);
+  return (aarch_enable_bti == 1);
 }
 
 /* The caller is going to use ST1D or LD1D to save or restore an SVE
@@ -9896,12 +9802,12 @@ aarch64_expand_prologue (void)
   /* Sign return address for functions.  */
   if (aarch64_return_address_signing_enabled ())
     {
-      switch (aarch64_ra_sign_key)
+      switch (aarch_ra_sign_key)
 	{
-	  case AARCH64_KEY_A:
+	  case AARCH_KEY_A:
 	    insn = emit_insn (gen_paciasp ());
 	    break;
-	  case AARCH64_KEY_B:
+	  case AARCH_KEY_B:
 	    insn = emit_insn (gen_pacibsp ());
 	    break;
 	  default:
@@ -10202,12 +10108,12 @@ aarch64_expand_epilogue (bool for_sibcall)
   if (aarch64_return_address_signing_enabled ()
       && (for_sibcall || !TARGET_ARMV8_3))
     {
-      switch (aarch64_ra_sign_key)
+      switch (aarch_ra_sign_key)
 	{
-	  case AARCH64_KEY_A:
+	  case AARCH_KEY_A:
 	    insn = emit_insn (gen_autiasp ());
 	    break;
-	  case AARCH64_KEY_B:
+	  case AARCH_KEY_B:
 	    insn = emit_insn (gen_autibsp ());
 	    break;
 	  default:
@@ -17222,12 +17128,12 @@ static void initialize_aarch64_code_model (struct gcc_options *);
 
 /* Parse the TO_PARSE string and put the architecture struct that it
    selects into RES and the architectural features into ISA_FLAGS.
-   Return an aarch64_parse_opt_result describing the parse result.
+   Return an aarch_parse_opt_result describing the parse result.
    If there is an error parsing, RES and ISA_FLAGS are left unchanged.
    When the TO_PARSE string contains an invalid extension,
    a copy of the string is created and stored to INVALID_EXTENSION.  */
 
-static enum aarch64_parse_opt_result
+static enum aarch_parse_opt_result
 aarch64_parse_arch (const char *to_parse, const struct processor **res,
 		    aarch64_feature_flags *isa_flags,
 		    std::string *invalid_extension)
@@ -17244,7 +17150,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
     len = strlen (to_parse);
 
   if (len == 0)
-    return AARCH64_PARSE_MISSING_ARG;
+    return AARCH_PARSE_MISSING_ARG;
 
 
   /* Loop through the list of supported ARCHes to find a match.  */
@@ -17258,32 +17164,32 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
 	  if (ext != NULL)
 	    {
 	      /* TO_PARSE string contains at least one extension.  */
-	      enum aarch64_parse_opt_result ext_res
+	      enum aarch_parse_opt_result ext_res
 		= aarch64_parse_extension (ext, &isa_temp, invalid_extension);
 
-	      if (ext_res != AARCH64_PARSE_OK)
+	      if (ext_res != AARCH_PARSE_OK)
 		return ext_res;
 	    }
 	  /* Extension parsing was successful.  Confirm the result
 	     arch and ISA flags.  */
 	  *res = arch;
 	  *isa_flags = isa_temp;
-	  return AARCH64_PARSE_OK;
+	  return AARCH_PARSE_OK;
 	}
     }
 
   /* ARCH name not found in list.  */
-  return AARCH64_PARSE_INVALID_ARG;
+  return AARCH_PARSE_INVALID_ARG;
 }
 
 /* Parse the TO_PARSE string and put the result tuning in RES and the
-   architecture flags in ISA_FLAGS.  Return an aarch64_parse_opt_result
+   architecture flags in ISA_FLAGS.  Return an aarch_parse_opt_result
    describing the parse result.  If there is an error parsing, RES and
    ISA_FLAGS are left unchanged.
    When the TO_PARSE string contains an invalid extension,
    a copy of the string is created and stored to INVALID_EXTENSION.  */
 
-static enum aarch64_parse_opt_result
+static enum aarch_parse_opt_result
 aarch64_parse_cpu (const char *to_parse, const struct processor **res,
 		   aarch64_feature_flags *isa_flags,
 		   std::string *invalid_extension)
@@ -17300,7 +17206,7 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
     len = strlen (to_parse);
 
   if (len == 0)
-    return AARCH64_PARSE_MISSING_ARG;
+    return AARCH_PARSE_MISSING_ARG;
 
 
   /* Loop through the list of supported CPUs to find a match.  */
@@ -17313,29 +17219,29 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
 	  if (ext != NULL)
 	    {
 	      /* TO_PARSE string contains at least one extension.  */
-	      enum aarch64_parse_opt_result ext_res
+	      enum aarch_parse_opt_result ext_res
 		= aarch64_parse_extension (ext, &isa_temp, invalid_extension);
 
-	      if (ext_res != AARCH64_PARSE_OK)
+	      if (ext_res != AARCH_PARSE_OK)
 		return ext_res;
 	    }
 	  /* Extension parsing was successfull.  Confirm the result
 	     cpu and ISA flags.  */
 	  *res = cpu;
 	  *isa_flags = isa_temp;
-	  return AARCH64_PARSE_OK;
+	  return AARCH_PARSE_OK;
 	}
     }
 
   /* CPU name not found in list.  */
-  return AARCH64_PARSE_INVALID_ARG;
+  return AARCH_PARSE_INVALID_ARG;
 }
 
 /* Parse the TO_PARSE string and put the cpu it selects into RES.
-   Return an aarch64_parse_opt_result describing the parse result.
+   Return an aarch_parse_opt_result describing the parse result.
    If the parsing fails the RES does not change.  */
 
-static enum aarch64_parse_opt_result
+static enum aarch_parse_opt_result
 aarch64_parse_tune (const char *to_parse, const struct processor **res)
 {
   const struct processor *cpu;
@@ -17346,12 +17252,12 @@ aarch64_parse_tune (const char *to_parse, const struct processor **res)
       if (strcmp (cpu->name, to_parse) == 0)
 	{
 	  *res = cpu;
-	  return AARCH64_PARSE_OK;
+	  return AARCH_PARSE_OK;
 	}
     }
 
   /* CPU name not found in list.  */
-  return AARCH64_PARSE_INVALID_ARG;
+  return AARCH_PARSE_INVALID_ARG;
 }
 
 /* Parse TOKEN, which has length LENGTH to see if it is an option
@@ -17942,22 +17848,22 @@ aarch64_validate_mcpu (const char *str, const struct processor **res,
 		       aarch64_feature_flags *isa_flags)
 {
   std::string invalid_extension;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_cpu (str, res, isa_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     return true;
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing cpu name in %<-mcpu=%s%>", str);
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("unknown value %qs for %<-mcpu%>", str);
 	aarch64_print_hint_for_core (str);
 	break;
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %qs in %<-mcpu=%s%>",
 	       invalid_extension.c_str (), str);
 	aarch64_print_hint_for_extensions (invalid_extension);
@@ -18042,110 +17948,6 @@ aarch64_validate_sls_mitigation (const char *const_str)
   free (str_root);
 }
 
-/* Parses CONST_STR for branch protection features specified in
-   aarch64_branch_protect_types, and set any global variables required.  Returns
-   the parsing result and assigns LAST_STR to the last processed token from
-   CONST_STR so that it can be used for error reporting.  */
-
-static enum
-aarch64_parse_opt_result aarch64_parse_branch_protection (const char *const_str,
-							  char** last_str)
-{
-  char *str_root = xstrdup (const_str);
-  char* token_save = NULL;
-  char *str = strtok_r (str_root, "+", &token_save);
-  enum aarch64_parse_opt_result res = AARCH64_PARSE_OK;
-  if (!str)
-    res = AARCH64_PARSE_MISSING_ARG;
-  else
-    {
-      char *next_str = strtok_r (NULL, "+", &token_save);
-      /* Reset the branch protection features to their defaults.  */
-      aarch64_handle_no_branch_protection (NULL, NULL);
-
-      while (str && res == AARCH64_PARSE_OK)
-	{
-	  const aarch64_branch_protect_type* type = aarch64_branch_protect_types;
-	  bool found = false;
-	  /* Search for this type.  */
-	  while (type && type->name && !found && res == AARCH64_PARSE_OK)
-	    {
-	      if (strcmp (str, type->name) == 0)
-		{
-		  found = true;
-		  res = type->handler (str, next_str);
-		  str = next_str;
-		  next_str = strtok_r (NULL, "+", &token_save);
-		}
-	      else
-		type++;
-	    }
-	  if (found && res == AARCH64_PARSE_OK)
-	    {
-	      bool found_subtype = true;
-	      /* Loop through each token until we find one that isn't a
-		 subtype.  */
-	      while (found_subtype)
-		{
-		  found_subtype = false;
-		  const aarch64_branch_protect_type *subtype = type->subtypes;
-		  /* Search for the subtype.  */
-		  while (str && subtype && subtype->name && !found_subtype
-			  && res == AARCH64_PARSE_OK)
-		    {
-		      if (strcmp (str, subtype->name) == 0)
-			{
-			  found_subtype = true;
-			  res = subtype->handler (str, next_str);
-			  str = next_str;
-			  next_str = strtok_r (NULL, "+", &token_save);
-			}
-		      else
-			subtype++;
-		    }
-		}
-	    }
-	  else if (!found)
-	    res = AARCH64_PARSE_INVALID_ARG;
-	}
-    }
-  /* Copy the last processed token into the argument to pass it back.
-    Used by option and attribute validation to print the offending token.  */
-  if (last_str)
-    {
-      if (str) strcpy (*last_str, str);
-      else *last_str = NULL;
-    }
-  if (res == AARCH64_PARSE_OK)
-    {
-      /* If needed, alloc the accepted string then copy in const_str.
-	Used by override_option_after_change_1.  */
-      if (!accepted_branch_protection_string)
-	accepted_branch_protection_string = (char *) xmalloc (
-						      BRANCH_PROTECT_STR_MAX
-							+ 1);
-      strncpy (accepted_branch_protection_string, const_str,
-		BRANCH_PROTECT_STR_MAX + 1);
-      /* Forcibly null-terminate.  */
-      accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0';
-    }
-  return res;
-}
-
-static bool
-aarch64_validate_mbranch_protection (const char *const_str)
-{
-  char *str = (char *) xmalloc (strlen (const_str));
-  enum aarch64_parse_opt_result res =
-    aarch64_parse_branch_protection (const_str, &str);
-  if (res == AARCH64_PARSE_INVALID_ARG)
-    error ("invalid argument %<%s%> for %<-mbranch-protection=%>", str);
-  else if (res == AARCH64_PARSE_MISSING_ARG)
-    error ("missing argument for %<-mbranch-protection=%>");
-  free (str);
-  return res == AARCH64_PARSE_OK;
-}
-
 /* Validate a command-line -march option.  Parse the arch and extensions
    (if any) specified in STR and throw errors if appropriate.  Put the
    results, if they are valid, in RES and ISA_FLAGS.  Return whether the
@@ -18156,27 +17958,27 @@ aarch64_validate_march (const char *str, const struct processor **res,
 			aarch64_feature_flags *isa_flags)
 {
   std::string invalid_extension;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_arch (str, res, isa_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     return true;
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing arch name in %<-march=%s%>", str);
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("unknown value %qs for %<-march%>", str);
 	aarch64_print_hint_for_arch (str);
 	/* A common user error is confusing -march and -mcpu.
 	   If the -march string matches a known CPU suggest -mcpu.  */
 	parse_res = aarch64_parse_cpu (str, res, isa_flags, &invalid_extension);
-	if (parse_res == AARCH64_PARSE_OK)
+	if (parse_res == AARCH_PARSE_OK)
 	  inform (input_location, "did you mean %<-mcpu=%s%>?", str);
 	break;
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %qs in %<-march=%s%>",
 	       invalid_extension.c_str (), str);
 	aarch64_print_hint_for_extensions (invalid_extension);
@@ -18196,18 +17998,18 @@ aarch64_validate_march (const char *str, const struct processor **res,
 static bool
 aarch64_validate_mtune (const char *str, const struct processor **res)
 {
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_tune (str, res);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     return true;
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing cpu name in %<-mtune=%s%>", str);
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("unknown value %qs for %<-mtune%>", str);
 	aarch64_print_hint_for_core (str);
 	break;
@@ -18269,7 +18071,7 @@ aarch64_override_options (void)
     aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
 
   if (aarch64_branch_protection_string)
-    aarch64_validate_mbranch_protection (aarch64_branch_protection_string);
+    aarch_validate_mbranch_protection (aarch64_branch_protection_string);
 
   /* -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU.
      If either of -march or -mtune is given, they override their
@@ -18322,12 +18124,12 @@ aarch64_override_options (void)
 
   selected_tune = tune ? tune->ident : cpu->ident;
 
-  if (aarch64_enable_bti == 2)
+  if (aarch_enable_bti == 2)
     {
 #ifdef TARGET_ENABLE_BTI
-      aarch64_enable_bti = 1;
+      aarch_enable_bti = 1;
 #else
-      aarch64_enable_bti = 0;
+      aarch_enable_bti = 0;
 #endif
     }
 
@@ -18337,9 +18139,9 @@ aarch64_override_options (void)
   if (!TARGET_ILP32 && accepted_branch_protection_string == NULL)
     {
 #ifdef TARGET_ENABLE_PAC_RET
-      aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
+      aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
 #else
-      aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE;
+      aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
 #endif
     }
 
@@ -18353,7 +18155,7 @@ aarch64_override_options (void)
   /* Convert -msve-vector-bits to a VG count.  */
   aarch64_sve_vg = aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits);
 
-  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
+  if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE && TARGET_ILP32)
     sorry ("return address signing is only supported for %<-mabi=lp64%>");
 
   /* The pass to insert speculation tracking runs before
@@ -18568,10 +18370,10 @@ aarch64_handle_attr_arch (const char *str)
   const struct processor *tmp_arch = NULL;
   std::string invalid_extension;
   aarch64_feature_flags tmp_flags;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_arch (str, &tmp_arch, &tmp_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     {
       gcc_assert (tmp_arch);
       selected_arch = tmp_arch->arch;
@@ -18581,14 +18383,14 @@ aarch64_handle_attr_arch (const char *str)
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing name in %<target(\"arch=\")%> pragma or attribute");
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("invalid name %qs in %<target(\"arch=\")%> pragma or attribute", str);
 	aarch64_print_hint_for_arch (str);
 	break;
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %s of value %qs in "
 	       "%<target()%> pragma or attribute", invalid_extension.c_str (), str);
 	aarch64_print_hint_for_extensions (invalid_extension);
@@ -18608,10 +18410,10 @@ aarch64_handle_attr_cpu (const char *str)
   const struct processor *tmp_cpu = NULL;
   std::string invalid_extension;
   aarch64_feature_flags tmp_flags;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_cpu (str, &tmp_cpu, &tmp_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     {
       gcc_assert (tmp_cpu);
       selected_tune = tmp_cpu->ident;
@@ -18622,14 +18424,14 @@ aarch64_handle_attr_cpu (const char *str)
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing name in %<target(\"cpu=\")%> pragma or attribute");
 	break;
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("invalid name %qs in %<target(\"cpu=\")%> pragma or attribute", str);
 	aarch64_print_hint_for_core (str);
 	break;
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %qs of value %qs in "
 	       "%<target()%> pragma or attribute", invalid_extension.c_str (), str);
 	aarch64_print_hint_for_extensions (invalid_extension);
@@ -18647,23 +18449,23 @@ aarch64_handle_attr_cpu (const char *str)
  aarch64_handle_attr_branch_protection (const char* str)
  {
   char *err_str = (char *) xmalloc (strlen (str) + 1);
-  enum aarch64_parse_opt_result res = aarch64_parse_branch_protection (str,
-								      &err_str);
+  enum aarch_parse_opt_result res = aarch_parse_branch_protection (str,
+								   &err_str);
   bool success = false;
   switch (res)
     {
-     case AARCH64_PARSE_MISSING_ARG:
+     case AARCH_PARSE_MISSING_ARG:
        error ("missing argument to %<target(\"branch-protection=\")%> pragma or"
 	      " attribute");
        break;
-     case AARCH64_PARSE_INVALID_ARG:
+     case AARCH_PARSE_INVALID_ARG:
        error ("invalid protection type %qs in %<target(\"branch-protection"
 	      "=\")%> pragma or attribute", err_str);
        break;
-     case AARCH64_PARSE_OK:
+     case AARCH_PARSE_OK:
        success = true;
       /* Fall through.  */
-     case AARCH64_PARSE_INVALID_FEATURE:
+     case AARCH_PARSE_INVALID_FEATURE:
        break;
      default:
        gcc_unreachable ();
@@ -18678,10 +18480,10 @@ static bool
 aarch64_handle_attr_tune (const char *str)
 {
   const struct processor *tmp_tune = NULL;
-  enum aarch64_parse_opt_result parse_res
+  enum aarch_parse_opt_result parse_res
     = aarch64_parse_tune (str, &tmp_tune);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     {
       gcc_assert (tmp_tune);
       selected_tune = tmp_tune->ident;
@@ -18690,7 +18492,7 @@ aarch64_handle_attr_tune (const char *str)
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_INVALID_ARG:
+      case AARCH_PARSE_INVALID_ARG:
 	error ("invalid name %qs in %<target(\"tune=\")%> pragma or attribute", str);
 	aarch64_print_hint_for_core (str);
 	break;
@@ -18709,7 +18511,7 @@ aarch64_handle_attr_tune (const char *str)
 static bool
 aarch64_handle_attr_isa_flags (char *str)
 {
-  enum aarch64_parse_opt_result parse_res;
+  enum aarch_parse_opt_result parse_res;
   auto isa_flags = aarch64_asm_isa_flags;
 
   /* We allow "+nothing" in the beginning to clear out all architectural
@@ -18723,7 +18525,7 @@ aarch64_handle_attr_isa_flags (char *str)
   std::string invalid_extension;
   parse_res = aarch64_parse_extension (str, &isa_flags, &invalid_extension);
 
-  if (parse_res == AARCH64_PARSE_OK)
+  if (parse_res == AARCH_PARSE_OK)
     {
       aarch64_set_asm_isa_flags (isa_flags);
       return true;
@@ -18731,11 +18533,11 @@ aarch64_handle_attr_isa_flags (char *str)
 
   switch (parse_res)
     {
-      case AARCH64_PARSE_MISSING_ARG:
+      case AARCH_PARSE_MISSING_ARG:
 	error ("missing value in %<target()%> pragma or attribute");
 	break;
 
-      case AARCH64_PARSE_INVALID_FEATURE:
+      case AARCH_PARSE_INVALID_FEATURE:
 	error ("invalid feature modifier %qs of value %qs in "
 	       "%<target()%> pragma or attribute", invalid_extension.c_str (), str);
 	break;
@@ -18984,10 +18786,10 @@ aarch64_process_target_attr (tree args)
 	     leading '+'.  */
 	  aarch64_feature_flags isa_temp = 0;
 	  auto with_plus = std::string ("+") + token;
-	  enum aarch64_parse_opt_result ext_res
+	  enum aarch_parse_opt_result ext_res
 	    = aarch64_parse_extension (with_plus.c_str (), &isa_temp, nullptr);
 
-	  if (ext_res == AARCH64_PARSE_OK)
+	  if (ext_res == AARCH_PARSE_OK)
 	    error ("arch extension %<%s%> should be prefixed by %<+%>",
 		   token);
 	  else
@@ -22753,7 +22555,7 @@ void
 aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED)
 {
   if (cfun->machine->frame.laid_out && aarch64_return_address_signing_enabled ()
-      && aarch64_ra_sign_key == AARCH64_KEY_B)
+      && aarch_ra_sign_key == AARCH_KEY_B)
 	asm_fprintf (f, "\t.cfi_b_key_frame\n");
 }
 
@@ -27163,7 +26965,7 @@ aarch64_file_end_indicate_exec_stack ()
   if (aarch64_bti_enabled ())
     feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
 
-  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE)
+  if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
     feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
 
   if (feature_1_and)
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 896b6a8ac79..9711a1ed419 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -891,7 +891,7 @@ (define_insn "*do_return"
     if (aarch64_return_address_signing_enabled ()
 	&& (TARGET_PAUTH))
       {
-	if (aarch64_ra_sign_key == AARCH64_KEY_B)
+	if (aarch_ra_sign_key == AARCH_KEY_B)
 	  ret = "retab";
 	else
 	  ret = "retaa";
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index b89b2045071..ded70bf7e39 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -21,6 +21,9 @@
 HeaderInclude
 config/aarch64/aarch64-opts.h
 
+HeaderInclude
+config/arm/aarch-common.h
+
 TargetVariable
 enum aarch64_processor selected_tune = aarch64_none
 
@@ -34,7 +37,7 @@ TargetVariable
 aarch64_feature_flags aarch64_isa_flags = 0
 
 TargetVariable
-unsigned aarch64_enable_bti = 2
+unsigned aarch_enable_bti = 2
 
 TargetVariable
 enum aarch64_key_type aarch64_ra_sign_key = AARCH64_KEY_A
@@ -164,21 +167,21 @@ Target RejectNegative Joined Var(aarch64_branch_protection_string) Save
 Use branch-protection features.
 
 msign-return-address=
-Target WarnRemoved RejectNegative Joined Enum(aarch64_ra_sign_scope_t) Var(aarch64_ra_sign_scope) Init(AARCH64_FUNCTION_NONE) Save
+Target WarnRemoved RejectNegative Joined Enum(aarch_ra_sign_scope_t) Var(aarch_ra_sign_scope) Init(AARCH_FUNCTION_NONE) Save
 Select return address signing scope.
 
 Enum
-Name(aarch64_ra_sign_scope_t) Type(enum aarch64_function_type)
+Name(aarch_ra_sign_scope_t) Type(enum aarch_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)
+Enum(aarch_ra_sign_scope_t) String(none) Value(AARCH_FUNCTION_NONE)
 
 EnumValue
-Enum(aarch64_ra_sign_scope_t) String(non-leaf) Value(AARCH64_FUNCTION_NON_LEAF)
+Enum(aarch_ra_sign_scope_t) String(non-leaf) Value(AARCH_FUNCTION_NON_LEAF)
 
 EnumValue
-Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL)
+Enum(aarch_ra_sign_scope_t) String(all) Value(AARCH_FUNCTION_ALL)
 
 mlow-precision-recip-sqrt
 Target Var(flag_mrecip_low_precision_sqrt) Optimization
diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
index ae0465159f7..17a369f7e99 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -153,4 +153,10 @@ rtx_insn *arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
 			     vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
 			     location_t loc);
 
+/* Parsing routine for branch-protection common to AArch64 and Arm.  */
+enum aarch_parse_opt_result aarch_parse_branch_protection (const char*, char**);
+
+/* Validation routine for branch-protection common to AArch64 and Arm.  */
+bool aarch_validate_mbranch_protection (const char *);
+
 #endif /* GCC_AARCH_COMMON_PROTOS_H */
diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
index 04a53d75093..6d254101f6a 100644
--- a/gcc/config/arm/aarch-common.cc
+++ b/gcc/config/arm/aarch-common.cc
@@ -36,6 +36,7 @@
 #include "expr.h"
 #include "function.h"
 #include "emit-rtl.h"
+#include "aarch-common.h"
 
 /* Return TRUE if X is either an arithmetic shift left, or
    is a multiplication by a power of two.  */
@@ -657,3 +658,187 @@ arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
 
   return saw_asm_flag ? seq : NULL;
 }
+
+#define BRANCH_PROTECT_STR_MAX 255
+extern char *accepted_branch_protection_string;
+extern enum aarch_key_type aarch_ra_sign_key;
+
+static enum aarch_parse_opt_result
+aarch_handle_no_branch_protection (char* str, char* rest)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
+  aarch_enable_bti = 0;
+  if (rest)
+    {
+      error ("unexpected %<%s%> after %<%s%>", rest, str);
+      return AARCH_PARSE_INVALID_FEATURE;
+    }
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_standard_branch_protection (char* str, char* rest)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch_ra_sign_key = AARCH_KEY_A;
+  aarch_enable_bti = 1;
+  if (rest)
+    {
+      error ("unexpected %<%s%> after %<%s%>", rest, str);
+      return AARCH_PARSE_INVALID_FEATURE;
+    }
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED,
+				 char* rest ATTRIBUTE_UNUSED)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch_ra_sign_key = AARCH_KEY_A;
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED,
+			   char* rest ATTRIBUTE_UNUSED)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_ALL;
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED,
+			    char* rest ATTRIBUTE_UNUSED)
+{
+  aarch_ra_sign_key = AARCH_KEY_B;
+  return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_bti_protection (char* str ATTRIBUTE_UNUSED,
+			     char* rest ATTRIBUTE_UNUSED)
+{
+  aarch_enable_bti = 1;
+  return AARCH_PARSE_OK;
+}
+
+static const struct aarch_branch_protect_type aarch_pac_ret_subtypes[] = {
+  { "leaf", aarch_handle_pac_ret_leaf, NULL, 0 },
+  { "b-key", aarch_handle_pac_ret_b_key, NULL, 0 },
+  { NULL, NULL, NULL, 0 }
+};
+
+static const struct aarch_branch_protect_type aarch_branch_protect_types[] = {
+  { "none", aarch_handle_no_branch_protection, NULL, 0 },
+  { "standard", aarch_handle_standard_branch_protection, NULL, 0 },
+  { "pac-ret", aarch_handle_pac_ret_protection, aarch_pac_ret_subtypes,
+    ARRAY_SIZE (aarch_pac_ret_subtypes) },
+  { "bti", aarch_handle_bti_protection, NULL, 0 },
+  { NULL, NULL, NULL, 0 }
+};
+
+/* Parses CONST_STR for branch protection features specified in
+   aarch64_branch_protect_types, and set any global variables required.  Returns
+   the parsing result and assigns LAST_STR to the last processed token from
+   CONST_STR so that it can be used for error reporting.  */
+
+enum aarch_parse_opt_result
+aarch_parse_branch_protection (const char *const_str, char** last_str)
+{
+  char *str_root = xstrdup (const_str);
+  char* token_save = NULL;
+  char *str = strtok_r (str_root, "+", &token_save);
+  enum aarch_parse_opt_result res = AARCH_PARSE_OK;
+  if (!str)
+    res = AARCH_PARSE_MISSING_ARG;
+  else
+    {
+      char *next_str = strtok_r (NULL, "+", &token_save);
+      /* Reset the branch protection features to their defaults.  */
+      aarch_handle_no_branch_protection (NULL, NULL);
+
+      while (str && res == AARCH_PARSE_OK)
+	{
+	  const aarch_branch_protect_type* type = aarch_branch_protect_types;
+	  bool found = false;
+	  /* Search for this type.  */
+	  while (type && type->name && !found && res == AARCH_PARSE_OK)
+	    {
+	      if (strcmp (str, type->name) == 0)
+		{
+		  found = true;
+		  res = type->handler (str, next_str);
+		  str = next_str;
+		  next_str = strtok_r (NULL, "+", &token_save);
+		}
+	      else
+		type++;
+	    }
+	  if (found && res == AARCH_PARSE_OK)
+	    {
+	      bool found_subtype = true;
+	      /* Loop through each token until we find one that isn't a
+		 subtype.  */
+	      while (found_subtype)
+		{
+		  found_subtype = false;
+		  const aarch_branch_protect_type *subtype = type->subtypes;
+		  /* Search for the subtype.  */
+		  while (str && subtype && subtype->name && !found_subtype
+			  && res == AARCH_PARSE_OK)
+		    {
+		      if (strcmp (str, subtype->name) == 0)
+			{
+			  found_subtype = true;
+			  res = subtype->handler (str, next_str);
+			  str = next_str;
+			  next_str = strtok_r (NULL, "+", &token_save);
+			}
+		      else
+			subtype++;
+		    }
+		}
+	    }
+	  else if (!found)
+	    res = AARCH_PARSE_INVALID_ARG;
+	}
+    }
+  /* Copy the last processed token into the argument to pass it back.
+    Used by option and attribute validation to print the offending token.  */
+  if (last_str)
+    {
+      if (str)
+	strcpy (*last_str, str);
+      else
+	*last_str = NULL;
+    }
+
+  if (res == AARCH_PARSE_OK)
+    {
+      /* If needed, alloc the accepted string then copy in const_str.
+	Used by override_option_after_change_1.  */
+      if (!accepted_branch_protection_string)
+	accepted_branch_protection_string
+	  = (char *) xmalloc (BRANCH_PROTECT_STR_MAX + 1);
+      strncpy (accepted_branch_protection_string, const_str,
+	       BRANCH_PROTECT_STR_MAX + 1);
+      /* Forcibly null-terminate.  */
+      accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0';
+    }
+  return res;
+}
+
+bool
+aarch_validate_mbranch_protection (const char *const_str)
+{
+  char *str = (char *) xmalloc (strlen (const_str));
+  enum aarch_parse_opt_result res =
+    aarch_parse_branch_protection (const_str, &str);
+  if (res == AARCH_PARSE_INVALID_ARG)
+    error ("invalid argument %<%s%> for %<-mbranch-protection=%>", str);
+  else if (res == AARCH_PARSE_MISSING_ARG)
+    error ("missing argument for %<-mbranch-protection=%>");
+  free (str);
+  return res == AARCH_PARSE_OK;
+}
diff --git a/gcc/config/arm/aarch-common.h b/gcc/config/arm/aarch-common.h
new file mode 100644
index 00000000000..c6a67f0d05c
--- /dev/null
+++ b/gcc/config/arm/aarch-common.h
@@ -0,0 +1,73 @@
+/* Types shared between arm and aarch64.
+
+   Copyright (C) 2009-2021 Free Software Foundation, Inc.
+   Contributed by Arm Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_AARCH_COMMON_H
+#define GCC_AARCH_COMMON_H
+
+/* Enum describing the various ways that the
+   aarch*_parse_{arch,tune,cpu,extension} functions can fail.
+   This way their callers can choose what kind of error to give.  */
+
+enum aarch_parse_opt_result
+{
+  AARCH_PARSE_OK,			/* Parsing was successful.  */
+  AARCH_PARSE_MISSING_ARG,		/* Missing argument.  */
+  AARCH_PARSE_INVALID_FEATURE,		/* Invalid feature modifier.  */
+  AARCH_PARSE_INVALID_ARG		/* Invalid arch, tune, cpu arg.  */
+};
+
+/* Function types -msign-return-address should sign.  */
+enum aarch_function_type {
+  /* Don't sign any function.  */
+  AARCH_FUNCTION_NONE,
+  /* Non-leaf functions.  */
+  AARCH_FUNCTION_NON_LEAF,
+  /* All functions.  */
+  AARCH_FUNCTION_ALL
+};
+
+/* The key type that -msign-return-address should use.  */
+enum aarch_key_type {
+  AARCH_KEY_A,
+  AARCH_KEY_B
+};
+
+struct aarch_branch_protect_type
+{
+  /* The type's name that the user passes to the branch-protection option
+     string.  */
+  const char* name;
+  /* Function to handle the protection type and set global variables.
+     First argument is the string token corresponding with this type and the
+     second argument is the next token in the option string.
+     Return values:
+     * AARCH_PARSE_OK: Handling was sucessful.
+     * AARCH_INVALID_ARG: The type is invalid in this context and the caller
+     should print an error.
+     * AARCH_INVALID_FEATURE: The type is invalid and the handler prints its
+     own error.  */
+  enum aarch_parse_opt_result (*handler)(char*, char*);
+  /* A list of types that can follow this type in the option string.  */
+  const struct aarch_branch_protect_type* subtypes;
+  unsigned int num_subtypes;
+};
+
+#endif /* GCC_AARCH_COMMON_H */
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 550272facd1..6e6bf147e9c 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -581,6 +581,8 @@ struct cpu_option
 extern const arch_option all_architectures[];
 extern const cpu_option all_cores[];
 
+extern enum aarch_key_type aarch_ra_sign_key;
+
 const cpu_option *arm_parse_cpu_option_name (const cpu_option *, const char *,
 					     const char *, bool = true);
 const arch_option *arm_parse_arch_option_name (const arch_option *,
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index b587561eebe..cfc8fdc4edd 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -72,6 +72,8 @@
 #include "selftest.h"
 #include "tree-vectorizer.h"
 #include "opts.h"
+#include "aarch-common.h"
+#include "aarch-common-protos.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -2413,6 +2415,11 @@ const struct tune_params arm_fa726te_tune =
   tune_params::SCHED_AUTOPREF_OFF
 };
 
+/* Key type for Pointer Authentication extension.  */
+enum aarch_key_type aarch_ra_sign_key = AARCH_KEY_A;
+
+char *accepted_branch_protection_string = NULL;
+
 /* Auto-generated CPU, FPU and architecture tables.  */
 #include "arm-cpu-data.h"
 
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index 3209b6c623b..500ff06bed4 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -21,6 +21,15 @@
 HeaderInclude
 config/arm/arm-opts.h
 
+HeaderInclude
+config/arm/aarch-common.h
+
+TargetVariable
+enum aarch_function_type aarch_ra_sign_scope = AARCH_FUNCTION_NONE
+
+TargetVariable
+unsigned aarch_enable_bti = 0
+
 Enum
 Name(tls_type) Type(enum arm_tls_type)
 TLS dialect to use:
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 12/15 V5] arm: implement bti injection
  2022-12-14 17:03                 ` Richard Earnshaw
@ 2022-12-22 17:13                   ` Andrea Corallo
  2023-01-11 15:08                     ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2022-12-22 17:13 UTC (permalink / raw)
  To: Richard Earnshaw
  Cc: Kyrylo Tkachov, Richard Earnshaw, nd, Andrea Corallo via Gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4493 bytes --]

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

> On 14/12/2022 17:00, Richard Earnshaw via Gcc-patches wrote:
>> On 14/12/2022 16:40, Andrea Corallo via Gcc-patches wrote:
>>> Hi Richard,
>>>
>>> thanks for reviewing.
>>>
>>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>>
>>>> On 28/10/2022 17:40, Andrea Corallo via Gcc-patches wrote:
>>>>> Hi all,
>>>>> please find attached the third iteration of this patch addresing
>>>>> review
>>>>> comments.
>>>>> Thanks
>>>>>     Andrea
>>>>>
>>>>
>>>> @@ -23374,12 +23374,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
>>>>     return "";
>>>>   }
>>>>
>>>> -static bool
>>>> -aarch_bti_enabled ()
>>>> -{
>>>> -  return false;
>>>> -}
>>>> -
>>>>   /* Generate the prologue instructions for entry into an ARM or Thumb-2
>>>>      function.  */
>>>>   void
>>>> @@ -32992,6 +32986,61 @@ arm_current_function_pac_enabled_p (void)
>>>>                 && !crtl->is_leaf));
>>>>   }
>>>>
>>>> +/* Return TRUE if Branch Target Identification Mechanism is
>>>> enabled.  */
>>>> +bool
>>>> +aarch_bti_enabled (void)
>>>> +{
>>>> +  return aarch_enable_bti == 1;
>>>> +}
>>>>
>>>> See comment in earlier patch about the location of this function
>>>> moving.   Can aarch_enable_bti take values other than 0 and 1?
>>>
>>> Yes default is 2.
>> It shouldn't be by this point, because, hopefully you've gone
>> through the equivalent of this hunk (from aarch64) somewhere in
>> arm_override_options:
>>     if (aarch_enable_bti == 2)
>>       {
>>   #ifdef TARGET_ENABLE_BTI
>>         aarch_enable_bti = 1;
>>   #else
>>         aarch_enable_bti = 0;
>>   #endif
>>       }
>> And after this point the '2' should never be seen again.  We use
>> this trick to permit the user to force a default that differs from
>> the configuration.
>> However, I don't see a hunk to do this in patch 3, so perhaps that
>> needs updating to fix this.
>
> I've just remembered that the above is to support a configure-time
> option of the compiler to enable branch protection.  But perhaps we
> don't want to have that in AArch32, in which case it would be better
> not to have the default be 2 anyway, just default to off (0).
>
> R.

Done in 1/15 (needs approval again now).

>>
>>> [...]
>>>
>>>> +  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) ==
>>>> UNSPEC_BTI_NOP;
>>>>
>>>> I'm not sure where this crept in, but UNSPEC and UNSPEC_VOLATILE have
>>>> separate enums in the backend, so UNSPEC_BIT_NOP should really be
>>>> VUNSPEC_BTI_NOP and defined in the enum "unspecv".
>>>
>>> Done
>>>
>>>> +aarch_pac_insn_p (rtx x)
>>>> +{
>>>> +  if (!x || !INSN_P (x))
>>>> +    return false;
>>>> +
>>>> +  rtx pat = PATTERN (x);
>>>> +
>>>> +  if (GET_CODE (pat) == SET)
>>>> +    {
>>>> +      rtx tmp = XEXP (pat, 1);
>>>> +      if (tmp
>>>> +      && GET_CODE (tmp) == UNSPEC
>>>> +      && (XINT (tmp, 1) == UNSPEC_PAC_NOP
>>>> +          || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
>>>> +    return true;
>>>> +    }
>>>> +
>>>>
>>>> This will also need updating (see review on earlier patch) because
>>>> PACBTI needs to be unspec_volatile, while PAC doesn't.
>>>
>>> Done
>>>
>>>> +/* The following two functions are for code compatibility with aarch64
>>>> +   code, this even if in arm we have only one bti instruction.  */
>>>> +
>>>>
>>>> I'd just write
>>>>   /* Target specific mapping for aarch_gen_bti_c and
>>>>   aarch_gen_bti_j. For Arm, both of these map to a simple BTI
>>>> instruction.  */
>>>
>>> Done
>>>
>>>>
>>>> @@ -162,6 +162,7 @@ (define_c_enum "unspec" [
>>>>     UNSPEC_PAC_NOP    ; Represents PAC signing LR
>>>>     UNSPEC_PACBTI_NOP    ; Represents PAC signing LR + valid landing pad
>>>>     UNSPEC_AUT_NOP    ; Represents PAC verifying LR
>>>> +  UNSPEC_BTI_NOP    ; Represent BTI
>>>>   ])
>>>>
>>>> BTI is an unspec volatile, so this should be in the "vunspec" enum and
>>>> renamed accordingly (see above).
>>>
>>> Done.
>>>
>>> Please find attached the updated version of this patch.
>>>
>>> BR
>>>
>>>    Andrea
>>>
>> Apart from that, this is OK.
>> R.

Cool, attached the updated patch.

Also I added some error handling not to run the bti pass if the march
selected does not support bti.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-12-15-arm-implement-bti-injection.patch --]
[-- Type: text/plain, Size: 11969 bytes --]

From afd54e771268733b7f1f4945c9b2cdabe1d6a6e5 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 7 Apr 2022 11:51:56 +0200
Subject: [PATCH] [PATCH 12/15] arm: implement bti injection

Hi all,

this patch enables Branch Target Identification Armv8.1-M Mechanism
[1].

This is achieved by using the bti pass made common with Aarch64.

The pass iterates through the instructions and adds the necessary BTI
instructions at the beginning of every function and at every landing
pads targeted by indirect jumps.

Best Regards

  Andrea

[1]
<https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* config.gcc (arm*-*-*): Add 'aarch-bti-insert.o' object.
	* config/arm/arm-protos.h: Update.
	* config/arm/aarch-common-protos.h: Declare
	'aarch_bti_arch_check'.
	* config/arm/arm.cc (aarch_bti_enabled) Update.
	(aarch_bti_j_insn_p, aarch_pac_insn_p, aarch_gen_bti_c)
	(aarch_gen_bti_j, aarch_bti_arch_check): New functions.
	* config/arm/arm.md (bti_nop): New insn.
	* config/arm/t-arm (PASSES_EXTRA): Add 'arm-passes.def'.
	(aarch-bti-insert.o): New target.
	* config/arm/unspecs.md (VUNSPEC_BTI_NOP): New unspec.
	* config/arm/aarch-bti-insert.cc (rest_of_insert_bti): Verify arch
	compatibility.
	* config/arm/arm-passes.def: New file.
	* config/aarch64/aarch64.cc (aarch_bti_arch_check): New function.
	* config/arm/aarch-bti-insert.cc (gate): Make use of
	'aarch_bti_arch_check'.

gcc/testsuite/ChangeLog

2022-04-07  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/bti-1.c: New testcase.
	* gcc.target/arm/bti-2.c: Likewise.
---
 gcc/config.gcc                       |  2 +-
 gcc/config/aarch64/aarch64.cc        |  4 ++
 gcc/config/arm/aarch-bti-insert.cc   |  7 +++-
 gcc/config/arm/aarch-common-protos.h |  1 +
 gcc/config/arm/arm-passes.def        | 21 ++++++++++
 gcc/config/arm/arm-protos.h          |  2 +
 gcc/config/arm/arm.cc                | 60 +++++++++++++++++++++++++++-
 gcc/config/arm/arm.md                |  7 ++++
 gcc/config/arm/t-arm                 | 10 +++++
 gcc/config/arm/unspecs.md            |  1 +
 gcc/testsuite/gcc.target/arm/bti-1.c | 12 ++++++
 gcc/testsuite/gcc.target/arm/bti-2.c | 58 +++++++++++++++++++++++++++
 12 files changed, 181 insertions(+), 4 deletions(-)
 create mode 100644 gcc/config/arm/arm-passes.def
 create mode 100644 gcc/testsuite/gcc.target/arm/bti-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/bti-2.c

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 86abcd26185..f578b88dd49 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -351,7 +351,7 @@ arc*-*-*)
 	;;
 arm*-*-*)
 	cpu_type=arm
-	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
+	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o aarch-bti-insert.o"
 	extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
 	target_type_format_char='%'
 	c_target_objs="arm-c.o"
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 37c4f798abc..737bb4f0532 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -8806,6 +8806,10 @@ aarch64_return_address_signing_enabled (void)
 	      && known_ge (cfun->machine->frame.reg_offset[LR_REGNUM], 0)));
 }
 
+/* Only used by the arm backend.  */
+void aarch_bti_arch_check (void)
+{}
+
 /* Return TRUE if Branch Target Identification Mechanism is enabled.  */
 bool
 aarch_bti_enabled (void)
diff --git a/gcc/config/arm/aarch-bti-insert.cc b/gcc/config/arm/aarch-bti-insert.cc
index 2d1d2e334a9..30d5bfcb77b 100644
--- a/gcc/config/arm/aarch-bti-insert.cc
+++ b/gcc/config/arm/aarch-bti-insert.cc
@@ -190,7 +190,12 @@ public:
   /* opt_pass methods: */
   virtual bool gate (function *)
     {
-      return aarch_bti_enabled ();
+      if (aarch_bti_enabled ())
+        {
+          aarch_bti_arch_check ();
+          return true;
+        }
+      return false;
     }
 
   virtual unsigned int execute (function *)
diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
index 374982752ad..f795730a59c 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -42,6 +42,7 @@ extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
 extern int arm_no_early_mul_dep (rtx, rtx);
 extern int arm_no_early_store_addr_dep (rtx, rtx);
 extern bool arm_rtx_shift_left_p (rtx);
+extern void aarch_bti_arch_check (void);
 extern bool aarch_bti_enabled (void);
 extern bool aarch_bti_j_insn_p (rtx_insn *);
 extern bool aarch_pac_insn_p (rtx);
diff --git a/gcc/config/arm/arm-passes.def b/gcc/config/arm/arm-passes.def
new file mode 100644
index 00000000000..71d6b563640
--- /dev/null
+++ b/gcc/config/arm/arm-passes.def
@@ -0,0 +1,21 @@
+/* Arm-specific passes declarations.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   Contributed by Arm Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index d97a1c3bf56..61c2bb7b526 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -24,6 +24,8 @@
 
 #include "sbitmap.h"
 
+rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
+
 extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *);
 extern int use_return_insn (int, rtx);
 extern bool use_simple_return_p (void);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 4af809373e4..0f105f60c08 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -33108,13 +33108,69 @@ arm_current_function_pac_enabled_p (void)
               && !crtl->is_leaf));
 }
 
+/* Raise an error if the current target arch is not bti compatible.  */
+void aarch_bti_arch_check (void)
+{
+  if (!arm_arch8m_main)
+    error ("This architecture does not support branch protection instructions");
+}
+
 /* Return TRUE if Branch Target Identification Mechanism is enabled.  */
-static bool
-aarch_bti_enabled ()
+bool
+aarch_bti_enabled (void)
+{
+  return aarch_enable_bti != 0;
+}
+
+/* Check if INSN is a BTI J insn.  */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+  if (!insn || !INSN_P (insn))
+    return false;
+
+  rtx pat = PATTERN (insn);
+  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == VUNSPEC_BTI_NOP;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction.  */
+bool
+aarch_pac_insn_p (rtx x)
 {
+  if (!x || !INSN_P (x))
+    return false;
+
+  rtx pat = PATTERN (x);
+
+  if (GET_CODE (pat) == SET)
+    {
+      rtx tmp = XEXP (pat, 1);
+      if (tmp
+	  && ((GET_CODE (tmp) == UNSPEC
+               && XINT (tmp, 1) == UNSPEC_PAC_NOP)
+              || (GET_CODE (tmp) == UNSPEC_VOLATILE
+                  && XINT (tmp, 1) == VUNSPEC_PACBTI_NOP)))
+	return true;
+    }
+
   return false;
 }
 
+ /* Target specific mapping for aarch_gen_bti_c and aarch_gen_bti_j.
+    For Arm, both of these map to a simple BTI instruction.  */
+
+rtx
+aarch_gen_bti_c (void)
+{
+  return gen_bti_nop ();
+}
+
+rtx
+aarch_gen_bti_j (void)
+{
+  return gen_bti_nop ();
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index d624cfae5b8..36062292b90 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -13001,6 +13001,13 @@ (define_insn "aut_nop"
   "aut\t%|ip, %|lr, %|sp"
   [(set_attr "conds" "unconditional")])
 
+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] VUNSPEC_BTI_NOP)]
+  "arm_arch8m_main"
+  "bti"
+  [(set_attr "conds" "unconditional")
+   (set_attr "type" "nop")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index 041cc6ec045..683342cb528 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -175,3 +175,13 @@ arm-d.o: $(srcdir)/config/arm/arm-d.cc
 arm-common.o: arm-cpu-cdata.h
 
 driver-arm.o: arm-native.h
+
+PASSES_EXTRA += $(srcdir)/config/arm/arm-passes.def
+
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.cc \
+    $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+    dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+    output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+    $(CONTEXT_H) $(TREE_PASS_H) regrename.h
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/arm/aarch-bti-insert.cc
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 370f0b12da1..93447a8ce9d 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -257,6 +257,7 @@ (define_c_enum "unspecv" [
 			; instruction.
   VUNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
   VUNSPEC_AUT_NOP	; Represents PAC verifying LR
+  VUNSPEC_BTI_NOP	; Represent BTI
 ])
 
 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/bti-1.c b/gcc/testsuite/gcc.target/arm/bti-1.c
new file mode 100644
index 00000000000..79dd8010d2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-1.c
@@ -0,0 +1,12 @@
+/* Check that GCC does bti instruction.  */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
+
+int
+main (void)
+{
+  return 0;
+}
+
+/* { dg-final { scan-assembler "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/bti-2.c b/gcc/testsuite/gcc.target/arm/bti-2.c
new file mode 100644
index 00000000000..33910563849
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/bti-2.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* -Os to create jump table.  */
+/* { dg-options "-Os" } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
+
+extern int f1 (void);
+extern int f2 (void);
+extern int f3 (void);
+extern int f4 (void);
+extern int f5 (void);
+extern int f6 (void);
+extern int f7 (void);
+extern int f8 (void);
+extern int f9 (void);
+extern int f10 (void);
+
+int (*ptr) (void);
+
+int
+f_jump_table (int y, int n)
+{
+  int i;
+  for (i = 0; i < n ;i ++)
+  {
+    switch (y)
+      {
+      case 0 : ptr = f1; break;
+      case 1 : ptr = f2; break;
+      case 2 : ptr = f3; break;
+      case 3 : ptr = f4; break;
+      case 4 : ptr = f5; break;
+      case 5 : ptr = f6; break;
+      case 6 : ptr = f7; break;
+      case 7 : ptr = f8; break;
+      case 8 : ptr = f9; break;
+      case 9 : ptr = f10; break;
+      default: break;
+      }
+    y += ptr ();
+  }
+  return (y == 0)? y+1:4;
+}
+
+int
+f_label_address ()
+{
+  static void * addr = &&lab1;
+  goto *addr;
+lab1:
+  addr = &&lab2;
+  return 1;
+lab2:
+  addr = &&lab1;
+  return 2;
+}
+
+/* { dg-final { scan-assembler-times "bti" 15 } } */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2022-10-26  8:49           ` Andrea Corallo
  2022-11-08 14:57             ` Richard Earnshaw
@ 2023-01-09 14:58             ` Andrea Corallo
  2023-01-09 15:57               ` Richard Earnshaw
  2023-01-09 16:48               ` Richard Earnshaw
  1 sibling, 2 replies; 66+ messages in thread
From: Andrea Corallo @ 2023-01-09 14:58 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd, Richard Earnshaw

Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:

> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>
>> On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
>>> 
>>>> -----Original Message-----
>>>> From: Andrea Corallo <andrea.corallo@arm.com>
>>>> Sent: Tuesday, September 27, 2022 11:06 AM
>>>> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
>>>> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
>>>> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>> popping if necessary
>>>>
>>>> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
>>>>
>>>>> Hi Andrea,
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Gcc-patches <gcc-patches-
>>>>>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>>>>>> Corallo via Gcc-patches
>>>>>> Sent: Friday, August 12, 2022 4:34 PM
>>>>>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>>>>>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>> popping
>>>>>> if necessary
>>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>>>>>> pointer as CFA reg when popping if this is necessary.
>>>>>>
>>>>>
>>>>>  From what I can tell from similar functions this is correct, but could you
>>>> elaborate on why this change is needed for my understanding please?
>>>>> Thanks,
>>>>> Kyrill
>>>>
>>>> Hi Kyrill,
>>>>
>>>> sure, if the frame pointer was set, than it is the current CFA register.
>>>> If we request to adjust the current CFA register offset indicating it
>>>> being SP (while it's actually FP) that is indeed not correct and the
>>>> incoherence we will be detected by an assertion in the dwarf emission
>>>> machinery.
>>> Thanks,  the patch is ok
>>> Kyrill
>>> 
>>>>
>>>> Best Regards
>>>>
>>>>    Andrea
>>
>> Hmm, wait.  Why would a multi-reg pop be updating the stack pointer?
>
> Hi Richard,
>
> not sure I understand, isn't any pop updating SP by definition?


Back on this,

compiling:

=======
int i;

void foo (int);

int bar()
{
  foo (i);
  return 0;
}
=======

With -march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb -O0 -g

Produces the following asm for bar.

bar:
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 1, uses_anonymous_args = 0
	pac	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	ldr	r3, .L3
	ldr	r3, [r3]
	mov	r0, r3
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

The offending instruction causing the ICE (without this patch) when
emitting dwarf is "pop {r3, r7, ip, lr}".

The current CFA reg when emitting the multipop is R7 (the frame
pointer).  If is not the multipop that has the duty to restore SP as
current CFA here which other instruction should do it?

Best Regards

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2023-01-09 14:58             ` Andrea Corallo
@ 2023-01-09 15:57               ` Richard Earnshaw
  2023-01-09 16:48               ` Richard Earnshaw
  1 sibling, 0 replies; 66+ messages in thread
From: Richard Earnshaw @ 2023-01-09 15:57 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw



On 09/01/2023 14:58, Andrea Corallo via Gcc-patches wrote:
> Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> 
>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>
>>> On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
>>>>
>>>>> -----Original Message-----
>>>>> From: Andrea Corallo <andrea.corallo@arm.com>
>>>>> Sent: Tuesday, September 27, 2022 11:06 AM
>>>>> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
>>>>> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
>>>>> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>>> popping if necessary
>>>>>
>>>>> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
>>>>>
>>>>>> Hi Andrea,
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Gcc-patches <gcc-patches-
>>>>>>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>>>>>>> Corallo via Gcc-patches
>>>>>>> Sent: Friday, August 12, 2022 4:34 PM
>>>>>>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>>>>>>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>>>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>>> popping
>>>>>>> if necessary
>>>>>>>
>>>>>>> Hi all,
>>>>>>>
>>>>>>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>>>>>>> pointer as CFA reg when popping if this is necessary.
>>>>>>>
>>>>>>
>>>>>>   From what I can tell from similar functions this is correct, but could you
>>>>> elaborate on why this change is needed for my understanding please?
>>>>>> Thanks,
>>>>>> Kyrill
>>>>>
>>>>> Hi Kyrill,
>>>>>
>>>>> sure, if the frame pointer was set, than it is the current CFA register.
>>>>> If we request to adjust the current CFA register offset indicating it
>>>>> being SP (while it's actually FP) that is indeed not correct and the
>>>>> incoherence we will be detected by an assertion in the dwarf emission
>>>>> machinery.
>>>> Thanks,  the patch is ok
>>>> Kyrill
>>>>
>>>>>
>>>>> Best Regards
>>>>>
>>>>>     Andrea
>>>
>>> Hmm, wait.  Why would a multi-reg pop be updating the stack pointer?
>>
>> Hi Richard,
>>
>> not sure I understand, isn't any pop updating SP by definition?
> 
> 
> Back on this,
> 
> compiling:
> 
> =======
> int i;
> 
> void foo (int);
> 
> int bar()
> {
>    foo (i);
>    return 0;
> }
> =======
> 
> With -march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb -O0 -g
> 
> Produces the following asm for bar.
> 
> bar:
> 	@ args = 0, pretend = 0, frame = 0
> 	@ frame_needed = 1, uses_anonymous_args = 0
> 	pac	ip, lr, sp
> 	push	{r3, r7, ip, lr}
> 	add	r7, sp, #0
> 	ldr	r3, .L3
> 	ldr	r3, [r3]
> 	mov	r0, r3
> 	bl	foo
> 	movs	r3, #0
> 	mov	r0, r3
> 	pop	{r3, r7, ip, lr}
> 	aut	ip, lr, sp
> 	bx	lr
> 
> The offending instruction causing the ICE (without this patch) when
> emitting dwarf is "pop {r3, r7, ip, lr}".
> 
> The current CFA reg when emitting the multipop is R7 (the frame
> pointer).  If is not the multipop that has the duty to restore SP as
> current CFA here which other instruction should do it?

Ah, OK.  I think this is a special case, though, because in this 
specific case the frame pointer (r7) and the stack pointer point to the 
same place.  This means that in the epilogue we don't start by restoring 
SP from FP (at which point we tell the dwarf code that the frame is back 
in SP again).

For example, if I have:


int i;

void foo (int, int*);

int bar()
{
   int j[10];
   foo (i,j);
   return 0;
}


then the epilogue sequence starts with:

         adds    r7, r7, #40
         .cfi_def_cfa_offset 8
         mov     sp, r7
         .cfi_def_cfa_register 13

And then the pop works correctly as-is.

But I'm not convinced that this is enough anyway, you cause the compiler 
to output a directive that changes the CFA pointer back to r13, but you 
don't output anything that changes the CFA offset.  So I think this 
means that the CFA state machine ends up pointing to the wrong location, 
but it's hard to tell as you haven't shown the CFA directives in your 
example above.

> 
> Best Regards
> 
>    Andrea

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2023-01-09 14:58             ` Andrea Corallo
  2023-01-09 15:57               ` Richard Earnshaw
@ 2023-01-09 16:48               ` Richard Earnshaw
  2023-01-09 17:22                 ` Richard Earnshaw
  1 sibling, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2023-01-09 16:48 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw



On 09/01/2023 14:58, Andrea Corallo via Gcc-patches wrote:
> Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> 
>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>
>>> On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
>>>>
>>>>> -----Original Message-----
>>>>> From: Andrea Corallo <andrea.corallo@arm.com>
>>>>> Sent: Tuesday, September 27, 2022 11:06 AM
>>>>> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
>>>>> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
>>>>> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>>> popping if necessary
>>>>>
>>>>> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
>>>>>
>>>>>> Hi Andrea,
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Gcc-patches <gcc-patches-
>>>>>>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>>>>>>> Corallo via Gcc-patches
>>>>>>> Sent: Friday, August 12, 2022 4:34 PM
>>>>>>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>>>>>>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>>>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>>> popping
>>>>>>> if necessary
>>>>>>>
>>>>>>> Hi all,
>>>>>>>
>>>>>>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>>>>>>> pointer as CFA reg when popping if this is necessary.
>>>>>>>
>>>>>>
>>>>>>   From what I can tell from similar functions this is correct, but could you
>>>>> elaborate on why this change is needed for my understanding please?
>>>>>> Thanks,
>>>>>> Kyrill
>>>>>
>>>>> Hi Kyrill,
>>>>>
>>>>> sure, if the frame pointer was set, than it is the current CFA register.
>>>>> If we request to adjust the current CFA register offset indicating it
>>>>> being SP (while it's actually FP) that is indeed not correct and the
>>>>> incoherence we will be detected by an assertion in the dwarf emission
>>>>> machinery.
>>>> Thanks,  the patch is ok
>>>> Kyrill
>>>>
>>>>>
>>>>> Best Regards
>>>>>
>>>>>     Andrea
>>>
>>> Hmm, wait.  Why would a multi-reg pop be updating the stack pointer?
>>
>> Hi Richard,
>>
>> not sure I understand, isn't any pop updating SP by definition?
> 
> 
> Back on this,
> 
> compiling:
> 
> =======
> int i;
> 
> void foo (int);
> 
> int bar()
> {
>    foo (i);
>    return 0;
> }
> =======
> 
> With -march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb -O0 -g
> 
> Produces the following asm for bar.
> 
> bar:
> 	@ args = 0, pretend = 0, frame = 0
> 	@ frame_needed = 1, uses_anonymous_args = 0
> 	pac	ip, lr, sp
> 	push	{r3, r7, ip, lr}
> 	add	r7, sp, #0
> 	ldr	r3, .L3
> 	ldr	r3, [r3]
> 	mov	r0, r3
> 	bl	foo
> 	movs	r3, #0
> 	mov	r0, r3
> 	pop	{r3, r7, ip, lr}
> 	aut	ip, lr, sp
> 	bx	lr
> 
> The offending instruction causing the ICE (without this patch) when
> emitting dwarf is "pop {r3, r7, ip, lr}".
> 
> The current CFA reg when emitting the multipop is R7 (the frame
> pointer).  If is not the multipop that has the duty to restore SP as
> current CFA here which other instruction should do it?
> 

Digging a bit deeper, I'm now even more confused.  arm_expand_epilogue 
contains (parphrasing the code):

  if frame_pointer_needed
    {
      if arm
        {}
      else
        {
          if adjust
            r7 += adjust
          mov sp, r7	// Reset CFA to SP
        }
     }

so there should always be a move of r7 into SP, even if this is strictly 
redundant.  I don't understand why this doesn't happen for your 
testcase.  Can you dig a bit deeper?  I wonder if we've (probably 
incorrectly) assumed that this function doesn't need an epilogue but can 
use a simple return?  I don't think we should do that when 
authentication is needed: a simple return should really be one instruction.

> Best Regards
> 
>    Andrea

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2023-01-09 16:48               ` Richard Earnshaw
@ 2023-01-09 17:22                 ` Richard Earnshaw
  2023-01-11  9:55                   ` Andrea Corallo
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Earnshaw @ 2023-01-09 17:22 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw



On 09/01/2023 16:48, Richard Earnshaw via Gcc-patches wrote:
> 
> 
> On 09/01/2023 14:58, Andrea Corallo via Gcc-patches wrote:
>> Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>>
>>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>>
>>>> On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Andrea Corallo <andrea.corallo@arm.com>
>>>>>> Sent: Tuesday, September 27, 2022 11:06 AM
>>>>>> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
>>>>>> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
>>>>>> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg 
>>>>>> when
>>>>>> popping if necessary
>>>>>>
>>>>>> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
>>>>>>
>>>>>>> Hi Andrea,
>>>>>>>
>>>>>>>> -----Original Message-----
>>>>>>>> From: Gcc-patches <gcc-patches-
>>>>>>>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>>>>>>>> Corallo via Gcc-patches
>>>>>>>> Sent: Friday, August 12, 2022 4:34 PM
>>>>>>>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>>>>>>>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>>>>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>>>> popping
>>>>>>>> if necessary
>>>>>>>>
>>>>>>>> Hi all,
>>>>>>>>
>>>>>>>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>>>>>>>> pointer as CFA reg when popping if this is necessary.
>>>>>>>>
>>>>>>>
>>>>>>>   From what I can tell from similar functions this is correct, 
>>>>>>> but could you
>>>>>> elaborate on why this change is needed for my understanding please?
>>>>>>> Thanks,
>>>>>>> Kyrill
>>>>>>
>>>>>> Hi Kyrill,
>>>>>>
>>>>>> sure, if the frame pointer was set, than it is the current CFA 
>>>>>> register.
>>>>>> If we request to adjust the current CFA register offset indicating it
>>>>>> being SP (while it's actually FP) that is indeed not correct and the
>>>>>> incoherence we will be detected by an assertion in the dwarf emission
>>>>>> machinery.
>>>>> Thanks,  the patch is ok
>>>>> Kyrill
>>>>>
>>>>>>
>>>>>> Best Regards
>>>>>>
>>>>>>     Andrea
>>>>
>>>> Hmm, wait.  Why would a multi-reg pop be updating the stack pointer?
>>>
>>> Hi Richard,
>>>
>>> not sure I understand, isn't any pop updating SP by definition?
>>
>>
>> Back on this,
>>
>> compiling:
>>
>> =======
>> int i;
>>
>> void foo (int);
>>
>> int bar()
>> {
>>    foo (i);
>>    return 0;
>> }
>> =======
>>
>> With -march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb 
>> -O0 -g
>>
>> Produces the following asm for bar.
>>
>> bar:
>>     @ args = 0, pretend = 0, frame = 0
>>     @ frame_needed = 1, uses_anonymous_args = 0
>>     pac    ip, lr, sp
>>     push    {r3, r7, ip, lr}
>>     add    r7, sp, #0
>>     ldr    r3, .L3
>>     ldr    r3, [r3]
>>     mov    r0, r3
>>     bl    foo
>>     movs    r3, #0
>>     mov    r0, r3
>>     pop    {r3, r7, ip, lr}
>>     aut    ip, lr, sp
>>     bx    lr
>>
>> The offending instruction causing the ICE (without this patch) when
>> emitting dwarf is "pop {r3, r7, ip, lr}".
>>
>> The current CFA reg when emitting the multipop is R7 (the frame
>> pointer).  If is not the multipop that has the duty to restore SP as
>> current CFA here which other instruction should do it?
>>
> 
> Digging a bit deeper, I'm now even more confused.  arm_expand_epilogue 
> contains (parphrasing the code):
> 
>   if frame_pointer_needed
>     {
>       if arm
>         {}
>       else
>         {
>           if adjust
>             r7 += adjust
>           mov sp, r7    // Reset CFA to SP
>         }
>      }
> 
> so there should always be a move of r7 into SP, even if this is strictly 
> redundant.  I don't understand why this doesn't happen for your 
> testcase.  Can you dig a bit deeper?  I wonder if we've (probably 
> incorrectly) assumed that this function doesn't need an epilogue but can 
> use a simple return?  I don't think we should do that when 
> authentication is needed: a simple return should really be one instruction.
> 

So I strongly suspect the real problem here is that use_return_insn () 
in arm.cc needs to be updated to return false when using pointer 
authentication.  The specification for this function says that a return 
can be done in one instruction; and clearly when we need authentication 
more than one is needed.

R.

>> Best Regards
>>
>>    Andrea
> 
> R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary
  2023-01-09 17:22                 ` Richard Earnshaw
@ 2023-01-11  9:55                   ` Andrea Corallo
  0 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2023-01-11  9:55 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, nd, Richard Earnshaw

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

> On 09/01/2023 16:48, Richard Earnshaw via Gcc-patches wrote:
>> On 09/01/2023 14:58, Andrea Corallo via Gcc-patches wrote:
>>> Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>>>
>>>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>>>
>>>>> On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Andrea Corallo <andrea.corallo@arm.com>
>>>>>>> Sent: Tuesday, September 27, 2022 11:06 AM
>>>>>>> To: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
>>>>>>> Cc: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>; Richard
>>>>>>> Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>>>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA
>>>>>>> reg when
>>>>>>> popping if necessary
>>>>>>>
>>>>>>> Kyrylo Tkachov <Kyrylo.Tkachov@arm.com> writes:
>>>>>>>
>>>>>>>> Hi Andrea,
>>>>>>>>
>>>>>>>>> -----Original Message-----
>>>>>>>>> From: Gcc-patches <gcc-patches-
>>>>>>>>> bounces+kyrylo.tkachov=arm.com@gcc.gnu.org> On Behalf Of Andrea
>>>>>>>>> Corallo via Gcc-patches
>>>>>>>>> Sent: Friday, August 12, 2022 4:34 PM
>>>>>>>>> To: Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
>>>>>>>>> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>
>>>>>>>>> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>>>>>> popping
>>>>>>>>> if necessary
>>>>>>>>>
>>>>>>>>> Hi all,
>>>>>>>>>
>>>>>>>>> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
>>>>>>>>> pointer as CFA reg when popping if this is necessary.
>>>>>>>>>
>>>>>>>>
>>>>>>>>   From what I can tell from similar functions this is correct,
>>>>>>>> but could you
>>>>>>> elaborate on why this change is needed for my understanding please?
>>>>>>>> Thanks,
>>>>>>>> Kyrill
>>>>>>>
>>>>>>> Hi Kyrill,
>>>>>>>
>>>>>>> sure, if the frame pointer was set, than it is the current CFA
>>>>>>> register.
>>>>>>> If we request to adjust the current CFA register offset indicating it
>>>>>>> being SP (while it's actually FP) that is indeed not correct and the
>>>>>>> incoherence we will be detected by an assertion in the dwarf emission
>>>>>>> machinery.
>>>>>> Thanks,  the patch is ok
>>>>>> Kyrill
>>>>>>
>>>>>>>
>>>>>>> Best Regards
>>>>>>>
>>>>>>>     Andrea
>>>>>
>>>>> Hmm, wait.  Why would a multi-reg pop be updating the stack pointer?
>>>>
>>>> Hi Richard,
>>>>
>>>> not sure I understand, isn't any pop updating SP by definition?
>>>
>>>
>>> Back on this,
>>>
>>> compiling:
>>>
>>> =======
>>> int i;
>>>
>>> void foo (int);
>>>
>>> int bar()
>>> {
>>>    foo (i);
>>>    return 0;
>>> }
>>> =======
>>>
>>> With -march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf
>>> -mthumb -O0 -g
>>>
>>> Produces the following asm for bar.
>>>
>>> bar:
>>>     @ args = 0, pretend = 0, frame = 0
>>>     @ frame_needed = 1, uses_anonymous_args = 0
>>>     pac    ip, lr, sp
>>>     push    {r3, r7, ip, lr}
>>>     add    r7, sp, #0
>>>     ldr    r3, .L3
>>>     ldr    r3, [r3]
>>>     mov    r0, r3
>>>     bl    foo
>>>     movs    r3, #0
>>>     mov    r0, r3
>>>     pop    {r3, r7, ip, lr}
>>>     aut    ip, lr, sp
>>>     bx    lr
>>>
>>> The offending instruction causing the ICE (without this patch) when
>>> emitting dwarf is "pop {r3, r7, ip, lr}".
>>>
>>> The current CFA reg when emitting the multipop is R7 (the frame
>>> pointer).  If is not the multipop that has the duty to restore SP as
>>> current CFA here which other instruction should do it?
>>>
>> Digging a bit deeper, I'm now even more confused. 
>> arm_expand_epilogue contains (parphrasing the code):
>>   if frame_pointer_needed
>>     {
>>       if arm
>>         {}
>>       else
>>         {
>>           if adjust
>>             r7 += adjust
>>           mov sp, r7    // Reset CFA to SP
>>         }
>>      }
>> so there should always be a move of r7 into SP, even if this is
>> strictly redundant.  I don't understand why this doesn't happen for
>> your testcase.  Can you dig a bit deeper?  I wonder if we've
>> (probably incorrectly) assumed that this function doesn't need an
>> epilogue but can use a simple return?  I don't think we should do
>> that when authentication is needed: a simple return should really be
>> one instruction.
>> 
>
> So I strongly suspect the real problem here is that use_return_insn ()
> in arm.cc needs to be updated to return false when using pointer
> authentication.  The specification for this function says that a
> return can be done in one instruction; and clearly when we need
> authentication more than one is needed.
>
> R.

So yes I agree with your analysis.  I'm respinning 10/15 to include your
suggestion and I believe we can just drop this patch.

Thanks

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 10/15 V7] arm: Implement cortex-M return signing address codegen
  2022-12-14 16:45                     ` Richard Earnshaw
@ 2023-01-11  9:58                       ` Andrea Corallo
  2023-01-11 10:39                         ` Richard Earnshaw
  0 siblings, 1 reply; 66+ messages in thread
From: Andrea Corallo @ 2023-01-11  9:58 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

[-- Attachment #1: Type: text/plain, Size: 235 bytes --]

Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:

[...]

>
> Otherwise ok with that change.
>
> R.

Minor respin of this patch addressing the suggestion to have
'use_return_insn' return zero when PAC is enabled.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-10-15-arm-Implement-cortex-M-return-signing-ad.patch --]
[-- Type: text/plain, Size: 22754 bytes --]

From 0a894f73fc09be865b7a7cb205e871bf82f8abba Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Thu, 20 Jan 2022 15:36:23 +0100
Subject: [PATCH] [PATCH 10/15] arm: Implement cortex-M return signing address
 codegen

Hi all,

this patch enables address return signature and verification based on
Armv8.1-M Pointer Authentication [1].

To sign the return address, we use the PAC R12, LR, SP instruction
upon function entry.  This is signing LR using SP and storing the
result in R12.  R12 will be pushed into the stack.

During function epilogue R12 will be popped and AUT R12, LR, SP will
be used to verify that the content of LR is still valid before return.

Here an example of PAC instrumented function prologue and epilogue:

void foo (void);

int main()
{
  foo ();
  return 0;
}

Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
-mthumb' translates into:

main:
	pac	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

The patch also takes care of generating a PACBTI instruction in place
of the sequence BTI+PAC when Branch Target Identification is enabled
contextually.

Ex. the previous example compiled with '-march=armv8.1-m.main
-mbranch-protection=pac-ret+bti -mthumb' translates into:

main:
	pacbti	ip, lr, sp
	push	{r3, r7, ip, lr}
	add	r7, sp, #0
	bl	foo
	movs	r3, #0
	mov	r0, r3
	pop	{r3, r7, ip, lr}
	aut	ip, lr, sp
	bx	lr

As part of previous upstream suggestions a test for varargs has been
added and '-mtpcs-frame' is deemed being incompatible with this return
signing address feature being introduced.

[1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>

gcc/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* config/arm/arm.h (arm_arch8m_main): Declare it.
	* config/arm/arm.cc (arm_arch8m_main): Define it.
	(arm_option_reconfigure_globals): Set arm_arch8m_main.
	(arm_compute_frame_layout, arm_expand_prologue)
	(thumb2_expand_return, arm_expand_epilogue)
	(arm_conditional_register_usage): Update for pac codegen.
	(arm_current_function_pac_enabled_p): New function.
	(aarch_bti_enabled) New function.
	(use_return_insn): Return zero when pac is enabled.
	* config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
	Add new patterns.
	* config/arm/unspecs.md (UNSPEC_PAC_NOP)
	(VUNSPEC_PACBTI_NOP, VUNSPEC_AUT_NOP): Add unspecs.

gcc/testsuite/Changelog

2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/arm/pac.h : New file.
	* gcc.target/arm/pac-1.c : New test case.
	* gcc.target/arm/pac-2.c : Likewise.
	* gcc.target/arm/pac-3.c : Likewise.
	* gcc.target/arm/pac-4.c : Likewise.
	* gcc.target/arm/pac-5.c : Likewise.
	* gcc.target/arm/pac-6.c : Likewise.
	* gcc.target/arm/pac-7.c : Likewise.
	* gcc.target/arm/pac-8.c : Likewise.
	* gcc.target/arm/pac-9.c : Likewise.
	* gcc.target/arm/pac-10.c : Likewise.
	* gcc.target/arm/pac-11.c : Likewise.
---
 gcc/config/arm/arm-protos.h           |  1 +
 gcc/config/arm/arm.cc                 | 79 ++++++++++++++++++++++++---
 gcc/config/arm/arm.h                  |  4 ++
 gcc/config/arm/arm.md                 | 23 ++++++++
 gcc/config/arm/unspecs.md             |  3 +
 gcc/testsuite/gcc.target/arm/pac-1.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-10.c | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-11.c | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-2.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-3.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac-4.c  | 10 ++++
 gcc/testsuite/gcc.target/arm/pac-5.c  | 28 ++++++++++
 gcc/testsuite/gcc.target/arm/pac-6.c  | 18 ++++++
 gcc/testsuite/gcc.target/arm/pac-7.c  | 32 +++++++++++
 gcc/testsuite/gcc.target/arm/pac-8.c  | 34 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac-9.c  | 11 ++++
 gcc/testsuite/gcc.target/arm/pac.h    | 17 ++++++
 17 files changed, 304 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-10.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-11.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-3.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-4.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-5.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-6.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-7.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-8.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac-9.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pac.h

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 6e6bf147e9c..d97a1c3bf56 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -378,6 +378,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 972d5699700..53d9dbbd691 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -923,6 +923,11 @@ int arm_arch8_3 = 0;
 
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 int arm_arch8_4 = 0;
+
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+int arm_arch8m_main = 0;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 int arm_arch8_1m_main = 0;
@@ -3205,6 +3210,15 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (!arm_arch8m_main)
+        error ("This architecture does not support branch protection "
+               "instructions");
+      if (TARGET_TPCS_FRAME)
+        sorry ("Return address signing is not supported with %<-mtpcs-frame%>.");
+    }
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -3851,6 +3865,7 @@ arm_option_reconfigure_globals (void)
   arm_arch_arm_hwdiv = bitmap_bit_p (arm_active_target.isa, isa_bit_adiv);
   arm_arch_crc = bitmap_bit_p (arm_active_target.isa, isa_bit_crc32);
   arm_arch_cmse = bitmap_bit_p (arm_active_target.isa, isa_bit_cmse);
+  arm_arch8m_main = arm_arch7 && arm_arch_cmse;
   arm_arch_lpae = bitmap_bit_p (arm_active_target.isa, isa_bit_lpae);
   arm_arch_i8mm = bitmap_bit_p (arm_active_target.isa, isa_bit_i8mm);
   arm_arch_bf16 = bitmap_bit_p (arm_active_target.isa, isa_bit_bf16);
@@ -4350,6 +4365,11 @@ use_return_insn (int iscond, rtx sibling)
   if (!reload_completed)
     return 0;
 
+  /* Never use a return instruction when return address signing
+     mechanism is enabled.  */
+  if (arm_current_function_pac_enabled_p ())
+    return 0;
+
   func_type = arm_current_func_type ();
 
   /* Naked, volatile and stack alignment functions need special
@@ -21227,6 +21247,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23518,12 +23541,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || arm_current_function_pac_enabled_p ()));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23548,7 +23572,6 @@ arm_expand_prologue (void)
 	{
 	  rtx addr, dwarf;
 
-	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
 	  saved_regs += 4;
 
 	  addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
@@ -23599,6 +23622,17 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      /* If IP was clobbered we only emit a PAC instruction as the BTI
+         one will be added before the push of the clobbered IP (if
+         necessary) by the bti pass.  */
+      if (aarch_bti_enabled () && !clobber_ip)
+	emit_insn (gen_pacbti_nop ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27410,7 +27444,14 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (arm_current_function_pac_enabled_p ())
+        {
+          gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+          arm_emit_multi_reg_pop (saved_regs_mask);
+          emit_insn (gen_aut_nop ());
+          emit_jump_insn (simple_return_rtx);
+        }
+      else if (num_regs == 1)
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27834,7 +27875,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27948,6 +27990,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -33049,6 +33094,22 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+          || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+              && !crtl->is_leaf));
+}
+
+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index ff8452ea04a..5f7c40805d3 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -506,6 +506,10 @@ extern int arm_arch8_3;
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 extern int arm_arch8_4;
 
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+extern int arm_arch8m_main;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 extern int arm_arch8_1m_main;
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 69bf343fb0e..d624cfae5b8 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12978,6 +12978,29 @@ (define_insn "*speculation_barrier_insn"
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PAC_NOP))]
+  "arm_arch8m_main"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec_volatile:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+			    VUNSPEC_PACBTI_NOP))]
+  "arm_arch8m_main"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "aut_nop"
+  [(unspec_volatile:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		       VUNSPEC_AUT_NOP)]
+  "arm_arch8m_main"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..370f0b12da1 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,7 @@ (define_c_enum "unspec" [
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
 ])
 
 
@@ -254,6 +255,8 @@ (define_c_enum "unspecv" [
 			; instruction.
   VUNSPEC_VLLDM		; Represent the lazy load multiple with vlldm
 			; instruction.
+  VUNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  VUNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..9b26f62b65f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-10.c b/gcc/testsuite/gcc.target/arm/pac-10.c
new file mode 100644
index 00000000000..a794195e8f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-10.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-11.c b/gcc/testsuite/gcc.target/arm/pac-11.c
new file mode 100644
index 00000000000..37ffc93b41b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-11.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-9.c b/gcc/testsuite/gcc.target/arm/pac-9.c
new file mode 100644
index 00000000000..ee2fad290b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-9.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 10/15 V7] arm: Implement cortex-M return signing address codegen
  2023-01-11  9:58                       ` [PATCH 10/15 V7] " Andrea Corallo
@ 2023-01-11 10:39                         ` Richard Earnshaw
  0 siblings, 0 replies; 66+ messages in thread
From: Richard Earnshaw @ 2023-01-11 10:39 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd



On 11/01/2023 09:58, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
> [...]
> 
>>
>> Otherwise ok with that change.
>>
>> R.
> 
> Minor respin of this patch addressing the suggestion to have
> 'use_return_insn' return zero when PAC is enabled.
> 
> BR
> 
>    Andrea
> 

+  /* Never use a return instruction when return address signing
+     mechanism is enabled.  */
+  if (arm_current_function_pac_enabled_p ())
+    return 0;
+

I can see what it does.  It would be better to explain why it does: ie 
that return address authentication needs more than one instruction.

OK with that change.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 1/15 V2] arm: Make mbranch-protection opts parsing common to AArch32/64
  2022-12-22 17:04   ` [PATCH 1/15 V2] " Andrea Corallo
@ 2023-01-11 10:48     ` Richard Earnshaw
  0 siblings, 0 replies; 66+ messages in thread
From: Richard Earnshaw @ 2023-01-11 10:48 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 22/12/2022 17:04, Andrea Corallo via Gcc-patches wrote:
> Hi all,
> 
> respinning this as a rebase was necessary, also now is setting
> 'aarch_enable_bti' to zero as default for arm as suggested during the
> review of 12/15.
> 
> Best Regards
> 
>    Andrea
> 
> 

gcc/ChangeLog:

	* common/config/aarch64/aarch64-common.cc: Include aarch-common.h.
	(all_architectures): Fix comment.
	(aarch64_parse_extension): Rename return type, enum value names.
	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Rename
	factored out aarch_ra_sign_scope and aarch_ra_sign_key variables.
	Also rename corresponding enum values.
	* config/aarch64/aarch64-opts.h (aarch64_function_type): Factor
	out aarch64_function_type and move it to common code as
	aarch_function_type in aarch-common.h.
	* config/aarch64/aarch64-protos.h: Include common types header,
	move out types aarch64_parse_opt_result and aarch64_key_type to
	aarch-common.h
	* config/aarch64/aarch64.cc: Move mbranch-protection parsing types
	and functions out into aarch-common.h and aarch-common.cc.  Fix up
	all the name changes resulting from the move.
	* config/aarch64/aarch64.md: Fix up aarch64_ra_sign_key type name change
	and enum value.
	* config/aarch64/aarch64.opt: Include aarch-common.h to import
	type move.  Fix up name changes from factoring out common code and
	data.
	* config/arm/aarch-common-protos.h: Export factored out routines to both
	backends.
	* config/arm/aarch-common.cc: Include newly factored out types.
	Move all mbranch-protection code and data structures from
	aarch64.cc.
	* config/arm/aarch-common.h: New header that declares types shared
	between aarch32 and aarch64 backends.
	* config/arm/arm-protos.h: Declare types and variables that are
	made common to aarch64 and aarch32 backends - aarch_ra_sign_key,
	aarch_ra_sign_scope and aarch_enable_bti.

I don't see an entry for config/arm/arm.opt.  Please make sure you 
patches pass "git gcc-verify".

Otherwise, this is OK.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH 12/15 V5] arm: implement bti injection
  2022-12-22 17:13                   ` [PATCH 12/15 V5] " Andrea Corallo
@ 2023-01-11 15:08                     ` Richard Earnshaw
  0 siblings, 0 replies; 66+ messages in thread
From: Richard Earnshaw @ 2023-01-11 15:08 UTC (permalink / raw)
  To: Andrea Corallo
  Cc: Kyrylo Tkachov, Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 22/12/2022 17:13, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 14/12/2022 17:00, Richard Earnshaw via Gcc-patches wrote:
>>> On 14/12/2022 16:40, Andrea Corallo via Gcc-patches wrote:
>>>> Hi Richard,
>>>>
>>>> thanks for reviewing.
>>>>
>>>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>>>
>>>>> On 28/10/2022 17:40, Andrea Corallo via Gcc-patches wrote:
>>>>>> Hi all,
>>>>>> please find attached the third iteration of this patch addresing
>>>>>> review
>>>>>> comments.
>>>>>> Thanks
>>>>>>      Andrea
>>>>>>
>>>>>
>>>>> @@ -23374,12 +23374,6 @@ output_probe_stack_range (rtx reg1, rtx reg2)
>>>>>      return "";
>>>>>    }
>>>>>
>>>>> -static bool
>>>>> -aarch_bti_enabled ()
>>>>> -{
>>>>> -  return false;
>>>>> -}
>>>>> -
>>>>>    /* Generate the prologue instructions for entry into an ARM or Thumb-2
>>>>>       function.  */
>>>>>    void
>>>>> @@ -32992,6 +32986,61 @@ arm_current_function_pac_enabled_p (void)
>>>>>                  && !crtl->is_leaf));
>>>>>    }
>>>>>
>>>>> +/* Return TRUE if Branch Target Identification Mechanism is
>>>>> enabled.  */
>>>>> +bool
>>>>> +aarch_bti_enabled (void)
>>>>> +{
>>>>> +  return aarch_enable_bti == 1;
>>>>> +}
>>>>>
>>>>> See comment in earlier patch about the location of this function
>>>>> moving.   Can aarch_enable_bti take values other than 0 and 1?
>>>>
>>>> Yes default is 2.
>>> It shouldn't be by this point, because, hopefully you've gone
>>> through the equivalent of this hunk (from aarch64) somewhere in
>>> arm_override_options:
>>>      if (aarch_enable_bti == 2)
>>>        {
>>>    #ifdef TARGET_ENABLE_BTI
>>>          aarch_enable_bti = 1;
>>>    #else
>>>          aarch_enable_bti = 0;
>>>    #endif
>>>        }
>>> And after this point the '2' should never be seen again.  We use
>>> this trick to permit the user to force a default that differs from
>>> the configuration.
>>> However, I don't see a hunk to do this in patch 3, so perhaps that
>>> needs updating to fix this.
>>
>> I've just remembered that the above is to support a configure-time
>> option of the compiler to enable branch protection.  But perhaps we
>> don't want to have that in AArch32, in which case it would be better
>> not to have the default be 2 anyway, just default to off (0).
>>
>> R.
> 
> Done in 1/15 (needs approval again now).
> 
>>>
>>>> [...]
>>>>
>>>>> +  return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) ==
>>>>> UNSPEC_BTI_NOP;
>>>>>
>>>>> I'm not sure where this crept in, but UNSPEC and UNSPEC_VOLATILE have
>>>>> separate enums in the backend, so UNSPEC_BIT_NOP should really be
>>>>> VUNSPEC_BTI_NOP and defined in the enum "unspecv".
>>>>
>>>> Done
>>>>
>>>>> +aarch_pac_insn_p (rtx x)
>>>>> +{
>>>>> +  if (!x || !INSN_P (x))
>>>>> +    return false;
>>>>> +
>>>>> +  rtx pat = PATTERN (x);
>>>>> +
>>>>> +  if (GET_CODE (pat) == SET)
>>>>> +    {
>>>>> +      rtx tmp = XEXP (pat, 1);
>>>>> +      if (tmp
>>>>> +      && GET_CODE (tmp) == UNSPEC
>>>>> +      && (XINT (tmp, 1) == UNSPEC_PAC_NOP
>>>>> +          || XINT (tmp, 1) == UNSPEC_PACBTI_NOP))
>>>>> +    return true;
>>>>> +    }
>>>>> +
>>>>>
>>>>> This will also need updating (see review on earlier patch) because
>>>>> PACBTI needs to be unspec_volatile, while PAC doesn't.
>>>>
>>>> Done
>>>>
>>>>> +/* The following two functions are for code compatibility with aarch64
>>>>> +   code, this even if in arm we have only one bti instruction.  */
>>>>> +
>>>>>
>>>>> I'd just write
>>>>>    /* Target specific mapping for aarch_gen_bti_c and
>>>>>    aarch_gen_bti_j. For Arm, both of these map to a simple BTI
>>>>> instruction.  */
>>>>
>>>> Done
>>>>
>>>>>
>>>>> @@ -162,6 +162,7 @@ (define_c_enum "unspec" [
>>>>>      UNSPEC_PAC_NOP    ; Represents PAC signing LR
>>>>>      UNSPEC_PACBTI_NOP    ; Represents PAC signing LR + valid landing pad
>>>>>      UNSPEC_AUT_NOP    ; Represents PAC verifying LR
>>>>> +  UNSPEC_BTI_NOP    ; Represent BTI
>>>>>    ])
>>>>>
>>>>> BTI is an unspec volatile, so this should be in the "vunspec" enum and
>>>>> renamed accordingly (see above).
>>>>
>>>> Done.
>>>>
>>>> Please find attached the updated version of this patch.
>>>>
>>>> BR
>>>>
>>>>     Andrea
>>>>
>>> Apart from that, this is OK.
>>> R.
> 
> Cool, attached the updated patch.
> 
> Also I added some error handling not to run the bti pass if the march
> selected does not support bti.
> 
> BR
> 
>    Andrea
> 


OK.

R.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M
  2022-09-21  8:07 ` [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  2022-10-21 13:01   ` Richard Earnshaw
  2022-12-05 14:10   ` Andrea Corallo
@ 2023-01-23 10:50   ` Andrea Corallo
  2 siblings, 0 replies; 66+ messages in thread
From: Andrea Corallo @ 2023-01-23 10:50 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

Hi Richard,

thanks for reviewing and approving this series, this is now in.

BR

  Andrea

^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2023-01-23 10:51 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-12 14:26 [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
2022-08-12 15:14 ` [PATCH 1/15] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
2022-12-22 17:04   ` [PATCH 1/15 V2] " Andrea Corallo
2023-01-11 10:48     ` Richard Earnshaw
2022-08-12 15:15 ` [PATCH 2/15] arm: Add Armv8.1-M Mainline target feature +pacbti Andrea Corallo
2022-08-12 15:21 ` [PATCH 3/15] arm: Add option -mbranch-protection Andrea Corallo
2022-08-12 15:22 ` [PATCH 4/15] arm: Add testsuite library support for PACBTI target Andrea Corallo
2022-08-12 15:26 ` [PATCH 5/15] arm: Implement target feature macros for PACBTI Andrea Corallo
2022-08-12 15:29 ` [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime Andrea Corallo
2022-08-12 15:30 ` [PATCH 7/15] arm: Emit build attributes for PACBTI target feature Andrea Corallo
2022-09-05 16:53   ` Andrea Corallo
2022-10-20 14:47   ` Kyrylo Tkachov
2022-10-20 15:15     ` Richard Earnshaw
2022-10-21 12:19   ` Richard Earnshaw
2022-08-12 15:33 ` [PATCH 8/15] arm: Introduce multilibs " Andrea Corallo
2022-08-12 15:34 ` [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary Andrea Corallo
2022-09-05 16:52   ` Andrea Corallo
2022-09-27  9:03   ` Kyrylo Tkachov
2022-09-27 10:05     ` Andrea Corallo
2022-09-27 15:24       ` Kyrylo Tkachov
2022-10-21 12:30         ` Richard Earnshaw
2022-10-26  8:49           ` Andrea Corallo
2022-11-08 14:57             ` Richard Earnshaw
2023-01-09 14:58             ` Andrea Corallo
2023-01-09 15:57               ` Richard Earnshaw
2023-01-09 16:48               ` Richard Earnshaw
2023-01-09 17:22                 ` Richard Earnshaw
2023-01-11  9:55                   ` Andrea Corallo
2022-08-12 15:36 ` [PATCH 10/15] arm: Implement cortex-M return signing address codegen Andrea Corallo
2022-09-05 16:55   ` Andrea Corallo
2022-09-14 14:20   ` [PATCH 10/15 V2] " Andrea Corallo
2022-10-21 12:58     ` Richard Earnshaw
2022-10-26 15:48       ` Andrea Corallo
2022-10-28 16:34         ` [PATCH 10/15 V3] " Andrea Corallo
2022-11-07  8:57           ` [PATCH 10/15 V4] " Andrea Corallo
2022-12-05 16:38             ` Richard Earnshaw
2022-12-09 14:16               ` [PATCH 10/15 V5] " Andrea Corallo
2022-12-12 10:53                 ` Richard Earnshaw
2022-12-14 16:35                   ` [PATCH 10/15 V6] " Andrea Corallo
2022-12-14 16:45                     ` Richard Earnshaw
2023-01-11  9:58                       ` [PATCH 10/15 V7] " Andrea Corallo
2023-01-11 10:39                         ` Richard Earnshaw
2022-08-12 15:40 ` [PATCH 11/15] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
2022-09-05 16:56   ` Andrea Corallo
2022-09-27  9:10   ` Kyrylo Tkachov
2022-08-12 15:41 ` [PATCH 12/15] arm: implement bti injection Andrea Corallo
2022-09-05 16:56   ` Andrea Corallo
2022-09-27  9:18   ` Kyrylo Tkachov
2022-09-29 15:45     ` [PATCH 12/15 V2] " Andrea Corallo
2022-10-20 14:56       ` Kyrylo Tkachov
2022-10-28 16:40         ` [PATCH 12/15 V3] " Andrea Corallo
2022-12-05 17:02           ` Richard Earnshaw
2022-12-14 16:40             ` [PATCH 12/15 V4] " Andrea Corallo
2022-12-14 17:00               ` Richard Earnshaw
2022-12-14 17:03                 ` Richard Earnshaw
2022-12-22 17:13                   ` [PATCH 12/15 V5] " Andrea Corallo
2023-01-11 15:08                     ` Richard Earnshaw
2022-08-12 16:44 ` [PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
2022-08-12 17:10 ` [PATCH 13/15] arm: Add pacbti related multilib support for armv8.1-m.main Srinath Parvathaneni
2022-10-21 13:00   ` Richard Earnshaw
2022-09-21  8:07 ` [PING][PATCH 0/15] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
2022-10-21 13:01   ` Richard Earnshaw
2022-10-21 13:32     ` Andrea Corallo
2022-12-05 14:10   ` Andrea Corallo
2022-12-05 14:19     ` Kyrylo Tkachov
2023-01-23 10:50   ` [PATCH " Andrea Corallo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).