1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-26 09:07:38 +01:00

Implement the base code to fetch x86/xmm state on x86. Offsets to be filled.

This commit is contained in:
Konstantin Belousov 2010-04-10 00:40:39 +03:00
parent 2c50c95cde
commit f6546e27ed
2 changed files with 89 additions and 24 deletions

View file

@ -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);
}

View file

@ -108,7 +108,31 @@
#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