public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
       [not found] <c9da17a6-c3de-4466-c023-4e4ddbe38efb@foss.arm.com>
@ 2016-11-11 18:22 ` Jiong Wang
  2016-11-11 18:33   ` [2/9] Encoding support for AArch64 DWARF operations Jiong Wang
                     ` (2 more replies)
       [not found] ` <4cf21d03-0a88-c6fa-df37-59ec4edf1d89@foss.arm.com>
  1 sibling, 3 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:22 UTC (permalink / raw)
  To: gcc-patches, gdb-patches, Binutils; +Cc: Richard Earnshaw (lists)

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

This patch introduces three AARCH64 private DWARF operations in vendor extension
space.

DW_OP_AARCH64_pauth 0xea
===
   Takes one unsigned LEB 128 Pointer Authentication Description. Bits [3:0] of
   the description contain the Authentication Action Code. All unused bits are
   initialized to 0. The operation then proceeds according to the value of the
   action code as described in the Action Code Table.

DW_OP_AARCH64_paciasp 0xeb
===
   Authenticates the contents in X30/LR register as per A key for instruction
   pointer using current CFA as salt. The result is pushed onto the stack.

DW_OP_AARCH64_paciasp_deref 0xec
===
   Takes one signed LEB128 offset and retrieves 8-byte contents from the address
   calculated by CFA plus this offset, the contents then authenticated as per A
   key for instruction pointer using current CFA as salt. The result is pushed
   onto the stack.

Action Code Table
==================================
Action Code      |     Note
----------------------------------
0                |  Pops a single 8-byte operand from the stack representing a
                  |  signed instruction pointer, "drops" the authentication
                  |  signature and pushes the value  onto stack.
----------------------------------
1                |  Pops a single 8-byte operand from the stack representing a
                  |  signed data pointer, "drops" the authentication signature
                  |  and pushes the value on to stack.
----------------------------------
2                |  Bits [7:4] of the Pointer Authentication Description contain
                  |  an Authentication Key Index. The operation then pops the top
                  |  two stack entries. The first is an 8-byte value to be
                  |  authenticated. The second is an 8-byte salt. The first value
                  |  is then authenticated as per the Authentication Key Index
                  |  using the salt. The result is pushed onto stack.

Authentication Key Index
=================================
0                |  A key for instruction pointer.
---------------------------------
1                |  B key for instruction pointer.
---------------------------------
2                |  A key for data pointer.
---------------------------------
3                |  B key for data pointer.
---------------------------------
4                |  A key for general pointer.

DW_OP_AARCH64_pauth is designed to offer general description for all scenarios.

DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref are two shortcut
operations for return address signing.  They offer more compact debug frame
encoding.

For DWARF operation vendor extension space between DW_OP_lo_user and
DW_OP_hi_user, I think vendor is free to reserve any number and numbers for one
vender can overlap with the other, as operations for different vendors are
not supposed to co-exist.

One exception is that GNU toolchain have reserved some numbers inside this space
(DW_OP_GNU*), so vendor's numbers need to avoid overlapping with them.

For these three numbers,  they are not used in LLVM's implementation.

NOTE: the assigned values are provisional, we may need to change them if they are
found to be in conflict with on other toolchains.

Please review, Thanks.


include/
2016-11-09  Richard Earnshaw<richard.earnshaw@arm.com>
             Jiong Wang<jiong.wang@arm.com>

         * dwarf2.def (DW_OP_AARCH64_pauth): Reserve the number 0xea.
         (DW_OP_AARCH64_paciasp): Reserve the number 0xeb.
         (Dw_OP_AARCH64_paciasp_deref): Reserve the number 0xec.


[-- Attachment #2: 1.patch --]
[-- Type: text/x-patch, Size: 958 bytes --]

diff --git a/include/dwarf2.def b/include/dwarf2.def
index 5241fe8615e0e3b288fee80c08a67723686ef411..8eaa90c3b4748ecfc025a6c2dd6afcd5fd80be28 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -631,6 +631,16 @@ DW_OP (DW_OP_HP_unmod_range, 0xe5)
 DW_OP (DW_OP_HP_tls, 0xe6)
 /* PGI (STMicroelectronics) extensions.  */
 DW_OP (DW_OP_PGI_omp_thread_num, 0xf8)
+/* ARM extension for pointer authentication
+   DW_OP_AARCH64_pauth: takes one uleb128 operand which is authentication
+   descriptor.  Perform actions indicated by the descriptor.
+   DW_OP_AARCH64_paciasp: no operand.  Authenticate value in X30/LR using A key
+   and CFA as salt.
+   DW_OP_AARCH64_paciasp_deref: takes one sleb128 operand as offset.
+   Authenticate value in [CFA + offset] using A key and salt is CFA.  */
+DW_OP (DW_OP_AARCH64_pauth, 0xea)
+DW_OP (DW_OP_AARCH64_paciasp, 0xeb)
+DW_OP (DW_OP_AARCH64_paciasp_deref, 0xec)
 DW_END_OP
 
 DW_FIRST_ATE (DW_ATE_void, 0x0)


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

* [2/9] Encoding support for AArch64 DWARF operations
  2016-11-11 18:22 ` [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space Jiong Wang
@ 2016-11-11 18:33   ` Jiong Wang
  2016-11-16 17:51     ` Jason Merrill
       [not found]   ` <64dd1b38-ff0a-5df0-1d3c-2fbf083e2697@foss.arm.com>
  2016-11-11 19:39   ` [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space Jakub Jelinek
  2 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:33 UTC (permalink / raw)
  To: gcc-patches
  Cc: Jason Merrill, Richard Earnshaw (lists), Richard Earnshaw (lists)

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

The encoding for new added AARCH64 DWARF operations.

I am thinking DWARF specification actually allows vendor private operations
overlap with each other as one can't co-exist with the other.  So in theory we
should introduce target hook to handle target private operations.

But in GCC/binutils/LLVM scope, I only see one overlap between
DW_OP_GNU_push_tls_address and and DW_OP_HP_unknown, and DW_OP_HP_unknown seems
not used.

So I added the support in GCC generic code directly instead of introducing
target hook.

Is this OK to install?


gcc/
2016-11-11  Jiong Wang<jiong.wang@arm.com>

         * dwarf2out.c (size_of_loc_descr): Increase set for
         DW_OP_AARCH64_pauth and DW_OP_AARCH64_paciasp_deref.
         (output_loc_operands): Generate encoding for DW_OP_AARCH64_pauth
         and DW_OP_AARCH64_paciasp_deref.
         (output_loc_operands_raw): Likewise.


[-- Attachment #2: 2.patch --]
[-- Type: text/x-patch, Size: 1465 bytes --]

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 4a5c602f535fa49a45ae96f356f63c955dc527c6..fd159abe3c402cc8dedb0422e7b2680aabd28f93 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -1698,6 +1698,12 @@ size_of_loc_descr (dw_loc_descr_ref loc)
     case DW_OP_GNU_parameter_ref:
       size += 4;
       break;
+    case DW_OP_AARCH64_pauth:
+      size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+      break;
+    case DW_OP_AARCH64_paciasp_deref:
+      size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
+      break;
     default:
       break;
     }
@@ -2177,6 +2183,13 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
       }
       break;
 
+    case DW_OP_AARCH64_pauth:
+      dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
+      break;
+    case DW_OP_AARCH64_paciasp_deref:
+      dw2_asm_output_data_sleb128 (val1->v.val_int, NULL);
+      break;
+
     default:
       /* Other codes have no operands.  */
       break;
@@ -2365,6 +2378,15 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
       gcc_unreachable ();
       break;
 
+    case DW_OP_AARCH64_pauth:
+      fputc (',', asm_out_file);
+      dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
+      break;
+    case DW_OP_AARCH64_paciasp_deref:
+      fputc (',', asm_out_file);
+      dw2_asm_output_data_sleb128_raw (val1->v.val_int);
+      break;
+
     default:
       /* Other codes have no operands.  */
       break;


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

* [4/9][AArch64] Return address protection on AArch64
       [not found]     ` <df0da0e0-df8d-50ff-4f7e-428948817b4b@foss.arm.com>
@ 2016-11-11 18:34       ` Jiong Wang
       [not found]       ` <532363d6-0b33-491f-264d-9cd627713bf6@foss.arm.com>
  1 sibling, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:34 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh

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

As described in the cover letter, this patch implements return address signing
for AArch64, it's controlled by the new option:

   -msign-return-address=[none | non-leaf | all]

"none" means don't do return address signing at all on any function.  "non-leaf"
means only sign non-leaf function.  "all" means sign all functions.  Return
address signing is currently disabled on ILP32.  I haven't tested it.

The instructions added in the architecture are of 2 kinds.

* In the NOP instruction space, which allows binaries to run without any traps
on older versions of the architecture. This doesn't give any additional
protection on older hardware but allows for the same binary to be used on
earlier versions of the architecture and newer versions of the architecture.

* New instructions that are only valid for v8.3 and will trap if used on earlier
versions of the architecture.

At default, once return address signing is enabled, it will only generates NOP
instruction.

While if -march=armv8.3-a specified, GCC will try to use the most efficient
pointer authentication instruction as it can.

The architecture has 2 user invisible system keys for signing and creating
signed addresses as part of these instructions. For some use case, the user
might want to use difference key for different functions.  The new option
"-msign-return-address-key=key_name" let GCC select the key used for return
address signing.  Permissible values are "a_key" for A key and "b_key" for B
key, and this option are supported by function target attribute and LTO will
hopefully just work.



gcc/
2016-11-09  Jiong Wang<jiong.wang@arm.com>

         * config/aarch64/aarch64-opts.h (aarch64_pauth_key_index): New enum.
         (aarch64_function_type): New enum.
         * config/aarch64/aarch64-protos.h (aarch64_output_sign_auth_reg): New
         declaration.
         * config/aarch64/aarch64.c (aarch64_expand_prologue): Sign return
         address before it's pushed onto stack.
         (aarch64_expand_epilogue): Authenticate return address fetched from
         stack.
         (aarch64_output_sign_auth_reg): New function.
         (aarch64_override_options): Sanity check for ILP32 and ISA level.
         (aarch64_attributes): New function attributes for "sign-return-address",
         "pauth-key".
         * config/aarch64/aarch64.md (UNSPEC_AUTH_REG, UNSPEC_AUTH_REG1716,
         UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN,
         UNSPEC_STRIP_X30_SIGN): New unspecs.
         ("*do_return"): Generate combined instructions according to key index.
         ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716",
         "strip_reg_sign", "strip_lr_sign"): New.
         * config/aarch64/aarch64.opt (msign-return-address, mpauth-key): New.
         * config/aarch64/predicates.md (aarch64_const0_const1): New predicate.
         * doc/extend.texi (AArch64 Function Attributes): Documents
         "sign-return-address=", "pauth-key".
         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=",
         "-pauth-key".

gcc/testsuite/
2016-11-09  Jiong Wang<jiong.wang@arm.com>

         * gcc.target/aarch64/return_address_sign_1.c: New testcase.
         * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.




[-- Attachment #2: 4.patch --]
[-- Type: text/x-patch, Size: 19469 bytes --]

diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
index c550a74..41c14b3 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -73,4 +73,30 @@ enum aarch64_code_model {
   AARCH64_CMODEL_LARGE
 };
 
+/* AArch64 pointer authentication key indexes.  "key_array" in
+   aarch64_output_sign_auth_reg depends on the order of this enum.  */
+enum aarch64_pauth_key_index
+{
+  /* A key for instruction pointer.  */
+  AARCH64_PAUTH_IKEY_A = 0,
+  /* B key for instruction pointer.  */
+  AARCH64_PAUTH_IKEY_B,
+  /* A key for data pointer.  */
+  AARCH64_PAUTH_DKEY_A,
+  /* B key for data pointer.  */
+  AARCH64_PAUTH_DKEY_B,
+  /* A key for general pointer.  */
+  AARCH64_PAUTH_GKEY_A
+};
+
+/* Function types -msign-return-address should sign.  */
+enum aarch64_function_type {
+  /* Don't sign any function.  */
+  AARCH64_FUNCTION_NONE,
+  /* Non-leaf functions.  */
+  AARCH64_FUNCTION_NON_LEAF,
+  /* All functions.  */
+  AARCH64_FUNCTION_ALL
+};
+
 #endif
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 3cdd69b..fa6d16b 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -329,6 +329,7 @@ rtx aarch64_reverse_mask (enum machine_mode);
 bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT);
 char *aarch64_output_scalar_simd_mov_immediate (rtx, machine_mode);
 char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
+const char *aarch64_output_sign_auth_reg (rtx *, bool, bool);
 bool aarch64_pad_arg_upward (machine_mode, const_tree);
 bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
 bool aarch64_regno_ok_for_base_p (int, bool);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 3e663eb..8401fa4 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3204,6 +3204,13 @@ aarch64_expand_prologue (void)
   unsigned reg2 = cfun->machine->frame.wb_candidate2;
   rtx_insn *insn;
 
+  if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
+    emit_insn (gen_sign_reg (gen_rtx_REG (Pmode, LR_REGNUM),
+			     gen_rtx_REG (Pmode, LR_REGNUM),
+			     stack_pointer_rtx,
+			     GEN_INT (aarch64_pauth_key),
+			     const0_rtx));
+
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size;
 
@@ -3340,6 +3347,20 @@ aarch64_expand_epilogue (bool for_sibcall)
       RTX_FRAME_RELATED_P (insn) = 1;
     }
 
+  /* sibcall won't generate normally return, therefore we need to authenticate
+     at here.  TARGET_PAUTH will allow GCC to use combined authentication
+     instruction which we prefer, eh_return path can't do combined
+     authentication, as the following stack adjustment will update CFA to
+     handler's CFA while we want to use the CFA of the function which calls
+     __builtin_eh_return.  */
+  if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
+      && (for_sibcall || !TARGET_PAUTH || crtl->calls_eh_return))
+    emit_insn (gen_auth_reg (gen_rtx_REG (Pmode, LR_REGNUM),
+			     gen_rtx_REG (Pmode, LR_REGNUM),
+			     stack_pointer_rtx,
+			     GEN_INT (aarch64_pauth_key),
+			     const0_rtx));
+
   /* Stack adjustment for exception handler.  */
   if (crtl->calls_eh_return)
     {
@@ -5434,6 +5455,74 @@ aarch64_output_casesi (rtx *operands)
   return "";
 }
 
+/* Output ARMv8.3-A pointer sign instructions when SIGN_P be TRUE or
+   authentication instructions when it's FALSE.  X1716_P is TRUE if this
+   function is called from fixed register patterns, i.e sign_reg1716 or
+   auth_reg1716.  */
+
+const char*
+aarch64_output_sign_auth_reg (rtx *operands, bool sign_p, bool x1716_p)
+{
+  char buf[64];
+  const char *action = sign_p ? "pac" : "aut";
+  /* Assembler suffix for key, this array should be synced with
+     "enum aarch64_pauth_key_index" in aarch64-opts.h.  */
+  const char key_array[5] = {'a', 'b', 'a', 'b', 'a'};
+  char key_char
+    = key_array[x1716_p ? INTVAL (operands[0]) : INTVAL (operands[3])];
+  char type
+    = (x1716_p ? INTVAL (operands[1]) : INTVAL (operands[4])) ? 'd' : 'i';
+  unsigned FM = ((sign_p ? 0 : 1) << 2 /* F bit.  */
+		 | ((key_char  == 'a' ? 0 : 1) << 1)); /* M bit.  */
+
+  if (x1716_p
+      || (REGNO (operands[0]) == R17_REGNUM
+	  && REG_P (operands[2]) && REGNO (operands[2]) == R16_REGNUM))
+    {
+      /* PAC*1716/AUT*1716 only support code pointer.  */
+      gcc_assert (type == 'i');
+      unsigned CRm = 0x1;
+      unsigned FMS = (FM /* F and M bits.  */
+		      | 0); /* S bit.  */
+      snprintf (buf, sizeof (buf), "hint\t%d %s%s%c1716", (CRm << 3) | FMS,
+		ASM_COMMENT_START, action, key_char);
+    }
+  else if (REGNO (operands[0]) == LR_REGNUM
+	   && REG_P (operands[2]) && REGNO (operands[2]) == SP_REGNUM)
+    {
+      /* PAC*SP/AUT*SP only support code pointer.  */
+      gcc_assert (type == 'i');
+      unsigned CRm = 0x3;
+      unsigned FMS = (FM /* F and M bits.  */
+		      | 1); /* S bit.  */
+      snprintf (buf, sizeof (buf), "hint\t%d %s%si%csp", (CRm << 3) | FMS,
+		ASM_COMMENT_START, action, key_char);
+    }
+  else if (REGNO (operands[0]) == LR_REGNUM && operands[2] == const0_rtx)
+    {
+      /* PAC*Z/AUT*Z only support code pointer.  */
+      gcc_assert (type == 'i');
+      unsigned CRm = 0x3;
+      unsigned FMS = (FM /* F and M bits.  */
+		      | 0); /* S bit.  */
+      snprintf (buf, sizeof (buf), "hint\t%d %s%si%cz", (CRm << 3) | FMS,
+		ASM_COMMENT_START, action, key_char);
+    }
+  else if (operands[2] == const0_rtx)
+    {
+      /* General format PAC* Xd, Xn/AUT* Xd, Xn.  */
+      snprintf (buf, sizeof (buf), "%s%cz%c %%0", action, type, key_char);
+    }
+  else
+    {
+      /* General format PAC*Z* Xd, Xn/AUT*Z* Xd, Xn.  */
+      snprintf (buf, sizeof (buf), "%s%c%c %%0, %%2", action, type, key_char);
+    }
+
+  output_asm_insn (buf, operands);
+
+  return "";
+}
 
 /* Return size in bits of an arithmetic operand which is shifted/scaled and
    masked such that it is suitable for a UXTB, UXTH, or UXTW extend
@@ -8466,6 +8555,9 @@ aarch64_override_options (void)
     error ("Assembler does not support -mabi=ilp32");
 #endif
 
+  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
+    error ("Return address signing is only supported on LP64");
+
   /* Make sure we properly set up the explicit options.  */
   if ((aarch64_cpu_string && valid_cpu)
        || (aarch64_tune_string && valid_tune))
@@ -8849,6 +8941,10 @@ static const struct aarch64_attribute_info aarch64_attributes[] =
   { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ },
   { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune,
      OPT_mtune_ },
+  { "sign-return-address", aarch64_attr_enum, false, NULL,
+     OPT_msign_return_address_ },
+  { "pauth-key", aarch64_attr_enum, false, NULL,
+    OPT_mpauth_key_ },
   { NULL, aarch64_attr_custom, false, NULL, OPT____ }
 };
 
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 70efbe9..4bfadb5 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -963,4 +963,11 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 extern tree aarch64_fp16_type_node;
 extern tree aarch64_fp16_ptr_type_node;
 
+/* Return address signing is enabled for AARCH64_FUNCTION_ALL, or for
+   AARCH64_FUNCTION_NON_LEAF.  */
+#define AARCH64_ENABLE_RETURN_ADDRESS_SIGN \
+	(aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL \
+	     || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF \
+		 && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0))
+
 #endif /* GCC_AARCH64_H */
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index c95258b..754ea00 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -66,6 +66,8 @@
 )
 
 (define_c_enum "unspec" [
+    UNSPEC_AUTH_REG
+    UNSPEC_AUTH_REG1716
     UNSPEC_CASESI
     UNSPEC_CRC32B
     UNSPEC_CRC32CB
@@ -108,6 +110,8 @@
     UNSPEC_PRLG_STK
     UNSPEC_RBIT
     UNSPEC_SCVTF
+    UNSPEC_SIGN_REG
+    UNSPEC_SIGN_REG1716
     UNSPEC_SISD_NEG
     UNSPEC_SISD_SSHL
     UNSPEC_SISD_USHL
@@ -119,6 +123,8 @@
     UNSPEC_ST2_LANE
     UNSPEC_ST3_LANE
     UNSPEC_ST4_LANE
+    UNSPEC_STRIP_REG_SIGN
+    UNSPEC_STRIP_X30_SIGN
     UNSPEC_TLS
     UNSPEC_TLSDESC
     UNSPEC_TLSLE12
@@ -574,7 +580,21 @@
 (define_insn "*do_return"
   [(return)]
   ""
-  "ret"
+  {
+    if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
+	&& TARGET_PAUTH
+	&& !crtl->calls_eh_return)
+      {
+	if (aarch64_pauth_key == AARCH64_PAUTH_IKEY_A)
+	  return "retaa";
+	else if (aarch64_pauth_key == AARCH64_PAUTH_IKEY_B)
+	  return "retab";
+
+	gcc_unreachable ();
+      }
+
+    return "ret";
+  }
   [(set_attr "type" "branch")]
 )
 
@@ -5210,6 +5230,114 @@
   [(set_attr "length" "0")]
 )
 
+;; ARMv8.3-A pointer authentication support
+;; OPERANDS[0] - Result.
+;; OPERANDS[1] - The value we want to sign or authenticate.
+;; OPERANDS[2] - The salt used for signing or authentication.
+;; OPERANDS[3] - Key index. See aarch64_pauth_key_type in aarch64-opts.h.
+;; OPERANDS[4] - Pointer type.  0 for code, 1 for data.
+;;
+;; These patterns are available for all architectures.  For architectures
+;; without TARGET_PAUTH, they will become nop, this let the user write portable
+;; software which can get pointer authentication on new hardware while still
+;; runs OK on old hardware.
+
+(define_insn "sign_reg"
+  [(set (match_operand:DI 0 "register_operand" "=rk")
+	(unspec:DI [(match_operand:DI 1 "register_operand" "0")
+		    (match_operand:DI 2 "aarch64_reg_or_zero" "rkZ")
+		    (match_operand:DI 3 "aarch64_const0_const1" "i")
+		    (match_operand:DI 4 "aarch64_const0_const1" "i")]
+	 UNSPEC_SIGN_REG))]
+  ""
+  {
+    return aarch64_output_sign_auth_reg (operands, /* sign_p */true,
+					 /* x1716_p */false);
+  }
+)
+
+(define_insn "sign_reg1716"
+  [(set (reg:DI R17_REGNUM)
+	(unspec:DI [(reg:DI R17_REGNUM)
+		    (reg:DI R16_REGNUM)
+		    (match_operand:DI 0 "aarch64_const0_const1" "i")
+		    (match_operand:DI 1 "aarch64_const0_const1" "i")]
+	 UNSPEC_SIGN_REG1716))]
+  ""
+  {
+    return aarch64_output_sign_auth_reg (operands, /* sign_p */true,
+					 /* x1716_p */true);
+  }
+)
+
+(define_insn "auth_reg"
+  [(set (match_operand:DI 0 "register_operand" "=rk")
+	(unspec:DI [(match_operand:DI 1 "register_operand" "0")
+		    (match_operand:DI 2 "aarch64_reg_or_zero" "rkZ")
+		    (match_operand:DI 3 "aarch64_const0_const1" "i")
+		    (match_operand:DI 4 "aarch64_const0_const1" "i")]
+	 UNSPEC_AUTH_REG))]
+  ""
+  {
+    return aarch64_output_sign_auth_reg (operands, /* sign_p */false,
+					 /* x1716_p */false);
+  }
+)
+
+(define_insn "auth_reg1716"
+  [(set (reg:DI R17_REGNUM)
+	(unspec:DI [(reg:DI R17_REGNUM)
+		    (reg:DI R16_REGNUM)
+		    (match_operand:DI 0 "aarch64_const0_const1" "i")
+		    (match_operand:DI 1 "aarch64_const0_const1" "i")]
+	 UNSPEC_AUTH_REG1716))]
+  ""
+  {
+    return aarch64_output_sign_auth_reg (operands, /* sign_p */false,
+					 /* x1716_p */true);
+  }
+)
+
+(define_insn "strip_reg_sign"
+  [(set (match_operand:DI 0 "register_operand" "=rk")
+	(unspec:DI [(match_operand:DI 1 "register_operand" "0")
+		    (match_operand:DI 2 "immediate_operand" "i")]
+	 UNSPEC_STRIP_REG_SIGN))]
+  ""
+  {
+    if (REGNO (operands[1]) == LR_REGNUM)
+      {
+	if (INTVAL (operands[2]) == 0)
+	  return "xpaclri";
+	else
+	  /* LR can't be used for data strip.  */
+	  gcc_unreachable ();
+      }
+    else
+      {
+	if (INTVAL (operands[2]) == 0)
+	  return "xpaci\t%0";
+	else
+	  return "xpacd\t%0";
+      }
+  }
+)
+
+(define_insn "strip_lr_sign"
+  [(set (reg:DI R30_REGNUM)
+	(unspec:DI [(reg:DI R30_REGNUM)
+		    (match_operand:DI 0 "immediate_operand" "i")]
+	 UNSPEC_STRIP_X30_SIGN))]
+  ""
+  {
+    if (INTVAL (operands[0]) == 0)
+      return "xpaclri";
+    else
+      /* LR can't be used for data strip.  */
+      gcc_unreachable ();
+  }
+)
+
 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
 ;; all of memory.  This blocks insns from being moved across this point.
 
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 82e9f5b..15fac36 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -149,6 +149,37 @@ mpc-relative-literal-loads
 Target Report Save Var(pcrelative_literal_loads) Init(2) Save
 PC relative literal loads.
 
+msign-return-address=
+Target RejectNegative Report Joined Enum(aarch64_ra_sign_scope_t) Var(aarch64_ra_sign_scope) Init(AARCH64_FUNCTION_NONE) Save
+Select return address signing scope
+
+Enum
+Name(aarch64_ra_sign_scope_t) Type(enum aarch64_function_type)
+Supported AArch64 return address signing scope (for use with -msign-return-address= option):
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(none) Value(AARCH64_FUNCTION_NONE)
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(non-leaf) Value(AARCH64_FUNCTION_NON_LEAF)
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL)
+
+mpauth-key=
+Target RejectNegative Report Joined Enum(aarch64_pauth_key_t) Var(aarch64_pauth_key) Init(AARCH64_PAUTH_IKEY_A) Save
+Select pointer authentication key
+
+Enum
+Name(aarch64_pauth_key_t) Type(enum aarch64_pauth_key_index)
+Known AArch64 pointer authentication keys (for use with the -mpauth-key= option):
+
+EnumValue
+Enum(aarch64_pauth_key_t) String(a_key) Value(AARCH64_PAUTH_IKEY_A)
+
+EnumValue
+Enum(aarch64_pauth_key_t) String(b_key) Value(AARCH64_PAUTH_IKEY_B)
+
 mlow-precision-recip-sqrt
 Common Var(flag_mrecip_low_precision_sqrt) Optimization
 Enable the reciprocal square root approximation.  Enabling this reduces
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index ebda6d8..73a66d5 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -35,6 +35,10 @@
   (and (match_code "const_int")
        (match_test "op == CONST0_RTX (mode)")))
 
+(define_predicate "aarch64_const0_const1"
+  (ior (match_test "op == const0_rtx")
+       (match_test "op == const1_rtx")))
+
 (define_predicate "aarch64_ccmp_immediate"
   (and (match_code "const_int")
        (match_test "IN_RANGE (INTVAL (op), -31, 31)")))
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 8cb93ab..204cf45 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3509,6 +3509,18 @@ Specifies the core for which to tune the performance of this function and also
 whose architectural features to use.  The behavior and valid arguments are the
 same as for the @option{-mcpu=} command-line option.
 
+@item sign-return-address
+@cindex @code{sign-return-address} function attribute, AArch64
+Select the function scope we want to do return address signing on.  The behavior
+and permissible arguments are the same as for the command-line option
+@option{-msign-return-address=}.  The default value is @code{none}
+
+@item pauth-key
+@cindex @code{pauth-key} function attribute, AArch64
+Specify the key used for return address signing for this function.  The behavior
+and permissible arguments are the same as for the command-line option
+@option{-mpauth-key=}.  The default key is @code{a_key}.
+
 @end table
 
 The above target attributes can be specified as follows:
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 18ab6d9..e7f842f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13344,6 +13344,19 @@ accessed using a single instruction and emitted after each function.  This
 limits the maximum size of functions to 1MB.  This is enabled by default for
 @option{-mcmodel=tiny}.
 
+@item -msign-return-address=@var{scope}
+@opindex msign-return-address
+Select the function scope we want to do return address signing on.  Permissible
+values are @samp{none}, @samp{none-leaf} and @samp{all}.  @samp{none} means
+return address signing is disabled.  @samp{non-leaf} enables it for non-leaf
+functions.  @samp{all} for all functions and is the default value.
+
+@item -mpauth-key=@var{key_name}
+@opindex mpauth-key
+Select the key used for return address signing.  Permissible values are
+@samp{a_key} for A key and @samp{b_key} for B key.  @samp{a_key} is the default
+value.
+
 @end table
 
 @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
new file mode 100644
index 0000000..b786b09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=all" } */
+
+int foo (int);
+int bar (int, int);
+
+/* sibcall only.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b)
+{
+  /* paciasp */
+  return foo (a + b);
+  /* autiasp */
+}
+
+/* non-leaf function with sibcall.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func2 (int a, int b)
+{
+  /* paciasp */
+  if (a < b)
+    return b;
+
+  a = foo (b);
+
+  return foo (a);
+  /* autiasp */
+}
+
+/* non-leaf function, legacy arch.  */
+int __attribute__ ((target ("arch=armv8.2-a")))
+func3 (int a, int b, int c)
+{
+  /* paciasp */
+  return a + foo (b) + c;
+  /* autiasp */
+}
+
+/* non-leaf function.  */
+int __attribute__ ((target ("arch=armv8.3-a, pauth-key=b_key")))
+func4 (int a, int b, int c)
+{
+  /* paciasp */
+  return a + foo (b) + c;
+  /* retab */
+}
+
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none")))
+func4_disable (int a, int b, int c, int d)
+{
+  return c + bar (a, b) + d;
+}
+
+/* { dg-final { scan-assembler-times "autiasp" 3 } } */
+/* { dg-final { scan-assembler-times "paciasp" 3 } } */
+/* { dg-final { scan-assembler-times "pacibsp" 1 } } */
+/* { dg-final { scan-assembler-times "retab" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c
new file mode 100644
index 0000000..f44644d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=non-leaf" } */
+
+int foo (int);
+int bar (int, int);
+
+/* sibcall only.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b)
+{
+  /* No authentication.  */
+  return foo (a + b);
+}
+
+/* non-leaf function with sibcall.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func2 (int a, int b)
+{
+  /* paciasp */
+  if (a < b)
+    return b;
+
+  a = foo (b);
+
+  return foo (a);
+  /* autiasp */
+}
+
+/* non-leaf function, legacy arch.  */
+int __attribute__ ((target ("arch=armv8.2-a, pauth-key=b_key")))
+func3 (int a, int b, int c)
+{
+  /* pacibsp */
+  return a + foo (b) + c;
+  /* autibsp */
+}
+
+/* non-leaf function.  */
+int __attribute__ ((target ("arch=armv8.3-a, pauth-key=b_key")))
+func4 (int a, int b, int c)
+{
+  /* pacibsp */
+  return a + foo (b) + c;
+  /* retab */
+}
+
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none")))
+func4_disable (int a, int b, int c, int d)
+{
+  return c + bar (a, b) + d;
+}
+
+/* { dg-final { scan-assembler-times "paciasp" 1 } } */
+/* { dg-final { scan-assembler-times "autiasp" 1 } } */
+/* { dg-final { scan-assembler-times "pacibsp" 2 } } */
+/* { dg-final { scan-assembler-times "autibsp" 1 } } */
+/* { dg-final { scan-assembler-times "retab" 1 } } */


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

* [3/9][AArch64] Add commandline support for -march=armv8.3-a
       [not found]   ` <64dd1b38-ff0a-5df0-1d3c-2fbf083e2697@foss.arm.com>
       [not found]     ` <df0da0e0-df8d-50ff-4f7e-428948817b4b@foss.arm.com>
@ 2016-11-11 18:34     ` Jiong Wang
  1 sibling, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:34 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh

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

This patch add command line support for ARMv8.3-A through new architecture:

   -march=armv8.3-a

ARMv8.3-A implies all default features of ARMv8.2-A and meanwhile it includes
the new pointer authentication extension.


gcc/
2016-11-08  Jiong Wang<jiong.wang@arm.com>

         * config/aarch64/aarch64-arches.def: New entry for "armv8.3-a".
         * config/aarch64/aarch64.h (AARCH64_FL_PAUTH, AARCH64_FL_V8_3,
         AARCH64_FL_FOR_ARCH8_3, AARCH64_ISA_PAUTH, AARCH64_ISA_V8_3,
         TARGET_PAUTH, TARGET_ARMV8_3): New.
         * doc/invoke.texi (AArch64 Options): Document "armv8.3-a".


[-- Attachment #2: 3.patch --]
[-- Type: text/x-patch, Size: 3584 bytes --]

diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
index 7dcf140411f6eb95504d9b92df9dadce50529a28..0a33f799e66b4ec6e016845eb333f24aaf63383e 100644
--- a/gcc/config/aarch64/aarch64-arches.def
+++ b/gcc/config/aarch64/aarch64-arches.def
@@ -33,4 +33,5 @@
 AARCH64_ARCH("armv8-a",	      generic,	     8A,	8,  AARCH64_FL_FOR_ARCH8)
 AARCH64_ARCH("armv8.1-a",     generic,	     8_1A,	8,  AARCH64_FL_FOR_ARCH8_1)
 AARCH64_ARCH("armv8.2-a",     generic,	     8_2A,	8,  AARCH64_FL_FOR_ARCH8_2)
+AARCH64_ARCH("armv8.3-a",     generic,	     8_3A,	8,  AARCH64_FL_FOR_ARCH8_3)
 
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 19caf9f2979e30671720823829464300b5349273..70efbe9b5f97bd38d61ad66e38608f7ac5bdfb38 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -138,6 +138,10 @@ extern unsigned aarch64_architecture_version;
 /* ARMv8.2-A architecture extensions.  */
 #define AARCH64_FL_V8_2	      (1 << 8)  /* Has ARMv8.2-A features.  */
 #define AARCH64_FL_F16	      (1 << 9)  /* Has ARMv8.2-A FP16 extensions.  */
+/* ARMv8.3-A architecture extensions.  */
+#define AARCH64_FL_PAUTH      (1 << 10)  /* Has Pointer Authentication
+					    Extensions.  */
+#define AARCH64_FL_V8_3	      (1 << 11)  /* Has ARMv8.3-A features.  */
 
 /* Has FP and SIMD.  */
 #define AARCH64_FL_FPSIMD     (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -151,6 +155,8 @@ extern unsigned aarch64_architecture_version;
   (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_CRC | AARCH64_FL_V8_1)
 #define AARCH64_FL_FOR_ARCH8_2			\
   (AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_V8_2)
+#define AARCH64_FL_FOR_ARCH8_3			\
+  (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3 | AARCH64_FL_PAUTH)
 
 /* Macros to test ISA flags.  */
 
@@ -162,6 +168,8 @@ extern unsigned aarch64_architecture_version;
 #define AARCH64_ISA_RDMA	   (aarch64_isa_flags & AARCH64_FL_V8_1)
 #define AARCH64_ISA_V8_2	   (aarch64_isa_flags & AARCH64_FL_V8_2)
 #define AARCH64_ISA_F16		   (aarch64_isa_flags & AARCH64_FL_F16)
+#define AARCH64_ISA_PAUTH	   (aarch64_isa_flags & AARCH64_FL_PAUTH)
+#define AARCH64_ISA_V8_3	   (aarch64_isa_flags & AARCH64_FL_V8_3)
 
 /* Crypto is an optional extension to AdvSIMD.  */
 #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -176,6 +184,12 @@ extern unsigned aarch64_architecture_version;
 #define TARGET_FP_F16INST (TARGET_FLOAT && AARCH64_ISA_F16)
 #define TARGET_SIMD_F16INST (TARGET_SIMD && AARCH64_ISA_F16)
 
+/* Pointer Authentication extension.  */
+#define TARGET_PAUTH (AARCH64_ISA_PAUTH)
+
+/* ARMv8.3-A extension.  */
+#define TARGET_ARMV8_3 (AARCH64_ISA_V8_3)
+
 /* Make sure this is always defined so we don't have to check for ifdefs
    but rather use normal ifs.  */
 #ifndef TARGET_FIX_ERR_A53_835769_DEFAULT
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 87da1f1c12b718fa63c9b89fdd8f85fbc6b54cb0..18ab6d9f20eca7fa29317e10678f1e46f64039bd 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13257,7 +13257,10 @@ more feature modifiers.  This option has the form
 @option{-march=@var{arch}@r{@{}+@r{[}no@r{]}@var{feature}@r{@}*}}.
 
 The permissible values for @var{arch} are @samp{armv8-a},
-@samp{armv8.1-a}, @samp{armv8.2-a} or @var{native}.
+@samp{armv8.1-a}, @samp{armv8.2-a}, @samp{armv8.3-a} or @var{native}.
+
+The value @samp{armv8.3-a} implies @samp{armv8.2-a} and enables compiler
+support for the ARMv8.3-A architecture extensions.
 
 The value @samp{armv8.2-a} implies @samp{armv8.1-a} and enables compiler
 support for the ARMv8.2-A architecture extensions.


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

* [6/9][AArch64] Add builtins support for pac/aut/xpac
       [not found]         ` <c46bb16a-4133-5aac-646f-cfd3f204d355@foss.arm.com>
@ 2016-11-11 18:35           ` Jiong Wang
       [not found]           ` <172bd740-755c-5267-3a9d-692c84d25395@foss.arm.com>
  1 sibling, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:35 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh

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

This patch implements a few ARMv8.3-A new builtins for pointer sign and
authentication instructions.

Currently, these builtins are supposed to be used by libgcc EH unwinder
only.  They are not public interface to external user.

OK to install?

gcc/
2016-11-11  Jiong Wang<jiong.wang@arm.com>

         * config/aarch64/aarch64-builtins.c (enum aarch64_builtins): New entries
         for AARCH64_PAUTH_BUILTIN_PACI1716, AARCH64_PAUTH_BUILTIN_AUTIA1716,
         AARCH64_PAUTH_BUILTIN_AUTIB1716, AARCH64_PAUTH_BUILTIN_XPACLRI.
         (aarch64_init_v8_3_builtins): New.
         (aarch64_init_builtins): Call aarch64_init_builtins.
         (arch64_expand_builtin): Expand new builtins.


[-- Attachment #2: 6.patch --]
[-- Type: text/x-patch, Size: 4676 bytes --]

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 9136910cd324a391de929ea9d1a13419dbcfb8bc..20679a5d3f6138f4c55b84f3aff5dfd0341e6787 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -353,6 +353,11 @@ enum aarch64_builtins
   AARCH64_CRC32_BUILTIN_BASE,
   AARCH64_CRC32_BUILTINS
   AARCH64_CRC32_BUILTIN_MAX,
+  /* ARMv8.3-A Pointer Authentication Builtins.  */
+  AARCH64_PAUTH_BUILTIN_AUTIA1716,
+  AARCH64_PAUTH_BUILTIN_AUTIB1716,
+  AARCH64_PAUTH_BUILTIN_XPACLRI,
+  AARCH64_PAUTH_BUILTIN_PACI1716,
   AARCH64_BUILTIN_MAX
 };
 
@@ -900,6 +905,37 @@ aarch64_init_fp16_types (void)
   aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
 }
 
+/* Pointer authentication builtins that will become NOP on legacy platform.
+   Currently, these builtins are for internal use only (libgcc EH unwinder).  */
+
+void
+aarch64_init_pauth_hint_builtins (void)
+{
+  /* Pointer Authentication builtins.  */
+  tree ftype_pointer_auth
+    = build_function_type_list (ptr_type_node, ptr_type_node,
+				unsigned_intDI_type_node, NULL_TREE);
+  tree ftype_pointer_strip
+    = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
+
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
+    = add_builtin_function ("__builtin_aarch64_autia1716", ftype_pointer_auth,
+			    AARCH64_PAUTH_BUILTIN_AUTIA1716, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIB1716]
+    = add_builtin_function ("__builtin_aarch64_autib1716", ftype_pointer_auth,
+			    AARCH64_PAUTH_BUILTIN_AUTIB1716, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
+    = add_builtin_function ("__builtin_aarch64_xpaclri", ftype_pointer_strip,
+			    AARCH64_PAUTH_BUILTIN_XPACLRI, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACI1716]
+    = add_builtin_function ("__builtin_aarch64_paci1716", ftype_pointer_auth,
+			    AARCH64_PAUTH_BUILTIN_PACI1716, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+}
+
 void
 aarch64_init_builtins (void)
 {
@@ -928,6 +964,10 @@ aarch64_init_builtins (void)
 
   aarch64_init_crc32_builtins ();
   aarch64_init_builtin_rsqrt ();
+
+/* Initialize pointer authentication builtins which are backed by instructions
+   in NOP encoding space.  */
+  aarch64_init_pauth_hint_builtins ();
 }
 
 tree
@@ -1270,6 +1310,76 @@ aarch64_expand_builtin (tree exp,
 	}
       emit_insn (pat);
       return target;
+    case AARCH64_PAUTH_BUILTIN_AUTIA1716:
+    case AARCH64_PAUTH_BUILTIN_AUTIB1716:
+    case AARCH64_PAUTH_BUILTIN_PACI1716:
+    case AARCH64_PAUTH_BUILTIN_XPACLRI:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = force_reg (Pmode, expand_normal (arg0));
+
+      if (!target)
+	target = gen_reg_rtx (Pmode);
+      else
+	target = force_reg (Pmode, target);
+
+      emit_move_insn (target, op0);
+
+      if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
+	{
+	  rtx lr_reg = gen_rtx_REG (Pmode, R30_REGNUM);
+	  icode = CODE_FOR_strip_lr_sign;
+	  emit_move_insn (lr_reg, op0);
+	  emit_insn (GEN_FCN (icode) (const0_rtx));
+	  emit_move_insn (target, lr_reg);
+	}
+      else
+	{
+	  tree arg1 = CALL_EXPR_ARG (exp, 1);
+	  rtx op1 = expand_normal (arg1);
+	  bool sign_op_p = (fcode == AARCH64_PAUTH_BUILTIN_PACI1716);
+
+	  bool x1716_op_p = (fcode == AARCH64_PAUTH_BUILTIN_AUTIA1716
+			     || fcode == AARCH64_PAUTH_BUILTIN_AUTIB1716
+			     || fcode == AARCH64_PAUTH_BUILTIN_PACI1716);
+
+	  bool a_key_p = (fcode == AARCH64_PAUTH_BUILTIN_AUTIA1716
+			  || (aarch64_pauth_key == AARCH64_PAUTH_IKEY_A
+			      && fcode == AARCH64_PAUTH_BUILTIN_PACI1716));
+	  HOST_WIDE_INT key_index =
+	    a_key_p ? AARCH64_PAUTH_IKEY_A : AARCH64_PAUTH_IKEY_B;
+
+	  if (sign_op_p)
+	    {
+	      if (x1716_op_p)
+		icode = CODE_FOR_sign_reg1716;
+	      else
+		icode = CODE_FOR_sign_reg;
+	    }
+	  else
+	    {
+	      if (x1716_op_p)
+		icode = CODE_FOR_auth_reg1716;
+	      else
+		icode = CODE_FOR_auth_reg;;
+	    }
+
+	  op1 = force_reg (Pmode, op1);
+
+	  if (x1716_op_p)
+	    {
+	      rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
+	      rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
+	      emit_move_insn (x17_reg, op0);
+	      emit_move_insn (x16_reg, op1);
+	      emit_insn (GEN_FCN (icode) (GEN_INT (key_index), const0_rtx));
+	      emit_move_insn (target, x17_reg);
+	    }
+	  else
+	    emit_insn (GEN_FCN (icode) (target, target, op1,
+					GEN_INT (key_index), const0_rtx));
+	}
+
+      return target;
     }
 
   if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)


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

* [5/9][AArch64] Generate dwarf information for -msign-return-address
       [not found]       ` <532363d6-0b33-491f-264d-9cd627713bf6@foss.arm.com>
       [not found]         ` <c46bb16a-4133-5aac-646f-cfd3f204d355@foss.arm.com>
@ 2016-11-11 18:35         ` Jiong Wang
  1 sibling, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:35 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh

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

This patch generate DWARF description for pointer authentication.  DWARF value
expression is used to describe the authentication action.

Please see the cover letter and AArch64 DWARF specification for the semantics
of AArch64 DWARF operations.

When authentication key index is A key, we use compact DWARF description which
can largely save DWARF frame size, otherwise we fallback to general operator.



Example
===

     int
     cal (int a, int b, int c)
     {
       return a + dec (b) + c;
     }

Compact DWARF description
(-march=armv8.3-a -msign-return-address)
===

   DW_CFA_advance_loc: 4 to 0000000000000004
   DW_CFA_val_expression: r30 (x30) (DW_OP_AARCH64_paciasp)
   DW_CFA_advance_loc: 4 to 0000000000000008
   DW_CFA_val_expression: r30 (x30) (DW_OP_AARCH64_paciasp_deref: -24)

General DWARF description
===
(-march=armv8.3-a -msign-return-address -mpauth-key=b_key)

   DW_CFA_advance_loc: 4 to 0000000000000004
   DW_CFA_val_expression: r30 (x30) (DW_OP_breg30 (x30): 0; DW_OP_AARCH64_pauth: 18)
   DW_CFA_advance_loc: 4 to 0000000000000008
   DW_CFA_val_expression: r30 (x30) (DW_OP_dup; DW_OP_const1s: -24; DW_OP_plus; DW_OP_deref; DW_OP_AARCH64_pauth: 18)

 From Linux kernel testing, -msign-return-address will introduce +24%
.debug_frame size increase when signing all functions and using compact
description, and about +45% .debug_frame size increase if using general
description.


gcc/
2016-11-11  Jiong Wang<jiong.wang@arm.com>

         * config/aarch64/aarch64.h (aarch64_pauth_action_type): New enum.
         * config/aarch64/aarch64.c (aarch64_attach_ra_auth_dwarf_note): New function.
         (aarch64_attach_ra_auth_dwarf_general): New function.
         (aarch64_attach_ra_auth_dwarf_shortcut): New function.
         (aarch64_save_callee_saves): Generate dwarf information if LR is signed.
         (aarch64_expand_prologue): Likewise.
         (aarch64_expand_epilogue): Likewise.


[-- Attachment #2: 5.patch --]
[-- Type: text/x-patch, Size: 10079 bytes --]

diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 4bfadb512915d5dc606f7fc06f027868d6be7613..907e8bdf5b4961b3107dcd5a481de28335e4be89 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -970,4 +970,16 @@ extern tree aarch64_fp16_ptr_type_node;
 	     || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF \
 		 && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0))
 
+/* AArch64 pointer authentication action types.  See AArch64 DWARF ABI for
+   details.  */
+enum aarch64_pauth_action_type
+{
+  /* Drop the authentication signature for instruction pointer.  */
+  AARCH64_PAUTH_DROP_I,
+  /* Likewise for data pointer.  */
+  AARCH64_PAUTH_DROP_D,
+  /* Do authentication.  */
+  AARCH64_PAUTH_AUTH
+};
+
 #endif /* GCC_AARCH64_H */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index b3d9a2a3f51ee240d00beb4cc65f99b089a3215e..cae177dca511fdb909ef82c972d3bbdebab215e2 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2717,6 +2717,104 @@ aarch64_output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
+/* Generate return address signing DWARF annotation using general DWARF
+   operator.  DWARF frame size will be bigger than using shortcut DWARF
+   operator.  See aarch64_attach_ra_auth_dwarf for parameter meanings.  */
+
+static rtx
+aarch64_attach_ra_auth_dwarf_general (rtx notes, HOST_WIDE_INT offset)
+{
+  /* The authentication descriptor.  */
+  HOST_WIDE_INT desc_const = (AARCH64_PAUTH_AUTH | (aarch64_pauth_key << 4));
+
+  /* DW_OP_AARCH64_pauth takes one uleb128 operand which is the authentication
+     descriptor.  The low 4 bits of the descriptor is the authentication action
+     code, all other bits are reserved and initialized into zero except when the
+     action code is AARCH64_PAUTH_AUTH then bits[7:4] is the authentication key
+     index.  */
+  rtx auth_op
+    = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, GEN_INT (desc_const), const0_rtx),
+		      DW_OP_AARCH64_pauth);
+
+  rtx par;
+  if (offset == 0)
+    {
+      /* Step 1: Push LR onto stack.
+		 NOTE: the bottom of DWARF expression stack is always CFA.
+	 Step 2: Issue AArch64 authentication operation.  */
+    par = gen_rtx_PARALLEL (DImode,
+			    gen_rtvec (2, gen_rtx_REG (Pmode, LR_REGNUM),
+				       auth_op));
+    }
+  else
+    {
+      rtx dup_cfa
+	= gen_rtx_UNSPEC (Pmode, gen_rtvec (2, const0_rtx, const0_rtx),
+			  DW_OP_dup);
+
+      rtx deref_op
+	= gen_rtx_UNSPEC (Pmode, gen_rtvec (2, const0_rtx, const0_rtx),
+			  DW_OP_deref);
+
+      rtx raw_plus
+	= gen_rtx_UNSPEC (Pmode, gen_rtvec (2, const0_rtx, const0_rtx),
+			  DW_OP_plus);
+      /* Step 1: Push the authentication key on to dwarf expression stack.
+	 Step 2: Push the stack address of where return address saved, followed
+	 by a memory de-reference operation.
+	 Step 3: Push the authentication descriptor.
+	 Step 4: Issue AArch64 authentication operation.  */
+      par = gen_rtx_PARALLEL (DImode,
+			      gen_rtvec (5, dup_cfa, GEN_INT (offset), raw_plus,
+					 deref_op, auth_op));
+    }
+
+  /* Generate the final dwarf value expression.  */
+  return alloc_reg_note (REG_CFA_VAL_EXPRESSION,
+			 gen_rtx_SET (gen_rtx_REG (DImode, LR_REGNUM), par),
+			 notes);
+}
+
+/* Generate return address signing DWARF annotation using shortcut DWARF
+   operators.  See aarch64_attach_ra_auth_dwarf for parameter meanings.  */
+
+static rtx
+aarch64_attach_ra_auth_dwarf_shortcut (rtx notes, HOST_WIDE_INT offset)
+{
+  rtx auth_op, par;
+
+  /* See GCC/include/dwarf2.def for the semantics of DW_OP_AARCH64_paciasp
+     and DW_OP_AARCH64_paciasp_deref.  */
+  if (offset == 0)
+    auth_op
+      = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, const0_rtx, const0_rtx),
+			DW_OP_AARCH64_paciasp);
+  else
+    auth_op
+      = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, GEN_INT (offset), const0_rtx),
+			DW_OP_AARCH64_paciasp_deref);
+
+  par = gen_rtx_PARALLEL (DImode, gen_rtvec (1, auth_op));
+
+  /* Generate the final dwarf value expression.  */
+  return alloc_reg_note (REG_CFA_VAL_EXPRESSION,
+			 gen_rtx_SET (gen_rtx_REG (DImode, LR_REGNUM), par),
+			 notes);
+}
+
+/* Generate AArch64 specific dwarf expression annotation.  NOTES is any existed
+   annotation that we want this new one to append.  BASE is a valid base
+   register if the value should be fetch from BASE + OFFSET.  */
+
+static rtx
+aarch64_attach_ra_auth_dwarf_note (rtx notes, HOST_WIDE_INT offset)
+{
+  if (aarch64_pauth_key != AARCH64_PAUTH_IKEY_A)
+    return aarch64_attach_ra_auth_dwarf_general (notes, offset);
+  else
+    return aarch64_attach_ra_auth_dwarf_shortcut (notes, offset);
+}
+
 static bool
 aarch64_frame_pointer_required (void)
 {
@@ -3058,6 +3156,7 @@ aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset,
     {
       rtx reg, mem;
       HOST_WIDE_INT offset;
+      unsigned lr_pair_reg = INVALID_REGNUM;
 
       if (skip_wb
 	  && (regno == cfun->machine->frame.wb_candidate1
@@ -3069,6 +3168,9 @@ aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset,
       mem = gen_mem_ref (mode, plus_constant (Pmode, stack_pointer_rtx,
 					      offset));
 
+      if (regno == LR_REGNUM)
+	lr_pair_reg = LR_REGNUM;
+
       regno2 = aarch64_next_callee_save (regno + 1, limit);
 
       if (regno2 <= limit
@@ -3090,12 +3192,39 @@ aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset,
 	     calculations; subsequent parts, are only
 	     frame-related if explicitly marked.  */
 	  RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1;
+
+	  if (regno2 == LR_REGNUM)
+	    lr_pair_reg = regno;
+
 	  regno = regno2;
 	}
       else
 	insn = emit_move_insn (mem, reg);
 
       RTX_FRAME_RELATED_P (insn) = 1;
+
+      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN && lr_pair_reg != INVALID_REGNUM)
+	{
+	  rtx cfi_ops = NULL_RTX;
+
+	  if (lr_pair_reg != LR_REGNUM)
+	    {
+	      /* Another register is saved together with LR to make a STP.  We
+		 need to generate .cfi_offset for that register.  */
+	      cfi_ops =
+		alloc_reg_note (REG_CFA_OFFSET,
+				gen_rtx_SET (mem,
+					     gen_rtx_REG (Pmode, lr_pair_reg)),
+				NULL_RTX);
+	    }
+
+	  HOST_WIDE_INT lr_cfa_adj
+	    = (-cfun->machine->frame.hard_fp_offset
+	       + cfun->machine->frame.reg_offset[LR_REGNUM]);
+
+	  REG_NOTES (insn)
+	    = aarch64_attach_ra_auth_dwarf_note (cfi_ops, lr_cfa_adj);
+	}
     }
 }
 
@@ -3204,12 +3333,18 @@ aarch64_expand_prologue (void)
   unsigned reg2 = cfun->machine->frame.wb_candidate2;
   rtx_insn *insn;
 
+  /* Do return address signing for all functions, even those for which LR is not
+     pushed onto stack.  */
   if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
-    emit_insn (gen_sign_reg (gen_rtx_REG (Pmode, LR_REGNUM),
-			     gen_rtx_REG (Pmode, LR_REGNUM),
-			     stack_pointer_rtx,
-			     GEN_INT (aarch64_pauth_key),
-			     const0_rtx));
+    {
+      insn = emit_insn (gen_sign_reg (gen_rtx_REG (Pmode, LR_REGNUM),
+				      gen_rtx_REG (Pmode, LR_REGNUM),
+				      stack_pointer_rtx,
+				      GEN_INT (aarch64_pauth_key),
+				      const0_rtx));
+      RTX_FRAME_RELATED_P (insn) = 1;
+      REG_NOTES (insn) = aarch64_attach_ra_auth_dwarf_note (NULL_RTX, 0);
+    }
 
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size;
@@ -3229,7 +3364,42 @@ aarch64_expand_prologue (void)
   aarch64_add_constant (Pmode, SP_REGNUM, IP0_REGNUM, -initial_adjust, true);
 
   if (callee_adjust != 0)
-    aarch64_push_regs (reg1, reg2, callee_adjust);
+    {
+      aarch64_push_regs (reg1, reg2, callee_adjust);
+      /* Generate return address signing dwarf annotation when
+	 omit-frame-pointer.  */
+      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
+	  && (reg1 == LR_REGNUM || reg2 == LR_REGNUM))
+	{
+	  rtx cfi_ops = NULL_RTX;
+
+	  if (reg2 == LR_REGNUM)
+	    {
+	      rtx mem_loc
+		= gen_rtx_MEM (Pmode,
+			       plus_constant (Pmode, stack_pointer_rtx, 0));
+	      cfi_ops
+		= alloc_reg_note (REG_CFA_OFFSET,
+				  gen_rtx_SET (mem_loc,
+					       gen_rtx_REG (Pmode, reg1)),
+				  cfi_ops);
+	    }
+
+	  rtx sp_adj
+	    = plus_constant (Pmode, stack_pointer_rtx, -callee_adjust);
+	  cfi_ops
+	    = alloc_reg_note (REG_CFA_ADJUST_CFA,
+			      gen_rtx_SET (stack_pointer_rtx, sp_adj),
+			      cfi_ops);
+
+	  HOST_WIDE_INT lr_cfa_adj
+	    = (-cfun->machine->frame.hard_fp_offset
+	       + cfun->machine->frame.reg_offset[LR_REGNUM]);
+	  rtx insn = get_last_insn ();
+	  REG_NOTES (insn) = aarch64_attach_ra_auth_dwarf_note (cfi_ops,
+								lr_cfa_adj);
+	}
+    }
 
   if (frame_pointer_needed)
     {
@@ -3331,7 +3501,12 @@ aarch64_expand_epilogue (bool for_sibcall)
       /* Emit delayed restores and set the CFA to be SP + initial_adjust.  */
       insn = get_last_insn ();
       rtx new_cfa = plus_constant (Pmode, stack_pointer_rtx, initial_adjust);
-      REG_NOTES (insn) = alloc_reg_note (REG_CFA_DEF_CFA, new_cfa, cfi_ops);
+      cfi_ops = alloc_reg_note (REG_CFA_DEF_CFA, new_cfa, cfi_ops);
+
+      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
+	REG_NOTES (insn) = aarch64_attach_ra_auth_dwarf_note (cfi_ops, 0);
+      else
+	REG_NOTES (insn) = cfi_ops;
       RTX_FRAME_RELATED_P (insn) = 1;
       cfi_ops = NULL;
     }
@@ -3355,11 +3530,14 @@ aarch64_expand_epilogue (bool for_sibcall)
      __builtin_eh_return.  */
   if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
       && (for_sibcall || !TARGET_PAUTH || crtl->calls_eh_return))
-    emit_insn (gen_auth_reg (gen_rtx_REG (Pmode, LR_REGNUM),
-			     gen_rtx_REG (Pmode, LR_REGNUM),
-			     stack_pointer_rtx,
-			     GEN_INT (aarch64_pauth_key),
-			     const0_rtx));
+    {
+      insn = emit_insn (gen_auth_reg (gen_rtx_REG (Pmode, LR_REGNUM),
+				      gen_rtx_REG (Pmode, LR_REGNUM),
+				      stack_pointer_rtx,
+				      GEN_INT (aarch64_pauth_key), const0_rtx));
+      add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (Pmode, LR_REGNUM));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   /* Stack adjustment for exception handler.  */
   if (crtl->calls_eh_return)


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

* [8/9][AArch64, libgcc] Runtime support for AArch64 DWARF operations
       [not found]             ` <9333e644-4daa-38e3-690e-2ea3473b0f29@foss.arm.com>
@ 2016-11-11 18:36               ` Jiong Wang
       [not found]               ` <1ae89b2b-9819-12f8-5341-776c3b02e5b3@foss.arm.com>
  1 sibling, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:36 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh

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

This patch add AArch64 specific runtime EH unwinding support for
DW_OP_AARCH64_pauth, DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref.

The semantics of them are described at the specification in patch [1/9].

The support includes:
   * Parsing these DWARF operations.  Perform unwinding actions according to
     their semantics.

   * Handling eh_return multi return paths.
     Function calling __builtin_eh_return (_Unwind_RaiseException*) will have
     multiple return paths.  One is for normal exit, the other is for install
     EH handler.  If the _Unwind_RaiseException itself is return address signed,
     then there will always be return address authentication before return,
     however, if the return path in _Unwind_RaiseException if from installing EH
     handler the address of which has already been authenticated during
     unwinding,  then we need to re-sign that address, so when the execution flow
     continues at _Unwind_RaiseException's epilogue, the authentication still
     works correctly.


OK for trunk?

libgcc/
2016-11-11  Jiong Wang<jiong.wang@arm.com>

         * config/aarch64/unwind-aarch64.c (RA_SIGN_BIT): New flag to indicate
         one frame is return address signed.
         (execute_stack_op): Handle DW_OP_AARCH64_pauth, DW_OP_AARCH64_paciasp,
         DW_OP_AARCH64_paciasp_deref.
         (uw_init_context): Call aarch64_uw_init_context_1.
         (uw_init_context_1): Rename to aarch64_uw_init_context_1.  Strip
         signature for seed address.
         (uw_install_context): Re-sign handler's address so it works correctly
         with caller's context.
         (uw_install_context_1): by_value[LR] can be true, after return address
         signing LR will come from DWARF value expression rule which is a
         by_value true rule.




[-- Attachment #2: 8.patch --]
[-- Type: text/x-patch, Size: 7236 bytes --]

diff --git a/libgcc/config/aarch64/unwind-aarch64.c b/libgcc/config/aarch64/unwind-aarch64.c
index 1fb6026d123f8e7fc676f5e95e8e66caccf3d6ff..f6441a56960dbd4b754f8fc17d581402389a4812 100644
--- a/libgcc/config/aarch64/unwind-aarch64.c
+++ b/libgcc/config/aarch64/unwind-aarch64.c
@@ -37,6 +37,10 @@
 #include "gthr.h"
 #include "unwind-dw2.h"
 
+/* This AArch64 implementation is exactly the same as libgcc/unwind-dw2.c,
+   except we have a customized uw_init_context_1 to handle pointer
+   authentication.  */
+
 #ifdef HAVE_SYS_SDT_H
 #include <sys/sdt.h>
 #endif
@@ -67,7 +71,7 @@
    waste.  However, some runtime libraries supplied with ICC do contain such
    an unorthodox transition, as well as the unwind info to match.  This loss
    of register restoration doesn't matter in practice, because the exception
-   is caught in the native unix abi, where all of the xmm registers are 
+   is caught in the native unix abi, where all of the xmm registers are
    call clobbered.
 
    Ideally, we'd record some bit to notice when we're failing to restore some
@@ -136,6 +140,8 @@ struct _Unwind_Context
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  /* Return address has been signed.  */
+#define RA_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
@@ -908,6 +914,89 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
 	case DW_OP_nop:
 	  goto no_push;
 
+	case DW_OP_AARCH64_paciasp:
+	  {
+	    _Unwind_Word lr_value = _Unwind_GetGR (context, LR_REGNUM);
+	    /* Note: initial is guaranteed to be CFA by DWARF specification.  */
+	    result
+	      = (_Unwind_Word) __builtin_aarch64_autia1716 ((void *) lr_value,
+							    initial);
+	    context->flags |= RA_SIGNED_BIT;
+	    break;
+	  }
+
+	case DW_OP_AARCH64_paciasp_deref:
+	  {
+	    _sleb128_t offset;
+	    op_ptr = read_sleb128 (op_ptr, &offset);
+	    result = (_Unwind_Word) read_pointer ((void *) initial + offset);
+	    result
+	      = (_Unwind_Word) __builtin_aarch64_autia1716 ((void *) result,
+							    initial);
+	    context->flags |= RA_SIGNED_BIT;
+	    break;
+	  }
+
+	case DW_OP_AARCH64_pauth:
+	  {
+	    _uleb128_t auth_descriptor;
+	    op_ptr = read_uleb128 (op_ptr, &auth_descriptor);
+	    enum aarch64_pauth_action_type action_code =
+	      (enum aarch64_pauth_action_type) (auth_descriptor & 0xf);
+	    context->flags |= RA_SIGNED_BIT;
+
+	    /* Different action may take different number of operands.
+	       AARCH64_PAUTH_DROP* takes one operand while AARCH64_PAUTH_AUTH
+	       takes two and both of them produce one result.  */
+	    switch (action_code)
+	      {
+	      case AARCH64_PAUTH_DROP_I:
+		{
+		  /* Fetch the value to drop signature.  */
+		  stack_elt -= 1;
+		  result = stack[stack_elt];
+		  result
+		    = (_Unwind_Word)
+		    __builtin_aarch64_xpaclri ((void *) result);
+		  break;
+		}
+	      case AARCH64_PAUTH_AUTH:
+		{
+		  enum aarch64_pauth_key_index key_index =
+		    (enum aarch64_pauth_key_index)
+		    (auth_descriptor >> 4) & 0xf;
+
+		  /* Fetch the value to be authenticated and the key.  */
+		  stack_elt -= 2;
+		  _Unwind_Word key = stack[stack_elt];
+		  result = stack[stack_elt + 1];
+
+		  switch (key_index)
+		    {
+		    case AARCH64_PAUTH_IKEY_A:
+		      result
+			= (_Unwind_Word)
+			__builtin_aarch64_autia1716 ((void *) result, key);
+		      break;
+		    case AARCH64_PAUTH_IKEY_B:
+		      result
+			= (_Unwind_Word)
+			__builtin_aarch64_autib1716 ((void *) result, key);
+		      break;
+		    default:
+		      /* For C++ exception unwinding, only instruction
+			 pointers are expected.  */
+		      gcc_unreachable ();
+		    }
+		}
+		break;
+	      default:
+		gcc_unreachable ();
+	      }
+
+	    break;
+	  }
+
 	default:
 	  gcc_unreachable ();
 	}
@@ -1534,8 +1623,8 @@ uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
       /* Do any necessary initialization to access arbitrary stack frames. \
 	 On the SPARC, this means flushing the register windows.  */	   \
       __builtin_unwind_init ();						   \
-      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
-			 __builtin_return_address (0));			   \
+      aarch64_uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),	   \
+				 __builtin_return_address (0));		   \
     }									   \
   while (0)
 
@@ -1546,10 +1635,15 @@ init_dwarf_reg_size_table (void)
 }
 
 static void __attribute__((noinline))
-uw_init_context_1 (struct _Unwind_Context *context,
-		   void *outer_cfa, void *outer_ra)
+aarch64_uw_init_context_1 (struct _Unwind_Context *context,
+			   void *outer_cfa, void *outer_ra)
 {
   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+  /* Drop authentication signature for inner RA.  It's anyway will be
+     authenticated later before return if return addresss signing is enabled for
+     libgcc.  Here it's served as the seed address which will be used for table
+     searching,  we need the original address.  */
+  ra = __builtin_aarch64_xpaclri (ra);
   _Unwind_FrameState fs;
   _Unwind_SpTmp sp_slot;
   _Unwind_Reason_Code code;
@@ -1586,6 +1680,11 @@ uw_init_context_1 (struct _Unwind_Context *context,
      initialization context, then we can't see it in the given
      call frame data.  So have the initialization context tell us.  */
   context->ra = __builtin_extract_return_addr (outer_ra);
+  void *orig_ra = __builtin_aarch64_xpaclri (context->ra);
+  if (context->ra != orig_ra)
+    context->flags |= RA_SIGNED_BIT;
+  /* Same reason as described at this function start.  */
+  context->ra = orig_ra;
 }
 
 static void _Unwind_DebugHook (void *, void *)
@@ -1610,13 +1709,22 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
 
 /* Install TARGET into CURRENT so that we can return to it.  This is a
    macro because __builtin_eh_return must be invoked in the context of
-   our caller.  */
+   our caller.
+
+   For AArch64 pointer authentication, as target EH handler's address is
+   already authenticated, we need to sign it again with the original SP
+   of CURRENT.  */
 
 #define uw_install_context(CURRENT, TARGET)				\
   do									\
     {									\
       long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
       void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      if ((CURRENT)->flags & RA_SIGNED_BIT)				\
+	handler								\
+	  = __builtin_aarch64_paci1716 (handler,			\
+					(_Unwind_Word)			\
+					  (CURRENT)->cfa);		\
       _Unwind_DebugHook ((TARGET)->cfa, handler);			\
       __builtin_eh_return (offset, handler);				\
     }									\
@@ -1639,7 +1747,8 @@ uw_install_context_1 (struct _Unwind_Context *current,
       void *c = (void *) (_Unwind_Internal_Ptr) current->reg[i];
       void *t = (void *) (_Unwind_Internal_Ptr)target->reg[i];
 
-      gcc_assert (current->by_value[i] == 0);
+      gcc_assert (current->by_value[i] == 0
+		  || i == (AARCH64_DWARF_R0 + LR_REGNUM));
       if (target->by_value[i] && c)
 	{
 	  _Unwind_Word w;


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

* [7/9][AArch64, libgcc] Let AArch64 use customized unwinder file
       [not found]           ` <172bd740-755c-5267-3a9d-692c84d25395@foss.arm.com>
       [not found]             ` <9333e644-4daa-38e3-690e-2ea3473b0f29@foss.arm.com>
@ 2016-11-11 18:36             ` Jiong Wang
  2016-11-11 22:12               ` Joseph Myers
  1 sibling, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:36 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh, Ian Lance Taylor

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

We need customized EH unwinder support for AArch64 DWARF operations introduced
earlier in this patchset, these changes mostly need to be done in the generic
file unwind-dw2.c.

There are two ways of introducing these AArch64 support:
   * Introducing a few target macros so we can customize functions like
     uw_init_context, uw_install_context etc.
   * Use target private unwind-dw2 implementation, i.e duplicate the generic
     unwind-dw2.c into target config directory and use it instead of generic one.
     This is current used by IA64 and CR16 is using.

I am not sure which approach is the convention in libgcc, Ian, any comments on this?
Thanks.

This patch is the start of using approach 2 includes necessary Makefile support
and copying of original unwind-dw2.c.

A follow up patch will implement those AArch64 specific stuff so the change will
be very clear.

OK for trunk?

libgcc/
2016-11-11  Jiong Wang<jiong.wang@arm.com>

         * config.host (aarch64*-*-elf, aarch64*-*-rtems*, aarch64*-*-linux*):
         Include new AArch64 EH makefile.
         * config/aarch64/t-eh-aarch64: New EH makefile.
         * config/aarch64/unwind-aarch64.c: New EH unwinder implementation,
         copied from unwind-dw2.c.


[-- Attachment #2: 7.patch --]
[-- Type: text/x-patch, Size: 50104 bytes --]

diff --git a/libgcc/config.host b/libgcc/config.host
index 002f650be9a7cd6f69ce3d51639a735ca7eba564..2bf90818c03e71bd3a601b607b98ac6b78fe763a 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -330,12 +330,14 @@ aarch64*-*-elf | aarch64*-*-rtems*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	tmake_file="${tmake_file} ${cpu_type}/t-eh-aarch64"
 	;;
 aarch64*-*-linux*)
 	extra_parts="$extra_parts crtfastmath.o"
 	md_unwind_header=aarch64/linux-unwind.h
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	tmake_file="${tmake_file} ${cpu_type}/t-eh-aarch64"
 	;;
 alpha*-*-linux*)
 	tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm alpha/t-linux"
diff --git a/libgcc/config/aarch64/t-eh-aarch64 b/libgcc/config/aarch64/t-eh-aarch64
new file mode 100644
index 0000000000000000000000000000000000000000..2ccc02d409ff850ec9db355a4d06efd125b4f68d
--- /dev/null
+++ b/libgcc/config/aarch64/t-eh-aarch64
@@ -0,0 +1,3 @@
+# Use customized EH unwinder implementation.
+LIB2ADDEH = $(srcdir)/config/aarch64/unwind-aarch64.c $(srcdir)/unwind-dw2-fde-dip.c \
+  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/aarch64/unwind-aarch64.c b/libgcc/config/aarch64/unwind-aarch64.c
new file mode 100644
index 0000000000000000000000000000000000000000..1fb6026d123f8e7fc676f5e95e8e66caccf3d6ff
--- /dev/null
+++ b/libgcc/config/aarch64/unwind-aarch64.c
@@ -0,0 +1,1715 @@
+/* DWARF2 exception handling and frame unwind runtime interface routines.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+
+   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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "libgcc_tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#ifdef __USING_SJLJ_EXCEPTIONS__
+# define NO_SIZE_OF_ENCODED_VALUE
+#endif
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "gthr.h"
+#include "unwind-dw2.h"
+
+#ifdef HAVE_SYS_SDT_H
+#include <sys/sdt.h>
+#endif
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+#ifndef __LIBGCC_STACK_GROWS_DOWNWARD__
+#define __LIBGCC_STACK_GROWS_DOWNWARD__ 0
+#else
+#undef __LIBGCC_STACK_GROWS_DOWNWARD__
+#define __LIBGCC_STACK_GROWS_DOWNWARD__ 1
+#endif
+
+/* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
+#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
+#define PRE_GCC3_DWARF_FRAME_REGISTERS __LIBGCC_DWARF_FRAME_REGISTERS__
+#endif
+
+/* ??? For the public function interfaces, we tend to gcc_assert that the
+   column numbers are in range.  For the dwarf2 unwind info this does happen,
+   although so far in a case that doesn't actually matter.
+
+   See PR49146, in which a call from x86_64 ms abi to x86_64 unix abi stores
+   the call-saved xmm registers and annotates them.  We havn't bothered
+   providing support for the xmm registers for the x86_64 port primarily
+   because the 64-bit windows targets don't use dwarf2 unwind, using sjlj or
+   SEH instead.  Adding the support for unix targets would generally be a
+   waste.  However, some runtime libraries supplied with ICC do contain such
+   an unorthodox transition, as well as the unwind info to match.  This loss
+   of register restoration doesn't matter in practice, because the exception
+   is caught in the native unix abi, where all of the xmm registers are 
+   call clobbered.
+
+   Ideally, we'd record some bit to notice when we're failing to restore some
+   register recorded in the unwind info, but to do that we need annotation on
+   the unix->ms abi edge, so that we know when the register data may be
+   discarded.  And since this edge is also within the ICC library, we're
+   unlikely to be able to get the new annotation.
+
+   Barring a magic solution to restore the ms abi defined 128-bit xmm registers
+   (as distictly opposed to the full runtime width) without causing extra
+   overhead for normal unix abis, the best solution seems to be to simply
+   ignore unwind data for unknown columns.  */
+
+#define UNWIND_COLUMN_IN_RANGE(x) \
+    __builtin_expect((x) <= __LIBGCC_DWARF_FRAME_REGISTERS__, 1)
+
+#ifdef REG_VALUE_IN_UNWIND_CONTEXT
+typedef _Unwind_Word _Unwind_Context_Reg_Val;
+
+#ifndef ASSUME_EXTENDED_UNWIND_CONTEXT
+#define ASSUME_EXTENDED_UNWIND_CONTEXT 1
+#endif
+
+static inline _Unwind_Word
+_Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val)
+{
+  return val;
+}
+
+static inline _Unwind_Context_Reg_Val
+_Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val)
+{
+  return val;
+}
+#else
+typedef void *_Unwind_Context_Reg_Val;
+
+static inline _Unwind_Word
+_Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val)
+{
+  return (_Unwind_Word) (_Unwind_Internal_Ptr) val;
+}
+
+static inline _Unwind_Context_Reg_Val
+_Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val)
+{
+  return (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) val;
+}
+#endif
+
+#ifndef ASSUME_EXTENDED_UNWIND_CONTEXT
+#define ASSUME_EXTENDED_UNWIND_CONTEXT 0
+#endif
+
+/* This is the register and unwind state for a particular frame.  This
+   provides the information necessary to unwind up past a frame and return
+   to its caller.  */
+struct _Unwind_Context
+{
+  _Unwind_Context_Reg_Val reg[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
+  void *cfa;
+  void *ra;
+  void *lsda;
+  struct dwarf_eh_bases bases;
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
+  /* Context which has version/args_size/by_value fields.  */
+#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  _Unwind_Word flags;
+  /* 0 for now, can be increased when further fields are added to
+     struct _Unwind_Context.  */
+  _Unwind_Word version;
+  _Unwind_Word args_size;
+  char by_value[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
+};
+
+/* Byte size of every register managed by these routines.  */
+static unsigned char dwarf_reg_size_table[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
+
+\f
+/* Read unaligned data from the instruction buffer.  */
+
+union unaligned
+{
+  void *p;
+  unsigned u2 __attribute__ ((mode (HI)));
+  unsigned u4 __attribute__ ((mode (SI)));
+  unsigned u8 __attribute__ ((mode (DI)));
+  signed s2 __attribute__ ((mode (HI)));
+  signed s4 __attribute__ ((mode (SI)));
+  signed s8 __attribute__ ((mode (DI)));
+} __attribute__ ((packed));
+
+static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
+static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
+					       _Unwind_FrameState *);
+
+static inline void *
+read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
+
+static inline int
+read_1u (const void *p) { return *(const unsigned char *) p; }
+
+static inline int
+read_1s (const void *p) { return *(const signed char *) p; }
+
+static inline int
+read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
+
+static inline int
+read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
+
+static inline unsigned int
+read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
+
+static inline int
+read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
+
+static inline unsigned long
+read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
+
+static inline unsigned long
+read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
+\f
+static inline _Unwind_Word
+_Unwind_IsSignalFrame (struct _Unwind_Context *context)
+{
+  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
+}
+
+static inline void
+_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
+{
+  if (val)
+    context->flags |= SIGNAL_FRAME_BIT;
+  else
+    context->flags &= ~SIGNAL_FRAME_BIT;
+}
+
+static inline _Unwind_Word
+_Unwind_IsExtendedContext (struct _Unwind_Context *context)
+{
+  return (ASSUME_EXTENDED_UNWIND_CONTEXT
+	  || (context->flags & EXTENDED_CONTEXT_BIT));
+}
+\f
+/* Get the value of register INDEX as saved in CONTEXT.  */
+
+inline _Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  int size;
+  _Unwind_Context_Reg_Val val;
+
+#ifdef DWARF_ZERO_REG
+  if (index == DWARF_ZERO_REG)
+    return 0;
+#endif
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+  val = context->reg[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return _Unwind_Get_Unwind_Word (val);
+
+  /* This will segfault if the register hasn't been saved.  */
+  if (size == sizeof(_Unwind_Ptr))
+    return * (_Unwind_Ptr *) (_Unwind_Internal_Ptr) val;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      return * (_Unwind_Word *) (_Unwind_Internal_Ptr) val;
+    }
+}
+
+static inline void *
+_Unwind_GetPtr (struct _Unwind_Context *context, int index)
+{
+  return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->cfa;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  int size;
+  void *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    {
+      context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val);
+      return;
+    }
+
+  ptr = (void *) (_Unwind_Internal_Ptr) context->reg[index];
+
+  if (size == sizeof(_Unwind_Ptr))
+    * (_Unwind_Ptr *) ptr = val;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      * (_Unwind_Word *) ptr = val;
+    }
+}
+
+/* Get the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void *
+_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return &context->reg[index];
+  return (void *) (_Unwind_Internal_Ptr) context->reg[index];
+}
+
+/* Set the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void
+_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context))
+    context->by_value[index] = 0;
+  context->reg[index] = (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) p;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+static inline void
+_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
+		    _Unwind_Word val)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  /* Return column size may be smaller than _Unwind_Context_Reg_Val.  */
+  gcc_assert (dwarf_reg_size_table[index] <= sizeof (_Unwind_Context_Reg_Val));
+
+  context->by_value[index] = 1;
+  context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val);
+}
+
+/* Return nonzero if register INDEX is stored by value rather than
+   by reference.  */
+
+static inline int
+_Unwind_GRByValue (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  return context->by_value[index];
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = _Unwind_IsSignalFrame (context);
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Overwrite the return address for CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  context->ra = (void *) val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return context->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.func;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+
+#ifndef __ia64__
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.dbase;
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.tbase;
+}
+#endif
+
+#include "md-unwind-support.h"
+\f
+/* Extract any interesting information from the CIE for the translation
+   unit F belongs to.  Return a pointer to the byte after the augmentation,
+   or NULL if we encountered an undecipherable augmentation.  */
+
+static const unsigned char *
+extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
+		  _Unwind_FrameState *fs)
+{
+  const unsigned char *aug = cie->augmentation;
+  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+  const unsigned char *ret = NULL;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  /* g++ v2 "eh" has pointer immediately following augmentation string,
+     so it must be handled first.  */
+  if (aug[0] == 'e' && aug[1] == 'h')
+    {
+      fs->eh_ptr = read_pointer (p);
+      p += sizeof (void *);
+      aug += 2;
+    }
+
+  /* After the augmentation resp. pointer for "eh" augmentation
+     follows for CIE version >= 4 address size byte and
+     segment size byte.  */
+  if (__builtin_expect (cie->version >= 4, 0))
+    {
+      if (p[0] != sizeof (void *) || p[1] != 0)
+	return NULL;
+      p += 2;
+    }
+  /* Immediately following this are the code and
+     data alignment and return address column.  */
+  p = read_uleb128 (p, &utmp);
+  fs->code_align = (_Unwind_Word)utmp;
+  p = read_sleb128 (p, &stmp);
+  fs->data_align = (_Unwind_Sword)stmp;
+  if (cie->version == 1)
+    fs->retaddr_column = *p++;
+  else
+    {
+      p = read_uleb128 (p, &utmp);
+      fs->retaddr_column = (_Unwind_Word)utmp;
+    }
+  fs->lsda_encoding = DW_EH_PE_omit;
+
+  /* If the augmentation starts with 'z', then a uleb128 immediately
+     follows containing the length of the augmentation field following
+     the size.  */
+  if (*aug == 'z')
+    {
+      p = read_uleb128 (p, &utmp);
+      ret = p + utmp;
+
+      fs->saw_z = 1;
+      ++aug;
+    }
+
+  /* Iterate over recognized augmentation subsequences.  */
+  while (*aug != '\0')
+    {
+      /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
+      if (aug[0] == 'L')
+	{
+	  fs->lsda_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "R" indicates a byte indicating how FDE addresses are encoded.  */
+      else if (aug[0] == 'R')
+	{
+	  fs->fde_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "P" indicates a personality routine in the CIE augmentation.  */
+      else if (aug[0] == 'P')
+	{
+	  _Unwind_Ptr personality;
+
+	  p = read_encoded_value (context, *p, p + 1, &personality);
+	  fs->personality = (_Unwind_Personality_Fn) personality;
+	  aug += 1;
+	}
+
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+	{
+	  fs->signal_frame = 1;
+	  aug += 1;
+	}
+
+      /* Otherwise we have an unknown augmentation string.
+	 Bail unless we saw a 'z' prefix.  */
+      else
+	return ret;
+    }
+
+  return ret ? ret : p;
+}
+
+
+/* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL
+   onto the stack to start.  */
+
+static _Unwind_Word
+execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
+		  struct _Unwind_Context *context, _Unwind_Word initial)
+{
+  _Unwind_Word stack[64];	/* ??? Assume this is enough.  */
+  int stack_elt;
+
+  stack[0] = initial;
+  stack_elt = 1;
+
+  while (op_ptr < op_end)
+    {
+      enum dwarf_location_atom op = *op_ptr++;
+      _Unwind_Word result;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      switch (op)
+	{
+	case DW_OP_lit0:
+	case DW_OP_lit1:
+	case DW_OP_lit2:
+	case DW_OP_lit3:
+	case DW_OP_lit4:
+	case DW_OP_lit5:
+	case DW_OP_lit6:
+	case DW_OP_lit7:
+	case DW_OP_lit8:
+	case DW_OP_lit9:
+	case DW_OP_lit10:
+	case DW_OP_lit11:
+	case DW_OP_lit12:
+	case DW_OP_lit13:
+	case DW_OP_lit14:
+	case DW_OP_lit15:
+	case DW_OP_lit16:
+	case DW_OP_lit17:
+	case DW_OP_lit18:
+	case DW_OP_lit19:
+	case DW_OP_lit20:
+	case DW_OP_lit21:
+	case DW_OP_lit22:
+	case DW_OP_lit23:
+	case DW_OP_lit24:
+	case DW_OP_lit25:
+	case DW_OP_lit26:
+	case DW_OP_lit27:
+	case DW_OP_lit28:
+	case DW_OP_lit29:
+	case DW_OP_lit30:
+	case DW_OP_lit31:
+	  result = op - DW_OP_lit0;
+	  break;
+
+	case DW_OP_addr:
+	  result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
+	  op_ptr += sizeof (void *);
+	  break;
+
+	case DW_OP_GNU_encoded_addr:
+	  {
+	    _Unwind_Ptr presult;
+	    op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
+	    result = presult;
+	  }
+	  break;
+
+	case DW_OP_const1u:
+	  result = read_1u (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const1s:
+	  result = read_1s (op_ptr);
+	  op_ptr += 1;
+	  break;
+	case DW_OP_const2u:
+	  result = read_2u (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const2s:
+	  result = read_2s (op_ptr);
+	  op_ptr += 2;
+	  break;
+	case DW_OP_const4u:
+	  result = read_4u (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const4s:
+	  result = read_4s (op_ptr);
+	  op_ptr += 4;
+	  break;
+	case DW_OP_const8u:
+	  result = read_8u (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_const8s:
+	  result = read_8s (op_ptr);
+	  op_ptr += 8;
+	  break;
+	case DW_OP_constu:
+	  op_ptr = read_uleb128 (op_ptr, &utmp);
+	  result = (_Unwind_Word)utmp;
+	  break;
+	case DW_OP_consts:
+	  op_ptr = read_sleb128 (op_ptr, &stmp);
+	  result = (_Unwind_Sword)stmp;
+	  break;
+
+	case DW_OP_reg0:
+	case DW_OP_reg1:
+	case DW_OP_reg2:
+	case DW_OP_reg3:
+	case DW_OP_reg4:
+	case DW_OP_reg5:
+	case DW_OP_reg6:
+	case DW_OP_reg7:
+	case DW_OP_reg8:
+	case DW_OP_reg9:
+	case DW_OP_reg10:
+	case DW_OP_reg11:
+	case DW_OP_reg12:
+	case DW_OP_reg13:
+	case DW_OP_reg14:
+	case DW_OP_reg15:
+	case DW_OP_reg16:
+	case DW_OP_reg17:
+	case DW_OP_reg18:
+	case DW_OP_reg19:
+	case DW_OP_reg20:
+	case DW_OP_reg21:
+	case DW_OP_reg22:
+	case DW_OP_reg23:
+	case DW_OP_reg24:
+	case DW_OP_reg25:
+	case DW_OP_reg26:
+	case DW_OP_reg27:
+	case DW_OP_reg28:
+	case DW_OP_reg29:
+	case DW_OP_reg30:
+	case DW_OP_reg31:
+	  result = _Unwind_GetGR (context, op - DW_OP_reg0);
+	  break;
+	case DW_OP_regx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  result = _Unwind_GetGR (context, reg);
+	  break;
+
+	case DW_OP_breg0:
+	case DW_OP_breg1:
+	case DW_OP_breg2:
+	case DW_OP_breg3:
+	case DW_OP_breg4:
+	case DW_OP_breg5:
+	case DW_OP_breg6:
+	case DW_OP_breg7:
+	case DW_OP_breg8:
+	case DW_OP_breg9:
+	case DW_OP_breg10:
+	case DW_OP_breg11:
+	case DW_OP_breg12:
+	case DW_OP_breg13:
+	case DW_OP_breg14:
+	case DW_OP_breg15:
+	case DW_OP_breg16:
+	case DW_OP_breg17:
+	case DW_OP_breg18:
+	case DW_OP_breg19:
+	case DW_OP_breg20:
+	case DW_OP_breg21:
+	case DW_OP_breg22:
+	case DW_OP_breg23:
+	case DW_OP_breg24:
+	case DW_OP_breg25:
+	case DW_OP_breg26:
+	case DW_OP_breg27:
+	case DW_OP_breg28:
+	case DW_OP_breg29:
+	case DW_OP_breg30:
+	case DW_OP_breg31:
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
+	  break;
+	case DW_OP_bregx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
+	  break;
+
+	case DW_OP_dup:
+	  gcc_assert (stack_elt);
+	  result = stack[stack_elt - 1];
+	  break;
+
+	case DW_OP_drop:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+	  goto no_push;
+
+	case DW_OP_pick:
+	  offset = *op_ptr++;
+	  gcc_assert (offset < stack_elt - 1);
+	  result = stack[stack_elt - 1 - offset];
+	  break;
+
+	case DW_OP_over:
+	  gcc_assert (stack_elt >= 2);
+	  result = stack[stack_elt - 2];
+	  break;
+
+	case DW_OP_swap:
+	  {
+	    _Unwind_Word t;
+	    gcc_assert (stack_elt >= 2);
+	    t = stack[stack_elt - 1];
+	    stack[stack_elt - 1] = stack[stack_elt - 2];
+	    stack[stack_elt - 2] = t;
+	    goto no_push;
+	  }
+
+	case DW_OP_rot:
+	  {
+	    _Unwind_Word t1, t2, t3;
+
+	    gcc_assert (stack_elt >= 3);
+	    t1 = stack[stack_elt - 1];
+	    t2 = stack[stack_elt - 2];
+	    t3 = stack[stack_elt - 3];
+	    stack[stack_elt - 1] = t2;
+	    stack[stack_elt - 2] = t3;
+	    stack[stack_elt - 3] = t1;
+	    goto no_push;
+	  }
+
+	case DW_OP_deref:
+	case DW_OP_deref_size:
+	case DW_OP_abs:
+	case DW_OP_neg:
+	case DW_OP_not:
+	case DW_OP_plus_uconst:
+	  /* Unary operations.  */
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  result = stack[stack_elt];
+
+	  switch (op)
+	    {
+	    case DW_OP_deref:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		result = (_Unwind_Ptr) read_pointer (ptr);
+	      }
+	      break;
+
+	    case DW_OP_deref_size:
+	      {
+		void *ptr = (void *) (_Unwind_Ptr) result;
+		switch (*op_ptr++)
+		  {
+		  case 1:
+		    result = read_1u (ptr);
+		    break;
+		  case 2:
+		    result = read_2u (ptr);
+		    break;
+		  case 4:
+		    result = read_4u (ptr);
+		    break;
+		  case 8:
+		    result = read_8u (ptr);
+		    break;
+		  default:
+		    gcc_unreachable ();
+		  }
+	      }
+	      break;
+
+	    case DW_OP_abs:
+	      if ((_Unwind_Sword) result < 0)
+		result = -result;
+	      break;
+	    case DW_OP_neg:
+	      result = -result;
+	      break;
+	    case DW_OP_not:
+	      result = ~result;
+	      break;
+	    case DW_OP_plus_uconst:
+	      op_ptr = read_uleb128 (op_ptr, &utmp);
+	      result += (_Unwind_Word)utmp;
+	      break;
+
+	    default:
+	      gcc_unreachable ();
+	    }
+	  break;
+
+	case DW_OP_and:
+	case DW_OP_div:
+	case DW_OP_minus:
+	case DW_OP_mod:
+	case DW_OP_mul:
+	case DW_OP_or:
+	case DW_OP_plus:
+	case DW_OP_shl:
+	case DW_OP_shr:
+	case DW_OP_shra:
+	case DW_OP_xor:
+	case DW_OP_le:
+	case DW_OP_ge:
+	case DW_OP_eq:
+	case DW_OP_lt:
+	case DW_OP_gt:
+	case DW_OP_ne:
+	  {
+	    /* Binary operations.  */
+	    _Unwind_Word first, second;
+	    gcc_assert (stack_elt >= 2);
+	    stack_elt -= 2;
+
+	    second = stack[stack_elt];
+	    first = stack[stack_elt + 1];
+
+	    switch (op)
+	      {
+	      case DW_OP_and:
+		result = second & first;
+		break;
+	      case DW_OP_div:
+		result = (_Unwind_Sword) second / (_Unwind_Sword) first;
+		break;
+	      case DW_OP_minus:
+		result = second - first;
+		break;
+	      case DW_OP_mod:
+		result = second % first;
+		break;
+	      case DW_OP_mul:
+		result = second * first;
+		break;
+	      case DW_OP_or:
+		result = second | first;
+		break;
+	      case DW_OP_plus:
+		result = second + first;
+		break;
+	      case DW_OP_shl:
+		result = second << first;
+		break;
+	      case DW_OP_shr:
+		result = second >> first;
+		break;
+	      case DW_OP_shra:
+		result = (_Unwind_Sword) second >> first;
+		break;
+	      case DW_OP_xor:
+		result = second ^ first;
+		break;
+	      case DW_OP_le:
+		result = (_Unwind_Sword) second <= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ge:
+		result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
+		break;
+	      case DW_OP_eq:
+		result = (_Unwind_Sword) second == (_Unwind_Sword) first;
+		break;
+	      case DW_OP_lt:
+		result = (_Unwind_Sword) second < (_Unwind_Sword) first;
+		break;
+	      case DW_OP_gt:
+		result = (_Unwind_Sword) second > (_Unwind_Sword) first;
+		break;
+	      case DW_OP_ne:
+		result = (_Unwind_Sword) second != (_Unwind_Sword) first;
+		break;
+
+	      default:
+		gcc_unreachable ();
+	      }
+	  }
+	  break;
+
+	case DW_OP_skip:
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_bra:
+	  gcc_assert (stack_elt);
+	  stack_elt -= 1;
+
+	  offset = read_2s (op_ptr);
+	  op_ptr += 2;
+	  if (stack[stack_elt] != 0)
+	    op_ptr += offset;
+	  goto no_push;
+
+	case DW_OP_nop:
+	  goto no_push;
+
+	default:
+	  gcc_unreachable ();
+	}
+
+      /* Most things push a result value.  */
+      gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
+      stack[stack_elt++] = result;
+    no_push:;
+    }
+
+  /* We were executing this program to get a value.  It should be
+     at top of stack.  */
+  gcc_assert (stack_elt);
+  stack_elt -= 1;
+  return stack[stack_elt];
+}
+
+
+/* Decode DWARF 2 call frame information. Takes pointers the
+   instruction sequence to decode, current register information and
+   CIE info, and the PC range to evaluate.  */
+
+static void
+execute_cfa_program (const unsigned char *insn_ptr,
+		     const unsigned char *insn_end,
+		     struct _Unwind_Context *context,
+		     _Unwind_FrameState *fs)
+{
+  struct frame_state_reg_info *unused_rs = NULL;
+
+  /* Don't allow remember/restore between CIE and FDE programs.  */
+  fs->regs.prev = NULL;
+
+  /* The comparison with the return address uses < rather than <= because
+     we are only interested in the effects of code before the call; for a
+     noreturn function, the return address may point to unrelated code with
+     a different stack configuration that we are not interested in.  We
+     assume that the call itself is unwind info-neutral; if not, or if
+     there are delay instructions that adjust the stack, these must be
+     reflected at the point immediately before the call insn.
+     In signal frames, return address is after last completed instruction,
+     so we add 1 to return address to make the comparison <=.  */
+  while (insn_ptr < insn_end
+	 && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
+    {
+      unsigned char insn = *insn_ptr++;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      if ((insn & 0xc0) == DW_CFA_advance_loc)
+	fs->pc += (insn & 0x3f) * fs->code_align;
+      else if ((insn & 0xc0) == DW_CFA_offset)
+	{
+	  reg = insn & 0x3f;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	}
+      else if ((insn & 0xc0) == DW_CFA_restore)
+	{
+	  reg = insn & 0x3f;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    fs->regs.reg[reg].how = REG_UNSAVED;
+	}
+      else switch (insn)
+	{
+	case DW_CFA_set_loc:
+	  {
+	    _Unwind_Ptr pc;
+
+	    insn_ptr = read_encoded_value (context, fs->fde_encoding,
+					   insn_ptr, &pc);
+	    fs->pc = (void *) pc;
+	  }
+	  break;
+
+	case DW_CFA_advance_loc1:
+	  fs->pc += read_1u (insn_ptr) * fs->code_align;
+	  insn_ptr += 1;
+	  break;
+	case DW_CFA_advance_loc2:
+	  fs->pc += read_2u (insn_ptr) * fs->code_align;
+	  insn_ptr += 2;
+	  break;
+	case DW_CFA_advance_loc4:
+	  fs->pc += read_4u (insn_ptr) * fs->code_align;
+	  insn_ptr += 4;
+	  break;
+
+	case DW_CFA_offset_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	  break;
+
+	case DW_CFA_restore_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  /* FIXME, this is wrong; the CIE might have said that the
+	     register was saved somewhere.  */
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    fs->regs.reg[reg].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_same_value:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    fs->regs.reg[reg].how = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_undefined:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    fs->regs.reg[reg].how = REG_UNDEFINED;
+	  break;
+
+	case DW_CFA_nop:
+	  break;
+
+	case DW_CFA_register:
+	  {
+	    _uleb128_t reg2;
+	    insn_ptr = read_uleb128 (insn_ptr, &reg);
+	    insn_ptr = read_uleb128 (insn_ptr, &reg2);
+	    reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	    if (UNWIND_COLUMN_IN_RANGE (reg))
+	      {
+	        fs->regs.reg[reg].how = REG_SAVED_REG;
+	        fs->regs.reg[reg].loc.reg = (_Unwind_Word)reg2;
+	      }
+	  }
+	  break;
+
+	case DW_CFA_remember_state:
+	  {
+	    struct frame_state_reg_info *new_rs;
+	    if (unused_rs)
+	      {
+		new_rs = unused_rs;
+		unused_rs = unused_rs->prev;
+	      }
+	    else
+	      new_rs = alloca (sizeof (struct frame_state_reg_info));
+
+	    *new_rs = fs->regs;
+	    fs->regs.prev = new_rs;
+	  }
+	  break;
+
+	case DW_CFA_restore_state:
+	  {
+	    struct frame_state_reg_info *old_rs = fs->regs.prev;
+	    fs->regs = *old_rs;
+	    old_rs->prev = unused_rs;
+	    unused_rs = old_rs;
+	  }
+	  break;
+
+	case DW_CFA_def_cfa:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_register:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = utmp;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_def_cfa_expression:
+	  fs->regs.cfa_exp = insn_ptr;
+	  fs->regs.cfa_how = CFA_EXP;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_EXP;
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
+	    }
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	  /* Dwarf3.  */
+	case DW_CFA_offset_extended_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	  break;
+
+	case DW_CFA_def_cfa_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  break;
+
+	case DW_CFA_def_cfa_offset_sf:
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_val_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	  break;
+
+	case DW_CFA_val_offset_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	  break;
+
+	case DW_CFA_val_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_VAL_EXP;
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
+	    }
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_GNU_window_save:
+	  /* ??? Hardcoded for SPARC register window configuration.  */
+	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
+	    for (reg = 16; reg < 32; ++reg)
+	      {
+		fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
+	      }
+	  break;
+
+	case DW_CFA_GNU_args_size:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  context->args_size = (_Unwind_Word)utmp;
+	  break;
+
+	case DW_CFA_GNU_negative_offset_extended:
+	  /* Obsoleted by DW_CFA_offset_extended_sf, but used by
+	     older PowerPC code.  */
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Word) utmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = -offset;
+	    }
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+}
+\f
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+   its caller and decode it into FS.  This function also sets the
+   args_size and lsda members of CONTEXT, as they are really information
+   about the caller's frame.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const struct dwarf_fde *fde;
+  const struct dwarf_cie *cie;
+  const unsigned char *aug, *insn, *end;
+
+  memset (fs, 0, sizeof (*fs));
+  context->args_size = 0;
+  context->lsda = 0;
+
+  if (context->ra == 0)
+    return _URC_END_OF_STACK;
+
+  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
+			  &context->bases);
+  if (fde == NULL)
+    {
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      /* Couldn't find frame unwind info for this function.  Try a
+	 target-specific fallback mechanism.  This will necessarily
+	 not provide a personality routine or LSDA.  */
+      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
+#else
+      return _URC_END_OF_STACK;
+#endif
+    }
+
+  fs->pc = context->bases.func;
+
+  cie = get_cie (fde);
+  insn = extract_cie_info (cie, context, fs);
+  if (insn == NULL)
+    /* CIE contained unknown augmentation.  */
+    return _URC_FATAL_PHASE1_ERROR;
+
+  /* First decode all the insns in the CIE.  */
+  end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
+  execute_cfa_program (insn, end, context, fs);
+
+  /* Locate augmentation for the fde.  */
+  aug = (const unsigned char *) fde + sizeof (*fde);
+  aug += 2 * size_of_encoded_value (fs->fde_encoding);
+  insn = NULL;
+  if (fs->saw_z)
+    {
+      _uleb128_t i;
+      aug = read_uleb128 (aug, &i);
+      insn = aug + i;
+    }
+  if (fs->lsda_encoding != DW_EH_PE_omit)
+    {
+      _Unwind_Ptr lsda;
+
+      aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
+      context->lsda = (void *) lsda;
+    }
+
+  /* Then the insns in the FDE up to our target PC.  */
+  if (insn == NULL)
+    insn = aug;
+  end = (const unsigned char *) next_fde (fde);
+  execute_cfa_program (insn, end, context, fs);
+
+  return _URC_NO_REASON;
+}
+\f
+typedef struct frame_state
+{
+  void *cfa;
+  void *eh_ptr;
+  long cfa_offset;
+  long args_size;
+  long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+  unsigned short cfa_reg;
+  unsigned short retaddr_column;
+  char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+struct frame_state * __frame_state_for (void *, struct frame_state *);
+
+/* Called from pre-G++ 3.0 __throw to find the registers to restore for
+   a given PC_TARGET.  The caller should allocate a local variable of
+   `struct frame_state' and pass its address to STATE_IN.  */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+  struct _Unwind_Context context;
+  _Unwind_FrameState fs;
+  int reg;
+
+  memset (&context, 0, sizeof (struct _Unwind_Context));
+  if (!ASSUME_EXTENDED_UNWIND_CONTEXT)
+    context.flags = EXTENDED_CONTEXT_BIT;
+  context.ra = pc_target + 1;
+
+  if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
+    return 0;
+
+  /* We have no way to pass a location expression for the CFA to our
+     caller.  It wouldn't understand it anyway.  */
+  if (fs.regs.cfa_how == CFA_EXP)
+    return 0;
+
+  for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
+    {
+      state_in->saved[reg] = fs.regs.reg[reg].how;
+      switch (state_in->saved[reg])
+	{
+	case REG_SAVED_REG:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
+	  break;
+	case REG_SAVED_OFFSET:
+	  state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
+	  break;
+	default:
+	  state_in->reg_or_offset[reg] = 0;
+	  break;
+	}
+    }
+
+  state_in->cfa_offset = fs.regs.cfa_offset;
+  state_in->cfa_reg = fs.regs.cfa_reg;
+  state_in->retaddr_column = fs.retaddr_column;
+  state_in->args_size = context.args_size;
+  state_in->eh_ptr = fs.eh_ptr;
+
+  return state_in;
+}
+\f
+typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
+
+static inline void
+_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
+		     _Unwind_SpTmp *tmp_sp)
+{
+  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
+
+  if (size == sizeof(_Unwind_Ptr))
+    tmp_sp->ptr = (_Unwind_Ptr) cfa;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      tmp_sp->word = (_Unwind_Ptr) cfa;
+    }
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
+}
+
+static void
+uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct _Unwind_Context orig_context = *context;
+  void *cfa;
+  long i;
+
+#ifdef __LIBGCC_EH_RETURN_STACKADJ_RTX__
+  /* Special handling here: Many machines do not use a frame pointer,
+     and track the CFA only through offsets from the stack pointer from
+     one frame to the next.  In this case, the stack pointer is never
+     stored, so it has no saved address in the context.  What we do
+     have is the CFA from the previous stack frame.
+
+     In very special situations (such as unwind info for signal return),
+     there may be location expressions that use the stack pointer as well.
+
+     Do this conditionally for one frame.  This allows the unwind info
+     for one frame to save a copy of the stack pointer from the previous
+     frame, and be able to use much easier CFA mechanisms to do it.
+     Always zap the saved stack pointer value for the next frame; carrying
+     the value over from one frame to another doesn't make sense.  */
+
+  _Unwind_SpTmp tmp_sp;
+
+  if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
+#endif
+
+  /* Compute this frame's CFA.  */
+  switch (fs->regs.cfa_how)
+    {
+    case CFA_REG_OFFSET:
+      cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
+      cfa += fs->regs.cfa_offset;
+      break;
+
+    case CFA_EXP:
+      {
+	const unsigned char *exp = fs->regs.cfa_exp;
+	_uleb128_t len;
+
+	exp = read_uleb128 (exp, &len);
+	cfa = (void *) (_Unwind_Ptr)
+	  execute_stack_op (exp, exp + len, &orig_context, 0);
+	break;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+  context->cfa = cfa;
+
+  /* Compute the addresses of all registers saved in this frame.  */
+  for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__ + 1; ++i)
+    switch (fs->regs.reg[i].how)
+      {
+      case REG_UNSAVED:
+      case REG_UNDEFINED:
+	break;
+
+      case REG_SAVED_OFFSET:
+	_Unwind_SetGRPtr (context, i,
+			  (void *) (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_REG:
+	if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
+	  _Unwind_SetGRValue (context, i,
+			      _Unwind_GetGR (&orig_context,
+					     fs->regs.reg[i].loc.reg));
+	else
+	  _Unwind_SetGRPtr (context, i,
+			    _Unwind_GetGRPtr (&orig_context,
+					      fs->regs.reg[i].loc.reg));
+	break;
+
+      case REG_SAVED_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRPtr (context, i, (void *) val);
+	}
+	break;
+
+      case REG_SAVED_VAL_OFFSET:
+	_Unwind_SetGRValue (context, i,
+			    (_Unwind_Internal_Ptr)
+			    (cfa + fs->regs.reg[i].loc.offset));
+	break;
+
+      case REG_SAVED_VAL_EXP:
+	{
+	  const unsigned char *exp = fs->regs.reg[i].loc.exp;
+	  _uleb128_t len;
+	  _Unwind_Ptr val;
+
+	  exp = read_uleb128 (exp, &len);
+	  val = execute_stack_op (exp, exp + len, &orig_context,
+				  (_Unwind_Ptr) cfa);
+	  _Unwind_SetGRValue (context, i, val);
+	}
+	break;
+      }
+
+  _Unwind_SetSignalFrame (context, fs->signal_frame);
+
+#ifdef MD_FROB_UPDATE_CONTEXT
+  MD_FROB_UPDATE_CONTEXT (context, fs);
+#endif
+}
+
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+   of its caller.  Update CONTEXT to refer to the caller as well.  Note
+   that the args_size and lsda members are not updated here, but later in
+   uw_frame_state_for.  */
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context_1 (context, fs);
+
+  /* In general this unwinder doesn't make any distinction between
+     undefined and same_value rule.  Call-saved registers are assumed
+     to have same_value rule by default and explicit undefined
+     rule is handled like same_value.  The only exception is
+     DW_CFA_undefined on retaddr_column which is supposed to
+     mark outermost frame in DWARF 3.  */
+  if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
+      == REG_UNDEFINED)
+    /* uw_frame_state_for uses context->ra == 0 check to find outermost
+       stack frame.  */
+    context->ra = 0;
+  else
+    /* Compute the return address now, since the return address column
+       can change from frame to frame.  */
+    context->ra = __builtin_extract_return_addr
+      (_Unwind_GetPtr (context, fs->retaddr_column));
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+\f
+/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
+   level will be the return address and the CFA.  */
+
+#define uw_init_context(CONTEXT)					   \
+  do									   \
+    {									   \
+      /* Do any necessary initialization to access arbitrary stack frames. \
+	 On the SPARC, this means flushing the register windows.  */	   \
+      __builtin_unwind_init ();						   \
+      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
+			 __builtin_return_address (0));			   \
+    }									   \
+  while (0)
+
+static inline void
+init_dwarf_reg_size_table (void)
+{
+  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+}
+
+static void __attribute__((noinline))
+uw_init_context_1 (struct _Unwind_Context *context,
+		   void *outer_cfa, void *outer_ra)
+{
+  void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+  _Unwind_FrameState fs;
+  _Unwind_SpTmp sp_slot;
+  _Unwind_Reason_Code code;
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->ra = ra;
+  if (!ASSUME_EXTENDED_UNWIND_CONTEXT)
+    context->flags = EXTENDED_CONTEXT_BIT;
+
+  code = uw_frame_state_for (context, &fs);
+  gcc_assert (code == _URC_NO_REASON);
+
+#if __GTHREADS
+  {
+    static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
+    if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
+	&& dwarf_reg_size_table[0] == 0)
+      init_dwarf_reg_size_table ();
+  }
+#else
+  if (dwarf_reg_size_table[0] == 0)
+    init_dwarf_reg_size_table ();
+#endif
+
+  /* Force the frame state to use the known cfa value.  */
+  _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
+  fs.regs.cfa_how = CFA_REG_OFFSET;
+  fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+  fs.regs.cfa_offset = 0;
+
+  uw_update_context_1 (context, &fs);
+
+  /* If the return address column was saved in a register in the
+     initialization context, then we can't see it in the given
+     call frame data.  So have the initialization context tell us.  */
+  context->ra = __builtin_extract_return_addr (outer_ra);
+}
+
+static void _Unwind_DebugHook (void *, void *)
+  __attribute__ ((__noinline__, __used__, __noclone__));
+
+/* This function is called during unwinding.  It is intended as a hook
+   for a debugger to intercept exceptions.  CFA is the CFA of the
+   target frame.  HANDLER is the PC to which control will be
+   transferred.  */
+static void
+_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+		   void *handler __attribute__ ((__unused__)))
+{
+  /* We only want to use stap probes starting with v3.  Earlier
+     versions added too much startup cost.  */
+#if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3
+  STAP_PROBE2 (libgcc, unwind, cfa, handler);
+#else
+  asm ("");
+#endif
+}
+
+/* Install TARGET into CURRENT so that we can return to it.  This is a
+   macro because __builtin_eh_return must be invoked in the context of
+   our caller.  */
+
+#define uw_install_context(CURRENT, TARGET)				\
+  do									\
+    {									\
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      _Unwind_DebugHook ((TARGET)->cfa, handler);			\
+      __builtin_eh_return (offset, handler);				\
+    }									\
+  while (0)
+
+static long
+uw_install_context_1 (struct _Unwind_Context *current,
+		      struct _Unwind_Context *target)
+{
+  long i;
+  _Unwind_SpTmp sp_slot;
+
+  /* If the target frame does not have a saved stack pointer,
+     then set up the target's CFA.  */
+  if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
+
+  for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__; ++i)
+    {
+      void *c = (void *) (_Unwind_Internal_Ptr) current->reg[i];
+      void *t = (void *) (_Unwind_Internal_Ptr)target->reg[i];
+
+      gcc_assert (current->by_value[i] == 0);
+      if (target->by_value[i] && c)
+	{
+	  _Unwind_Word w;
+	  _Unwind_Ptr p;
+	  if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
+	    {
+	      w = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &w, sizeof (_Unwind_Word));
+	    }
+	  else
+	    {
+	      gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
+	      p = (_Unwind_Internal_Ptr) t;
+	      memcpy (c, &p, sizeof (_Unwind_Ptr));
+	    }
+	}
+      else if (t && c && t != c)
+	memcpy (c, t, dwarf_reg_size_table[i]);
+    }
+
+  /* If the current frame doesn't have a saved stack pointer, then we
+     need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
+     pointer value reloaded.  */
+  if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
+    {
+      void *target_cfa;
+
+      target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
+
+      /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
+      if (__LIBGCC_STACK_GROWS_DOWNWARD__)
+	return target_cfa - current->cfa + target->args_size;
+      else
+	return current->cfa - target_cfa - target->args_size;
+    }
+  return 0;
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  /* The CFA is not sufficient to disambiguate the context of a function
+     interrupted by a signal before establishing its frame and the context
+     of the signal itself.  */
+  if (__LIBGCC_STACK_GROWS_DOWNWARD__)
+    return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
+  else
+    return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
+}
+
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetDataRelBase);
+alias (_Unwind_GetTextRelBase);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif /* !USING_SJLJ_EXCEPTIONS */


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

* [9/9][RFC][AArch64] Accelerate -fstack-protector through pointer authentication extension
       [not found]               ` <1ae89b2b-9819-12f8-5341-776c3b02e5b3@foss.arm.com>
@ 2016-11-11 18:37                 ` Jiong Wang
  2017-01-18 17:10                   ` [AArch64] " Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2016-11-11 18:37 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh

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

This patch accelerates GCC's existed -fstack-protector using ARMv8.3-A pointer
authentication instructions.

Given AArch64 currently has the following stack layout:

   | caller's LR
   | ....
   |------------
   | canary        <- sentinel for -fstack-protector
   | locals (buffer located here)
   |------------
   |
   | other callees
   |
   | callee's LR  <- sentinel for -msign-return-address
   |------------
   |

we can switch locals and callees,

     | ...
     | vararg
     |------------
     | other callee
     |------------
     | LR
     |------------
     | locals (buffer located here)

We then sign LR and make it serve as canary value.  There are several benefits
of this approach:

   *  It's evetually -msign-return-address + swap locals and callees areas.
   *  Require nearly no modifications on prologue and epilogue, avoid making them
      complexer.
   *  No need of any other runtime support, libssp is not required.

The runtime overhead before and after this patch will be:

   o canary insert

     GCC default SSP runtime was loading from global variable "__stack_chk_guard"
     initilized in libssp:

       adrp    x19, _GLOBAL_OFFSET_TABLE_
       ldr     x19, [x19, #:gotpage_lo15:__stack_chk_guard]
       ldr     x2, [x19]
       str     x2, [x29, 56]

     this patch accelerats into:

       sign lr

   o canary check

     GCC default SSP runtime was reloading from stack, then comparing with
     original value and branch to abort function:

       ldr     x2, [x29, 56]
       ldr     x1, [x19]
       eor     x1, x2, x1
       cbnz    x1, .L5
       ...
       ret
       .L5:
       bl      __stack_chk_fail

     acclerated into:

       aut lr + ret or retaa
     the the canary value (signed LR) fails authentication, the return to invalid
     address will cause exception.

NOTE, this approach however requires DWARF change as the original LR is signed,
the binary needs new libgcc to make sure c++ eh works correctly.  Given this
acceleration already needs the user specify -mstack-protector-dialect=pauth
which means the target platform largely should have install new libgcc, otherwise
you can't utilize new pointer authentication features.

gcc/
2016-11-11  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-opts.h (aarch64_stack_protector_type): New
         enum.
         (aarch64_layout_frame): Swap callees and locals when
         -mstack-protector-dialect=pauth specified.
         (aarch64_expand_prologue): Use AARCH64_PAUTH_SSP_OR_RA_SIGN instead
         of AARCH64_ENABLE_RETURN_ADDRESS_SIGN.
         (aarch64_expand_epilogue): Likewise.
         * config/aarch64/aarch64.md (*do_return): Likewise.
         (aarch64_override_options): Sanity check for ILP32 and TARGET_PAUTH.
         * config/aarch64/aarch64.h (AARCH64_PAUTH_SSP_OPTION, AARCH64_PAUTH_SSP,
         AARCH64_PAUTH_SSP_OR_RA_SIGN, LINK_SSP_SPEC): New defines.
         * config/aarch64/aarch64.opt (-mstack-protector-dialect=): New option.
         * doc/invoke.texi (AArch64 Options): Documents
         -mstack-protector-dialect=.


[-- Attachment #2: 9.patch --]
[-- Type: text/x-patch, Size: 7380 bytes --]

diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
index 41c14b38a6188d399eb04baca2896e033c03ff1b..ff464ea5675146d62f0b676fe776f882fc1b8d80 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -99,4 +99,10 @@ enum aarch64_function_type {
   AARCH64_FUNCTION_ALL
 };
 
+/* GCC standard stack protector (Canary insertion based) types for AArch64.  */
+enum aarch64_stack_protector_type {
+  STACK_PROTECTOR_TRAD,
+  STACK_PROTECTOR_PAUTH
+};
+
 #endif
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 907e8bdf5b4961b3107dcd5a481de28335e4be89..73ef2677a11450fe21f765011317bd3367ef0d94 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -982,4 +982,25 @@ enum aarch64_pauth_action_type
   AARCH64_PAUTH_AUTH
 };
 
+/* Pointer authentication accelerated -fstack-protector.  */
+#define AARCH64_PAUTH_SSP_OPTION \
+  (TARGET_PAUTH && aarch64_stack_protector_dialect == STACK_PROTECTOR_PAUTH)
+
+#define AARCH64_PAUTH_SSP \
+  (crtl->stack_protect_guard && AARCH64_PAUTH_SSP_OPTION)
+
+#define AARCH64_PAUTH_SSP_OR_RA_SIGN \
+  (AARCH64_PAUTH_SSP || AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
+
+#ifndef TARGET_LIBC_PROVIDES_SSP
+#define LINK_SSP_SPEC "%{!mstack-protector-dialect=pauth:\
+			 %{fstack-protector|fstack-protector-all\
+			   |fstack-protector-strong|fstack-protector-explicit:\
+			   -lssp_nonshared -lssp}}"
+#endif
+
+/* Don't use GCC default SSP runtime if pointer authentication acceleration
+   enabled.  */
+#define ENABLE_DEFAULT_SSP_RUNTIME  !(AARCH64_PAUTH_SSP_OPTION)
+
 #endif /* GCC_AARCH64_H */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index cae177dca511fdb909ef82c972d3bbdebab215e2..c469baf92268ff894f5cf0ea9f5dbd4180714b98 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2993,6 +2993,15 @@ aarch64_layout_frame (void)
 	= cfun->machine->frame.frame_size - cfun->machine->frame.initial_adjust;
     }
 
+  if (AARCH64_PAUTH_SSP)
+    {
+      cfun->machine->frame.callee_adjust = varargs_and_saved_regs_size;
+      cfun->machine->frame.final_adjust
+	= cfun->machine->frame.frame_size - cfun->machine->frame.callee_adjust;
+      cfun->machine->frame.hard_fp_offset = cfun->machine->frame.callee_adjust;
+      cfun->machine->frame.locals_offset = cfun->machine->frame.hard_fp_offset;
+    }
+
   cfun->machine->frame.laid_out = true;
 }
 
@@ -3203,7 +3212,7 @@ aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset,
 
       RTX_FRAME_RELATED_P (insn) = 1;
 
-      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN && lr_pair_reg != INVALID_REGNUM)
+      if (AARCH64_PAUTH_SSP_OR_RA_SIGN && lr_pair_reg != INVALID_REGNUM)
 	{
 	  rtx cfi_ops = NULL_RTX;
 
@@ -3335,7 +3344,7 @@ aarch64_expand_prologue (void)
 
   /* Do return address signing for all functions, even those for which LR is not
      pushed onto stack.  */
-  if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
+  if (AARCH64_PAUTH_SSP_OR_RA_SIGN)
     {
       insn = emit_insn (gen_sign_reg (gen_rtx_REG (Pmode, LR_REGNUM),
 				      gen_rtx_REG (Pmode, LR_REGNUM),
@@ -3368,7 +3377,7 @@ aarch64_expand_prologue (void)
       aarch64_push_regs (reg1, reg2, callee_adjust);
       /* Generate return address signing dwarf annotation when
 	 omit-frame-pointer.  */
-      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
+      if (AARCH64_PAUTH_SSP_OR_RA_SIGN
 	  && (reg1 == LR_REGNUM || reg2 == LR_REGNUM))
 	{
 	  rtx cfi_ops = NULL_RTX;
@@ -3503,7 +3512,7 @@ aarch64_expand_epilogue (bool for_sibcall)
       rtx new_cfa = plus_constant (Pmode, stack_pointer_rtx, initial_adjust);
       cfi_ops = alloc_reg_note (REG_CFA_DEF_CFA, new_cfa, cfi_ops);
 
-      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
+      if (AARCH64_PAUTH_SSP_OR_RA_SIGN)
 	REG_NOTES (insn) = aarch64_attach_ra_auth_dwarf_note (cfi_ops, 0);
       else
 	REG_NOTES (insn) = cfi_ops;
@@ -3528,7 +3537,7 @@ aarch64_expand_epilogue (bool for_sibcall)
      authentication, as the following stack adjustment will update CFA to
      handler's CFA while we want to use the CFA of the function which calls
      __builtin_eh_return.  */
-  if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
+  if (AARCH64_PAUTH_SSP_OR_RA_SIGN
       && (for_sibcall || !TARGET_PAUTH || crtl->calls_eh_return))
     {
       insn = emit_insn (gen_auth_reg (gen_rtx_REG (Pmode, LR_REGNUM),
@@ -8737,6 +8746,14 @@ aarch64_override_options (void)
   if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
     error ("Return address signing is only supported on LP64");
 
+  if (aarch64_stack_protector_dialect == STACK_PROTECTOR_PAUTH && TARGET_ILP32)
+    error ("Pointer authentication based -fstack-protector is only supported "
+	   "on LP64.");
+
+  if (aarch64_stack_protector_dialect == STACK_PROTECTOR_PAUTH && !TARGET_PAUTH)
+    error ("Pointer authentication based -fstack-protector is only supported "
+	   "on architecture with pointer authentication extension.");
+
   /* Make sure we properly set up the explicit options.  */
   if ((aarch64_cpu_string && valid_cpu)
        || (aarch64_tune_string && valid_tune))
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 754ea00d2f3027f0d4c57e1a2c1ea06d35135259..4fd94d23b7570fbcdb931e1e0a03257088c42955 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -581,9 +581,7 @@
   [(return)]
   ""
   {
-    if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
-	&& TARGET_PAUTH
-	&& !crtl->calls_eh_return)
+    if (AARCH64_PAUTH_SSP_OR_RA_SIGN && TARGET_PAUTH && !crtl->calls_eh_return)
       {
 	if (aarch64_pauth_key == AARCH64_PAUTH_IKEY_A)
 	  return "retaa";
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 0b172021dbba918ecc5a7d953cfcbdf8edfe0b5f..781f68f6b7789c386c4e2a21fef797ea8fc48810 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -198,3 +198,17 @@ Common Var(flag_mlow_precision_div) Optimization
 Enable the division approximation.  Enabling this reduces
 precision of division results to about 16 bits for
 single precision and to 32 bits for double precision.
+
+Enum
+Name(stack_protector_type) Type(enum aarch64_stack_protector_type)
+The possible stack protector dialects:
+
+EnumValue
+Enum(stack_protector_type) String(trad) Value(STACK_PROTECTOR_TRAD)
+
+EnumValue
+Enum(stack_protector_type) String(pauth) Value(STACK_PROTECTOR_PAUTH)
+
+mstack-protector-dialect=
+Target RejectNegative Joined Enum(stack_protector_type) Var(aarch64_stack_protector_dialect) Init(STACK_PROTECTOR_TRAD) Save
+Specify stack protector dialect.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e7f842f9d21bd4e94eec9955851d8632837ba2c3..32c5cee54c8897bfee3d135a548fa70ed555e1fe 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13357,6 +13357,12 @@ Select the key used for return address signing.  Permissible values are
 @samp{a_key} for A key and @samp{b_key} for B key.  @samp{a_key} is the default
 value.
 
+@item -mstack-protector-dialect=@var{dialect}
+@opindex mstack-protector-dialect
+Select the dialect for GCC -fstack-protector.  @samp{trad} for GCC default
+implementation and @samp{pauth} for pointer authentication accelerated
+implementation for AArch64 LP64.
+
 @end table
 
 @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-11 18:22 ` [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space Jiong Wang
  2016-11-11 18:33   ` [2/9] Encoding support for AArch64 DWARF operations Jiong Wang
       [not found]   ` <64dd1b38-ff0a-5df0-1d3c-2fbf083e2697@foss.arm.com>
@ 2016-11-11 19:39   ` Jakub Jelinek
  2016-11-15 16:00     ` Jiong Wang
  2016-12-28 19:54     ` Cary Coutant
  2 siblings, 2 replies; 75+ messages in thread
From: Jakub Jelinek @ 2016-11-11 19:39 UTC (permalink / raw)
  To: Jiong Wang; +Cc: gcc-patches, gdb-patches, Binutils, Richard Earnshaw (lists)

On Fri, Nov 11, 2016 at 06:21:48PM +0000, Jiong Wang wrote:
> This patch introduces three AARCH64 private DWARF operations in vendor extension
> space.
> 
> DW_OP_AARCH64_pauth 0xea
> ===
>   Takes one unsigned LEB 128 Pointer Authentication Description. Bits [3:0] of
>   the description contain the Authentication Action Code. All unused bits are
>   initialized to 0. The operation then proceeds according to the value of the
>   action code as described in the Action Code Table.
> 
> DW_OP_AARCH64_paciasp 0xeb
> ===
>   Authenticates the contents in X30/LR register as per A key for instruction
>   pointer using current CFA as salt. The result is pushed onto the stack.
> 
> DW_OP_AARCH64_paciasp_deref 0xec
> ===
>   Takes one signed LEB128 offset and retrieves 8-byte contents from the address
>   calculated by CFA plus this offset, the contents then authenticated as per A
>   key for instruction pointer using current CFA as salt. The result is pushed
>   onto the stack.

I'd like to point out that especially the vendor range of DW_OP_* is
extremely scarce resource, we have only a couple of unused values, so taking
3 out of the remaining unused 12 for a single architecture is IMHO too much.
Can't you use just a single opcode and encode which of the 3 operations it is
in say the low 2 bits of a LEB 128 operand?
We'll likely need to do RSN some multiplexing even for the generic GNU
opcodes if we need just a few further ones (say 0xff as an extension,
followed by uleb128 containing the opcode - 0xff).
In the non-vendor area we still have 54 values left, so there is more space
for future expansion.

	Jakub

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

* Re: [7/9][AArch64, libgcc] Let AArch64 use customized unwinder file
  2016-11-11 18:36             ` [7/9][AArch64, libgcc] Let AArch64 use customized unwinder file Jiong Wang
@ 2016-11-11 22:12               ` Joseph Myers
  2016-11-14 13:55                 ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Joseph Myers @ 2016-11-11 22:12 UTC (permalink / raw)
  To: Jiong Wang
  Cc: gcc-patches, Richard Earnshaw (lists),
	James Greenhalgh, Ian Lance Taylor

On Fri, 11 Nov 2016, Jiong Wang wrote:

> There are two ways of introducing these AArch64 support:
>   * Introducing a few target macros so we can customize functions like
>     uw_init_context, uw_install_context etc.
>   * Use target private unwind-dw2 implementation, i.e duplicate the generic
>     unwind-dw2.c into target config directory and use it instead of generic
> one.
>     This is current used by IA64 and CR16 is using.
> 
> I am not sure which approach is the convention in libgcc, Ian, any comments on
> this?

Although as you note duplication has been used before, I think it should 
be strongly discouraged; duplicated files are unlikely to be kept up to 
date with relevant changes to the main file.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [7/9][AArch64, libgcc] Let AArch64 use customized unwinder file
  2016-11-11 22:12               ` Joseph Myers
@ 2016-11-14 13:55                 ` Jiong Wang
  0 siblings, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-14 13:55 UTC (permalink / raw)
  To: Joseph Myers
  Cc: gcc-patches, Richard Earnshaw (lists),
	James Greenhalgh, Ian Lance Taylor

On 11/11/16 22:12, Joseph Myers wrote:
> On Fri, 11 Nov 2016, Jiong Wang wrote:
>
>> There are two ways of introducing these AArch64 support:
>>    * Introducing a few target macros so we can customize functions like
>>      uw_init_context, uw_install_context etc.
>>    * Use target private unwind-dw2 implementation, i.e duplicate the generic
>>      unwind-dw2.c into target config directory and use it instead of generic
>> one.
>>      This is current used by IA64 and CR16 is using.
>>
>> I am not sure which approach is the convention in libgcc, Ian, any comments on
>> this?
> Although as you note duplication has been used before, I think it should
> be strongly discouraged; duplicated files are unlikely to be kept up to
> date with relevant changes to the main file.
>
>
> Hi Joseph,

   The changes AArch64 needs to do on top of the generic unwind-dw2.c is at:

      https://gcc.gnu.org/ml/gcc-patches/2016-11/msg01167.html

   If I don't duplicate unwind-dw2.c, then I need to guard those changes with
something like __aarch64__ or introduce several target macros.  It looks to me
only the hunk that supports AArch64 DWARF operations worth a target macro,
something like MD_DW_OP_HANDLER, for the other changes they are quite scattered,
for example the field extension on "struct _Unwind_Context" and the relax of
assertion on uw_install_context_1.

   Any comments on this?

   Thanks.

Regards,
Jiong


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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-11 19:39   ` [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space Jakub Jelinek
@ 2016-11-15 16:00     ` Jiong Wang
  2016-11-15 16:18       ` Jakub Jelinek
  2016-12-28 19:54     ` Cary Coutant
  1 sibling, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2016-11-15 16:00 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: gcc-patches, gdb-patches, Binutils, Richard Earnshaw (lists)

On 11/11/16 19:38, Jakub Jelinek wrote:

> On Fri, Nov 11, 2016 at 06:21:48PM +0000, Jiong Wang wrote:
>> This patch introduces three AARCH64 private DWARF operations in vendor extension
>> space.
>>
>> DW_OP_AARCH64_pauth 0xea
>> ===
>>    Takes one unsigned LEB 128 Pointer Authentication Description. Bits [3:0] of
>>    the description contain the Authentication Action Code. All unused bits are
>>    initialized to 0. The operation then proceeds according to the value of the
>>    action code as described in the Action Code Table.
>>
>> DW_OP_AARCH64_paciasp 0xeb
>> ===
>>    Authenticates the contents in X30/LR register as per A key for instruction
>>    pointer using current CFA as salt. The result is pushed onto the stack.
>>
>> DW_OP_AARCH64_paciasp_deref 0xec
>> ===
>>    Takes one signed LEB128 offset and retrieves 8-byte contents from the address
>>    calculated by CFA plus this offset, the contents then authenticated as per A
>>    key for instruction pointer using current CFA as salt. The result is pushed
>>    onto the stack.
> I'd like to point out that especially the vendor range of DW_OP_* is
> extremely scarce resource, we have only a couple of unused values, so taking
> 3 out of the remaining unused 12 for a single architecture is IMHO too much.
> Can't you use just a single opcode and encode which of the 3 operations it is
> in say the low 2 bits of a LEB 128 operand?
> We'll likely need to do RSN some multiplexing even for the generic GNU
> opcodes if we need just a few further ones (say 0xff as an extension,
> followed by uleb128 containing the opcode - 0xff).
> In the non-vendor area we still have 54 values left, so there is more space
> for future expansion.
>
> 	Jakub

                                                                                        
   Seperate DWARF operations are introduced instead of combining all of them into
one are mostly because these operations are going to be used for most of the
functions once return address signing are enabled, and they are used for
describing frame unwinding that they will go into unwind table for C++ program
or C program compiled with -fexceptions, the impact on unwind table size is
significant.  So I was trying to lower the unwind table size overhead as much as
I can.

   IMHO, three numbers actually is not that much for one architecture in DWARF
operation vendor extension space as vendors can overlap with each other.  The
only painful thing from my understand is there are platform vendors, for example
"GNU" and "LLVM" etc, for which architecture vendor can't overlap with.

   In include/dwarf2.def, I saw DW_OP_GNU* has reserved 13, DW_OP_HP* has reserved
7 and DW_OP_PGI has reserved 1.

   So for an alternative approach, can these AArch64 extensions overlap and reuse
those numbers reserved for DW_OP_HP* ? for example 0xe4, 0xe5, 0xe6.  I am even
thinking GNU toolchain makes the 8 numbers reserved by existed DW_OP_HP* and
DW_OP_SGI* as architecture vendor area and allow multiplexing on them for
different architectures.  This may offer more flexibilities for architecture
vendors.

   Under current code base, my search shows the overlap should be safe inside
GCC/GDB and we only needs minor disassemble tweak in Binutils.

   Thanks.

Regards,
Jiong

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-15 16:00     ` Jiong Wang
@ 2016-11-15 16:18       ` Jakub Jelinek
  2016-11-15 16:48         ` Jiong Wang
  2016-11-15 16:51         ` Jiong Wang
  0 siblings, 2 replies; 75+ messages in thread
From: Jakub Jelinek @ 2016-11-15 16:18 UTC (permalink / raw)
  To: Jiong Wang, mjw
  Cc: gcc-patches, gdb-patches, Binutils, Richard Earnshaw (lists)

On Tue, Nov 15, 2016 at 04:00:40PM +0000, Jiong Wang wrote:
> >>   Takes one signed LEB128 offset and retrieves 8-byte contents from the address
> >>   calculated by CFA plus this offset, the contents then authenticated as per A
> >>   key for instruction pointer using current CFA as salt. The result is pushed
> >>   onto the stack.
> >I'd like to point out that especially the vendor range of DW_OP_* is
> >extremely scarce resource, we have only a couple of unused values, so taking
> >3 out of the remaining unused 12 for a single architecture is IMHO too much.
> >Can't you use just a single opcode and encode which of the 3 operations it is
> >in say the low 2 bits of a LEB 128 operand?
> >We'll likely need to do RSN some multiplexing even for the generic GNU
> >opcodes if we need just a few further ones (say 0xff as an extension,
> >followed by uleb128 containing the opcode - 0xff).
> >In the non-vendor area we still have 54 values left, so there is more space
> >for future expansion.
> 
>   Seperate DWARF operations are introduced instead of combining all of them into
> one are mostly because these operations are going to be used for most of the
> functions once return address signing are enabled, and they are used for
> describing frame unwinding that they will go into unwind table for C++ program
> or C program compiled with -fexceptions, the impact on unwind table size is
> significant.  So I was trying to lower the unwind table size overhead as much as
> I can.
> 
>   IMHO, three numbers actually is not that much for one architecture in DWARF
> operation vendor extension space as vendors can overlap with each other.  The
> only painful thing from my understand is there are platform vendors, for example
> "GNU" and "LLVM" etc, for which architecture vendor can't overlap with.

For DW_OP_*, there aren't two vendor ranges like e.g. in ELF, there is just
one range, so ideally the opcodes would be unique everywhere, if not, there
is just a single GNU vendor, there is no separate range for Aarch64, that
can overlap with range for x86_64, and powerpc, etc.

Perhaps we could declare that certain opcode subrange for the GNU vendor is
architecture specific and document that the meaning of opcodes in that range
and count/encoding of their arguments depends on the architecture, but then
we should document how to figure out the architecture too (e.g. for ELF
base it on the containing EM_*).  All the tools that look at DWARF (readelf,
objdump, eu-readelf, libdw, libunwind, gdb, dwz, ...) would need to agree on that
though.

I know nothing about the aarch64 return address signing, would all 3 or say
2 usually appear together without any separate pc advance, or are they all
going to appear frequently and at different pcs?  Perhaps if there is just 1
opcode and has all the info encoded just in one bigger uleb128 or something
similar...

	Jakub

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-15 16:18       ` Jakub Jelinek
@ 2016-11-15 16:48         ` Jiong Wang
  2016-11-15 19:25           ` Richard Earnshaw (lists)
  2016-11-15 16:51         ` Jiong Wang
  1 sibling, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2016-11-15 16:48 UTC (permalink / raw)
  To: Jakub Jelinek, mjw
  Cc: gcc-patches, gdb-patches, Binutils, Richard Earnshaw (lists)



On 15/11/16 16:18, Jakub Jelinek wrote:
> On Tue, Nov 15, 2016 at 04:00:40PM +0000, Jiong Wang wrote:
>>>>    Takes one signed LEB128 offset and retrieves 8-byte contents from the address
>>>>    calculated by CFA plus this offset, the contents then authenticated as per A
>>>>    key for instruction pointer using current CFA as salt. The result is pushed
>>>>    onto the stack.
>>> I'd like to point out that especially the vendor range of DW_OP_* is
>>> extremely scarce resource, we have only a couple of unused values, so taking
>>> 3 out of the remaining unused 12 for a single architecture is IMHO too much.
>>> Can't you use just a single opcode and encode which of the 3 operations it is
>>> in say the low 2 bits of a LEB 128 operand?
>>> We'll likely need to do RSN some multiplexing even for the generic GNU
>>> opcodes if we need just a few further ones (say 0xff as an extension,
>>> followed by uleb128 containing the opcode - 0xff).
>>> In the non-vendor area we still have 54 values left, so there is more space
>>> for future expansion.
>>    Seperate DWARF operations are introduced instead of combining all of them into
>> one are mostly because these operations are going to be used for most of the
>> functions once return address signing are enabled, and they are used for
>> describing frame unwinding that they will go into unwind table for C++ program
>> or C program compiled with -fexceptions, the impact on unwind table size is
>> significant.  So I was trying to lower the unwind table size overhead as much as
>> I can.
>>
>>    IMHO, three numbers actually is not that much for one architecture in DWARF
>> operation vendor extension space as vendors can overlap with each other.  The
>> only painful thing from my understand is there are platform vendors, for example
>> "GNU" and "LLVM" etc, for which architecture vendor can't overlap with.
> For DW_OP_*, there aren't two vendor ranges like e.g. in ELF, there is just
> one range, so ideally the opcodes would be unique everywhere, if not, there
> is just a single GNU vendor, there is no separate range for Aarch64, that
> can overlap with range for x86_64, and powerpc, etc.
>
> Perhaps we could declare that certain opcode subrange for the GNU vendor is
> architecture specific and document that the meaning of opcodes in that range
> and count/encoding of their arguments depends on the architecture, but then
> we should document how to figure out the architecture too (e.g. for ELF
> base it on the containing EM_*).  All the tools that look at DWARF (readelf,
> objdump, eu-readelf, libdw, libunwind, gdb, dwz, ...) would need to agree on that
> though.
>
> I know nothing about the aarch64 return address signing, would all 3 or say
> 2 usually appear together without any separate pc advance, or are they all
> going to appear frequently and at different pcs?

   I think it's the latter, the DW_OP_AARCH64_paciasp and
DW_OP_AARCH64_paciasp_deref are going to appear frequently and at different pcs.
   
   For example, the following function prologue, there are three instructions
at 0x0, 0x4, 0x8.

   After the first instruction at 0x0, LR/X30 will be mangled.  The "paciasp" always
mangle LR register using SP as salt and write back the value into LR.  We then generate
DW_OP_AARCH64_paciasp to notify any unwinder that the original LR is mangled in this
way so they can unwind the original value properly.

   After the second instruction at 0x4, The mangled value of LR/X30 will be pushed on
to stack, unlike usual .cfi_offset, the unwind rule for LR/X30 becomes: first fetch the
mangled value from stack offset -16, then do whatever to restore the original value
from the mangled value.  This is represented by (DW_OP_AARCH64_paciasp_deref, offset).

         .cfi_startproc
    0x0  paciasp (this instruction sign return address register LR/X30)
         .cfi_val_expression 30, DW_OP_AARCH64_paciasp
    0x4  stp     x29, x30, [sp, -32]!
         .cfi_val_expression 30, DW_OP_AARCH64_paciasp_deref, -16
         .cfi_offset 29, -32
         .cfi_def_cfa_offset 32
    0x8  add     x29, sp, 0

> Perhaps if there is just 1
> opcode and has all the info encoded just in one bigger uleb128 or something
> similar...

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-15 16:18       ` Jakub Jelinek
  2016-11-15 16:48         ` Jiong Wang
@ 2016-11-15 16:51         ` Jiong Wang
  1 sibling, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-15 16:51 UTC (permalink / raw)
  To: Jakub Jelinek, mjw
  Cc: gcc-patches, gdb-patches, Binutils, Richard Earnshaw (lists)

On 15/11/16 16:18, Jakub Jelinek wrote:
> On Tue, Nov 15, 2016 at 04:00:40PM +0000, Jiong Wang wrote:
>>>>    Takes one signed LEB128 offset and retrieves 8-byte contents from the address
>>>>    calculated by CFA plus this offset, the contents then authenticated as per A
>>>>    key for instruction pointer using current CFA as salt. The result is pushed
>>>>    onto the stack.
>>> I'd like to point out that especially the vendor range of DW_OP_* is
>>> extremely scarce resource, we have only a couple of unused values, so taking
>>> 3 out of the remaining unused 12 for a single architecture is IMHO too much.
>>> Can't you use just a single opcode and encode which of the 3 operations it is
>>> in say the low 2 bits of a LEB 128 operand?
>>> We'll likely need to do RSN some multiplexing even for the generic GNU
>>> opcodes if we need just a few further ones (say 0xff as an extension,
>>> followed by uleb128 containing the opcode - 0xff).
>>> In the non-vendor area we still have 54 values left, so there is more space
>>> for future expansion.
>>    Seperate DWARF operations are introduced instead of combining all of them into
>> one are mostly because these operations are going to be used for most of the
>> functions once return address signing are enabled, and they are used for
>> describing frame unwinding that they will go into unwind table for C++ program
>> or C program compiled with -fexceptions, the impact on unwind table size is
>> significant.  So I was trying to lower the unwind table size overhead as much as
>> I can.
>>
>>    IMHO, three numbers actually is not that much for one architecture in DWARF
>> operation vendor extension space as vendors can overlap with each other.  The
>> only painful thing from my understand is there are platform vendors, for example
>> "GNU" and "LLVM" etc, for which architecture vendor can't overlap with.
> For DW_OP_*, there aren't two vendor ranges like e.g. in ELF, there is just
> one range, so ideally the opcodes would be unique everywhere, if not, there
> is just a single GNU vendor, there is no separate range for Aarch64, that
> can overlap with range for x86_64, and powerpc, etc.
>
> Perhaps we could declare that certain opcode subrange for the GNU vendor is
> architecture specific and document that the meaning of opcodes in that range
> and count/encoding of their arguments depends on the architecture, but then
> we should document how to figure out the architecture too (e.g. for ELF
> base it on the containing EM_*).  All the tools that look at DWARF (readelf,
> objdump, eu-readelf, libdw, libunwind, gdb, dwz, ...) would need to agree on that
> though.
>
> I know nothing about the aarch64 return address signing, would all 3 or say
> 2 usually appear together without any separate pc advance, or are they all
> going to appear frequently and at different pcs?

  I think it's the latter, the DW_OP_AARCH64_paciasp and
DW_OP_AARCH64_paciasp_deref are going to appear frequently and at different pcs.
     For example, the following function prologue, there are three instructions
at 0x0, 0x4, 0x8.

   After the first instruction at 0x0, LR/X30 will be mangled.  The "paciasp" always
mangle LR register using SP as salt and write back the value into LR.  We then generate
DW_OP_AARCH64_paciasp to notify any unwinder that the original LR is mangled in this
way so they can unwind the original value properly.

   After the second instruction at 0x4, The mangled value of LR/X30 will be pushed on
to stack, unlike usual .cfi_offset, the unwind rule for LR/X30 becomes: first fetch the
mangled value from stack offset -16, then do whatever to restore the original value
from the mangled value.  This is represented by (DW_OP_AARCH64_paciasp_deref, offset).

         .cfi_startproc
    0x0  paciasp (this instruction sign return address register LR/X30)
         .cfi_val_expression 30, DW_OP_AARCH64_paciasp
    0x4  stp     x29, x30, [sp, -32]!
         .cfi_val_expression 30, DW_OP_AARCH64_paciasp_deref, -16
         .cfi_offset 29, -32
         .cfi_def_cfa_offset 32
    0x8  add     x29, sp, 0


>   Perhaps if there is just 1
> opcode and has all the info encoded just in one bigger uleb128 or something
> similar...
>
> 	Jakub

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-15 16:48         ` Jiong Wang
@ 2016-11-15 19:25           ` Richard Earnshaw (lists)
  2016-11-16 10:00             ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2016-11-15 19:25 UTC (permalink / raw)
  To: Jiong Wang, Jakub Jelinek, mjw; +Cc: gcc-patches, gdb-patches, Binutils

On 15/11/16 16:48, Jiong Wang wrote:
> 
> 
> On 15/11/16 16:18, Jakub Jelinek wrote:
>> On Tue, Nov 15, 2016 at 04:00:40PM +0000, Jiong Wang wrote:
>>>>>    Takes one signed LEB128 offset and retrieves 8-byte contents
>>>>> from the address
>>>>>    calculated by CFA plus this offset, the contents then
>>>>> authenticated as per A
>>>>>    key for instruction pointer using current CFA as salt. The
>>>>> result is pushed
>>>>>    onto the stack.
>>>> I'd like to point out that especially the vendor range of DW_OP_* is
>>>> extremely scarce resource, we have only a couple of unused values,
>>>> so taking
>>>> 3 out of the remaining unused 12 for a single architecture is IMHO
>>>> too much.
>>>> Can't you use just a single opcode and encode which of the 3
>>>> operations it is
>>>> in say the low 2 bits of a LEB 128 operand?
>>>> We'll likely need to do RSN some multiplexing even for the generic GNU
>>>> opcodes if we need just a few further ones (say 0xff as an extension,
>>>> followed by uleb128 containing the opcode - 0xff).
>>>> In the non-vendor area we still have 54 values left, so there is
>>>> more space
>>>> for future expansion.
>>>    Seperate DWARF operations are introduced instead of combining all
>>> of them into
>>> one are mostly because these operations are going to be used for most
>>> of the
>>> functions once return address signing are enabled, and they are used for
>>> describing frame unwinding that they will go into unwind table for
>>> C++ program
>>> or C program compiled with -fexceptions, the impact on unwind table
>>> size is
>>> significant.  So I was trying to lower the unwind table size overhead
>>> as much as
>>> I can.
>>>
>>>    IMHO, three numbers actually is not that much for one architecture
>>> in DWARF
>>> operation vendor extension space as vendors can overlap with each
>>> other.  The
>>> only painful thing from my understand is there are platform vendors,
>>> for example
>>> "GNU" and "LLVM" etc, for which architecture vendor can't overlap with.
>> For DW_OP_*, there aren't two vendor ranges like e.g. in ELF, there is
>> just
>> one range, so ideally the opcodes would be unique everywhere, if not,
>> there
>> is just a single GNU vendor, there is no separate range for Aarch64, that
>> can overlap with range for x86_64, and powerpc, etc.
>>
>> Perhaps we could declare that certain opcode subrange for the GNU
>> vendor is
>> architecture specific and document that the meaning of opcodes in that
>> range
>> and count/encoding of their arguments depends on the architecture, but
>> then
>> we should document how to figure out the architecture too (e.g. for ELF
>> base it on the containing EM_*).  All the tools that look at DWARF
>> (readelf,
>> objdump, eu-readelf, libdw, libunwind, gdb, dwz, ...) would need to
>> agree on that
>> though.
>>
>> I know nothing about the aarch64 return address signing, would all 3
>> or say
>> 2 usually appear together without any separate pc advance, or are they
>> all
>> going to appear frequently and at different pcs?
> 
>   I think it's the latter, the DW_OP_AARCH64_paciasp and
> DW_OP_AARCH64_paciasp_deref are going to appear frequently and at
> different pcs.
>     For example, the following function prologue, there are three
> instructions
> at 0x0, 0x4, 0x8.
> 
>   After the first instruction at 0x0, LR/X30 will be mangled.  The
> "paciasp" always
> mangle LR register using SP as salt and write back the value into LR. 
> We then generate
> DW_OP_AARCH64_paciasp to notify any unwinder that the original LR is
> mangled in this
> way so they can unwind the original value properly.
> 
>   After the second instruction at 0x4, The mangled value of LR/X30 will
> be pushed on
> to stack, unlike usual .cfi_offset, the unwind rule for LR/X30 becomes:
> first fetch the
> mangled value from stack offset -16, then do whatever to restore the
> original value
> from the mangled value.  This is represented by
> (DW_OP_AARCH64_paciasp_deref, offset).
> 
>         .cfi_startproc
>    0x0  paciasp (this instruction sign return address register LR/X30)
>         .cfi_val_expression 30, DW_OP_AARCH64_paciasp
>    0x4  stp     x29, x30, [sp, -32]!
>         .cfi_val_expression 30, DW_OP_AARCH64_paciasp_deref, -16
>         .cfi_offset 29, -32
>         .cfi_def_cfa_offset 32
>    0x8  add     x29, sp, 0
> 

Now I'm confused.

I was thinking that we needed one opcode for the sign operation in the
prologue and one for the unsign/validate operation in the epilogue (to
support non-call exceptions.  But why do we need a separate code to say
that a previously signed value has now been pushed on the stack?  Surely
that's just a normal store operation that can be tracked through the
unwinding state machine.

I was expecting the third opcode to be needed for the special operations
that are not frequently used by the compiler.

R.

>> Perhaps if there is just 1
>> opcode and has all the info encoded just in one bigger uleb128 or
>> something
>> similar...
> 

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-15 19:25           ` Richard Earnshaw (lists)
@ 2016-11-16 10:00             ` Jiong Wang
  2016-11-16 13:55               ` Mark Wielaard
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2016-11-16 10:00 UTC (permalink / raw)
  To: Richard Earnshaw (lists), Jakub Jelinek, mjw
  Cc: gcc-patches, gdb-patches, Binutils

On 15/11/16 19:25, Richard Earnshaw (lists) wrote:
> On 15/11/16 16:48, Jiong Wang wrote:
>> On 15/11/16 16:18, Jakub Jelinek wrote:
>>> I know nothing about the aarch64 return address signing, would all 3
>>> or say
>>> 2 usually appear together without any separate pc advance, or are they
>>> all
>>> going to appear frequently and at different pcs?
>>
>>   I think it's the latter, the DW_OP_AARCH64_paciasp and
>> DW_OP_AARCH64_paciasp_deref are going to appear frequently and at
>> different pcs.
>>     For example, the following function prologue, there are three
>> instructions
>> at 0x0, 0x4, 0x8.
>>
>>   After the first instruction at 0x0, LR/X30 will be mangled.  The
>> "paciasp" always
>> mangle LR register using SP as salt and write back the value into LR.
>> We then generate
>> DW_OP_AARCH64_paciasp to notify any unwinder that the original LR is
>> mangled in this
>> way so they can unwind the original value properly.
>>
>>   After the second instruction at 0x4, The mangled value of LR/X30 will
>> be pushed on
>> to stack, unlike usual .cfi_offset, the unwind rule for LR/X30 becomes:
>> first fetch the
>> mangled value from stack offset -16, then do whatever to restore the
>> original value
>> from the mangled value.  This is represented by
>> (DW_OP_AARCH64_paciasp_deref, offset).
>>
>>         .cfi_startproc
>>    0x0  paciasp (this instruction sign return address register LR/X30)
>>         .cfi_val_expression 30, DW_OP_AARCH64_paciasp
>>    0x4  stp     x29, x30, [sp, -32]!
>>         .cfi_val_expression 30, DW_OP_AARCH64_paciasp_deref, -16
>>         .cfi_offset 29, -32
>>         .cfi_def_cfa_offset 32
>>    0x8  add     x29, sp, 0
>>
>
> Now I'm confused.
>
> I was thinking that we needed one opcode for the sign operation in the
> prologue and one for the unsign/validate operation in the epilogue (to
> support non-call exceptions.

   IMO, non-call exceptions is fine, it looks to me doesn't need extra
description as for non-call exceptions (exceptions thrown from signal
handler) the key point is how to unwind across signal frame.  For libgcc EH
unwinder, when normal unwinding failed, it will fall back to architecture
unwinding hook which restore some information from signal frame which is just
on top of the signal handler's frame.

   I can see AArch64 implementation will setup return address column like the
following logic where "sc->pc" is initialized by kernel and it's not signed
therefore should sucess on further unwinding.

     fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].how =
       REG_SAVED_VAL_OFFSET;
     fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].loc.offset =
       (_Unwind_Ptr) (sc->pc) - new_cfa;

> But why do we need a separate code to say
> that a previously signed value has now been pushed on the stack?  Surely
> that's just a normal store operation that can be tracked through the
> unwinding state machine.

   I was thinking the same thing, but found it doesn't work.  My understanding
of frame unwinding described at DWARF specification is: there are two steps
for frame unwinding.  The first step is to calculate register restore rules.
Unwinder scans register rules from function start to the unwinding PC, one
rule will be *overridden* by the next for the same register, there is *no
inheritance*.  The second step is then to evaluate all the final rules
collected at the unwinding PC.  According to the rule, either fetch the value
from stack or evaluate the value on DWARF expression stack etc.

  I also had tried to modify ".cfi_val_expression" at offset 0x4 in above
example into ".cfi_offset 30, -24", libgcc EH unwinder just doesn't work.

>
> I was expecting the third opcode to be needed for the special operations
> that are not frequently used by the compiler.

  The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
designed as shortcut operations when LR is signed with A key and using
function's CFA as salt.  This is the default behaviour of return address
signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
is designed as a generic operation that allow describing pointer signing on
any value using any salt and key in case we can't use the shortcut operations
we can use this.

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-16 10:00             ` Jiong Wang
@ 2016-11-16 13:55               ` Mark Wielaard
  2016-11-16 14:02                 ` Jakub Jelinek
  0 siblings, 1 reply; 75+ messages in thread
From: Mark Wielaard @ 2016-11-16 13:55 UTC (permalink / raw)
  To: Jiong Wang
  Cc: Richard Earnshaw (lists),
	Jakub Jelinek, gcc-patches, gdb-patches, Binutils

On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
>   The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
> designed as shortcut operations when LR is signed with A key and using
> function's CFA as salt.  This is the default behaviour of return address
> signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
> is designed as a generic operation that allow describing pointer signing on
> any value using any salt and key in case we can't use the shortcut operations
> we can use this.

I admit to not fully understand the salting/keying involved. But given
that the DW_OP space is really tiny, so we would like to not eat up too
many of them for new opcodes. And given that introducing any new DW_OPs
using for CFI unwinding will break any unwinder anyway causing us to
update them all for this new feature. Have you thought about using a new
CIE augmentation string character for describing that the return
address/link register used by a function/frame is salted/keyed?

This seems a good description of CIE records and augmentation
characters: http://www.airs.com/blog/archives/460

It obviously also involves updating all unwinders to understand the new
augmentation character (and possible arguments). But it might be more
generic and saves us from using up too many DW_OPs.

Cheers,

Mark

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-16 13:55               ` Mark Wielaard
@ 2016-11-16 14:02                 ` Jakub Jelinek
  2016-11-30 11:15                   ` Jiong Wang
  2016-11-30 21:44                   ` Cary Coutant
  0 siblings, 2 replies; 75+ messages in thread
From: Jakub Jelinek @ 2016-11-16 14:02 UTC (permalink / raw)
  To: Mark Wielaard
  Cc: Jiong Wang, Richard Earnshaw (lists), gcc-patches, gdb-patches, Binutils

On Wed, Nov 16, 2016 at 02:54:56PM +0100, Mark Wielaard wrote:
> On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
> >   The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
> > designed as shortcut operations when LR is signed with A key and using
> > function's CFA as salt.  This is the default behaviour of return address
> > signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
> > is designed as a generic operation that allow describing pointer signing on
> > any value using any salt and key in case we can't use the shortcut operations
> > we can use this.
> 
> I admit to not fully understand the salting/keying involved. But given
> that the DW_OP space is really tiny, so we would like to not eat up too
> many of them for new opcodes. And given that introducing any new DW_OPs
> using for CFI unwinding will break any unwinder anyway causing us to
> update them all for this new feature. Have you thought about using a new
> CIE augmentation string character for describing that the return
> address/link register used by a function/frame is salted/keyed?
> 
> This seems a good description of CIE records and augmentation
> characters: http://www.airs.com/blog/archives/460
> 
> It obviously also involves updating all unwinders to understand the new
> augmentation character (and possible arguments). But it might be more
> generic and saves us from using up too many DW_OPs.

From what I understood, the return address is not always scrambled, so
it doesn't apply to the whole function, just to most of it (except for
an insn in the prologue and some in the epilogue).  So I think one op is
needed.  But can't it be just a toggable flag whether the return address
is scrambled + some arguments to it?
Thus DW_OP_AARCH64_scramble .uleb128 0 would mean that the default
way of scrambling starts here (if not already active) or any kind of
scrambling ends here (if already active), and
DW_OP_AARCH64_scramble .uleb128 non-zero would be whatever encoding you need
to represent details of the less common variants with details what to do.
Then you'd just hook through some MD_* macro in the unwinder the
descrambling operation if the scrambling is active at the insns you unwind
on.

	Jakub

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

* Re: [2/9] Encoding support for AArch64 DWARF operations
  2016-11-11 18:33   ` [2/9] Encoding support for AArch64 DWARF operations Jiong Wang
@ 2016-11-16 17:51     ` Jason Merrill
  2016-11-16 20:39       ` Jason Merrill
  0 siblings, 1 reply; 75+ messages in thread
From: Jason Merrill @ 2016-11-16 17:51 UTC (permalink / raw)
  To: Jiong Wang; +Cc: gcc-patches, Richard Earnshaw (lists)

On Fri, Nov 11, 2016 at 1:33 PM, Jiong Wang <jiong.wang@foss.arm.com> wrote:
> The encoding for new added AARCH64 DWARF operations.

This patch seems rather incomplete; I only see a change to
dwarf2out.c, which won't compile since the opcodes aren't defined
anywhere.

Jason

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

* Re: [2/9] Encoding support for AArch64 DWARF operations
  2016-11-16 17:51     ` Jason Merrill
@ 2016-11-16 20:39       ` Jason Merrill
  0 siblings, 0 replies; 75+ messages in thread
From: Jason Merrill @ 2016-11-16 20:39 UTC (permalink / raw)
  To: Jiong Wang; +Cc: gcc-patches, Richard Earnshaw (lists)

On Wed, Nov 16, 2016 at 12:50 PM, Jason Merrill <jason@redhat.com> wrote:
> On Fri, Nov 11, 2016 at 1:33 PM, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>> The encoding for new added AARCH64 DWARF operations.
>
> This patch seems rather incomplete; I only see a change to
> dwarf2out.c, which won't compile since the opcodes aren't defined
> anywhere.

Sorry, now I see the rest of the patchset.

Jason

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-16 14:02                 ` Jakub Jelinek
@ 2016-11-30 11:15                   ` Jiong Wang
  2016-11-30 18:25                     ` Yao Qi
                                       ` (2 more replies)
  2016-11-30 21:44                   ` Cary Coutant
  1 sibling, 3 replies; 75+ messages in thread
From: Jiong Wang @ 2016-11-30 11:15 UTC (permalink / raw)
  To: Jakub Jelinek, Mark Wielaard
  Cc: Richard Earnshaw (lists), gcc-patches, gdb-patches, Binutils

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

On 16/11/16 14:02, Jakub Jelinek wrote:
> On Wed, Nov 16, 2016 at 02:54:56PM +0100, Mark Wielaard wrote:
>> On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
>>>   The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
>>> designed as shortcut operations when LR is signed with A key and using
>>> function's CFA as salt.  This is the default behaviour of return address
>>> signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
>>> is designed as a generic operation that allow describing pointer signing on
>>> any value using any salt and key in case we can't use the shortcut operations
>>> we can use this.
>>
>> I admit to not fully understand the salting/keying involved. But given
>> that the DW_OP space is really tiny, so we would like to not eat up too
>> many of them for new opcodes. And given that introducing any new DW_OPs
>> using for CFI unwinding will break any unwinder anyway causing us to
>> update them all for this new feature. Have you thought about using a new
>> CIE augmentation string character for describing that the return
>> address/link register used by a function/frame is salted/keyed?
>>
>> This seems a good description of CIE records and augmentation
>> characters:http://www.airs.com/blog/archives/460
>>
>> It obviously also involves updating all unwinders to understand the new
>> augmentation character (and possible arguments). But it might be more
>> generic and saves us from using up too many DW_OPs.
>
> From what I understood, the return address is not always scrambled, so
> it doesn't apply to the whole function, just to most of it (except for
> an insn in the prologue and some in the epilogue).  So I think one op is
> needed.  But can't it be just a toggable flag whether the return address
> is scrambled + some arguments to it?
> Thus DW_OP_AARCH64_scramble .uleb128 0 would mean that the default
> way of scrambling starts here (if not already active) or any kind of
> scrambling ends here (if already active), and
> DW_OP_AARCH64_scramble .uleb128 non-zero would be whatever encoding you need
> to represent details of the less common variants with details what to do.
> Then you'd just hook through some MD_* macro in the unwinder the
> descrambling operation if the scrambling is active at the insns you unwind
> on.
>
>       Jakub

Hi Mark, Jakub:

   Thanks very much for the suggestions.

   I have done some experiments on your ideas and am thinking it's good to
   combine them together.  The use of DW_CFA instead of DW_OP can avoid building
   all information from scratch at each unwind location, while we can indicate
   the signing key index through new AArch64 CIE augmentation 'B'. This new
   approach reduce the unwind table size overhead from ~25% to ~5% when return
   address signing enabled, it also largely simplified dwarf generation code for
   return address signing.

   As one new DWARF call frame instruction is needed for AArch64, I want to reuse
   DW_CFA_GNU_window_save to save the space.  It is in vendor extension space and
   used for Sparc only, I think it make sense to reuse it for AArch64. On
   AArch64, DW_CFA_GNU_window_save toggle return address sign status which kept
   in a new boolean type column in DWARF table,  so DW_CFA_GNU_window_save takes
   no argument on AArch64, the same as on Sparc, this makes no difference to those
   existed encoding, length calculation code.

   Meanwhile one new DWARF expression operation number is still needed for
   AArch64, it's useful for describing those complex pointer signing scenarios
   and it will be used to multiplex some further extensions on AArch64.

   OK on this proposal and to install this patch to gcc trunk?

Hi GDB, Binutils maintainer:

   OK on this proposal and install this patch to binutils-gdb master?

include/
2016-11-29   Richard Earnshaw  <rearnsha@arm.com>
              Jiong Wang  <jiong.wang@arm.com>

         * dwarf2.def (DW_OP_AARCH64_operation): Reserve the number 0xea.



[-- Attachment #2: dw.patch --]
[-- Type: text/x-diff, Size: 1119 bytes --]

diff --git a/include/dwarf2.def b/include/dwarf2.def
index bb916ca238221151cf49359c25fd92643c7e60af..f3892a20da1fe13ddb419e5d7eda07f2c8d8b0c6 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -684,6 +684,12 @@ DW_OP (DW_OP_HP_unmod_range, 0xe5)
 DW_OP (DW_OP_HP_tls, 0xe6)
 /* PGI (STMicroelectronics) extensions.  */
 DW_OP (DW_OP_PGI_omp_thread_num, 0xf8)
+/* AARCH64 extensions.
+   DW_OP_AARCH64_operation takes one mandatory unsigned LEB128 operand.
+   Bits[6:0] of this operand is the action code, all others bits are initialized
+   to 0 except explicitly documented for one action.  Please refer AArch64 DWARF
+   ABI documentation for details.  */
+DW_OP (DW_OP_AARCH64_operation, 0xea)
 DW_END_OP
 
 DW_FIRST_ATE (DW_ATE_void, 0x0)
@@ -765,7 +771,8 @@ DW_CFA (DW_CFA_hi_user, 0x3f)
 
 /* SGI/MIPS specific.  */
 DW_CFA (DW_CFA_MIPS_advance_loc8, 0x1d)
-/* GNU extensions.  */
+/* GNU extensions.
+   NOTE: DW_CFA_GNU_window_save is multiplexed on Sparc and AArch64.  */
 DW_CFA (DW_CFA_GNU_window_save, 0x2d)
 DW_CFA (DW_CFA_GNU_args_size, 0x2e)
 DW_CFA (DW_CFA_GNU_negative_offset_extended, 0x2f)

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-30 11:15                   ` Jiong Wang
@ 2016-11-30 18:25                     ` Yao Qi
  2016-12-12 13:40                     ` [Ping~][1/9][RFC][DWARF] " Jiong Wang
  2016-12-28 21:14                     ` [1/9][RFC][DWARF] " Cary Coutant
  2 siblings, 0 replies; 75+ messages in thread
From: Yao Qi @ 2016-11-30 18:25 UTC (permalink / raw)
  To: Jiong Wang
  Cc: Jakub Jelinek, Mark Wielaard, Richard Earnshaw (lists),
	gcc-patches, gdb-patches, Binutils

On Wed, Nov 30, 2016 at 11:15:22AM +0000, Jiong Wang wrote:
> 
> Hi GDB, Binutils maintainer:
> 
>   OK on this proposal and install this patch to binutils-gdb master?
>

This proposal is good to GDB, as long as you add a gdbarch hook and move
the code handling DW_CFA_GNU_window_save in
gdb/dwarf2-frame.c:execute_cfa_program to sparc-tdep.c or/and
sparc64-tdep.c.

-- 
Yao (齐尧)

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-16 14:02                 ` Jakub Jelinek
  2016-11-30 11:15                   ` Jiong Wang
@ 2016-11-30 21:44                   ` Cary Coutant
  2016-12-01 10:42                     ` Richard Earnshaw (lists)
  1 sibling, 1 reply; 75+ messages in thread
From: Cary Coutant @ 2016-11-30 21:44 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Mark Wielaard, Jiong Wang, Richard Earnshaw (lists),
	gcc-patches, GDB, Binutils

How about if instead of special DW_OP codes, you instead define a new
virtual register that contains the mangled return address? If the rule
for that virtual register is anything other than DW_CFA_undefined,
you'd expect to find the mangled return address using that rule;
otherwise, you would use the rule for LR instead and expect an
unmangled return address. The earlier example would become (picking an
arbitrary value of 120 for the new virtual register number):

        .cfi_startproc
   0x0  paciasp (this instruction sign return address register LR/X30)
        .cfi_val 120, DW_OP_reg30
   0x4  stp     x29, x30, [sp, -32]!
        .cfi_offset 120, -16
        .cfi_offset 29, -32
        .cfi_def_cfa_offset 32
   0x8  add     x29, sp, 0

Just a suggestion...

-cary


On Wed, Nov 16, 2016 at 6:02 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Nov 16, 2016 at 02:54:56PM +0100, Mark Wielaard wrote:
>> On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
>> >   The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
>> > designed as shortcut operations when LR is signed with A key and using
>> > function's CFA as salt.  This is the default behaviour of return address
>> > signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
>> > is designed as a generic operation that allow describing pointer signing on
>> > any value using any salt and key in case we can't use the shortcut operations
>> > we can use this.
>>
>> I admit to not fully understand the salting/keying involved. But given
>> that the DW_OP space is really tiny, so we would like to not eat up too
>> many of them for new opcodes. And given that introducing any new DW_OPs
>> using for CFI unwinding will break any unwinder anyway causing us to
>> update them all for this new feature. Have you thought about using a new
>> CIE augmentation string character for describing that the return
>> address/link register used by a function/frame is salted/keyed?
>>
>> This seems a good description of CIE records and augmentation
>> characters: http://www.airs.com/blog/archives/460
>>
>> It obviously also involves updating all unwinders to understand the new
>> augmentation character (and possible arguments). But it might be more
>> generic and saves us from using up too many DW_OPs.
>
> From what I understood, the return address is not always scrambled, so
> it doesn't apply to the whole function, just to most of it (except for
> an insn in the prologue and some in the epilogue).  So I think one op is
> needed.  But can't it be just a toggable flag whether the return address
> is scrambled + some arguments to it?
> Thus DW_OP_AARCH64_scramble .uleb128 0 would mean that the default
> way of scrambling starts here (if not already active) or any kind of
> scrambling ends here (if already active), and
> DW_OP_AARCH64_scramble .uleb128 non-zero would be whatever encoding you need
> to represent details of the less common variants with details what to do.
> Then you'd just hook through some MD_* macro in the unwinder the
> descrambling operation if the scrambling is active at the insns you unwind
> on.
>
>         Jakub

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-30 21:44                   ` Cary Coutant
@ 2016-12-01 10:42                     ` Richard Earnshaw (lists)
  2016-12-01 11:09                       ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2016-12-01 10:42 UTC (permalink / raw)
  To: Cary Coutant, Jakub Jelinek
  Cc: Mark Wielaard, Jiong Wang, gcc-patches, GDB, Binutils

On 30/11/16 21:43, Cary Coutant wrote:
> How about if instead of special DW_OP codes, you instead define a new
> virtual register that contains the mangled return address? If the rule
> for that virtual register is anything other than DW_CFA_undefined,
> you'd expect to find the mangled return address using that rule;
> otherwise, you would use the rule for LR instead and expect an
> unmangled return address. The earlier example would become (picking an
> arbitrary value of 120 for the new virtual register number):
> 
>         .cfi_startproc
>    0x0  paciasp (this instruction sign return address register LR/X30)
>         .cfi_val 120, DW_OP_reg30
>    0x4  stp     x29, x30, [sp, -32]!
>         .cfi_offset 120, -16
>         .cfi_offset 29, -32
>         .cfi_def_cfa_offset 32
>    0x8  add     x29, sp, 0
> 
> Just a suggestion...

What about signing other registers?  And what if the value is then
copied to another register?  Don't you end up with every possible
register (including the FP/SIMD registers) needing a shadow copy?

R.

> 
> -cary
> 
> 
> On Wed, Nov 16, 2016 at 6:02 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Wed, Nov 16, 2016 at 02:54:56PM +0100, Mark Wielaard wrote:
>>> On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
>>>>   The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
>>>> designed as shortcut operations when LR is signed with A key and using
>>>> function's CFA as salt.  This is the default behaviour of return address
>>>> signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
>>>> is designed as a generic operation that allow describing pointer signing on
>>>> any value using any salt and key in case we can't use the shortcut operations
>>>> we can use this.
>>>
>>> I admit to not fully understand the salting/keying involved. But given
>>> that the DW_OP space is really tiny, so we would like to not eat up too
>>> many of them for new opcodes. And given that introducing any new DW_OPs
>>> using for CFI unwinding will break any unwinder anyway causing us to
>>> update them all for this new feature. Have you thought about using a new
>>> CIE augmentation string character for describing that the return
>>> address/link register used by a function/frame is salted/keyed?
>>>
>>> This seems a good description of CIE records and augmentation
>>> characters: http://www.airs.com/blog/archives/460
>>>
>>> It obviously also involves updating all unwinders to understand the new
>>> augmentation character (and possible arguments). But it might be more
>>> generic and saves us from using up too many DW_OPs.
>>
>> From what I understood, the return address is not always scrambled, so
>> it doesn't apply to the whole function, just to most of it (except for
>> an insn in the prologue and some in the epilogue).  So I think one op is
>> needed.  But can't it be just a toggable flag whether the return address
>> is scrambled + some arguments to it?
>> Thus DW_OP_AARCH64_scramble .uleb128 0 would mean that the default
>> way of scrambling starts here (if not already active) or any kind of
>> scrambling ends here (if already active), and
>> DW_OP_AARCH64_scramble .uleb128 non-zero would be whatever encoding you need
>> to represent details of the less common variants with details what to do.
>> Then you'd just hook through some MD_* macro in the unwinder the
>> descrambling operation if the scrambling is active at the insns you unwind
>> on.
>>
>>         Jakub

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-12-01 10:42                     ` Richard Earnshaw (lists)
@ 2016-12-01 11:09                       ` Jiong Wang
  0 siblings, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-12-01 11:09 UTC (permalink / raw)
  To: Richard Earnshaw (lists), Cary Coutant, Jakub Jelinek
  Cc: Mark Wielaard, gcc-patches, GDB, Binutils

On 01/12/16 10:42, Richard Earnshaw (lists) wrote:
> On 30/11/16 21:43, Cary Coutant wrote:
>> How about if instead of special DW_OP codes, you instead define a new
>> virtual register that contains the mangled return address? If the rule
>> for that virtual register is anything other than DW_CFA_undefined,
>> you'd expect to find the mangled return address using that rule;
>> otherwise, you would use the rule for LR instead and expect an
>> unmangled return address. The earlier example would become (picking an
>> arbitrary value of 120 for the new virtual register number):
>>
>>          .cfi_startproc
>>     0x0  paciasp (this instruction sign return address register LR/X30)
>>          .cfi_val 120, DW_OP_reg30
>>     0x4  stp     x29, x30, [sp, -32]!
>>          .cfi_offset 120, -16
>>          .cfi_offset 29, -32
>>          .cfi_def_cfa_offset 32
>>     0x8  add     x29, sp, 0
>>
>> Just a suggestion...
> What about signing other registers?  And what if the value is then
> copied to another register?  Don't you end up with every possible
> register (including the FP/SIMD registers) needing a shadow copy?

   
   Another issue is compared with the DW_CFA approach, this virtual register
   approach is less efficient on unwind table size and complexer to implement.

   .cfi_register takes two ULEB128 register number, it needs 3 bytes rather
    than DW_CFA's 1 byte.  From example .debug_frame section size for linux
    kernel increment will be ~14% compared with DW_CFA approach's 5%.

   In the implementation, the prologue then normally will be

          .cfi_startproc
     0x0  paciasp (this instruction sign return address register LR/X30)
          .cfi_val 120, DW_OP_reg30  <-A
     0x4  stp     x29, x30, [sp, -32]!
          .cfi_offset 120, -16       <-B
          .cfi_offset 29, -32
          .cfi_def_cfa_offset 32

     The epilogue normally will be
     ...
         ldp     x29, x30, [sp], 32
           .cfi_val 120, DW_OP_reg30  <- C
           .cfi_restore 29
           .cfi_def_cfa 31, 0

         autiasp (this instruction unsign LR/X30)
           .cfi_restore 30

    For the virual register approach, GCC needs to track dwarf generation for
    LR/X30 in every place (A/B/C, maybe some other rare LR copy places), and
    rewrite LR to new virtual register accordingly. This seems easy, but my
    practice shows GCC won't do any DWARF auto-deduction if you have one
    explict DWARF CFI note attached to an insn (handled_one will be true in
    dwarf2out_frame_debug).  So for instruction like stp/ldp, we then need to
    explicitly generate all three DWARF CFI note manually.

    While for DW_CFA approach, they will be:

          .cfi_startproc
     0x0  paciasp (this instruction sign return address register LR/X30)
          .cfi_cfa_window_save
     0x4  stp     x29, x30, [sp, -32]!     \
          .cfi_offset 30, -16              |
          .cfi_offset 29, -32              |
          .cfi_def_cfa_offset 32           |  all dwarf generation between sign and
     ...                                   |  unsign (paciasp/autiasp) is the same
         ldp     x29, x30, [sp], 16        |  as before
           .cfi_restore 30                 |
           .cfi_restore 29                 |
           .cfi_def_cfa 31, 0              |
                                           /
         autiasp (this instruction unsign LR/X30)
           .cfi_cfa_window_save

    The DWARF generation implementation in backend is very simple, nothing needs to be
    updated between sign and unsign instruction.

  For the impact on the unwinder, the virtual register approach needs to change
  the implementation of "save value" rule which is quite general code. A target hook
  might need for AArch64 that when the destination register is the special virtual
  register, it seems a little bit hack to me.

>> -cary
>>
>>
>> On Wed, Nov 16, 2016 at 6:02 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>>> On Wed, Nov 16, 2016 at 02:54:56PM +0100, Mark Wielaard wrote:
>>>> On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
>>>>>    The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
>>>>> designed as shortcut operations when LR is signed with A key and using
>>>>> function's CFA as salt.  This is the default behaviour of return address
>>>>> signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
>>>>> is designed as a generic operation that allow describing pointer signing on
>>>>> any value using any salt and key in case we can't use the shortcut operations
>>>>> we can use this.
>>>> I admit to not fully understand the salting/keying involved. But given
>>>> that the DW_OP space is really tiny, so we would like to not eat up too
>>>> many of them for new opcodes. And given that introducing any new DW_OPs
>>>> using for CFI unwinding will break any unwinder anyway causing us to
>>>> update them all for this new feature. Have you thought about using a new
>>>> CIE augmentation string character for describing that the return
>>>> address/link register used by a function/frame is salted/keyed?
>>>>
>>>> This seems a good description of CIE records and augmentation
>>>> characters: http://www.airs.com/blog/archives/460
>>>>
>>>> It obviously also involves updating all unwinders to understand the new
>>>> augmentation character (and possible arguments). But it might be more
>>>> generic and saves us from using up too many DW_OPs.
>>>  From what I understood, the return address is not always scrambled, so
>>> it doesn't apply to the whole function, just to most of it (except for
>>> an insn in the prologue and some in the epilogue).  So I think one op is
>>> needed.  But can't it be just a toggable flag whether the return address
>>> is scrambled + some arguments to it?
>>> Thus DW_OP_AARCH64_scramble .uleb128 0 would mean that the default
>>> way of scrambling starts here (if not already active) or any kind of
>>> scrambling ends here (if already active), and
>>> DW_OP_AARCH64_scramble .uleb128 non-zero would be whatever encoding you need
>>> to represent details of the less common variants with details what to do.
>>> Then you'd just hook through some MD_* macro in the unwinder the
>>> descrambling operation if the scrambling is active at the insns you unwind
>>> on.
>>>
>>>          Jakub

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

* Re: [Ping~][1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-30 11:15                   ` Jiong Wang
  2016-11-30 18:25                     ` Yao Qi
@ 2016-12-12 13:40                     ` Jiong Wang
  2016-12-19 14:07                       ` [Ping^2][1/9][RFC][DWARF] " Jiong Wang
  2016-12-28 21:14                     ` [1/9][RFC][DWARF] " Cary Coutant
  2 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2016-12-12 13:40 UTC (permalink / raw)
  To: Jakub Jelinek, Mark Wielaard
  Cc: Richard Earnshaw (lists), gcc-patches, gdb-patches, Binutils


Jiong Wang writes:

> On 16/11/16 14:02, Jakub Jelinek wrote:
>> On Wed, Nov 16, 2016 at 02:54:56PM +0100, Mark Wielaard wrote:
>>> On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
>>>>   The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
>>>> designed as shortcut operations when LR is signed with A key and using
>>>> function's CFA as salt.  This is the default behaviour of return address
>>>> signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
>>>> is designed as a generic operation that allow describing pointer signing on
>>>> any value using any salt and key in case we can't use the shortcut operations
>>>> we can use this.
>>>
>>> I admit to not fully understand the salting/keying involved. But given
>>> that the DW_OP space is really tiny, so we would like to not eat up too
>>> many of them for new opcodes. And given that introducing any new DW_OPs
>>> using for CFI unwinding will break any unwinder anyway causing us to
>>> update them all for this new feature. Have you thought about using a new
>>> CIE augmentation string character for describing that the return
>>> address/link register used by a function/frame is salted/keyed?
>>>
>>> This seems a good description of CIE records and augmentation
>>> characters:http://www.airs.com/blog/archives/460
>>>
>>> It obviously also involves updating all unwinders to understand the new
>>> augmentation character (and possible arguments). But it might be more
>>> generic and saves us from using up too many DW_OPs.
>>
>> From what I understood, the return address is not always scrambled, so
>> it doesn't apply to the whole function, just to most of it (except for
>> an insn in the prologue and some in the epilogue).  So I think one op is
>> needed.  But can't it be just a toggable flag whether the return address
>> is scrambled + some arguments to it?
>> Thus DW_OP_AARCH64_scramble .uleb128 0 would mean that the default
>> way of scrambling starts here (if not already active) or any kind of
>> scrambling ends here (if already active), and
>> DW_OP_AARCH64_scramble .uleb128 non-zero would be whatever encoding you need
>> to represent details of the less common variants with details what to do.
>> Then you'd just hook through some MD_* macro in the unwinder the
>> descrambling operation if the scrambling is active at the insns you unwind
>> on.
>>
>>       Jakub
>
> Hi Mark, Jakub:
>
>    Thanks very much for the suggestions.
>
>    I have done some experiments on your ideas and am thinking it's good to
>    combine them together.  The use of DW_CFA instead of DW_OP can avoid building
>    all information from scratch at each unwind location, while we can indicate
>    the signing key index through new AArch64 CIE augmentation 'B'. This new
>    approach reduce the unwind table size overhead from ~25% to ~5% when return
>    address signing enabled, it also largely simplified dwarf generation code for
>    return address signing.
>
>    As one new DWARF call frame instruction is needed for AArch64, I want to reuse
>    DW_CFA_GNU_window_save to save the space.  It is in vendor extension space and
>    used for Sparc only, I think it make sense to reuse it for AArch64. On
>    AArch64, DW_CFA_GNU_window_save toggle return address sign status which kept
>    in a new boolean type column in DWARF table,  so DW_CFA_GNU_window_save takes
>    no argument on AArch64, the same as on Sparc, this makes no difference to those
>    existed encoding, length calculation code.
>
>    Meanwhile one new DWARF expression operation number is still needed for
>    AArch64, it's useful for describing those complex pointer signing scenarios
>    and it will be used to multiplex some further extensions on AArch64.
>
>    OK on this proposal and to install this patch to gcc trunk?
>
> Hi GDB, Binutils maintainer:
>
>    OK on this proposal and install this patch to binutils-gdb master?
>
> include/
> 2016-11-29   Richard Earnshaw  <rearnsha@arm.com>
>               Jiong Wang  <jiong.wang@arm.com>
>
>          * dwarf2.def (DW_OP_AARCH64_operation): Reserve the number 0xea.

Ping~

Thanks.

-- 
Regards,
Jiong

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

* [Ping^2][1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-12-12 13:40                     ` [Ping~][1/9][RFC][DWARF] " Jiong Wang
@ 2016-12-19 14:07                       ` Jiong Wang
  2016-12-28 18:25                         ` [Ping^3][1/9][RFC][DWARF] " Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2016-12-19 14:07 UTC (permalink / raw)
  To: Jakub Jelinek, Mark Wielaard
  Cc: Richard Earnshaw (lists),
	gcc-patches, gdb-patches, Binutils, Jason Merrill, ccoutant


Jiong Wang writes:

> Jiong Wang writes:
>
>> On 16/11/16 14:02, Jakub Jelinek wrote:
>>> On Wed, Nov 16, 2016 at 02:54:56PM +0100, Mark Wielaard wrote:
>>>> On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
>>>>>   The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
>>>>> designed as shortcut operations when LR is signed with A key and using
>>>>> function's CFA as salt.  This is the default behaviour of return address
>>>>> signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
>>>>> is designed as a generic operation that allow describing pointer signing on
>>>>> any value using any salt and key in case we can't use the shortcut operations
>>>>> we can use this.
>>>>
>>>> I admit to not fully understand the salting/keying involved. But given
>>>> that the DW_OP space is really tiny, so we would like to not eat up too
>>>> many of them for new opcodes. And given that introducing any new DW_OPs
>>>> using for CFI unwinding will break any unwinder anyway causing us to
>>>> update them all for this new feature. Have you thought about using a new
>>>> CIE augmentation string character for describing that the return
>>>> address/link register used by a function/frame is salted/keyed?
>>>>
>>>> This seems a good description of CIE records and augmentation
>>>> characters:http://www.airs.com/blog/archives/460
>>>>
>>>> It obviously also involves updating all unwinders to understand the new
>>>> augmentation character (and possible arguments). But it might be more
>>>> generic and saves us from using up too many DW_OPs.
>>>
>>> From what I understood, the return address is not always scrambled, so
>>> it doesn't apply to the whole function, just to most of it (except for
>>> an insn in the prologue and some in the epilogue).  So I think one op is
>>> needed.  But can't it be just a toggable flag whether the return address
>>> is scrambled + some arguments to it?
>>> Thus DW_OP_AARCH64_scramble .uleb128 0 would mean that the default
>>> way of scrambling starts here (if not already active) or any kind of
>>> scrambling ends here (if already active), and
>>> DW_OP_AARCH64_scramble .uleb128 non-zero would be whatever encoding you need
>>> to represent details of the less common variants with details what to do.
>>> Then you'd just hook through some MD_* macro in the unwinder the
>>> descrambling operation if the scrambling is active at the insns you unwind
>>> on.
>>>
>>>       Jakub
>>
>> Hi Mark, Jakub:
>>
>>    Thanks very much for the suggestions.
>>
>>    I have done some experiments on your ideas and am thinking it's good to
>>    combine them together.  The use of DW_CFA instead of DW_OP can avoid building
>>    all information from scratch at each unwind location, while we can indicate
>>    the signing key index through new AArch64 CIE augmentation 'B'. This new
>>    approach reduce the unwind table size overhead from ~25% to ~5% when return
>>    address signing enabled, it also largely simplified dwarf generation code for
>>    return address signing.
>>
>>    As one new DWARF call frame instruction is needed for AArch64, I want to reuse
>>    DW_CFA_GNU_window_save to save the space.  It is in vendor extension space and
>>    used for Sparc only, I think it make sense to reuse it for AArch64. On
>>    AArch64, DW_CFA_GNU_window_save toggle return address sign status which kept
>>    in a new boolean type column in DWARF table,  so DW_CFA_GNU_window_save takes
>>    no argument on AArch64, the same as on Sparc, this makes no difference to those
>>    existed encoding, length calculation code.
>>
>>    Meanwhile one new DWARF expression operation number is still needed for
>>    AArch64, it's useful for describing those complex pointer signing scenarios
>>    and it will be used to multiplex some further extensions on AArch64.
>>
>>    OK on this proposal and to install this patch to gcc trunk?
>>
>> Hi GDB, Binutils maintainer:
>>
>>    OK on this proposal and install this patch to binutils-gdb master?
>>
>> include/
>> 2016-11-29   Richard Earnshaw  <rearnsha@arm.com>
>>               Jiong Wang  <jiong.wang@arm.com>
>>
>>          * dwarf2.def (DW_OP_AARCH64_operation): Reserve the number 0xea.
>
> Ping~

Ping^2

-- 
Regards,
Jiong

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

* [Ping^3][1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-12-19 14:07                       ` [Ping^2][1/9][RFC][DWARF] " Jiong Wang
@ 2016-12-28 18:25                         ` Jiong Wang
  0 siblings, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2016-12-28 18:25 UTC (permalink / raw)
  To: Jakub Jelinek, Mark Wielaard, law
  Cc: Richard Earnshaw (lists),
	gcc-patches, gdb-patches, Binutils, Jason Merrill, ccoutant


Jiong Wang writes:

> Jiong Wang writes:
>
>> Jiong Wang writes:
>>
>>> On 16/11/16 14:02, Jakub Jelinek wrote:
>>>> On Wed, Nov 16, 2016 at 02:54:56PM +0100, Mark Wielaard wrote:
>>>>> On Wed, 2016-11-16 at 10:00 +0000, Jiong Wang wrote:
>>>>>>   The two operations DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref were
>>>>>> designed as shortcut operations when LR is signed with A key and using
>>>>>> function's CFA as salt.  This is the default behaviour of return address
>>>>>> signing so is expected to be used for most of the time.  DW_OP_AARCH64_pauth
>>>>>> is designed as a generic operation that allow describing pointer signing on
>>>>>> any value using any salt and key in case we can't use the shortcut operations
>>>>>> we can use this.
>>>>>
>>>>> I admit to not fully understand the salting/keying involved. But given
>>>>> that the DW_OP space is really tiny, so we would like to not eat up too
>>>>> many of them for new opcodes. And given that introducing any new DW_OPs
>>>>> using for CFI unwinding will break any unwinder anyway causing us to
>>>>> update them all for this new feature. Have you thought about using a new
>>>>> CIE augmentation string character for describing that the return
>>>>> address/link register used by a function/frame is salted/keyed?
>>>>>
>>>>> This seems a good description of CIE records and augmentation
>>>>> characters:http://www.airs.com/blog/archives/460
>>>>>
>>>>> It obviously also involves updating all unwinders to understand the new
>>>>> augmentation character (and possible arguments). But it might be more
>>>>> generic and saves us from using up too many DW_OPs.
>>>>
>>>> From what I understood, the return address is not always scrambled, so
>>>> it doesn't apply to the whole function, just to most of it (except for
>>>> an insn in the prologue and some in the epilogue).  So I think one op is
>>>> needed.  But can't it be just a toggable flag whether the return address
>>>> is scrambled + some arguments to it?
>>>> Thus DW_OP_AARCH64_scramble .uleb128 0 would mean that the default
>>>> way of scrambling starts here (if not already active) or any kind of
>>>> scrambling ends here (if already active), and
>>>> DW_OP_AARCH64_scramble .uleb128 non-zero would be whatever encoding you need
>>>> to represent details of the less common variants with details what to do.
>>>> Then you'd just hook through some MD_* macro in the unwinder the
>>>> descrambling operation if the scrambling is active at the insns you unwind
>>>> on.
>>>>
>>>>       Jakub
>>>
>>> Hi Mark, Jakub:
>>>
>>>    Thanks very much for the suggestions.
>>>
>>>    I have done some experiments on your ideas and am thinking it's good to
>>>    combine them together.  The use of DW_CFA instead of DW_OP can avoid building
>>>    all information from scratch at each unwind location, while we can indicate
>>>    the signing key index through new AArch64 CIE augmentation 'B'. This new
>>>    approach reduce the unwind table size overhead from ~25% to ~5% when return
>>>    address signing enabled, it also largely simplified dwarf generation code for
>>>    return address signing.
>>>
>>>    As one new DWARF call frame instruction is needed for AArch64, I want to reuse
>>>    DW_CFA_GNU_window_save to save the space.  It is in vendor extension space and
>>>    used for Sparc only, I think it make sense to reuse it for AArch64. On
>>>    AArch64, DW_CFA_GNU_window_save toggle return address sign status which kept
>>>    in a new boolean type column in DWARF table,  so DW_CFA_GNU_window_save takes
>>>    no argument on AArch64, the same as on Sparc, this makes no difference to those
>>>    existed encoding, length calculation code.
>>>
>>>    Meanwhile one new DWARF expression operation number is still needed for
>>>    AArch64, it's useful for describing those complex pointer signing scenarios
>>>    and it will be used to multiplex some further extensions on AArch64.
>>>
>>>    OK on this proposal and to install this patch to gcc trunk?
>>>
>>> Hi GDB, Binutils maintainer:
>>>
>>>    OK on this proposal and install this patch to binutils-gdb master?
>>>
>>> include/
>>> 2016-11-29   Richard Earnshaw  <rearnsha@arm.com>
>>>               Jiong Wang  <jiong.wang@arm.com>
>>>
>>>          * dwarf2.def (DW_OP_AARCH64_operation): Reserve the number 0xea.
>>
>> Ping~
> Ping^2

Ping^3

Can DWARF maintainers or global reviewers have a look at this?

Thanks very much.

-- 
Regards,
Jiong

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-11 19:39   ` [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space Jakub Jelinek
  2016-11-15 16:00     ` Jiong Wang
@ 2016-12-28 19:54     ` Cary Coutant
  1 sibling, 0 replies; 75+ messages in thread
From: Cary Coutant @ 2016-12-28 19:54 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Jiong Wang, gcc-patches, GDB, Binutils, Richard Earnshaw (lists)

> I'd like to point out that especially the vendor range of DW_OP_* is
> extremely scarce resource, we have only a couple of unused values, so taking
> 3 out of the remaining unused 12 for a single architecture is IMHO too much.
> Can't you use just a single opcode and encode which of the 3 operations it is
> in say the low 2 bits of a LEB 128 operand?
> We'll likely need to do RSN some multiplexing even for the generic GNU
> opcodes if we need just a few further ones (say 0xff as an extension,
> followed by uleb128 containing the opcode - 0xff).
> In the non-vendor area we still have 54 values left, so there is more space
> for future expansion.

Most of the Gnu extensions have been adopted into the standard as of DWARF 5:

/* GNU extensions.  */
DW_OP (DW_OP_GNU_push_tls_address, 0xe0)
/* The following is for marking variables that are uninitialized.  */
DW_OP (DW_OP_GNU_uninit, 0xf0)
DW_OP (DW_OP_GNU_encoded_addr, 0xf1)
/* The GNU implicit pointer extension.
   See http://www.dwarfstd.org/ShowIssue.php?issue=100831.1&type=open .  */
DW_OP (DW_OP_GNU_implicit_pointer, 0xf2)
/* The GNU entry value extension.
   See http://www.dwarfstd.org/ShowIssue.php?issue=100909.1&type=open .  */
DW_OP (DW_OP_GNU_entry_value, 0xf3)
/* The GNU typed stack extension.
   See http://www.dwarfstd.org/doc/040408.1.html .  */
DW_OP (DW_OP_GNU_const_type, 0xf4)
DW_OP (DW_OP_GNU_regval_type, 0xf5)
DW_OP (DW_OP_GNU_deref_type, 0xf6)
DW_OP (DW_OP_GNU_convert, 0xf7)
DW_OP (DW_OP_GNU_reinterpret, 0xf9)
/* The GNU parameter ref extension.  */
DW_OP (DW_OP_GNU_parameter_ref, 0xfa)
/* Extensions for Fission.  See http://gcc.gnu.org/wiki/DebugFission.  */
DW_OP (DW_OP_GNU_addr_index, 0xfb)
DW_OP (DW_OP_GNU_const_index, 0xfc)

Of these, I think only DW_OP_GNU_uninit and DW_OP_GNU_encoded_addr
remain as Gnu extensions. The rest could be deprecated as of DWARF 5,
and, if necessary, reused for other purposes in DWARF 6 and later.
Depending on how aggressive we want to be with deprecation, we could
even declare that they are available for reuse in DWARF 5 and later,
as long as the Gnu toolchain uses only the new standard values when
generating DWARF 5. That frees up 11 more opcodes.

-cary

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-11-30 11:15                   ` Jiong Wang
  2016-11-30 18:25                     ` Yao Qi
  2016-12-12 13:40                     ` [Ping~][1/9][RFC][DWARF] " Jiong Wang
@ 2016-12-28 21:14                     ` Cary Coutant
  2017-01-03  9:32                       ` Jiong Wang
  2 siblings, 1 reply; 75+ messages in thread
From: Cary Coutant @ 2016-12-28 21:14 UTC (permalink / raw)
  To: Jiong Wang
  Cc: Jakub Jelinek, Mark Wielaard, Richard Earnshaw (lists),
	gcc-patches, GDB, Binutils

>   OK on this proposal and to install this patch to gcc trunk?
>
> Hi GDB, Binutils maintainer:
>
>   OK on this proposal and install this patch to binutils-gdb master?
>
> include/
> 2016-11-29   Richard Earnshaw  <rearnsha@arm.com>
>              Jiong Wang  <jiong.wang@arm.com>
>
>         * dwarf2.def (DW_OP_AARCH64_operation): Reserve the number 0xea.

This is OK, but:

+/* AARCH64 extensions.
+   DW_OP_AARCH64_operation takes one mandatory unsigned LEB128 operand.
+   Bits[6:0] of this operand is the action code, all others bits are
initialized
+   to 0 except explicitly documented for one action.  Please refer
AArch64 DWARF
+   ABI documentation for details.  */

Is it possible to include a stable URL that points to the ABI document?

-cary

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

* Re: [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space
  2016-12-28 21:14                     ` [1/9][RFC][DWARF] " Cary Coutant
@ 2017-01-03  9:32                       ` Jiong Wang
  0 siblings, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2017-01-03  9:32 UTC (permalink / raw)
  To: Cary Coutant
  Cc: Jakub Jelinek, Mark Wielaard, Richard Earnshaw (lists),
	gcc-patches, GDB, Binutils



On 28/12/16 19:54, Cary Coutant wrote:
>>    OK on this proposal and to install this patch to gcc trunk?
>>
>> Hi GDB, Binutils maintainer:
>>
>>    OK on this proposal and install this patch to binutils-gdb master?
>>
>> include/
>> 2016-11-29   Richard Earnshaw  <rearnsha@arm.com>
>>               Jiong Wang  <jiong.wang@arm.com>
>>
>>          * dwarf2.def (DW_OP_AARCH64_operation): Reserve the number 0xea.
> This is OK, but:
>
> +/* AARCH64 extensions.
> +   DW_OP_AARCH64_operation takes one mandatory unsigned LEB128 operand.
> +   Bits[6:0] of this operand is the action code, all others bits are
> initialized
> +   to 0 except explicitly documented for one action.  Please refer
> AArch64 DWARF
> +   ABI documentation for details.  */
>
> Is it possible to include a stable URL that points to the ABI document?
Hi Cary,

   Thanks for the review.

   Currently there is no URL for this AArch64 DWARF ABI updates.  I will 
update the comments as soon as the stable URL is available.

Regards,
Jiong

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

* [Ping~][AArch64] Add commandline support for -march=armv8.3-a
       [not found]     ` <f97bf031-e589-5879-17f6-60ed02468561@foss.arm.com>
@ 2017-01-06 11:33       ` Jiong Wang
  2017-01-10 17:00         ` James Greenhalgh
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-06 11:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: James Greenhalgh, Richard Earnshaw (lists)

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

On 11/11/16 18:22, Jiong Wang wrote:
> This patch add command line support for ARMv8.3-A through new architecture:
>
>    -march=armv8.3-a
>
> ARMv8.3-A implies all default features of ARMv8.2-A and meanwhile it includes
> the new pointer authentication extension.
>
>
> gcc/
> 2016-11-08  Jiong Wang<jiong.wang@arm.com>
>
>          * config/aarch64/aarch64-arches.def: New entry for "armv8.3-a".
>          * config/aarch64/aarch64.h (AARCH64_FL_PAUTH, AARCH64_FL_V8_3,
>          AARCH64_FL_FOR_ARCH8_3, AARCH64_ISA_PAUTH, AARCH64_ISA_V8_3,
>          TARGET_PAUTH, TARGET_ARMV8_3): New.
>          * doc/invoke.texi (AArch64 Options): Document "armv8.3-a".

Ping ~

As pointer authentication extension is defined to be mandatory extension on
ARMv8.3-A and is not optional, I adjusted the patch slightly.

This also let GCC treating pointer authentication extension in consistent way
with Binutils.

OK for trunk?

gcc/
2017-01-06  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-arches.def: New entry for "armv8.3-a".
         * config/aarch64/aarch64.h (AARCH64_FL_V8_3, AARCH64_FL_FOR_ARCH8_3,
         AARCH64_ISA_V8_3, TARGET_ARMV8_3): New.
         * doc/invoke.texi (AArch64 Options): Document "armv8.3-a".



[-- Attachment #2: 1.patch --]
[-- Type: text/x-diff, Size: 3329 bytes --]

diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
index 830a7cf545532c050847a8c915d21bef12152388..ce6f73b3e5853b3d40e07545b9581298c768edca 100644
--- a/gcc/config/aarch64/aarch64-arches.def
+++ b/gcc/config/aarch64/aarch64-arches.def
@@ -33,5 +33,6 @@
 AARCH64_ARCH("armv8-a",	      generic,	     8A,	8,  AARCH64_FL_FOR_ARCH8)
 AARCH64_ARCH("armv8.1-a",     generic,	     8_1A,	8,  AARCH64_FL_FOR_ARCH8_1)
 AARCH64_ARCH("armv8.2-a",     generic,	     8_2A,	8,  AARCH64_FL_FOR_ARCH8_2)
+AARCH64_ARCH("armv8.3-a",     generic,	     8_3A,	8,  AARCH64_FL_FOR_ARCH8_3)
 
 #undef AARCH64_ARCH
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 584ff5c43afcd1a7918019b09165371bb88bfda1..51916c95a736ade697a823f15d483336651ac99a 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -138,6 +138,8 @@ extern unsigned aarch64_architecture_version;
 /* ARMv8.2-A architecture extensions.  */
 #define AARCH64_FL_V8_2	      (1 << 8)  /* Has ARMv8.2-A features.  */
 #define AARCH64_FL_F16	      (1 << 9)  /* Has ARMv8.2-A FP16 extensions.  */
+/* ARMv8.3-A architecture extensions.  */
+#define AARCH64_FL_V8_3	      (1 << 10)  /* Has ARMv8.3-A features.  */
 
 /* Has FP and SIMD.  */
 #define AARCH64_FL_FPSIMD     (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -151,6 +153,8 @@ extern unsigned aarch64_architecture_version;
   (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_CRC | AARCH64_FL_V8_1)
 #define AARCH64_FL_FOR_ARCH8_2			\
   (AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_V8_2)
+#define AARCH64_FL_FOR_ARCH8_3			\
+  (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3)
 
 /* Macros to test ISA flags.  */
 
@@ -162,6 +166,7 @@ extern unsigned aarch64_architecture_version;
 #define AARCH64_ISA_RDMA	   (aarch64_isa_flags & AARCH64_FL_V8_1)
 #define AARCH64_ISA_V8_2	   (aarch64_isa_flags & AARCH64_FL_V8_2)
 #define AARCH64_ISA_F16		   (aarch64_isa_flags & AARCH64_FL_F16)
+#define AARCH64_ISA_V8_3	   (aarch64_isa_flags & AARCH64_FL_V8_3)
 
 /* Crypto is an optional extension to AdvSIMD.  */
 #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -176,6 +181,9 @@ extern unsigned aarch64_architecture_version;
 #define TARGET_FP_F16INST (TARGET_FLOAT && AARCH64_ISA_F16)
 #define TARGET_SIMD_F16INST (TARGET_SIMD && AARCH64_ISA_F16)
 
+/* ARMv8.3-A features.  */
+#define TARGET_ARMV8_3	(AARCH64_ISA_V8_3)
+
 /* Make sure this is always defined so we don't have to check for ifdefs
    but rather use normal ifs.  */
 #ifndef TARGET_FIX_ERR_A53_835769_DEFAULT
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8e2f46617b8e44ccf16941c31029ab5625322867..791718831d7089c44dfadb137f5e93caa9cd05f0 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13874,7 +13874,10 @@ more feature modifiers.  This option has the form
 @option{-march=@var{arch}@r{@{}+@r{[}no@r{]}@var{feature}@r{@}*}}.
 
 The permissible values for @var{arch} are @samp{armv8-a},
-@samp{armv8.1-a}, @samp{armv8.2-a} or @var{native}.
+@samp{armv8.1-a}, @samp{armv8.2-a}, @samp{armv8.3-a} or @var{native}.
+
+The value @samp{armv8.3-a} implies @samp{armv8.2-a} and enables compiler
+support for the ARMv8.3-A architecture extensions.
 
 The value @samp{armv8.2-a} implies @samp{armv8.1-a} and enables compiler
 support for the ARMv8.2-A architecture extensions.

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

* [1/5][AArch64] Return address protection on AArch64
       [not found]       ` <6f8e65e0-643d-d0b0-26ad-4a20c3daf421@foss.arm.com>
@ 2017-01-06 11:47         ` Jiong Wang
  2017-01-13 16:05           ` James Greenhalgh
  2017-01-20  4:15           ` Andrew Pinski
  0 siblings, 2 replies; 75+ messages in thread
From: Jiong Wang @ 2017-01-06 11:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: James Greenhalgh, Richard Earnshaw (lists)

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

On 11/11/16 18:22, Jiong Wang wrote:
> As described in the cover letter, this patch implements return address signing
> for AArch64, it's controlled by the new option:
>
>    -msign-return-address=[none | non-leaf | all]
>
> "none" means don't do return address signing at all on any function.  "non-leaf"
> means only sign non-leaf function.  "all" means sign all functions.  Return
> address signing is currently disabled on ILP32.  I haven't tested it.
>
> The instructions added in the architecture are of 2 kinds.
>
> * In the NOP instruction space, which allows binaries to run without any traps
> on older versions of the architecture. This doesn't give any additional
> protection on older hardware but allows for the same binary to be used on
> earlier versions of the architecture and newer versions of the architecture.
>
> * New instructions that are only valid for v8.3 and will trap if used on earlier
> versions of the architecture.
>
> At default, once return address signing is enabled, it will only generates NOP
> instruction.
>
> While if -march=armv8.3-a specified, GCC will try to use the most efficient
> pointer authentication instruction as it can.
>
> The architecture has 2 user invisible system keys for signing and creating
> signed addresses as part of these instructions. For some use case, the user
> might want to use difference key for different functions.  The new option
> "-msign-return-address-key=key_name" let GCC select the key used for return
> address signing.  Permissible values are "a_key" for A key and "b_key" for B
> key, and this option are supported by function target attribute and LTO will
> hopefully just work.
>
>
>
> gcc/
> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>
>          * config/aarch64/aarch64-opts.h (aarch64_pauth_key_index): New enum.
>          (aarch64_function_type): New enum.
>          * config/aarch64/aarch64-protos.h (aarch64_output_sign_auth_reg): New
>          declaration.
>          * config/aarch64/aarch64.c (aarch64_expand_prologue): Sign return
>          address before it's pushed onto stack.
>          (aarch64_expand_epilogue): Authenticate return address fetched from
>          stack.
>          (aarch64_output_sign_auth_reg): New function.
>          (aarch64_override_options): Sanity check for ILP32 and ISA level.
>          (aarch64_attributes): New function attributes for "sign-return-address",
>          "pauth-key".
>          * config/aarch64/aarch64.md (UNSPEC_AUTH_REG, UNSPEC_AUTH_REG1716,
>          UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN,
>          UNSPEC_STRIP_X30_SIGN): New unspecs.
>          ("*do_return"): Generate combined instructions according to key index.
>          ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716",
>          "strip_reg_sign", "strip_lr_sign"): New.
>          * config/aarch64/aarch64.opt (msign-return-address, mpauth-key): New.
>          * config/aarch64/predicates.md (aarch64_const0_const1): New predicate.
>          * doc/extend.texi (AArch64 Function Attributes): Documents
>          "sign-return-address=", "pauth-key".
>          * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=",
>          "-pauth-key".
>
> gcc/testsuite/
> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>
>          * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>          * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.

Update the patchset according to new DWARF proposal described at

   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03010.html

While A key support for return address signing using DW_CFA_GNU_window_save only
needs simple modifications on code and associated DWARF generation, B key
support is complexer, it needs multiple CIE support in GCC and Binutils, so
currently we fall back to DWARF value expression which fully works although
requires longer encodings. Value expression also requires a few changes on
AArch64 prologue and epilogue hooks that code review will not be easy.

Therefore I have removed all B key support code in the initial support patch set,
and will organize them into a seperate follow up patchset so that we can do A key
code review first.

This patch is an update on the return address signing code generation.

gcc/
2017-01-06  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
         * config/aarch64/aarch64-protos.h
         (aarch64_return_address_signing_enabled): New declaration.
         * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
         New function.
         (aarch64_expand_prologue): Sign return address before it's pushed onto
         stack.
         (aarch64_expand_epilogue): Authenticate return address fetched from
         stack.
         (aarch64_override_options): Sanity check for ILP32 and ISA level.
         (aarch64_attributes): New function attributes for "sign-return-address".
         * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
         UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
         ("*do_return"): Generate combined instructions according to key index.
         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer
         iterators.
         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
         * config/aarch64/aarch64.opt (msign-return-address=): New.
         * doc/extend.texi (AArch64 Function Attributes): Documents
         "sign-return-address=".
         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".

gcc/testsuite/
2017-01-06  Jiong Wang  <jiong.wang@arm.com>

         * gcc.target/aarch64/return_address_sign_1.c: New testcase.
         * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.



[-- Attachment #2: 1.patch --]
[-- Type: text/x-diff, Size: 13645 bytes --]

diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
index 9f37b9b432e5ed978032fa3356b138e2c7433760..ba5d052e9b694289574a68f156ca68b66ad6e2ee 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -71,4 +71,14 @@ enum aarch64_code_model {
   AARCH64_CMODEL_LARGE
 };
 
+/* Function types -msign-return-address should sign.  */
+enum aarch64_function_type {
+  /* Don't sign any function.  */
+  AARCH64_FUNCTION_NONE,
+  /* Non-leaf functions.  */
+  AARCH64_FUNCTION_NON_LEAF,
+  /* All functions.  */
+  AARCH64_FUNCTION_ALL
+};
+
 #endif
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 29a3bd71151aa4fb7c6728f0fb52e2f3f233f41d..632dd4768d82c340ae4e9b4a93206743756c06e7 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -386,6 +386,7 @@ void aarch64_emit_call_insn (rtx);
 void aarch64_register_pragmas (void);
 void aarch64_relayout_simd_types (void);
 void aarch64_reset_previous_fndecl (void);
+bool aarch64_return_address_signing_enabled (void);
 void aarch64_save_restore_target_globals (tree);
 
 /* Initialize builtins for SIMD intrinsics.  */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 9dd75b07498871db3e37b335dc8a3e1d66ec1d8b..002895a167ce0deb45a5c1726527651af18bb4df 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3117,6 +3117,22 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
     }
 }
 
+/* Return TRUE if return address signing should be enabled for one function,
+   otherwise return FALSE.  */
+
+bool
+aarch64_return_address_signing_enabled (void)
+{
+  /* This function should only be called after frame laid out.   */
+  gcc_assert (cfun->machine->frame.laid_out);
+
+  /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
+     if it's LR is pushed onto stack.  */
+  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
+	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
+	      && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));
+}
+
 /* Emit code to save the callee-saved registers from register number START
    to LIMIT to the stack at the location starting at offset START_OFFSET,
    skipping any write-back candidates if SKIP_WB is true.  */
@@ -3535,6 +3551,10 @@ aarch64_expand_prologue (void)
   unsigned reg2 = cfun->machine->frame.wb_candidate2;
   rtx_insn *insn;
 
+  /* Sign return address for functions.  */
+  if (aarch64_return_address_signing_enabled ())
+    emit_insn (gen_pacisp ());
+
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size;
 
@@ -3670,6 +3690,16 @@ aarch64_expand_epilogue (bool for_sibcall)
       RTX_FRAME_RELATED_P (insn) = 1;
     }
 
+  /* sibcall won't generate normally return, therefore we need to authenticate
+     at here.  !TARGET_ARMV8_3 disallows GCC to use combined authentication
+     instruction which we prefer, so we need to generate a seperate
+     authentication. eh_return path can't do combined authentication, as it will
+     do extra stack adjustment which updates CFA to EH handler's CFA while we
+     want to use the CFA of the function which calls eh_return.  */
+  if (aarch64_return_address_signing_enabled ()
+      && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
+    emit_insn (gen_autisp ());
+
   /* Stack adjustment for exception handler.  */
   if (crtl->calls_eh_return)
     {
@@ -8894,6 +8924,9 @@ aarch64_override_options (void)
     error ("Assembler does not support -mabi=ilp32");
 #endif
 
+  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
+    error ("Return address signing is only supported on LP64");
+
   /* Make sure we properly set up the explicit options.  */
   if ((aarch64_cpu_string && valid_cpu)
        || (aarch64_tune_string && valid_tune))
@@ -9277,6 +9310,8 @@ static const struct aarch64_attribute_info aarch64_attributes[] =
   { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ },
   { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune,
      OPT_mtune_ },
+  { "sign-return-address", aarch64_attr_enum, false, NULL,
+     OPT_msign_return_address_ },
   { NULL, aarch64_attr_custom, false, NULL, OPT____ }
 };
 
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index bde42317f1bfd91a9d38a4cfa94d4cedd5246003..9b6f99dee3cecc0f15f24ec2375d3641fe03892d 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -67,6 +67,8 @@
 )
 
 (define_c_enum "unspec" [
+    UNSPEC_AUTI1716
+    UNSPEC_AUTISP
     UNSPEC_CASESI
     UNSPEC_CRC32B
     UNSPEC_CRC32CB
@@ -106,6 +108,8 @@
     UNSPEC_LD4_LANE
     UNSPEC_MB
     UNSPEC_NOP
+    UNSPEC_PACI1716
+    UNSPEC_PACISP
     UNSPEC_PRLG_STK
     UNSPEC_RBIT
     UNSPEC_SCVTF
@@ -135,6 +139,7 @@
     UNSPEC_RSQRTE
     UNSPEC_RSQRTS
     UNSPEC_NZCV
+    UNSPEC_XPACLRI
 ])
 
 (define_c_enum "unspecv" [
@@ -575,7 +580,14 @@
 (define_insn "*do_return"
   [(return)]
   ""
-  "ret"
+  {
+    if (aarch64_return_address_signing_enabled ()
+	&& TARGET_ARMV8_3
+	&& !crtl->calls_eh_return)
+      return "retaa";
+
+    return "ret";
+  }
   [(set_attr "type" "branch")]
 )
 
@@ -5341,6 +5353,31 @@
   [(set_attr "length" "0")]
 )
 
+;; Pointer authentication patterns are available for all architectures.  On
+;; pre-ARMv8.3-A architectures they are NOP.  This let the user write portable
+;; software which can get pointer authentication on new hardware while still
+;; runs correctly on old hardware though no pointer authentication protection.
+
+(define_insn "<pauth_mnem_prefix>sp"
+  [(set (reg:DI R30_REGNUM)
+	(unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
+  ""
+  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
+)
+
+(define_insn "<pauth_mnem_prefix>1716"
+  [(set (reg:DI R17_REGNUM)
+	(unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
+  ""
+  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
+)
+
+(define_insn "xpaclri"
+  [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
+  ""
+  "hint\t7 // xpaclri"
+)
+
 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
 ;; all of memory.  This blocks insns from being moved across this point.
 
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 56b920dfe5abda1349c441c2188e5ac3ca05ab5a..54368848bbb249949921a3018d927c4bd61b1fbd 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -149,6 +149,23 @@ mpc-relative-literal-loads
 Target Report Save Var(pcrelative_literal_loads) Init(2) Save
 PC relative literal loads.
 
+msign-return-address=
+Target RejectNegative Report Joined Enum(aarch64_ra_sign_scope_t) Var(aarch64_ra_sign_scope) Init(AARCH64_FUNCTION_NONE) Save
+Select return address signing scope.
+
+Enum
+Name(aarch64_ra_sign_scope_t) Type(enum aarch64_function_type)
+Supported AArch64 return address signing scope (for use with -msign-return-address= option):
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(none) Value(AARCH64_FUNCTION_NONE)
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(non-leaf) Value(AARCH64_FUNCTION_NON_LEAF)
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL)
+
 mlow-precision-recip-sqrt
 Common Var(flag_mrecip_low_precision_sqrt) Optimization
 Enable the reciprocal square root approximation.  Enabling this reduces
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index e2377c1cb2161c52ccadec3804294c494819cbb8..c59d31e5053a28fa31259341e82b6696f6ac8781 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -1032,6 +1032,10 @@
 (define_int_iterator FMAXMIN_UNS [UNSPEC_FMAX UNSPEC_FMIN
 				  UNSPEC_FMAXNM UNSPEC_FMINNM])
 
+(define_int_iterator PAUTH_LR_SP [UNSPEC_PACISP UNSPEC_AUTISP])
+
+(define_int_iterator PAUTH_17_16 [UNSPEC_PACI1716 UNSPEC_AUTI1716])
+
 (define_int_iterator VQDMULH [UNSPEC_SQDMULH UNSPEC_SQRDMULH])
 
 (define_int_iterator USSUQADD [UNSPEC_SUQADD UNSPEC_USQADD])
@@ -1218,6 +1222,18 @@
 				  (UNSPEC_FCVTZS "fcvtzs")
 				  (UNSPEC_FCVTZU "fcvtzu")])
 
+;; Pointer authentication mnemonic prefix.
+(define_int_attr pauth_mnem_prefix [(UNSPEC_PACISP "paci")
+				    (UNSPEC_AUTISP "auti")
+				    (UNSPEC_PACI1716 "paci")
+				    (UNSPEC_AUTI1716 "auti")])
+
+;; Pointer authentication HINT number for NOP space instructions using A Key.
+(define_int_attr pauth_hint_num_a [(UNSPEC_PACISP "25")
+				    (UNSPEC_AUTISP "29")
+				    (UNSPEC_PACI1716 "8")
+				    (UNSPEC_AUTI1716 "12")])
+
 (define_int_attr perm_insn [(UNSPEC_ZIP1 "zip") (UNSPEC_ZIP2 "zip")
 			    (UNSPEC_TRN1 "trn") (UNSPEC_TRN2 "trn")
 			    (UNSPEC_UZP1 "uzp") (UNSPEC_UZP2 "uzp")])
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 30bdcf07ad8b1bd086bbb87acb36fb0333944087..47250ebb149bbde021ef64eba8e96e35c2623284 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3513,6 +3513,12 @@ Specifies the core for which to tune the performance of this function and also
 whose architectural features to use.  The behavior and valid arguments are the
 same as for the @option{-mcpu=} command-line option.
 
+@item sign-return-address
+@cindex @code{sign-return-address} function attribute, AArch64
+Select the function scope we want to do return address signing on.  The behavior
+and permissible arguments are the same as for the command-line option
+@option{-msign-return-address=}.  The default value is @code{none}
+
 @end table
 
 The above target attributes can be specified as follows:
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index aa0ac8b41128483be53645b91bdcead096582e23..2792dbd0a2d0ed9e3f46237685f8ae65a5d8bcf5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14044,6 +14044,13 @@ accessed using a single instruction and emitted after each function.  This
 limits the maximum size of functions to 1MB.  This is enabled by default for
 @option{-mcmodel=tiny}.
 
+@item -msign-return-address=@var{scope}
+@opindex msign-return-address
+Select the function scope we want to do return address signing on.  Permissible
+values are @samp{none}, @samp{none-leaf} and @samp{all}.  @samp{none} means
+return address signing is disabled.  @samp{non-leaf} enables it for non-leaf
+functions.  @samp{all} for all functions and is the default value.
+
 @end table
 
 @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..9a0332abd41ca6ae994e6ed72771fca8ee532cd0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=all" } */
+
+int foo (int);
+int bar (int, int);
+
+/* sibcall only.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b)
+{
+  /* paciasp */
+  return foo (a + b);
+  /* autiasp */
+}
+
+/* non-leaf function with sibcall.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func2 (int a, int b)
+{
+  /* paciasp */
+  if (a < b)
+    return b;
+
+  a = foo (b);
+
+  return foo (a);
+  /* autiasp */
+}
+
+/* non-leaf function, legacy arch.  */
+int __attribute__ ((target ("arch=armv8.2-a")))
+func3 (int a, int b, int c)
+{
+  /* paciasp */
+  return a + foo (b) + c;
+  /* autiasp */
+}
+
+/* non-leaf function.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func4 (int a, int b, int c)
+{
+  /* paciasp */
+  return a + foo (b) + c;
+  /* retab */
+}
+
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none")))
+func4_disable (int a, int b, int c, int d)
+{
+  return c + bar (a, b) + d;
+}
+
+/* { dg-final { scan-assembler-times "autiasp" 3 } } */
+/* { dg-final { scan-assembler-times "paciasp" 4 } } */
+/* { dg-final { scan-assembler-times "retaa" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..6876e26a6a38eb670f8676f8f06dd74dfc18f41d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=non-leaf" } */
+
+int foo (int);
+int bar (int, int);
+
+/* sibcall only.  */
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=non-leaf")))
+func1 (int a, int b)
+{
+  /* No authentication.  */
+  return foo (a + b);
+}
+
+/* non-leaf function with sibcall.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func2 (int a, int b)
+{
+  /* paciasp */
+  if (a < b)
+    return b;
+
+  a = foo (b);
+
+  return foo (a);
+  /* autiasp */
+}
+
+/* non-leaf function, legacy arch.  */
+int __attribute__ ((target ("arch=armv8.2-a")))
+func3 (int a, int b, int c)
+{
+  /* pacibsp */
+  return a + foo (b) + c;
+  /* autibsp */
+}
+
+/* non-leaf function.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func4 (int a, int b, int c)
+{
+  /* pacibsp */
+  return a + foo (b) + c;
+  /* retab */
+}
+
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none")))
+func4_disable (int a, int b, int c, int d)
+{
+  return c + bar (a, b) + d;
+}
+
+/* { dg-final { scan-assembler-times "paciasp" 3 } } */
+/* { dg-final { scan-assembler-times "autiasp" 2 } } */
+/* { dg-final { scan-assembler-times "retaa" 1 } } */

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

* [3/5][AArch64] New builtins required by libgcc unwinder
       [not found]           ` <8d24add0-1c8d-6778-11dd-f7d018b34396@foss.arm.com>
@ 2017-01-06 11:47             ` Jiong Wang
  2017-01-13 16:14               ` Richard Earnshaw (lists)
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-06 11:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: James Greenhalgh, Richard Earnshaw (lists)

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

On 11/11/16 18:22, Jiong Wang wrote:
> This patch implements a few ARMv8.3-A new builtins for pointer sign and
> authentication instructions.
>
> Currently, these builtins are supposed to be used by libgcc EH unwinder
> only.  They are not public interface to external user.
>
> OK to install?
>
> gcc/
> 2016-11-11  Jiong Wang<jiong.wang@arm.com>
>
>          * config/aarch64/aarch64-builtins.c (enum aarch64_builtins): New entries
>          for AARCH64_PAUTH_BUILTIN_PACI1716, AARCH64_PAUTH_BUILTIN_AUTIA1716,
>          AARCH64_PAUTH_BUILTIN_AUTIB1716, AARCH64_PAUTH_BUILTIN_XPACLRI.
>          (aarch64_init_v8_3_builtins): New.
>          (aarch64_init_builtins): Call aarch64_init_builtins.
>          (arch64_expand_builtin): Expand new builtins.
>
>
This patch is an update on builtins support.  All these builtins are to be
internally used by libgcc only, so the updates only keeps those used.

OK for trunk?

gcc/

2017-01-06  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-builtins.c (enum aarch64_builtins): New entries
         for AARCH64_PAUTH_BUILTIN_XPACLRI, AARCH64_PAUTH_BUILTIN_PACIA1716,
         AARCH64_PAUTH_BUILTIN_AUTIA1716);
         (aarch64_init_pauth_hint_builtins): New.
         (aarch64_init_builtins): Call aarch64_init_pauth_hint_builtins.
         (aarch64_expand_builtin): Expand new builtins.


[-- Attachment #2: 3.patch --]
[-- Type: text/x-diff, Size: 3480 bytes --]

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 69fb756f0fbdc016f35ce1d08f2aaf092a034704..9ae9d9afc9c141235d7eee037d5571b9f35edc31 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -376,6 +376,10 @@ enum aarch64_builtins
   AARCH64_CRC32_BUILTIN_BASE,
   AARCH64_CRC32_BUILTINS
   AARCH64_CRC32_BUILTIN_MAX,
+  /* ARMv8.3-A Pointer Authentication Builtins.  */
+  AARCH64_PAUTH_BUILTIN_AUTIA1716,
+  AARCH64_PAUTH_BUILTIN_PACIA1716,
+  AARCH64_PAUTH_BUILTIN_XPACLRI,
   AARCH64_BUILTIN_MAX
 };
 
@@ -923,6 +927,33 @@ aarch64_init_fp16_types (void)
   aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
 }
 
+/* Pointer authentication builtins that will become NOP on legacy platform.
+   Currently, these builtins are for internal use only (libgcc EH unwinder).  */
+
+void
+aarch64_init_pauth_hint_builtins (void)
+{
+  /* Pointer Authentication builtins.  */
+  tree ftype_pointer_auth
+    = build_function_type_list (ptr_type_node, ptr_type_node,
+				unsigned_intDI_type_node, NULL_TREE);
+  tree ftype_pointer_strip
+    = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
+
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
+    = add_builtin_function ("__builtin_aarch64_autia1716", ftype_pointer_auth,
+			    AARCH64_PAUTH_BUILTIN_AUTIA1716, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIA1716]
+    = add_builtin_function ("__builtin_aarch64_pacia1716", ftype_pointer_auth,
+			    AARCH64_PAUTH_BUILTIN_PACIA1716, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
+    = add_builtin_function ("__builtin_aarch64_xpaclri", ftype_pointer_strip,
+			    AARCH64_PAUTH_BUILTIN_XPACLRI, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+}
+
 void
 aarch64_init_builtins (void)
 {
@@ -951,6 +982,10 @@ aarch64_init_builtins (void)
 
   aarch64_init_crc32_builtins ();
   aarch64_init_builtin_rsqrt ();
+
+/* Initialize pointer authentication builtins which are backed by instructions
+   in NOP encoding space.  */
+  aarch64_init_pauth_hint_builtins ();
 }
 
 tree
@@ -1293,6 +1328,43 @@ aarch64_expand_builtin (tree exp,
 	}
       emit_insn (pat);
       return target;
+    case AARCH64_PAUTH_BUILTIN_AUTIA1716:
+    case AARCH64_PAUTH_BUILTIN_PACIA1716:
+    case AARCH64_PAUTH_BUILTIN_XPACLRI:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = force_reg (Pmode, expand_normal (arg0));
+
+      if (!target)
+	target = gen_reg_rtx (Pmode);
+      else
+	target = force_reg (Pmode, target);
+
+      emit_move_insn (target, op0);
+
+      if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
+	{
+	  rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
+	  icode = CODE_FOR_xpaclri;
+	  emit_move_insn (lr, op0);
+	  emit_insn (GEN_FCN (icode) ());
+	  emit_move_insn (target, lr);
+	}
+      else
+	{
+	  tree arg1 = CALL_EXPR_ARG (exp, 1);
+	  rtx op1 = force_reg (Pmode, expand_normal (arg1));
+	  icode = (fcode == AARCH64_PAUTH_BUILTIN_PACIA1716
+		   ? CODE_FOR_paci1716 : CODE_FOR_auti1716);
+
+	  rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
+	  rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
+	  emit_move_insn (x17_reg, op0);
+	  emit_move_insn (x16_reg, op1);
+	  emit_insn (GEN_FCN (icode) ());
+	  emit_move_insn (target, x17_reg);
+	}
+
+      return target;
     }
 
   if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)

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

* [4/5][AArch64, libgcc] Let AArch64 use customized unwinder file
       [not found]             ` <e9d558d5-0f41-c1e1-e184-94a9311fa664@foss.arm.com>
@ 2017-01-06 11:47               ` Jiong Wang
  0 siblings, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2017-01-06 11:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: James Greenhalgh, Richard Earnshaw (lists), Ian Lance Taylor

On 11/11/16 18:22, Jiong Wang wrote:
> We need customized EH unwinder support for AArch64 DWARF operations introduced
> earlier in this patchset, these changes mostly need to be done in the generic
> file unwind-dw2.c.
>
> There are two ways of introducing these AArch64 support:
>    * Introducing a few target macros so we can customize functions like
>      uw_init_context, uw_install_context etc.
>    * Use target private unwind-dw2 implementation, i.e duplicate the generic
>      unwind-dw2.c into target config directory and use it instead of generic one.
>      This is current used by IA64 and CR16 is using.
>
> I am not sure which approach is the convention in libgcc, Ian, any comments on this?
> Thanks.
>
> This patch is the start of using approach 2 includes necessary Makefile support
> and copying of original unwind-dw2.c.
>
> A follow up patch will implement those AArch64 specific stuff so the change will
> be very clear.
>
> OK for trunk?
>
> libgcc/
> 2016-11-08  Jiong Wang<jiong.wang@arm.com>
>
>          * config.host (aarch64*-*-elf, aarch64*-*-rtems*, aarch64*-*-linux*):
>          Include new AArch64 EH makefile.
>          * config/aarch64/t-eh-aarch64: New EH makefile.
>          * config/aarch64/unwind-aarch64.c: New EH unwinder implementation,
>          copied from unwind-dw2.c.
>
Ping ~
No change on this patch for new DWARF proposal.

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

* [5/5][AArch64, libgcc] Runtime support for AArch64 DWARF operations
       [not found]               ` <fdda17f4-5594-c983-64ac-158a9ba43e4c@foss.arm.com>
@ 2017-01-06 11:47                 ` Jiong Wang
  2017-01-12 18:10                   ` [Ping~]Re: [5/5][AArch64, libgcc] Runtime support for AArch64 return address signing (also attached target macros version) Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-06 11:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: James Greenhalgh, Richard Earnshaw (lists), Ian Lance Taylor

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

On 11/11/16 18:22, Jiong Wang wrote:
> This patch add AArch64 specific runtime EH unwinding support for
> DW_OP_AARCH64_pauth, DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref.
>
> The semantics of them are described at the specification in patch [1/9].
>
> The support includes:
>    * Parsing these DWARF operations.  Perform unwinding actions according to
>      their semantics.
>
>    * Handling eh_return multi return paths.
>      Function calling __builtin_eh_return (_Unwind_RaiseException*) will have
>      multiple return paths.  One is for normal exit, the other is for install
>      EH handler.  If the _Unwind_RaiseException itself is return address signed,
>      then there will always be return address authentication before return,
>      however, if the return path in _Unwind_RaiseException if from installing EH
>      handler the address of which has already been authenticated during
>      unwinding,  then we need to re-sign that address, so when the execution flow
>      continues at _Unwind_RaiseException's epilogue, the authentication still
>      works correctly.
>
>
> OK for trunk?
>
> libgcc/
> 2016-11-11  Jiong Wang<jiong.wang@arm.com>
>
>          * config/aarch64/unwind-aarch64.c (RA_SIGN_BIT): New flag to indicate
>          one frame is return address signed.
>          (execute_stack_op): Handle DW_OP_AARCH64_pauth, DW_OP_AARCH64_paciasp,
>          DW_OP_AARCH64_paciasp_deref.
>          (uw_init_context): Call aarch64_uw_init_context_1.
>          (uw_init_context_1): Rename to aarch64_uw_init_context_1.  Strip
>          signature for seed address.
>          (uw_install_context): Re-sign handler's address so it works correctly
>          with caller's context.
>          (uw_install_context_1): by_value[LR] can be true, after return address
>          signing LR will come from DWARF value expression rule which is a
>          by_value true rule.
>
>
This is the update on libgcc unwinder support according to new DWARF proposal.

As Joseph commented, duplication of unwind-dw2.c is not encouraged in libgcc,
But from this patch, you can see there are a few places we need to modify for
AArch64 in unwind-aarch64.c, so the file duplication approach is acceptable?


libgcc/

2017-01-06  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/unwind-aarch64.c (DWARF_REGNUM_AARCH64_RA_STATE,
         RA_A_SIGNED_BIT): New macros.
         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on AArch64.
         (uw_frame_state_for): Clear bit[0] of DWARF_REGNUM_AARCH64_RA_STATE.
         (uw_update_context): Authenticate return address according to
         DWARF_REGNUM_AARCH64_RA_STATE.
         (uw_init_context_1): Strip signature of seed address.
         (uw_install_context): Re-authenticate EH handler's address.


[-- Attachment #2: 5.patch --]
[-- Type: text/x-diff, Size: 5381 bytes --]

diff --git a/libgcc/config/aarch64/unwind-aarch64.c b/libgcc/config/aarch64/unwind-aarch64.c
index 1fb6026d123f8e7fc676f5e95e8e66caccf3d6ff..11e3c9f724c9bc5796103a0d973bfe769d23b6e7 100644
--- a/libgcc/config/aarch64/unwind-aarch64.c
+++ b/libgcc/config/aarch64/unwind-aarch64.c
@@ -37,6 +37,9 @@
 #include "gthr.h"
 #include "unwind-dw2.h"
 
+/* This is a copy of libgcc/unwind-dw2.c with AArch64 return address signing
+   support.  */
+
 #ifdef HAVE_SYS_SDT_H
 #include <sys/sdt.h>
 #endif
@@ -55,6 +58,8 @@
 #define PRE_GCC3_DWARF_FRAME_REGISTERS __LIBGCC_DWARF_FRAME_REGISTERS__
 #endif
 
+#define DWARF_REGNUM_AARCH64_RA_STATE 32
+
 /* ??? For the public function interfaces, we tend to gcc_assert that the
    column numbers are in range.  For the dwarf2 unwind info this does happen,
    although so far in a case that doesn't actually matter.
@@ -136,6 +141,8 @@ struct _Unwind_Context
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  /* Return address has been signed with A key.  */
+#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
@@ -1185,13 +1192,9 @@ execute_cfa_program (const unsigned char *insn_ptr,
 	  break;
 
 	case DW_CFA_GNU_window_save:
-	  /* ??? Hardcoded for SPARC register window configuration.  */
-	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
-	    for (reg = 16; reg < 32; ++reg)
-	      {
-		fs->regs.reg[reg].how = REG_SAVED_OFFSET;
-		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
-	      }
+	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
+	     return address signing status.  */
+	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
 	  break;
 
 	case DW_CFA_GNU_args_size:
@@ -1263,6 +1266,8 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
   /* First decode all the insns in the CIE.  */
   end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
   execute_cfa_program (insn, end, context, fs);
+  /* Clear bit 0 of RA_STATE pseudo register.  */
+  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset &= ~0x1;
 
   /* Locate augmentation for the fde.  */
   aug = (const unsigned char *) fde + sizeof (*fde);
@@ -1513,10 +1518,19 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
        stack frame.  */
     context->ra = 0;
   else
-    /* Compute the return address now, since the return address column
-       can change from frame to frame.  */
-    context->ra = __builtin_extract_return_addr
-      (_Unwind_GetPtr (context, fs->retaddr_column));
+    {
+      /* Compute the return address now, since the return address column
+	 can change from frame to frame.  */
+      context->ra
+	= __builtin_extract_return_addr (_Unwind_GetPtr (context,
+							 fs->retaddr_column));
+      if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+	{
+	  _Unwind_Word salt = (_Unwind_Word) context->cfa;
+	  context->ra
+	    = (void *) __builtin_aarch64_autia1716 (context->ra, salt);
+	}
+    }
 }
 
 static void
@@ -1550,6 +1564,11 @@ uw_init_context_1 (struct _Unwind_Context *context,
 		   void *outer_cfa, void *outer_ra)
 {
   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+  /* Drop authentication signature for inner RA.  It's anyway will be
+     authenticated later before return if return addresss signing is enabled for
+     libgcc.  Here it's served as the seed address which will be used for table
+     searching,  we need the original address.  */
+  ra = __builtin_aarch64_xpaclri (ra);
   _Unwind_FrameState fs;
   _Unwind_SpTmp sp_slot;
   _Unwind_Reason_Code code;
@@ -1586,6 +1605,10 @@ uw_init_context_1 (struct _Unwind_Context *context,
      initialization context, then we can't see it in the given
      call frame data.  So have the initialization context tell us.  */
   context->ra = __builtin_extract_return_addr (outer_ra);
+  context->ra = __builtin_aarch64_xpaclri (context->ra);
+  if (fs.regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    /* The flag is used for re-authenticating EH handler's address.  */
+    context->flags |= RA_A_SIGNED_BIT;
 }
 
 static void _Unwind_DebugHook (void *, void *)
@@ -1610,13 +1633,22 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
 
 /* Install TARGET into CURRENT so that we can return to it.  This is a
    macro because __builtin_eh_return must be invoked in the context of
-   our caller.  */
+   our caller.
+
+   For AArch64 pointer authentication, as target EH handler's address is
+   already authenticated, we need to sign it again with the original SP
+   of CURRENT.  */
 
 #define uw_install_context(CURRENT, TARGET)				\
   do									\
     {									\
       long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
       void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      if ((CURRENT)->flags & RA_A_SIGNED_BIT)				\
+	handler								\
+	  = __builtin_aarch64_pacia1716 (handler,			\
+					 (_Unwind_Word)			\
+					 (CURRENT)->cfa);		\
       _Unwind_DebugHook ((TARGET)->cfa, handler);			\
       __builtin_eh_return (offset, handler);				\
     }									\

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

* [2/5][AArch64] Generate dwarf information for -msign-return-address
       [not found]         ` <2718d6de-4571-694b-3eeb-90b7b839a867@foss.arm.com>
@ 2017-01-06 11:47           ` Jiong Wang
  2017-01-13 16:09             ` Richard Earnshaw (lists)
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-06 11:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: James Greenhalgh, Richard Earnshaw (lists)

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

On 11/11/16 18:22, Jiong Wang wrote:
> This patch generate DWARF description for pointer authentication.  DWARF value
> expression is used to describe the authentication action.
>
> Please see the cover letter and AArch64 DWARF specification for the semantics
> of AArch64 DWARF operations.
>
> When authentication key index is A key, we use compact DWARF description which
> can largely save DWARF frame size, otherwise we fallback to general operator.
>
>
>
> Example
> ===
>
>      int
>      cal (int a, int b, int c)
>      {
>        return a + dec (b) + c;
>      }
>
> Compact DWARF description
> (-march=armv8.3-a -msign-return-address)
> ===
>
>    DW_CFA_advance_loc: 4 to 0000000000000004
>    DW_CFA_val_expression: r30 (x30) (DW_OP_AARCH64_paciasp)
>    DW_CFA_advance_loc: 4 to 0000000000000008
>    DW_CFA_val_expression: r30 (x30) (DW_OP_AARCH64_paciasp_deref: -24)
>
> General DWARF description
> ===
> (-march=armv8.3-a -msign-return-address -mpauth-key=b_key)
>
>    DW_CFA_advance_loc: 4 to 0000000000000004
>    DW_CFA_val_expression: r30 (x30) (DW_OP_breg30 (x30): 0; DW_OP_AARCH64_pauth: 18)
>    DW_CFA_advance_loc: 4 to 0000000000000008
>    DW_CFA_val_expression: r30 (x30) (DW_OP_dup; DW_OP_const1s: -24; DW_OP_plus; DW_OP_deref; DW_OP_AARCH64_pauth: 18)
>
>  From Linux kernel testing, -msign-return-address will introduce +24%
> .debug_frame size increase when signing all functions and using compact
> description, and about +45% .debug_frame size increase if using general
> description.
>
>
> gcc/
> 2016-11-11  Jiong Wang<jiong.wang@arm.com>
>
>          * config/aarch64/aarch64.h (aarch64_pauth_action_type): New enum.
>          * config/aarch64/aarch64.c (aarch64_attach_ra_auth_dwarf_note): New function.
>          (aarch64_attach_ra_auth_dwarf_general): New function.
>          (aarch64_attach_ra_auth_dwarf_shortcut): New function.
>          (aarch64_save_callee_saves): Generate dwarf information if LR is signed.
>          (aarch64_expand_prologue): Likewise.
>          (aarch64_expand_epilogue): Likewise.

This patch is an update on DWARF generation for return address signing.

According to new proposal, we simply needs to generate REG_CFA_WINDOW_SAVE
annotation.

gcc/

2017-01-06  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64.c (aarch64_expand_prologue): Generate dwarf
         annotation (REG_CFA_WINDOW_SAVE) for return address signing.
         (aarch64_expand_epilogue): Likewise.



[-- Attachment #2: 2.patch --]
[-- Type: text/x-diff, Size: 1185 bytes --]

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 002895a167ce0deb45a5c1726527651af18bb4df..20ed79e5690f45ec121ef516245c686cc0cc82b5 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3553,7 +3553,11 @@ aarch64_expand_prologue (void)
 
   /* Sign return address for functions.  */
   if (aarch64_return_address_signing_enabled ())
-    emit_insn (gen_pacisp ());
+    {
+      insn = emit_insn (gen_pacisp ());
+      add_reg_note (insn, REG_CFA_WINDOW_SAVE, const0_rtx);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size;
@@ -3698,7 +3702,11 @@ aarch64_expand_epilogue (bool for_sibcall)
      want to use the CFA of the function which calls eh_return.  */
   if (aarch64_return_address_signing_enabled ()
       && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
-    emit_insn (gen_autisp ());
+    {
+      insn = emit_insn (gen_autisp ());
+      add_reg_note (insn, REG_CFA_WINDOW_SAVE, const0_rtx);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   /* Stack adjustment for exception handler.  */
   if (crtl->calls_eh_return)

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

* Re: [Ping~][AArch64] Add commandline support for -march=armv8.3-a
  2017-01-06 11:33       ` [Ping~][AArch64] Add commandline support for -march=armv8.3-a Jiong Wang
@ 2017-01-10 17:00         ` James Greenhalgh
  0 siblings, 0 replies; 75+ messages in thread
From: James Greenhalgh @ 2017-01-10 17:00 UTC (permalink / raw)
  To: Jiong Wang; +Cc: gcc-patches, Richard Earnshaw (lists), nd

On Fri, Jan 06, 2017 at 11:33:39AM +0000, Jiong Wang wrote:
> On 11/11/16 18:22, Jiong Wang wrote:
> >This patch add command line support for ARMv8.3-A through new architecture:
> >
> >   -march=armv8.3-a
> >
> >ARMv8.3-A implies all default features of ARMv8.2-A and meanwhile it includes
> >the new pointer authentication extension.
> >
> >
> >gcc/
> >2016-11-08  Jiong Wang<jiong.wang@arm.com>
> >
> >         * config/aarch64/aarch64-arches.def: New entry for "armv8.3-a".
> >         * config/aarch64/aarch64.h (AARCH64_FL_PAUTH, AARCH64_FL_V8_3,
> >         AARCH64_FL_FOR_ARCH8_3, AARCH64_ISA_PAUTH, AARCH64_ISA_V8_3,
> >         TARGET_PAUTH, TARGET_ARMV8_3): New.
> >         * doc/invoke.texi (AArch64 Options): Document "armv8.3-a".
> 
> Ping ~
> 
> As pointer authentication extension is defined to be mandatory extension on
> ARMv8.3-A and is not optional, I adjusted the patch slightly.
> 
> This also let GCC treating pointer authentication extension in consistent way
> with Binutils.
> 
> OK for trunk?

OK.

Thanks,
James

> 
> gcc/
> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
> 
>         * config/aarch64/aarch64-arches.def: New entry for "armv8.3-a".
>         * config/aarch64/aarch64.h (AARCH64_FL_V8_3, AARCH64_FL_FOR_ARCH8_3,
>         AARCH64_ISA_V8_3, TARGET_ARMV8_3): New.
>         * doc/invoke.texi (AArch64 Options): Document "armv8.3-a".
> 
> 

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

* [Ping~]Re: [5/5][AArch64, libgcc] Runtime support for AArch64 return address signing (also attached target macros version)
  2017-01-06 11:47                 ` [5/5][AArch64, libgcc] Runtime support for AArch64 DWARF operations Jiong Wang
@ 2017-01-12 18:10                   ` Jiong Wang
  2017-01-13 14:12                     ` James Greenhalgh
  2017-01-18 17:10                     ` [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros) Jiong Wang
  0 siblings, 2 replies; 75+ messages in thread
From: Jiong Wang @ 2017-01-12 18:10 UTC (permalink / raw)
  To: gcc-patches
  Cc: James Greenhalgh, Richard Earnshaw (lists),
	Ian Lance Taylor, Joseph Myers

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

On 06/01/17 11:47, Jiong Wang wrote:
> This is the update on libgcc unwinder support according to new DWARF 
> proposal.
>
> As Joseph commented, duplication of unwind-dw2.c is not encouraged in 
> libgcc,
> But from this patch, you can see there are a few places we need to 
> modify for
> AArch64 in unwind-aarch64.c, so the file duplication approach is 
> acceptable?
>
>
> libgcc/
>
> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>
>         * config/aarch64/unwind-aarch64.c (DWARF_REGNUM_AARCH64_RA_STATE,
>         RA_A_SIGNED_BIT): New macros.
>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on 
> AArch64.
>         (uw_frame_state_for): Clear bit[0] of 
> DWARF_REGNUM_AARCH64_RA_STATE.
>         (uw_update_context): Authenticate return address according to
>         DWARF_REGNUM_AARCH64_RA_STATE.
>         (uw_init_context_1): Strip signature of seed address.
>         (uw_install_context): Re-authenticate EH handler's address.
>
Ping~

For comparision, I have also attached the patch using the target macros.

Four new target macros are introduced:

   MD_POST_EXTRACT_ROOT_ADDR
   MD_POST_EXTRACT_FRAME_ADDR
   MD_POST_FROB_EH_HANDLER_ADDR
   MD_POST_INIT_CONTEXT

MD_POST_EXTRACT_ROOT_ADDR is to do target private post processing on the address
inside _Unwind* functions, they are serving as root address to start the
unwinding.  MD_POST_EXTRACT_FRAME_ADDR is to do target private post processing
on th address inside the real user program which throws the exceptions.

MD_POST_FROB_EH_HANDLER_ADDR is to do target private frob on the EH handler's
address before we install it into current context.

MD_POST_INIT_CONTEXT it to do target private initialization on the context
structure after common initialization.

One "__aarch64__" macro check is needed to multiplex DW_CFA_window_save.

libgcc/ChangeLog:

2017-01-11  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-unwind.h: New file.
         (DWARF_REGNUM_AARCH64_RA_STATE): Define.
         (MD_POST_EXTRACT_ROOT_ADDR): Define.
         (MD_POST_EXTRACT_FRAME_ADDR): Define.
         (MD_POST_FROB_EH_HANDLER_ADDR): Define.
         (MD_POST_INIT_CONTEXT): Define.
         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
         * config.host (aarch64*-*-elf, aarch64*-*-rtems*, aarch64*-*-freebsd*):
         Initialize md_unwind_header to include aarch64-unwind.h.
         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for __aarch64__.
         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR and
         MD_POST_INIT_CONTEXT.
         (uw_frob_return_addr): New function.
         (_Unwind_DebugHook): Use uw_frob_return_addr.


[-- Attachment #2: macros-verion.patch --]
[-- Type: text/x-diff, Size: 8768 bytes --]

diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 8085a42ace15d53f4cb0c6681717012d906a6d47..35010a4065bb83f706701cb05392193f0ffa1f11 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -136,6 +136,8 @@ struct _Unwind_Context
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  /* Bit reserved on AArch64, return address has been signed with A key.  */
+#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
@@ -1185,6 +1187,11 @@ execute_cfa_program (const unsigned char *insn_ptr,
 	  break;
 
 	case DW_CFA_GNU_window_save:
+#ifdef __aarch64__
+	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
+	     return address signing status.  */
+	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
+#else
 	  /* ??? Hardcoded for SPARC register window configuration.  */
 	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
 	    for (reg = 16; reg < 32; ++reg)
@@ -1192,6 +1199,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
 		fs->regs.reg[reg].how = REG_SAVED_OFFSET;
 		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
 	      }
+#endif
 	  break;
 
 	case DW_CFA_GNU_args_size:
@@ -1513,10 +1521,15 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
        stack frame.  */
     context->ra = 0;
   else
-    /* Compute the return address now, since the return address column
-       can change from frame to frame.  */
-    context->ra = __builtin_extract_return_addr
-      (_Unwind_GetPtr (context, fs->retaddr_column));
+    {
+      /* Compute the return address now, since the return address column
+	 can change from frame to frame.  */
+      context->ra = __builtin_extract_return_addr
+	(_Unwind_GetPtr (context, fs->retaddr_column));
+#ifdef MD_POST_EXTRACT_FRAME_ADDR
+      context->ra = MD_POST_EXTRACT_FRAME_ADDR (context, fs, context->ra);
+#endif
+    }
 }
 
 static void
@@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
 		   void *outer_cfa, void *outer_ra)
 {
   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
+#endif
   _Unwind_FrameState fs;
   _Unwind_SpTmp sp_slot;
   _Unwind_Reason_Code code;
@@ -1586,6 +1602,12 @@ uw_init_context_1 (struct _Unwind_Context *context,
      initialization context, then we can't see it in the given
      call frame data.  So have the initialization context tell us.  */
   context->ra = __builtin_extract_return_addr (outer_ra);
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
+#endif
+#ifdef MD_POST_INIT_CONTEXT
+  MD_POST_INIT_CONTEXT (context, &fs);
+#endif
 }
 
 static void _Unwind_DebugHook (void *, void *)
@@ -1608,6 +1630,20 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
 #endif
 }
 
+/* Frob exception handler's address kept in TARGET before installing into
+   CURRENT context.  */
+
+static void *
+uw_frob_return_addr (struct _Unwind_Context *current,
+		     struct _Unwind_Context *target)
+{
+  void *ret_addr = __builtin_frob_return_addr (target->ra);
+#ifdef MD_POST_FROB_EH_HANDLER_ADDR
+  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
+#endif
+  return ret_addr;
+}
+
 /* Install TARGET into CURRENT so that we can return to it.  This is a
    macro because __builtin_eh_return must be invoked in the context of
    our caller.  */
@@ -1616,7 +1652,7 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
   do									\
     {									\
       long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
-      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      void *handler = uw_frob_return_addr ((CURRENT), (TARGET));	\
       _Unwind_DebugHook ((TARGET)->cfa, handler);			\
       __builtin_eh_return (offset, handler);				\
     }									\
diff --git a/libgcc/config.host b/libgcc/config.host
index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -331,11 +331,13 @@ aarch64*-*-elf | aarch64*-*-rtems*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-freebsd*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-linux*)
 	extra_parts="$extra_parts crtfastmath.o"
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd20feb0ce061c82c9134609438c84bc161670f9
--- /dev/null
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2017 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef AARCH64_UNWIND_H
+#define AARCH64_UNWIND_H
+
+#define DWARF_REGNUM_AARCH64_RA_STATE 34
+
+#define MD_POST_EXTRACT_ROOT_ADDR(addr)  __builtin_aarch64_xpaclri (addr)
+#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \
+  aarch64_post_extract_frame_addr (context, fs, addr)
+#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \
+  aarch64_post_frob_eh_handler_addr (current, target, addr)
+#define MD_POST_INIT_CONTEXT(context, fs) \
+  aarch64_post_init_context (context, fs)
+
+/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
+   unwind frame info FS.  If ADDR is signed, we do address authentication on it
+   using CFA of current frame.  */
+
+static void *
+aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
+				 _Unwind_FrameState *fs, void *addr)
+{
+  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    {
+      _Unwind_Word salt = (_Unwind_Word) context->cfa;
+      return __builtin_aarch64_autia1716 (addr, salt);
+    }
+  else
+    return addr;
+}
+
+/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before
+   installing it into current context CURRENT.  TARGET is currently not used.
+   We need to sign exception handler's address if CURRENT itself is signed.  */
+
+static void *
+aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
+				   struct _Unwind_Context *target
+				   ATTRIBUTE_UNUSED,
+				   void *handler_addr)
+{
+  if (current->flags & RA_A_SIGNED_BIT)
+    return __builtin_aarch64_pacia1716 (handler_addr,
+					(_Unwind_Word) current->cfa);
+  else
+    return handler_addr;
+}
+
+/* Do AArch64 private initialization on CONTEXT based on frame info FS.  Mark
+   CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE is
+   set.  */
+
+static void
+aarch64_post_init_context (struct _Unwind_Context *context,
+			   _Unwind_FrameState *fs)
+{
+  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    /* The flag is used for re-authenticating EH handler's address.  */
+    context->flags |= RA_A_SIGNED_BIT;
+
+  return;
+}
+
+#endif /* defined AARCH64_UNWIND_H */
diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
index 1256f010007ac964de8bb895379a7d893a446bd9..75774b30c080ad2361fb37c7208bcf3d3b57d77a 100644
--- a/libgcc/config/aarch64/linux-unwind.h
+++ b/libgcc/config/aarch64/linux-unwind.h
@@ -24,6 +24,7 @@
 
 #include <signal.h>
 #include <sys/ucontext.h>
+#include "aarch64-unwind.h"
 
 
 /* Since insns are always stored LE, on a BE system the opcodes will

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

* Re: [Ping~]Re: [5/5][AArch64, libgcc] Runtime support for AArch64 return address signing (also attached target macros version)
  2017-01-12 18:10                   ` [Ping~]Re: [5/5][AArch64, libgcc] Runtime support for AArch64 return address signing (also attached target macros version) Jiong Wang
@ 2017-01-13 14:12                     ` James Greenhalgh
  2017-01-18 17:10                     ` [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros) Jiong Wang
  1 sibling, 0 replies; 75+ messages in thread
From: James Greenhalgh @ 2017-01-13 14:12 UTC (permalink / raw)
  To: Jiong Wang
  Cc: gcc-patches, Richard Earnshaw (lists),
	Ian Lance Taylor, Joseph Myers, nd

On Thu, Jan 12, 2017 at 06:10:36PM +0000, Jiong Wang wrote:
> On 06/01/17 11:47, Jiong Wang wrote:
> >This is the update on libgcc unwinder support according to new
> >DWARF proposal.
> >
> >As Joseph commented, duplication of unwind-dw2.c is not encouraged
> >in libgcc,
> >But from this patch, you can see there are a few places we need to
> >modify for
> >AArch64 in unwind-aarch64.c, so the file duplication approach is
> >acceptable?
> >
> >
> >libgcc/
> >
> >2017-01-06  Jiong Wang  <jiong.wang@arm.com>
> >
> >        * config/aarch64/unwind-aarch64.c (DWARF_REGNUM_AARCH64_RA_STATE,
> >        RA_A_SIGNED_BIT): New macros.
> >        (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on
> >AArch64.
> >        (uw_frame_state_for): Clear bit[0] of
> >DWARF_REGNUM_AARCH64_RA_STATE.
> >        (uw_update_context): Authenticate return address according to
> >        DWARF_REGNUM_AARCH64_RA_STATE.
> >        (uw_init_context_1): Strip signature of seed address.
> >        (uw_install_context): Re-authenticate EH handler's address.
> >
> Ping~
> 
> For comparision, I have also attached the patch using the target macros.

Personally, I much prefer this approach.

I haven't looked at your patch in detail, I'll leave that for after a
libgcc maintainer has commented on whether these macros would be
acceptable.

Thanks,
James


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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-06 11:47         ` [1/5][AArch64] Return address protection on AArch64 Jiong Wang
@ 2017-01-13 16:05           ` James Greenhalgh
  2017-01-13 17:05             ` Jiong Wang
  2017-01-20  4:15           ` Andrew Pinski
  1 sibling, 1 reply; 75+ messages in thread
From: James Greenhalgh @ 2017-01-13 16:05 UTC (permalink / raw)
  To: Jiong Wang; +Cc: gcc-patches, Richard Earnshaw (lists), nd

On Fri, Jan 06, 2017 at 11:47:07AM +0000, Jiong Wang wrote:
> On 11/11/16 18:22, Jiong Wang wrote:
> gcc/
> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
> 
>         * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
>         * config/aarch64/aarch64-protos.h
>         (aarch64_return_address_signing_enabled): New declaration.
>         * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
>         New function.
>         (aarch64_expand_prologue): Sign return address before it's pushed onto
>         stack.
>         (aarch64_expand_epilogue): Authenticate return address fetched from
>         stack.
>         (aarch64_override_options): Sanity check for ILP32 and ISA level.
>         (aarch64_attributes): New function attributes for "sign-return-address".
>         * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
>         UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
>         ("*do_return"): Generate combined instructions according to key index.
>         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
>         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer
>         iterators.
>         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
>         * config/aarch64/aarch64.opt (msign-return-address=): New.
>         * doc/extend.texi (AArch64 Function Attributes): Documents
>         "sign-return-address=".
>         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".
> 
> gcc/testsuite/
> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
> 
>         * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>         * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.

I have a few comments on this patch, mostly around the wording of comments.

> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -3670,6 +3690,16 @@ aarch64_expand_epilogue (bool for_sibcall)
>        RTX_FRAME_RELATED_P (insn) = 1;
>      }
>  
> +  /* sibcall won't generate normally return, therefore we need to authenticate
> +     at here.  !TARGET_ARMV8_3 disallows GCC to use combined authentication
> +     instruction which we prefer, so we need to generate a seperate
> +     authentication. eh_return path can't do combined authentication, as it will
> +     do extra stack adjustment which updates CFA to EH handler's CFA while we
> +     want to use the CFA of the function which calls eh_return.  */

This comment does not read correctly to me, and I'm not sure what you
mean by it. I'd rewrite it as so:

  We prefer to emit the combined return/authenticate instruction RETAA,
  however there are three cases in which we must instead emit an explicit
  authentication instruction.

    1) Sibcalls don't return in a normal way, so if we're about to
       call one we must authenticate.
    2) The RETAA instruction is not available before ARMv8.3-A, so if we
       are generating code for !TARGET_ARMV8_3 we can't use it and must
       explicitly authenticate.
    3) On an eh_return path we make extra stack adjustments to update the
       canonical frame address to be the exception handler's CFA.  We want
       to authenticate using the CFA of the function which calls eh_return.

> +  if (aarch64_return_address_signing_enabled ()
> +      && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
> +    emit_insn (gen_autisp ());
> +
>    /* Stack adjustment for exception handler.  */
>    if (crtl->calls_eh_return)
>      {
> @@ -8894,6 +8924,9 @@ aarch64_override_options (void)
>      error ("Assembler does not support -mabi=ilp32");
>  #endif
>  
> +  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
> +    error ("Return address signing is only supported on LP64");

Should this be a sorry? I think this is something which has not been
implemented rather than a fundamental restriction.

Maybe:

  sorry ("Return address signing is only supported for -mabi=lp64");

Would be clear for our users.

> +
>    /* Make sure we properly set up the explicit options.  */
>    if ((aarch64_cpu_string && valid_cpu)
>         || (aarch64_tune_string && valid_tune))
> @@ -9277,6 +9310,8 @@ static const struct aarch64_attribute_info aarch64_attributes[] =
>    { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ },
>    { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune,
>       OPT_mtune_ },
> +  { "sign-return-address", aarch64_attr_enum, false, NULL,
> +     OPT_msign_return_address_ },
>    { NULL, aarch64_attr_custom, false, NULL, OPT____ }
>  };
>  
> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
> index bde42317f1bfd91a9d38a4cfa94d4cedd5246003..9b6f99dee3cecc0f15f24ec2375d3641fe03892d 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -67,6 +67,8 @@
>  )
>  
>  (define_c_enum "unspec" [
> +    UNSPEC_AUTI1716
> +    UNSPEC_AUTISP
>      UNSPEC_CASESI
>      UNSPEC_CRC32B
>      UNSPEC_CRC32CB
> @@ -106,6 +108,8 @@
>      UNSPEC_LD4_LANE
>      UNSPEC_MB
>      UNSPEC_NOP
> +    UNSPEC_PACI1716
> +    UNSPEC_PACISP
>      UNSPEC_PRLG_STK
>      UNSPEC_RBIT
>      UNSPEC_SCVTF
> @@ -135,6 +139,7 @@
>      UNSPEC_RSQRTE
>      UNSPEC_RSQRTS
>      UNSPEC_NZCV
> +    UNSPEC_XPACLRI
>  ])
>  
>  (define_c_enum "unspecv" [
> @@ -575,7 +580,14 @@
>  (define_insn "*do_return"
>    [(return)]
>    ""
> -  "ret"
> +  {
> +    if (aarch64_return_address_signing_enabled ()
> +	&& TARGET_ARMV8_3
> +	&& !crtl->calls_eh_return)
> +      return "retaa";
> +
> +    return "ret";
> +  }
>    [(set_attr "type" "branch")]
>  )
>  
> @@ -5341,6 +5353,31 @@
>    [(set_attr "length" "0")]
>  )
>  
> +;; Pointer authentication patterns are available for all architectures.  On
> +;; pre-ARMv8.3-A architectures they are NOP.  This let the user write portable
> +;; software which can get pointer authentication on new hardware while still
> +;; runs correctly on old hardware though no pointer authentication protection.

This comment should be reworded slightly:

;; Pointer authentication patterns are always provided.  In architecture
;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
;; This lets the user write portable software which authenticates pointers
;; when run on something which implements ARMv8.3-A, and which runs
;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
;; implemented.

Each of these new instructions could do with a comment explaining 

> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 30bdcf07ad8b1bd086bbb87acb36fb0333944087..47250ebb149bbde021ef64eba8e96e35c2623284 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -3513,6 +3513,12 @@ Specifies the core for which to tune the performance of this function and also
>  whose architectural features to use.  The behavior and valid arguments are the
>  same as for the @option{-mcpu=} command-line option.
>  
> +@item sign-return-address
> +@cindex @code{sign-return-address} function attribute, AArch64
> +Select the function scope we want to do return address signing on.  The behavior
> +and permissible arguments are the same as for the command-line option
> +@option{-msign-return-address=}.  The default value is @code{none}
> +

This could do with rewording slightly:

  Select the function scope on which return address signing will be applied.
  The behaviour and permissible arguments are the same as for the
  command-line option @option{-msign-return-address=}.  The default value is
  @code{none}.

>  @end table
>  
>  The above target attributes can be specified as follows:
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index aa0ac8b41128483be53645b91bdcead096582e23..2792dbd0a2d0ed9e3f46237685f8ae65a5d8bcf5 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -14044,6 +14044,13 @@ accessed using a single instruction and emitted after each function.  This
>  limits the maximum size of functions to 1MB.  This is enabled by default for
>  @option{-mcmodel=tiny}.
>  
> +@item -msign-return-address=@var{scope}
> +@opindex msign-return-address
> +Select the function scope we want to do return address signing on.  Permissible
> +values are @samp{none}, @samp{none-leaf} and @samp{all}.  @samp{none} means

Typo: s/none-leaf/non-leaf/

> +return address signing is disabled.  @samp{non-leaf} enables it for non-leaf
> +functions.  @samp{all} for all functions and is the default value.

This documentation does not follow the patch. In the patch, the default is
"none".

I'd reword this as so:

  Select the function scope on which return address signing will be applied.
  Permissible values are @samp{none}, which disables return address signing,
  @samp{non-leaf}, which enables pointer signing for functions which
  are not leaf functions, and @samp{all}, which enables pointer signing for
  all functions.  The default value is @samp{none}.

>  @end table
>  
>  @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
> diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..9a0332abd41ca6ae994e6ed72771fca8ee532cd0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
> @@ -0,0 +1,56 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -msign-return-address=all" } */
> +
> +int foo (int);
> +int bar (int, int);
> +
> +/* sibcall only.  */
> +int __attribute__ ((target ("arch=armv8.3-a")))
> +func1 (int a, int b)
> +{
> +  /* paciasp */
> +  return foo (a + b);
> +  /* autiasp */
> +}
> +
> +/* non-leaf function with sibcall.  */
> +int __attribute__ ((target ("arch=armv8.3-a")))
> +func2 (int a, int b)
> +{
> +  /* paciasp */
> +  if (a < b)
> +    return b;
> +
> +  a = foo (b);
> +
> +  return foo (a);
> +  /* autiasp */
> +}
> +
> +/* non-leaf function, legacy arch.  */
> +int __attribute__ ((target ("arch=armv8.2-a")))
> +func3 (int a, int b, int c)
> +{
> +  /* paciasp */
> +  return a + foo (b) + c;
> +  /* autiasp */
> +}
> +
> +/* non-leaf function.  */
> +int __attribute__ ((target ("arch=armv8.3-a")))
> +func4 (int a, int b, int c)
> +{
> +  /* paciasp */
> +  return a + foo (b) + c;
> +  /* retab */
> +}
> +
> +int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none")))
> +func4_disable (int a, int b, int c, int d)
> +{
> +  return c + bar (a, b) + d;
> +}
> +
> +/* { dg-final { scan-assembler-times "autiasp" 3 } } */
> +/* { dg-final { scan-assembler-times "paciasp" 4 } } */
> +/* { dg-final { scan-assembler-times "retaa" 1 } } */

These testcases should both be split.

As it stands, multiple buggy implementations could cancel each other out
when it comes to a scan-assembler-times and the test would still pass.

It would be much clearer to test each expected behaviour in a single file.

Thanks,
James

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

* Re: [2/5][AArch64] Generate dwarf information for -msign-return-address
  2017-01-06 11:47           ` [2/5][AArch64] Generate dwarf information for -msign-return-address Jiong Wang
@ 2017-01-13 16:09             ` Richard Earnshaw (lists)
  2017-01-13 18:02               ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-13 16:09 UTC (permalink / raw)
  To: Jiong Wang, gcc-patches; +Cc: James Greenhalgh

On 06/01/17 11:47, Jiong Wang wrote:
> On 11/11/16 18:22, Jiong Wang wrote:
>> This patch generate DWARF description for pointer authentication. 
>> DWARF value
>> expression is used to describe the authentication action.
>>
>> Please see the cover letter and AArch64 DWARF specification for the
>> semantics
>> of AArch64 DWARF operations.
>>
>> When authentication key index is A key, we use compact DWARF
>> description which
>> can largely save DWARF frame size, otherwise we fallback to general
>> operator.
>>
>>
>>
>> Example
>> ===
>>
>>      int
>>      cal (int a, int b, int c)
>>      {
>>        return a + dec (b) + c;
>>      }
>>
>> Compact DWARF description
>> (-march=armv8.3-a -msign-return-address)
>> ===
>>
>>    DW_CFA_advance_loc: 4 to 0000000000000004
>>    DW_CFA_val_expression: r30 (x30) (DW_OP_AARCH64_paciasp)
>>    DW_CFA_advance_loc: 4 to 0000000000000008
>>    DW_CFA_val_expression: r30 (x30) (DW_OP_AARCH64_paciasp_deref: -24)
>>
>> General DWARF description
>> ===
>> (-march=armv8.3-a -msign-return-address -mpauth-key=b_key)
>>
>>    DW_CFA_advance_loc: 4 to 0000000000000004
>>    DW_CFA_val_expression: r30 (x30) (DW_OP_breg30 (x30): 0;
>> DW_OP_AARCH64_pauth: 18)
>>    DW_CFA_advance_loc: 4 to 0000000000000008
>>    DW_CFA_val_expression: r30 (x30) (DW_OP_dup; DW_OP_const1s: -24;
>> DW_OP_plus; DW_OP_deref; DW_OP_AARCH64_pauth: 18)
>>
>>  From Linux kernel testing, -msign-return-address will introduce +24%
>> .debug_frame size increase when signing all functions and using compact
>> description, and about +45% .debug_frame size increase if using general
>> description.
>>
>>
>> gcc/
>> 2016-11-11  Jiong Wang<jiong.wang@arm.com>
>>
>>          * config/aarch64/aarch64.h (aarch64_pauth_action_type): New
>> enum.
>>          * config/aarch64/aarch64.c
>> (aarch64_attach_ra_auth_dwarf_note): New function.
>>          (aarch64_attach_ra_auth_dwarf_general): New function.
>>          (aarch64_attach_ra_auth_dwarf_shortcut): New function.
>>          (aarch64_save_callee_saves): Generate dwarf information if LR
>> is signed.
>>          (aarch64_expand_prologue): Likewise.
>>          (aarch64_expand_epilogue): Likewise.
> 
> This patch is an update on DWARF generation for return address signing.
> 
> According to new proposal, we simply needs to generate REG_CFA_WINDOW_SAVE
> annotation.
> 
> gcc/
> 
> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
> 
>         * config/aarch64/aarch64.c (aarch64_expand_prologue): Generate
> dwarf
>         annotation (REG_CFA_WINDOW_SAVE) for return address signing.
>         (aarch64_expand_epilogue): Likewise.
> 
> 

I don't think we should be overloading REG_CFA_WINDOW_SAVE internally in
the compiler -- it's one thing to do it in the dwarf output tables, but
quite another to be doing it elsewhere in the compiler.

Instead we should create a new reg note kind and use that, but in the
final dwarf output then emit the overloaded opcode.

R.

> 
> 2.patch
> 
> 
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 002895a167ce0deb45a5c1726527651af18bb4df..20ed79e5690f45ec121ef516245c686cc0cc82b5 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -3553,7 +3553,11 @@ aarch64_expand_prologue (void)
>  
>    /* Sign return address for functions.  */
>    if (aarch64_return_address_signing_enabled ())
> -    emit_insn (gen_pacisp ());
> +    {
> +      insn = emit_insn (gen_pacisp ());
> +      add_reg_note (insn, REG_CFA_WINDOW_SAVE, const0_rtx);
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +    }
>  
>    if (flag_stack_usage_info)
>      current_function_static_stack_size = frame_size;
> @@ -3698,7 +3702,11 @@ aarch64_expand_epilogue (bool for_sibcall)
>       want to use the CFA of the function which calls eh_return.  */
>    if (aarch64_return_address_signing_enabled ()
>        && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
> -    emit_insn (gen_autisp ());
> +    {
> +      insn = emit_insn (gen_autisp ());
> +      add_reg_note (insn, REG_CFA_WINDOW_SAVE, const0_rtx);
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +    }
>  
>    /* Stack adjustment for exception handler.  */
>    if (crtl->calls_eh_return)
> 

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

* Re: [3/5][AArch64] New builtins required by libgcc unwinder
  2017-01-06 11:47             ` [3/5][AArch64] New builtins required by libgcc unwinder Jiong Wang
@ 2017-01-13 16:14               ` Richard Earnshaw (lists)
  0 siblings, 0 replies; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-13 16:14 UTC (permalink / raw)
  To: Jiong Wang, gcc-patches; +Cc: James Greenhalgh

On 06/01/17 11:47, Jiong Wang wrote:
> On 11/11/16 18:22, Jiong Wang wrote:
>> This patch implements a few ARMv8.3-A new builtins for pointer sign and
>> authentication instructions.
>>
>> Currently, these builtins are supposed to be used by libgcc EH unwinder
>> only.  They are not public interface to external user.
>>
>> OK to install?
>>
>> gcc/
>> 2016-11-11  Jiong Wang<jiong.wang@arm.com>
>>
>>          * config/aarch64/aarch64-builtins.c (enum aarch64_builtins):
>> New entries
>>          for AARCH64_PAUTH_BUILTIN_PACI1716,
>> AARCH64_PAUTH_BUILTIN_AUTIA1716,
>>          AARCH64_PAUTH_BUILTIN_AUTIB1716, AARCH64_PAUTH_BUILTIN_XPACLRI.
>>          (aarch64_init_v8_3_builtins): New.
>>          (aarch64_init_builtins): Call aarch64_init_builtins.
>>          (arch64_expand_builtin): Expand new builtins.
>>
>>
> This patch is an update on builtins support.  All these builtins are to be
> internally used by libgcc only, so the updates only keeps those used.
> 
> OK for trunk?
> 
> gcc/
> 
> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
> 
>         * config/aarch64/aarch64-builtins.c (enum aarch64_builtins): New
> entries
>         for AARCH64_PAUTH_BUILTIN_XPACLRI, AARCH64_PAUTH_BUILTIN_PACIA1716,
>         AARCH64_PAUTH_BUILTIN_AUTIA1716);
>         (aarch64_init_pauth_hint_builtins): New.
>         (aarch64_init_builtins): Call aarch64_init_pauth_hint_builtins.
>         (aarch64_expand_builtin): Expand new builtins.
> 
> 
> 3.patch
> 
> 
> diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
> index 69fb756f0fbdc016f35ce1d08f2aaf092a034704..9ae9d9afc9c141235d7eee037d5571b9f35edc31 100644
> --- a/gcc/config/aarch64/aarch64-builtins.c
> +++ b/gcc/config/aarch64/aarch64-builtins.c
> @@ -376,6 +376,10 @@ enum aarch64_builtins
>    AARCH64_CRC32_BUILTIN_BASE,
>    AARCH64_CRC32_BUILTINS
>    AARCH64_CRC32_BUILTIN_MAX,
> +  /* ARMv8.3-A Pointer Authentication Builtins.  */
> +  AARCH64_PAUTH_BUILTIN_AUTIA1716,
> +  AARCH64_PAUTH_BUILTIN_PACIA1716,
> +  AARCH64_PAUTH_BUILTIN_XPACLRI,
>    AARCH64_BUILTIN_MAX
>  };
>  
> @@ -923,6 +927,33 @@ aarch64_init_fp16_types (void)
>    aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
>  }
>  
> +/* Pointer authentication builtins that will become NOP on legacy platform.
> +   Currently, these builtins are for internal use only (libgcc EH unwinder).  */
> +
> +void
> +aarch64_init_pauth_hint_builtins (void)
> +{
> +  /* Pointer Authentication builtins.  */
> +  tree ftype_pointer_auth
> +    = build_function_type_list (ptr_type_node, ptr_type_node,
> +				unsigned_intDI_type_node, NULL_TREE);
> +  tree ftype_pointer_strip
> +    = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
> +
> +  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
> +    = add_builtin_function ("__builtin_aarch64_autia1716", ftype_pointer_auth,
> +			    AARCH64_PAUTH_BUILTIN_AUTIA1716, BUILT_IN_MD, NULL,
> +			    NULL_TREE);
> +  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIA1716]
> +    = add_builtin_function ("__builtin_aarch64_pacia1716", ftype_pointer_auth,
> +			    AARCH64_PAUTH_BUILTIN_PACIA1716, BUILT_IN_MD, NULL,
> +			    NULL_TREE);
> +  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
> +    = add_builtin_function ("__builtin_aarch64_xpaclri", ftype_pointer_strip,
> +			    AARCH64_PAUTH_BUILTIN_XPACLRI, BUILT_IN_MD, NULL,
> +			    NULL_TREE);
> +}
> +
>  void
>  aarch64_init_builtins (void)
>  {
> @@ -951,6 +982,10 @@ aarch64_init_builtins (void)
>  
>    aarch64_init_crc32_builtins ();
>    aarch64_init_builtin_rsqrt ();
> +
> +/* Initialize pointer authentication builtins which are backed by instructions
> +   in NOP encoding space.  */
> +  aarch64_init_pauth_hint_builtins ();
>  }
>  
>  tree
> @@ -1293,6 +1328,43 @@ aarch64_expand_builtin (tree exp,
>  	}
>        emit_insn (pat);
>        return target;

Add a blank line before case statements.


OK with that change.

R.

> +    case AARCH64_PAUTH_BUILTIN_AUTIA1716:
> +    case AARCH64_PAUTH_BUILTIN_PACIA1716:
> +    case AARCH64_PAUTH_BUILTIN_XPACLRI:
> +      arg0 = CALL_EXPR_ARG (exp, 0);
> +      op0 = force_reg (Pmode, expand_normal (arg0));
> +
> +      if (!target)
> +	target = gen_reg_rtx (Pmode);
> +      else
> +	target = force_reg (Pmode, target);
> +
> +      emit_move_insn (target, op0);
> +
> +      if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
> +	{
> +	  rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
> +	  icode = CODE_FOR_xpaclri;
> +	  emit_move_insn (lr, op0);
> +	  emit_insn (GEN_FCN (icode) ());
> +	  emit_move_insn (target, lr);
> +	}
> +      else
> +	{
> +	  tree arg1 = CALL_EXPR_ARG (exp, 1);
> +	  rtx op1 = force_reg (Pmode, expand_normal (arg1));
> +	  icode = (fcode == AARCH64_PAUTH_BUILTIN_PACIA1716
> +		   ? CODE_FOR_paci1716 : CODE_FOR_auti1716);
> +
> +	  rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
> +	  rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
> +	  emit_move_insn (x17_reg, op0);
> +	  emit_move_insn (x16_reg, op1);
> +	  emit_insn (GEN_FCN (icode) ());
> +	  emit_move_insn (target, x17_reg);
> +	}
> +
> +      return target;
>      }
>  
>    if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
> 

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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-13 16:05           ` James Greenhalgh
@ 2017-01-13 17:05             ` Jiong Wang
  2017-01-16 11:25               ` James Greenhalgh
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-13 17:05 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, Richard Earnshaw (lists), nd

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

On 13/01/17 16:04, James Greenhalgh wrote:
> On Fri, Jan 06, 2017 at 11:47:07AM +0000, Jiong Wang wrote:
>> On 11/11/16 18:22, Jiong Wang wrote:
>> gcc/
>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>
>>          * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
>>          * config/aarch64/aarch64-protos.h
>>          (aarch64_return_address_signing_enabled): New declaration.
>>          * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
>>          New function.
>>          (aarch64_expand_prologue): Sign return address before it's pushed onto
>>          stack.
>>          (aarch64_expand_epilogue): Authenticate return address fetched from
>>          stack.
>>          (aarch64_override_options): Sanity check for ILP32 and ISA level.
>>          (aarch64_attributes): New function attributes for "sign-return-address".
>>          * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
>>          UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
>>          ("*do_return"): Generate combined instructions according to key index.
>>          ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
>>          * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer
>>          iterators.
>>          (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
>>          * config/aarch64/aarch64.opt (msign-return-address=): New.
>>          * doc/extend.texi (AArch64 Function Attributes): Documents
>>          "sign-return-address=".
>>          * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".
>>
>> gcc/testsuite/
>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>
>>          * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>>          * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.
> I have a few comments on this patch

All fixed.  New patch attached.

gcc/
2017-01-13  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
         * config/aarch64/aarch64-protos.h
         (aarch64_return_address_signing_enabled): New declaration.
         * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
         New function.
         (aarch64_expand_prologue): Sign return address before it's pushed onto
         stack.
         (aarch64_expand_epilogue): Authenticate return address fetched from
         stack.
         (aarch64_override_options): Sanity check for ILP32 and ISA level.
         (aarch64_attributes): New function attributes for "sign-return-address".
         * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
         UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
         ("*do_return"): Generate combined instructions according to key index.
         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer
         iterators.
         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
         * config/aarch64/aarch64.opt (msign-return-address=): New.
         * doc/extend.texi (AArch64 Function Attributes): Documents
         "sign-return-address=".
         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".

gcc/testsuite/
2017-01-13  Jiong Wang  <jiong.wang@arm.com>

         * gcc.target/aarch64/return_address_sign_1.c: New testcase for no
         combined instructions.
         * gcc.target/aarch64/return_address_sign_2.c: New testcase for combined
         instructions.
         * gcc.target/aarch64/return_address_sign_3.c: New testcase for disable
         of pointer authentication.


[-- Attachment #2: 1.patch --]
[-- Type: text/x-diff, Size: 13538 bytes --]

diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
index 9f37b9b..ba5d052 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -71,4 +71,14 @@ enum aarch64_code_model {
   AARCH64_CMODEL_LARGE
 };
 
+/* Function types -msign-return-address should sign.  */
+enum aarch64_function_type {
+  /* Don't sign any function.  */
+  AARCH64_FUNCTION_NONE,
+  /* Non-leaf functions.  */
+  AARCH64_FUNCTION_NON_LEAF,
+  /* All functions.  */
+  AARCH64_FUNCTION_ALL
+};
+
 #endif
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 29a3bd7..632dd47 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -386,6 +386,7 @@ void aarch64_emit_call_insn (rtx);
 void aarch64_register_pragmas (void);
 void aarch64_relayout_simd_types (void);
 void aarch64_reset_previous_fndecl (void);
+bool aarch64_return_address_signing_enabled (void);
 void aarch64_save_restore_target_globals (tree);
 
 /* Initialize builtins for SIMD intrinsics.  */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 9dd75b0..3bcad76 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3117,6 +3117,22 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
     }
 }
 
+/* Return TRUE if return address signing should be enabled for one function,
+   otherwise return FALSE.  */
+
+bool
+aarch64_return_address_signing_enabled (void)
+{
+  /* This function should only be called after frame laid out.   */
+  gcc_assert (cfun->machine->frame.laid_out);
+
+  /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
+     if it's LR is pushed onto stack.  */
+  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
+	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
+	      && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));
+}
+
 /* Emit code to save the callee-saved registers from register number START
    to LIMIT to the stack at the location starting at offset START_OFFSET,
    skipping any write-back candidates if SKIP_WB is true.  */
@@ -3535,6 +3551,10 @@ aarch64_expand_prologue (void)
   unsigned reg2 = cfun->machine->frame.wb_candidate2;
   rtx_insn *insn;
 
+  /* Sign return address for functions.  */
+  if (aarch64_return_address_signing_enabled ())
+    emit_insn (gen_pacisp ());
+
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size;
 
@@ -3670,6 +3690,25 @@ aarch64_expand_epilogue (bool for_sibcall)
       RTX_FRAME_RELATED_P (insn) = 1;
     }
 
+  /* We prefer to emit the combined return/authenticate instruction RETAA,
+     however there are three cases in which we must instead emit an explicit
+     authentication instruction.
+
+	1) Sibcalls don't return in a normal way, so if we're about to call one
+	   we must authenticate.
+
+	2) The RETAA instruction is not available before ARMv8.3-A, so if we are
+	   generating code for !TARGET_ARMV8_3 we can't use it and must
+	   explicitly authenticate.
+
+	3) On an eh_return path we make extra stack adjustments to update the
+	   canonical frame address to be the exception handler's CFA.  We want
+	   to authenticate using the CFA of the function which calls eh_return.
+    */
+  if (aarch64_return_address_signing_enabled ()
+      && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
+    emit_insn (gen_autisp ());
+
   /* Stack adjustment for exception handler.  */
   if (crtl->calls_eh_return)
     {
@@ -8894,6 +8933,9 @@ aarch64_override_options (void)
     error ("Assembler does not support -mabi=ilp32");
 #endif
 
+  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
+    sorry ("Return address signing is only supported for -mabi=lp64");
+
   /* Make sure we properly set up the explicit options.  */
   if ((aarch64_cpu_string && valid_cpu)
        || (aarch64_tune_string && valid_tune))
@@ -9277,6 +9319,8 @@ static const struct aarch64_attribute_info aarch64_attributes[] =
   { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ },
   { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune,
      OPT_mtune_ },
+  { "sign-return-address", aarch64_attr_enum, false, NULL,
+     OPT_msign_return_address_ },
   { NULL, aarch64_attr_custom, false, NULL, OPT____ }
 };
 
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index bde4231..5dc68b7 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -67,6 +67,8 @@
 )
 
 (define_c_enum "unspec" [
+    UNSPEC_AUTI1716
+    UNSPEC_AUTISP
     UNSPEC_CASESI
     UNSPEC_CRC32B
     UNSPEC_CRC32CB
@@ -106,6 +108,8 @@
     UNSPEC_LD4_LANE
     UNSPEC_MB
     UNSPEC_NOP
+    UNSPEC_PACI1716
+    UNSPEC_PACISP
     UNSPEC_PRLG_STK
     UNSPEC_RBIT
     UNSPEC_SCVTF
@@ -135,6 +139,7 @@
     UNSPEC_RSQRTE
     UNSPEC_RSQRTS
     UNSPEC_NZCV
+    UNSPEC_XPACLRI
 ])
 
 (define_c_enum "unspecv" [
@@ -575,7 +580,14 @@
 (define_insn "*do_return"
   [(return)]
   ""
-  "ret"
+  {
+    if (aarch64_return_address_signing_enabled ()
+	&& TARGET_ARMV8_3
+	&& !crtl->calls_eh_return)
+      return "retaa";
+
+    return "ret";
+  }
   [(set_attr "type" "branch")]
 )
 
@@ -5341,6 +5353,36 @@
   [(set_attr "length" "0")]
 )
 
+;; Pointer authentication patterns are always provided.  In architecture
+;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
+;; This lets the user write portable software which authenticates pointers
+;; when run on something which implements ARMv8.3-A, and which runs
+;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
+;; implemented.
+
+;; Signing/Authenticating R30 using SP as the salt.
+(define_insn "<pauth_mnem_prefix>sp"
+  [(set (reg:DI R30_REGNUM)
+	(unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
+  ""
+  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
+)
+
+;; Signing/Authenticating X17 using X16 as the salt.
+(define_insn "<pauth_mnem_prefix>1716"
+  [(set (reg:DI R17_REGNUM)
+	(unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
+  ""
+  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
+)
+
+;; Stripping the signature in R30.
+(define_insn "xpaclri"
+  [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
+  ""
+  "hint\t7 // xpaclri"
+)
+
 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
 ;; all of memory.  This blocks insns from being moved across this point.
 
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 56b920d..5436884 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -149,6 +149,23 @@ mpc-relative-literal-loads
 Target Report Save Var(pcrelative_literal_loads) Init(2) Save
 PC relative literal loads.
 
+msign-return-address=
+Target RejectNegative Report Joined Enum(aarch64_ra_sign_scope_t) Var(aarch64_ra_sign_scope) Init(AARCH64_FUNCTION_NONE) Save
+Select return address signing scope.
+
+Enum
+Name(aarch64_ra_sign_scope_t) Type(enum aarch64_function_type)
+Supported AArch64 return address signing scope (for use with -msign-return-address= option):
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(none) Value(AARCH64_FUNCTION_NONE)
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(non-leaf) Value(AARCH64_FUNCTION_NON_LEAF)
+
+EnumValue
+Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL)
+
 mlow-precision-recip-sqrt
 Common Var(flag_mrecip_low_precision_sqrt) Optimization
 Enable the reciprocal square root approximation.  Enabling this reduces
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index e2377c1..c59d31e 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -1032,6 +1032,10 @@
 (define_int_iterator FMAXMIN_UNS [UNSPEC_FMAX UNSPEC_FMIN
 				  UNSPEC_FMAXNM UNSPEC_FMINNM])
 
+(define_int_iterator PAUTH_LR_SP [UNSPEC_PACISP UNSPEC_AUTISP])
+
+(define_int_iterator PAUTH_17_16 [UNSPEC_PACI1716 UNSPEC_AUTI1716])
+
 (define_int_iterator VQDMULH [UNSPEC_SQDMULH UNSPEC_SQRDMULH])
 
 (define_int_iterator USSUQADD [UNSPEC_SUQADD UNSPEC_USQADD])
@@ -1218,6 +1222,18 @@
 				  (UNSPEC_FCVTZS "fcvtzs")
 				  (UNSPEC_FCVTZU "fcvtzu")])
 
+;; Pointer authentication mnemonic prefix.
+(define_int_attr pauth_mnem_prefix [(UNSPEC_PACISP "paci")
+				    (UNSPEC_AUTISP "auti")
+				    (UNSPEC_PACI1716 "paci")
+				    (UNSPEC_AUTI1716 "auti")])
+
+;; Pointer authentication HINT number for NOP space instructions using A Key.
+(define_int_attr pauth_hint_num_a [(UNSPEC_PACISP "25")
+				    (UNSPEC_AUTISP "29")
+				    (UNSPEC_PACI1716 "8")
+				    (UNSPEC_AUTI1716 "12")])
+
 (define_int_attr perm_insn [(UNSPEC_ZIP1 "zip") (UNSPEC_ZIP2 "zip")
 			    (UNSPEC_TRN1 "trn") (UNSPEC_TRN2 "trn")
 			    (UNSPEC_UZP1 "uzp") (UNSPEC_UZP2 "uzp")])
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 30bdcf0..4516a86 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3513,6 +3513,12 @@ Specifies the core for which to tune the performance of this function and also
 whose architectural features to use.  The behavior and valid arguments are the
 same as for the @option{-mcpu=} command-line option.
 
+@item sign-return-address
+@cindex @code{sign-return-address} function attribute, AArch64
+Select the function scope on which return address signing will be applied.  The
+behaviour and permissible arguments are the same as for the command-line option
+@option{-msign-return-address=}.  The default value is @code{none}.
+
 @end table
 
 The above target attributes can be specified as follows:
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index aa0ac8b..c75d4b3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14044,6 +14044,14 @@ accessed using a single instruction and emitted after each function.  This
 limits the maximum size of functions to 1MB.  This is enabled by default for
 @option{-mcmodel=tiny}.
 
+@item -msign-return-address=@var{scope}
+@opindex msign-return-address
+Select the function scope on which return address signing will be applied.
+Permissible values are @samp{none}, which disables return address signing,
+@samp{non-leaf}, which enables pointer signing for functions which are not leaf
+functions, and @samp{all}, which enables pointer signing for all functions.  The
+default value is @samp{none}.
+
 @end table
 
 @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
new file mode 100644
index 0000000..fda72a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
@@ -0,0 +1,51 @@
+/* Testing return address signing where no combined instructions used.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=all" } */
+
+int foo (int);
+
+/* sibcall only.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b)
+{
+  /* paciasp */
+  return foo (a + b);
+  /* autiasp */
+}
+
+/* non-leaf function with sibcall.  */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func2 (int a, int b)
+{
+  /* paciasp */
+  if (a < b)
+    return b;
+
+  a = foo (b);
+
+  return foo (a);
+  /* autiasp */
+}
+
+/* non-leaf function, legacy arch.  */
+int __attribute__ ((target ("arch=armv8.2-a")))
+func3 (int a, int b, int c)
+{
+  /* paciasp */
+  return a + foo (b) + c;
+  /* autiasp */
+}
+
+/* eh_return.  */
+void __attribute__ ((target ("arch=armv8.3-a")))
+func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
+{
+  /* paciasp */
+  *ptr = imm1 + foo (imm1) + imm2;
+  __builtin_eh_return (offset, handler);
+  /* autiasp */
+  return;
+}
+
+/* { dg-final { scan-assembler-times "autiasp" 4 } } */
+/* { dg-final { scan-assembler-times "paciasp" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
new file mode 100644
index 0000000..54fe47a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
@@ -0,0 +1,17 @@
+/* Testing return address signing where combined instructions used.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=all" } */
+
+int foo (int);
+int bar (int, int);
+
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b, int c)
+{
+  /* paciasp */
+  return a + foo (b) + c;
+  /* retaa */
+}
+
+/* { dg-final { scan-assembler-times "paciasp" 1 } } */
+/* { dg-final { scan-assembler-times "retaa" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
new file mode 100644
index 0000000..adc5eff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
@@ -0,0 +1,21 @@
+/* Testing the disable of return address signing.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=all" } */
+
+int bar (int, int);
+
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=non-leaf")))
+func1_leaf (int a, int b, int c, int d)
+{
+  return a + b + c + d;
+}
+
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none")))
+func2_none (int a, int b, int c, int d)
+{
+  return c + bar (a, b) + d;
+}
+
+/* { dg-final { scan-assembler-not "paciasp" } } */
+/* { dg-final { scan-assembler-not "autiasp" } } */
+/* { dg-final { scan-assembler-not "retaa" } } */

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

* Re: [2/5][AArch64] Generate dwarf information for -msign-return-address
  2017-01-13 16:09             ` Richard Earnshaw (lists)
@ 2017-01-13 18:02               ` Jiong Wang
  2017-01-16 14:29                 ` [2/5][DWARF] Generate dwarf information for -msign-return-address by introducing new DWARF mapping hook Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-13 18:02 UTC (permalink / raw)
  To: Richard Earnshaw (lists), gcc-patches; +Cc: James Greenhalgh

On 13/01/17 16:09, Richard Earnshaw (lists) wrote:
> On 06/01/17 11:47, Jiong Wang wrote:
>>
>> This patch is an update on DWARF generation for return address signing.
>>
>> According to new proposal, we simply needs to generate REG_CFA_WINDOW_SAVE
>> annotation.
>>
>> gcc/
>>
>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>
>>          * config/aarch64/aarch64.c (aarch64_expand_prologue): Generate
>> dwarf
>>          annotation (REG_CFA_WINDOW_SAVE) for return address signing.
>>          (aarch64_expand_epilogue): Likewise.
>>
>>
> I don't think we should be overloading REG_CFA_WINDOW_SAVE internally in
> the compiler -- it's one thing to do it in the dwarf output tables, but
> quite another to be doing it elsewhere in the compiler.
>
> Instead we should create a new reg note kind and use that, but in the
> final dwarf output then emit the overloaded opcode.

I can see the reason for doing this is if you want to seperate the interpretion
of GCC CFA reg-note and the final DWARF CFA operation.  My understanding is all
reg notes defined in gcc/reg-note.def should have general meaning, even the
CFA_WINDOW_SAVE.  For those which are architecture specific we might need a
mechanism to define them in backend only.
    
For general reg-notes in gcc/reg-note.def, they are not always have the
corresponding standard DWARF CFA operation, for example CFA_WINDOW_SAVE,
therefore if we want to achieve what you described, I think we also need to
define a new target hook which maps a GCC CFA reg-note into architecture DWARF
CFA operation.

Regards,
Jiong


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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-13 17:05             ` Jiong Wang
@ 2017-01-16 11:25               ` James Greenhalgh
  0 siblings, 0 replies; 75+ messages in thread
From: James Greenhalgh @ 2017-01-16 11:25 UTC (permalink / raw)
  To: Jiong Wang; +Cc: gcc-patches, Richard Earnshaw (lists), nd

On Fri, Jan 13, 2017 at 05:05:43PM +0000, Jiong Wang wrote:
> On 13/01/17 16:04, James Greenhalgh wrote:
> >On Fri, Jan 06, 2017 at 11:47:07AM +0000, Jiong Wang wrote:
> >>On 11/11/16 18:22, Jiong Wang wrote:
> >>gcc/
> >>2017-01-06  Jiong Wang  <jiong.wang@arm.com>
> >>
> >>         * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
> >>         * config/aarch64/aarch64-protos.h
> >>         (aarch64_return_address_signing_enabled): New declaration.
> >>         * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
> >>         New function.
> >>         (aarch64_expand_prologue): Sign return address before it's pushed onto
> >>         stack.
> >>         (aarch64_expand_epilogue): Authenticate return address fetched from
> >>         stack.
> >>         (aarch64_override_options): Sanity check for ILP32 and ISA level.
> >>         (aarch64_attributes): New function attributes for "sign-return-address".
> >>         * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
> >>         UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
> >>         ("*do_return"): Generate combined instructions according to key index.
> >>         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
> >>         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer
> >>         iterators.
> >>         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
> >>         * config/aarch64/aarch64.opt (msign-return-address=): New.
> >>         * doc/extend.texi (AArch64 Function Attributes): Documents
> >>         "sign-return-address=".
> >>         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".
> >>
> >>gcc/testsuite/
> >>2017-01-06  Jiong Wang  <jiong.wang@arm.com>
> >>
> >>         * gcc.target/aarch64/return_address_sign_1.c: New testcase.
> >>         * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.
> >I have a few comments on this patch
> 
> All fixed.  New patch attached.

OK with two trivial changes (see below).

We're late in stage 3, but as this option is default off and doesn't affect
the rest of the AArch64 port I think it will be OK to take at this stage.
Because of the timing, please give Richard/Marcus a 24hr chance to comment
on whether they think this is acceptable.

> gcc/
> 2017-01-13  Jiong Wang  <jiong.wang@arm.com>
> 
>         * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
>         * config/aarch64/aarch64-protos.h
>         (aarch64_return_address_signing_enabled): New declaration.
>         * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
>         New function.
>         (aarch64_expand_prologue): Sign return address before it's pushed onto
>         stack.
>         (aarch64_expand_epilogue): Authenticate return address fetched from
>         stack.
>         (aarch64_override_options): Sanity check for ILP32 and ISA level.
>         (aarch64_attributes): New function attributes for "sign-return-address".
>         * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
>         UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
>         ("*do_return"): Generate combined instructions according to key index.
>         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
>         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer
>         iterators.
>         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
>         * config/aarch64/aarch64.opt (msign-return-address=): New.
>         * doc/extend.texi (AArch64 Function Attributes): Documents
>         "sign-return-address=".
>         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".
> 
> gcc/testsuite/
> 2017-01-13  Jiong Wang  <jiong.wang@arm.com>
> 
>         * gcc.target/aarch64/return_address_sign_1.c: New testcase for no
>         combined instructions.
>         * gcc.target/aarch64/return_address_sign_2.c: New testcase for combined
>         instructions.
>         * gcc.target/aarch64/return_address_sign_3.c: New testcase for disable
>         of pointer authentication.
> 

> diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
> index 9f37b9b..ba5d052 100644
> --- a/gcc/config/aarch64/aarch64-opts.h
> +++ b/gcc/config/aarch64/aarch64-opts.h
> @@ -71,4 +71,14 @@ enum aarch64_code_model {
>    AARCH64_CMODEL_LARGE
>  };
>  
> +/* Function types -msign-return-address should sign.  */
> +enum aarch64_function_type {
> +  /* Don't sign any function.  */
> +  AARCH64_FUNCTION_NONE,
> +  /* Non-leaf functions.  */
> +  AARCH64_FUNCTION_NON_LEAF,
> +  /* All functions.  */
> +  AARCH64_FUNCTION_ALL
> +};
> +
>  #endif
> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
> index 29a3bd7..632dd47 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -386,6 +386,7 @@ void aarch64_emit_call_insn (rtx);
>  void aarch64_register_pragmas (void);
>  void aarch64_relayout_simd_types (void);
>  void aarch64_reset_previous_fndecl (void);
> +bool aarch64_return_address_signing_enabled (void);
>  void aarch64_save_restore_target_globals (tree);
>  
>  /* Initialize builtins for SIMD intrinsics.  */
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 9dd75b0..3bcad76 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -3117,6 +3117,22 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
>      }
>  }
>  
> +/* Return TRUE if return address signing should be enabled for one function,

s/one/the current/

> +   otherwise return FALSE.  */
> +
> +bool
> +aarch64_return_address_signing_enabled (void)
> +{
> +  /* This function should only be called after frame laid out.   */
> +  gcc_assert (cfun->machine->frame.laid_out);
> +
> +  /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
> +     if it's LR is pushed onto stack.  */
> +  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
> +	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
> +	      && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));
> +}
> +
>  /* Emit code to save the callee-saved registers from register number START
>     to LIMIT to the stack at the location starting at offset START_OFFSET,
>     skipping any write-back candidates if SKIP_WB is true.  */
> @@ -3535,6 +3551,10 @@ aarch64_expand_prologue (void)
>    unsigned reg2 = cfun->machine->frame.wb_candidate2;
>    rtx_insn *insn;
>  
> +  /* Sign return address for functions.  */
> +  if (aarch64_return_address_signing_enabled ())
> +    emit_insn (gen_pacisp ());
> +
>    if (flag_stack_usage_info)
>      current_function_static_stack_size = frame_size;
>  
> @@ -3670,6 +3690,25 @@ aarch64_expand_epilogue (bool for_sibcall)
>        RTX_FRAME_RELATED_P (insn) = 1;
>      }
>  
> +  /* We prefer to emit the combined return/authenticate instruction RETAA,
> +     however there are three cases in which we must instead emit an explicit
> +     authentication instruction.
> +
> +	1) Sibcalls don't return in a normal way, so if we're about to call one
> +	   we must authenticate.
> +
> +	2) The RETAA instruction is not available before ARMv8.3-A, so if we are
> +	   generating code for !TARGET_ARMV8_3 we can't use it and must
> +	   explicitly authenticate.
> +
> +	3) On an eh_return path we make extra stack adjustments to update the
> +	   canonical frame address to be the exception handler's CFA.  We want
> +	   to authenticate using the CFA of the function which calls eh_return.
> +    */
> +  if (aarch64_return_address_signing_enabled ()
> +      && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
> +    emit_insn (gen_autisp ());
> +
>    /* Stack adjustment for exception handler.  */
>    if (crtl->calls_eh_return)
>      {
> @@ -8894,6 +8933,9 @@ aarch64_override_options (void)
>      error ("Assembler does not support -mabi=ilp32");
>  #endif
>  
> +  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
> +    sorry ("Return address signing is only supported for -mabi=lp64");
> +
>    /* Make sure we properly set up the explicit options.  */
>    if ((aarch64_cpu_string && valid_cpu)
>         || (aarch64_tune_string && valid_tune))
> @@ -9277,6 +9319,8 @@ static const struct aarch64_attribute_info aarch64_attributes[] =
>    { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ },
>    { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune,
>       OPT_mtune_ },
> +  { "sign-return-address", aarch64_attr_enum, false, NULL,
> +     OPT_msign_return_address_ },
>    { NULL, aarch64_attr_custom, false, NULL, OPT____ }
>  };
>  
> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
> index bde4231..5dc68b7 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -67,6 +67,8 @@
>  )
>  
>  (define_c_enum "unspec" [
> +    UNSPEC_AUTI1716
> +    UNSPEC_AUTISP
>      UNSPEC_CASESI
>      UNSPEC_CRC32B
>      UNSPEC_CRC32CB
> @@ -106,6 +108,8 @@
>      UNSPEC_LD4_LANE
>      UNSPEC_MB
>      UNSPEC_NOP
> +    UNSPEC_PACI1716
> +    UNSPEC_PACISP
>      UNSPEC_PRLG_STK
>      UNSPEC_RBIT
>      UNSPEC_SCVTF
> @@ -135,6 +139,7 @@
>      UNSPEC_RSQRTE
>      UNSPEC_RSQRTS
>      UNSPEC_NZCV
> +    UNSPEC_XPACLRI
>  ])
>  
>  (define_c_enum "unspecv" [
> @@ -575,7 +580,14 @@
>  (define_insn "*do_return"
>    [(return)]
>    ""
> -  "ret"
> +  {
> +    if (aarch64_return_address_signing_enabled ()
> +	&& TARGET_ARMV8_3
> +	&& !crtl->calls_eh_return)
> +      return "retaa";
> +
> +    return "ret";
> +  }
>    [(set_attr "type" "branch")]
>  )
>  
> @@ -5341,6 +5353,36 @@
>    [(set_attr "length" "0")]
>  )
>  
> +;; Pointer authentication patterns are always provided.  In architecture
> +;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
> +;; This lets the user write portable software which authenticates pointers
> +;; when run on something which implements ARMv8.3-A, and which runs
> +;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
> +;; implemented.
> +
> +;; Signing/Authenticating R30 using SP as the salt.

Newline between comment and pattern.

> +(define_insn "<pauth_mnem_prefix>sp"
> +  [(set (reg:DI R30_REGNUM)
> +	(unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
> +  ""
> +  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
> +)
> +
> +;; Signing/Authenticating X17 using X16 as the salt.

Newline between comment and pattern.

> +(define_insn "<pauth_mnem_prefix>1716"
> +  [(set (reg:DI R17_REGNUM)
> +	(unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
> +  ""
> +  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
> +)
> +
> +;; Stripping the signature in R30.

Newline between comment and pattern.

> +(define_insn "xpaclri"
> +  [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
> +  ""
> +  "hint\t7 // xpaclri"
> +)
> +
>  ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
>  ;; all of memory.  This blocks insns from being moved across this point.
  
Thanks,
James

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

* Re: [2/5][DWARF] Generate dwarf information for -msign-return-address by introducing new DWARF mapping hook
  2017-01-13 18:02               ` Jiong Wang
@ 2017-01-16 14:29                 ` Jiong Wang
  2017-01-17 13:57                   ` Richard Earnshaw (lists)
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-16 14:29 UTC (permalink / raw)
  To: Richard Earnshaw (lists), gcc-patches
  Cc: James Greenhalgh, Jason Merrill, Jeff Law

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

On 13/01/17 18:02, Jiong Wang wrote:
> On 13/01/17 16:09, Richard Earnshaw (lists) wrote:
>> On 06/01/17 11:47, Jiong Wang wrote:
>>>
>>> This patch is an update on DWARF generation for return address signing.
>>>
>>> According to new proposal, we simply needs to generate 
>>> REG_CFA_WINDOW_SAVE
>>> annotation.
>>>
>>> gcc/
>>>
>>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>>
>>>          * config/aarch64/aarch64.c (aarch64_expand_prologue): Generate
>>> dwarf
>>>          annotation (REG_CFA_WINDOW_SAVE) for return address signing.
>>>          (aarch64_expand_epilogue): Likewise.
>>>
>>>
>> I don't think we should be overloading REG_CFA_WINDOW_SAVE internally in
>> the compiler -- it's one thing to do it in the dwarf output tables, but
>> quite another to be doing it elsewhere in the compiler.
>>
>> Instead we should create a new reg note kind and use that, but in the
>> final dwarf output then emit the overloaded opcode.
>
> I can see the reason for doing this is if you want to seperate the 
> interpretion
> of GCC CFA reg-note and the final DWARF CFA operation.  My 
> understanding is all
> reg notes defined in gcc/reg-note.def should have general meaning, 
> even the
> CFA_WINDOW_SAVE.  For those which are architecture specific we might 
> need a
> mechanism to define them in backend only.
>    For general reg-notes in gcc/reg-note.def, they are not always have 
> the
> corresponding standard DWARF CFA operation, for example CFA_WINDOW_SAVE,
> therefore if we want to achieve what you described, I think we also 
> need to
> define a new target hook which maps a GCC CFA reg-note into 
> architecture DWARF
> CFA operation.
>
> Regards,
> Jiong
>
>
Here is the patch.

Introduced one new target hook TARGET_DWARF_MAP_REGNOTE_TO_CFA.  The purpose is
to allow GCC to map DWARF CFA reg notes in reg-note.def, which looks to me have
generic meaning, into target private DWARF CFI if there is no standard DWARF CFI
mapping.

One new GCC reg-note REG_TOGGLE_RA_MANGLE introduced as well, currently, it's
only used by AArch64 to implement return address signing and is mapped to
AArch64's target private DWARF CFI.

Does this approach and implementation looks OK?

I can come up with seperate patches to define this hook on Sparc for
CFA_WINDOW_SAVE, and to remove redundant including of dwarf2.h although there is
"ifdef" protector in header file.

The default hook implementation "default_dwarf_map_regnote_to_cfa" in
targhooks.c used the types "enum reg_note" and "enum dwarf_call_frame_info"
which is not included in coretypes.h thus this patch has several change in
header files.  I have done X86 bootstrap to make sure no build breakage.  I'd
appreciate there is better ideas to handle these type define.

Thanks.

gcc/ChangeLog:

2017-01-16  Jiong Wang  <jiong.wang@arm.com>

         * target.def (dwarf_map_regnote_to_cfa): New hook.
         * targhooks.c (default_dwarf_map_regnote_to_cfa): Default implementation
         for TARGET_DWARF_MAP_REGNOTE_TO_CFA.
         * targhooks.h (default_dwarf_map_regnote_to_cfa): New declaration.
         * rtl.h (enum reg_note): Move enum reg_note to...
         * coretypes.h: ... here.
         (dwarf2.h): New include file.
         * reg-notes.def (CFA_TOGGLE_RA_MANGLE): New reg-note.
         * combine-stack-adj.c (no_unhandled_cfa): Handle
         REG_CFA_TOGGLE_RA_MANGLE.
         * dwarf2cfi.c (dwarf2out_frame_debug_cfa_toggle_ra_mangle): New
         function.
         (dwarf2out_frame_debug): Handle REG_CFA_TOGGLE_RA_MANGLE.
         * doc/tm.texi: Regenerate.
         * doc/tm.texi.in: Documents TARGET_DWARF_MAP_REGNOTE_TO_CFA.
         * config/aarch64/aarch64.c (aarch64_map_regnote_to_cfa): Implements
         TARGET_DWARF_MAP_REGNOTE_TO_CFA.
         (aarch64_expand_prologue): Generate DWARF info for return address
         signing.
         (aarch64_expand_epilogue): Likewise.
         (TARGET_DWARF_MAP_REGNOTE_TO_CFA): Define.


[-- Attachment #2: 1.patch --]
[-- Type: text/x-diff, Size: 8520 bytes --]

diff --git a/gcc/target.def b/gcc/target.def
index 0443390..6aaa9e6 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3995,6 +3995,14 @@ the CFI label attached to the insn, @var{pattern} is the pattern of\n\
 the insn and @var{index} is @code{UNSPEC_INDEX} or @code{UNSPECV_INDEX}.",
  void, (const char *label, rtx pattern, int index), NULL)
 
+/* This target hook allows the backend to map GCC DWARF CFA reg-note to
+   architecture specific DWARF call frame instruction.  */
+DEFHOOK
+(dwarf_map_regnote_to_cfa,
+ "Maps the incoming GCC DWARF CFA reg-note to architecture specific DWARF call\
+ frame instruction.",
+ enum dwarf_call_frame_info, (enum reg_note), default_dwarf_map_regnote_to_cfa)
+
 /* ??? Documenting this hook requires a GFDL license grant.  */
 DEFHOOK_UNDOC
 (stdarg_optimize_hook,
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 2f2abd3..df07911 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -1711,6 +1711,17 @@ default_dwarf_frame_reg_mode (int regno)
   return save_mode;
 }
 
+/* Determine the correct mode for a Dwarf frame register that represents
+   register REGNO.  */
+
+enum dwarf_call_frame_info
+default_dwarf_map_regnote_to_cfa (enum reg_note note)
+{
+  const char *name = GET_REG_NOTE_NAME (note);
+  error ("This target doesn't support %s", name);
+  gcc_unreachable ();
+}
+
 /* To be used by targets where reg_raw_mode doesn't return the right
    mode for registers used in apply_builtin_return and apply_builtin_arg.  */
 
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index a5565f5..6b1c47f 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -221,6 +221,8 @@ extern int default_jump_align_max_skip (rtx_insn *);
 extern section * default_function_section(tree decl, enum node_frequency freq,
 					  bool startup, bool exit);
 extern machine_mode default_dwarf_frame_reg_mode (int);
+extern enum dwarf_call_frame_info default_dwarf_map_regnote_to_cfa
+  (enum reg_note note);
 extern machine_mode default_get_reg_raw_mode (int);
 extern bool default_keep_leaf_when_profiled ();
 
diff --git a/gcc/rtl.h b/gcc/rtl.h
index b9a7989..2d3bcb9 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1543,14 +1543,6 @@ inline rtvec rtx_jump_table_data::get_labels () const
    question.  */
 #define ENTRY_VALUE_EXP(RTX) (RTL_CHECKC1 (RTX, 0, ENTRY_VALUE).rt_rtx)
 
-enum reg_note
-{
-#define DEF_REG_NOTE(NAME) NAME,
-#include "reg-notes.def"
-#undef DEF_REG_NOTE
-  REG_NOTE_MAX
-};
-
 /* Define macros to extract and insert the reg-note kind in an EXPR_LIST.  */
 #define REG_NOTE_KIND(LINK) ((enum reg_note) GET_MODE (LINK))
 #define PUT_REG_NOTE_KIND(LINK, KIND) \
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 8eb33cc..915ac5a 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -253,6 +253,14 @@ enum warn_strict_overflow_code
   WARN_STRICT_OVERFLOW_MAGNITUDE = 5
 };
 
+enum reg_note
+{
+#define DEF_REG_NOTE(NAME) NAME,
+#include "reg-notes.def"
+#undef DEF_REG_NOTE
+  REG_NOTE_MAX
+};
+
 /* The type of an alias set.  Code currently assumes that variables of
    this type can take the values 0 (the alias set which aliases
    everything) and -1 (sometimes indicating that the alias set is
@@ -364,6 +372,7 @@ typedef unsigned char uchar;
 #include "signop.h"
 #include "wide-int.h" 
 #include "double-int.h"
+#include "dwarf2.h"
 #include "real.h"
 #include "fixed-value.h"
 #include "hash-table.h"
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index ead4a9f..175da11 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -177,6 +177,11 @@ REG_NOTE (CFA_WINDOW_SAVE)
    the rest of the compiler as a CALL_INSN.  */
 REG_NOTE (CFA_FLUSH_QUEUE)
 
+/* Attached to insns that are RTX_FRAME_RELATED_P, toggling the mangling status
+   of return address.  Currently it's only used by AArch64.  The argument is
+   ignored.  */
+REG_NOTE (CFA_TOGGLE_RA_MANGLE)
+
 /* Indicates what exception region an INSN belongs in.  This is used
    to indicate what region to which a call may throw.  REGION 0
    indicates that a call cannot throw at all.  REGION -1 indicates
diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
index 20cd59a..9ec14a3 100644
--- a/gcc/combine-stack-adj.c
+++ b/gcc/combine-stack-adj.c
@@ -208,6 +208,7 @@ no_unhandled_cfa (rtx_insn *insn)
       case REG_CFA_SET_VDRAP:
       case REG_CFA_WINDOW_SAVE:
       case REG_CFA_FLUSH_QUEUE:
+      case REG_CFA_TOGGLE_RA_MANGLE:
 	return false;
       }
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 2748e2f..3f574b3 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -1336,6 +1336,17 @@ dwarf2out_frame_debug_cfa_window_save (void)
   add_cfi (cfi);
 }
 
+/* A subroutine of dwarf2out_frame_debug, process a REG_TOGGLE_RA_MANGLE.  */
+
+static void
+dwarf2out_frame_debug_cfa_toggle_ra_mangle (void)
+{
+  dw_cfi_ref cfi = new_cfi ();
+
+  cfi->dw_cfi_opc = targetm.dwarf_map_regnote_to_cfa (REG_CFA_TOGGLE_RA_MANGLE);
+  add_cfi (cfi);
+}
+
 /* Record call frame debugging information for an expression EXPR,
    which either sets SP or FP (adjusting how we calculate the frame
    address) or saves a register to the stack or another register.
@@ -2108,6 +2119,11 @@ dwarf2out_frame_debug (rtx_insn *insn)
 	handled_one = true;
 	break;
 
+      case REG_CFA_TOGGLE_RA_MANGLE:
+	dwarf2out_frame_debug_cfa_toggle_ra_mangle ();
+	handled_one = true;
+	break;
+
       default:
 	break;
       }
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 4b62e05..07227fc 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -9776,6 +9776,10 @@ exceptions are enabled, GCC will output this information not matter
 how you define @code{DWARF2_FRAME_INFO}.
 @end defmac
 
+@deftypefn {Target Hook} {enum dwarf_call_frame_info} TARGET_DWARF_MAP_REGNOTE_TO_CFA (enum @var{reg_note})
+Maps the incoming GCC DWARF CFA reg-note to architecture specific DWARF call frame instruction.
+@end deftypefn
+
 @deftypefn {Target Hook} {enum unwind_info_type} TARGET_DEBUG_UNWIND_INFO (void)
 This hook defines the mechanism that will be used for describing frame
 unwind information to the debugger.  Normally the hook will return
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index ea74d37..bdb3c51 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7078,6 +7078,8 @@ exceptions are enabled, GCC will output this information not matter
 how you define @code{DWARF2_FRAME_INFO}.
 @end defmac
 
+@hook TARGET_DWARF_MAP_REGNOTE_TO_CFA
+
 @hook TARGET_DEBUG_UNWIND_INFO
 
 @defmac DWARF2_ASM_LINE_DEBUG_INFO

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 3bcad76..7c16457 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -983,6 +983,18 @@ aarch64_dbx_register_number (unsigned regno)
    return DWARF_FRAME_REGISTERS;
 }
 
+/* Implement target hook TARGET_DWARF_MAP_REGNOTE_TO_CFA.
+   Maps GCC reg-note NOTE into AArch64's architecture DWARF CFA instruction.
+   Currently, only REG_CFA_TOGGLE_RA_MANGLE is expected to reach here.  */
+
+enum dwarf_call_frame_info
+aarch64_map_regnote_to_cfa (enum reg_note note)
+{
+  gcc_assert (note == REG_CFA_TOGGLE_RA_MANGLE);
+
+  return DW_CFA_GNU_window_save;
+}
+
 /* Return TRUE if MODE is any of the large INT modes.  */
 static bool
 aarch64_vect_struct_mode_p (machine_mode mode)
@@ -3553,7 +3565,11 @@ aarch64_expand_prologue (void)
 
   /* Sign return address for functions.  */
   if (aarch64_return_address_signing_enabled ())
-    emit_insn (gen_pacisp ());
+    {
+      insn = emit_insn (gen_pacisp ());
+      add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size;
@@ -3707,7 +3723,11 @@ aarch64_expand_epilogue (bool for_sibcall)
     */
   if (aarch64_return_address_signing_enabled ()
       && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
-    emit_insn (gen_autisp ());
+    {
+      insn = emit_insn (gen_autisp ());
+      add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   /* Stack adjustment for exception handler.  */
   if (crtl->calls_eh_return)
@@ -14730,6 +14750,9 @@ aarch64_excess_precision (enum excess_precision_type type)
 #undef TARGET_C_EXCESS_PRECISION
 #define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
 
+#undef TARGET_DWARF_MAP_REGNOTE_TO_CFA
+#define TARGET_DWARF_MAP_REGNOTE_TO_CFA aarch64_map_regnote_to_cfa
+
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
 

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

* Re: [2/5][DWARF] Generate dwarf information for -msign-return-address by introducing new DWARF mapping hook
  2017-01-16 14:29                 ` [2/5][DWARF] Generate dwarf information for -msign-return-address by introducing new DWARF mapping hook Jiong Wang
@ 2017-01-17 13:57                   ` Richard Earnshaw (lists)
  2017-01-17 15:11                     ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-17 13:57 UTC (permalink / raw)
  To: Jiong Wang, gcc-patches; +Cc: James Greenhalgh, Jason Merrill, Jeff Law

On 16/01/17 14:29, Jiong Wang wrote:
> On 13/01/17 18:02, Jiong Wang wrote:
>> On 13/01/17 16:09, Richard Earnshaw (lists) wrote:
>>> On 06/01/17 11:47, Jiong Wang wrote:
>>>>
>>>> This patch is an update on DWARF generation for return address signing.
>>>>
>>>> According to new proposal, we simply needs to generate
>>>> REG_CFA_WINDOW_SAVE
>>>> annotation.
>>>>
>>>> gcc/
>>>>
>>>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>>>
>>>>          * config/aarch64/aarch64.c (aarch64_expand_prologue): Generate
>>>> dwarf
>>>>          annotation (REG_CFA_WINDOW_SAVE) for return address signing.
>>>>          (aarch64_expand_epilogue): Likewise.
>>>>
>>>>
>>> I don't think we should be overloading REG_CFA_WINDOW_SAVE internally in
>>> the compiler -- it's one thing to do it in the dwarf output tables, but
>>> quite another to be doing it elsewhere in the compiler.
>>>
>>> Instead we should create a new reg note kind and use that, but in the
>>> final dwarf output then emit the overloaded opcode.
>>
>> I can see the reason for doing this is if you want to seperate the
>> interpretion
>> of GCC CFA reg-note and the final DWARF CFA operation.  My
>> understanding is all
>> reg notes defined in gcc/reg-note.def should have general meaning,
>> even the
>> CFA_WINDOW_SAVE.  For those which are architecture specific we might
>> need a
>> mechanism to define them in backend only.
>>    For general reg-notes in gcc/reg-note.def, they are not always have
>> the
>> corresponding standard DWARF CFA operation, for example CFA_WINDOW_SAVE,
>> therefore if we want to achieve what you described, I think we also
>> need to
>> define a new target hook which maps a GCC CFA reg-note into
>> architecture DWARF
>> CFA operation.
>>
>> Regards,
>> Jiong
>>
>>
> Here is the patch.
> 

Hmm, I really wasn't expecting any more than something like the
following in dwarf2cfi.c:

@@ -2098,7 +2098,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
        handled_one = true;
        break;

+      case REG_CFA_TOGGLE_RA_MANGLE:
       case REG_CFA_WINDOW_SAVE:
+       /* We overload both of these operations onto the same DWARF
opcode.  */
        dwarf2out_frame_debug_cfa_window_save ();
        handled_one = true;
        break;

This keeps the two reg notes separate within the compiler, but emits the
same dwarf operation during final output.  This avoids the need for new
hooks or anything more complicated.

R.

> Introduced one new target hook TARGET_DWARF_MAP_REGNOTE_TO_CFA.  The
> purpose is
> to allow GCC to map DWARF CFA reg notes in reg-note.def, which looks to
> me have
> generic meaning, into target private DWARF CFI if there is no standard
> DWARF CFI
> mapping.
> 
> One new GCC reg-note REG_TOGGLE_RA_MANGLE introduced as well, currently,
> it's
> only used by AArch64 to implement return address signing and is mapped to
> AArch64's target private DWARF CFI.
> 
> Does this approach and implementation looks OK?
> 
> I can come up with seperate patches to define this hook on Sparc for
> CFA_WINDOW_SAVE, and to remove redundant including of dwarf2.h although
> there is
> "ifdef" protector in header file.
> 
> The default hook implementation "default_dwarf_map_regnote_to_cfa" in
> targhooks.c used the types "enum reg_note" and "enum dwarf_call_frame_info"
> which is not included in coretypes.h thus this patch has several change in
> header files.  I have done X86 bootstrap to make sure no build
> breakage.  I'd
> appreciate there is better ideas to handle these type define.
> 
> Thanks.
> 
> gcc/ChangeLog:
> 
> 2017-01-16  Jiong Wang  <jiong.wang@arm.com>
> 
>         * target.def (dwarf_map_regnote_to_cfa): New hook.
>         * targhooks.c (default_dwarf_map_regnote_to_cfa): Default
> implementation
>         for TARGET_DWARF_MAP_REGNOTE_TO_CFA.
>         * targhooks.h (default_dwarf_map_regnote_to_cfa): New declaration.
>         * rtl.h (enum reg_note): Move enum reg_note to...
>         * coretypes.h: ... here.
>         (dwarf2.h): New include file.
>         * reg-notes.def (CFA_TOGGLE_RA_MANGLE): New reg-note.
>         * combine-stack-adj.c (no_unhandled_cfa): Handle
>         REG_CFA_TOGGLE_RA_MANGLE.
>         * dwarf2cfi.c (dwarf2out_frame_debug_cfa_toggle_ra_mangle): New
>         function.
>         (dwarf2out_frame_debug): Handle REG_CFA_TOGGLE_RA_MANGLE.
>         * doc/tm.texi: Regenerate.
>         * doc/tm.texi.in: Documents TARGET_DWARF_MAP_REGNOTE_TO_CFA.
>         * config/aarch64/aarch64.c (aarch64_map_regnote_to_cfa): Implements
>         TARGET_DWARF_MAP_REGNOTE_TO_CFA.
>         (aarch64_expand_prologue): Generate DWARF info for return address
>         signing.
>         (aarch64_expand_epilogue): Likewise.
>         (TARGET_DWARF_MAP_REGNOTE_TO_CFA): Define.
> 
> 
> 1.patch
> 
> 
> diff --git a/gcc/target.def b/gcc/target.def
> index 0443390..6aaa9e6 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -3995,6 +3995,14 @@ the CFI label attached to the insn, @var{pattern} is the pattern of\n\
>  the insn and @var{index} is @code{UNSPEC_INDEX} or @code{UNSPECV_INDEX}.",
>   void, (const char *label, rtx pattern, int index), NULL)
>  
> +/* This target hook allows the backend to map GCC DWARF CFA reg-note to
> +   architecture specific DWARF call frame instruction.  */
> +DEFHOOK
> +(dwarf_map_regnote_to_cfa,
> + "Maps the incoming GCC DWARF CFA reg-note to architecture specific DWARF call\
> + frame instruction.",
> + enum dwarf_call_frame_info, (enum reg_note), default_dwarf_map_regnote_to_cfa)
> +
>  /* ??? Documenting this hook requires a GFDL license grant.  */
>  DEFHOOK_UNDOC
>  (stdarg_optimize_hook,
> diff --git a/gcc/targhooks.c b/gcc/targhooks.c
> index 2f2abd3..df07911 100644
> --- a/gcc/targhooks.c
> +++ b/gcc/targhooks.c
> @@ -1711,6 +1711,17 @@ default_dwarf_frame_reg_mode (int regno)
>    return save_mode;
>  }
>  
> +/* Determine the correct mode for a Dwarf frame register that represents
> +   register REGNO.  */
> +
> +enum dwarf_call_frame_info
> +default_dwarf_map_regnote_to_cfa (enum reg_note note)
> +{
> +  const char *name = GET_REG_NOTE_NAME (note);
> +  error ("This target doesn't support %s", name);
> +  gcc_unreachable ();
> +}
> +
>  /* To be used by targets where reg_raw_mode doesn't return the right
>     mode for registers used in apply_builtin_return and apply_builtin_arg.  */
>  
> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
> index a5565f5..6b1c47f 100644
> --- a/gcc/targhooks.h
> +++ b/gcc/targhooks.h
> @@ -221,6 +221,8 @@ extern int default_jump_align_max_skip (rtx_insn *);
>  extern section * default_function_section(tree decl, enum node_frequency freq,
>  					  bool startup, bool exit);
>  extern machine_mode default_dwarf_frame_reg_mode (int);
> +extern enum dwarf_call_frame_info default_dwarf_map_regnote_to_cfa
> +  (enum reg_note note);
>  extern machine_mode default_get_reg_raw_mode (int);
>  extern bool default_keep_leaf_when_profiled ();
>  
> diff --git a/gcc/rtl.h b/gcc/rtl.h
> index b9a7989..2d3bcb9 100644
> --- a/gcc/rtl.h
> +++ b/gcc/rtl.h
> @@ -1543,14 +1543,6 @@ inline rtvec rtx_jump_table_data::get_labels () const
>     question.  */
>  #define ENTRY_VALUE_EXP(RTX) (RTL_CHECKC1 (RTX, 0, ENTRY_VALUE).rt_rtx)
>  
> -enum reg_note
> -{
> -#define DEF_REG_NOTE(NAME) NAME,
> -#include "reg-notes.def"
> -#undef DEF_REG_NOTE
> -  REG_NOTE_MAX
> -};
> -
>  /* Define macros to extract and insert the reg-note kind in an EXPR_LIST.  */
>  #define REG_NOTE_KIND(LINK) ((enum reg_note) GET_MODE (LINK))
>  #define PUT_REG_NOTE_KIND(LINK, KIND) \
> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
> index 8eb33cc..915ac5a 100644
> --- a/gcc/coretypes.h
> +++ b/gcc/coretypes.h
> @@ -253,6 +253,14 @@ enum warn_strict_overflow_code
>    WARN_STRICT_OVERFLOW_MAGNITUDE = 5
>  };
>  
> +enum reg_note
> +{
> +#define DEF_REG_NOTE(NAME) NAME,
> +#include "reg-notes.def"
> +#undef DEF_REG_NOTE
> +  REG_NOTE_MAX
> +};
> +
>  /* The type of an alias set.  Code currently assumes that variables of
>     this type can take the values 0 (the alias set which aliases
>     everything) and -1 (sometimes indicating that the alias set is
> @@ -364,6 +372,7 @@ typedef unsigned char uchar;
>  #include "signop.h"
>  #include "wide-int.h" 
>  #include "double-int.h"
> +#include "dwarf2.h"
>  #include "real.h"
>  #include "fixed-value.h"
>  #include "hash-table.h"
> diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
> index ead4a9f..175da11 100644
> --- a/gcc/reg-notes.def
> +++ b/gcc/reg-notes.def
> @@ -177,6 +177,11 @@ REG_NOTE (CFA_WINDOW_SAVE)
>     the rest of the compiler as a CALL_INSN.  */
>  REG_NOTE (CFA_FLUSH_QUEUE)
>  
> +/* Attached to insns that are RTX_FRAME_RELATED_P, toggling the mangling status
> +   of return address.  Currently it's only used by AArch64.  The argument is
> +   ignored.  */
> +REG_NOTE (CFA_TOGGLE_RA_MANGLE)
> +
>  /* Indicates what exception region an INSN belongs in.  This is used
>     to indicate what region to which a call may throw.  REGION 0
>     indicates that a call cannot throw at all.  REGION -1 indicates
> diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
> index 20cd59a..9ec14a3 100644
> --- a/gcc/combine-stack-adj.c
> +++ b/gcc/combine-stack-adj.c
> @@ -208,6 +208,7 @@ no_unhandled_cfa (rtx_insn *insn)
>        case REG_CFA_SET_VDRAP:
>        case REG_CFA_WINDOW_SAVE:
>        case REG_CFA_FLUSH_QUEUE:
> +      case REG_CFA_TOGGLE_RA_MANGLE:
>  	return false;
>        }
> diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
> index 2748e2f..3f574b3 100644
> --- a/gcc/dwarf2cfi.c
> +++ b/gcc/dwarf2cfi.c
> @@ -1336,6 +1336,17 @@ dwarf2out_frame_debug_cfa_window_save (void)
>    add_cfi (cfi);
>  }
>  
> +/* A subroutine of dwarf2out_frame_debug, process a REG_TOGGLE_RA_MANGLE.  */
> +
> +static void
> +dwarf2out_frame_debug_cfa_toggle_ra_mangle (void)
> +{
> +  dw_cfi_ref cfi = new_cfi ();
> +
> +  cfi->dw_cfi_opc = targetm.dwarf_map_regnote_to_cfa (REG_CFA_TOGGLE_RA_MANGLE);
> +  add_cfi (cfi);
> +}
> +
>  /* Record call frame debugging information for an expression EXPR,
>     which either sets SP or FP (adjusting how we calculate the frame
>     address) or saves a register to the stack or another register.
> @@ -2108,6 +2119,11 @@ dwarf2out_frame_debug (rtx_insn *insn)
>  	handled_one = true;
>  	break;
>  
> +      case REG_CFA_TOGGLE_RA_MANGLE:
> +	dwarf2out_frame_debug_cfa_toggle_ra_mangle ();
> +	handled_one = true;
> +	break;
> +
>        default:
>  	break;
>        }
> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> index 4b62e05..07227fc 100644
> --- a/gcc/doc/tm.texi
> +++ b/gcc/doc/tm.texi
> @@ -9776,6 +9776,10 @@ exceptions are enabled, GCC will output this information not matter
>  how you define @code{DWARF2_FRAME_INFO}.
>  @end defmac
>  
> +@deftypefn {Target Hook} {enum dwarf_call_frame_info} TARGET_DWARF_MAP_REGNOTE_TO_CFA (enum @var{reg_note})
> +Maps the incoming GCC DWARF CFA reg-note to architecture specific DWARF call frame instruction.
> +@end deftypefn
> +
>  @deftypefn {Target Hook} {enum unwind_info_type} TARGET_DEBUG_UNWIND_INFO (void)
>  This hook defines the mechanism that will be used for describing frame
>  unwind information to the debugger.  Normally the hook will return
> diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> index ea74d37..bdb3c51 100644
> --- a/gcc/doc/tm.texi.in
> +++ b/gcc/doc/tm.texi.in
> @@ -7078,6 +7078,8 @@ exceptions are enabled, GCC will output this information not matter
>  how you define @code{DWARF2_FRAME_INFO}.
>  @end defmac
>  
> +@hook TARGET_DWARF_MAP_REGNOTE_TO_CFA
> +
>  @hook TARGET_DEBUG_UNWIND_INFO
>  
>  @defmac DWARF2_ASM_LINE_DEBUG_INFO
> 
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 3bcad76..7c16457 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -983,6 +983,18 @@ aarch64_dbx_register_number (unsigned regno)
>     return DWARF_FRAME_REGISTERS;
>  }
>  
> +/* Implement target hook TARGET_DWARF_MAP_REGNOTE_TO_CFA.
> +   Maps GCC reg-note NOTE into AArch64's architecture DWARF CFA instruction.
> +   Currently, only REG_CFA_TOGGLE_RA_MANGLE is expected to reach here.  */
> +
> +enum dwarf_call_frame_info
> +aarch64_map_regnote_to_cfa (enum reg_note note)
> +{
> +  gcc_assert (note == REG_CFA_TOGGLE_RA_MANGLE);
> +
> +  return DW_CFA_GNU_window_save;
> +}
> +
>  /* Return TRUE if MODE is any of the large INT modes.  */
>  static bool
>  aarch64_vect_struct_mode_p (machine_mode mode)
> @@ -3553,7 +3565,11 @@ aarch64_expand_prologue (void)
>  
>    /* Sign return address for functions.  */
>    if (aarch64_return_address_signing_enabled ())
> -    emit_insn (gen_pacisp ());
> +    {
> +      insn = emit_insn (gen_pacisp ());
> +      add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +    }
>  
>    if (flag_stack_usage_info)
>      current_function_static_stack_size = frame_size;
> @@ -3707,7 +3723,11 @@ aarch64_expand_epilogue (bool for_sibcall)
>      */
>    if (aarch64_return_address_signing_enabled ()
>        && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
> -    emit_insn (gen_autisp ());
> +    {
> +      insn = emit_insn (gen_autisp ());
> +      add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +    }
>  
>    /* Stack adjustment for exception handler.  */
>    if (crtl->calls_eh_return)
> @@ -14730,6 +14750,9 @@ aarch64_excess_precision (enum excess_precision_type type)
>  #undef TARGET_C_EXCESS_PRECISION
>  #define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
>  
> +#undef TARGET_DWARF_MAP_REGNOTE_TO_CFA
> +#define TARGET_DWARF_MAP_REGNOTE_TO_CFA aarch64_map_regnote_to_cfa
> +
>  #undef  TARGET_EXPAND_BUILTIN
>  #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
>  
> 

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

* Re: [2/5][DWARF] Generate dwarf information for -msign-return-address by introducing new DWARF mapping hook
  2017-01-17 13:57                   ` Richard Earnshaw (lists)
@ 2017-01-17 15:11                     ` Jiong Wang
  2017-01-19 14:19                       ` Richard Earnshaw (lists)
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-17 15:11 UTC (permalink / raw)
  To: Richard Earnshaw (lists), gcc-patches
  Cc: James Greenhalgh, Jason Merrill, Jeff Law

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



On 17/01/17 13:57, Richard Earnshaw (lists) wrote:
> On 16/01/17 14:29, Jiong Wang wrote:
>>
>>> I can see the reason for doing this is if you want to seperate the
>>> interpretion
>>> of GCC CFA reg-note and the final DWARF CFA operation.  My
>>> understanding is all
>>> reg notes defined in gcc/reg-note.def should have general meaning,
>>> even the
>>> CFA_WINDOW_SAVE.  For those which are architecture specific we might
>>> need a
>>> mechanism to define them in backend only.
>>>     For general reg-notes in gcc/reg-note.def, they are not always have
>>> the
>>> corresponding standard DWARF CFA operation, for example CFA_WINDOW_SAVE,
>>> therefore if we want to achieve what you described, I think we also
>>> need to
>>> define a new target hook which maps a GCC CFA reg-note into
>>> architecture DWARF
>>> CFA operation.
>>>
>>> Regards,
>>> Jiong
>>>
>>>
>> Here is the patch.
>>
> Hmm, I really wasn't expecting any more than something like the
> following in dwarf2cfi.c:
>
> @@ -2098,7 +2098,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
>          handled_one = true;
>          break;
>
> +      case REG_CFA_TOGGLE_RA_MANGLE:
>         case REG_CFA_WINDOW_SAVE:
> +       /* We overload both of these operations onto the same DWARF
> opcode.  */
>          dwarf2out_frame_debug_cfa_window_save ();
>          handled_one = true;
>          break;
>
> This keeps the two reg notes separate within the compiler, but emits the
> same dwarf operation during final output.  This avoids the need for new
> hooks or anything more complicated.

This was my initial thoughts and the patch would be very small as you've
demonstrated.  I later moved to this complexer patch as I am thinking it's
better to completely treat notes in reg-notes.def as having generic meaning and
maps them to standard DWARF CFA if there is, otherwise maps them to target
private DWARF CFA through this new hook.  This give other targets a chance to
map, for example REG_CFA_TOGGLE_RA_MANGLE, to their architecture DWARF number.

The introduction of new hook looks be very low risk in this stage, the only
painful thing is the header file needs to be reorganized as we need to use some
DWARF type and reg-note type in targhooks.c.

Anyway, if the new hook patch is too heavy, I have attached the the simplified
version which simply defines the new REG_CFA_TOGGLE_RA_MANGLE and maps to same
code of REG_CFA_WINDOW_SAVE.


gcc/

2017-01-17  Jiong Wang  <jiong.wang@arm.com>

         * reg-notes.def (CFA_TOGGLE_RA_MANGLE): New reg-note.
         * combine-stack-adj.c (no_unhandled_cfa): Handle
         REG_CFA_TOGGLE_RA_MANGLE.
         * dwarf2cfi.c
         (dwarf2out_frame_debug): Handle REG_CFA_TOGGLE_RA_MANGLE.
         * config/aarch64/aarch64.c (aarch64_expand_prologue): Generates DWARF
         info for return address signing.
         (aarch64_expand_epilogue): Likewise.


[-- Attachment #2: k.patch --]
[-- Type: text/x-diff, Size: 2806 bytes --]

diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
index 20cd59ad08329e9f4f834bfc01d6f9ccc4485283..9ec14a3e44363f35f6419c38233ce5eebddd3458 100644
--- a/gcc/combine-stack-adj.c
+++ b/gcc/combine-stack-adj.c
@@ -208,6 +208,7 @@ no_unhandled_cfa (rtx_insn *insn)
       case REG_CFA_SET_VDRAP:
       case REG_CFA_WINDOW_SAVE:
       case REG_CFA_FLUSH_QUEUE:
+      case REG_CFA_TOGGLE_RA_MANGLE:
 	return false;
       }
 
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 3bcad76b68b6ea7c9d75d150d79c45fb74d6bf0d..6451b08191cf1a44aed502930da8603111f6e8ca 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3553,7 +3553,11 @@ aarch64_expand_prologue (void)
 
   /* Sign return address for functions.  */
   if (aarch64_return_address_signing_enabled ())
-    emit_insn (gen_pacisp ());
+    {
+      insn = emit_insn (gen_pacisp ());
+      add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size;
@@ -3707,7 +3711,11 @@ aarch64_expand_epilogue (bool for_sibcall)
     */
   if (aarch64_return_address_signing_enabled ()
       && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
-    emit_insn (gen_autisp ());
+    {
+      insn = emit_insn (gen_autisp ());
+      add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   /* Stack adjustment for exception handler.  */
   if (crtl->calls_eh_return)
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 2748e2fa48e4794181496b26df9b51b7e51e7b84..2a527c9fecab091dccb417492e5dbb2ade244be2 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -2098,7 +2098,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
 	handled_one = true;
 	break;
 
+      case REG_CFA_TOGGLE_RA_MANGLE:
       case REG_CFA_WINDOW_SAVE:
+	/* We overload both of these operations onto the same DWARF opcode.  */
 	dwarf2out_frame_debug_cfa_window_save ();
 	handled_one = true;
 	break;
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index ead4a9f58e8621288ee765e029c673640fdf38f4..175da119b6a534b04bd154f2c69dd087afd474ea 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -177,6 +177,11 @@ REG_NOTE (CFA_WINDOW_SAVE)
    the rest of the compiler as a CALL_INSN.  */
 REG_NOTE (CFA_FLUSH_QUEUE)
 
+/* Attached to insns that are RTX_FRAME_RELATED_P, toggling the mangling status
+   of return address.  Currently it's only used by AArch64.  The argument is
+   ignored.  */
+REG_NOTE (CFA_TOGGLE_RA_MANGLE)
+
 /* Indicates what exception region an INSN belongs in.  This is used
    to indicate what region to which a call may throw.  REGION 0
    indicates that a call cannot throw at all.  REGION -1 indicates

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

* [AArch64] Accelerate -fstack-protector through pointer authentication extension
  2016-11-11 18:37                 ` [9/9][RFC][AArch64] Accelerate -fstack-protector through pointer authentication extension Jiong Wang
@ 2017-01-18 17:10                   ` Jiong Wang
  2017-02-07 16:06                     ` Ping [AArch64] Accelerate -fstack-protector Jiong Wang
  2017-02-15 16:06                     ` [AArch64] Accelerate -fstack-protector through pointer authentication extension Richard Earnshaw (lists)
  0 siblings, 2 replies; 75+ messages in thread
From: Jiong Wang @ 2017-01-18 17:10 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh

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

> NOTE, this approach however requires DWARF change as the original LR is signed,
> the binary needs new libgcc to make sure c++ eh works correctly.  Given this
> acceleration already needs the user specify -mstack-protector-dialect=pauth
> which means the target platform largely should have install new libgcc, otherwise
> you can't utilize new pointer authentication features.
>
> gcc/
> 2016-11-11  Jiong Wang  <jiong.wang@arm.com>
>
>         * config/aarch64/aarch64-opts.h (aarch64_stack_protector_type): New
>         enum.
>         (aarch64_layout_frame): Swap callees and locals when
>         -mstack-protector-dialect=pauth specified.
>         (aarch64_expand_prologue): Use AARCH64_PAUTH_SSP_OR_RA_SIGN instead
>         of AARCH64_ENABLE_RETURN_ADDRESS_SIGN.
>         (aarch64_expand_epilogue): Likewise.
>         * config/aarch64/aarch64.md (*do_return): Likewise.
>         (aarch64_override_options): Sanity check for ILP32 and TARGET_PAUTH.
>         * config/aarch64/aarch64.h (AARCH64_PAUTH_SSP_OPTION, AARCH64_PAUTH_SSP,
>         AARCH64_PAUTH_SSP_OR_RA_SIGN, LINK_SSP_SPEC): New defines.
>         * config/aarch64/aarch64.opt (-mstack-protector-dialect=): New option.
>         * doc/invoke.texi (AArch64 Options): Documents
>         -mstack-protector-dialect=.
>
                                                          
Patch updated to migrate to TARGET_STACK_PROTECT_RUNTIME_ENABLED_P.

aarch64 cross check OK with the following options enabled on all testcases.
   
   -fstack-protector-all -mstack-protector-pauth

OK for trunk?
                                                                     
gcc/
2017-01-18  Jiong Wang  <jiong.wang@arm.com>
    
         * config/aarch64/aarch64-protos.h
         (aarch64_pauth_stack_protector_enabled): New declaration.
         * config/aarch64/aarch64.c (aarch64_layout_frame): Swap callee-save area
         and locals area when aarch64_pauth_stack_protector_enabled returns true.
         (aarch64_stack_protect_runtime_enabled): New function.
         (aarch64_pauth_stack_protector_enabled): New function.
         (aarch64_return_address_signing_enabled): Enabled by
         aarch64_pauth_stack_protector_enabled.
         (aarch64_override_options): Sanity check for -mstack-protector-pauth.
         (TARGET_STACK_PROTECT_RUNTIME_ENABLED_P): Define.
         * config/aarch64/aarch64.h (LINK_SSP_SPEC): Likewise.
         * config/aarch64/aarch64.opt (-mstack-protector-pauth): New option.
         * doc/invoke.texi (AArch64 Options): Documents -mstack-protector-pauth.

gcc/testsuite/
         * gcc.target/aarch64/stack_protector_1.c: New test.


[-- Attachment #2: 1.patch --]
[-- Type: text/x-diff, Size: 7895 bytes --]

diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 632dd4768d82c340ae4e9b4a93206743756c06e7..a3ad623eef498d00b52d24bf02a5748fad576c3d 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -383,6 +383,7 @@ void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,
 void aarch64_init_expanders (void);
 void aarch64_init_simd_builtins (void);
 void aarch64_emit_call_insn (rtx);
+bool aarch64_pauth_stack_protector_enabled (void);
 void aarch64_register_pragmas (void);
 void aarch64_relayout_simd_types (void);
 void aarch64_reset_previous_fndecl (void);
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 3718ad1b3bf27c6bdb9e74831fd660e617cccbde..dd742d37ab6fc6fb5085e1c6b5d86d5ce1ce5f8a 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -958,4 +958,11 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 extern tree aarch64_fp16_type_node;
 extern tree aarch64_fp16_ptr_type_node;
 
+#ifndef TARGET_LIBC_PROVIDES_SSP
+#define LINK_SSP_SPEC "%{!mstack-protector-pauth:\
+			 %{fstack-protector|fstack-protector-all\
+			   |fstack-protector-strong|fstack-protector-explicit:\
+			   -lssp_nonshared -lssp}}"
+#endif
+
 #endif /* GCC_AARCH64_H */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 6451b08191cf1a44aed502930da8603111f6e8ca..461f7b59584af9315accaecc0256abc9a2df4350 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2884,8 +2884,28 @@ aarch64_layout_frame (void)
   else if (cfun->machine->frame.wb_candidate1 != INVALID_REGNUM)
     max_push_offset = 256;
 
-  if (cfun->machine->frame.frame_size < max_push_offset
-      && crtl->outgoing_args_size == 0)
+  /* Swap callee-save and local variables area to make callee-save which
+     includes return address register X30/LR position above local variables
+     that any local buffer overflow will override return address.  */
+  if (aarch64_pauth_stack_protector_enabled ())
+    {
+      if (varargs_and_saved_regs_size < max_push_offset)
+	/* stp reg1, reg2, [sp, -varargs_and_saved_regs_size]!.  */
+	cfun->machine->frame.callee_adjust = varargs_and_saved_regs_size;
+      else
+	/* sub sp, sp, varargs_and_saved_regs_size.  */
+	cfun->machine->frame.initial_adjust = varargs_and_saved_regs_size;
+
+      /* Any final_adjust needed.  */
+      cfun->machine->frame.final_adjust
+	= cfun->machine->frame.frame_size - varargs_and_saved_regs_size;
+
+      /* Point hard_fp_offset and locals_offset to correct offsets.  */
+      cfun->machine->frame.hard_fp_offset = varargs_and_saved_regs_size;
+      cfun->machine->frame.locals_offset = cfun->machine->frame.hard_fp_offset;
+    }
+  else if (cfun->machine->frame.frame_size < max_push_offset
+	   && crtl->outgoing_args_size == 0)
     {
       /* Simple, small frame with no outgoing arguments:
 	 stp reg1, reg2, [sp, -frame_size]!
@@ -3117,6 +3137,26 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
     }
 }
 
+/* Implement the TARGET_STACK_PROTECT_RUNTIME_ENABLED_P.  */
+
+static bool
+aarch64_stack_protect_runtime_enabled (void)
+{
+  return !(TARGET_AARCH64_SSP_PAUTH && TARGET_ARMV8_3);
+}
+
+/* Return TRUE if pointer authentication accelerated -fstack-protector is
+   enabled.  */
+
+bool
+aarch64_pauth_stack_protector_enabled (void)
+{
+  /* Enable if this function is identified by GCC to be with buffer over flow
+     risk and we are not using GCC's standard libssp runtime.  */
+  return (crtl->stack_protect_guard
+	  && !aarch64_stack_protect_runtime_enabled ());
+}
+
 /* Return TRUE if return address signing should be enabled for one function,
    otherwise return FALSE.  */
 
@@ -3127,10 +3167,12 @@ aarch64_return_address_signing_enabled (void)
   gcc_assert (cfun->machine->frame.laid_out);
 
   /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
-     if it's LR is pushed onto stack.  */
-  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
-	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
-	      && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));
+     if it's LR is pushed onto stack.  Pointer authentication based stack
+     protector also implies return address signing.  */
+  return ((aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
+	   || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
+	       && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0))
+	  || aarch64_pauth_stack_protector_enabled ());
 }
 
 /* Emit code to save the callee-saved registers from register number START
@@ -8944,6 +8986,14 @@ aarch64_override_options (void)
   if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
     sorry ("Return address signing is only supported for -mabi=lp64");
 
+  if (TARGET_AARCH64_SSP_PAUTH && TARGET_ILP32)
+    sorry ("Pointer authentication based -fstack-protector is only supported "
+	   "on -mabi=lp64.");
+
+  if (TARGET_AARCH64_SSP_PAUTH && !TARGET_ARMV8_3)
+    error ("Pointer authentication based -fstack-protector is only supported "
+	   "on architecture with pointer authentication extension.");
+
   /* Make sure we properly set up the explicit options.  */
   if ((aarch64_cpu_string && valid_cpu)
        || (aarch64_tune_string && valid_tune))
@@ -14859,6 +14909,10 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_SETUP_INCOMING_VARARGS
 #define TARGET_SETUP_INCOMING_VARARGS aarch64_setup_incoming_varargs
 
+#undef TARGET_STACK_PROTECT_RUNTIME_ENABLED_P
+#define TARGET_STACK_PROTECT_RUNTIME_ENABLED_P \
+  aarch64_stack_protect_runtime_enabled
+
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX   aarch64_struct_value_rtx
 
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 54368848bbb249949921a3018d927c4bd61b1fbd..b157e51fd37d9040ca0a63c1f823f2ad70c8c17e 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -188,3 +188,7 @@ single precision and to 32 bits for double precision.
 mverbose-cost-dump
 Common Undocumented Var(flag_aarch64_verbose_cost)
 Enables verbose cost model dummping in the debug dump files.
+
+mstack-protector-pauth
+Target Report RejectNegative Mask(AARCH64_SSP_PAUTH) Save
+Enable pointer authentication accelerated stack protector.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c75d4b3697bae8805e13168d47066a1d0dd28df7..4eaefb4fc5e4eee92ba429ca5d23d314aa6f3d29 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14052,6 +14052,11 @@ Permissible values are @samp{none}, which disables return address signing,
 functions, and @samp{all}, which enables pointer signing for all functions.  The
 default value is @samp{none}.
 
+@item -mstack-protector-pauth
+@opindex mstack-protector-pauth
+Use ARMv8.3-A Pointer Authentication Extension to accelerate GCC
+-fstack-protector.
+
 @end table
 
 @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
diff --git a/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c b/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..56741bb38f4a2e95b82f04fe8009bcd6b1eb3f26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fstack-protector-all -mstack-protector-pauth" } */
+
+int foo (int);
+
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b, int c)
+{
+  /* paciasp */
+  return a + foo (b) + c;
+  /* retaa */
+}
+
+/* Shouldn't enable pauth acceleration as it's ARMv8.2-A.  */
+
+int __attribute__ ((target ("arch=armv8.2-a")))
+func2 (int a, int b, int c)
+{
+  return a + foo (b) + c;
+}
+
+/* { dg-final { scan-assembler-times "paciasp" 1 } } */
+/* { dg-final { scan-assembler-times "retaa" 1 } } */

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

* [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-12 18:10                   ` [Ping~]Re: [5/5][AArch64, libgcc] Runtime support for AArch64 return address signing (also attached target macros version) Jiong Wang
  2017-01-13 14:12                     ` James Greenhalgh
@ 2017-01-18 17:10                     ` Jiong Wang
  2017-01-19 14:23                       ` Richard Earnshaw (lists)
  1 sibling, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-18 17:10 UTC (permalink / raw)
  To: gcc-patches
  Cc: James Greenhalgh, Richard Earnshaw (lists),
	Ian Lance Taylor, Joseph Myers, Jakub Jelinek

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

On 12/01/17 18:10, Jiong Wang wrote:
> On 06/01/17 11:47, Jiong Wang wrote:
>> This is the update on libgcc unwinder support according to new DWARF proposal.
>>
>> As Joseph commented, duplication of unwind-dw2.c is not encouraged in libgcc,
>> But from this patch, you can see there are a few places we need to modify for
>> AArch64 in unwind-aarch64.c, so the file duplication approach is acceptable?
>>
>>
>> libgcc/
>>
>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>
>>         * config/aarch64/unwind-aarch64.c (DWARF_REGNUM_AARCH64_RA_STATE,
>>         RA_A_SIGNED_BIT): New macros.
>>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on AArch64.
>>         (uw_frame_state_for): Clear bit[0] of DWARF_REGNUM_AARCH64_RA_STATE.
>>         (uw_update_context): Authenticate return address according to
>>         DWARF_REGNUM_AARCH64_RA_STATE.
>>         (uw_init_context_1): Strip signature of seed address.
>>         (uw_install_context): Re-authenticate EH handler's address.
>>
> Ping~
>
> For comparision, I have also attached the patch using the target macros.
>
> Four new target macros are introduced:
>
>   MD_POST_EXTRACT_ROOT_ADDR
>   MD_POST_EXTRACT_FRAME_ADDR
>   MD_POST_FROB_EH_HANDLER_ADDR
>   MD_POST_INIT_CONTEXT
>
> MD_POST_EXTRACT_ROOT_ADDR is to do target private post processing on the address
> inside _Unwind* functions, they are serving as root address to start the
> unwinding.  MD_POST_EXTRACT_FRAME_ADDR is to do target private post processing
> on th address inside the real user program which throws the exceptions.
>
> MD_POST_FROB_EH_HANDLER_ADDR is to do target private frob on the EH handler's
> address before we install it into current context.
>
> MD_POST_INIT_CONTEXT it to do target private initialization on the context
> structure after common initialization.
>
> One "__aarch64__" macro check is needed to multiplex DW_CFA_window_save.

Ping ~

Could global reviewers or libgcc maintainers please give a review on the generic
part change?

One small change is I removed MD_POST_INIT_CONTEXT as I found there is
MD_FROB_UPDATE_CONTEXT which serve the same purpose.  I still need to define

    MD_POST_EXTRACT_ROOT_ADDR
    MD_POST_EXTRACT_FRAME_ADDR
    MD_POST_FROB_EH_HANDLER_ADDR

And do one __aarch64__ check to multiplexing DW_CFA_GNU_window_save.

Thanks.

libgcc/ChangeLog:

2017-01-18  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-unwind.h: New file.
         (DWARF_REGNUM_AARCH64_RA_STATE): Define.
         (MD_POST_EXTRACT_ROOT_ADDR): Define.
         (MD_POST_EXTRACT_FRAME_ADDR): Define.
         (MD_POST_FROB_EH_HANDLER_ADDR): Define.
         (MD_FROB_UPDATE_CONTEXT): Define.
         (aarch64_post_extract_frame_addr): New function.
         (aarch64_post_frob_eh_handler_addr): New function.
         (aarch64_frob_update_context): New function.
         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
         * config.host (aarch64*-*-elf, aarch64*-*-rtems*, aarch64*-*-freebsd*):
         Initialize md_unwind_header to include aarch64-unwind.h.
         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for __aarch64__.
         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
         (uw_frob_return_addr): New function.
         (_Unwind_DebugHook): Use uw_frob_return_addr.


[-- Attachment #2: 1.patch --]
[-- Type: text/x-diff, Size: 8698 bytes --]

diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -136,6 +136,8 @@ struct _Unwind_Context
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  /* Bit reserved on AArch64, return address has been signed with A key.  */
+#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
@@ -1185,6 +1187,11 @@ execute_cfa_program (const unsigned char *insn_ptr,
 	  break;
 
 	case DW_CFA_GNU_window_save:
+#ifdef __aarch64__
+	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
+	     return address signing status.  */
+	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
+#else
 	  /* ??? Hardcoded for SPARC register window configuration.  */
 	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
 	    for (reg = 16; reg < 32; ++reg)
@@ -1192,6 +1199,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
 		fs->regs.reg[reg].how = REG_SAVED_OFFSET;
 		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
 	      }
+#endif
 	  break;
 
 	case DW_CFA_GNU_args_size:
@@ -1513,10 +1521,15 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
        stack frame.  */
     context->ra = 0;
   else
-    /* Compute the return address now, since the return address column
-       can change from frame to frame.  */
-    context->ra = __builtin_extract_return_addr
-      (_Unwind_GetPtr (context, fs->retaddr_column));
+    {
+      /* Compute the return address now, since the return address column
+	 can change from frame to frame.  */
+      context->ra = __builtin_extract_return_addr
+	(_Unwind_GetPtr (context, fs->retaddr_column));
+#ifdef MD_POST_EXTRACT_FRAME_ADDR
+      context->ra = MD_POST_EXTRACT_FRAME_ADDR (context, fs, context->ra);
+#endif
+    }
 }
 
 static void
@@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
 		   void *outer_cfa, void *outer_ra)
 {
   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
+#endif
   _Unwind_FrameState fs;
   _Unwind_SpTmp sp_slot;
   _Unwind_Reason_Code code;
@@ -1586,6 +1602,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
      initialization context, then we can't see it in the given
      call frame data.  So have the initialization context tell us.  */
   context->ra = __builtin_extract_return_addr (outer_ra);
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
+#endif
 }
 
 static void _Unwind_DebugHook (void *, void *)
@@ -1608,6 +1627,20 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
 #endif
 }
 
+/* Frob exception handler's address kept in TARGET before installing into
+   CURRENT context.  */
+
+static void *
+uw_frob_return_addr (struct _Unwind_Context *current,
+		     struct _Unwind_Context *target)
+{
+  void *ret_addr = __builtin_frob_return_addr (target->ra);
+#ifdef MD_POST_FROB_EH_HANDLER_ADDR
+  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
+#endif
+  return ret_addr;
+}
+
 /* Install TARGET into CURRENT so that we can return to it.  This is a
    macro because __builtin_eh_return must be invoked in the context of
    our caller.  */
@@ -1616,7 +1649,7 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
   do									\
     {									\
       long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
-      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      void *handler = uw_frob_return_addr ((CURRENT), (TARGET));	\
       _Unwind_DebugHook ((TARGET)->cfa, handler);			\
       __builtin_eh_return (offset, handler);				\
     }									\
diff --git a/libgcc/config.host b/libgcc/config.host
index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -331,11 +331,13 @@ aarch64*-*-elf | aarch64*-*-rtems*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-freebsd*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-linux*)
 	extra_parts="$extra_parts crtfastmath.o"
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
new file mode 100644
index 0000000000000000000000000000000000000000..a57cae0ff54ea7e11c32362677c0b51501a9f727
--- /dev/null
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2017 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef AARCH64_UNWIND_H
+#define AARCH64_UNWIND_H
+
+#define DWARF_REGNUM_AARCH64_RA_STATE 34
+
+#define MD_POST_EXTRACT_ROOT_ADDR(addr)  __builtin_aarch64_xpaclri (addr)
+#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \
+  aarch64_post_extract_frame_addr (context, fs, addr)
+#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \
+  aarch64_post_frob_eh_handler_addr (current, target, addr)
+#define MD_FROB_UPDATE_CONTEXT(context, fs) \
+  aarch64_frob_update_context (context, fs)
+
+/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
+   unwind frame info FS.  If ADDR is signed, we do address authentication on it
+   using CFA of current frame.  */
+
+static void *
+aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
+				 _Unwind_FrameState *fs, void *addr)
+{
+  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    {
+      _Unwind_Word salt = (_Unwind_Word) context->cfa;
+      return __builtin_aarch64_autia1716 (addr, salt);
+    }
+  else
+    return addr;
+}
+
+/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before
+   installing it into current context CURRENT.  TARGET is currently not used.
+   We need to sign exception handler's address if CURRENT itself is signed.  */
+
+static void *
+aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
+				   struct _Unwind_Context *target
+				   ATTRIBUTE_UNUSED,
+				   void *handler_addr)
+{
+  if (current->flags & RA_A_SIGNED_BIT)
+    return __builtin_aarch64_pacia1716 (handler_addr,
+					(_Unwind_Word) current->cfa);
+  else
+    return handler_addr;
+}
+
+/* Do AArch64 private initialization on CONTEXT based on frame info FS.  Mark
+   CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE is
+   set.  */
+
+static void
+aarch64_frob_update_context (struct _Unwind_Context *context,
+			     _Unwind_FrameState *fs)
+{
+  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    /* The flag is used for re-authenticating EH handler's address.  */
+    context->flags |= RA_A_SIGNED_BIT;
+
+  return;
+}
+
+#endif /* defined AARCH64_UNWIND_H */
diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
index 1256f010007ac964de8bb895379a7d893a446bd9..75774b30c080ad2361fb37c7208bcf3d3b57d77a 100644
--- a/libgcc/config/aarch64/linux-unwind.h
+++ b/libgcc/config/aarch64/linux-unwind.h
@@ -24,6 +24,7 @@
 
 #include <signal.h>
 #include <sys/ucontext.h>
+#include "aarch64-unwind.h"
 
 
 /* Since insns are always stored LE, on a BE system the opcodes will

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

* Re: [2/5][DWARF] Generate dwarf information for -msign-return-address by introducing new DWARF mapping hook
  2017-01-17 15:11                     ` Jiong Wang
@ 2017-01-19 14:19                       ` Richard Earnshaw (lists)
  0 siblings, 0 replies; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-19 14:19 UTC (permalink / raw)
  To: Jiong Wang, gcc-patches; +Cc: James Greenhalgh, Jason Merrill, Jeff Law

On 17/01/17 15:11, Jiong Wang wrote:
> 
> 
> On 17/01/17 13:57, Richard Earnshaw (lists) wrote:
>> On 16/01/17 14:29, Jiong Wang wrote:
>>>
>>>> I can see the reason for doing this is if you want to seperate the
>>>> interpretion
>>>> of GCC CFA reg-note and the final DWARF CFA operation.  My
>>>> understanding is all
>>>> reg notes defined in gcc/reg-note.def should have general meaning,
>>>> even the
>>>> CFA_WINDOW_SAVE.  For those which are architecture specific we might
>>>> need a
>>>> mechanism to define them in backend only.
>>>>     For general reg-notes in gcc/reg-note.def, they are not always have
>>>> the
>>>> corresponding standard DWARF CFA operation, for example
>>>> CFA_WINDOW_SAVE,
>>>> therefore if we want to achieve what you described, I think we also
>>>> need to
>>>> define a new target hook which maps a GCC CFA reg-note into
>>>> architecture DWARF
>>>> CFA operation.
>>>>
>>>> Regards,
>>>> Jiong
>>>>
>>>>
>>> Here is the patch.
>>>
>> Hmm, I really wasn't expecting any more than something like the
>> following in dwarf2cfi.c:
>>
>> @@ -2098,7 +2098,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
>>          handled_one = true;
>>          break;
>>
>> +      case REG_CFA_TOGGLE_RA_MANGLE:
>>         case REG_CFA_WINDOW_SAVE:
>> +       /* We overload both of these operations onto the same DWARF
>> opcode.  */
>>          dwarf2out_frame_debug_cfa_window_save ();
>>          handled_one = true;
>>          break;
>>
>> This keeps the two reg notes separate within the compiler, but emits the
>> same dwarf operation during final output.  This avoids the need for new
>> hooks or anything more complicated.
> 
> This was my initial thoughts and the patch would be very small as you've
> demonstrated.  I later moved to this complexer patch as I am thinking it's
> better to completely treat notes in reg-notes.def as having generic
> meaning and
> maps them to standard DWARF CFA if there is, otherwise maps them to target
> private DWARF CFA through this new hook.  This give other targets a
> chance to
> map, for example REG_CFA_TOGGLE_RA_MANGLE, to their architecture DWARF
> number.
> 
> The introduction of new hook looks be very low risk in this stage, the only
> painful thing is the header file needs to be reorganized as we need to
> use some
> DWARF type and reg-note type in targhooks.c.
> 
> Anyway, if the new hook patch is too heavy, I have attached the the
> simplified
> version which simply defines the new REG_CFA_TOGGLE_RA_MANGLE and maps
> to same
> code of REG_CFA_WINDOW_SAVE.
> 
> 

Yes, this is much more like what I had in mind.

OK.

R.

> gcc/
> 
> 2017-01-17  Jiong Wang  <jiong.wang@arm.com>
> 
>         * reg-notes.def (CFA_TOGGLE_RA_MANGLE): New reg-note.
>         * combine-stack-adj.c (no_unhandled_cfa): Handle
>         REG_CFA_TOGGLE_RA_MANGLE.
>         * dwarf2cfi.c
>         (dwarf2out_frame_debug): Handle REG_CFA_TOGGLE_RA_MANGLE.
>         * config/aarch64/aarch64.c (aarch64_expand_prologue): Generates
> DWARF
>         info for return address signing.
>         (aarch64_expand_epilogue): Likewise.
> 
> 
> k.patch
> 
> 
> diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
> index 20cd59ad08329e9f4f834bfc01d6f9ccc4485283..9ec14a3e44363f35f6419c38233ce5eebddd3458 100644
> --- a/gcc/combine-stack-adj.c
> +++ b/gcc/combine-stack-adj.c
> @@ -208,6 +208,7 @@ no_unhandled_cfa (rtx_insn *insn)
>        case REG_CFA_SET_VDRAP:
>        case REG_CFA_WINDOW_SAVE:
>        case REG_CFA_FLUSH_QUEUE:
> +      case REG_CFA_TOGGLE_RA_MANGLE:
>  	return false;
>        }
>  
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 3bcad76b68b6ea7c9d75d150d79c45fb74d6bf0d..6451b08191cf1a44aed502930da8603111f6e8ca 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -3553,7 +3553,11 @@ aarch64_expand_prologue (void)
>  
>    /* Sign return address for functions.  */
>    if (aarch64_return_address_signing_enabled ())
> -    emit_insn (gen_pacisp ());
> +    {
> +      insn = emit_insn (gen_pacisp ());
> +      add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +    }
>  
>    if (flag_stack_usage_info)
>      current_function_static_stack_size = frame_size;
> @@ -3707,7 +3711,11 @@ aarch64_expand_epilogue (bool for_sibcall)
>      */
>    if (aarch64_return_address_signing_enabled ()
>        && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
> -    emit_insn (gen_autisp ());
> +    {
> +      insn = emit_insn (gen_autisp ());
> +      add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +    }
>  
>    /* Stack adjustment for exception handler.  */
>    if (crtl->calls_eh_return)
> diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
> index 2748e2fa48e4794181496b26df9b51b7e51e7b84..2a527c9fecab091dccb417492e5dbb2ade244be2 100644
> --- a/gcc/dwarf2cfi.c
> +++ b/gcc/dwarf2cfi.c
> @@ -2098,7 +2098,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
>  	handled_one = true;
>  	break;
>  
> +      case REG_CFA_TOGGLE_RA_MANGLE:
>        case REG_CFA_WINDOW_SAVE:
> +	/* We overload both of these operations onto the same DWARF opcode.  */
>  	dwarf2out_frame_debug_cfa_window_save ();
>  	handled_one = true;
>  	break;
> diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
> index ead4a9f58e8621288ee765e029c673640fdf38f4..175da119b6a534b04bd154f2c69dd087afd474ea 100644
> --- a/gcc/reg-notes.def
> +++ b/gcc/reg-notes.def
> @@ -177,6 +177,11 @@ REG_NOTE (CFA_WINDOW_SAVE)
>     the rest of the compiler as a CALL_INSN.  */
>  REG_NOTE (CFA_FLUSH_QUEUE)
>  
> +/* Attached to insns that are RTX_FRAME_RELATED_P, toggling the mangling status
> +   of return address.  Currently it's only used by AArch64.  The argument is
> +   ignored.  */
> +REG_NOTE (CFA_TOGGLE_RA_MANGLE)
> +
>  /* Indicates what exception region an INSN belongs in.  This is used
>     to indicate what region to which a call may throw.  REGION 0
>     indicates that a call cannot throw at all.  REGION -1 indicates
> 

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-18 17:10                     ` [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros) Jiong Wang
@ 2017-01-19 14:23                       ` Richard Earnshaw (lists)
  2017-01-19 14:51                         ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-19 14:23 UTC (permalink / raw)
  To: Jiong Wang, gcc-patches
  Cc: James Greenhalgh, Ian Lance Taylor, Joseph Myers, Jakub Jelinek

On 18/01/17 17:07, Jiong Wang wrote:
> On 12/01/17 18:10, Jiong Wang wrote:
>> On 06/01/17 11:47, Jiong Wang wrote:
>>> This is the update on libgcc unwinder support according to new DWARF
>>> proposal.
>>>
>>> As Joseph commented, duplication of unwind-dw2.c is not encouraged in
>>> libgcc,
>>> But from this patch, you can see there are a few places we need to
>>> modify for
>>> AArch64 in unwind-aarch64.c, so the file duplication approach is
>>> acceptable?
>>>
>>>
>>> libgcc/
>>>
>>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>>
>>>         * config/aarch64/unwind-aarch64.c
>>> (DWARF_REGNUM_AARCH64_RA_STATE,
>>>         RA_A_SIGNED_BIT): New macros.
>>>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on
>>> AArch64.
>>>         (uw_frame_state_for): Clear bit[0] of
>>> DWARF_REGNUM_AARCH64_RA_STATE.
>>>         (uw_update_context): Authenticate return address according to
>>>         DWARF_REGNUM_AARCH64_RA_STATE.
>>>         (uw_init_context_1): Strip signature of seed address.
>>>         (uw_install_context): Re-authenticate EH handler's address.
>>>
>> Ping~
>>
>> For comparision, I have also attached the patch using the target macros.
>>
>> Four new target macros are introduced:
>>
>>   MD_POST_EXTRACT_ROOT_ADDR
>>   MD_POST_EXTRACT_FRAME_ADDR
>>   MD_POST_FROB_EH_HANDLER_ADDR
>>   MD_POST_INIT_CONTEXT
>>
>> MD_POST_EXTRACT_ROOT_ADDR is to do target private post processing on
>> the address
>> inside _Unwind* functions, they are serving as root address to start the
>> unwinding.  MD_POST_EXTRACT_FRAME_ADDR is to do target private post
>> processing
>> on th address inside the real user program which throws the exceptions.
>>
>> MD_POST_FROB_EH_HANDLER_ADDR is to do target private frob on the EH
>> handler's
>> address before we install it into current context.
>>
>> MD_POST_INIT_CONTEXT it to do target private initialization on the
>> context
>> structure after common initialization.
>>
>> One "__aarch64__" macro check is needed to multiplex DW_CFA_window_save.
> 
> Ping ~
> 
> Could global reviewers or libgcc maintainers please give a review on the
> generic
> part change?
> 
> One small change is I removed MD_POST_INIT_CONTEXT as I found there is
> MD_FROB_UPDATE_CONTEXT which serve the same purpose.  I still need to
> define
> 
>    MD_POST_EXTRACT_ROOT_ADDR
>    MD_POST_EXTRACT_FRAME_ADDR
>    MD_POST_FROB_EH_HANDLER_ADDR
> 
> And do one __aarch64__ check to multiplexing DW_CFA_GNU_window_save.
> 
> Thanks.
> 
> libgcc/ChangeLog:
> 
> 2017-01-18  Jiong Wang  <jiong.wang@arm.com>
> 
>         * config/aarch64/aarch64-unwind.h: New file.
>         (DWARF_REGNUM_AARCH64_RA_STATE): Define.
>         (MD_POST_EXTRACT_ROOT_ADDR): Define.
>         (MD_POST_EXTRACT_FRAME_ADDR): Define.
>         (MD_POST_FROB_EH_HANDLER_ADDR): Define.
>         (MD_FROB_UPDATE_CONTEXT): Define.
>         (aarch64_post_extract_frame_addr): New function.
>         (aarch64_post_frob_eh_handler_addr): New function.
>         (aarch64_frob_update_context): New function.
>         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
>         * config.host (aarch64*-*-elf, aarch64*-*-rtems*,
> aarch64*-*-freebsd*):
>         Initialize md_unwind_header to include aarch64-unwind.h.
>         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for
> __aarch64__.
>         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
>         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
>         (uw_frob_return_addr): New function.
>         (_Unwind_DebugHook): Use uw_frob_return_addr.
> 
> 

Comments inline.

> 1.patch
> 
> 
> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
> index 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2 100644
> --- a/libgcc/unwind-dw2.c
> +++ b/libgcc/unwind-dw2.c
> @@ -136,6 +136,8 @@ struct _Unwind_Context
>  #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
>    /* Context which has version/args_size/by_value fields.  */
>  #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
> +  /* Bit reserved on AArch64, return address has been signed with A key.  */
> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)

Why is this here?   It appears to only be used within the
AArch64-specific header file.

>    _Unwind_Word flags;
>    /* 0 for now, can be increased when further fields are added to
>       struct _Unwind_Context.  */
> @@ -1185,6 +1187,11 @@ execute_cfa_program (const unsigned char *insn_ptr,
>  	  break;
>  
>  	case DW_CFA_GNU_window_save:
> +#ifdef __aarch64__
> +	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
> +	     return address signing status.  */
> +	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
> +#else
>  	  /* ??? Hardcoded for SPARC register window configuration.  */
>  	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
>  	    for (reg = 16; reg < 32; ++reg)
> @@ -1192,6 +1199,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
>  		fs->regs.reg[reg].how = REG_SAVED_OFFSET;
>  		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
>  	      }
> +#endif
>  	  break;
>  
>  	case DW_CFA_GNU_args_size:
> @@ -1513,10 +1521,15 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
>         stack frame.  */
>      context->ra = 0;
>    else
> -    /* Compute the return address now, since the return address column
> -       can change from frame to frame.  */
> -    context->ra = __builtin_extract_return_addr
> -      (_Unwind_GetPtr (context, fs->retaddr_column));
> +    {
> +      /* Compute the return address now, since the return address column
> +	 can change from frame to frame.  */
> +      context->ra = __builtin_extract_return_addr
> +	(_Unwind_GetPtr (context, fs->retaddr_column));
> +#ifdef MD_POST_EXTRACT_FRAME_ADDR
> +      context->ra = MD_POST_EXTRACT_FRAME_ADDR (context, fs, context->ra);
> +#endif
> +    }
>  }
>  
>  static void
> @@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
>  		   void *outer_cfa, void *outer_ra)
>  {
>    void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
> +#ifdef MD_POST_EXTRACT_ROOT_ADDR
> +  ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
> +#endif
>    _Unwind_FrameState fs;
>    _Unwind_SpTmp sp_slot;
>    _Unwind_Reason_Code code;
> @@ -1586,6 +1602,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
>       initialization context, then we can't see it in the given
>       call frame data.  So have the initialization context tell us.  */
>    context->ra = __builtin_extract_return_addr (outer_ra);
> +#ifdef MD_POST_EXTRACT_ROOT_ADDR
> +  context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
> +#endif
>  }
>  
>  static void _Unwind_DebugHook (void *, void *)
> @@ -1608,6 +1627,20 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
>  #endif
>  }
>  
> +/* Frob exception handler's address kept in TARGET before installing into
> +   CURRENT context.  */
> +
> +static void *
> +uw_frob_return_addr (struct _Unwind_Context *current,
> +		     struct _Unwind_Context *target)
> +{
> +  void *ret_addr = __builtin_frob_return_addr (target->ra);
> +#ifdef MD_POST_FROB_EH_HANDLER_ADDR
> +  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
> +#endif
> +  return ret_addr;
> +}
> +

I think this function should be marked inline.  The optimizers would
probably inline it anyway, but it seems wrong for us to rely on that.

>  /* Install TARGET into CURRENT so that we can return to it.  This is a
>     macro because __builtin_eh_return must be invoked in the context of
>     our caller.  */
> @@ -1616,7 +1649,7 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
>    do									\
>      {									\
>        long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
> -      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
> +      void *handler = uw_frob_return_addr ((CURRENT), (TARGET));	\
>        _Unwind_DebugHook ((TARGET)->cfa, handler);			\
>        __builtin_eh_return (offset, handler);				\
>      }									\
> diff --git a/libgcc/config.host b/libgcc/config.host
> index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644
> --- a/libgcc/config.host
> +++ b/libgcc/config.host
> @@ -331,11 +331,13 @@ aarch64*-*-elf | aarch64*-*-rtems*)
>  	extra_parts="$extra_parts crtfastmath.o"
>  	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
>  	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
> +	md_unwind_header=aarch64/aarch64-unwind.h
>  	;;
>  aarch64*-*-freebsd*)
>  	extra_parts="$extra_parts crtfastmath.o"
>  	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
>  	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
> +	md_unwind_header=aarch64/aarch64-unwind.h
>  	;;
>  aarch64*-*-linux*)
>  	extra_parts="$extra_parts crtfastmath.o"
> diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..a57cae0ff54ea7e11c32362677c0b51501a9f727
> --- /dev/null
> +++ b/libgcc/config/aarch64/aarch64-unwind.h
> @@ -0,0 +1,87 @@
> +/* Copyright (C) 2017 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.
> +
> +Under Section 7 of GPL version 3, you are granted additional
> +permissions described in the GCC Runtime Library Exception, version
> +3.1, as published by the Free Software Foundation.
> +
> +You should have received a copy of the GNU General Public License and
> +a copy of the GCC Runtime Library Exception along with this program;
> +see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#ifndef AARCH64_UNWIND_H
> +#define AARCH64_UNWIND_H
> +
> +#define DWARF_REGNUM_AARCH64_RA_STATE 34
> +
> +#define MD_POST_EXTRACT_ROOT_ADDR(addr)  __builtin_aarch64_xpaclri (addr)
> +#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \
> +  aarch64_post_extract_frame_addr (context, fs, addr)
> +#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \
> +  aarch64_post_frob_eh_handler_addr (current, target, addr)
> +#define MD_FROB_UPDATE_CONTEXT(context, fs) \
> +  aarch64_frob_update_context (context, fs)
> +
> +/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
> +   unwind frame info FS.  If ADDR is signed, we do address authentication on it
> +   using CFA of current frame.  */
> +

All the functions in this HEADER file should be marked inline.

> +static void *
> +aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
> +				 _Unwind_FrameState *fs, void *addr)
> +{
> +  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
> +    {
> +      _Unwind_Word salt = (_Unwind_Word) context->cfa;
> +      return __builtin_aarch64_autia1716 (addr, salt);
> +    }
> +  else
> +    return addr;
> +}
> +
> +/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before
> +   installing it into current context CURRENT.  TARGET is currently not used.
> +   We need to sign exception handler's address if CURRENT itself is signed.  */
> +
> +static void *
> +aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
> +				   struct _Unwind_Context *target
> +				   ATTRIBUTE_UNUSED,
> +				   void *handler_addr)
> +{
> +  if (current->flags & RA_A_SIGNED_BIT)
> +    return __builtin_aarch64_pacia1716 (handler_addr,
> +					(_Unwind_Word) current->cfa);
> +  else
> +    return handler_addr;
> +}
> +
> +/* Do AArch64 private initialization on CONTEXT based on frame info FS.  Mark
> +   CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE is
> +   set.  */
> +
> +static void
> +aarch64_frob_update_context (struct _Unwind_Context *context,
> +			     _Unwind_FrameState *fs)
> +{
> +  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
> +    /* The flag is used for re-authenticating EH handler's address.  */
> +    context->flags |= RA_A_SIGNED_BIT;
> +
> +  return;
> +}
> +
> +#endif /* defined AARCH64_UNWIND_H */
> diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
> index 1256f010007ac964de8bb895379a7d893a446bd9..75774b30c080ad2361fb37c7208bcf3d3b57d77a 100644
> --- a/libgcc/config/aarch64/linux-unwind.h
> +++ b/libgcc/config/aarch64/linux-unwind.h
> @@ -24,6 +24,7 @@
>  
>  #include <signal.h>
>  #include <sys/ucontext.h>
> +#include "aarch64-unwind.h"
>  
>  
>  /* Since insns are always stored LE, on a BE system the opcodes will
> 

R.

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-19 14:23                       ` Richard Earnshaw (lists)
@ 2017-01-19 14:51                         ` Jiong Wang
  2017-01-19 20:25                           ` Richard Earnshaw (lists)
  2017-01-20  8:42                           ` Christophe Lyon
  0 siblings, 2 replies; 75+ messages in thread
From: Jiong Wang @ 2017-01-19 14:51 UTC (permalink / raw)
  To: Richard Earnshaw (lists), gcc-patches
  Cc: James Greenhalgh, Ian Lance Taylor, Joseph Myers, Jakub Jelinek

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

Thanks for the review.

On 19/01/17 14:18, Richard Earnshaw (lists) wrote:
>
>>
>>
>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
>> index 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2 100644
>> --- a/libgcc/unwind-dw2.c
>> +++ b/libgcc/unwind-dw2.c
>> @@ -136,6 +136,8 @@ struct _Unwind_Context
>>  #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
>>    /* Context which has version/args_size/by_value fields.  */
>>  #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
>> +  /* Bit reserved on AArch64, return address has been signed with A key.  */
>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
>
> Why is this here?   It appears to only be used within the
> AArch64-specific header file.

I was putting it here so that when we allocate the next general purpose bit, we
know clearly that bit 3 is allocated to AArch64 already, and the new general bit
needs to go to the next one.  This can avoid bit collision.

>
>> ...
>>
>> +/* Frob exception handler's address kept in TARGET before installing into
>> +   CURRENT context.  */
>> +
>> +static void *
>> +uw_frob_return_addr (struct _Unwind_Context *current,
>> +                 struct _Unwind_Context *target)
>> +{
>> +  void *ret_addr = __builtin_frob_return_addr (target->ra);
>> +#ifdef MD_POST_FROB_EH_HANDLER_ADDR
>> +  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
>> +#endif
>> +  return ret_addr;
>> +}
>> +
>
> I think this function should be marked inline.  The optimizers would
> probably inline it anyway, but it seems wrong for us to rely on that.

Thanks, fixed.

Does the updated patch looks OK to you know?

libgcc/

2017-01-19  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-unwind.h: New file.
         (DWARF_REGNUM_AARCH64_RA_STATE): Define.
         (MD_POST_EXTRACT_ROOT_ADDR): Define.
         (MD_POST_EXTRACT_FRAME_ADDR): Define.
         (MD_POST_FROB_EH_HANDLER_ADDR): Define.
         (MD_FROB_UPDATE_CONTEXT): Define.
         (aarch64_post_extract_frame_addr): New function.
         (aarch64_post_frob_eh_handler_addr): New function.
         (aarch64_frob_update_context): New function.
         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
         * config.host (aarch64*-*-elf, aarch64*-*-rtems*, aarch64*-*-freebsd*):
         Initialize md_unwind_header to include aarch64-unwind.h.
         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for __aarch64__.
         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
         (uw_frob_return_addr): New function.
         (_Unwind_DebugHook): Use uw_frob_return_addr.


[-- Attachment #2: new.patch --]
[-- Type: text/x-diff, Size: 8726 bytes --]

diff --git a/libgcc/config.host b/libgcc/config.host
index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -331,11 +331,13 @@ aarch64*-*-elf | aarch64*-*-rtems*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-freebsd*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-linux*)
 	extra_parts="$extra_parts crtfastmath.o"
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
new file mode 100644
index 0000000000000000000000000000000000000000..a43d965b358f3e830b85fc42c7bceacf7d41a671
--- /dev/null
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2017 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef AARCH64_UNWIND_H
+#define AARCH64_UNWIND_H
+
+#define DWARF_REGNUM_AARCH64_RA_STATE 34
+
+#define MD_POST_EXTRACT_ROOT_ADDR(addr)  __builtin_aarch64_xpaclri (addr)
+#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \
+  aarch64_post_extract_frame_addr (context, fs, addr)
+#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \
+  aarch64_post_frob_eh_handler_addr (current, target, addr)
+#define MD_FROB_UPDATE_CONTEXT(context, fs) \
+  aarch64_frob_update_context (context, fs)
+
+/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
+   unwind frame info FS.  If ADDR is signed, we do address authentication on it
+   using CFA of current frame.  */
+
+static inline void *
+aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
+				 _Unwind_FrameState *fs, void *addr)
+{
+  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    {
+      _Unwind_Word salt = (_Unwind_Word) context->cfa;
+      return __builtin_aarch64_autia1716 (addr, salt);
+    }
+  else
+    return addr;
+}
+
+/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before
+   installing it into current context CURRENT.  TARGET is currently not used.
+   We need to sign exception handler's address if CURRENT itself is signed.  */
+
+static inline void *
+aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
+				   struct _Unwind_Context *target
+				   ATTRIBUTE_UNUSED,
+				   void *handler_addr)
+{
+  if (current->flags & RA_A_SIGNED_BIT)
+    return __builtin_aarch64_pacia1716 (handler_addr,
+					(_Unwind_Word) current->cfa);
+  else
+    return handler_addr;
+}
+
+/* Do AArch64 private initialization on CONTEXT based on frame info FS.  Mark
+   CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE is
+   set.  */
+
+static inline void
+aarch64_frob_update_context (struct _Unwind_Context *context,
+			     _Unwind_FrameState *fs)
+{
+  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    /* The flag is used for re-authenticating EH handler's address.  */
+    context->flags |= RA_A_SIGNED_BIT;
+
+  return;
+}
+
+#endif /* defined AARCH64_UNWIND_H */
diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
index 1256f010007ac964de8bb895379a7d893a446bd9..75774b30c080ad2361fb37c7208bcf3d3b57d77a 100644
--- a/libgcc/config/aarch64/linux-unwind.h
+++ b/libgcc/config/aarch64/linux-unwind.h
@@ -24,6 +24,7 @@
 
 #include <signal.h>
 #include <sys/ucontext.h>
+#include "aarch64-unwind.h"
 
 
 /* Since insns are always stored LE, on a BE system the opcodes will
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 8085a42ace15d53f4cb0c6681717012d906a6d47..f2e5ce832190ff3ee69f31e3b6d44b68395f68df 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -136,6 +136,8 @@ struct _Unwind_Context
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  /* Bit reserved on AArch64, return address has been signed with A key.  */
+#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
@@ -1185,6 +1187,11 @@ execute_cfa_program (const unsigned char *insn_ptr,
 	  break;
 
 	case DW_CFA_GNU_window_save:
+#ifdef __aarch64__
+	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
+	     return address signing status.  */
+	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
+#else
 	  /* ??? Hardcoded for SPARC register window configuration.  */
 	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
 	    for (reg = 16; reg < 32; ++reg)
@@ -1192,6 +1199,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
 		fs->regs.reg[reg].how = REG_SAVED_OFFSET;
 		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
 	      }
+#endif
 	  break;
 
 	case DW_CFA_GNU_args_size:
@@ -1513,10 +1521,15 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
        stack frame.  */
     context->ra = 0;
   else
-    /* Compute the return address now, since the return address column
-       can change from frame to frame.  */
-    context->ra = __builtin_extract_return_addr
-      (_Unwind_GetPtr (context, fs->retaddr_column));
+    {
+      /* Compute the return address now, since the return address column
+	 can change from frame to frame.  */
+      context->ra = __builtin_extract_return_addr
+	(_Unwind_GetPtr (context, fs->retaddr_column));
+#ifdef MD_POST_EXTRACT_FRAME_ADDR
+      context->ra = MD_POST_EXTRACT_FRAME_ADDR (context, fs, context->ra);
+#endif
+    }
 }
 
 static void
@@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
 		   void *outer_cfa, void *outer_ra)
 {
   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
+#endif
   _Unwind_FrameState fs;
   _Unwind_SpTmp sp_slot;
   _Unwind_Reason_Code code;
@@ -1586,6 +1602,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
      initialization context, then we can't see it in the given
      call frame data.  So have the initialization context tell us.  */
   context->ra = __builtin_extract_return_addr (outer_ra);
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
+#endif
 }
 
 static void _Unwind_DebugHook (void *, void *)
@@ -1608,6 +1627,20 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
 #endif
 }
 
+/* Frob exception handler's address kept in TARGET before installing into
+   CURRENT context.  */
+
+static inline void *
+uw_frob_return_addr (struct _Unwind_Context *current,
+		     struct _Unwind_Context *target)
+{
+  void *ret_addr = __builtin_frob_return_addr (target->ra);
+#ifdef MD_POST_FROB_EH_HANDLER_ADDR
+  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
+#endif
+  return ret_addr;
+}
+
 /* Install TARGET into CURRENT so that we can return to it.  This is a
    macro because __builtin_eh_return must be invoked in the context of
    our caller.  */
@@ -1616,7 +1649,7 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
   do									\
     {									\
       long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
-      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      void *handler = uw_frob_return_addr ((CURRENT), (TARGET));	\
       _Unwind_DebugHook ((TARGET)->cfa, handler);			\
       __builtin_eh_return (offset, handler);				\
     }									\

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-19 14:51                         ` Jiong Wang
@ 2017-01-19 20:25                           ` Richard Earnshaw (lists)
  2017-01-20  8:42                           ` Christophe Lyon
  1 sibling, 0 replies; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-19 20:25 UTC (permalink / raw)
  To: Jiong Wang, gcc-patches
  Cc: James Greenhalgh, Ian Lance Taylor, Joseph Myers, Jakub Jelinek

On 19/01/17 14:46, Jiong Wang wrote:
> Thanks for the review.
> 
> On 19/01/17 14:18, Richard Earnshaw (lists) wrote:
>>
>>>
>>>
>>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
>>> index
>>> 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2
>>> 100644
>>> --- a/libgcc/unwind-dw2.c
>>> +++ b/libgcc/unwind-dw2.c
>>> @@ -136,6 +136,8 @@ struct _Unwind_Context
>>>  #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
>>>    /* Context which has version/args_size/by_value fields.  */
>>>  #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
>>> +  /* Bit reserved on AArch64, return address has been signed with A
>>> key.  */
>>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
>>
>> Why is this here?   It appears to only be used within the
>> AArch64-specific header file.
> 
> I was putting it here so that when we allocate the next general purpose
> bit, we
> know clearly that bit 3 is allocated to AArch64 already, and the new
> general bit
> needs to go to the next one.  This can avoid bit collision.
> 

Fair enough.
>>
>>> ...
>>>
>>> +/* Frob exception handler's address kept in TARGET before installing
>>> into
>>> +   CURRENT context.  */
>>> +
>>> +static void *
>>> +uw_frob_return_addr (struct _Unwind_Context *current,
>>> +                 struct _Unwind_Context *target)
>>> +{
>>> +  void *ret_addr = __builtin_frob_return_addr (target->ra);
>>> +#ifdef MD_POST_FROB_EH_HANDLER_ADDR
>>> +  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
>>> +#endif
>>> +  return ret_addr;
>>> +}
>>> +
>>
>> I think this function should be marked inline.  The optimizers would
>> probably inline it anyway, but it seems wrong for us to rely on that.
> 
> Thanks, fixed.
> 
> Does the updated patch looks OK to you know?
> 
> libgcc/
> 
> 2017-01-19  Jiong Wang  <jiong.wang@arm.com>
> 
>         * config/aarch64/aarch64-unwind.h: New file.
>         (DWARF_REGNUM_AARCH64_RA_STATE): Define.
>         (MD_POST_EXTRACT_ROOT_ADDR): Define.
>         (MD_POST_EXTRACT_FRAME_ADDR): Define.
>         (MD_POST_FROB_EH_HANDLER_ADDR): Define.
>         (MD_FROB_UPDATE_CONTEXT): Define.
>         (aarch64_post_extract_frame_addr): New function.
>         (aarch64_post_frob_eh_handler_addr): New function.
>         (aarch64_frob_update_context): New function.
>         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
>         * config.host (aarch64*-*-elf, aarch64*-*-rtems*,
> aarch64*-*-freebsd*):
>         Initialize md_unwind_header to include aarch64-unwind.h.
>         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for
> __aarch64__.
>         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
>         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
>         (uw_frob_return_addr): New function.
>         (_Unwind_DebugHook): Use uw_frob_return_addr.
> 

OK.

R.

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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-06 11:47         ` [1/5][AArch64] Return address protection on AArch64 Jiong Wang
  2017-01-13 16:05           ` James Greenhalgh
@ 2017-01-20  4:15           ` Andrew Pinski
  2017-01-20 11:39             ` Jiong Wang
  1 sibling, 1 reply; 75+ messages in thread
From: Andrew Pinski @ 2017-01-20  4:15 UTC (permalink / raw)
  To: Jiong Wang; +Cc: gcc-patches, James Greenhalgh, Richard Earnshaw (lists)

On Fri, Jan 6, 2017 at 3:47 AM, Jiong Wang <jiong.wang@foss.arm.com> wrote:
> On 11/11/16 18:22, Jiong Wang wrote:
>>
>> As described in the cover letter, this patch implements return address
>> signing
>> for AArch64, it's controlled by the new option:
>>
>>    -msign-return-address=[none | non-leaf | all]
>>
>> "none" means don't do return address signing at all on any function.
>> "non-leaf"
>> means only sign non-leaf function.  "all" means sign all functions.
>> Return
>> address signing is currently disabled on ILP32.  I haven't tested it.
>>
>> The instructions added in the architecture are of 2 kinds.
>>
>> * In the NOP instruction space, which allows binaries to run without any
>> traps
>> on older versions of the architecture. This doesn't give any additional
>> protection on older hardware but allows for the same binary to be used on
>> earlier versions of the architecture and newer versions of the
>> architecture.
>>
>> * New instructions that are only valid for v8.3 and will trap if used on
>> earlier
>> versions of the architecture.
>>
>> At default, once return address signing is enabled, it will only generates
>> NOP
>> instruction.
>>
>> While if -march=armv8.3-a specified, GCC will try to use the most
>> efficient
>> pointer authentication instruction as it can.
>>
>> The architecture has 2 user invisible system keys for signing and creating
>> signed addresses as part of these instructions. For some use case, the
>> user
>> might want to use difference key for different functions.  The new option
>> "-msign-return-address-key=key_name" let GCC select the key used for
>> return
>> address signing.  Permissible values are "a_key" for A key and "b_key" for
>> B
>> key, and this option are supported by function target attribute and LTO
>> will
>> hopefully just work.
>>
>>
>>
>> gcc/
>> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>>
>>          * config/aarch64/aarch64-opts.h (aarch64_pauth_key_index): New
>> enum.
>>          (aarch64_function_type): New enum.
>>          * config/aarch64/aarch64-protos.h (aarch64_output_sign_auth_reg):
>> New
>>          declaration.
>>          * config/aarch64/aarch64.c (aarch64_expand_prologue): Sign return
>>          address before it's pushed onto stack.
>>          (aarch64_expand_epilogue): Authenticate return address fetched
>> from
>>          stack.
>>          (aarch64_output_sign_auth_reg): New function.
>>          (aarch64_override_options): Sanity check for ILP32 and ISA level.
>>          (aarch64_attributes): New function attributes for
>> "sign-return-address",
>>          "pauth-key".
>>          * config/aarch64/aarch64.md (UNSPEC_AUTH_REG,
>> UNSPEC_AUTH_REG1716,
>>          UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN,
>>          UNSPEC_STRIP_X30_SIGN): New unspecs.
>>          ("*do_return"): Generate combined instructions according to key
>> index.
>>          ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716",
>>          "strip_reg_sign", "strip_lr_sign"): New.
>>          * config/aarch64/aarch64.opt (msign-return-address, mpauth-key):
>> New.
>>          * config/aarch64/predicates.md (aarch64_const0_const1): New
>> predicate.
>>          * doc/extend.texi (AArch64 Function Attributes): Documents
>>          "sign-return-address=", "pauth-key".
>>          * doc/invoke.texi (AArch64 Options): Documents
>> "-msign-return-address=",
>>          "-pauth-key".
>>
>> gcc/testsuite/
>> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>>
>>          * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>>          * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.
>
>
> Update the patchset according to new DWARF proposal described at
>
>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03010.html

One of these patches of this patch set break ILP32 building for
aarch64-elf and most likely also aarch64-linux-gnu.

/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:
In function ‘uw_init_context_1’:
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:1567:6:
internal compiler error: in emit_move_insn, at expr.c:3698
   ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
0x8270cf emit_move_insn(rtx_def*, rtx_def*)
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.c:3697
0x80867b force_reg(machine_mode, rtx_def*)
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/explow.c:648
0xe9143f aarch64_expand_builtin(tree_node*, rtx_def*, rtx_def*,
machine_mode, int)
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/config/aarch64/aarch64-builtins.c:1336
0x6fae09 expand_builtin(tree_node*, rtx_def*, rtx_def*, machine_mode, int)
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/builtins.c:6359
0x8227bb expand_expr_real_1(tree_node*, rtx_def*, machine_mode,
expand_modifier, rtx_def**, bool)
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.c:10782
0x82de70 expand_expr
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.h:276
0x82de70 store_expr_with_bounds(tree_node*, rtx_def*, int, bool, bool,
tree_node*)
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.c:5459
0x82f3b8 expand_assignment(tree_node*, tree_node*, bool)
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.c:5321
0x71e8da expand_call_stmt
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/cfgexpand.c:2656
0x71e8da expand_gimple_stmt_1
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/cfgexpand.c:3571
0x71e8da expand_gimple_stmt
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/cfgexpand.c:3737
0x72085f expand_gimple_basic_block
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/cfgexpand.c:5744
0x726826 execute
/home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/cfgexpand.c:6357
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://www.cavium.com/support.html> for instructions.


Thanks,
Andrew




>
> While A key support for return address signing using DW_CFA_GNU_window_save
> only
> needs simple modifications on code and associated DWARF generation, B key
> support is complexer, it needs multiple CIE support in GCC and Binutils, so
> currently we fall back to DWARF value expression which fully works although
> requires longer encodings. Value expression also requires a few changes on
> AArch64 prologue and epilogue hooks that code review will not be easy.
>
> Therefore I have removed all B key support code in the initial support patch
> set,
> and will organize them into a seperate follow up patchset so that we can do
> A key
> code review first.
>
> This patch is an update on the return address signing code generation.
>
> gcc/
> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>
>         * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
>         * config/aarch64/aarch64-protos.h
>         (aarch64_return_address_signing_enabled): New declaration.
>         * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
>         New function.
>         (aarch64_expand_prologue): Sign return address before it's pushed
> onto
>         stack.
>         (aarch64_expand_epilogue): Authenticate return address fetched from
>         stack.
>         (aarch64_override_options): Sanity check for ILP32 and ISA level.
>         (aarch64_attributes): New function attributes for
> "sign-return-address".
>         * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
>         UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
>         ("*do_return"): Generate combined instructions according to key
> index.
>         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
>         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New
> integer
>         iterators.
>         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
>         * config/aarch64/aarch64.opt (msign-return-address=): New.
>         * doc/extend.texi (AArch64 Function Attributes): Documents
>         "sign-return-address=".
>         * doc/invoke.texi (AArch64 Options): Documents
> "-msign-return-address=".
>
> gcc/testsuite/
> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>
>
>         * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>         * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.
>
>

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-19 14:51                         ` Jiong Wang
  2017-01-19 20:25                           ` Richard Earnshaw (lists)
@ 2017-01-20  8:42                           ` Christophe Lyon
  2017-01-20  9:46                             ` Jiong Wang
  1 sibling, 1 reply; 75+ messages in thread
From: Christophe Lyon @ 2017-01-20  8:42 UTC (permalink / raw)
  To: Jiong Wang
  Cc: Richard Earnshaw (lists),
	gcc-patches, James Greenhalgh, Ian Lance Taylor, Joseph Myers,
	Jakub Jelinek

Hi Jiong,

On 19 January 2017 at 15:46, Jiong Wang <jiong.wang@foss.arm.com> wrote:
> Thanks for the review.
>
> On 19/01/17 14:18, Richard Earnshaw (lists) wrote:
>>
>>
>>>
>>>
>>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
>>> index
>>> 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2
>>> 100644
>>> --- a/libgcc/unwind-dw2.c
>>> +++ b/libgcc/unwind-dw2.c
>>> @@ -136,6 +136,8 @@ struct _Unwind_Context
>>>  #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
>>>    /* Context which has version/args_size/by_value fields.  */
>>>  #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
>>> +  /* Bit reserved on AArch64, return address has been signed with A key.
>>> */
>>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
>>
>>
>> Why is this here?   It appears to only be used within the
>> AArch64-specific header file.
>
>
> I was putting it here so that when we allocate the next general purpose bit,
> we
> know clearly that bit 3 is allocated to AArch64 already, and the new general
> bit
> needs to go to the next one.  This can avoid bit collision.
>
>>
>>> ...
>>>
>>> +/* Frob exception handler's address kept in TARGET before installing
>>> into
>>> +   CURRENT context.  */
>>> +
>>> +static void *
>>> +uw_frob_return_addr (struct _Unwind_Context *current,
>>> +                 struct _Unwind_Context *target)
>>> +{
>>> +  void *ret_addr = __builtin_frob_return_addr (target->ra);
>>> +#ifdef MD_POST_FROB_EH_HANDLER_ADDR
>>> +  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
>>> +#endif
>>> +  return ret_addr;
>>> +}
>>> +
>>
>>
>> I think this function should be marked inline.  The optimizers would
>> probably inline it anyway, but it seems wrong for us to rely on that.
>
>
> Thanks, fixed.
>
> Does the updated patch looks OK to you know?
>
> libgcc/
>
> 2017-01-19  Jiong Wang  <jiong.wang@arm.com>
>
>
>         * config/aarch64/aarch64-unwind.h: New file.
>         (DWARF_REGNUM_AARCH64_RA_STATE): Define.
>         (MD_POST_EXTRACT_ROOT_ADDR): Define.
>         (MD_POST_EXTRACT_FRAME_ADDR): Define.
>         (MD_POST_FROB_EH_HANDLER_ADDR): Define.
>         (MD_FROB_UPDATE_CONTEXT): Define.
>         (aarch64_post_extract_frame_addr): New function.
>         (aarch64_post_frob_eh_handler_addr): New function.
>         (aarch64_frob_update_context): New function.
>         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
>         * config.host (aarch64*-*-elf, aarch64*-*-rtems*,
> aarch64*-*-freebsd*):
>         Initialize md_unwind_header to include aarch64-unwind.h.
>         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for
> __aarch64__.
>         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
>         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
>         (uw_frob_return_addr): New function.
>         (_Unwind_DebugHook): Use uw_frob_return_addr.
>

Since you committed this (r244673), GCC fails to build for AArch64:
/tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:
In function 'execute_cfa_program':
/tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:
error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
function)
    fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Christophe

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-20  8:42                           ` Christophe Lyon
@ 2017-01-20  9:46                             ` Jiong Wang
  2017-01-20 10:19                               ` Christophe Lyon
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-20  9:46 UTC (permalink / raw)
  To: Christophe Lyon
  Cc: Richard Earnshaw (lists),
	gcc-patches, James Greenhalgh, Ian Lance Taylor, Joseph Myers,
	Jakub Jelinek



On 20/01/17 08:41, Christophe Lyon wrote:
> Hi Jiong,
>
> On 19 January 2017 at 15:46, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>> Thanks for the review.
>>
>> On 19/01/17 14:18, Richard Earnshaw (lists) wrote:
>>>
>>>>
>>>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
>>>> index
>>>> 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2
>>>> 100644
>>>> --- a/libgcc/unwind-dw2.c
>>>> +++ b/libgcc/unwind-dw2.c
>>>> @@ -136,6 +136,8 @@ struct _Unwind_Context
>>>>   #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
>>>>     /* Context which has version/args_size/by_value fields.  */
>>>>   #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
>>>> +  /* Bit reserved on AArch64, return address has been signed with A key.
>>>> */
>>>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
>>>
>>> Why is this here?   It appears to only be used within the
>>> AArch64-specific header file.
>>
>> I was putting it here so that when we allocate the next general purpose bit,
>> we
>> know clearly that bit 3 is allocated to AArch64 already, and the new general
>> bit
>> needs to go to the next one.  This can avoid bit collision.
>>
>>>> ...
>>>>
>>>> +/* Frob exception handler's address kept in TARGET before installing
>>>> into
>>>> +   CURRENT context.  */
>>>> +
>>>> +static void *
>>>> +uw_frob_return_addr (struct _Unwind_Context *current,
>>>> +                 struct _Unwind_Context *target)
>>>> +{
>>>> +  void *ret_addr = __builtin_frob_return_addr (target->ra);
>>>> +#ifdef MD_POST_FROB_EH_HANDLER_ADDR
>>>> +  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
>>>> +#endif
>>>> +  return ret_addr;
>>>> +}
>>>> +
>>>
>>> I think this function should be marked inline.  The optimizers would
>>> probably inline it anyway, but it seems wrong for us to rely on that.
>>
>> Thanks, fixed.
>>
>> Does the updated patch looks OK to you know?
>>
>> libgcc/
>>
>> 2017-01-19  Jiong Wang  <jiong.wang@arm.com>
>>
>>
>>          * config/aarch64/aarch64-unwind.h: New file.
>>          (DWARF_REGNUM_AARCH64_RA_STATE): Define.
>>          (MD_POST_EXTRACT_ROOT_ADDR): Define.
>>          (MD_POST_EXTRACT_FRAME_ADDR): Define.
>>          (MD_POST_FROB_EH_HANDLER_ADDR): Define.
>>          (MD_FROB_UPDATE_CONTEXT): Define.
>>          (aarch64_post_extract_frame_addr): New function.
>>          (aarch64_post_frob_eh_handler_addr): New function.
>>          (aarch64_frob_update_context): New function.
>>          * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
>>          * config.host (aarch64*-*-elf, aarch64*-*-rtems*,
>> aarch64*-*-freebsd*):
>>          Initialize md_unwind_header to include aarch64-unwind.h.
>>          * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
>>          (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for
>> __aarch64__.
>>          (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
>>          (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
>>          (uw_frob_return_addr): New function.
>>          (_Unwind_DebugHook): Use uw_frob_return_addr.
>>
> Since you committed this (r244673), GCC fails to build for AArch64:
> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:
> In function 'execute_cfa_program':
> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:
> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
> function)
>      fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
>                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Hi Christophe, could you please confirm you svn revision please?

I do have done bootstrap and regression on both x86 and aarch64 before 
commit this patch.  I had forgotten to "svn add" one header file, but 
add it later.

Thanks.

> Christophe

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-20  9:46                             ` Jiong Wang
@ 2017-01-20 10:19                               ` Christophe Lyon
  2017-01-20 10:31                                 ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Christophe Lyon @ 2017-01-20 10:19 UTC (permalink / raw)
  To: Jiong Wang
  Cc: Richard Earnshaw (lists),
	gcc-patches, James Greenhalgh, Ian Lance Taylor, Joseph Myers,
	Jakub Jelinek

On 20 January 2017 at 10:44, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>
>
> On 20/01/17 08:41, Christophe Lyon wrote:
>>
>> Hi Jiong,
>>
>> On 19 January 2017 at 15:46, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>>>
>>> Thanks for the review.
>>>
>>> On 19/01/17 14:18, Richard Earnshaw (lists) wrote:
>>>>
>>>>
>>>>>
>>>>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
>>>>> index
>>>>>
>>>>> 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2
>>>>> 100644
>>>>> --- a/libgcc/unwind-dw2.c
>>>>> +++ b/libgcc/unwind-dw2.c
>>>>> @@ -136,6 +136,8 @@ struct _Unwind_Context
>>>>>   #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
>>>>>     /* Context which has version/args_size/by_value fields.  */
>>>>>   #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
>>>>> +  /* Bit reserved on AArch64, return address has been signed with A
>>>>> key.
>>>>> */
>>>>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
>>>>
>>>>
>>>> Why is this here?   It appears to only be used within the
>>>> AArch64-specific header file.
>>>
>>>
>>> I was putting it here so that when we allocate the next general purpose
>>> bit,
>>> we
>>> know clearly that bit 3 is allocated to AArch64 already, and the new
>>> general
>>> bit
>>> needs to go to the next one.  This can avoid bit collision.
>>>
>>>>> ...
>>>>>
>>>>> +/* Frob exception handler's address kept in TARGET before installing
>>>>> into
>>>>> +   CURRENT context.  */
>>>>> +
>>>>> +static void *
>>>>> +uw_frob_return_addr (struct _Unwind_Context *current,
>>>>> +                 struct _Unwind_Context *target)
>>>>> +{
>>>>> +  void *ret_addr = __builtin_frob_return_addr (target->ra);
>>>>> +#ifdef MD_POST_FROB_EH_HANDLER_ADDR
>>>>> +  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
>>>>> +#endif
>>>>> +  return ret_addr;
>>>>> +}
>>>>> +
>>>>
>>>>
>>>> I think this function should be marked inline.  The optimizers would
>>>> probably inline it anyway, but it seems wrong for us to rely on that.
>>>
>>>
>>> Thanks, fixed.
>>>
>>> Does the updated patch looks OK to you know?
>>>
>>> libgcc/
>>>
>>> 2017-01-19  Jiong Wang  <jiong.wang@arm.com>
>>>
>>>
>>>          * config/aarch64/aarch64-unwind.h: New file.
>>>          (DWARF_REGNUM_AARCH64_RA_STATE): Define.
>>>          (MD_POST_EXTRACT_ROOT_ADDR): Define.
>>>          (MD_POST_EXTRACT_FRAME_ADDR): Define.
>>>          (MD_POST_FROB_EH_HANDLER_ADDR): Define.
>>>          (MD_FROB_UPDATE_CONTEXT): Define.
>>>          (aarch64_post_extract_frame_addr): New function.
>>>          (aarch64_post_frob_eh_handler_addr): New function.
>>>          (aarch64_frob_update_context): New function.
>>>          * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
>>>          * config.host (aarch64*-*-elf, aarch64*-*-rtems*,
>>> aarch64*-*-freebsd*):
>>>          Initialize md_unwind_header to include aarch64-unwind.h.
>>>          * unwind-dw2.c (struct _Unwind_Context): Define
>>> "RA_A_SIGNED_BIT".
>>>          (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for
>>> __aarch64__.
>>>          (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
>>>          (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
>>>          (uw_frob_return_addr): New function.
>>>          (_Unwind_DebugHook): Use uw_frob_return_addr.
>>>
>> Since you committed this (r244673), GCC fails to build for AArch64:
>>
>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:
>> In function 'execute_cfa_program':
>>
>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:
>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
>> function)
>>      fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
>>                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>
> Hi Christophe, could you please confirm you svn revision please?
>
> I do have done bootstrap and regression on both x86 and aarch64 before
> commit this patch.  I had forgotten to "svn add" one header file, but add it
> later.
>

The failures started with r244673, and are still present with r244687.
When did you add the missing file?

> Thanks.
>
>> Christophe
>
>

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-20 10:19                               ` Christophe Lyon
@ 2017-01-20 10:31                                 ` Jiong Wang
  2017-01-20 10:32                                   ` Christophe Lyon
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-20 10:31 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Richard Earnshaw (lists), gcc-patches, James Greenhalgh



On 20/01/17 10:11, Christophe Lyon wrote:
>
>>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:
>>> In function 'execute_cfa_program':
>>>
>>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:
>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
>>> function)
>>>       fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
>>>                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>> Hi Christophe, could you please confirm you svn revision please?
>>
>> I do have done bootstrap and regression on both x86 and aarch64 before
>> commit this patch.  I had forgotten to "svn add" one header file, but add it
>> later.
>>
> The failures started with r244673, and are still present with r244687.
> When did you add the missing file?

It was r244674, https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  
so should have been included in your code.  The faliure looks strange to 
me then,  I will svn up and re-start a fresh bootstrap on AArch64.

>
>> Thanks.
>>
>>> Christophe
>>

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-20 10:31                                 ` Jiong Wang
@ 2017-01-20 10:32                                   ` Christophe Lyon
  2017-01-20 11:55                                     ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Christophe Lyon @ 2017-01-20 10:32 UTC (permalink / raw)
  To: Jiong Wang; +Cc: Richard Earnshaw (lists), gcc-patches, James Greenhalgh

On 20 January 2017 at 11:18, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>
>
> On 20/01/17 10:11, Christophe Lyon wrote:
>>
>>
>>>>
>>>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:
>>>> In function 'execute_cfa_program':
>>>>
>>>>
>>>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:
>>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
>>>> function)
>>>>       fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
>>>>                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>
>>>
>>> Hi Christophe, could you please confirm you svn revision please?
>>>
>>> I do have done bootstrap and regression on both x86 and aarch64 before
>>> commit this patch.  I had forgotten to "svn add" one header file, but add
>>> it
>>> later.
>>>
>> The failures started with r244673, and are still present with r244687.
>> When did you add the missing file?
>
>
> It was r244674, https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  so
> should have been included in your code.  The faliure looks strange to me
> then,  I will svn up and re-start a fresh bootstrap on AArch64.
>

The file is present in my git clone.
I'm not bootstrapping on AArch64, I'm building a cross-compiler on x86_64,
but it shouldn't matter.

>>
>>> Thanks.
>>>
>>>> Christophe
>>>
>>>
>

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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-20  4:15           ` Andrew Pinski
@ 2017-01-20 11:39             ` Jiong Wang
  2017-01-20 13:15               ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-20 11:39 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: gcc-patches, James Greenhalgh, Richard Earnshaw (lists)



On 20/01/17 03:39, Andrew Pinski wrote:
> On Fri, Jan 6, 2017 at 3:47 AM, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>> On 11/11/16 18:22, Jiong Wang wrote:
>>> As described in the cover letter, this patch implements return address
>>> signing
>>> for AArch64, it's controlled by the new option:
>>>
>>>     -msign-return-address=[none | non-leaf | all]
>>>
>>> "none" means don't do return address signing at all on any function.
>>> "non-leaf"
>>> means only sign non-leaf function.  "all" means sign all functions.
>>> Return
>>> address signing is currently disabled on ILP32.  I haven't tested it.
>>>
>>> The instructions added in the architecture are of 2 kinds.
>>>
>>> * In the NOP instruction space, which allows binaries to run without any
>>> traps
>>> on older versions of the architecture. This doesn't give any additional
>>> protection on older hardware but allows for the same binary to be used on
>>> earlier versions of the architecture and newer versions of the
>>> architecture.
>>>
>>> * New instructions that are only valid for v8.3 and will trap if used on
>>> earlier
>>> versions of the architecture.
>>>
>>> At default, once return address signing is enabled, it will only generates
>>> NOP
>>> instruction.
>>>
>>> While if -march=armv8.3-a specified, GCC will try to use the most
>>> efficient
>>> pointer authentication instruction as it can.
>>>
>>> The architecture has 2 user invisible system keys for signing and creating
>>> signed addresses as part of these instructions. For some use case, the
>>> user
>>> might want to use difference key for different functions.  The new option
>>> "-msign-return-address-key=key_name" let GCC select the key used for
>>> return
>>> address signing.  Permissible values are "a_key" for A key and "b_key" for
>>> B
>>> key, and this option are supported by function target attribute and LTO
>>> will
>>> hopefully just work.
>>>
>>>
>>>
>>> gcc/
>>> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>>>
>>>           * config/aarch64/aarch64-opts.h (aarch64_pauth_key_index): New
>>> enum.
>>>           (aarch64_function_type): New enum.
>>>           * config/aarch64/aarch64-protos.h (aarch64_output_sign_auth_reg):
>>> New
>>>           declaration.
>>>           * config/aarch64/aarch64.c (aarch64_expand_prologue): Sign return
>>>           address before it's pushed onto stack.
>>>           (aarch64_expand_epilogue): Authenticate return address fetched
>>> from
>>>           stack.
>>>           (aarch64_output_sign_auth_reg): New function.
>>>           (aarch64_override_options): Sanity check for ILP32 and ISA level.
>>>           (aarch64_attributes): New function attributes for
>>> "sign-return-address",
>>>           "pauth-key".
>>>           * config/aarch64/aarch64.md (UNSPEC_AUTH_REG,
>>> UNSPEC_AUTH_REG1716,
>>>           UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN,
>>>           UNSPEC_STRIP_X30_SIGN): New unspecs.
>>>           ("*do_return"): Generate combined instructions according to key
>>> index.
>>>           ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716",
>>>           "strip_reg_sign", "strip_lr_sign"): New.
>>>           * config/aarch64/aarch64.opt (msign-return-address, mpauth-key):
>>> New.
>>>           * config/aarch64/predicates.md (aarch64_const0_const1): New
>>> predicate.
>>>           * doc/extend.texi (AArch64 Function Attributes): Documents
>>>           "sign-return-address=", "pauth-key".
>>>           * doc/invoke.texi (AArch64 Options): Documents
>>> "-msign-return-address=",
>>>           "-pauth-key".
>>>
>>> gcc/testsuite/
>>> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>>>
>>>           * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>>>           * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.
>>
>> Update the patchset according to new DWARF proposal described at
>>
>>    https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03010.html
> One of these patches of this patch set break ILP32 building for
> aarch64-elf and most likely also aarch64-linux-gnu.
>
> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:
> In function ‘uw_init_context_1’:
> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:1567:6:
> internal compiler error: in emit_move_insn, at expr.c:3698
>     ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
> 0x8270cf emit_move_insn(rtx_def*, rtx_def*)
> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.c:3697
> 0x80867b force_reg(machine_mode, rtx_def*)
Must be the Pmode issue under ILP32, I am testing a fix (I don't have 
full ILP32 environment, so can only test simply by force libgcc build 
with -mabi=ilp32)

>
> Thanks,
> Andrew
>
>
>
>
>> While A key support for return address signing using DW_CFA_GNU_window_save
>> only
>> needs simple modifications on code and associated DWARF generation, B key
>> support is complexer, it needs multiple CIE support in GCC and Binutils, so
>> currently we fall back to DWARF value expression which fully works although
>> requires longer encodings. Value expression also requires a few changes on
>> AArch64 prologue and epilogue hooks that code review will not be easy.
>>
>> Therefore I have removed all B key support code in the initial support patch
>> set,
>> and will organize them into a seperate follow up patchset so that we can do
>> A key
>> code review first.
>>
>> This patch is an update on the return address signing code generation.
>>
>> gcc/
>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>
>>          * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum.
>>          * config/aarch64/aarch64-protos.h
>>          (aarch64_return_address_signing_enabled): New declaration.
>>          * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
>>          New function.
>>          (aarch64_expand_prologue): Sign return address before it's pushed
>> onto
>>          stack.
>>          (aarch64_expand_epilogue): Authenticate return address fetched from
>>          stack.
>>          (aarch64_override_options): Sanity check for ILP32 and ISA level.
>>          (aarch64_attributes): New function attributes for
>> "sign-return-address".
>>          * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP,
>>          UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs.
>>          ("*do_return"): Generate combined instructions according to key
>> index.
>>          ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
>>          * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New
>> integer
>>          iterators.
>>          (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
>>          * config/aarch64/aarch64.opt (msign-return-address=): New.
>>          * doc/extend.texi (AArch64 Function Attributes): Documents
>>          "sign-return-address=".
>>          * doc/invoke.texi (AArch64 Options): Documents
>> "-msign-return-address=".
>>
>> gcc/testsuite/
>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>
>>
>>
>>          * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>>          * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.
>>
>>

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-20 10:32                                   ` Christophe Lyon
@ 2017-01-20 11:55                                     ` Jiong Wang
  2017-01-20 12:14                                       ` Richard Earnshaw (lists)
  2017-01-20 14:33                                       ` Christophe Lyon
  0 siblings, 2 replies; 75+ messages in thread
From: Jiong Wang @ 2017-01-20 11:55 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Richard Earnshaw (lists), gcc-patches, James Greenhalgh

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

On 20/01/17 10:30, Christophe Lyon wrote:
>>>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
>>>>> function)
>>>>>        fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
>>>>>                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>
>>>> Hi Christophe, could you please confirm you svn revision please?
>>>>
>>>> I do have done bootstrap and regression on both x86 and aarch64 before
>>>> commit this patch.  I had forgotten to "svn add" one header file, but add
>>>> it
>>>> later.
>>>>
>>> The failures started with r244673, and are still present with r244687.
>>> When did you add the missing file?
>>
>> It was r244674, https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  so
>> should have been included in your code.  The faliure looks strange to me
>> then,  I will svn up and re-start a fresh bootstrap on AArch64.
>>
> The file is present in my git clone.
> I'm not bootstrapping on AArch64, I'm building a cross-compiler on x86_64,
> but it shouldn't matter.

Hi Christophe,

   Thanks, I reproduced this on cross linux environment, the reason is the header file is not included because of the inhabit_libc guard, while the unwinder header file should always be included.

    I will committed the attached patch as obvious, once I finished a fresh bootstrap, cross elf, cross linux.

    Thanks.

libgcc/

2017-01-20  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/linux-unwind.h: Always include aarch64-unwind.h.



[-- Attachment #2: k.patch --]
[-- Type: text/x-diff, Size: 630 bytes --]

diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
index a8fa1d5..70e5a8a 100644
--- a/libgcc/config/aarch64/linux-unwind.h
+++ b/libgcc/config/aarch64/linux-unwind.h
@@ -20,11 +20,13 @@
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+/* Always include AArch64 unwinder header file.  */
+#include "config/aarch64/aarch64-unwind.h"
+
 #ifndef inhibit_libc
 
 #include <signal.h>
 #include <sys/ucontext.h>
-#include "config/aarch64/aarch64-unwind.h"
 
 
 /* Since insns are always stored LE, on a BE system the opcodes will

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-20 11:55                                     ` Jiong Wang
@ 2017-01-20 12:14                                       ` Richard Earnshaw (lists)
  2017-01-20 14:33                                       ` Christophe Lyon
  1 sibling, 0 replies; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-20 12:14 UTC (permalink / raw)
  To: Jiong Wang, Christophe Lyon; +Cc: gcc-patches, James Greenhalgh

On 20/01/17 11:54, Jiong Wang wrote:
> On 20/01/17 10:30, Christophe Lyon wrote:
>>>>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
>>>>>> function)
>>>>>>        fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
>>>>>>                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>>
>>>>> Hi Christophe, could you please confirm you svn revision please?
>>>>>
>>>>> I do have done bootstrap and regression on both x86 and aarch64 before
>>>>> commit this patch.  I had forgotten to "svn add" one header file,
>>>>> but add
>>>>> it
>>>>> later.
>>>>>
>>>> The failures started with r244673, and are still present with r244687.
>>>> When did you add the missing file?
>>>
>>> It was r244674,
>>> https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  so
>>> should have been included in your code.  The faliure looks strange to me
>>> then,  I will svn up and re-start a fresh bootstrap on AArch64.
>>>
>> The file is present in my git clone.
>> I'm not bootstrapping on AArch64, I'm building a cross-compiler on
>> x86_64,
>> but it shouldn't matter.
> 
> Hi Christophe,
> 
>   Thanks, I reproduced this on cross linux environment, the reason is
> the header file is not included because of the inhabit_libc guard, while
> the unwinder header file should always be included.
> 
>    I will committed the attached patch as obvious, once I finished a
> fresh bootstrap, cross elf, cross linux.
> 

If this survives a cross-build, please just commit it.  It's very
unlikely that a native build will throw up any problems.

R.

>    Thanks.
> 
> libgcc/
> 
> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>
> 
>         * config/aarch64/linux-unwind.h: Always include aarch64-unwind.h.
> 
> 
> 
> k.patch
> 
> 
> diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
> index a8fa1d5..70e5a8a 100644
> --- a/libgcc/config/aarch64/linux-unwind.h
> +++ b/libgcc/config/aarch64/linux-unwind.h
> @@ -20,11 +20,13 @@
>     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +/* Always include AArch64 unwinder header file.  */
> +#include "config/aarch64/aarch64-unwind.h"
> +
>  #ifndef inhibit_libc
>  
>  #include <signal.h>
>  #include <sys/ucontext.h>
> -#include "config/aarch64/aarch64-unwind.h"
>  
>  
>  /* Since insns are always stored LE, on a BE system the opcodes will
> 

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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-20 11:39             ` Jiong Wang
@ 2017-01-20 13:15               ` Jiong Wang
  2017-01-20 16:24                 ` Richard Earnshaw (lists)
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-20 13:15 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: gcc-patches, James Greenhalgh, Richard Earnshaw (lists)

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



On 20/01/17 11:15, Jiong Wang wrote:
>
>
> On 20/01/17 03:39, Andrew Pinski wrote:
>> On Fri, Jan 6, 2017 at 3:47 AM, Jiong Wang <jiong.wang@foss.arm.com> 
>> wrote:
>>> On 11/11/16 18:22, Jiong Wang wrote:
>>>> As described in the cover letter, this patch implements return address
>>>> signing
>>>> for AArch64, it's controlled by the new option:
>>>>
>>>>     -msign-return-address=[none | non-leaf | all]
>>>>
>>>> "none" means don't do return address signing at all on any function.
>>>> "non-leaf"
>>>> means only sign non-leaf function.  "all" means sign all functions.
>>>> Return
>>>> address signing is currently disabled on ILP32.  I haven't tested it.
>>>>
>>>> The instructions added in the architecture are of 2 kinds.
>>>>
>>>> * In the NOP instruction space, which allows binaries to run 
>>>> without any
>>>> traps
>>>> on older versions of the architecture. This doesn't give any 
>>>> additional
>>>> protection on older hardware but allows for the same binary to be 
>>>> used on
>>>> earlier versions of the architecture and newer versions of the
>>>> architecture.
>>>>
>>>> * New instructions that are only valid for v8.3 and will trap if 
>>>> used on
>>>> earlier
>>>> versions of the architecture.
>>>>
>>>> At default, once return address signing is enabled, it will only 
>>>> generates
>>>> NOP
>>>> instruction.
>>>>
>>>> While if -march=armv8.3-a specified, GCC will try to use the most
>>>> efficient
>>>> pointer authentication instruction as it can.
>>>>
>>>> The architecture has 2 user invisible system keys for signing and 
>>>> creating
>>>> signed addresses as part of these instructions. For some use case, the
>>>> user
>>>> might want to use difference key for different functions. The new 
>>>> option
>>>> "-msign-return-address-key=key_name" let GCC select the key used for
>>>> return
>>>> address signing.  Permissible values are "a_key" for A key and 
>>>> "b_key" for
>>>> B
>>>> key, and this option are supported by function target attribute and 
>>>> LTO
>>>> will
>>>> hopefully just work.
>>>>
>>>>
>>>>
>>>> gcc/
>>>> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>>>>
>>>>           * config/aarch64/aarch64-opts.h 
>>>> (aarch64_pauth_key_index): New
>>>> enum.
>>>>           (aarch64_function_type): New enum.
>>>>           * config/aarch64/aarch64-protos.h 
>>>> (aarch64_output_sign_auth_reg):
>>>> New
>>>>           declaration.
>>>>           * config/aarch64/aarch64.c (aarch64_expand_prologue): 
>>>> Sign return
>>>>           address before it's pushed onto stack.
>>>>           (aarch64_expand_epilogue): Authenticate return address 
>>>> fetched
>>>> from
>>>>           stack.
>>>>           (aarch64_output_sign_auth_reg): New function.
>>>>           (aarch64_override_options): Sanity check for ILP32 and 
>>>> ISA level.
>>>>           (aarch64_attributes): New function attributes for
>>>> "sign-return-address",
>>>>           "pauth-key".
>>>>           * config/aarch64/aarch64.md (UNSPEC_AUTH_REG,
>>>> UNSPEC_AUTH_REG1716,
>>>>           UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN,
>>>>           UNSPEC_STRIP_X30_SIGN): New unspecs.
>>>>           ("*do_return"): Generate combined instructions according 
>>>> to key
>>>> index.
>>>>           ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716",
>>>>           "strip_reg_sign", "strip_lr_sign"): New.
>>>>           * config/aarch64/aarch64.opt (msign-return-address, 
>>>> mpauth-key):
>>>> New.
>>>>           * config/aarch64/predicates.md (aarch64_const0_const1): New
>>>> predicate.
>>>>           * doc/extend.texi (AArch64 Function Attributes): Documents
>>>>           "sign-return-address=", "pauth-key".
>>>>           * doc/invoke.texi (AArch64 Options): Documents
>>>> "-msign-return-address=",
>>>>           "-pauth-key".
>>>>
>>>> gcc/testsuite/
>>>> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>>>>
>>>>           * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>>>>           * gcc.target/aarch64/return_address_sign_scope_1.c: New 
>>>> testcase.
>>>
>>> Update the patchset according to new DWARF proposal described at
>>>
>>>    https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03010.html
>> One of these patches of this patch set break ILP32 building for
>> aarch64-elf and most likely also aarch64-linux-gnu.
>>
>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c: 
>>
>> In function ‘uw_init_context_1’:
>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:1567:6: 
>>
>> internal compiler error: in emit_move_insn, at expr.c:3698
>>     ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
>> 0x8270cf emit_move_insn(rtx_def*, rtx_def*)
>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.c:3697 
>>
>> 0x80867b force_reg(machine_mode, rtx_def*)
> Must be the Pmode issue under ILP32, I am testing a fix (I don't have 
> full ILP32 environment, so can only test simply by force libgcc build 
> with -mabi=ilp32)

Here is the patch.

For XPACLRI builtin which drops the signature in a pointer, it's prototype is  "void *foo (void *)"
FOR PAC/AUT builtin which sign or authenticate a pointer, it's prototype is "void *foo (void *, uint64)".

This patch adjusted those modes to make sure they strictly follow the C prototype. I also borrow the type define in ARM backend

   typedef unsigned _uw64 __attribute__((mode(__DI__)));

And this is need to type cast the salt value which is always DImode.

It passed my local ILP32 cross build.

OK for trunk?

gcc/
2017-01-20  Jiong Wang  <jiong.wang@arm.com>
         * config/aarch64/aarch64-builtins.c (aarch64_expand_builtin): Fix modes
         for AARCH64_PAUTH_BUILTIN_XPACLRI, AARCH64_PAUTH_BUILTIN_PACIA1716 and
         AARCH64_PAUTH_BUILTIN_AUTIA1716.

libgcc/
         * config/aarch64/aarch64-unwind.h (_uw64): New typedef.
         (aarch64_post_extract_frame_addr):  Cast salt to _uw64.
         (aarch64_post_frob_eh_handler_addr): Likewise.


[-- Attachment #2: k.patch --]
[-- Type: text/x-diff, Size: 3067 bytes --]

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 6c6530c..7ef351e 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -1333,18 +1333,20 @@ aarch64_expand_builtin (tree exp,
     case AARCH64_PAUTH_BUILTIN_PACIA1716:
     case AARCH64_PAUTH_BUILTIN_XPACLRI:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = force_reg (Pmode, expand_normal (arg0));
+      /* Operand0 should have ptr_mode as its a ptr_type_node, this makes both
+	 LP64 and ILP32 expand correctly.  */
+      op0 = force_reg (ptr_mode, expand_normal (arg0));
 
       if (!target)
-	target = gen_reg_rtx (Pmode);
+	target = gen_reg_rtx (ptr_mode);
       else
-	target = force_reg (Pmode, target);
+	target = force_reg (ptr_mode, target);
 
       emit_move_insn (target, op0);
 
       if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
 	{
-	  rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
+	  rtx lr = gen_rtx_REG (ptr_mode, R30_REGNUM);
 	  icode = CODE_FOR_xpaclri;
 	  emit_move_insn (lr, op0);
 	  emit_insn (GEN_FCN (icode) ());
@@ -1353,12 +1355,13 @@ aarch64_expand_builtin (tree exp,
       else
 	{
 	  tree arg1 = CALL_EXPR_ARG (exp, 1);
-	  rtx op1 = force_reg (Pmode, expand_normal (arg1));
+	  /* Operand1 for either PAC or AUT is a unsigned_intDI_type_node.  */
+	  rtx op1 = force_reg (DImode, expand_normal (arg1));
 	  icode = (fcode == AARCH64_PAUTH_BUILTIN_PACIA1716
 		   ? CODE_FOR_paci1716 : CODE_FOR_auti1716);
 
-	  rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
-	  rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
+	  rtx x16_reg = gen_rtx_REG (DImode, R16_REGNUM);
+	  rtx x17_reg = gen_rtx_REG (ptr_mode, R17_REGNUM);
 	  emit_move_insn (x17_reg, op0);
 	  emit_move_insn (x16_reg, op1);
 	  emit_insn (GEN_FCN (icode) ());
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
index a43d965..7dd2549 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -35,6 +35,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define MD_FROB_UPDATE_CONTEXT(context, fs) \
   aarch64_frob_update_context (context, fs)
 
+typedef unsigned _uw64 __attribute__((mode(__DI__)));
+
 /* Do AArch64 private extraction on ADDR based on context info CONTEXT and
    unwind frame info FS.  If ADDR is signed, we do address authentication on it
    using CFA of current frame.  */
@@ -45,7 +47,7 @@ aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
 {
   if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
     {
-      _Unwind_Word salt = (_Unwind_Word) context->cfa;
+      _uw64 salt = (_uw64) context->cfa;
       return __builtin_aarch64_autia1716 (addr, salt);
     }
   else
@@ -64,7 +66,7 @@ aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
 {
   if (current->flags & RA_A_SIGNED_BIT)
     return __builtin_aarch64_pacia1716 (handler_addr,
-					(_Unwind_Word) current->cfa);
+					(_uw64) current->cfa);
   else
     return handler_addr;
 }

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

* Re: [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros)
  2017-01-20 11:55                                     ` Jiong Wang
  2017-01-20 12:14                                       ` Richard Earnshaw (lists)
@ 2017-01-20 14:33                                       ` Christophe Lyon
  1 sibling, 0 replies; 75+ messages in thread
From: Christophe Lyon @ 2017-01-20 14:33 UTC (permalink / raw)
  To: Jiong Wang; +Cc: Richard Earnshaw (lists), gcc-patches, James Greenhalgh

On 20 January 2017 at 12:54, Jiong Wang <jiong.wang@foss.arm.com> wrote:
> On 20/01/17 10:30, Christophe Lyon wrote:
>>>>>>
>>>>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
>>>>>> function)
>>>>>>        fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
>>>>>>                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>>
>>>>>
>>>>> Hi Christophe, could you please confirm you svn revision please?
>>>>>
>>>>> I do have done bootstrap and regression on both x86 and aarch64 before
>>>>> commit this patch.  I had forgotten to "svn add" one header file, but
>>>>> add
>>>>> it
>>>>> later.
>>>>>
>>>> The failures started with r244673, and are still present with r244687.
>>>> When did you add the missing file?
>>>
>>>
>>> It was r244674, https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  so
>>> should have been included in your code.  The faliure looks strange to me
>>> then,  I will svn up and re-start a fresh bootstrap on AArch64.
>>>
>> The file is present in my git clone.
>> I'm not bootstrapping on AArch64, I'm building a cross-compiler on x86_64,
>> but it shouldn't matter.
>
>
> Hi Christophe,
>
>   Thanks, I reproduced this on cross linux environment, the reason is the
> header file is not included because of the inhabit_libc guard, while the
> unwinder header file should always be included.
>
>    I will committed the attached patch as obvious, once I finished a fresh
> bootstrap, cross elf, cross linux.
>

After you committed this (r244710), my cross build for aarch64-linux-gnu
now passes.

I'm now left with the build failure reported by Andrew on aarch64(_be)-none-elf.

Thanks for the fix.

Christophe.

>    Thanks.
>
> libgcc/
>
> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>
>
>         * config/aarch64/linux-unwind.h: Always include aarch64-unwind.h.
>
>

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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-20 13:15               ` Jiong Wang
@ 2017-01-20 16:24                 ` Richard Earnshaw (lists)
  2017-01-20 18:30                   ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-20 16:24 UTC (permalink / raw)
  To: Jiong Wang, Andrew Pinski; +Cc: gcc-patches, James Greenhalgh

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=us-ascii, Size: 9771 bytes --]

On 20/01/17 12:36, Jiong Wang wrote:
> 
> 
> On 20/01/17 11:15, Jiong Wang wrote:
>>
>>
>> On 20/01/17 03:39, Andrew Pinski wrote:
>>> On Fri, Jan 6, 2017 at 3:47 AM, Jiong Wang <jiong.wang@foss.arm.com>
>>> wrote:
>>>> On 11/11/16 18:22, Jiong Wang wrote:
>>>>> As described in the cover letter, this patch implements return address
>>>>> signing
>>>>> for AArch64, it's controlled by the new option:
>>>>>
>>>>>     -msign-return-address=[none | non-leaf | all]
>>>>>
>>>>> "none" means don't do return address signing at all on any function.
>>>>> "non-leaf"
>>>>> means only sign non-leaf function.  "all" means sign all functions.
>>>>> Return
>>>>> address signing is currently disabled on ILP32.  I haven't tested it.
>>>>>
>>>>> The instructions added in the architecture are of 2 kinds.
>>>>>
>>>>> * In the NOP instruction space, which allows binaries to run
>>>>> without any
>>>>> traps
>>>>> on older versions of the architecture. This doesn't give any
>>>>> additional
>>>>> protection on older hardware but allows for the same binary to be
>>>>> used on
>>>>> earlier versions of the architecture and newer versions of the
>>>>> architecture.
>>>>>
>>>>> * New instructions that are only valid for v8.3 and will trap if
>>>>> used on
>>>>> earlier
>>>>> versions of the architecture.
>>>>>
>>>>> At default, once return address signing is enabled, it will only
>>>>> generates
>>>>> NOP
>>>>> instruction.
>>>>>
>>>>> While if -march=armv8.3-a specified, GCC will try to use the most
>>>>> efficient
>>>>> pointer authentication instruction as it can.
>>>>>
>>>>> The architecture has 2 user invisible system keys for signing and
>>>>> creating
>>>>> signed addresses as part of these instructions. For some use case, the
>>>>> user
>>>>> might want to use difference key for different functions. The new
>>>>> option
>>>>> "-msign-return-address-key=key_name" let GCC select the key used for
>>>>> return
>>>>> address signing.  Permissible values are "a_key" for A key and
>>>>> "b_key" for
>>>>> B
>>>>> key, and this option are supported by function target attribute and
>>>>> LTO
>>>>> will
>>>>> hopefully just work.
>>>>>
>>>>>
>>>>>
>>>>> gcc/
>>>>> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>>>>>
>>>>>           * config/aarch64/aarch64-opts.h
>>>>> (aarch64_pauth_key_index): New
>>>>> enum.
>>>>>           (aarch64_function_type): New enum.
>>>>>           * config/aarch64/aarch64-protos.h
>>>>> (aarch64_output_sign_auth_reg):
>>>>> New
>>>>>           declaration.
>>>>>           * config/aarch64/aarch64.c (aarch64_expand_prologue):
>>>>> Sign return
>>>>>           address before it's pushed onto stack.
>>>>>           (aarch64_expand_epilogue): Authenticate return address
>>>>> fetched
>>>>> from
>>>>>           stack.
>>>>>           (aarch64_output_sign_auth_reg): New function.
>>>>>           (aarch64_override_options): Sanity check for ILP32 and
>>>>> ISA level.
>>>>>           (aarch64_attributes): New function attributes for
>>>>> "sign-return-address",
>>>>>           "pauth-key".
>>>>>           * config/aarch64/aarch64.md (UNSPEC_AUTH_REG,
>>>>> UNSPEC_AUTH_REG1716,
>>>>>           UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN,
>>>>>           UNSPEC_STRIP_X30_SIGN): New unspecs.
>>>>>           ("*do_return"): Generate combined instructions according
>>>>> to key
>>>>> index.
>>>>>           ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716",
>>>>>           "strip_reg_sign", "strip_lr_sign"): New.
>>>>>           * config/aarch64/aarch64.opt (msign-return-address,
>>>>> mpauth-key):
>>>>> New.
>>>>>           * config/aarch64/predicates.md (aarch64_const0_const1): New
>>>>> predicate.
>>>>>           * doc/extend.texi (AArch64 Function Attributes): Documents
>>>>>           "sign-return-address=", "pauth-key".
>>>>>           * doc/invoke.texi (AArch64 Options): Documents
>>>>> "-msign-return-address=",
>>>>>           "-pauth-key".
>>>>>
>>>>> gcc/testsuite/
>>>>> 2016-11-09  Jiong Wang<jiong.wang@arm.com>
>>>>>
>>>>>           * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>>>>>           * gcc.target/aarch64/return_address_sign_scope_1.c: New
>>>>> testcase.
>>>>
>>>> Update the patchset according to new DWARF proposal described at
>>>>
>>>>    https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03010.html
>>> One of these patches of this patch set break ILP32 building for
>>> aarch64-elf and most likely also aarch64-linux-gnu.
>>>
>>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:
>>>
>>> In function ‘uw_init_context_1’:
>>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:1567:6:
>>>
>>> internal compiler error: in emit_move_insn, at expr.c:3698
>>>     ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
>>> 0x8270cf emit_move_insn(rtx_def*, rtx_def*)
>>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.c:3697
>>>
>>> 0x80867b force_reg(machine_mode, rtx_def*)
>> Must be the Pmode issue under ILP32, I am testing a fix (I don't have
>> full ILP32 environment, so can only test simply by force libgcc build
>> with -mabi=ilp32)
> 
> Here is the patch.
> 
> For XPACLRI builtin which drops the signature in a pointer, it's
> prototype is  "void *foo (void *)"
> FOR PAC/AUT builtin which sign or authenticate a pointer, it's prototype
> is "void *foo (void *, uint64)".
> 
> This patch adjusted those modes to make sure they strictly follow the C
> prototype. I also borrow the type define in ARM backend
> 
>   typedef unsigned _uw64 __attribute__((mode(__DI__)));
> 
> And this is need to type cast the salt value which is always DImode.
> 
> It passed my local ILP32 cross build.
> 
> OK for trunk?
> 
> gcc/
> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>
>         * config/aarch64/aarch64-builtins.c (aarch64_expand_builtin):
> Fix modes
>         for AARCH64_PAUTH_BUILTIN_XPACLRI,
> AARCH64_PAUTH_BUILTIN_PACIA1716 and
>         AARCH64_PAUTH_BUILTIN_AUTIA1716.
> 
> libgcc/
>         * config/aarch64/aarch64-unwind.h (_uw64): New typedef.
>         (aarch64_post_extract_frame_addr):  Cast salt to _uw64.
>         (aarch64_post_frob_eh_handler_addr): Likewise.
> 
> 

Hmm, we currently don't support ILP32 at all for pointer signing (sorry
("Return address signing is only supported for -mabi=lp64");), so I
wonder if it would be better for now to simply suppress all the new
hooks in aarch64-unwind.h ifdef __ILP32__.

R.

> k.patch
> 
> 
> diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
> index 6c6530c..7ef351e 100644
> --- a/gcc/config/aarch64/aarch64-builtins.c
> +++ b/gcc/config/aarch64/aarch64-builtins.c
> @@ -1333,18 +1333,20 @@ aarch64_expand_builtin (tree exp,
>      case AARCH64_PAUTH_BUILTIN_PACIA1716:
>      case AARCH64_PAUTH_BUILTIN_XPACLRI:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = force_reg (Pmode, expand_normal (arg0));
> +      /* Operand0 should have ptr_mode as its a ptr_type_node, this makes both
> +	 LP64 and ILP32 expand correctly.  */
> +      op0 = force_reg (ptr_mode, expand_normal (arg0));
>  
>        if (!target)
> -	target = gen_reg_rtx (Pmode);
> +	target = gen_reg_rtx (ptr_mode);
>        else
> -	target = force_reg (Pmode, target);
> +	target = force_reg (ptr_mode, target);
>  
>        emit_move_insn (target, op0);
>  
>        if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
>  	{
> -	  rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
> +	  rtx lr = gen_rtx_REG (ptr_mode, R30_REGNUM);
>  	  icode = CODE_FOR_xpaclri;
>  	  emit_move_insn (lr, op0);
>  	  emit_insn (GEN_FCN (icode) ());
> @@ -1353,12 +1355,13 @@ aarch64_expand_builtin (tree exp,
>        else
>  	{
>  	  tree arg1 = CALL_EXPR_ARG (exp, 1);
> -	  rtx op1 = force_reg (Pmode, expand_normal (arg1));
> +	  /* Operand1 for either PAC or AUT is a unsigned_intDI_type_node.  */
> +	  rtx op1 = force_reg (DImode, expand_normal (arg1));
>  	  icode = (fcode == AARCH64_PAUTH_BUILTIN_PACIA1716
>  		   ? CODE_FOR_paci1716 : CODE_FOR_auti1716);
>  
> -	  rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
> -	  rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
> +	  rtx x16_reg = gen_rtx_REG (DImode, R16_REGNUM);
> +	  rtx x17_reg = gen_rtx_REG (ptr_mode, R17_REGNUM);
>  	  emit_move_insn (x17_reg, op0);
>  	  emit_move_insn (x16_reg, op1);
>  	  emit_insn (GEN_FCN (icode) ());
> diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
> index a43d965..7dd2549 100644
> --- a/libgcc/config/aarch64/aarch64-unwind.h
> +++ b/libgcc/config/aarch64/aarch64-unwind.h
> @@ -35,6 +35,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>  #define MD_FROB_UPDATE_CONTEXT(context, fs) \
>    aarch64_frob_update_context (context, fs)
>  
> +typedef unsigned _uw64 __attribute__((mode(__DI__)));
> +
>  /* Do AArch64 private extraction on ADDR based on context info CONTEXT and
>     unwind frame info FS.  If ADDR is signed, we do address authentication on it
>     using CFA of current frame.  */
> @@ -45,7 +47,7 @@ aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
>  {
>    if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
>      {
> -      _Unwind_Word salt = (_Unwind_Word) context->cfa;
> +      _uw64 salt = (_uw64) context->cfa;
>        return __builtin_aarch64_autia1716 (addr, salt);
>      }
>    else
> @@ -64,7 +66,7 @@ aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
>  {
>    if (current->flags & RA_A_SIGNED_BIT)
>      return __builtin_aarch64_pacia1716 (handler_addr,
> -					(_Unwind_Word) current->cfa);
> +					(_uw64) current->cfa);
>    else
>      return handler_addr;
>  }
> 

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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-20 16:24                 ` Richard Earnshaw (lists)
@ 2017-01-20 18:30                   ` Jiong Wang
  2017-01-20 18:49                     ` Jiong Wang
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-20 18:30 UTC (permalink / raw)
  To: Richard Earnshaw (lists), Andrew Pinski; +Cc: gcc-patches, James Greenhalgh

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


>> Here is the patch.
>>
>> For XPACLRI builtin which drops the signature in a pointer, it's
>> prototype is  "void *foo (void *)"
>> FOR PAC/AUT builtin which sign or authenticate a pointer, it's prototype
>> is "void *foo (void *, uint64)".
>>
>> This patch adjusted those modes to make sure they strictly follow the C
>> prototype. I also borrow the type define in ARM backend
>>
>>    typedef unsigned _uw64 __attribute__((mode(__DI__)));
>>
>> And this is need to type cast the salt value which is always DImode.
>>
>> It passed my local ILP32 cross build.
>>
>> OK for trunk?
>>
>> gcc/
>> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>
>>          * config/aarch64/aarch64-builtins.c (aarch64_expand_builtin):
>> Fix modes
>>          for AARCH64_PAUTH_BUILTIN_XPACLRI,
>> AARCH64_PAUTH_BUILTIN_PACIA1716 and
>>          AARCH64_PAUTH_BUILTIN_AUTIA1716.
>>
>> libgcc/
>>          * config/aarch64/aarch64-unwind.h (_uw64): New typedef.
>>          (aarch64_post_extract_frame_addr):  Cast salt to _uw64.
>>          (aarch64_post_frob_eh_handler_addr): Likewise.
>>
>>
> Hmm, we currently don't support ILP32 at all for pointer signing (sorry
> ("Return address signing is only supported for -mabi=lp64");), so I
> wonder if it would be better for now to simply suppress all the new
> hooks in aarch64-unwind.h ifdef __ILP32__.
>
> R.
>

OK, the attached patch disable the building of pointer signing code in libgcc
on ILP32 mode, except the macro bit RA_A_SIGNED_BIT is still defined as I
want to book this bit for ILP32 as LP64 in case we later enable ILP32 support.

All pauth builtins are not registered as well for ILP32 mode as these builtins
are supposed to be used by libgcc unwinder code only.

I also gated the three new testcases for return address signing using the
following directive and verified it works under my dejagnu environment.

{ dg-require-effective-target lp64 }

multilib cross build finished (lp64, ilp32), OK for trunk?

BTW, the mode fix patch doesn't have conflict with this patch, we may
still need it if we want to enable ILP32 support later.

Thanks.

gcc/
2017-01-20  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-builtins.c (aarch64_init_builtins): Don't
         register pauth builtins for ILP32.

libgcc/
         * config/aarch64/aarch64-unwind.h: Restrict this file on LP64 only.
         * unwind-dw2.c (execute_cfa_program):  Only multiplexing
         DW_CFA_GNU_window_save for AArch64 LP64.



[-- Attachment #2: k.patch --]
[-- Type: text/x-diff, Size: 4069 bytes --]

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 7ef351eb53b21c94a07dbd7c49813276dfcebdb2..66bcb9ad5872d1f6cac4ce9613806eb390be33af 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -983,9 +983,14 @@ aarch64_init_builtins (void)
   aarch64_init_crc32_builtins ();
   aarch64_init_builtin_rsqrt ();
 
-/* Initialize pointer authentication builtins which are backed by instructions
-   in NOP encoding space.  */
-  aarch64_init_pauth_hint_builtins ();
+  /* Initialize pointer authentication builtins which are backed by instructions
+     in NOP encoding space.
+
+     NOTE: these builtins are supposed to be used by libgcc unwinder only, as
+     there is no support on return address signing under ILP32, we don't
+     register them.  */
+  if (!TARGET_ILP32)
+    aarch64_init_pauth_hint_builtins ();
 }
 
 tree
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
index fda72a414f1df7e81785864e994681e3695852f1..f87c3d28d1edff473a787a39a436e57076f97508 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
@@ -1,6 +1,7 @@
 /* Testing return address signing where no combined instructions used.  */
 /* { dg-do compile } */
 /* { dg-options "-O2 -msign-return-address=all" } */
+/* { dg-require-effective-target lp64 } */
 
 int foo (int);
 
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
index 54fe47a69723d182c65941ddb73e2f1a5aa0af84..c5c1439b92e6637f85c47c6161cd797c0d68df25 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
@@ -1,6 +1,7 @@
 /* Testing return address signing where combined instructions used.  */
 /* { dg-do compile } */
 /* { dg-options "-O2 -msign-return-address=all" } */
+/* { dg-require-effective-target lp64 } */
 
 int foo (int);
 int bar (int, int);
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
index adc5effdded8900b2dfb68459883d399ebd91ac8..7d9ec6eebd1ce452013d2895a551671c59e98f0c 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
@@ -1,6 +1,7 @@
 /* Testing the disable of return address signing.  */
 /* { dg-do compile } */
 /* { dg-options "-O2 -msign-return-address=all" } */
+/* { dg-require-effective-target lp64 } */
 
 int bar (int, int);
 
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
index 7dd2549dbda501314112fa36b00f298342416a6a..76f7ea8a4e72133160f8caee95e31bcf9292c951 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -22,7 +22,7 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
-#ifndef AARCH64_UNWIND_H
+#if !defined (AARCH64_UNWIND_H) && !defined (__ILP32__)
 #define AARCH64_UNWIND_H
 
 #define DWARF_REGNUM_AARCH64_RA_STATE 34
@@ -86,4 +86,4 @@ aarch64_frob_update_context (struct _Unwind_Context *context,
   return;
 }
 
-#endif /* defined AARCH64_UNWIND_H */
+#endif /* defined AARCH64_UNWIND_H && defined __ILP32__ */
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index fe74387992ab7f10c141d7b62f72a755878612c5..3f26eaf73de3116b538dc8ba0a99f12de939c5e5 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -1187,7 +1187,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
 	  break;
 
 	case DW_CFA_GNU_window_save:
-#ifdef __aarch64__
+#if defined (__aarch64__) && !defined (__ILP32__)
 	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
 	     return address signing status.  */
 	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-20 18:30                   ` Jiong Wang
@ 2017-01-20 18:49                     ` Jiong Wang
  2017-01-20 19:14                       ` Richard Earnshaw (lists)
  0 siblings, 1 reply; 75+ messages in thread
From: Jiong Wang @ 2017-01-20 18:49 UTC (permalink / raw)
  To: Richard Earnshaw (lists), Andrew Pinski; +Cc: gcc-patches, James Greenhalgh


On 20/01/17 18:23, Jiong Wang wrote:
>
> OK, the attached patch disable the building of pointer signing code in 
> libgcc
> on ILP32 mode, except the macro bit RA_A_SIGNED_BIT is still defined as I
> want to book this bit for ILP32 as LP64 in case we later enable ILP32 
> support.
>
> All pauth builtins are not registered as well for ILP32 mode as these 
> builtins
> are supposed to be used by libgcc unwinder code only.
>
> I also gated the three new testcases for return address signing using the
> following directive and verified it works under my dejagnu environment.
>
> { dg-require-effective-target lp64 }
>
> multilib cross build finished (lp64, ilp32), OK for trunk?
>
> BTW, the mode fix patch doesn't have conflict with this patch, we may
> still need it if we want to enable ILP32 support later.
>
> Thanks.
>
> gcc/
> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>
>
>         * config/aarch64/aarch64-builtins.c (aarch64_init_builtins): 
> Don't
>         register pauth builtins for ILP32.
>
> libgcc/
>         * config/aarch64/aarch64-unwind.h: Restrict this file on LP64 
> only.
>         * unwind-dw2.c (execute_cfa_program):  Only multiplexing
>         DW_CFA_GNU_window_save for AArch64 LP64.
>
>

Missing testcase change in Changelog, added:

gcc/
2017-01-20  Jiong Wang  <jiong.wang@arm.com>

          * config/aarch64/aarch64-builtins.c (aarch64_init_builtins): Register
          register pauth builtins for LP64 only.
          * testsuite/gcc.target/aarch64/return_address_sign_1.c: Enable on LP64
          only.
          * testsuite/gcc.target/aarch64/return_address_sign_2.c: Likewise.
          * testsuite/gcc.target/aarch64/return_address_sign_3.c: Likewise.

libgcc/
          * config/aarch64/aarch64-unwind.h: Empty this file on ILP32.
          * unwind-dw2.c (execute_cfa_program):  Only multiplexing
          DW_CFA_GNU_window_save for AArch64 and LP64.


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

* Re: [1/5][AArch64] Return address protection on AArch64
  2017-01-20 18:49                     ` Jiong Wang
@ 2017-01-20 19:14                       ` Richard Earnshaw (lists)
  0 siblings, 0 replies; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-01-20 19:14 UTC (permalink / raw)
  To: Jiong Wang, Andrew Pinski; +Cc: gcc-patches, James Greenhalgh

On 20/01/17 18:30, Jiong Wang wrote:
> 
> On 20/01/17 18:23, Jiong Wang wrote:
>>
>> OK, the attached patch disable the building of pointer signing code in
>> libgcc
>> on ILP32 mode, except the macro bit RA_A_SIGNED_BIT is still defined as I
>> want to book this bit for ILP32 as LP64 in case we later enable ILP32
>> support.
>>
>> All pauth builtins are not registered as well for ILP32 mode as these
>> builtins
>> are supposed to be used by libgcc unwinder code only.
>>
>> I also gated the three new testcases for return address signing using the
>> following directive and verified it works under my dejagnu environment.
>>
>> { dg-require-effective-target lp64 }
>>
>> multilib cross build finished (lp64, ilp32), OK for trunk?
>>
>> BTW, the mode fix patch doesn't have conflict with this patch, we may
>> still need it if we want to enable ILP32 support later.
>>
>> Thanks.
>>
>> gcc/
>> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>
>>
>>         * config/aarch64/aarch64-builtins.c (aarch64_init_builtins):
>> Don't
>>         register pauth builtins for ILP32.
>>
>> libgcc/
>>         * config/aarch64/aarch64-unwind.h: Restrict this file on LP64
>> only.
>>         * unwind-dw2.c (execute_cfa_program):  Only multiplexing
>>         DW_CFA_GNU_window_save for AArch64 LP64.
>>
>>
> 
> Missing testcase change in Changelog, added:
> 
> gcc/
> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>
> 
>          * config/aarch64/aarch64-builtins.c (aarch64_init_builtins):
> Register
>          register pauth builtins for LP64 only.
>          * testsuite/gcc.target/aarch64/return_address_sign_1.c: Enable
> on LP64
>          only.
>          * testsuite/gcc.target/aarch64/return_address_sign_2.c: Likewise.
>          * testsuite/gcc.target/aarch64/return_address_sign_3.c: Likewise.
> 
> libgcc/
>          * config/aarch64/aarch64-unwind.h: Empty this file on ILP32.
>          * unwind-dw2.c (execute_cfa_program):  Only multiplexing
>          DW_CFA_GNU_window_save for AArch64 and LP64.
> 
> 

The testsuite has its own ChangeLog file.

Otherwise OK.

R.

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

* Ping [AArch64] Accelerate -fstack-protector
  2017-01-18 17:10                   ` [AArch64] " Jiong Wang
@ 2017-02-07 16:06                     ` Jiong Wang
  2017-02-15 16:06                     ` [AArch64] Accelerate -fstack-protector through pointer authentication extension Richard Earnshaw (lists)
  1 sibling, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2017-02-07 16:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw (lists), James Greenhalgh

On 18/01/17 17:10, Jiong Wang wrote:
> aarch64 cross check OK with the following options enabled on all testcases.
>     -fstack-protector-all -mstack-protector-pauth
>
> OK for trunk?
>                                                                     gcc/
> 2017-01-18  Jiong Wang  <jiong.wang@arm.com>
>            * config/aarch64/aarch64-protos.h
>         (aarch64_pauth_stack_protector_enabled): New declaration.
>         * config/aarch64/aarch64.c (aarch64_layout_frame): Swap callee-save area
>         and locals area when aarch64_pauth_stack_protector_enabled returns true.
>         (aarch64_stack_protect_runtime_enabled): New function.
>         (aarch64_pauth_stack_protector_enabled): New function.
>         (aarch64_return_address_signing_enabled): Enabled by
>         aarch64_pauth_stack_protector_enabled.
>         (aarch64_override_options): Sanity check for -mstack-protector-pauth.
>         (TARGET_STACK_PROTECT_RUNTIME_ENABLED_P): Define.
>         * config/aarch64/aarch64.h (LINK_SSP_SPEC): Likewise.
>         * config/aarch64/aarch64.opt (-mstack-protector-pauth): New option.
>         * doc/invoke.texi (AArch64 Options): Documents -mstack-protector-pauth.
>
> gcc/testsuite/
>         * gcc.target/aarch64/stack_protector_1.c: New test.

I'd like to ping this patch which acclerates GCC -fstack-protector using
ARMv8.3-A Pointer Authentication Extension.  The whole acceleration will
only be enabled through the new option "-mstack-protector-pauth" which is
disabled at default.

This patch does not touch any generic code and does not change GCC codegen on
AArch64 at default, it should be with very low risk.  So is it OK to commit
to GCC trunk?

Code compiled with "-mstack-protector-pauth" can co-work with code compiled
without "-mstack-protector-pauth".  The only problem is when
"-mstack-protector-pauth" is specified, "-lssp/-lssp_nonshared" won't be implied
as the software runtime supports are not required any more.  So if the user has
some object files compiled using default stack protector and wants them to be
linked with object files compiled using "-mstack-protector-pauth", if
"-mstack-protector-pauth" appear in the final command line and "gcc" is used as
linker driver, then "-lssp/-lssp_nonshared" needs to be specified explicitly.

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

* Re: [AArch64] Accelerate -fstack-protector through pointer authentication extension
  2017-01-18 17:10                   ` [AArch64] " Jiong Wang
  2017-02-07 16:06                     ` Ping [AArch64] Accelerate -fstack-protector Jiong Wang
@ 2017-02-15 16:06                     ` Richard Earnshaw (lists)
  2017-02-15 17:30                       ` Jiong Wang
  1 sibling, 1 reply; 75+ messages in thread
From: Richard Earnshaw (lists) @ 2017-02-15 16:06 UTC (permalink / raw)
  To: Jiong Wang, gcc-patches; +Cc: James Greenhalgh

On 18/01/17 17:10, Jiong Wang wrote:
>> NOTE, this approach however requires DWARF change as the original LR
>> is signed,
>> the binary needs new libgcc to make sure c++ eh works correctly. 
>> Given this
>> acceleration already needs the user specify
>> -mstack-protector-dialect=pauth
>> which means the target platform largely should have install new
>> libgcc, otherwise
>> you can't utilize new pointer authentication features.
>>
>> gcc/
>> 2016-11-11  Jiong Wang  <jiong.wang@arm.com>
>>
>>         * config/aarch64/aarch64-opts.h
>> (aarch64_stack_protector_type): New
>>         enum.
>>         (aarch64_layout_frame): Swap callees and locals when
>>         -mstack-protector-dialect=pauth specified.
>>         (aarch64_expand_prologue): Use AARCH64_PAUTH_SSP_OR_RA_SIGN
>> instead
>>         of AARCH64_ENABLE_RETURN_ADDRESS_SIGN.
>>         (aarch64_expand_epilogue): Likewise.
>>         * config/aarch64/aarch64.md (*do_return): Likewise.
>>         (aarch64_override_options): Sanity check for ILP32 and
>> TARGET_PAUTH.
>>         * config/aarch64/aarch64.h (AARCH64_PAUTH_SSP_OPTION,
>> AARCH64_PAUTH_SSP,
>>         AARCH64_PAUTH_SSP_OR_RA_SIGN, LINK_SSP_SPEC): New defines.
>>         * config/aarch64/aarch64.opt (-mstack-protector-dialect=): New
>> option.
>>         * doc/invoke.texi (AArch64 Options): Documents
>>         -mstack-protector-dialect=.
>>
>                                                          Patch updated
> to migrate to TARGET_STACK_PROTECT_RUNTIME_ENABLED_P.
> 
> aarch64 cross check OK with the following options enabled on all testcases.
>     -fstack-protector-all -mstack-protector-pauth
> 
> OK for trunk?
>                                                                     gcc/
> 2017-01-18  Jiong Wang  <jiong.wang@arm.com>
>            * config/aarch64/aarch64-protos.h
>         (aarch64_pauth_stack_protector_enabled): New declaration.
>         * config/aarch64/aarch64.c (aarch64_layout_frame): Swap
> callee-save area
>         and locals area when aarch64_pauth_stack_protector_enabled
> returns true.
>         (aarch64_stack_protect_runtime_enabled): New function.
>         (aarch64_pauth_stack_protector_enabled): New function.
>         (aarch64_return_address_signing_enabled): Enabled by
>         aarch64_pauth_stack_protector_enabled.
>         (aarch64_override_options): Sanity check for
> -mstack-protector-pauth.
>         (TARGET_STACK_PROTECT_RUNTIME_ENABLED_P): Define.
>         * config/aarch64/aarch64.h (LINK_SSP_SPEC): Likewise.
>         * config/aarch64/aarch64.opt (-mstack-protector-pauth): New option.
>         * doc/invoke.texi (AArch64 Options): Documents
> -mstack-protector-pauth.
> 
> gcc/testsuite/
>         * gcc.target/aarch64/stack_protector_1.c: New test.
> 
> 
> 1.patch
> 
> 
> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
> index 632dd4768d82c340ae4e9b4a93206743756c06e7..a3ad623eef498d00b52d24bf02a5748fad576c3d 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -383,6 +383,7 @@ void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,
>  void aarch64_init_expanders (void);
>  void aarch64_init_simd_builtins (void);
>  void aarch64_emit_call_insn (rtx);
> +bool aarch64_pauth_stack_protector_enabled (void);
>  void aarch64_register_pragmas (void);
>  void aarch64_relayout_simd_types (void);
>  void aarch64_reset_previous_fndecl (void);
> diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
> index 3718ad1b3bf27c6bdb9e74831fd660e617cccbde..dd742d37ab6fc6fb5085e1c6b5d86d5ce1ce5f8a 100644
> --- a/gcc/config/aarch64/aarch64.h
> +++ b/gcc/config/aarch64/aarch64.h
> @@ -958,4 +958,11 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
>  extern tree aarch64_fp16_type_node;
>  extern tree aarch64_fp16_ptr_type_node;
>  
> +#ifndef TARGET_LIBC_PROVIDES_SSP
> +#define LINK_SSP_SPEC "%{!mstack-protector-pauth:\
> +			 %{fstack-protector|fstack-protector-all\
> +			   |fstack-protector-strong|fstack-protector-explicit:\
> +			   -lssp_nonshared -lssp}}"
> +#endif
> +

I don't think we want to suppress this.  PAUTH pased stack protections
isn't an all-or-nothing solution.  What if some object files are built
with traditional -fstack-protector code?

If the library isn't referenced by any of the input objects we won't
pull anything useful in from the library, so leaving it in the link list
should be harmless.


>  #endif /* GCC_AARCH64_H */
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 6451b08191cf1a44aed502930da8603111f6e8ca..461f7b59584af9315accaecc0256abc9a2df4350 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -2884,8 +2884,28 @@ aarch64_layout_frame (void)
>    else if (cfun->machine->frame.wb_candidate1 != INVALID_REGNUM)
>      max_push_offset = 256;
>  
> -  if (cfun->machine->frame.frame_size < max_push_offset
> -      && crtl->outgoing_args_size == 0)
> +  /* Swap callee-save and local variables area to make callee-save which
> +     includes return address register X30/LR position above local variables
> +     that any local buffer overflow will override return address.  */
> +  if (aarch64_pauth_stack_protector_enabled ())
> +    {
> +      if (varargs_and_saved_regs_size < max_push_offset)
> +	/* stp reg1, reg2, [sp, -varargs_and_saved_regs_size]!.  */
> +	cfun->machine->frame.callee_adjust = varargs_and_saved_regs_size;
> +      else
> +	/* sub sp, sp, varargs_and_saved_regs_size.  */
> +	cfun->machine->frame.initial_adjust = varargs_and_saved_regs_size;
> +
> +      /* Any final_adjust needed.  */
> +      cfun->machine->frame.final_adjust
> +	= cfun->machine->frame.frame_size - varargs_and_saved_regs_size;
> +
> +      /* Point hard_fp_offset and locals_offset to correct offsets.  */
> +      cfun->machine->frame.hard_fp_offset = varargs_and_saved_regs_size;
> +      cfun->machine->frame.locals_offset = cfun->machine->frame.hard_fp_offset;
> +    }
> +  else if (cfun->machine->frame.frame_size < max_push_offset
> +	   && crtl->outgoing_args_size == 0)
>      {
>        /* Simple, small frame with no outgoing arguments:
>  	 stp reg1, reg2, [sp, -frame_size]!
> @@ -3117,6 +3137,26 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
>      }
>  }
>  
> +/* Implement the TARGET_STACK_PROTECT_RUNTIME_ENABLED_P.  */
> +
> +static bool
> +aarch64_stack_protect_runtime_enabled (void)
> +{
> +  return !(TARGET_AARCH64_SSP_PAUTH && TARGET_ARMV8_3);
> +}
> +
> +/* Return TRUE if pointer authentication accelerated -fstack-protector is
> +   enabled.  */
> +
> +bool
> +aarch64_pauth_stack_protector_enabled (void)
> +{
> +  /* Enable if this function is identified by GCC to be with buffer over flow
> +     risk and we are not using GCC's standard libssp runtime.  */
> +  return (crtl->stack_protect_guard
> +	  && !aarch64_stack_protect_runtime_enabled ());
> +}
> +
>  /* Return TRUE if return address signing should be enabled for one function,
>     otherwise return FALSE.  */
>  
> @@ -3127,10 +3167,12 @@ aarch64_return_address_signing_enabled (void)
>    gcc_assert (cfun->machine->frame.laid_out);
>  
>    /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
> -     if it's LR is pushed onto stack.  */
> -  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
> -	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
> -	      && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));
> +     if it's LR is pushed onto stack.  Pointer authentication based stack
> +     protector also implies return address signing.  */
> +  return ((aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
> +	   || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
> +	       && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0))
> +	  || aarch64_pauth_stack_protector_enabled ());
>  }

Do we really want to force signing of ALL leaf functions if using PAUTH
based signing?  Surely we only need to check those that might be
vulnerable to buffer overruns.

R.

>  
>  /* Emit code to save the callee-saved registers from register number START
> @@ -8944,6 +8986,14 @@ aarch64_override_options (void)
>    if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
>      sorry ("Return address signing is only supported for -mabi=lp64");
>  
> +  if (TARGET_AARCH64_SSP_PAUTH && TARGET_ILP32)
> +    sorry ("Pointer authentication based -fstack-protector is only supported "
> +	   "on -mabi=lp64.");
> +
> +  if (TARGET_AARCH64_SSP_PAUTH && !TARGET_ARMV8_3)
> +    error ("Pointer authentication based -fstack-protector is only supported "
> +	   "on architecture with pointer authentication extension.");
> +
>    /* Make sure we properly set up the explicit options.  */
>    if ((aarch64_cpu_string && valid_cpu)
>         || (aarch64_tune_string && valid_tune))
> @@ -14859,6 +14909,10 @@ aarch64_libgcc_floating_mode_supported_p
>  #undef TARGET_SETUP_INCOMING_VARARGS
>  #define TARGET_SETUP_INCOMING_VARARGS aarch64_setup_incoming_varargs
>  
> +#undef TARGET_STACK_PROTECT_RUNTIME_ENABLED_P
> +#define TARGET_STACK_PROTECT_RUNTIME_ENABLED_P \
> +  aarch64_stack_protect_runtime_enabled
> +
>  #undef TARGET_STRUCT_VALUE_RTX
>  #define TARGET_STRUCT_VALUE_RTX   aarch64_struct_value_rtx
>  
> diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
> index 54368848bbb249949921a3018d927c4bd61b1fbd..b157e51fd37d9040ca0a63c1f823f2ad70c8c17e 100644
> --- a/gcc/config/aarch64/aarch64.opt
> +++ b/gcc/config/aarch64/aarch64.opt
> @@ -188,3 +188,7 @@ single precision and to 32 bits for double precision.
>  mverbose-cost-dump
>  Common Undocumented Var(flag_aarch64_verbose_cost)
>  Enables verbose cost model dummping in the debug dump files.
> +
> +mstack-protector-pauth
> +Target Report RejectNegative Mask(AARCH64_SSP_PAUTH) Save
> +Enable pointer authentication accelerated stack protector.
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index c75d4b3697bae8805e13168d47066a1d0dd28df7..4eaefb4fc5e4eee92ba429ca5d23d314aa6f3d29 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -14052,6 +14052,11 @@ Permissible values are @samp{none}, which disables return address signing,
>  functions, and @samp{all}, which enables pointer signing for all functions.  The
>  default value is @samp{none}.
>  
> +@item -mstack-protector-pauth
> +@opindex mstack-protector-pauth
> +Use ARMv8.3-A Pointer Authentication Extension to accelerate GCC
> +-fstack-protector.
> +
>  @end table
>  
>  @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
> diff --git a/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c b/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..56741bb38f4a2e95b82f04fe8009bcd6b1eb3f26
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c
> @@ -0,0 +1,23 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-pauth" } */
> +
> +int foo (int);
> +
> +int __attribute__ ((target ("arch=armv8.3-a")))
> +func1 (int a, int b, int c)
> +{
> +  /* paciasp */
> +  return a + foo (b) + c;
> +  /* retaa */
> +}
> +
> +/* Shouldn't enable pauth acceleration as it's ARMv8.2-A.  */
> +
> +int __attribute__ ((target ("arch=armv8.2-a")))
> +func2 (int a, int b, int c)
> +{
> +  return a + foo (b) + c;
> +}
> +
> +/* { dg-final { scan-assembler-times "paciasp" 1 } } */
> +/* { dg-final { scan-assembler-times "retaa" 1 } } */
> 

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

* Re: [AArch64] Accelerate -fstack-protector through pointer authentication extension
  2017-02-15 16:06                     ` [AArch64] Accelerate -fstack-protector through pointer authentication extension Richard Earnshaw (lists)
@ 2017-02-15 17:30                       ` Jiong Wang
  0 siblings, 0 replies; 75+ messages in thread
From: Jiong Wang @ 2017-02-15 17:30 UTC (permalink / raw)
  To: Richard Earnshaw (lists), gcc-patches; +Cc: James Greenhalgh



On 15/02/17 15:45, Richard Earnshaw (lists) wrote:
> On 18/01/17 17:10, Jiong Wang wrote:
>>> NOTE, this approach however requires DWARF change as the original LR
>>> is signed,
>>> the binary needs new libgcc to make sure c++ eh works correctly.
>>> Given this
>>> acceleration already needs the user specify
>>> -mstack-protector-dialect=pauth
>>> which means the target platform largely should have install new
>>> libgcc, otherwise
>>> you can't utilize new pointer authentication features.
>>>
>>> gcc/
>>> 2016-11-11  Jiong Wang  <jiong.wang@arm.com>
>>>
>>>          * config/aarch64/aarch64-opts.h
>>> (aarch64_stack_protector_type): New
>>>          enum.
>>>          (aarch64_layout_frame): Swap callees and locals when
>>>          -mstack-protector-dialect=pauth specified.
>>>          (aarch64_expand_prologue): Use AARCH64_PAUTH_SSP_OR_RA_SIGN
>>> instead
>>>          of AARCH64_ENABLE_RETURN_ADDRESS_SIGN.
>>>          (aarch64_expand_epilogue): Likewise.
>>>          * config/aarch64/aarch64.md (*do_return): Likewise.
>>>          (aarch64_override_options): Sanity check for ILP32 and
>>> TARGET_PAUTH.
>>>          * config/aarch64/aarch64.h (AARCH64_PAUTH_SSP_OPTION,
>>> AARCH64_PAUTH_SSP,
>>>          AARCH64_PAUTH_SSP_OR_RA_SIGN, LINK_SSP_SPEC): New defines.
>>>          * config/aarch64/aarch64.opt (-mstack-protector-dialect=): New
>>> option.
>>>          * doc/invoke.texi (AArch64 Options): Documents
>>>          -mstack-protector-dialect=.
>>>
>>                                                           Patch updated
>> to migrate to TARGET_STACK_PROTECT_RUNTIME_ENABLED_P.
>>
>> aarch64 cross check OK with the following options enabled on all testcases.
>>      -fstack-protector-all -mstack-protector-pauth
>>
>> OK for trunk?
>>                                                                      gcc/
>> 2017-01-18  Jiong Wang  <jiong.wang@arm.com>
>>             * config/aarch64/aarch64-protos.h
>>          (aarch64_pauth_stack_protector_enabled): New declaration.
>>          * config/aarch64/aarch64.c (aarch64_layout_frame): Swap
>> callee-save area
>>          and locals area when aarch64_pauth_stack_protector_enabled
>> returns true.
>>          (aarch64_stack_protect_runtime_enabled): New function.
>>          (aarch64_pauth_stack_protector_enabled): New function.
>>          (aarch64_return_address_signing_enabled): Enabled by
>>          aarch64_pauth_stack_protector_enabled.
>>          (aarch64_override_options): Sanity check for
>> -mstack-protector-pauth.
>>          (TARGET_STACK_PROTECT_RUNTIME_ENABLED_P): Define.
>>          * config/aarch64/aarch64.h (LINK_SSP_SPEC): Likewise.
>>          * config/aarch64/aarch64.opt (-mstack-protector-pauth): New option.
>>          * doc/invoke.texi (AArch64 Options): Documents
>> -mstack-protector-pauth.
>>
>> gcc/testsuite/
>>          * gcc.target/aarch64/stack_protector_1.c: New test.
>>
>>
>> 1.patch
>>
>>
>> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
>> index 632dd4768d82c340ae4e9b4a93206743756c06e7..a3ad623eef498d00b52d24bf02a5748fad576c3d 100644
>> --- a/gcc/config/aarch64/aarch64-protos.h
>> +++ b/gcc/config/aarch64/aarch64-protos.h
>> @@ -383,6 +383,7 @@ void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,
>>   void aarch64_init_expanders (void);
>>   void aarch64_init_simd_builtins (void);
>>   void aarch64_emit_call_insn (rtx);
>> +bool aarch64_pauth_stack_protector_enabled (void);
>>   void aarch64_register_pragmas (void);
>>   void aarch64_relayout_simd_types (void);
>>   void aarch64_reset_previous_fndecl (void);
>> diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
>> index 3718ad1b3bf27c6bdb9e74831fd660e617cccbde..dd742d37ab6fc6fb5085e1c6b5d86d5ce1ce5f8a 100644
>> --- a/gcc/config/aarch64/aarch64.h
>> +++ b/gcc/config/aarch64/aarch64.h
>> @@ -958,4 +958,11 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
>>   extern tree aarch64_fp16_type_node;
>>   extern tree aarch64_fp16_ptr_type_node;
>>   
>> +#ifndef TARGET_LIBC_PROVIDES_SSP
>> +#define LINK_SSP_SPEC "%{!mstack-protector-pauth:\
>> +			 %{fstack-protector|fstack-protector-all\
>> +			   |fstack-protector-strong|fstack-protector-explicit:\
>> +			   -lssp_nonshared -lssp}}"
>> +#endif
>> +
> I don't think we want to suppress this.  PAUTH pased stack protections
> isn't an all-or-nothing solution.  What if some object files are built
> with traditional -fstack-protector code?

I had done a decription on this in the ping email (changed summary may caused
trouble to email client)

--
Code compiled with "-mstack-protector-pauth" can co-work with code compiled
without "-mstack-protector-pauth".  The only problem is when
"-mstack-protector-pauth" is specified, "-lssp/-lssp_nonshared" won't be implied
as the software runtime supports are not required any more.  So if the user has
some object files compiled using default stack protector and wants them to be
linked with object files compiled using "-mstack-protector-pauth", if
"-mstack-protector-pauth" appear in the final command line and "gcc" is used as
linker driver, then "-lssp/-lssp_nonshared" needs to be specified explicitly.
--

Generally, after this patch, if there are object files comes from tranditional
-fstack-protector then the user is responsible to specify -lssp/-lssp-nonshared.

My intention to remove ssp library when -fstack-protector-pauth specified was to
make pauth based stack protector also be available on those configurations where
libssp is not enabled or not available.

Does this make sense?

>
> If the library isn't referenced by any of the input objects we won't
> pull anything useful in from the library, so leaving it in the link list
> should be harmless.

For linux target, I agree.

>> +  return ((aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
>> +	   || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
>> +	       && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0))
>> +	  || aarch64_pauth_stack_protector_enabled ());
>>   }
> Do we really want to force signing of ALL leaf functions if using PAUTH
> based signing?  Surely we only need to check those that might be
> vulnerable to buffer overruns.

aarch64_pauth_stack_protector_enabled () is already checking that, it will
return true only if crtl->stack_protect_guard is not NULL.  While
crtl->stack_protect_guard will only be created for functions which gcc
middle-end (create_stack_guard) identified to be vulnerable to buffer overruns.

Regards,
Jiong

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

end of thread, other threads:[~2017-02-15 17:07 UTC | newest]

Thread overview: 75+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <c9da17a6-c3de-4466-c023-4e4ddbe38efb@foss.arm.com>
2016-11-11 18:22 ` [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space Jiong Wang
2016-11-11 18:33   ` [2/9] Encoding support for AArch64 DWARF operations Jiong Wang
2016-11-16 17:51     ` Jason Merrill
2016-11-16 20:39       ` Jason Merrill
     [not found]   ` <64dd1b38-ff0a-5df0-1d3c-2fbf083e2697@foss.arm.com>
     [not found]     ` <df0da0e0-df8d-50ff-4f7e-428948817b4b@foss.arm.com>
2016-11-11 18:34       ` [4/9][AArch64] Return address protection on AArch64 Jiong Wang
     [not found]       ` <532363d6-0b33-491f-264d-9cd627713bf6@foss.arm.com>
     [not found]         ` <c46bb16a-4133-5aac-646f-cfd3f204d355@foss.arm.com>
2016-11-11 18:35           ` [6/9][AArch64] Add builtins support for pac/aut/xpac Jiong Wang
     [not found]           ` <172bd740-755c-5267-3a9d-692c84d25395@foss.arm.com>
     [not found]             ` <9333e644-4daa-38e3-690e-2ea3473b0f29@foss.arm.com>
2016-11-11 18:36               ` [8/9][AArch64, libgcc] Runtime support for AArch64 DWARF operations Jiong Wang
     [not found]               ` <1ae89b2b-9819-12f8-5341-776c3b02e5b3@foss.arm.com>
2016-11-11 18:37                 ` [9/9][RFC][AArch64] Accelerate -fstack-protector through pointer authentication extension Jiong Wang
2017-01-18 17:10                   ` [AArch64] " Jiong Wang
2017-02-07 16:06                     ` Ping [AArch64] Accelerate -fstack-protector Jiong Wang
2017-02-15 16:06                     ` [AArch64] Accelerate -fstack-protector through pointer authentication extension Richard Earnshaw (lists)
2017-02-15 17:30                       ` Jiong Wang
2016-11-11 18:36             ` [7/9][AArch64, libgcc] Let AArch64 use customized unwinder file Jiong Wang
2016-11-11 22:12               ` Joseph Myers
2016-11-14 13:55                 ` Jiong Wang
2016-11-11 18:35         ` [5/9][AArch64] Generate dwarf information for -msign-return-address Jiong Wang
2016-11-11 18:34     ` [3/9][AArch64] Add commandline support for -march=armv8.3-a Jiong Wang
2016-11-11 19:39   ` [1/9][RFC][DWARF] Reserve three DW_OP numbers in vendor extension space Jakub Jelinek
2016-11-15 16:00     ` Jiong Wang
2016-11-15 16:18       ` Jakub Jelinek
2016-11-15 16:48         ` Jiong Wang
2016-11-15 19:25           ` Richard Earnshaw (lists)
2016-11-16 10:00             ` Jiong Wang
2016-11-16 13:55               ` Mark Wielaard
2016-11-16 14:02                 ` Jakub Jelinek
2016-11-30 11:15                   ` Jiong Wang
2016-11-30 18:25                     ` Yao Qi
2016-12-12 13:40                     ` [Ping~][1/9][RFC][DWARF] " Jiong Wang
2016-12-19 14:07                       ` [Ping^2][1/9][RFC][DWARF] " Jiong Wang
2016-12-28 18:25                         ` [Ping^3][1/9][RFC][DWARF] " Jiong Wang
2016-12-28 21:14                     ` [1/9][RFC][DWARF] " Cary Coutant
2017-01-03  9:32                       ` Jiong Wang
2016-11-30 21:44                   ` Cary Coutant
2016-12-01 10:42                     ` Richard Earnshaw (lists)
2016-12-01 11:09                       ` Jiong Wang
2016-11-15 16:51         ` Jiong Wang
2016-12-28 19:54     ` Cary Coutant
     [not found] ` <4cf21d03-0a88-c6fa-df37-59ec4edf1d89@foss.arm.com>
     [not found]   ` <ac547390-abfc-3d6a-f10b-dbb9e4bad5b2@foss.arm.com>
     [not found]     ` <f97bf031-e589-5879-17f6-60ed02468561@foss.arm.com>
2017-01-06 11:33       ` [Ping~][AArch64] Add commandline support for -march=armv8.3-a Jiong Wang
2017-01-10 17:00         ` James Greenhalgh
     [not found]     ` <ae7c1f2a-06e4-55d1-d3be-e43ae7ec76df@foss.arm.com>
     [not found]       ` <6f8e65e0-643d-d0b0-26ad-4a20c3daf421@foss.arm.com>
2017-01-06 11:47         ` [1/5][AArch64] Return address protection on AArch64 Jiong Wang
2017-01-13 16:05           ` James Greenhalgh
2017-01-13 17:05             ` Jiong Wang
2017-01-16 11:25               ` James Greenhalgh
2017-01-20  4:15           ` Andrew Pinski
2017-01-20 11:39             ` Jiong Wang
2017-01-20 13:15               ` Jiong Wang
2017-01-20 16:24                 ` Richard Earnshaw (lists)
2017-01-20 18:30                   ` Jiong Wang
2017-01-20 18:49                     ` Jiong Wang
2017-01-20 19:14                       ` Richard Earnshaw (lists)
     [not found]       ` <60457276-8566-8bef-6073-4b00dd975759@foss.arm.com>
     [not found]         ` <1e3f0dce-74c8-5a80-ed5a-7e6feeec1e63@foss.arm.com>
     [not found]           ` <97fad7f9-cb42-ab1c-f039-ba42d5dc72c8@foss.arm.com>
     [not found]             ` <d0b329fc-d564-3b14-da21-0eb084c6661f@foss.arm.com>
     [not found]               ` <fdda17f4-5594-c983-64ac-158a9ba43e4c@foss.arm.com>
2017-01-06 11:47                 ` [5/5][AArch64, libgcc] Runtime support for AArch64 DWARF operations Jiong Wang
2017-01-12 18:10                   ` [Ping~]Re: [5/5][AArch64, libgcc] Runtime support for AArch64 return address signing (also attached target macros version) Jiong Wang
2017-01-13 14:12                     ` James Greenhalgh
2017-01-18 17:10                     ` [Ping~]Re: [5/5][libgcc] Runtime support for AArch64 return address signing (needs new target macros) Jiong Wang
2017-01-19 14:23                       ` Richard Earnshaw (lists)
2017-01-19 14:51                         ` Jiong Wang
2017-01-19 20:25                           ` Richard Earnshaw (lists)
2017-01-20  8:42                           ` Christophe Lyon
2017-01-20  9:46                             ` Jiong Wang
2017-01-20 10:19                               ` Christophe Lyon
2017-01-20 10:31                                 ` Jiong Wang
2017-01-20 10:32                                   ` Christophe Lyon
2017-01-20 11:55                                     ` Jiong Wang
2017-01-20 12:14                                       ` Richard Earnshaw (lists)
2017-01-20 14:33                                       ` Christophe Lyon
     [not found]             ` <e9d558d5-0f41-c1e1-e184-94a9311fa664@foss.arm.com>
2017-01-06 11:47               ` [4/5][AArch64, libgcc] Let AArch64 use customized unwinder file Jiong Wang
     [not found]           ` <8d24add0-1c8d-6778-11dd-f7d018b34396@foss.arm.com>
2017-01-06 11:47             ` [3/5][AArch64] New builtins required by libgcc unwinder Jiong Wang
2017-01-13 16:14               ` Richard Earnshaw (lists)
     [not found]         ` <2718d6de-4571-694b-3eeb-90b7b839a867@foss.arm.com>
2017-01-06 11:47           ` [2/5][AArch64] Generate dwarf information for -msign-return-address Jiong Wang
2017-01-13 16:09             ` Richard Earnshaw (lists)
2017-01-13 18:02               ` Jiong Wang
2017-01-16 14:29                 ` [2/5][DWARF] Generate dwarf information for -msign-return-address by introducing new DWARF mapping hook Jiong Wang
2017-01-17 13:57                   ` Richard Earnshaw (lists)
2017-01-17 15:11                     ` Jiong Wang
2017-01-19 14:19                       ` Richard Earnshaw (lists)

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