[AArch64][4/4] libgcc unwinder support for return address signing
authorJiong Wang <jiong.wang@arm.com>
Fri, 20 Jan 2017 00:19:01 +0000 (00:19 +0000)
committerJiong Wang <jiwang@gcc.gnu.org>
Fri, 20 Jan 2017 00:19:01 +0000 (00:19 +0000)
libgcc/
* config/aarch64/aarch64-unwind.h: New file.
(DWARF_REGNUM_AARCH64_RA_STATE): Define.
(MD_POST_EXTRACT_ROOT_ADDR): New target marcro and define it on AArch64.
(MD_POST_EXTRACT_FRAME_ADDR): Likewise.
(MD_POST_FROB_EH_HANDLER_ADDR): Likewise.
(MD_FROB_UPDATE_CONTEXT): Define it on AArch64.
(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.
(uw_install_context): Use uw_frob_return_addr.

From-SVN: r244673

libgcc/ChangeLog
libgcc/config.host
libgcc/config/aarch64/linux-unwind.h
libgcc/unwind-dw2.c

index 256dc24a2510add0e6c014011cbe0483292ac39b..926312eca6574f87b8f8d71c7d38243e273077a8 100644 (file)
@@ -1,3 +1,26 @@
+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): New target marcro and define it on AArch64.
+       (MD_POST_EXTRACT_FRAME_ADDR): Likewise.
+       (MD_POST_FROB_EH_HANDLER_ADDR): Likewise.
+       (MD_FROB_UPDATE_CONTEXT): Define it on AArch64.
+       (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.
+       (uw_install_context): Use uw_frob_return_addr.
+
 2017-01-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR other/79046
index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644 (file)
@@ -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"
index 1256f010007ac964de8bb895379a7d893a446bd9..a8fa1d504529fc1e145f3f145fedf8670c6de526 100644 (file)
@@ -24,6 +24,7 @@
 
 #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
index 8085a42ace15d53f4cb0c6681717012d906a6d47..fe74387992ab7f10c141d7b62f72a755878612c5 100644 (file)
@@ -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,21 @@ _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
+                    __attribute__ ((__unused__)),
+                    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 +1650,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);                           \
     }                                                                  \