mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-17 13:47:37 +01:00
Preliminary version of freebsd syscall unwinder
This commit is contained in:
parent
c1b1c10cfc
commit
752ce15c4f
4 changed files with 45 additions and 12 deletions
|
@ -63,7 +63,8 @@ struct cursor
|
||||||
{
|
{
|
||||||
X86_64_SCF_NONE, /* no signal frame encountered */
|
X86_64_SCF_NONE, /* no signal frame encountered */
|
||||||
X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */
|
X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */
|
||||||
X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD ucontext_t */
|
X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD signal frame */
|
||||||
|
X86_64_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall */
|
||||||
}
|
}
|
||||||
sigcontext_format;
|
sigcontext_format;
|
||||||
unw_word_t sigcontext_addr;
|
unw_word_t sigcontext_addr;
|
||||||
|
|
|
@ -262,8 +262,9 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
|
||||||
|
|
||||||
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
|
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
abort ();
|
abort ();
|
||||||
#if 0
|
#else
|
||||||
/* If there is no search table or it has an unsupported
|
/* If there is no search table or it has an unsupported
|
||||||
encoding, fall back on linear search. */
|
encoding, fall back on linear search. */
|
||||||
if (hdr->table_enc == DW_EH_PE_omit)
|
if (hdr->table_enc == DW_EH_PE_omit)
|
||||||
|
|
|
@ -54,7 +54,8 @@ unw_is_signal_frame (unw_cursor_t *cursor)
|
||||||
|| (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
|
|| (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
w1 &= 0xff;
|
w1 &= 0xff;
|
||||||
return (w0 == 0x0f0000000fc0c748 && w1 == 0x05);
|
return (w0 == 0x0f0000000fc0c748 && w1 == 0x05) ?
|
||||||
|
X86_64_SCF_LINUX_RT_SIGFRAME : X86_64_SCF_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
|
@ -63,7 +64,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
|
||||||
{
|
{
|
||||||
/* XXXKIB */
|
/* XXXKIB */
|
||||||
struct cursor *c = (struct cursor *) cursor;
|
struct cursor *c = (struct cursor *) cursor;
|
||||||
unw_word_t w0, w1, w2, w3, w4, ip;
|
unw_word_t w0, w1, w2, b0, ip;
|
||||||
unw_addr_space_t as;
|
unw_addr_space_t as;
|
||||||
unw_accessors_t *a;
|
unw_accessors_t *a;
|
||||||
void *arg;
|
void *arg;
|
||||||
|
@ -88,10 +89,20 @@ eb fd jmp 0b
|
||||||
|| (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0)
|
|| (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
w2 &= 0xffffff;
|
w2 &= 0xffffff;
|
||||||
ret = w0 == 0x48006a10247c8d48 &&
|
if (w0 == 0x48006a10247c8d48 &&
|
||||||
w1 == 0x050f000001a1c0c7 &&
|
w1 == 0x050f000001a1c0c7 &&
|
||||||
w2 == 0x0000000000fdebf4;
|
w2 == 0x0000000000fdebf4)
|
||||||
return ret;
|
return X86_64_SCF_FREEBSD_SIGFRAME;
|
||||||
|
/* Check if RIP points at standard syscall sequence.
|
||||||
|
49 89 ca mov %rcx,%r10
|
||||||
|
0f 05 syscall
|
||||||
|
*/
|
||||||
|
if ((ret = (*a->access_mem) (as, ip - 5, &b0, 0, arg)) < 0)
|
||||||
|
return (0);
|
||||||
|
b0 &= 0xffffffffff;
|
||||||
|
if (b0 == 0x000000050fca8949)
|
||||||
|
return X86_64_SCF_FREEBSD_SYSCALL;
|
||||||
|
return X86_64_SCF_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !__linux__ && !__FreeBSD__ */
|
#else /* !__linux__ && !__FreeBSD__ */
|
||||||
|
|
|
@ -83,7 +83,24 @@ unw_step (unw_cursor_t *cursor)
|
||||||
|
|
||||||
Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
|
Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
|
||||||
|
|
||||||
if (unw_is_signal_frame (cursor))
|
c->sigcontext_format = unw_is_signal_frame (cursor);
|
||||||
|
if (c->sigcontext_format == X86_64_SCF_FREEBSD_SYSCALL) {
|
||||||
|
c->dwarf.loc[RCX] = c->dwarf.loc[R10];
|
||||||
|
// rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0);
|
||||||
|
// rbp_loc = c->dwarf.loc[RBP];
|
||||||
|
c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0);
|
||||||
|
ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
|
||||||
|
Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n",
|
||||||
|
(unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]),
|
||||||
|
(unsigned long long) c->dwarf.ip);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
Debug (2, "returning %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
c->dwarf.cfa += 8;
|
||||||
|
return 1;
|
||||||
|
} else if (c->sigcontext_format != X86_64_SCF_NONE)
|
||||||
{
|
{
|
||||||
unw_word_t ucontext;
|
unw_word_t ucontext;
|
||||||
|
|
||||||
|
@ -91,10 +108,13 @@ unw_step (unw_cursor_t *cursor)
|
||||||
|
|
||||||
#if defined __linux__
|
#if defined __linux__
|
||||||
ucontext = c->dwarf.cfa;
|
ucontext = c->dwarf.cfa;
|
||||||
c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
|
if (c->sigcontext_format != X86_64_SCF_LINUX_RT_SIGFRAME)
|
||||||
|
return -UNW_EBADFRAME;
|
||||||
#elif defined __FreeBSD__
|
#elif defined __FreeBSD__
|
||||||
|
if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME)
|
||||||
ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc);
|
ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc);
|
||||||
c->sigcontext_format = X86_64_SCF_FREEBSD_SIGFRAME;
|
else
|
||||||
|
return -UNW_EBADFRAME;
|
||||||
#endif
|
#endif
|
||||||
c->sigcontext_addr = c->dwarf.cfa;
|
c->sigcontext_addr = c->dwarf.cfa;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue