mirror of git://gcc.gnu.org/git/gcc.git
[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. From-SVN: r244673
This commit is contained in:
parent
1d9a762962
commit
5636faf2bc
|
|
@ -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>
|
2017-01-17 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR other/79046
|
PR other/79046
|
||||||
|
|
|
||||||
|
|
@ -331,11 +331,13 @@ aarch64*-*-elf | aarch64*-*-rtems*)
|
||||||
extra_parts="$extra_parts crtfastmath.o"
|
extra_parts="$extra_parts crtfastmath.o"
|
||||||
tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
|
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-softfp t-softfp t-crtfm"
|
||||||
|
md_unwind_header=aarch64/aarch64-unwind.h
|
||||||
;;
|
;;
|
||||||
aarch64*-*-freebsd*)
|
aarch64*-*-freebsd*)
|
||||||
extra_parts="$extra_parts crtfastmath.o"
|
extra_parts="$extra_parts crtfastmath.o"
|
||||||
tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
|
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-softfp t-softfp t-crtfm"
|
||||||
|
md_unwind_header=aarch64/aarch64-unwind.h
|
||||||
;;
|
;;
|
||||||
aarch64*-*-linux*)
|
aarch64*-*-linux*)
|
||||||
extra_parts="$extra_parts crtfastmath.o"
|
extra_parts="$extra_parts crtfastmath.o"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/ucontext.h>
|
#include <sys/ucontext.h>
|
||||||
|
#include "config/aarch64/aarch64-unwind.h"
|
||||||
|
|
||||||
|
|
||||||
/* Since insns are always stored LE, on a BE system the opcodes will
|
/* Since insns are always stored LE, on a BE system the opcodes will
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,8 @@ struct _Unwind_Context
|
||||||
#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
|
#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
|
||||||
/* Context which has version/args_size/by_value fields. */
|
/* Context which has version/args_size/by_value fields. */
|
||||||
#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
|
#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;
|
_Unwind_Word flags;
|
||||||
/* 0 for now, can be increased when further fields are added to
|
/* 0 for now, can be increased when further fields are added to
|
||||||
struct _Unwind_Context. */
|
struct _Unwind_Context. */
|
||||||
|
|
@ -1185,6 +1187,11 @@ execute_cfa_program (const unsigned char *insn_ptr,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_GNU_window_save:
|
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. */
|
/* ??? Hardcoded for SPARC register window configuration. */
|
||||||
if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
|
if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
|
||||||
for (reg = 16; reg < 32; ++reg)
|
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].how = REG_SAVED_OFFSET;
|
||||||
fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
|
fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_GNU_args_size:
|
case DW_CFA_GNU_args_size:
|
||||||
|
|
@ -1513,10 +1521,15 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
||||||
stack frame. */
|
stack frame. */
|
||||||
context->ra = 0;
|
context->ra = 0;
|
||||||
else
|
else
|
||||||
/* Compute the return address now, since the return address column
|
{
|
||||||
can change from frame to frame. */
|
/* Compute the return address now, since the return address column
|
||||||
context->ra = __builtin_extract_return_addr
|
can change from frame to frame. */
|
||||||
(_Unwind_GetPtr (context, fs->retaddr_column));
|
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
|
static void
|
||||||
|
|
@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
|
||||||
void *outer_cfa, void *outer_ra)
|
void *outer_cfa, void *outer_ra)
|
||||||
{
|
{
|
||||||
void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
|
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_FrameState fs;
|
||||||
_Unwind_SpTmp sp_slot;
|
_Unwind_SpTmp sp_slot;
|
||||||
_Unwind_Reason_Code code;
|
_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
|
initialization context, then we can't see it in the given
|
||||||
call frame data. So have the initialization context tell us. */
|
call frame data. So have the initialization context tell us. */
|
||||||
context->ra = __builtin_extract_return_addr (outer_ra);
|
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 *)
|
static void _Unwind_DebugHook (void *, void *)
|
||||||
|
|
@ -1608,6 +1627,21 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
|
||||||
#endif
|
#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
|
/* 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
|
macro because __builtin_eh_return must be invoked in the context of
|
||||||
our caller. */
|
our caller. */
|
||||||
|
|
@ -1616,7 +1650,7 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
|
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); \
|
_Unwind_DebugHook ((TARGET)->cfa, handler); \
|
||||||
__builtin_eh_return (offset, handler); \
|
__builtin_eh_return (offset, handler); \
|
||||||
} \
|
} \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue