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

Hi all,

this series 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] 53+ messages in thread

* [PATCH 1/12] arm: Make mbranch-protection opts parsing common to AArch32/64
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
@ 2022-04-28  9:08 ` Andrea Corallo
  2022-07-01 10:49   ` Richard Earnshaw
  2022-04-28  9:37 ` [PATCH 2/12] arm: Add Armv8.1-M Mainline target feature +pacbti Andrea Corallo
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:08 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

[-- Attachment #1: Type: text/plain, Size: 2474 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.

This patch implements the changes requested and was pre-approved here
<https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586139.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-12.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] 53+ messages in thread

* [PATCH 2/12] arm: Add Armv8.1-M Mainline target feature +pacbti
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  2022-04-28  9:08 ` [PATCH 1/12] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
@ 2022-04-28  9:37 ` Andrea Corallo
  2022-07-01 10:51   ` Richard Earnshaw
  2022-04-28  9:38 ` [PATCH 3/12] arm: Add option -mbranch-protection Andrea Corallo
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:37 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

[-- Attachment #1: Type: text/plain, Size: 470 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-12.patch --]
[-- Type: text/plain, Size: 2089 bytes --]

diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
index 0d3082b569f..6c1dffe56e3 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
@@ -748,6 +752,7 @@ begin arch armv8.1-m.main
  option nofp remove ALL_FP
  option mve add MVE
  option mve.fp add MVE_FP
+ option pacbti add pacbti
  option cdecp0 add cdecp0
  option cdecp1 add cdecp1
  option cdecp2 add cdecp2
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] 53+ messages in thread

* [PATCH 3/12] arm: Add option -mbranch-protection
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  2022-04-28  9:08 ` [PATCH 1/12] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
  2022-04-28  9:37 ` [PATCH 2/12] arm: Add Armv8.1-M Mainline target feature +pacbti Andrea Corallo
@ 2022-04-28  9:38 ` Andrea Corallo
  2022-07-01 10:59   ` Richard Earnshaw
  2022-04-28  9:40 ` [PATCH 4/12] arm: Add testsuite library support for PACBTI target Andrea Corallo
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:38 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

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

[PATCH 3/12] arm: Add option -mbranch-protection

Add -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>


[-- Attachment #2: 3-12.patch --]
[-- Type: text/plain, Size: 3607 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..f6f724af26e 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,37 @@ 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}.
+
+The default is to generate code without branch protection or return
+address signing.
+
 @end table
 
 @node AVR Options

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

* [PATCH 4/12] arm: Add testsuite library support for PACBTI target
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (2 preceding siblings ...)
  2022-04-28  9:38 ` [PATCH 3/12] arm: Add option -mbranch-protection Andrea Corallo
@ 2022-04-28  9:40 ` Andrea Corallo
  2022-07-01 13:03   ` Richard Earnshaw
  2022-04-28  9:42 ` [PATCH 5/12] arm: Implement target feature macros for PACBTI Andrea Corallo
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:40 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

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

Add 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-12.patch --]
[-- Type: text/plain, Size: 1461 bytes --]

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 613ac29967b..e8cbd8e4aef 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.
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ff8edbd3e17..df8ab037fb3 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");
+	}
+    } ""]
+}
+
 # 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] 53+ messages in thread

* [PATCH 5/12] arm: Implement target feature macros for PACBTI
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (3 preceding siblings ...)
  2022-04-28  9:40 ` [PATCH 4/12] arm: Add testsuite library support for PACBTI target Andrea Corallo
@ 2022-04-28  9:42 ` Andrea Corallo
  2022-07-01 14:26   ` Richard Earnshaw
  2022-04-28  9:44 ` [PATCH 6/12] arm: Add pointer authentication for stack-unwinding runtime Andrea Corallo
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:42 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

[-- Attachment #1: Type: text/plain, Size: 927 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/ChangeLog:

	* 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/ChangeLog:

	* gcc.target/arm/acle/pacbti-m-predef-2.c: New test.
	* gcc.target/arm/acle/pacbti-m-predef-4.c: New test.
	* gcc.target/arm/acle/pacbti-m-predef-5.c: New test.

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


[-- Attachment #2: 5-12.patch --]
[-- Type: text/plain, Size: 3466 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-2.c b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c
new file mode 100644
index 00000000000..4394fd147d7
--- /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 arm_pacbti_hw } */
+/* { dg-additional-options " -mbranch-protection=bti+pac-ret+leaf" } */
+
+#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..90f0c724b9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-4.c
@@ -0,0 +1,21 @@
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-additional-options " -mbranch-protection=pac-ret" } */
+
+#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..c865809b8b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
@@ -0,0 +1,24 @@
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-additional-options " -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;
+}

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

* [PATCH 6/12] arm: Add pointer authentication for stack-unwinding runtime
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (4 preceding siblings ...)
  2022-04-28  9:42 ` [PATCH 5/12] arm: Implement target feature macros for PACBTI Andrea Corallo
@ 2022-04-28  9:44 ` Andrea Corallo
  2022-07-01 14:41   ` Richard Earnshaw
  2022-04-28  9:45 ` [PATCH 7/12] arm: Emit build attributes for PACBTI target feature Andrea Corallo
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:44 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

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

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.

Pre-approved with the requested changes here
<https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586555.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-12.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] 53+ messages in thread

* [PATCH 7/12] arm: Emit build attributes for PACBTI target feature
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (5 preceding siblings ...)
  2022-04-28  9:44 ` [PATCH 6/12] arm: Add pointer authentication for stack-unwinding runtime Andrea Corallo
@ 2022-04-28  9:45 ` Andrea Corallo
  2022-07-01 14:49   ` Richard Earnshaw
  2022-04-28  9:46 ` [PATCH 8/12] arm: Introduce multilibs " Andrea Corallo
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:45 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

[-- 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-12.patch --]
[-- Type: text/plain, Size: 4921 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..75d3e00ef64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=pac-ret+bti --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..bf6c3ba90c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=pac-ret+leaf --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..82af11ee407
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-6.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=bti --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..48a40e64c11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-7.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.1-m.main+pacbti --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 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] 53+ messages in thread

* [PATCH 8/12] arm: Introduce multilibs for PACBTI target feature
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (6 preceding siblings ...)
  2022-04-28  9:45 ` [PATCH 7/12] arm: Emit build attributes for PACBTI target feature Andrea Corallo
@ 2022-04-28  9:46 ` Andrea Corallo
  2022-06-01 12:32   ` [PATCH 8/12 V2] " Andrea Corallo
  2022-04-28  9:48 ` [PATCH 9/12] arm: Make libgcc bti compatible Andrea Corallo
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:46 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

[-- Attachment #1: Type: text/plain, Size: 999 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

gcc/ChangeLog:

	* config/arm/t-rmprofile: Add multilib rules for +pacbti.


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

diff --git a/gcc/config/arm/t-rmprofile b/gcc/config/arm/t-rmprofile
index eb321e832f1..542ff874b2e 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 8.1-m.main+pacbti+mve
+
+MULTI_ARCH_OPTS_RM	+= mbranch-protection=pac-ret+bti
+MULTI_ARCH_DIRS_RM	+= mbranch-protection
 
 # Base M-profile (no fp)
 MULTILIB_REQUIRED	+= mthumb/march=armv6s-m/mfloat-abi=soft
@@ -50,6 +53,14 @@ 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
 
@@ -93,3 +104,4 @@ 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

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

* [PATCH 9/12] arm: Make libgcc bti compatible
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (7 preceding siblings ...)
  2022-04-28  9:46 ` [PATCH 8/12] arm: Introduce multilibs " Andrea Corallo
@ 2022-04-28  9:48 ` Andrea Corallo
  2022-07-01 15:03   ` Richard Earnshaw
  2022-04-28  9:50 ` [PATCH 10/12] arm: Implement cortex-M return signing address codegen Andrea Corallo
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:48 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

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

This change add bti instructions at the beginning of arm specific
libgcc hand written assembly routines.

2022-03-31  Andrea Corallo  <andrea.corallo@arm.com>

	* libgcc/config/arm/crti.S (FUNC_START): Add bti instruction if
	necessary.
	* libgcc/config/arm/lib1funcs.S (THUMB_FUNC_START, FUNC_START):
	Likewise.


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

diff --git a/libgcc/config/arm/crti.S b/libgcc/config/arm/crti.S
index 0192972a7e6..bac2d87fbb9 100644
--- a/libgcc/config/arm/crti.S
+++ b/libgcc/config/arm/crti.S
@@ -51,7 +51,9 @@
 .macro FUNC_START
 #ifdef __thumb__
 	.thumb
-	
+#if defined(__ARM_FEATURE_BTI)
+	bti
+#endif
 	push	{r3, r4, r5, r6, r7, lr}
 #else
 	.arm
diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S
index 8c39c9f20a2..45dfb5da9ee 100644
--- a/libgcc/config/arm/lib1funcs.S
+++ b/libgcc/config/arm/lib1funcs.S
@@ -345,6 +345,9 @@ LSYM(Ldiv0):
 	TYPE	(\name)
 	.thumb_func
 SYM (\name):
+#if defined(__ARM_FEATURE_BTI)
+	bti
+#endif
 .endm
 
 /* Function start macros.  Variants for ARM and Thumb.  */
@@ -372,6 +375,9 @@ SYM (\name):
 	THUMB_FUNC
 	THUMB_SYNTAX
 SYM (__\name):
+#if defined(__ARM_FEATURE_BTI)
+	bti
+#endif
 .endm
 
 .macro ARM_SYM_START name

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

* [PATCH 10/12] arm: Implement cortex-M return signing address codegen
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (8 preceding siblings ...)
  2022-04-28  9:48 ` [PATCH 9/12] arm: Make libgcc bti compatible Andrea Corallo
@ 2022-04-28  9:50 ` Andrea Corallo
  2022-06-28  9:17   ` [PATCH 10/12 V2] " Andrea Corallo
  2022-04-28  9:51 ` [PATCH 11/12] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:50 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

[-- Attachment #1: Type: text/plain, Size: 2379 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

	* 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

	* 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-12.patch --]
[-- Type: text/plain, Size: 13056 bytes --]

diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index ceec14f84b6..c91dae292c8 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -302,6 +302,7 @@ static bool arm_vectorize_vec_perm_const (machine_mode, rtx, rtx, rtx,
 					  const vec_perm_indices &);
 
 static bool aarch_macro_fusion_pair_p (rtx_insn*, rtx_insn*);
+static bool arm_current_function_pac_enabled_p (void);
 
 static int arm_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
 					   tree vectype,
@@ -21139,6 +21140,14 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (TARGET_TPCS_FRAME
+	  || (TARGET_TPCS_LEAF_FRAME && crtl->is_leaf))
+	error ("TPCS incompatible with return address signing.");
+      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.
@@ -22302,7 +22311,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
     par = emit_insn (par);
 
   REG_NOTES (par) = dwarf;
-  if (!return_in_pc)
+  if (!return_in_pc && !frame_pointer_needed)
     arm_add_cfa_adjust_cfa_note (par, UNITS_PER_WORD * num_regs,
 				 stack_pointer_rtx, stack_pointer_rtx);
 }
@@ -23352,6 +23361,11 @@ 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
@@ -23431,11 +23445,12 @@ 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 ()));
+    && (((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:
@@ -23511,6 +23526,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))
@@ -27299,7 +27322,8 @@ 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);
@@ -27314,10 +27338,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 ())
+	    {
+	      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
     {
@@ -27723,7 +27757,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);
@@ -27837,6 +27872,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -30541,6 +30579,9 @@ arm_conditional_register_usage (void)
 	global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1;
     }
 
+  if (TARGET_HAVE_PACBTI)
+    call_used_regs[IP_REGNUM] = 1;
+
   /* The Q and GE bits are only accessed via special ACLE patterns.  */
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRQ_REGNUM);
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRGE_REGNUM);
@@ -32931,6 +32972,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.  */
+static 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..b480f76a876 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -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))]
+  "TARGET_THUMB2"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "2")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PACBTI_NOP))]
+  "TARGET_THUMB2"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "2")])
+
+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+              UNSPEC_AUT_NOP)]
+  "TARGET_THUMB2"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "2")])
+
 ;; 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..627a93f8a56
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,9 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb --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 "bti" } } */
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..a89eb73f012
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,9 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret -mthumb --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 "bti" } } */
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..a241fd0f172
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,9 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=bti+pac-ret+leaf -mthumb --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\t" } } */
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..63dc9a9e08e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,9 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.1-m.main+pacbti -mthumb --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..97de00d8057
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,26 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb --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 "bti" } } */
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..0d640751335
--- /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-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -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..3882b05a9be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,30 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb --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 "bti" } } */
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..35728308c32
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb --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 "bti" } } */
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] 53+ messages in thread

* [PATCH 11/12] aarch64: Make bti pass generic so it can be used by the arm backend
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (9 preceding siblings ...)
  2022-04-28  9:50 ` [PATCH 10/12] arm: Implement cortex-M return signing address codegen Andrea Corallo
@ 2022-04-28  9:51 ` Andrea Corallo
  2022-05-06  8:23   ` Richard Sandiford
  2022-07-01 15:53   ` Richard Earnshaw
  2022-04-28  9:53 ` [PATCH 12/12] arm: implement bti injection Andrea Corallo
  2022-06-01 12:34 ` [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  12 siblings, 2 replies; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:51 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

[-- Attachment #1: Type: text/plain, Size: 901 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.

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.
	* config/arm/arm-passes.def: New file.


[-- Attachment #2: 11-12.patch --]
[-- Type: text/plain, Size: 12052 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
diff --git a/gcc/config/arm/arm-passes.def b/gcc/config/arm/arm-passes.def
new file mode 100644
index 00000000000..beecd2b5455
--- /dev/null
+++ b/gcc/config/arm/arm-passes.def
@@ -0,0 +1,21 @@
+/* Arm-specific passes declarations.
+   Copyright (C) 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/>.  */
+
+INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);

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

* [PATCH 12/12] arm: implement bti injection
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (10 preceding siblings ...)
  2022-04-28  9:51 ` [PATCH 11/12] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
@ 2022-04-28  9:53 ` Andrea Corallo
  2022-06-28  9:21   ` [PATCH 12/12 V2] " Andrea Corallo
  2022-06-01 12:34 ` [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
  12 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-04-28  9:53 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw

[-- Attachment #1: Type: text/plain, Size: 1052 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

	* 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.

gcc/testsuite/ChangeLog

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


[-- Attachment #2: 12-12.patch --]
[-- Type: text/plain, Size: 6291 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/arm-protos.h b/gcc/config/arm/arm-protos.h
index cff7ff1da2a..da23e0a4735 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 c91dae292c8..a2b720a6660 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -23361,11 +23361,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
@@ -32981,6 +32976,56 @@ 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 b480f76a876..2221bc68f35 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12913,6 +12913,12 @@
   "aut\t%|ip, %|lr, %|sp"
   [(set_attr "length" "2")])
 
+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
+  "TARGET_THUMB2"
+  "bti"
+  [(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] 53+ messages in thread

* Re: [PATCH 11/12] aarch64: Make bti pass generic so it can be used by the arm backend
  2022-04-28  9:51 ` [PATCH 11/12] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
@ 2022-05-06  8:23   ` Richard Sandiford
  2022-07-01 15:53   ` Richard Earnshaw
  1 sibling, 0 replies; 53+ messages in thread
From: Richard Sandiford @ 2022-05-06  8:23 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Andrea Corallo, 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.
>
> 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.
> 	* config/arm/arm-passes.def: New file.

Looks good to me, thanks.

Richard

> 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
> diff --git a/gcc/config/arm/arm-passes.def b/gcc/config/arm/arm-passes.def
> new file mode 100644
> index 00000000000..beecd2b5455
> --- /dev/null
> +++ b/gcc/config/arm/arm-passes.def
> @@ -0,0 +1,21 @@
> +/* Arm-specific passes declarations.
> +   Copyright (C) 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/>.  */
> +
> +INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);

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

* [PATCH 8/12 V2] arm: Introduce multilibs for PACBTI target feature
  2022-04-28  9:46 ` [PATCH 8/12] arm: Introduce multilibs " Andrea Corallo
@ 2022-06-01 12:32   ` Andrea Corallo
  2022-07-01 14:54     ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-06-01 12:32 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

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

Hi all,

second iteration of the previous patch adding 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

To trigger 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

gcc/ChangeLog:

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


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

diff --git a/gcc/config/arm/t-rmprofile b/gcc/config/arm/t-rmprofile
index eb321e832f1..77147dde2ea 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 8.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,14 @@ 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 +98,19 @@ 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
+
 # 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

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

* Re: [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M
  2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
                   ` (11 preceding siblings ...)
  2022-04-28  9:53 ` [PATCH 12/12] arm: implement bti injection Andrea Corallo
@ 2022-06-01 12:34 ` Andrea Corallo
  12 siblings, 0 replies; 53+ messages in thread
From: Andrea Corallo @ 2022-06-01 12:34 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: nd, Richard Earnshaw, Kyrylo Tkachov

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

> Hi all,
>
> this series 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,

this is to ping this series.

I believe 3/12 7/12 8/12 9/12 10/12 12/12 are still pending for review.

Thanks!

  Andrea

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

* [PATCH 10/12 V2] arm: Implement cortex-M return signing address codegen
  2022-04-28  9:50 ` [PATCH 10/12] arm: Implement cortex-M return signing address codegen Andrea Corallo
@ 2022-06-28  9:17   ` Andrea Corallo
  2022-07-01 15:43     ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-06-28  9:17 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

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

Hi all,

second version of this patch enabling 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

	* 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

	* 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-12.patch --]
[-- Type: text/plain, Size: 13753 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 ceec14f84b6..6760a01d68a 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -21139,6 +21139,14 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (TARGET_TPCS_FRAME
+	  || (TARGET_TPCS_LEAF_FRAME && crtl->is_leaf))
+	error ("TPCS incompatible with return address signing.");
+      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.
@@ -22302,7 +22310,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
     par = emit_insn (par);
 
   REG_NOTES (par) = dwarf;
-  if (!return_in_pc)
+  if (!return_in_pc && !frame_pointer_needed)
     arm_add_cfa_adjust_cfa_note (par, UNITS_PER_WORD * num_regs,
 				 stack_pointer_rtx, stack_pointer_rtx);
 }
@@ -23352,6 +23360,11 @@ 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
@@ -23431,11 +23444,12 @@ 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 ()));
+    && (((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:
@@ -23511,6 +23525,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))
@@ -27299,7 +27321,8 @@ 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);
@@ -27314,10 +27337,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 ())
+	    {
+	      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
     {
@@ -27723,7 +27756,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);
@@ -27837,6 +27871,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -30541,6 +30578,9 @@ arm_conditional_register_usage (void)
 	global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1;
     }
 
+  if (TARGET_HAVE_PACBTI)
+    call_used_regs[IP_REGNUM] = 1;
+
   /* The Q and GE bits are only accessed via special ACLE patterns.  */
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRQ_REGNUM);
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRGE_REGNUM);
@@ -32931,6 +32971,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..ae032e70a7d 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -11514,11 +11514,17 @@
 (define_expand "prologue"
   [(clobber (const_int 0))]
   "TARGET_EITHER"
-  "if (TARGET_32BIT)
+  "if (arm_current_function_pac_enabled_p () && !arm_arch8)
+     {
+       error (\"This architecture does not support branch protection instructions\");
+       DONE;
+     }
+
+   if (TARGET_32BIT)
      arm_expand_prologue ();
    else
      thumb1_expand_prologue ();
-  DONE;
+   DONE;
   "
 )
 
@@ -12890,6 +12896,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))]
+  "TARGET_THUMB2"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "2")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PACBTI_NOP))]
+  "TARGET_THUMB2"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "2")])
+
+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+              UNSPEC_AUT_NOP)]
+  "TARGET_THUMB2"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "2")])
+
 ;; 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..627a93f8a56
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,9 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb --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 "bti" } } */
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..a89eb73f012
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,9 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret -mthumb --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 "bti" } } */
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..a241fd0f172
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,9 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=bti+pac-ret+leaf -mthumb --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\t" } } */
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..63dc9a9e08e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,9 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.1-m.main+pacbti -mthumb --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..97de00d8057
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,26 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb --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 "bti" } } */
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..0d640751335
--- /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-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -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..3882b05a9be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,30 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb --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 "bti" } } */
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..35728308c32
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb --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 "bti" } } */
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] 53+ messages in thread

* [PATCH 12/12 V2] arm: implement bti injection
  2022-04-28  9:53 ` [PATCH 12/12] arm: implement bti injection Andrea Corallo
@ 2022-06-28  9:21   ` Andrea Corallo
  2022-07-01 16:04     ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-06-28  9:21 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd

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

Hi all,

second iteration of this patch enabling 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.

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-12.patch --]
[-- Type: text/plain, Size: 7209 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..38f5a58ef2f 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
@@ -104,6 +105,14 @@ rest_of_insert_bti (void)
   rtx_insn *insn;
   basic_block bb;
 
+#if defined (TARGET_32BIT) || defined (TARGET_THUMB1)
+  if (!arm_arch8)
+    {
+      error ("This architecture does not support branch protection instructions");
+      goto exit;
+    }
+#endif
+
   bb = 0;
   FOR_EACH_BB_FN (bb, cfun)
     {
@@ -175,6 +184,7 @@ rest_of_insert_bti (void)
 	}
     }
 
+ exit:
   timevar_pop (TV_MACH_DEP);
   return 0;
 }
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 6760a01d68a..059075e2c95 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -23360,11 +23360,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
@@ -32980,6 +32975,56 @@ 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 ae032e70a7d..b14c45638a8 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12919,6 +12919,12 @@
   "aut\t%|ip, %|lr, %|sp"
   [(set_attr "length" "2")])
 
+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
+  "TARGET_THUMB2"
+  "bti"
+  [(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] 53+ messages in thread

* Re: [PATCH 1/12] arm: Make mbranch-protection opts parsing common to AArch32/64
  2022-04-28  9:08 ` [PATCH 1/12] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
@ 2022-07-01 10:49   ` Richard Earnshaw
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 10:49 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:08, Andrea Corallo via Gcc-patches wrote:
> 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.
> 
> This patch implements the changes requested and was pre-approved here
> <https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586139.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>
> 

OK, but please wait for the rest of this series to be approved before 
applying.

R.

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

* Re: [PATCH 2/12] arm: Add Armv8.1-M Mainline target feature +pacbti
  2022-04-28  9:37 ` [PATCH 2/12] arm: Add Armv8.1-M Mainline target feature +pacbti Andrea Corallo
@ 2022-07-01 10:51   ` Richard Earnshaw
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 10:51 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:37, Andrea Corallo via Gcc-patches wrote:
> 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>
> 

OK.

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

* Re: [PATCH 3/12] arm: Add option -mbranch-protection
  2022-04-28  9:38 ` [PATCH 3/12] arm: Add option -mbranch-protection Andrea Corallo
@ 2022-07-01 10:59   ` Richard Earnshaw
  2022-07-04  9:27     ` [PATCH 3/12 V2] " Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 10:59 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:38, Andrea Corallo via Gcc-patches wrote:
> [PATCH 3/12] arm: Add option -mbranch-protection
> 
> Add -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>
> 
+@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}.
+
+The default is to generate code without branch protection or return
+address signing.

This needs to make it clear that -mbranch-protection != none is only 
supported on armv8-m.main or later.

R.

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

* Re: [PATCH 4/12] arm: Add testsuite library support for PACBTI target
  2022-04-28  9:40 ` [PATCH 4/12] arm: Add testsuite library support for PACBTI target Andrea Corallo
@ 2022-07-01 13:03   ` Richard Earnshaw
  2022-07-01 14:17     ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 13:03 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:40, Andrea Corallo via Gcc-patches wrote:
> Add 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>
> 
+proc check_effective_target_arm_pacbti_hw {} {
+    return [check_runtime arm_pacbti_hw_available {
+	__attribute__ ((naked)) int
+	main (void)
+	{
+	  asm ("pac r12, lr, sp");

So the armv8-m Arm ARM says that this instruction is in the NOP space 
and that it is undefined if we aren't armv8-m.main or higher.

+	  asm ("mov r0, #0");
+	  asm ("autg r12, lr, sp");

This isn't in the nop space, but the Arm ARM says it is unpredictable if 
the extension isn't present.  Unfortunately, that means this isn't a 
particularly reliable way of detecting that the PACBTI feature is present.

However, I can't think off hand of more reliable way of testing this 
since reading the feature register ID_ISAR5 is not possible when in 
unprivileged mode.

So I think we'll have to live with this.

+	  asm ("bx lr");
+	}
+    } ""]

OK.

R.

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

* Re: [PATCH 4/12] arm: Add testsuite library support for PACBTI target
  2022-07-01 13:03   ` Richard Earnshaw
@ 2022-07-01 14:17     ` Richard Earnshaw
  2022-07-04 14:47       ` Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 14:17 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 01/07/2022 14:03, Richard Earnshaw via Gcc-patches wrote:
> 
> 
> On 28/04/2022 10:40, Andrea Corallo via Gcc-patches wrote:
>> Add 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>
>>
> +proc check_effective_target_arm_pacbti_hw {} {
> +    return [check_runtime arm_pacbti_hw_available {
> +    __attribute__ ((naked)) int
> +    main (void)
> +    {
> +      asm ("pac r12, lr, sp");
> 
> So the armv8-m Arm ARM says that this instruction is in the NOP space 
> and that it is undefined if we aren't armv8-m.main or higher.
> 
> +      asm ("mov r0, #0");
> +      asm ("autg r12, lr, sp");
> 
> This isn't in the nop space, but the Arm ARM says it is unpredictable if 
> the extension isn't present.  Unfortunately, that means this isn't a 
> particularly reliable way of detecting that the PACBTI feature is present.
> 
> However, I can't think off hand of more reliable way of testing this 
> since reading the feature register ID_ISAR5 is not possible when in 
> unprivileged mode.
> 
> So I think we'll have to live with this.
> 
> +      asm ("bx lr");
> +    }
> +    } ""]
> 
> OK.
> 

Or perhaps not. The test does not try to add the right options to enable 
PAC/BTI if those aren't in the default selection for the current 
testsuite run.

Perhaps we also need some additional tests to work out what architecture 
options to add (if any) to ensure the test will at least assemble.

> R.
R.

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

* Re: [PATCH 5/12] arm: Implement target feature macros for PACBTI
  2022-04-28  9:42 ` [PATCH 5/12] arm: Implement target feature macros for PACBTI Andrea Corallo
@ 2022-07-01 14:26   ` Richard Earnshaw
  2022-07-12 15:45     ` [PATCH 5/12 V2] " Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 14:26 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:42, Andrea Corallo via Gcc-patches wrote:
> 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/ChangeLog:
> 
> 	* config/arm/arm-c.c (arm_cpu_builtins): Define
> 	__ARM_FEATURE_BTI_DEFAULT, __ARM_FEATURE_PAC_DEFAULT,
> 	__ARM_FEATURE_PAUTH and __ARM_FEATURE_BTI.

This bit is OK.

> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/arm/acle/pacbti-m-predef-2.c: New test.
> 	* gcc.target/arm/acle/pacbti-m-predef-4.c: New test.
> 	* gcc.target/arm/acle/pacbti-m-predef-5.c: New test.
> 

These are all execution tests.  I think we also need some compile-only 
tests so that we get better coverage when the target does not directly 
support PACBTI.

We also need some tests for the defines when targetting armv8-m.main and 
some tests for checking __ARM_FEATURE_BTI and __ARM_FEATURE_PAC (the 
tests here check only the '..._DEFAULT' macros.

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

R.

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

* Re: [PATCH 6/12] arm: Add pointer authentication for stack-unwinding runtime
  2022-04-28  9:44 ` [PATCH 6/12] arm: Add pointer authentication for stack-unwinding runtime Andrea Corallo
@ 2022-07-01 14:41   ` Richard Earnshaw
  2022-11-09 11:17     ` [PATCH 6/12 V2] " Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 14:41 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:44, Andrea Corallo via Gcc-patches wrote:
> 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.
> 
> Pre-approved with the requested changes here
> <https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586555.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>
> 

Ok.

R.

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

* Re: [PATCH 7/12] arm: Emit build attributes for PACBTI target feature
  2022-04-28  9:45 ` [PATCH 7/12] arm: Emit build attributes for PACBTI target feature Andrea Corallo
@ 2022-07-01 14:49   ` Richard Earnshaw
  2022-07-13  8:58     ` [PATCH 7/12 V2] " Andrea Corallo
  2022-07-22 14:57     ` Andrea Corallo
  0 siblings, 2 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 14:49 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:45, 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.

This bit is OK.

> 
> 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.

These tests contain directives like:

+/* { dg-additional-options " -mbranch-protection=pac-ret+bti 
--save-temps" } */

But they don't check that the architecture permits this (it has to be 
armv8-m.main or later).

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

R.

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

* Re: [PATCH 8/12 V2] arm: Introduce multilibs for PACBTI target feature
  2022-06-01 12:32   ` [PATCH 8/12 V2] " Andrea Corallo
@ 2022-07-01 14:54     ` Richard Earnshaw
  2022-07-01 14:57       ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 14:54 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 01/06/2022 13:32, Andrea Corallo via Gcc-patches wrote:
> Hi all,
> 
> second iteration of the previous patch adding 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
> 
> To trigger 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
> 
> gcc/ChangeLog:
> 
> 	* config/arm/t-rmprofile: Add multilib rules for march +pacbti
>            and mbranch-protection.
> 

+# 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
+

The documentation mentions -mbranch-protection=standard+leaf, so you're 
missing a mapping for that.


OK with that change.

R.

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

* Re: [PATCH 8/12 V2] arm: Introduce multilibs for PACBTI target feature
  2022-07-01 14:54     ` Richard Earnshaw
@ 2022-07-01 14:57       ` Richard Earnshaw
  2022-07-21  9:04         ` [PATCH 8/12 V3] " Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 14:57 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 01/07/2022 15:54, Richard Earnshaw via Gcc-patches wrote:
> 
> 
> On 01/06/2022 13:32, Andrea Corallo via Gcc-patches wrote:
>> Hi all,
>>
>> second iteration of the previous patch adding 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
>>
>> To trigger 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
>>
>> gcc/ChangeLog:
>>
>>     * config/arm/t-rmprofile: Add multilib rules for march +pacbti
>>            and mbranch-protection.
>>
> 
> +# 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
> +
> 
> The documentation mentions -mbranch-protection=standard+leaf, so you're 
> missing a mapping for that.
> 
> 
> OK with that change.
> 
> R.

Oh, and please add some tests to gcc/testsuite/gcc.target/arm/multilib.exp

R.

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

* Re: [PATCH 9/12] arm: Make libgcc bti compatible
  2022-04-28  9:48 ` [PATCH 9/12] arm: Make libgcc bti compatible Andrea Corallo
@ 2022-07-01 15:03   ` Richard Earnshaw
  2022-07-21  9:17     ` [PATCH 9/12 V2] " Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 15:03 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:48, Andrea Corallo via Gcc-patches wrote:
> This change add bti instructions at the beginning of arm specific
> libgcc hand written assembly routines.
> 
> 2022-03-31  Andrea Corallo  <andrea.corallo@arm.com>
> 
> 	* libgcc/config/arm/crti.S (FUNC_START): Add bti instruction if
> 	necessary.
> 	* libgcc/config/arm/lib1funcs.S (THUMB_FUNC_START, FUNC_START):
> 	Likewise.
> 

+#if defined(__ARM_FEATURE_BTI)

Wouldn't it be better to use __ARM_FEATURE_BTI_DEFAULT?  That way we 
only get BTI instructions in multilib variants that have asked for BTI.

R.

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

* Re: [PATCH 10/12 V2] arm: Implement cortex-M return signing address codegen
  2022-06-28  9:17   ` [PATCH 10/12 V2] " Andrea Corallo
@ 2022-07-01 15:43     ` Richard Earnshaw
  2022-08-08  9:33       ` Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 15:43 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/06/2022 10:17, Andrea Corallo via Gcc-patches wrote:
> Hi all,
> 
> second version of this patch enabling 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
> 
> 	* 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
> 
> 	* 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.
> 

@@ -21139,6 +21139,14 @@ arm_compute_save_core_reg_mask (void)

    save_reg_mask |= arm_compute_save_reg0_reg12_mask ();

+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (TARGET_TPCS_FRAME
+	  || (TARGET_TPCS_LEAF_FRAME && crtl->is_leaf))
+	error ("TPCS incompatible with return address signing.");
+      save_reg_mask |= 1 << IP_REGNUM;
+    }
+

This is the wrong place for a test like this as it will be generated 
every time this function is called (which might be more than once per 
compiled function).

However, TPCS frames are only supported for 'thumb-1' code and PACBTI 
needs armv8-m.main (ie Thumb-2), so the test is really pretty pointless 
at the moment.  I think we should just drop the error.

@@ -22302,7 +22310,7 @@ arm_emit_multi_reg_pop (unsigned long 
saved_regs_mask)
      par = emit_insn (par);

    REG_NOTES (par) = dwarf;
-  if (!return_in_pc)
+  if (!return_in_pc && !frame_pointer_needed)
      arm_add_cfa_adjust_cfa_note (par, UNITS_PER_WORD * num_regs,
  				 stack_pointer_rtx, stack_pointer_rtx);
  }

What's this hunk for?  It doesn't seem related to the PAC changes.  Is 
this some generic bug?  If so, it should be pulled out into a separate 
patch.  If not, it needs some comment as to why we do it this way.

@@ -23352,6 +23360,11 @@ output_probe_stack_range (rtx reg1, rtx reg2)
    return "";
  }

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

GNU style requires the function name to be in the first column:

static bool
aarch_bti_enabled ()
{
   ...

@@ -23431,11 +23444,12 @@ 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 ()));
+    && (((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 ()));

This whole statement needs parenthesis around it so that auto-indent 
will work properly:

   clobber_ip
     = (IS_NESTED (func_type)
        && (....
	   || arm_current_function_pac_enabled_p ()));

@@ -23511,6 +23525,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 ());
+    }

What about BTI enabled but PAC not?

@@ -27299,7 +27321,8 @@ 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 ()))

Redundant parenthesis.

@@ -27314,10 +27337,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 ())
+	    {
+	      saved_regs_mask &= ~ (1 << PC_REGNUM);

Is that really needed?  The other cases are changing LR to PC, but I 
don't think PC should already be set as otherwise our calculation of the 
frame size will be incorrect.  Please try it as a gcc_assert() and 
validate this assertion.


+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	      emit_insn (gen_aut_nop ());
+	      emit_jump_insn (simple_return_rtx);


@@ -30541,6 +30578,9 @@ arm_conditional_register_usage (void)
  	global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1;
      }

+  if (TARGET_HAVE_PACBTI)
+    call_used_regs[IP_REGNUM] = 1;
+

Why is this needed?  CALL_USED_REGISTERS already defines IP (r12) as 
call-used.

+++ b/gcc/config/arm/arm.md
@@ -11514,11 +11514,17 @@
  (define_expand "prologue"
    [(clobber (const_int 0))]
    "TARGET_EITHER"
-  "if (TARGET_32BIT)
+  "if (arm_current_function_pac_enabled_p () && !arm_arch8)
+     {
+       error (\"This architecture does not support branch protection 
instructions\");
+       DONE;
+     }

No, this is the wrong place for a test like this.  A check should be 
placed in arm_option_override_internal instead (and normally we warn and 
tweak the options to be something sensible if they conflict).

+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PAC_NOP))]
+  "TARGET_THUMB2"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "2")])

This pattern is missing a type.  The length is also incorrect as the 
instruction is 32-bits (4 bytes).  Similarly for the other instructions 
below.  Also, you need to mark them as incompatible with conditional 
execution (they're constrained-unpredictable in IT blocks).

All of the tests lack checks that the target board can run PAC/BTI.

R.

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

* Re: [PATCH 11/12] aarch64: Make bti pass generic so it can be used by the arm backend
  2022-04-28  9:51 ` [PATCH 11/12] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
  2022-05-06  8:23   ` Richard Sandiford
@ 2022-07-01 15:53   ` Richard Earnshaw
  1 sibling, 0 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 15:53 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/04/2022 10:51, Andrea Corallo via Gcc-patches wrote:
> 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.
> 
> 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.
> 	* config/arm/arm-passes.def: New file.
> 

Is this patch fully stand-alone?  It adds arm-passes.def, which adds a 
reference to pass_insert_bti, but that isn't fully wired up until the 
next patch.

R.

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

* Re: [PATCH 12/12 V2] arm: implement bti injection
  2022-06-28  9:21   ` [PATCH 12/12 V2] " Andrea Corallo
@ 2022-07-01 16:04     ` Richard Earnshaw
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-01 16:04 UTC (permalink / raw)
  To: Andrea Corallo, Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, nd



On 28/06/2022 10:21, Andrea Corallo via Gcc-patches wrote:
> Hi all,
> 
> second iteration of this patch enabling 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.
> 
> 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.
> 
@@ -104,6 +105,14 @@ rest_of_insert_bti (void)
    rtx_insn *insn;
    basic_block bb;

+#if defined (TARGET_32BIT) || defined (TARGET_THUMB1)

See the comment about errors in response to patch 10.  I'd simply expect 
the gate function to be disabled when we can't support PAC, so we should 
never get here.


+  if (!arm_arch8)
+    {
+      error ("This architecture does not support branch protection 
instructions");
+      goto exit;
+    }
+#endif
+
...
+
+rtx aarch_gen_bti_c (void)
+{
+  return gen_bti_nop ();
+}
+
+rtx aarch_gen_bti_j (void)
+{
+  return gen_bti_nop ();
+}
+

Function names should start a new line... Thus:

rtx
aarch_gen_bti_c (void)

etc.

+(define_insn "bti_nop"
+  [(unspec_volatile [(const_int 0)] UNSPEC_BTI_NOP)]
+  "TARGET_THUMB2"

This isn't quite right.  We need v8-m.main as the baseline architecture 
for the NOPs to behave as NOPs.

+  "bti"
+  [(set_attr "type" "mov_reg")])
+

How to deal with architectural NOPs is an interesting question.  I think 
really, for the scheduler we need to describe each newly defined NOP 
separately, then in the scheduling descriptions we can handle all 
unimplemented NOPs by grouping them together for that architecture, 
whilst describing more accurately how to handle them on CPUs where they 
acquire a defined behaviour.

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"

--- 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

See comment on patch 11.  Perhaps the right thing to do is to move the 
hunk that adds arm-passes.def into this patch.

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

* [PATCH 3/12 V2] arm: Add option -mbranch-protection
  2022-07-01 10:59   ` Richard Earnshaw
@ 2022-07-04  9:27     ` Andrea Corallo
  2022-07-04 10:55       ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-07-04  9:27 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

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

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

[...]

> +@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}.
> +
> +The default is to generate code without branch protection or return
> +address signing.
>
> This needs to make it clear that -mbranch-protection != none is only
> supported on armv8-m.main or later.
>
> R.

Hi Richard,

thanks for reviewing, please find attached the respinned patch.

Ok for trunk (when the rest of the series will be approved)?

Best Regards

  Andrea

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>


[-- Attachment #2: 3-12.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] 53+ messages in thread

* Re: [PATCH 3/12 V2] arm: Add option -mbranch-protection
  2022-07-04  9:27     ` [PATCH 3/12 V2] " Andrea Corallo
@ 2022-07-04 10:55       ` Richard Earnshaw
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-04 10:55 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 04/07/2022 10:27, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
> [...]
> 
>> +@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}.
>> +
>> +The default is to generate code without branch protection or return
>> +address signing.
>>
>> This needs to make it clear that -mbranch-protection != none is only
>> supported on armv8-m.main or later.
>>
>> R.
> 
> Hi Richard,
> 
> thanks for reviewing, please find attached the respinned patch.
> 
> Ok for trunk (when the rest of the series will be approved)?
> 
> Best Regards
> 
>    Andrea
> 
> 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>
> 

OK.

R.

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

* Re: [PATCH 4/12] arm: Add testsuite library support for PACBTI target
  2022-07-01 14:17     ` Richard Earnshaw
@ 2022-07-04 14:47       ` Andrea Corallo
  2022-07-05 10:05         ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-07-04 14:47 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

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

> On 01/07/2022 14:03, Richard Earnshaw via Gcc-patches wrote:
>> On 28/04/2022 10:40, Andrea Corallo via Gcc-patches wrote:
>>> Add 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>
>>>
>> +proc check_effective_target_arm_pacbti_hw {} {
>> +    return [check_runtime arm_pacbti_hw_available {
>> +    __attribute__ ((naked)) int
>> +    main (void)
>> +    {
>> +      asm ("pac r12, lr, sp");
>> So the armv8-m Arm ARM says that this instruction is in the NOP
>> space and that it is undefined if we aren't armv8-m.main or higher.
>> +      asm ("mov r0, #0");
>> +      asm ("autg r12, lr, sp");
>> This isn't in the nop space, but the Arm ARM says it is
>> unpredictable if the extension isn't present.  Unfortunately, that
>> means this isn't a particularly reliable way of detecting that the
>> PACBTI feature is present.
>> However, I can't think off hand of more reliable way of testing this
>> since reading the feature register ID_ISAR5 is not possible when in
>> unprivileged mode.
>> So I think we'll have to live with this.
>> +      asm ("bx lr");
>> +    }
>> +    } ""]
>> OK.
>> 
>
> Or perhaps not. The test does not try to add the right options to
> enable PAC/BTI if those aren't in the default selection for the
> current testsuite run.
>
> Perhaps we also need some additional tests to work out what
> architecture options to add (if any) to ensure the test will at least
> assemble.

Hi Richard,
thanks for reviewing.

Wouldn't be sufficient for that to have this test compiled with
-march=armv8-m.main?

BR

  Andrea

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

* Re: [PATCH 4/12] arm: Add testsuite library support for PACBTI target
  2022-07-04 14:47       ` Andrea Corallo
@ 2022-07-05 10:05         ` Richard Earnshaw
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-05 10:05 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd



On 04/07/2022 15:47, Andrea Corallo wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 01/07/2022 14:03, Richard Earnshaw via Gcc-patches wrote:
>>> On 28/04/2022 10:40, Andrea Corallo via Gcc-patches wrote:
>>>> Add 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 
> <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>
>>>>
>>> +proc check_effective_target_arm_pacbti_hw {} {
>>> +    return [check_runtime arm_pacbti_hw_available {
>>> +    __attribute__ ((naked)) int
>>> +    main (void)
>>> +    {
>>> +      asm ("pac r12, lr, sp");
>>> So the armv8-m Arm ARM says that this instruction is in the NOP
>>> space and that it is undefined if we aren't armv8-m.main or higher.
>>> +      asm ("mov r0, #0");
>>> +      asm ("autg r12, lr, sp");
>>> This isn't in the nop space, but the Arm ARM says it is
>>> unpredictable if the extension isn't present.  Unfortunately, that
>>> means this isn't a particularly reliable way of detecting that the
>>> PACBTI feature is present.
>>> However, I can't think off hand of more reliable way of testing this
>>> since reading the feature register ID_ISAR5 is not possible when in
>>> unprivileged mode.
>>> So I think we'll have to live with this.
>>> +      asm ("bx lr");
>>> +    }
>>> +    } ""]
>>> OK.
>>> 
>>
>> Or perhaps not. The test does not try to add the right options to
>> enable PAC/BTI if those aren't in the default selection for the
>> current testsuite run.
>>
>> Perhaps we also need some additional tests to work out what
>> architecture options to add (if any) to ensure the test will at least
>> assemble.
> 
> Hi Richard,
> thanks for reviewing.
> 
> Wouldn't be sufficient for that to have this test compiled with
> -march=armv8-m.main?

Take a look at how, for example, check_effective_target_arm_mve_hw (and 
add_options_for_v8_1_m_mve_fp) is implemented.

R.

> 
> BR
> 
>    Andrea

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

* [PATCH 5/12 V2] arm: Implement target feature macros for PACBTI
  2022-07-01 14:26   ` Richard Earnshaw
@ 2022-07-12 15:45     ` Andrea Corallo
  2022-07-21 11:01       ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-07-12 15:45 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

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

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

> On 28/04/2022 10:42, Andrea Corallo via Gcc-patches wrote:
>> 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/ChangeLog:
>> 	* config/arm/arm-c.c (arm_cpu_builtins): Define
>> 	__ARM_FEATURE_BTI_DEFAULT, __ARM_FEATURE_PAC_DEFAULT,
>> 	__ARM_FEATURE_PAUTH and __ARM_FEATURE_BTI.
>
> This bit is OK.
>
>> gcc/testsuite/ChangeLog:
>> 	* gcc.target/arm/acle/pacbti-m-predef-2.c: New test.
>> 	* gcc.target/arm/acle/pacbti-m-predef-4.c: New test.
>> 	* gcc.target/arm/acle/pacbti-m-predef-5.c: New test.
>> 
>
> These are all execution tests.  I think we also need some compile-only
> tests so that we get better coverage when the target does not directly
> support PACBTI.
>
> We also need some tests for the defines when targetting armv8-m.main
> and some tests for checking __ARM_FEATURE_BTI and __ARM_FEATURE_PAC
> (the tests here check only the '..._DEFAULT' macros.

Hi Richard & all,

please find attached the updated version of this patch.

Best Regards

  Andrea

gcc/ChangeLog:

	* 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/ChangeLog:

	* 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.


[-- Attachment #2: 0001-PATCH-5-12-arm-Implement-target-feature-macros-for-P.patch --]
[-- Type: text/plain, Size: 9128 bytes --]

From d1897ca2db828d214a6591ab34f29cf42ebd2fb6 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Mon, 6 Dec 2021 11:39:59 +0100
Subject: [PATCH] [PATCH 5/12] arm: Implement target feature macros for PACBTI

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/ChangeLog:

	* 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/ChangeLog:

	* 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>
---
 gcc/config/arm/arm-c.cc                       | 18 ++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-10.c  | 10 ++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-11.c  | 10 ++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-12.c  | 10 ++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-2.c   | 24 +++++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-4.c   | 21 ++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-5.c   | 24 +++++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-8.c   | 11 +++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-9.c   | 10 ++++++++
 9 files changed, 138 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-12.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-4.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-8.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-9.c

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..311cf572dd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=bti+pac-ret" } */
+
+#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..2663551e18a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { 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..01a53c0b536
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-12.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.1-m.main" } */
+
+#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..4394fd147d7
--- /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 arm_pacbti_hw } */
+/* { dg-additional-options " -mbranch-protection=bti+pac-ret+leaf" } */
+
+#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..90f0c724b9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-4.c
@@ -0,0 +1,21 @@
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-additional-options " -mbranch-protection=pac-ret" } */
+
+#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..c865809b8b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
@@ -0,0 +1,24 @@
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-additional-options " -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..d5d069cbc89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-8.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=bti+pac-ret+leaf" } */
+
+#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..f301beba0c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-9.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=pac-ret" } */
+
+#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
-- 
2.25.1


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

* [PATCH 7/12 V2] arm: Emit build attributes for PACBTI target feature
  2022-07-01 14:49   ` Richard Earnshaw
@ 2022-07-13  8:58     ` Andrea Corallo
  2022-07-21 11:03       ` Richard Earnshaw
  2022-07-22 14:57     ` Andrea Corallo
  1 sibling, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-07-13  8:58 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

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

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

> On 28/04/2022 10:45, 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.
>
> This bit is OK.
>
>> 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.
>
> These tests contain directives like:
>
> +/* { dg-additional-options " -mbranch-protection=pac-ret+bti
> --save-temps" } */
>
> But they don't check that the architecture permits this (it has to be
> armv8-m.main or later).

Hi Richard & all,

please find attached the updated patch.

BR

 Andrea


[-- Attachment #2: 0001-PATCH-7-12-arm-Emit-build-attributes-for-PACBTI-targ.patch --]
[-- Type: text/plain, Size: 6532 bytes --]

From 7d66e00bf62c8624d03e0173be8b8631d7435c38 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Mon, 6 Dec 2021 11:42:24 +0100
Subject: [PATCH] [PATCH 7/12] 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>
---
 gcc/config/arm/arm.cc                          | 18 ++++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-1.c    | 16 ++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-3.c    | 16 ++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-6.c    | 15 +++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-7.c    | 16 ++++++++++++++++
 5 files changed, 81 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-3.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-6.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-7.c

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..d3ef58fcf9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+bti --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..c82c3a4b638
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf --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..211c4753808
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-6.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.1-m.main -mbranch-protection=bti --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..48a40e64c11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-7.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.1-m.main+pacbti --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 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" } } */
-- 
2.25.1


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

* [PATCH 8/12 V3] arm: Introduce multilibs for PACBTI target feature
  2022-07-01 14:57       ` Richard Earnshaw
@ 2022-07-21  9:04         ` Andrea Corallo
  2022-07-21 11:09           ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-07-21  9:04 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

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

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

[...]

>> The documentation mentions -mbranch-protection=standard+leaf, so
>> you're missing a mapping for that.
>> OK with that change.
>> R.
>
> Oh, and please add some tests to gcc/testsuite/gcc.target/arm/multilib.exp
>
> R.

Hi Richard,

thanks, here the updated patch.

PS I've also added three mlibarch -> march matches that were missing.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-8-12-arm-Introduce-multilibs-for-PACBTI-target.patch --]
[-- Type: text/plain, Size: 7083 bytes --]

From bbd0efb375c08981be7632319b24830196429e9b Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Mon, 6 Dec 2021 11:42:59 +0100
Subject: [PATCH] [PATCH 8/12] arm: Introduce multilibs for PACBTI target
 feature

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

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.
---
 gcc/config/arm/t-rmprofile                | 29 +++++++++++++++++++++--
 gcc/testsuite/gcc.target/arm/multilib.exp |  6 +++++
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/gcc/config/arm/t-rmprofile b/gcc/config/arm/t-rmprofile
index eb321e832f1..c50bf4b3557 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,14 @@ 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 +98,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"
-- 
2.25.1


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

* [PATCH 9/12 V2] arm: Make libgcc bti compatible
  2022-07-01 15:03   ` Richard Earnshaw
@ 2022-07-21  9:17     ` Andrea Corallo
  2022-07-21 11:41       ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-07-21  9:17 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

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

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

> On 28/04/2022 10:48, Andrea Corallo via Gcc-patches wrote:
>> This change add bti instructions at the beginning of arm specific
>> libgcc hand written assembly routines.
>> 2022-03-31  Andrea Corallo  <andrea.corallo@arm.com>
>> 	* libgcc/config/arm/crti.S (FUNC_START): Add bti instruction
>> if
>> 	necessary.
>> 	* libgcc/config/arm/lib1funcs.S (THUMB_FUNC_START, FUNC_START):
>> 	Likewise.
>> 
>
> +#if defined(__ARM_FEATURE_BTI)
>
> Wouldn't it be better to use __ARM_FEATURE_BTI_DEFAULT?  That way we
> only get BTI instructions in multilib variants that have asked for
> BTI.
>
> R.

Hi Richard,

good point, yes I think so.

Please find attached the updated patch.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-9-12-arm-Make-libgcc-bti-compatible.patch --]
[-- Type: text/plain, Size: 1561 bytes --]

From 6975c9ddbc8a4b790a765589c6fd07fea92173e5 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Tue, 8 Feb 2022 10:58:31 +0100
Subject: [PATCH] [PATCH 9/12] arm: Make libgcc bti compatible

This change add bti instructions at the beginning of arm specific
libgcc hand written assembly routines.

2022-03-31  Andrea Corallo  <andrea.corallo@arm.com>

	* libgcc/config/arm/crti.S (FUNC_START): Add bti instruction if
	necessary.
	* libgcc/config/arm/lib1funcs.S (THUMB_FUNC_START, FUNC_START):
	Likewise.
---
 libgcc/config/arm/crti.S      | 4 +++-
 libgcc/config/arm/lib1funcs.S | 6 ++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/libgcc/config/arm/crti.S b/libgcc/config/arm/crti.S
index 0192972a7e6..4098353af1c 100644
--- a/libgcc/config/arm/crti.S
+++ b/libgcc/config/arm/crti.S
@@ -51,7 +51,9 @@
 .macro FUNC_START
 #ifdef __thumb__
 	.thumb
-	
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+	bti
+#endif
 	push	{r3, r4, r5, r6, r7, lr}
 #else
 	.arm
diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S
index 8c39c9f20a2..de98edcc300 100644
--- a/libgcc/config/arm/lib1funcs.S
+++ b/libgcc/config/arm/lib1funcs.S
@@ -345,6 +345,9 @@ LSYM(Ldiv0):
 	TYPE	(\name)
 	.thumb_func
 SYM (\name):
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+	bti
+#endif
 .endm
 
 /* Function start macros.  Variants for ARM and Thumb.  */
@@ -372,6 +375,9 @@ SYM (\name):
 	THUMB_FUNC
 	THUMB_SYNTAX
 SYM (__\name):
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+	bti
+#endif
 .endm
 
 .macro ARM_SYM_START name
-- 
2.25.1


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

* Re: [PATCH 5/12 V2] arm: Implement target feature macros for PACBTI
  2022-07-12 15:45     ` [PATCH 5/12 V2] " Andrea Corallo
@ 2022-07-21 11:01       ` Richard Earnshaw
  2022-07-22 10:35         ` [PATCH 5/12 V3] " Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-21 11:01 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 12/07/2022 16:45, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 28/04/2022 10:42, Andrea Corallo via Gcc-patches wrote:
>>> 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/ChangeLog:
>>> 	* config/arm/arm-c.c (arm_cpu_builtins): Define
>>> 	__ARM_FEATURE_BTI_DEFAULT, __ARM_FEATURE_PAC_DEFAULT,
>>> 	__ARM_FEATURE_PAUTH and __ARM_FEATURE_BTI.
>>
>> This bit is OK.
>>
>>> gcc/testsuite/ChangeLog:
>>> 	* gcc.target/arm/acle/pacbti-m-predef-2.c: New test.
>>> 	* gcc.target/arm/acle/pacbti-m-predef-4.c: New test.
>>> 	* gcc.target/arm/acle/pacbti-m-predef-5.c: New test.
>>>
>>
>> These are all execution tests.  I think we also need some compile-only
>> tests so that we get better coverage when the target does not directly
>> support PACBTI.
>>
>> We also need some tests for the defines when targetting armv8-m.main
>> and some tests for checking __ARM_FEATURE_BTI and __ARM_FEATURE_PAC
>> (the tests here check only the '..._DEFAULT' macros.
> 
> Hi Richard & all,
> 
> please find attached the updated version of this patch.
> 
> Best Regards
> 
>    Andrea
> 
> gcc/ChangeLog:
> 
> 	* 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/ChangeLog:
> 
> 	* 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.
> 

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..311cf572dd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=bti+pac-ret" } */

This is not enough.  For example, if the testsuite is being run with 
"-march=armv6-m" as the testrun options, we'll get an error that will 
cause a test failure.  You need to run a pre-test rule that validates 
that adding -mbranch-protection is safe.

+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.1-m.main+pacbti" } */

Similarly here, this would conflict with, for example, "-marm" as test 
options.

+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
@@ -0,0 +1,24 @@
+
+/* { dg-do run } */

Blank line at the start of the test.

The other tests have similar issues.

R.

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

* Re: [PATCH 7/12 V2] arm: Emit build attributes for PACBTI target feature
  2022-07-13  8:58     ` [PATCH 7/12 V2] " Andrea Corallo
@ 2022-07-21 11:03       ` Richard Earnshaw
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-21 11:03 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 13/07/2022 09:58, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 28/04/2022 10:45, 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.
>>
>> This bit is OK.
>>
>>> 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.
>>
>> These tests contain directives like:
>>
>> +/* { dg-additional-options " -mbranch-protection=pac-ret+bti
>> --save-temps" } */
>>
>> But they don't check that the architecture permits this (it has to be
>> armv8-m.main or later).
> 
> Hi Richard & all,
> 
> please find attached the updated patch.
> 
> BR
> 
>   Andrea
> 

The tests in this patch have similar issues to my previous reply.  You 
need to make sure that adding options will not cause a conflict with 
other options added by the test driver.

R.

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

* Re: [PATCH 8/12 V3] arm: Introduce multilibs for PACBTI target feature
  2022-07-21  9:04         ` [PATCH 8/12 V3] " Andrea Corallo
@ 2022-07-21 11:09           ` Richard Earnshaw
  0 siblings, 0 replies; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-21 11:09 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 21/07/2022 10:04, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
> [...]
> 
>>> The documentation mentions -mbranch-protection=standard+leaf, so
>>> you're missing a mapping for that.
>>> OK with that change.
>>> R.
>>
>> Oh, and please add some tests to gcc/testsuite/gcc.target/arm/multilib.exp
>>
>> R.
> 
> Hi Richard,
> 
> thanks, here the updated patch.
> 
> PS I've also added three mlibarch -> march matches that were missing.
> 
> BR
> 
>    Andrea
> 

+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

Just one blank line between sections.

Otherwise OK.

R.

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

* Re: [PATCH 9/12 V2] arm: Make libgcc bti compatible
  2022-07-21  9:17     ` [PATCH 9/12 V2] " Andrea Corallo
@ 2022-07-21 11:41       ` Richard Earnshaw
  2022-07-22 15:09         ` Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-21 11:41 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches

On 21/07/2022 10:17, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 28/04/2022 10:48, Andrea Corallo via Gcc-patches wrote:
>>> This change add bti instructions at the beginning of arm specific
>>> libgcc hand written assembly routines.
>>> 2022-03-31  Andrea Corallo  <andrea.corallo@arm.com>
>>> 	* libgcc/config/arm/crti.S (FUNC_START): Add bti instruction
>>> if
>>> 	necessary.
>>> 	* libgcc/config/arm/lib1funcs.S (THUMB_FUNC_START, FUNC_START):
>>> 	Likewise.
>>>
>>
>> +#if defined(__ARM_FEATURE_BTI)
>>
>> Wouldn't it be better to use __ARM_FEATURE_BTI_DEFAULT?  That way we
>> only get BTI instructions in multilib variants that have asked for
>> BTI.
>>
>> R.
> 
> Hi Richard,
> 
> good point, yes I think so.
> 
> Please find attached the updated patch.
> 
> BR
> 
>    Andrea
> 

I've been pondering this patch.  The way it is implemented would put a 
BTI instruction at the start of every assembler routine in libgcc.  But 
the vast majority of functions in libgcc cannot have their address 
taken, so a BTI isn't needed (BTI is only needed when an indirect jump 
could be used).  So I wonder if we really need to do this so aggressively?

Perhaps a better approach would be to define a macro (eg MAYBEBTI) which 
expands a BTI if the compilation requires it and nothing otherwise), and 
then manually insert that in any functions that really need this (if any).

R.

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

* [PATCH 5/12 V3] arm: Implement target feature macros for PACBTI
  2022-07-21 11:01       ` Richard Earnshaw
@ 2022-07-22 10:35         ` Andrea Corallo
  2022-07-22 14:34           ` [PATCH 5/12 V4] " Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-07-22 10:35 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches

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

Hi Richard,

thanks for reviewing.

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

[...]

> 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..311cf572dd9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options " -mbranch-protection=bti+pac-ret" } */
>
> This is not enough.  For example, if the testsuite is being run with
> "-march=armv6-m" as the testrun options, we'll get an error that will
> cause a test failure.  You need to run a pre-test rule that validates
> that adding -mbranch-protection is safe.

Right, please find attached the updated patch, it should fix this and
the mentioned spacing issue.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-5-12-arm-Implement-target-feature-macros-for-P.patch --]
[-- Type: text/plain, Size: 10140 bytes --]

From d5e0c5c0c4a3a07eb6a65c7626f474a0dbd4f8db Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Mon, 6 Dec 2021 11:39:59 +0100
Subject: [PATCH] [PATCH 5/12] arm: Implement target feature macros for PACBTI

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>
---
 gcc/config/arm/arm-c.cc                       | 18 +++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-10.c  | 11 +++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-11.c  | 11 +++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-12.c  | 11 +++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-2.c   | 23 +++++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-4.c   | 20 ++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-5.c   | 23 +++++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-8.c   | 11 +++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-9.c   | 10 ++++++++
 gcc/testsuite/lib/target-supports.exp         | 10 ++++++++
 10 files changed, 148 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-12.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-4.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-8.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-9.c

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..4fcc96f3eb4
--- /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 " -mbranch-protection=bti+pac-ret" } */
+
+#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..2437140992f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { 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..9e97f99c33d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-12.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main" } */
+
+#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..bd29806c326
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-additional-options " -mbranch-protection=bti+pac-ret+leaf" } */
+
+#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..88e7957486d
--- /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-additional-options " -mbranch-protection=pac-ret" } */
+
+#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..17e3543ab8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-additional-options " -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..d5d069cbc89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-8.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=bti+pac-ret+leaf" } */
+
+#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..f301beba0c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-9.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options " -mbranch-protection=pac-ret" } */
+
+#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 df8ab037fb3..62e41d1e8d4 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.
 
-- 
2.25.1


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

* [PATCH 5/12 V4] arm: Implement target feature macros for PACBTI
  2022-07-22 10:35         ` [PATCH 5/12 V3] " Andrea Corallo
