|
|
57942a |
2017-01-19 Jiong Wang <jiong.wang@arm.com>
|
|
|
57942a |
|
|
|
57942a |
* config/aarch64/aarch64-unwind.h: New file.
|
|
|
57942a |
(DWARF_REGNUM_AARCH64_RA_STATE): Define.
|
|
|
57942a |
(MD_POST_EXTRACT_ROOT_ADDR): New target marcro and define it on AArch64.
|
|
|
57942a |
(MD_POST_EXTRACT_FRAME_ADDR): Likewise.
|
|
|
57942a |
(MD_POST_FROB_EH_HANDLER_ADDR): Likewise.
|
|
|
57942a |
(MD_FROB_UPDATE_CONTEXT): Define it on AArch64.
|
|
|
57942a |
(aarch64_post_extract_frame_addr): New function.
|
|
|
57942a |
(aarch64_post_frob_eh_handler_addr): New function.
|
|
|
57942a |
(aarch64_frob_update_context): New function.
|
|
|
57942a |
* config/aarch64/linux-unwind.h: Include aarch64-unwind.h
|
|
|
57942a |
* config.host (aarch64*-*-elf, aarch64*-*-rtems*,
|
|
|
57942a |
aarch64*-*-freebsd*):
|
|
|
57942a |
Initialize md_unwind_header to include aarch64-unwind.h.
|
|
|
57942a |
* unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
|
|
|
57942a |
(execute_cfa_program): Multiplex DW_CFA_GNU_window_save for
|
|
|
57942a |
__aarch64__.
|
|
|
57942a |
(uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
|
|
|
57942a |
(uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
|
|
|
57942a |
(uw_frob_return_addr): New function.
|
|
|
57942a |
(uw_install_context): Use uw_frob_return_addr.
|
|
|
57942a |
|
|
|
57942a |
--- libgcc/config.host (revision 244672)
|
|
|
57942a |
+++ libgcc/config.host (revision 244674)
|
|
|
57942a |
@@ -284,6 +284,7 @@
|
|
|
57942a |
extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o"
|
|
|
57942a |
tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
|
|
|
57942a |
tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp"
|
|
|
57942a |
+ md_unwind_header=aarch64/aarch64-unwind.h
|
|
|
57942a |
;;
|
|
|
57942a |
aarch64*-*-linux*)
|
|
|
57942a |
md_unwind_header=aarch64/linux-unwind.h
|
|
|
57942a |
--- libgcc/config/aarch64/aarch64-unwind.h (nonexistent)
|
|
|
57942a |
+++ libgcc/config/aarch64/aarch64-unwind.h (revision 244674)
|
|
|
57942a |
@@ -0,0 +1,89 @@
|
|
|
57942a |
+/* Copyright (C) 2017 Free Software Foundation, Inc.
|
|
|
57942a |
+ Contributed by ARM Ltd.
|
|
|
57942a |
+
|
|
|
57942a |
+This file is part of GCC.
|
|
|
57942a |
+
|
|
|
57942a |
+GCC is free software; you can redistribute it and/or modify it under
|
|
|
57942a |
+the terms of the GNU General Public License as published by the Free
|
|
|
57942a |
+Software Foundation; either version 3, or (at your option) any later
|
|
|
57942a |
+version.
|
|
|
57942a |
+
|
|
|
57942a |
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
57942a |
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
57942a |
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
57942a |
+for more details.
|
|
|
57942a |
+
|
|
|
57942a |
+Under Section 7 of GPL version 3, you are granted additional
|
|
|
57942a |
+permissions described in the GCC Runtime Library Exception, version
|
|
|
57942a |
+3.1, as published by the Free Software Foundation.
|
|
|
57942a |
+
|
|
|
57942a |
+You should have received a copy of the GNU General Public License and
|
|
|
57942a |
+a copy of the GCC Runtime Library Exception along with this program;
|
|
|
57942a |
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
|
57942a |
+<http://www.gnu.org/licenses/>. */
|
|
|
57942a |
+
|
|
|
57942a |
+#ifndef AARCH64_UNWIND_H
|
|
|
57942a |
+#define AARCH64_UNWIND_H
|
|
|
57942a |
+
|
|
|
57942a |
+#define DWARF_REGNUM_AARCH64_RA_STATE 34
|
|
|
57942a |
+
|
|
|
57942a |
+#define MD_POST_EXTRACT_ROOT_ADDR(addr) \
|
|
|
57942a |
+ ({ void *__addr; asm ("mov x30, %0; hint 7; mov %0, x30" \
|
|
|
57942a |
+ : "=r" (__addr) : "0" (addr) : "x30", "cc"); __addr; })
|
|
|
57942a |
+#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \
|
|
|
57942a |
+ aarch64_post_extract_frame_addr (context, fs, addr)
|
|
|
57942a |
+#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \
|
|
|
57942a |
+ aarch64_post_frob_eh_handler_addr (current, target, addr)
|
|
|
57942a |
+#define MD_FROB_UPDATE_CONTEXT(context, fs) \
|
|
|
57942a |
+ aarch64_frob_update_context (context, fs)
|
|
|
57942a |
+
|
|
|
57942a |
+/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
|
|
|
57942a |
+ unwind frame info FS. If ADDR is signed, we do address authentication on it
|
|
|
57942a |
+ using CFA of current frame. */
|
|
|
57942a |
+
|
|
|
57942a |
+static inline void *
|
|
|
57942a |
+aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
|
|
|
57942a |
+ _Unwind_FrameState *fs, void *addr)
|
|
|
57942a |
+{
|
|
|
57942a |
+ if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
|
|
|
57942a |
+ {
|
|
|
57942a |
+ _Unwind_Word salt = (_Unwind_Word) context->cfa;
|
|
|
57942a |
+ asm ("mov x17, %0; mov x16, %1; hint 12; mov %0, x17"
|
|
|
57942a |
+ : "+r" (addr) : "r" (salt) : "x16", "x17", "cc");
|
|
|
57942a |
+ }
|
|
|
57942a |
+ return addr;
|
|
|
57942a |
+}
|
|
|
57942a |
+
|
|
|
57942a |
+/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before
|
|
|
57942a |
+ installing it into current context CURRENT. TARGET is currently not used.
|
|
|
57942a |
+ We need to sign exception handler's address if CURRENT itself is signed. */
|
|
|
57942a |
+
|
|
|
57942a |
+static inline void *
|
|
|
57942a |
+aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
|
|
|
57942a |
+ struct _Unwind_Context *target
|
|
|
57942a |
+ ATTRIBUTE_UNUSED,
|
|
|
57942a |
+ void *handler_addr)
|
|
|
57942a |
+{
|
|
|
57942a |
+ if (current->flags & RA_A_SIGNED_BIT)
|
|
|
57942a |
+ asm ("mov x17, %0; mov x16, %1; hint 8; mov %0, x17"
|
|
|
57942a |
+ : "+r" (handler_addr) : "r" ((_Unwind_Word) current->cfa)
|
|
|
57942a |
+ : "x16", "x17", "cc");
|
|
|
57942a |
+ return handler_addr;
|
|
|
57942a |
+}
|
|
|
57942a |
+
|
|
|
57942a |
+/* Do AArch64 private initialization on CONTEXT based on frame info FS. Mark
|
|
|
57942a |
+ CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE is
|
|
|
57942a |
+ set. */
|
|
|
57942a |
+
|
|
|
57942a |
+static inline void
|
|
|
57942a |
+aarch64_frob_update_context (struct _Unwind_Context *context,
|
|
|
57942a |
+ _Unwind_FrameState *fs)
|
|
|
57942a |
+{
|
|
|
57942a |
+ if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
|
|
|
57942a |
+ /* The flag is used for re-authenticating EH handler's address. */
|
|
|
57942a |
+ context->flags |= RA_A_SIGNED_BIT;
|
|
|
57942a |
+
|
|
|
57942a |
+ return;
|
|
|
57942a |
+}
|
|
|
57942a |
+
|
|
|
57942a |
+#endif /* defined AARCH64_UNWIND_H */
|
|
|
57942a |
--- libgcc/config/aarch64/linux-unwind.h (revision 244672)
|
|
|
57942a |
+++ libgcc/config/aarch64/linux-unwind.h (revision 244674)
|
|
|
57942a |
@@ -24,6 +24,7 @@
|
|
|
57942a |
|
|
|
57942a |
#include <signal.h>
|
|
|
57942a |
#include <sys/ucontext.h>
|
|
|
57942a |
+#include "config/aarch64/aarch64-unwind.h"
|
|
|
57942a |
|
|
|
57942a |
#define MD_FALLBACK_FRAME_STATE_FOR aarch64_fallback_frame_state
|
|
|
57942a |
|
|
|
57942a |
--- libgcc/unwind-dw2.c (revision 244672)
|
|
|
57942a |
+++ libgcc/unwind-dw2.c (revision 244674)
|
|
|
57942a |
@@ -136,6 +136,8 @@ struct _Unwind_Context
|
|
|
57942a |
#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
|
|
|
57942a |
/* Context which has version/args_size/by_value fields. */
|
|
|
57942a |
#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
|
|
|
57942a |
+ /* Bit reserved on AArch64, return address has been signed with A key. */
|
|
|
57942a |
+#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
|
|
|
57942a |
_Unwind_Word flags;
|
|
|
57942a |
/* 0 for now, can be increased when further fields are added to
|
|
|
57942a |
struct _Unwind_Context. */
|
|
|
57942a |
@@ -1189,6 +1191,11 @@ execute_cfa_program (const unsigned char
|
|
|
57942a |
break;
|
|
|
57942a |
|
|
|
57942a |
case DW_CFA_GNU_window_save:
|
|
|
57942a |
+#ifdef __aarch64__
|
|
|
57942a |
+ /* This CFA is multiplexed with Sparc. On AArch64 it's used to toggle
|
|
|
57942a |
+ return address signing status. */
|
|
|
57942a |
+ fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
|
|
|
57942a |
+#else
|
|
|
57942a |
/* ??? Hardcoded for SPARC register window configuration. */
|
|
|
57942a |
if (DWARF_FRAME_REGISTERS >= 32)
|
|
|
57942a |
for (reg = 16; reg < 32; ++reg)
|
|
|
57942a |
@@ -1192,6 +1199,7 @@ execute_cfa_program (const unsigned char
|
|
|
57942a |
fs->regs.reg[reg].how = REG_SAVED_OFFSET;
|
|
|
57942a |
fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
|
|
|
57942a |
}
|
|
|
57942a |
+#endif
|
|
|
57942a |
break;
|
|
|
57942a |
|
|
|
57942a |
case DW_CFA_GNU_args_size:
|
|
|
57942a |
@@ -1513,10 +1521,15 @@ uw_update_context (struct _Unwind_Contex
|
|
|
57942a |
stack frame. */
|
|
|
57942a |
context->ra = 0;
|
|
|
57942a |
else
|
|
|
57942a |
- /* Compute the return address now, since the return address column
|
|
|
57942a |
- can change from frame to frame. */
|
|
|
57942a |
- context->ra = __builtin_extract_return_addr
|
|
|
57942a |
- (_Unwind_GetPtr (context, fs->retaddr_column));
|
|
|
57942a |
+ {
|
|
|
57942a |
+ /* Compute the return address now, since the return address column
|
|
|
57942a |
+ can change from frame to frame. */
|
|
|
57942a |
+ context->ra = __builtin_extract_return_addr
|
|
|
57942a |
+ (_Unwind_GetPtr (context, fs->retaddr_column));
|
|
|
57942a |
+#ifdef MD_POST_EXTRACT_FRAME_ADDR
|
|
|
57942a |
+ context->ra = MD_POST_EXTRACT_FRAME_ADDR (context, fs, context->ra);
|
|
|
57942a |
+#endif
|
|
|
57942a |
+ }
|
|
|
57942a |
}
|
|
|
57942a |
|
|
|
57942a |
static void
|
|
|
57942a |
@@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Contex
|
|
|
57942a |
void *outer_cfa, void *outer_ra)
|
|
|
57942a |
{
|
|
|
57942a |
void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
|
|
|
57942a |
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
|
|
|
57942a |
+ ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
|
|
|
57942a |
+#endif
|
|
|
57942a |
_Unwind_FrameState fs;
|
|
|
57942a |
_Unwind_SpTmp sp_slot;
|
|
|
57942a |
_Unwind_Reason_Code code;
|
|
|
57942a |
@@ -1586,6 +1602,9 @@ uw_init_context_1 (struct _Unwind_Contex
|
|
|
57942a |
initialization context, then we can't see it in the given
|
|
|
57942a |
call frame data. So have the initialization context tell us. */
|
|
|
57942a |
context->ra = __builtin_extract_return_addr (outer_ra);
|
|
|
57942a |
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
|
|
|
57942a |
+ context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
|
|
|
57942a |
+#endif
|
|
|
57942a |
}
|
|
|
57942a |
|
|
|
57942a |
static void _Unwind_DebugHook (void *, void *)
|
|
|
57942a |
@@ -1608,6 +1627,10 @@ _Unwind_DebugHook (void *cfa __attribute
|
|
|
57942a |
#endif
|
|
|
57942a |
}
|
|
|
57942a |
|
|
|
57942a |
+#ifndef MD_POST_FROB_EH_HANDLER_ADDR
|
|
|
57942a |
+#define MD_POST_FROB_EH_HANDLER_ADDR(c, t, r) r
|
|
|
57942a |
+#endif
|
|
|
57942a |
+
|
|
|
57942a |
/* Install TARGET into CURRENT so that we can return to it. This is a
|
|
|
57942a |
macro because __builtin_eh_return must be invoked in the context of
|
|
|
57942a |
our caller. */
|
|
|
57942a |
@@ -1621,6 +1644,8 @@ _Unwind_DebugHook (void *cfa __attribute
|
|
|
57942a |
{ \
|
|
|
57942a |
long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
|
|
|
57942a |
void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
|
|
|
57942a |
+ handler = (MD_POST_FROB_EH_HANDLER_ADDR ((CURRENT), (TARGET), \
|
|
|
57942a |
+ handler)); \
|
|
|
57942a |
_Unwind_DebugHook ((TARGET)->cfa, handler); \
|
|
|
57942a |
__builtin_eh_return (offset, handler); \
|
|
|
57942a |
} \
|