1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-12-23 12:03:41 +01:00

Support walk over freebsd sigframes

This commit is contained in:
Konstantin Belousov 2010-03-07 21:53:01 +02:00
parent d0d5f9979b
commit c64723835c
5 changed files with 27 additions and 10 deletions

View file

@ -62,7 +62,8 @@ struct cursor
enum enum
{ {
X86_64_SCF_NONE, /* no signal frame encountered */ 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; sigcontext_format;
unw_word_t sigcontext_addr; unw_word_t sigcontext_addr;

View file

@ -82,3 +82,6 @@
#define LINUX_FPSTATE_XMM5_OFF 0x160 #define LINUX_FPSTATE_XMM5_OFF 0x160
#define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM6_OFF 0x170
#define LINUX_FPSTATE_XMM7_OFF 0x180 #define LINUX_FPSTATE_XMM7_OFF 0x180
/* FreeBSD specific definitions */
#define FREEBSD_UC_MCONTEXT_OFF 0x10

View file

@ -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 + 8, &w1, 0, arg)) < 0
|| (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;
#if 0
fprintf(stderr, "is_signal_frame: ip %lx w0 %lx w1 %lx w2 %lx\n",
ip, w0, w1, w2);
#endif
w2 &= 0xffffff; w2 &= 0xffffff;
return (w0 == 0x48006a10247c8d48 && ret = w0 == 0x48006a10247c8d48 &&
w1 == 0x050f000001a1c0c7 && w1 == 0x050f000001a1c0c7 &&
w2 == 0x0000000000fdebf4); w2 == 0x0000000000fdebf4;
return ret;
} }
#else /* __linux__ */ #else /* !__linux__ && !__FreeBSD__ */
PROTECTED int PROTECTED int
unw_is_signal_frame (unw_cursor_t *cursor) 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__); printf ("%s: implement me\n", __FUNCTION__);
return -UNW_ENOINFO; return -UNW_ENOINFO;
} }
#endif /* __linux__ */ #endif

View file

@ -41,6 +41,10 @@ linux_scratch_loc (struct cursor *c, unw_regnum_t reg)
case X86_64_SCF_LINUX_RT_SIGFRAME: case X86_64_SCF_LINUX_RT_SIGFRAME:
addr += LINUX_UC_MCONTEXT_OFF; addr += LINUX_UC_MCONTEXT_OFF;
break; break;
case X86_64_SCF_FREEBSD_SIGFRAME:
addr += FREEBSD_UC_MCONTEXT_OFF;
break;
} }
return DWARF_REG_LOC (&c->dwarf, reg); return DWARF_REG_LOC (&c->dwarf, reg);

View file

@ -28,6 +28,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h" #include "unwind_i.h"
#include "ucontext_i.h" #include "ucontext_i.h"
#include <signal.h> #include <signal.h>
#include <stddef.h>
#if defined __FreeBSD__
#include <sys/ucontext.h>
#include <machine/sigframe.h>
#endif
PROTECTED int PROTECTED int
unw_step (unw_cursor_t *cursor) unw_step (unw_cursor_t *cursor)
@ -79,11 +85,17 @@ unw_step (unw_cursor_t *cursor)
if (unw_is_signal_frame (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"); Debug(1, "signal frame, skip over trampoline\n");
#if defined __linux__
ucontext = c->dwarf.cfa;
c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; 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; c->sigcontext_addr = c->dwarf.cfa;
rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);