@ 2022-07-22 14:34           ` Andrea Corallo
  0 siblings, 0 replies; 53+ messages in thread
From: Andrea Corallo @ 2022-07-22 14:34 UTC (permalink / raw)
  To: Andrea Corallo via Gcc-patches; +Cc: Richard Earnshaw, Richard Earnshaw, nd

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

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

> Hi Richard,
>
> thanks for reviewing.
>
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>
> [...]
>
>> 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..311cf572dd9
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
>> @@ -0,0 +1,10 @@
>> +/* { dg-do compile } */
>> +/* { dg-additional-options " -mbranch-protection=bti+pac-ret" } */
>>
>> This is not enough.  For example, if the testsuite is being run with
>> "-march=armv6-m" as the testrun options, we'll get an error that will
>> cause a test failure.  You need to run a pre-test rule that validates
>> that adding -mbranch-protection is safe.
>
> Right, please find attached the updated patch, it should fix this and
> the mentioned spacing issue.

Scratch that, I think the attached is better.

Sorry for the noise.

  Andrea


[-- Attachment #2: 0001-PATCH-5-12-arm-Implement-target-feature-macros-for-P.patch --]
[-- Type: text/plain, Size: 10324 bytes --]

From 0238ad4a53b78b8458ed254d0cb226457b6a76de Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Mon, 6 Dec 2021 11:39:59 +0100
Subject: [PATCH] [PATCH 5/12] arm: Implement target feature macros for PACBTI

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>
---
 gcc/config/arm/arm-c.cc                       | 18 +++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-10.c  | 11 +++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-11.c  | 11 +++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-12.c  | 11 +++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-2.c   | 23 +++++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-4.c   | 20 ++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-5.c   | 23 +++++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-8.c   | 12 ++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-9.c   | 11 +++++++++
 gcc/testsuite/lib/target-supports.exp         | 10 ++++++++
 10 files changed, 150 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-10.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-11.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-12.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-4.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-8.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-9.c

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..4fcc96f3eb4
--- /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 " -mbranch-protection=bti+pac-ret" } */
+
+#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..47d4ac2ab9a
--- /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=*" } } */
+/* { 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..ea95f7c7b91
--- /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.1-m.main" } */
+
+#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..bd29806c326
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-2.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-additional-options " -mbranch-protection=bti+pac-ret+leaf" } */
+
+#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..88e7957486d
--- /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-additional-options " -mbranch-protection=pac-ret" } */
+
+#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..17e3543ab8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-5.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-additional-options " -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..ffae0d2a24e
--- /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 " -mbranch-protection=bti+pac-ret+leaf" } */
+
+#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..4dde64b827c
--- /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 " -mbranch-protection=pac-ret" } */
+
+#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 df8ab037fb3..62e41d1e8d4 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.
 
-- 
2.25.1


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

* [PATCH 7/12 V2] arm: Emit build attributes for PACBTI target feature
  2022-07-01 14:49   ` Richard Earnshaw
  2022-07-13  8:58     ` [PATCH 7/12 V2] " Andrea Corallo
@ 2022-07-22 14:57     ` Andrea Corallo
  1 sibling, 0 replies; 53+ messages in thread
From: Andrea Corallo @ 2022-07-22 14:57 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

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

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

> On 28/04/2022 10:45, 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.
>
> This bit is OK.
>
>> 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.
>
> These tests contain directives like:
>
> +/* { dg-additional-options " -mbranch-protection=pac-ret+bti
> --save-temps" } */
>
> But they don't check that the architecture permits this (it has to be
> armv8-m.main or later).

Hi Richard,

please find attached the respinned version of the patch.

BR

  Andrea


[-- Attachment #2: 0001-PATCH-7-12-arm-Emit-build-attributes-for-PACBTI-targ.patch --]
[-- Type: text/plain, Size: 6810 bytes --]

From b89ac2dc737593a290345cb96c5d9b048e731bf4 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Mon, 6 Dec 2021 11:42:24 +0100
Subject: [PATCH] [PATCH 7/12] 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>
---
 gcc/config/arm/arm.cc                          | 18 ++++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-1.c    | 17 +++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-3.c    | 17 +++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-6.c    | 16 ++++++++++++++++
 .../gcc.target/arm/acle/pacbti-m-predef-7.c    | 17 +++++++++++++++++
 5 files changed, 85 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-3.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-6.c
 create mode 100644 gcc/testsuite/gcc.target/arm/acle/pacbti-m-predef-7.c

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..225b44de80a
--- /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-additional-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+bti --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..1eae39edfe2
--- /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-additional-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf --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..b49c6c4cc6f
--- /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 -mbranch-protection=bti --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..006e66520a2
--- /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 --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 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" } } */
-- 
2.25.1


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

* Re: [PATCH 9/12 V2] arm: Make libgcc bti compatible
  2022-07-21 11:41       ` Richard Earnshaw
@ 2022-07-22 15:09         ` Andrea Corallo
  2022-07-25 10:41           ` Richard Earnshaw
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-07-22 15:09 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches

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

> On 21/07/2022 10:17, Andrea Corallo via Gcc-patches wrote:
>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>> 
>>> On 28/04/2022 10:48, Andrea Corallo via Gcc-patches wrote:
>>>> This change add bti instructions at the beginning of arm specific
>>>> libgcc hand written assembly routines.
>>>> 2022-03-31  Andrea Corallo  <andrea.corallo@arm.com>
>>>> 	* libgcc/config/arm/crti.S (FUNC_START): Add bti instruction
>>>> if
>>>> 	necessary.
>>>> 	* libgcc/config/arm/lib1funcs.S (THUMB_FUNC_START, FUNC_START):
>>>> 	Likewise.
>>>>
>>>
>>> +#if defined(__ARM_FEATURE_BTI)
>>>
>>> Wouldn't it be better to use __ARM_FEATURE_BTI_DEFAULT?  That way we
>>> only get BTI instructions in multilib variants that have asked for
>>> BTI.
>>>
>>> R.
>> Hi Richard,
>> good point, yes I think so.
>> Please find attached the updated patch.
>> BR
>>    Andrea
>> 
>
> I've been pondering this patch.  The way it is implemented would put a
> BTI instruction at the start of every assembler routine in libgcc.
> But the vast majority of functions in libgcc cannot have their address
> taken, so a BTI isn't needed (BTI is only needed when an indirect jump
> could be used).  So I wonder if we really need to do this so
> aggressively?
>
> Perhaps a better approach would be to define a macro (eg MAYBEBTI)
> which expands a BTI if the compilation requires it and nothing
> otherwise), and then manually insert that in any functions that really
> need this (if any).

I guess the main downside of this approach would be the maintanace
burden, we'll have to remember forever that every time an asm function
is called by function pointer we have to add the bti landing pad
manually, otherwise this will be broken when pacbti enabled. WDYT?

If we want to go this way I'll start reworking the patch in this
direction (tho this might not be trivial).

BR

  Andrea

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

* Re: [PATCH 9/12 V2] arm: Make libgcc bti compatible
  2022-07-22 15:09         ` Andrea Corallo
@ 2022-07-25 10:41           ` Richard Earnshaw
  2022-12-12 14:54             ` Andrea Corallo
  0 siblings, 1 reply; 53+ messages in thread
From: Richard Earnshaw @ 2022-07-25 10:41 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches



On 22/07/2022 16:09, Andrea Corallo via Gcc-patches wrote:
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
>> On 21/07/2022 10:17, Andrea Corallo via Gcc-patches wrote:
>>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>>
>>>> On 28/04/2022 10:48, Andrea Corallo via Gcc-patches wrote:
>>>>> This change add bti instructions at the beginning of arm specific
>>>>> libgcc hand written assembly routines.
>>>>> 2022-03-31  Andrea Corallo  <andrea.corallo@arm.com>
>>>>> 	* libgcc/config/arm/crti.S (FUNC_START): Add bti instruction
>>>>> if
>>>>> 	necessary.
>>>>> 	* libgcc/config/arm/lib1funcs.S (THUMB_FUNC_START, FUNC_START):
>>>>> 	Likewise.
>>>>>
>>>>
>>>> +#if defined(__ARM_FEATURE_BTI)
>>>>
>>>> Wouldn't it be better to use __ARM_FEATURE_BTI_DEFAULT?  That way we
>>>> only get BTI instructions in multilib variants that have asked for
>>>> BTI.
>>>>
>>>> R.
>>> Hi Richard,
>>> good point, yes I think so.
>>> Please find attached the updated patch.
>>> BR
>>>     Andrea
>>>
>>
>> I've been pondering this patch.  The way it is implemented would put a
>> BTI instruction at the start of every assembler routine in libgcc.
>> But the vast majority of functions in libgcc cannot have their address
>> taken, so a BTI isn't needed (BTI is only needed when an indirect jump
>> could be used).  So I wonder if we really need to do this so
>> aggressively?
>>
>> Perhaps a better approach would be to define a macro (eg MAYBEBTI)
>> which expands a BTI if the compilation requires it and nothing
>> otherwise), and then manually insert that in any functions that really
>> need this (if any).
> 
> I guess the main downside of this approach would be the maintanace
> burden, we'll have to remember forever that every time an asm function
> is called by function pointer we have to add the bti landing pad
> manually, otherwise this will be broken when pacbti enabled. WDYT?
> 
> If we want to go this way I'll start reworking the patch in this
> direction (tho this might not be trivial).
> 

Yes, it's a trade-off.  The lazy way, however, costs all users even if a 
function is never addressed (which I think is the case for practically 
all functions in libgcc).

So I think in this case it's worth taking that extra development pain.

R.
> BR
> 
>    Andrea

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

* Re: [PATCH 10/12 V2] arm: Implement cortex-M return signing address codegen
  2022-07-01 15:43     ` Richard Earnshaw
@ 2022-08-08  9:33       ` Andrea Corallo
  2022-10-20 14:53         ` Kyrylo Tkachov
  0 siblings, 1 reply; 53+ messages in thread
From: Andrea Corallo @ 2022-08-08  9:33 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd

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

[...]

> +(define_insn "pac_nop"
> +  [(set (reg:SI IP_REGNUM)
> +	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
> +                   UNSPEC_PAC_NOP))]
> +  "TARGET_THUMB2"
> +  "pac\t%|ip, %|lr, %|sp"
> +  [(set_attr "length" "2")])
>
> This pattern is missing a type.

Which type do you think is missing?

> The length is also incorrect as the
> instruction is 32-bits (4 bytes).

Ack.

> Similarly for the other
> instructions below.  Also, you need to mark them as incompatible with
> conditional execution (they're constrained-unpredictable in IT
> blocks).

I guess this would translate in setting it with '(set_attr "predicable" "no")'

But isn't this already the default?

Thanks

  Andrea

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

* RE: [PATCH 10/12 V2] arm: Implement cortex-M return signing address codegen
  2022-08-08  9:33       ` Andrea Corallo
