1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-22 23:47:39 +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 HIDDEN dwarf_loc_t
x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg)
{ {
unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; unw_word_t addr = c->sigcontext_addr, off, xmm_off;
int ret, is_fpstate = 0; unw_word_t fpstate, fpformat;
int ret, is_fpstate = 0, is_xmmstate = 0;
switch (c->sigcontext_format) switch (c->sigcontext_format)
{ {
@ -171,6 +172,7 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg)
break; break;
} }
off = 0; /* shut gcc warning */
switch (reg) switch (reg)
{ {
case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break; 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_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break;
case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;
/* XXXKIB fix */ case UNW_X86_FCW:
case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; is_fpstate = 1;
case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; off = FREEBSD_UC_MCONTEXT_CW_OFF;
case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; xmm_off = FREEBSD_UC_MCONTEXT_CW_XMM_OFF;
case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; break;
case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; case UNW_X86_FSW:
case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; is_fpstate = 1;
case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; off = FREEBSD_UC_MCONTEXT_SW_OFF;
case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; 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 */ /* stacked fp registers */
case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: 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: case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7:
is_fpstate = 1; 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; break;
/* SSE fp registers */ /* 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_XMM6_lo: case UNW_X86_XMM6_hi:
case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi:
is_fpstate = 1; 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; break;
case UNW_X86_XMM0: case UNW_X86_XMM0:
case UNW_X86_XMM1: 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_XMM6:
case UNW_X86_XMM7: case UNW_X86_XMM7:
is_fpstate = 1; 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; break;
case UNW_X86_FOP: case UNW_X86_FOP:
@ -242,17 +278,22 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg)
if (is_fpstate) if (is_fpstate)
{ {
if ((ret = dwarf_get (&c->dwarf, if ((ret = dwarf_get (&c->dwarf,
DWARF_MEM_LOC (&c->dwarf, DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPSTATE_OFF),
addr + LINUX_SC_FPSTATE_OFF), &fpstate)) < 0)
&fpstate_addr)) < 0)
return DWARF_NULL_LOC; return DWARF_NULL_LOC;
if (fpstate == FREEBSD_UC_MCONTEXT_FPOWNED_NONE)
if (!fpstate_addr)
return DWARF_NULL_LOC; return DWARF_NULL_LOC;
if ((ret = dwarf_get (&c->dwarf,
return DWARF_MEM_LOC (c, fpstate_addr + off); 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); return DWARF_MEM_LOC (c, addr + off);
} }

View file

@ -103,12 +103,36 @@
#define FREEBSD_UC_MCONTEXT_CS_OFF 0x50 #define FREEBSD_UC_MCONTEXT_CS_OFF 0x50
#define FREEBSD_UC_MCONTEXT_EFLAGS_OFF 0x54 #define FREEBSD_UC_MCONTEXT_EFLAGS_OFF 0x54
#define FREEBSD_UC_MCONTEXT_OWNEDFP_OFF 0x68 #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_FPSTATE_OFF 0x70
#define FREEBSD_UC_MCONTEXT_MC_LEN_OFF 0x60 #define FREEBSD_UC_MCONTEXT_MC_LEN_OFF 0x60
#define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44 #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_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_387 0x10001
#define FREEBSD_UC_MCONTEXT_FPFMT_XMM 0x10002 #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