Hurd x86_64: add unwind support for signal trampoline code
Tested with some simple toy examples where an exception is thrown in the signal handler. libgcc/ChangeLog: * config/i386/gnu-unwind.h: Support unwinding x86_64 signal frames. Signed-off-by: Flavio Cruz <flaviocruz@gmail.com> Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
This commit is contained in:
parent
d2b25083a4
commit
b7c4ae5ace
1 changed files with 94 additions and 3 deletions
|
@ -32,9 +32,100 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|||
|
||||
#ifdef __x86_64__
|
||||
|
||||
/*
|
||||
* TODO: support for 64 bits needs to be implemented.
|
||||
*/
|
||||
#define MD_FALLBACK_FRAME_STATE_FOR x86_gnu_fallback_frame_state
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
x86_gnu_fallback_frame_state
|
||||
(struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
||||
{
|
||||
static const unsigned char gnu_sigtramp_code[] =
|
||||
{
|
||||
/* rpc_wait_trampoline: */
|
||||
0x48, 0xc7, 0xc0, 0xe7, 0xff, 0xff, 0xff, /* mov $-25,%rax */
|
||||
0x0f, 0x05, /* syscall */
|
||||
0x49, 0x89, 0x04, 0x24, /* mov %rax,(%r12) */
|
||||
0x48, 0x89, 0xdc, /* mov %rbx,%rsp */
|
||||
|
||||
/* trampoline: */
|
||||
0x5f, /* pop %rdi */
|
||||
0x5e, /* pop %rsi */
|
||||
0x5a, /* pop %rdx */
|
||||
0x48, 0x83, 0xc4, 0x08, /* add $0x8,%rsp */
|
||||
0x41, 0xff, 0xd5, /* call *%r13 */
|
||||
|
||||
/* RA HERE */
|
||||
0x48, 0x8b, 0x7c, 0x24, 0x10, /* mov 0x10(%rsp),%rdi */
|
||||
0xc3, /* ret */
|
||||
|
||||
/* firewall: */
|
||||
0xf4, /* hlt */
|
||||
};
|
||||
|
||||
const size_t gnu_sigtramp_len = sizeof gnu_sigtramp_code;
|
||||
const size_t gnu_sigtramp_tail = 7; /* length of tail after RA */
|
||||
|
||||
struct stack_contents {
|
||||
void *sigreturn_addr;
|
||||
void *sigreturn_returns_here;
|
||||
struct sigcontext *return_scp;
|
||||
} *stack_contents;
|
||||
struct sigcontext *scp;
|
||||
unsigned long usp;
|
||||
|
||||
unsigned char *adjusted_pc = (unsigned char*)(context->ra) +
|
||||
gnu_sigtramp_tail - gnu_sigtramp_len;
|
||||
if (memcmp (adjusted_pc, gnu_sigtramp_code, gnu_sigtramp_len))
|
||||
return _URC_END_OF_STACK;
|
||||
|
||||
stack_contents = context->cfa;
|
||||
|
||||
scp = stack_contents->return_scp;
|
||||
usp = scp->sc_ursp;
|
||||
|
||||
fs->regs.reg[0].loc.offset = (unsigned long)&scp->sc_rax - usp;
|
||||
fs->regs.reg[1].loc.offset = (unsigned long)&scp->sc_rdx - usp;
|
||||
fs->regs.reg[2].loc.offset = (unsigned long)&scp->sc_rcx - usp;
|
||||
fs->regs.reg[3].loc.offset = (unsigned long)&scp->sc_rbx - usp;
|
||||
fs->regs.reg[4].loc.offset = (unsigned long)&scp->sc_rsi - usp;
|
||||
fs->regs.reg[5].loc.offset = (unsigned long)&scp->sc_rdi - usp;
|
||||
fs->regs.reg[6].loc.offset = (unsigned long)&scp->sc_rbp - usp;
|
||||
fs->regs.reg[8].loc.offset = (unsigned long)&scp->sc_r8 - usp;
|
||||
fs->regs.reg[9].loc.offset = (unsigned long)&scp->sc_r9 - usp;
|
||||
fs->regs.reg[10].loc.offset = (unsigned long)&scp->sc_r10 - usp;
|
||||
fs->regs.reg[11].loc.offset = (unsigned long)&scp->sc_r11 - usp;
|
||||
fs->regs.reg[12].loc.offset = (unsigned long)&scp->sc_r12 - usp;
|
||||
fs->regs.reg[13].loc.offset = (unsigned long)&scp->sc_r13 - usp;
|
||||
fs->regs.reg[14].loc.offset = (unsigned long)&scp->sc_r14 - usp;
|
||||
fs->regs.reg[15].loc.offset = (unsigned long)&scp->sc_r15 - usp;
|
||||
fs->regs.reg[16].loc.offset = (unsigned long)&scp->sc_rip - usp;
|
||||
|
||||
/* Register 7 is rsp */
|
||||
fs->regs.cfa_how = CFA_REG_OFFSET;
|
||||
fs->regs.cfa_reg = 7;
|
||||
fs->regs.cfa_offset = usp - (unsigned long) context->cfa;
|
||||
|
||||
fs->regs.how[0] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[1] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[2] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[3] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[4] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[5] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[6] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[8] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[9] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[10] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[11] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[12] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[13] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[14] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[15] = REG_SAVED_OFFSET;
|
||||
fs->regs.how[16] = REG_SAVED_OFFSET;
|
||||
|
||||
fs->retaddr_column = 16;
|
||||
fs->signal_frame = 1;
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
#else /* ifdef __x86_64__ */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue