aboutsummaryrefslogtreecommitdiff
path: root/libgcc/unwind-dw2.c
diff options
context:
space:
mode:
authorjiwang <jiwang@138bc75d-0d04-0410-961f-82ee72b054a4>2017-01-20 00:19:01 +0000
committerjiwang <jiwang@138bc75d-0d04-0410-961f-82ee72b054a4>2017-01-20 00:19:01 +0000
commitf53cdddc37b7cd1ec3db93b4227af50c04a79fb2 (patch)
treea4200a84af112696952a0471531da8b9d2130bf8 /libgcc/unwind-dw2.c
parentddbbb24903b5be27533805954bc95a6cb97b4f7c (diff)
[AArch64][4/4] libgcc unwinder support for return address signing
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@244673 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc/unwind-dw2.c')
-rw-r--r--libgcc/unwind-dw2.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 8085a42ace1..fe74387992a 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,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); \
} \