@ 2022-10-20 14:53         ` Kyrylo Tkachov
  0 siblings, 0 replies; 53+ messages in thread
From: Kyrylo Tkachov @ 2022-10-20 14:53 UTC (permalink / raw)
  To: Andrea Corallo, Richard Earnshaw
  Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches

(Sorry, this is a very late reply)

> -----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, August 8, 2022 10:34 AM
> To: Richard Earnshaw <Richard.Earnshaw@foss.arm.com>
> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; nd <nd@arm.com>;
> Andrea Corallo via Gcc-patches <gcc-patches@gcc.gnu.org>
> Subject: Re: [PATCH 10/12 V2] arm: Implement cortex-M return signing
> address codegen
> 
> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
> 
> [...]
> 
> > +(define_insn "pac_nop"
> > +  [(set (reg:SI IP_REGNUM)
> > +	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
> > +                   UNSPEC_PAC_NOP))]
> > +  "TARGET_THUMB2"
> > +  "pac\t%|ip, %|lr, %|sp"
> > +  [(set_attr "length" "2")])
> >
> > This pattern is missing a type.
> 
> Which type do you think is missing?
> 
> > The length is also incorrect as the
> > instruction is 32-bits (4 bytes).
> 
> Ack.
> 
> > Similarly for the other
> > instructions below.  Also, you need to mark them as incompatible with
> > conditional execution (they're constrained-unpredictable in IT
> > blocks).
> 
> I guess this would translate in setting it with '(set_attr "predicable" "no")'
> 
> But isn't this already the default?

I think Richard means the "conds" attribute. It's something I'd like to see cleaned from the arm backend eventually, but for now there's a (very) late condexec pass that can generate conditional instructions based on that attribute.
Basically, it needs to be set to "undconditional" for these instructions.
Thanks,
Kyrill

> 
> Thanks
> 
>   Andrea

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

* [PATCH 6/12 V2] arm: Add pointer authentication for stack-unwinding runtime
  2022-07-01 14:41   ` Richard Earnshaw
@ 2022-11-09 11:17     ` Andrea Corallo
  0 siblings, 0 replies; 53+ messages in thread
From: Andrea Corallo @ 2022-11-09 11:17 UTC (permalink / raw)
  To: Richard Earnshaw
  Cc: Andrea Corallo via Gcc-patches, Richard Earnshaw, nd,
	Srinath Parvathaneni

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

Hi all,

please find attached the latest version of this patch now updating the
stack pointer value after the pop used to read the PAC value.

Best Regards

  Andrea


[-- Attachment #2: 0001-PATCH-6-15-arm-Add-pointer-authentication-for-stack-.patch --]
[-- Type: text/plain, Size: 6589 bytes --]

From a78acf8804daa3d493b419b4998f4ac705869ff9 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.corallo@arm.com>
Date: Mon, 6 Dec 2021 11:42:11 +0100
Subject: [PATCH] [PATCH 6/15] arm: Add pointer authentication for
 stack-unwinding runtime

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.

Pre-approved with the requested changes here
<https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586555.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>
Co-Authored-By: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
---
 gcc/ginclude/unwind-arm-common.h |  3 ++-
 libgcc/config/arm/pr-support.c   | 32 ++++++++++++++++++++++++++++++++
 libgcc/config/arm/unwind-arm.c   | 28 ++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)

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..9acb3de6bc3 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,16 @@ _Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
       }
       return _UVRSR_OK;
 
+    case _UVRSC_PAC:
+      {
+	_uw *ptr = (_uw *) vrs->core.r[R_SP];
+	if (discriminator != 0)
+	  return _UVRSR_FAILED;
+	vrs->pseudo.pac = *(ptr++);
+	vrs->core.r[R_SP] = (_uw) ptr;
+	return _UVRSR_OK;
+      }
+
     case _UVRSC_VFP:
       {
 	_uw start = discriminator >> 16;
-- 
2.25.1


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

* Re: [PATCH 9/12 V2] arm: Make libgcc bti compatible
  2022-07-25 10:41           ` Richard Earnshaw
@ 2022-12-12 14:54             ` Andrea Corallo
  0 siblings, 0 replies; 53+ messages in thread
From: Andrea Corallo @ 2022-12-12 14:54 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Richard Earnshaw, nd, Andrea Corallo via Gcc-patches

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

> On 22/07/2022 16:09, Andrea Corallo via Gcc-patches wrote:
>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>> 
>>> On 21/07/2022 10:17, Andrea Corallo via Gcc-patches wrote:
>>>> Richard Earnshaw <Richard.Earnshaw@foss.arm.com> writes:
>>>>
>>>>> On 28/04/2022 10:48, Andrea Corallo via Gcc-patches wrote:
>>>>>> This change add bti instructions at the beginning of arm specific
>>>>>> libgcc hand written assembly routines.
>>>>>> 2022-03-31  Andrea Corallo  <andrea.corallo@arm.com>
>>>>>> 	* libgcc/config/arm/crti.S (FUNC_START): Add bti instruction
>>>>>> if
>>>>>> 	necessary.
>>>>>> 	* libgcc/config/arm/lib1funcs.S (THUMB_FUNC_START, FUNC_START):
>>>>>> 	Likewise.
>>>>>>
>>>>>
>>>>> +#if defined(__ARM_FEATURE_BTI)
>>>>>
>>>>> Wouldn't it be better to use __ARM_FEATURE_BTI_DEFAULT?  That way we
>>>>> only get BTI instructions in multilib variants that have asked for
>>>>> BTI.
>>>>>
>>>>> R.
>>>> Hi Richard,
>>>> good point, yes I think so.
>>>> Please find attached the updated patch.
>>>> BR
>>>>     Andrea
>>>>
>>>
>>> I've been pondering this patch.  The way it is implemented would put a
>>> BTI instruction at the start of every assembler routine in libgcc.
>>> But the vast majority of functions in libgcc cannot have their address
>>> taken, so a BTI isn't needed (BTI is only needed when an indirect jump
>>> could be used).  So I wonder if we really need to do this so
>>> aggressively?
>>>
>>> Perhaps a better approach would be to define a macro (eg MAYBEBTI)
>>> which expands a BTI if the compilation requires it and nothing
>>> otherwise), and then manually insert that in any functions that really
>>> need this (if any).
>> I guess the main downside of this approach would be the maintanace
>> burden, we'll have to remember forever that every time an asm function
>> is called by function pointer we have to add the bti landing pad
>> manually, otherwise this will be broken when pacbti enabled. WDYT?
>> If we want to go this way I'll start reworking the patch in this
>> direction (tho this might not be trivial).
>> 
>
> Yes, it's a trade-off.  The lazy way, however, costs all users even if
> a function is never addressed (which I think is the case for
> practically all functions in libgcc).
>
> So I think in this case it's worth taking that extra development pain.
>
> R.

As a late follow-up to this.

I believe there are no hand written asm functions in libgcc that are
addressed, so this patch was dropped from the series in the following
iteration.  It is true that we could pac instrument them but ATM we
don't.

  Andrea

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

end of thread, other threads:[~2022-12-12 14:55 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-28  8:39 [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M Andrea Corallo
2022-04-28  9:08 ` [PATCH 1/12] arm: Make mbranch-protection opts parsing common to AArch32/64 Andrea Corallo
2022-07-01 10:49   ` Richard Earnshaw
2022-04-28  9:37 ` [PATCH 2/12] arm: Add Armv8.1-M Mainline target feature +pacbti Andrea Corallo
2022-07-01 10:51   ` Richard Earnshaw
2022-04-28  9:38 ` [PATCH 3/12] arm: Add option -mbranch-protection Andrea Corallo
2022-07-01 10:59   ` Richard Earnshaw
2022-07-04  9:27     ` [PATCH 3/12 V2] " Andrea Corallo
2022-07-04 10:55       ` Richard Earnshaw
2022-04-28  9:40 ` [PATCH 4/12] arm: Add testsuite library support for PACBTI target Andrea Corallo
2022-07-01 13:03   ` Richard Earnshaw
2022-07-01 14:17     ` Richard Earnshaw
2022-07-04 14:47       ` Andrea Corallo
2022-07-05 10:05         ` Richard Earnshaw
2022-04-28  9:42 ` [PATCH 5/12] arm: Implement target feature macros for PACBTI Andrea Corallo
2022-07-01 14:26   ` Richard Earnshaw
2022-07-12 15:45     ` [PATCH 5/12 V2] " Andrea Corallo
2022-07-21 11:01       ` Richard Earnshaw
2022-07-22 10:35         ` [PATCH 5/12 V3] " Andrea Corallo
2022-07-22 14:34           ` [PATCH 5/12 V4] " Andrea Corallo
2022-04-28  9:44 ` [PATCH 6/12] arm: Add pointer authentication for stack-unwinding runtime Andrea Corallo
2022-07-01 14:41   ` Richard Earnshaw
2022-11-09 11:17     ` [PATCH 6/12 V2] " Andrea Corallo
2022-04-28  9:45 ` [PATCH 7/12] arm: Emit build attributes for PACBTI target feature Andrea Corallo
2022-07-01 14:49   ` Richard Earnshaw
2022-07-13  8:58     ` [PATCH 7/12 V2] " Andrea Corallo
2022-07-21 11:03       ` Richard Earnshaw
2022-07-22 14:57     ` Andrea Corallo
2022-04-28  9:46 ` [PATCH 8/12] arm: Introduce multilibs " Andrea Corallo
2022-06-01 12:32   ` [PATCH 8/12 V2] " Andrea Corallo
2022-07-01 14:54     ` Richard Earnshaw
2022-07-01 14:57       ` Richard Earnshaw
2022-07-21  9:04         ` [PATCH 8/12 V3] " Andrea Corallo
2022-07-21 11:09           ` Richard Earnshaw
2022-04-28  9:48 ` [PATCH 9/12] arm: Make libgcc bti compatible Andrea Corallo
2022-07-01 15:03   ` Richard Earnshaw
2022-07-21  9:17     ` [PATCH 9/12 V2] " Andrea Corallo
2022-07-21 11:41       ` Richard Earnshaw
2022-07-22 15:09         ` Andrea Corallo
2022-07-25 10:41           ` Richard Earnshaw
2022-12-12 14:54             ` Andrea Corallo
2022-04-28  9:50 ` [PATCH 10/12] arm: Implement cortex-M return signing address codegen Andrea Corallo
2022-06-28  9:17   ` [PATCH 10/12 V2] " Andrea Corallo
2022-07-01 15:43     ` Richard Earnshaw
2022-08-08  9:33       ` Andrea Corallo
2022-10-20 14:53         ` Kyrylo Tkachov
2022-04-28  9:51 ` [PATCH 11/12] aarch64: Make bti pass generic so it can be used by the arm backend Andrea Corallo
2022-05-06  8:23   ` Richard Sandiford
2022-07-01 15:53   ` Richard Earnshaw
2022-04-28  9:53 ` [PATCH 12/12] arm: implement bti injection Andrea Corallo
2022-06-28  9:21   ` [PATCH 12/12 V2] " Andrea Corallo
2022-07-01 16:04     ` Richard Earnshaw
2022-06-01 12:34 ` [PATCH 0/12] arm: Enables return address verification and branch target identification on Cortex-M 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).