diff options
author | Konstantin Belousov <kostik@pooma.home> | 2010-04-10 00:40:39 +0300 |
---|---|---|
committer | Konstantin Belousov <kostik@pooma.home> | 2010-04-10 00:40:39 +0300 |
commit | f6546e27ed70661c1b148521e15c539559ee4e25 (patch) | |
tree | 07c07484466e9fcbc188b62ab99b6990e893c4b3 /src/x86 | |
parent | 2c50c95cde4e2a7f69b7f14ff48934f34003aabd (diff) | |
download | libunwind-f6546e27ed70661c1b148521e15c539559ee4e25.tar.gz |
Implement the base code to fetch x86/xmm state on x86. Offsets to be filled.
Diffstat (limited to 'src/x86')
-rw-r--r-- | src/x86/Gos-freebsd.c | 85 | ||||
-rw-r--r-- | src/x86/offsets.h | 28 |
2 files changed, 89 insertions, 24 deletions
diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index b4495686..9fbf854b 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -139,8 +139,9 @@ unw_handle_signal_frame (unw_cursor_t *cursor) HIDDEN dwarf_loc_t x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) { - unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; - int ret, is_fpstate = 0; + unw_word_t addr = c->sigcontext_addr, off, xmm_off; + unw_word_t fpstate, fpformat; + int ret, is_fpstate = 0, is_xmmstate = 0; switch (c->sigcontext_format) { @@ -171,6 +172,7 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) break; } + off = 0; /* shut gcc warning */ switch (reg) { case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break; @@ -191,21 +193,53 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break; case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; - /* XXXKIB fix */ - case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; - case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; - case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; - case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; - case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; - case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; - case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; - case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; + case UNW_X86_FCW: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_CW_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_CW_XMM_OFF; + break; + case UNW_X86_FSW: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_SW_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_SW_XMM_OFF; + break; + case UNW_X86_FTW: + is_fpstate = 1; + xmm_off = FREEBSD_UC_MCONTEXT_TAG_XMM_OFF; + off = FREEBSD_UC_MCONTEXT_TAG_OFF; + break; + case UNW_X86_FCS: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_CSSEL_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF; + break; + case UNW_X86_FIP: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_IPOFF_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF; + break; + case UNW_X86_FEA: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_DATAOFF_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF; + break; + case UNW_X86_FDS: + is_fpstate = 1; + off = FREEBSD_US_MCONTEXT_DATASEL_OFF; + xmm_off = FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF; + break; + case UNW_X86_MXCSR: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_MXCSR_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF; + break; /* stacked fp registers */ case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: is_fpstate = 1; - off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0); + off = FREEBSD_UC_MCONTEXT_ST0_OFF + 10*(reg - UNW_X86_ST0); + xmm_off = FREEBSD_UC_MCONTEXT_ST0_XMM_OFF + 10*(reg - UNW_X86_ST0); break; /* SSE fp registers */ @@ -218,7 +252,8 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); + is_xmmstate = 1; + xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); break; case UNW_X86_XMM0: case UNW_X86_XMM1: @@ -229,7 +264,8 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case UNW_X86_XMM6: case UNW_X86_XMM7: is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0); + is_xmmstate = 1; + xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 16*(reg - UNW_X86_XMM0); break; case UNW_X86_FOP: @@ -242,17 +278,22 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) if (is_fpstate) { if ((ret = dwarf_get (&c->dwarf, - DWARF_MEM_LOC (&c->dwarf, - addr + LINUX_SC_FPSTATE_OFF), - &fpstate_addr)) < 0) + DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPSTATE_OFF), + &fpstate)) < 0) return DWARF_NULL_LOC; - - if (!fpstate_addr) + if (fpstate == FREEBSD_UC_MCONTEXT_FPOWNED_NONE) return DWARF_NULL_LOC; - - return DWARF_MEM_LOC (c, fpstate_addr + off); + if ((ret = dwarf_get (&c->dwarf, + DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPFORMAT_OFF), + &fpformat)) < 0) + return DWARF_NULL_LOC; + if (fpformat == FREEBSD_UC_MCONTEXT_FPFMT_NODEV || + (is_xmmstate && fpformat != FREEBSD_UC_MCONTEXT_FPFMT_XMM)) + return DWARF_NULL_LOC; + if (is_xmmstate) + off = xmm_off; } - else + return DWARF_MEM_LOC (c, addr + off); } diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 7b32cab4..a708cfcc 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -103,12 +103,36 @@ #define FREEBSD_UC_MCONTEXT_CS_OFF 0x50 #define FREEBSD_UC_MCONTEXT_EFLAGS_OFF 0x54 #define FREEBSD_UC_MCONTEXT_OWNEDFP_OFF 0x68 -#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64 +#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64 #define FREEBSD_UC_MCONTEXT_FPSTATE_OFF 0x70 #define FREEBSD_UC_MCONTEXT_MC_LEN_OFF 0x60 #define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44 +#define FREEBSD_UC_MCONTEXT_CW_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CW_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_SW_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_SW_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_TAG_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_TAG_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CSSEL_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_IPOFF_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_DATAOFF_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF 0x11111 +#define FREEBSD_US_MCONTEXT_DATASEL_OFF 0x11111 +#define FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_MXCSR_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_ST0_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_ST0_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_XMM0_OFF 0x11111 + #define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x280 -#define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 +#define FREEBSD_UC_MCONTEXT_FPFMT_NODEV 0x10000 #define FREEBSD_UC_MCONTEXT_FPFMT_387 0x10001 #define FREEBSD_UC_MCONTEXT_FPFMT_XMM 0x10002 +#define FREEBSD_UC_MCONTEXT_FPOWNED_NONE 0x20000 +#define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 +#define FREEBSD_UC_MCONTEXT_FPOWNED_PCB 0x20002 + |