--- src/x86/offsets.h.orig 2021-07-08 07:46:10.219184000 +1000 +++ src/x86/offsets.h 2021-07-08 07:48:53.864692000 +1000 @@ -138,3 +138,59 @@ #define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 #define FREEBSD_UC_MCONTEXT_FPOWNED_PCB 0x20002 + +/* BSDSUniX-specific definitions: */ + +#define BSDSUNIX_SC_UCONTEXT_OFF 0x20 +#define BSDSUNIX_UC_MCONTEXT_OFF 0x10 + +#define BSDSUNIX_UC_MCONTEXT_GS_OFF 0x14 +#define BSDSUNIX_UC_MCONTEXT_FS_OFF 0x18 +#define BSDSUNIX_UC_MCONTEXT_ES_OFF 0x1c +#define BSDSUNIX_UC_MCONTEXT_DS_OFF 0x20 +#define BSDSUNIX_UC_MCONTEXT_EDI_OFF 0x24 +#define BSDSUNIX_UC_MCONTEXT_ESI_OFF 0x28 +#define BSDSUNIX_UC_MCONTEXT_EBP_OFF 0x2c +#define BSDSUNIX_UC_MCONTEXT_EBX_OFF 0x34 +#define BSDSUNIX_UC_MCONTEXT_EDX_OFF 0x38 +#define BSDSUNIX_UC_MCONTEXT_ECX_OFF 0x3c +#define BSDSUNIX_UC_MCONTEXT_EAX_OFF 0x40 +#define BSDSUNIX_UC_MCONTEXT_TRAPNO_OFF 0x44 +#define BSDSUNIX_UC_MCONTEXT_EIP_OFF 0x4c +#define BSDSUNIX_UC_MCONTEXT_ESP_OFF 0x58 +#define BSDSUNIX_UC_MCONTEXT_CS_OFF 0x50 +#define BSDSUNIX_UC_MCONTEXT_EFLAGS_OFF 0x54 +#define BSDSUNIX_UC_MCONTEXT_SS_OFF 0x5c +#define BSDSUNIX_UC_MCONTEXT_MC_LEN_OFF 0x60 +#define BSDSUNIX_UC_MCONTEXT_FPFORMAT_OFF 0x64 +#define BSDSUNIX_UC_MCONTEXT_OWNEDFP_OFF 0x68 +#define BSDSUNIX_UC_MCONTEXT_FPSTATE_OFF 0x70 + +#define BSDSUNIX_UC_MCONTEXT_CW_OFF 0x70 +#define BSDSUNIX_UC_MCONTEXT_SW_OFF 0x74 +#define BSDSUNIX_UC_MCONTEXT_TAG_OFF 0x78 +#define BSDSUNIX_UC_MCONTEXT_IPOFF_OFF 0x7c +#define BSDSUNIX_UC_MCONTEXT_CSSEL_OFF 0x80 +#define BSDSUNIX_UC_MCONTEXT_DATAOFF_OFF 0x84 +#define BSDSUNIX_US_MCONTEXT_DATASEL_OFF 0x88 +#define BSDSUNIX_UC_MCONTEXT_ST0_OFF 0x8c + +#define BSDSUNIX_UC_MCONTEXT_CW_XMM_OFF 0x70 +#define BSDSUNIX_UC_MCONTEXT_SW_XMM_OFF 0x72 +#define BSDSUNIX_UC_MCONTEXT_TAG_XMM_OFF 0x74 +#define BSDSUNIX_UC_MCONTEXT_IPOFF_XMM_OFF 0x78 +#define BSDSUNIX_UC_MCONTEXT_CSSEL_XMM_OFF 0x7c +#define BSDSUNIX_UC_MCONTEXT_DATAOFF_XMM_OFF 0x80 +#define BSDSUNIX_US_MCONTEXT_DATASEL_XMM_OFF 0x84 +#define BSDSUNIX_UC_MCONTEXT_MXCSR_XMM_OFF 0x88 +#define BSDSUNIX_UC_MCONTEXT_ST0_XMM_OFF 0x90 +#define BSDSUNIX_UC_MCONTEXT_XMM0_OFF 0x110 + +#define BSDSUNIX_UC_MCONTEXT_MC_LEN_VAL 0x280 +#define BSDSUNIX_UC_MCONTEXT_FPFMT_NODEV 0x10000 +#define BSDSUNIX_UC_MCONTEXT_FPFMT_387 0x10001 +#define BSDSUNIX_UC_MCONTEXT_FPFMT_XMM 0x10002 +#define BSDSUNIX_UC_MCONTEXT_FPOWNED_NONE 0x20000 +#define BSDSUNIX_UC_MCONTEXT_FPOWNED_FPU 0x20001 +#define BSDSUNIX_UC_MCONTEXT_FPOWNED_PCB 0x20002 + --- src/x86/siglongjmp.S.orig 2021-07-08 07:46:16.088101000 +1000 +++ src/x86/siglongjmp.S 2021-07-08 07:49:37.656064000 +1000 @@ -28,7 +28,7 @@ #if defined(__linux__) #define SIG_SETMASK 2 -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__BSDSUniX__) #define SIG_SETMASK 3 #endif @@ -70,7 +70,7 @@ lea 8(%esp), %esp /* pop sigmask */ .cfi_adjust_cfa_offset -4 jmp *%edx -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__BSDSUniX__) pushl %eax pushl %edx pushl $0 --- src/x86/Gos-bsdsunix.c.orig 2021-07-08 07:47:09.025173000 +1000 +++ src/x86/Gos-bsdsunix.c 2021-07-08 07:51:52.533002000 +1000 @@ -0,0 +1,374 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "unwind_i.h" +#include "offsets.h" + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, w2, w3, w4, w5, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors_int (as); + arg = c->dwarf.as_arg; + + /* Check if EIP points at sigreturn() sequence. It can be: +sigcode+4: from amd64 bsdsunix32 environment +8d 44 24 20 lea 0x20(%esp),%eax +50 push %eax +b8 a1 01 00 00 mov $0x1a1,%eax +50 push %eax +cd 80 int $0x80 + +sigcode+4: from real i386 +8d 44 24 20 lea 0x20(%esp),%eax +50 push %eax +f7 40 54 00 02 00 testl $0x20000,0x54(%eax) +75 03 jne sigcode+21 +8e 68 14 mov 0x14(%eax),%gs +b8 a1 01 00 00 mov $0x1a1,%eax +50 push %eax +cd 80 int $0x80 + +freebsd4_sigcode+4: +XXX +osigcode: +XXX + */ + ip = c->dwarf.ip; + ret = X86_SCF_NONE; + c->sigcontext_format = ret; + if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 || + (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 || + (*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 || + (*a->access_mem) (as, ip + 12, &w3, 0, arg) < 0) + return ret; + if (w0 == 0x2024448d && w1 == 0x01a1b850 && w2 == 0xcd500000 && + (w3 & 0xff) == 0x80) + ret = X86_SCF_BSDSUNIX_SIGFRAME; + else { + if ((*a->access_mem) (as, ip + 16, &w4, 0, arg) < 0 || + (*a->access_mem) (as, ip + 20, &w5, 0, arg) < 0) + return ret; + if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 && + w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000) + ret = X86_SCF_BSDSUNIX_SIGFRAME; + } + + /* Check for syscall */ + if (ret == X86_SCF_NONE && (*a->access_mem) (as, ip - 2, &w0, 0, arg) >= 0 && + (w0 & 0xffff) == 0x80cd) + ret = X86_SCF_BSDSUNIX_SYSCALL; + Debug (16, "returning %d\n", ret); + c->sigcontext_format = ret; + return (ret); +} + +HIDDEN int +x86_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + if (c->sigcontext_format == X86_SCF_BSDSUNIX_SIGFRAME) { + struct sigframe *sf; + uintptr_t uc_addr; + struct dwarf_loc esp_loc; + + sf = (struct sigframe *)c->dwarf.cfa; + uc_addr = (uintptr_t)&(sf->sf_uc); + c->sigcontext_addr = c->dwarf.cfa; + + esp_loc = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_ESP_OFF, 0); + ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); + if (ret < 0) + { + Debug (2, "returning 0\n"); + return 0; + } + + c->dwarf.loc[EIP] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_EIP_OFF, 0); + c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_ESP_OFF, 0); + c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_EAX_OFF, 0); + c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_ECX_OFF, 0); + c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_EDX_OFF, 0); + c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_EBX_OFF, 0); + c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_EBP_OFF, 0); + c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_ESI_OFF, 0); + c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_EDI_OFF, 0); + c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_EFLAGS_OFF, 0); + c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + BSDSUNIX_UC_MCONTEXT_TRAPNO_OFF, 0); + c->dwarf.loc[ST0] = DWARF_NULL_LOC; + } else if (c->sigcontext_format == X86_SCF_BSDSUNIX_SYSCALL) { + c->dwarf.loc[EIP] = DWARF_LOC (c->dwarf.cfa, 0); + c->dwarf.loc[EAX] = DWARF_NULL_LOC; + c->dwarf.cfa += 4; + c->dwarf.use_prev_instr = 1; + } else { + Debug (8, "Gstep: not handling frame format %d\n", c->sigcontext_format); + abort(); + } + return 0; +} + +HIDDEN dwarf_loc_t +x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) +{ + 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) + { + case X86_SCF_NONE: + return DWARF_REG_LOC (&c->dwarf, reg); + + case X86_SCF_BSDSUNIX_SIGFRAME: + addr += offsetof(struct sigframe, sf_uc) + BSDSUNIX_UC_MCONTEXT_OFF; + break; + + case X86_SCF_BSDSUNIX_SIGFRAME4: + abort(); + break; + + case X86_SCF_BSDSUNIX_OSIGFRAME: + /* XXXKIB */ + abort(); + break; + + case X86_SCF_BSDSUNIX_SYSCALL: + /* XXXKIB */ + abort(); + break; + + default: + /* XXXKIB */ + abort(); + break; + } + + off = 0; /* shut gcc warning */ + switch (reg) + { + case UNW_X86_GS: off = BSDSUNIX_UC_MCONTEXT_GS_OFF; break; + case UNW_X86_FS: off = BSDSUNIX_UC_MCONTEXT_FS_OFF; break; + case UNW_X86_ES: off = BSDSUNIX_UC_MCONTEXT_ES_OFF; break; + case UNW_X86_DS: off = BSDSUNIX_UC_MCONTEXT_SS_OFF; break; + case UNW_X86_EDI: off = BSDSUNIX_UC_MCONTEXT_EDI_OFF; break; + case UNW_X86_ESI: off = BSDSUNIX_UC_MCONTEXT_ESI_OFF; break; + case UNW_X86_EBP: off = BSDSUNIX_UC_MCONTEXT_EBP_OFF; break; + case UNW_X86_ESP: off = BSDSUNIX_UC_MCONTEXT_ESP_OFF; break; + case UNW_X86_EBX: off = BSDSUNIX_UC_MCONTEXT_EBX_OFF; break; + case UNW_X86_EDX: off = BSDSUNIX_UC_MCONTEXT_EDX_OFF; break; + case UNW_X86_ECX: off = BSDSUNIX_UC_MCONTEXT_ECX_OFF; break; + case UNW_X86_EAX: off = BSDSUNIX_UC_MCONTEXT_EAX_OFF; break; + case UNW_X86_TRAPNO: off = BSDSUNIX_UC_MCONTEXT_TRAPNO_OFF; break; + case UNW_X86_EIP: off = BSDSUNIX_UC_MCONTEXT_EIP_OFF; break; + case UNW_X86_CS: off = BSDSUNIX_UC_MCONTEXT_CS_OFF; break; + case UNW_X86_EFLAGS: off = BSDSUNIX_UC_MCONTEXT_EFLAGS_OFF; break; + case UNW_X86_SS: off = BSDSUNIX_UC_MCONTEXT_SS_OFF; break; + + case UNW_X86_FCW: + is_fpstate = 1; + off = BSDSUNIX_UC_MCONTEXT_CW_OFF; + xmm_off = BSDSUNIX_UC_MCONTEXT_CW_XMM_OFF; + break; + case UNW_X86_FSW: + is_fpstate = 1; + off = BSDSUNIX_UC_MCONTEXT_SW_OFF; + xmm_off = BSDSUNIX_UC_MCONTEXT_SW_XMM_OFF; + break; + case UNW_X86_FTW: + is_fpstate = 1; + xmm_off = BSDSUNIX_UC_MCONTEXT_TAG_XMM_OFF; + off = BSDSUNIX_UC_MCONTEXT_TAG_OFF; + break; + case UNW_X86_FCS: + is_fpstate = 1; + off = BSDSUNIX_UC_MCONTEXT_CSSEL_OFF; + xmm_off = BSDSUNIX_UC_MCONTEXT_CSSEL_XMM_OFF; + break; + case UNW_X86_FIP: + is_fpstate = 1; + off = BSDSUNIX_UC_MCONTEXT_IPOFF_OFF; + xmm_off = BSDSUNIX_UC_MCONTEXT_IPOFF_XMM_OFF; + break; + case UNW_X86_FEA: + is_fpstate = 1; + off = BSDSUNIX_UC_MCONTEXT_DATAOFF_OFF; + xmm_off = BSDSUNIX_UC_MCONTEXT_DATAOFF_XMM_OFF; + break; + case UNW_X86_FDS: + is_fpstate = 1; + off = BSDSUNIX_US_MCONTEXT_DATASEL_OFF; + xmm_off = BSDSUNIX_US_MCONTEXT_DATASEL_XMM_OFF; + break; + case UNW_X86_MXCSR: + is_fpstate = 1; + is_xmmstate = 1; + xmm_off = BSDSUNIX_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 = BSDSUNIX_UC_MCONTEXT_ST0_OFF + 10*(reg - UNW_X86_ST0); + xmm_off = BSDSUNIX_UC_MCONTEXT_ST0_XMM_OFF + 10*(reg - UNW_X86_ST0); + break; + + /* SSE fp registers */ + case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi: + case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi: + case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi: + case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi: + case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi: + case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi: + case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: + case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: + is_fpstate = 1; + is_xmmstate = 1; + xmm_off = BSDSUNIX_UC_MCONTEXT_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); + break; + case UNW_X86_XMM0: + case UNW_X86_XMM1: + case UNW_X86_XMM2: + case UNW_X86_XMM3: + case UNW_X86_XMM4: + case UNW_X86_XMM5: + case UNW_X86_XMM6: + case UNW_X86_XMM7: + is_fpstate = 1; + is_xmmstate = 1; + xmm_off = BSDSUNIX_UC_MCONTEXT_XMM0_OFF + 16*(reg - UNW_X86_XMM0); + break; + + case UNW_X86_FOP: + case UNW_X86_TSS: + case UNW_X86_LDT: + default: + return DWARF_REG_LOC (&c->dwarf, reg); + } + + if (is_fpstate) + { + if ((ret = dwarf_get (&c->dwarf, + DWARF_MEM_LOC (&c->dwarf, addr + BSDSUNIX_UC_MCONTEXT_FPSTATE_OFF), + &fpstate)) < 0) + return DWARF_NULL_LOC; + if (fpstate == BSDSUNIX_UC_MCONTEXT_FPOWNED_NONE) + return DWARF_NULL_LOC; + if ((ret = dwarf_get (&c->dwarf, + DWARF_MEM_LOC (&c->dwarf, addr + BSDSUNIX_UC_MCONTEXT_FPFORMAT_OFF), + &fpformat)) < 0) + return DWARF_NULL_LOC; + if (fpformat == BSDSUNIX_UC_MCONTEXT_FPFMT_NODEV || + (is_xmmstate && fpformat != BSDSUNIX_UC_MCONTEXT_FPFMT_XMM)) + return DWARF_NULL_LOC; + if (is_xmmstate) + off = xmm_off; + } + + return DWARF_MEM_LOC (c, addr + off); +} + +#ifndef UNW_REMOTE_ONLY +HIDDEN void * +x86_r_uc_addr (ucontext_t *uc, int reg) +{ + void *addr; + + switch (reg) + { + 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; + + default: + addr = NULL; + } + return addr; +} + +HIDDEN int +x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->uc; + + /* Ensure c->pi is up-to-date. On x86, it's relatively common to be + missing DWARF unwind info. We don't want to fail in that case, + because the frame-chain still would let us do a backtrace at + least. */ + dwarf_make_proc_info (&c->dwarf); + + if (c->sigcontext_format == X86_SCF_NONE) { + Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); + setcontext (uc); + abort(); + } else if (c->sigcontext_format == X86_SCF_BSDSUNIX_SIGFRAME) { + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + + Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); + sigreturn((ucontext_t *)((const char *)sc + BSDSUNIX_SC_UCONTEXT_OFF)); + abort(); + } else { + Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n", + c->dwarf.ip, c->sigcontext_format); + abort(); + } + return -UNW_EINVAL; +} + +#endif --- src/x86/Los-bsdsunix.c.orig 2021-07-08 07:47:09.025222000 +1000 +++ src/x86/Los-bsdsunix.c 2021-07-08 07:52:02.662425000 +1000 @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gos-bsdsunix.c" +#endif --- src/x86/getcontext-bsdsunix.S.orig 2021-07-08 07:47:09.025253000 +1000 +++ src/x86/getcontext-bsdsunix.S 2021-07-08 07:52:33.217670000 +1000 @@ -0,0 +1,112 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" + + .global _Ux86_getcontext + .type _Ux86_getcontext, @function +_Ux86_getcontext: + .cfi_startproc + pushl %eax + .cfi_adjust_cfa_offset 4 + mov 8(%esp),%eax /* ucontext_t* */ + popl BSDSUNIX_UC_MCONTEXT_EAX_OFF(%eax) + .cfi_adjust_cfa_offset 4 + movl %ebx, BSDSUNIX_UC_MCONTEXT_EBX_OFF(%eax) + movl %ecx, BSDSUNIX_UC_MCONTEXT_ECX_OFF(%eax) + movl %edx, BSDSUNIX_UC_MCONTEXT_EDX_OFF(%eax) + movl %edi, BSDSUNIX_UC_MCONTEXT_EDI_OFF(%eax) + movl %esi, BSDSUNIX_UC_MCONTEXT_ESI_OFF(%eax) + movl %ebp, BSDSUNIX_UC_MCONTEXT_EBP_OFF(%eax) + + movl (%esp), %ecx + movl %ecx, BSDSUNIX_UC_MCONTEXT_EIP_OFF(%eax) + + leal 4(%esp), %ecx /* Exclude the return address. */ + movl %ecx, BSDSUNIX_UC_MCONTEXT_ESP_OFF(%eax) + + xorl %ecx, %ecx + movw %fs, %cx + movl %ecx, BSDSUNIX_UC_MCONTEXT_FS_OFF(%eax) + movw %gs, %cx + movl %ecx, BSDSUNIX_UC_MCONTEXT_GS_OFF(%eax) + movw %ds, %cx + movl %ecx, BSDSUNIX_UC_MCONTEXT_DS_OFF(%eax) + movw %es, %cx + movl %ecx, BSDSUNIX_UC_MCONTEXT_ES_OFF(%eax) + movw %ss, %cx + movl %ecx, BSDSUNIX_UC_MCONTEXT_SS_OFF(%eax) + movw %cs, %cx + movl %ecx, BSDSUNIX_UC_MCONTEXT_CS_OFF(%eax) + + pushfl + .cfi_adjust_cfa_offset 4 + popl BSDSUNIX_UC_MCONTEXT_EFLAGS_OFF(%eax) + .cfi_adjust_cfa_offset -4 + + movl $0, BSDSUNIX_UC_MCONTEXT_TRAPNO_OFF(%eax) + + movl $BSDSUNIX_UC_MCONTEXT_FPOWNED_FPU,\ + BSDSUNIX_UC_MCONTEXT_OWNEDFP_OFF(%eax) + movl $BSDSUNIX_UC_MCONTEXT_FPFMT_XMM,\ + BSDSUNIX_UC_MCONTEXT_FPFORMAT_OFF(%eax) + + /* + * Require CPU with fxsave implemented, and enabled by OS. + * + * If passed ucontext is not aligned to 16-byte boundary, + * save fpu context into temporary aligned location on stack + * and then copy. + */ + leal BSDSUNIX_UC_MCONTEXT_FPSTATE_OFF(%eax), %edx + testl $0xf, %edx + jne 2f + fxsave (%edx) /* fast path, passed ucontext save area was aligned */ +1: movl $BSDSUNIX_UC_MCONTEXT_MC_LEN_VAL,\ + BSDSUNIX_UC_MCONTEXT_MC_LEN_OFF(%eax) + + xorl %eax, %eax + ret + +2: movl %edx, %edi /* not aligned, do the dance */ + subl $512 + 16, %esp /* save area and 16 bytes for alignment */ + .cfi_adjust_cfa_offset 512 + 16 + movl %esp, %edx + orl $0xf, %edx /* align *%edx to 16-byte up */ + incl %edx + fxsave (%edx) + movl %edx, %esi /* copy to the final destination */ + movl $512/4,%ecx + rep; movsl + addl $512 + 16, %esp /* restore the stack */ + .cfi_adjust_cfa_offset -512 - 16 + movl BSDSUNIX_UC_MCONTEXT_ESI_OFF(%eax), %esi + movl BSDSUNIX_UC_MCONTEXT_EDI_OFF(%eax), %edi + jmp 1b + + .cfi_endproc + .size _Ux86_getcontext, . - _Ux86_getcontext + + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits