From c64723835c0c855fde5bec3d7528db64fe539015 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 7 Mar 2010 21:53:01 +0200 Subject: [PATCH] Support walk over freebsd sigframes --- include/tdep-x86_64/libunwind_i.h | 3 ++- src/x86/offsets.h | 3 +++ src/x86_64/Gis_signal_frame.c | 13 +++++-------- src/x86_64/Gregs.c | 4 ++++ src/x86_64/Gstep.c | 14 +++++++++++++- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h index a949a4cb..974d610e 100644 --- a/include/tdep-x86_64/libunwind_i.h +++ b/include/tdep-x86_64/libunwind_i.h @@ -62,7 +62,8 @@ struct cursor enum { X86_64_SCF_NONE, /* no signal frame encountered */ - X86_64_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */ + X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */ + X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD ucontext_t */ } sigcontext_format; unw_word_t sigcontext_addr; diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 94307c12..63a28729 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -82,3 +82,6 @@ #define LINUX_FPSTATE_XMM5_OFF 0x160 #define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM7_OFF 0x180 + +/* FreeBSD specific definitions */ +#define FREEBSD_UC_MCONTEXT_OFF 0x10 diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gis_signal_frame.c index 263ad87a..ce81699f 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gis_signal_frame.c @@ -97,17 +97,14 @@ eb fd jmp 0b || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0 || (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0) return 0; -#if 0 - fprintf(stderr, "is_signal_frame: ip %lx w0 %lx w1 %lx w2 %lx\n", - ip, w0, w1, w2); -#endif w2 &= 0xffffff; - return (w0 == 0x48006a10247c8d48 && + ret = w0 == 0x48006a10247c8d48 && w1 == 0x050f000001a1c0c7 && - w2 == 0x0000000000fdebf4); + w2 == 0x0000000000fdebf4; + return ret; } -#else /* __linux__ */ +#else /* !__linux__ && !__FreeBSD__ */ PROTECTED int unw_is_signal_frame (unw_cursor_t *cursor) @@ -115,4 +112,4 @@ unw_is_signal_frame (unw_cursor_t *cursor) printf ("%s: implement me\n", __FUNCTION__); return -UNW_ENOINFO; } -#endif /* __linux__ */ +#endif diff --git a/src/x86_64/Gregs.c b/src/x86_64/Gregs.c index ddf7b7e3..5dd7b0b6 100644 --- a/src/x86_64/Gregs.c +++ b/src/x86_64/Gregs.c @@ -41,6 +41,10 @@ linux_scratch_loc (struct cursor *c, unw_regnum_t reg) case X86_64_SCF_LINUX_RT_SIGFRAME: addr += LINUX_UC_MCONTEXT_OFF; break; + + case X86_64_SCF_FREEBSD_SIGFRAME: + addr += FREEBSD_UC_MCONTEXT_OFF; + break; } return DWARF_REG_LOC (&c->dwarf, reg); diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 2da1c25d..5a1654e1 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -28,6 +28,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include "ucontext_i.h" #include +#include + +#if defined __FreeBSD__ +#include +#include +#endif PROTECTED int unw_step (unw_cursor_t *cursor) @@ -79,11 +85,17 @@ unw_step (unw_cursor_t *cursor) if (unw_is_signal_frame (cursor)) { - unw_word_t ucontext = c->dwarf.cfa; + unw_word_t ucontext; Debug(1, "signal frame, skip over trampoline\n"); +#if defined __linux__ + ucontext = c->dwarf.cfa; c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; +#elif defined __FreeBSD__ + ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); + c->sigcontext_format = X86_64_SCF_FREEBSD_SIGFRAME; +#endif c->sigcontext_addr = c->dwarf.cfa; rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);