diff --git a/src/x86/Gcreate_addr_space.c b/src/x86/Gcreate_addr_space.c index fd850c47..5dd6367a 100644 --- a/src/x86/Gcreate_addr_space.c +++ b/src/x86/Gcreate_addr_space.c @@ -27,6 +27,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" +#if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) +#define __LITTLE_ENDIAN _LITTLE_ENDIAN +#endif + PROTECTED unw_addr_space_t unw_create_addr_space (unw_accessors_t *a, int byte_order) { diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index 9205fb43..00a5b075 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -47,6 +47,7 @@ uc_addr (ucontext_t *uc, int reg) switch (reg) { +#if defined __linux__ case UNW_X86_GS: addr = &uc->uc_mcontext.gregs[REG_GS]; break; case UNW_X86_FS: addr = &uc->uc_mcontext.gregs[REG_FS]; break; case UNW_X86_ES: addr = &uc->uc_mcontext.gregs[REG_ES]; break; @@ -64,6 +65,27 @@ uc_addr (ucontext_t *uc, int reg) case UNW_X86_CS: addr = &uc->uc_mcontext.gregs[REG_CS]; break; case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.gregs[REG_EFL]; break; case UNW_X86_SS: addr = &uc->uc_mcontext.gregs[REG_SS]; break; +#elif defined __FreeBSD__ + case UNW_X86_GS: addr = &uc->uc_mcontext.mc_gs; break; + case UNW_X86_FS: addr = &uc->uc_mcontext.mc_fs; break; + case UNW_X86_ES: addr = &uc->uc_mcontext.mc_es; break; + case UNW_X86_DS: addr = &uc->uc_mcontext.mc_ds; break; + case UNW_X86_EAX: addr = &uc->uc_mcontext.mc_eax; break; + case UNW_X86_EBX: addr = &uc->uc_mcontext.mc_ebx; break; + case UNW_X86_ECX: addr = &uc->uc_mcontext.mc_ecx; break; + case UNW_X86_EDX: addr = &uc->uc_mcontext.mc_edx; break; + case UNW_X86_ESI: addr = &uc->uc_mcontext.mc_esi; break; + case UNW_X86_EDI: addr = &uc->uc_mcontext.mc_edi; break; + case UNW_X86_EBP: addr = &uc->uc_mcontext.mc_ebp; break; + case UNW_X86_EIP: addr = &uc->uc_mcontext.mc_eip; break; + case UNW_X86_ESP: addr = &uc->uc_mcontext.mc_esp; break; + case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.mc_trapno; break; + case UNW_X86_CS: addr = &uc->uc_mcontext.mc_cs; break; + case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.mc_eflags; break; + case UNW_X86_SS: addr = &uc->uc_mcontext.mc_ss; break; +#else +#error Port me +#endif default: addr = NULL; diff --git a/src/x86/getcontext.S b/src/x86/getcontext.S index a2999bef..7dfa2c01 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext.S @@ -38,6 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ _Ux86_getcontext: mov 4(%esp),%eax /* ucontext_t* */ +#if defined __linux__ /* EAX is not preserved. */ movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) @@ -63,11 +64,54 @@ _Ux86_getcontext: movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) fnstenv (%ecx) fldenv (%ecx) +#elif defined __FreeBSD__ + /* EAX is not preserved. */ + movl $0, (FREEBSD_UC_MCONTEXT_EAX_OFF)(%eax) + + movl %ebx, (FREEBSD_UC_MCONTEXT_EBX_OFF)(%eax) + movl %ecx, (FREEBSD_UC_MCONTEXT_ECX_OFF)(%eax) + movl %edx, (FREEBSD_UC_MCONTEXT_EDX_OFF)(%eax) + movl %edi, (FREEBSD_UC_MCONTEXT_EDI_OFF)(%eax) + movl %esi, (FREEBSD_UC_MCONTEXT_ESI_OFF)(%eax) + movl %ebp, (FREEBSD_UC_MCONTEXT_EBP_OFF)(%eax) + + movl (%esp), %ecx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_EIP)(%eax) + + leal 4(%esp), %ecx /* Exclude the return address. */ + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_ESP)(%eax) + + xorl %ecx, %ecx + movw %fs, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_FS)(%eax) + movw %gs, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_GS)(%eax) + movw %ds, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_DS)(%eax) + movw %es, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_ES)(%eax) + movw %ss, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_SS)(%eax) + movw %cs, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_CS)(%eax) + + pushfl + popl (FREEBSD_UC_MCONTEXT_OFF_EFLAGS)(%eax) + + movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,FREEBSD_UC_MCONTEXT_OWNEDFP(%eax) + movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,FREEBSD_UC_MCONTEXT_FPFORMAT(%eax) + + leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) + fnstenv (%ecx) + fldenv (%ecx) + + movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL, FREEBSD_UC_MCONTEXT_MC_LEN(%eax) +#endif xor %eax, %eax ret + .size _Ux86_getcontext, . - _Ux86_getcontext -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 94307c12..81f69f90 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -82,3 +82,29 @@ #define LINUX_FPSTATE_XMM5_OFF 0x160 #define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM7_OFF 0x180 + +#define FREEBSD_UC_MCONTEXT_EAX_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_EBX_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_ECX_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_EDX_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_EDI_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_ESI_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_EBP_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_EIP 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_ESP 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_FS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_GS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_DS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_ES 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_SS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_CS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_EFLAGS 0x11 +#define FREEBSD_UC_MCONTEXT_OWNEDFP 0x11 +#define FREEBSD_UC_MCONTEXT_FPFORMAT 0x11 +#define FREEBSD_UC_MCONTEXT_FPSTATE 0x11 +#define FREEBSD_UC_MCONTEXT_MC_LEN 0x11 + +#define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x11 +#define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 +#define FREEBSD_UC_MCONTEXT_FPFMT_387 0x10001 +#define FREEBSD_UC_MCONTEXT_FPFMT_XMM 0x10002