diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-05-30 21:38:43 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-05-30 21:38:43 +0200 |
| commit | 2038df85c0fc289acc7ff1dce4cd6b416031f7f5 (patch) | |
| tree | 0f9d73ad0b29388b8452f812fca9028eed8d0339 | |
| parent | b142c5a1817fb788b9692870ff6aa0cb3e622aea (diff) | |
| download | box64-2038df85c0fc289acc7ff1dce4cd6b416031f7f5.tar.gz box64-2038df85c0fc289acc7ff1dce4cd6b416031f7f5.zip | |
[ARM64_DYNAREC] Try to optimise Windows INT n version on 64bits (TODO: Interp and 32bits and wowbox64)
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 2 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_functions.c | 6 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_functions.h | 1 | ||||
| -rw-r--r-- | src/emu/x87emu_private.c | 6 | ||||
| -rw-r--r-- | src/emu/x87emu_private.h | 1 | ||||
| -rw-r--r-- | src/include/emit_signals.h | 1 | ||||
| -rw-r--r-- | src/libtools/signal_private.h | 231 | ||||
| -rw-r--r-- | src/libtools/signals.c | 228 | ||||
| -rw-r--r-- | src/os/emit_signals_linux.c | 147 |
9 files changed, 395 insertions, 228 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 7b227e24..84f134fc 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2672,13 +2672,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOV32w(x1, u8); CALL(native_int, -1); LOAD_XEMU_CALL(xRIP); + LOAD_XEMU_REM(); TABLE64(x3, addr); // expected return address CMPSx_REG(xRIP, x3); B_MARK(cNE); LDRw_U12(w1, xEmu, offsetof(x64emu_t, quit)); CBZw_NEXT(w1); MARK; - LOAD_XEMU_REM(); jump_to_epilog(dyn, 0, xRIP, ninst); } else if (u8==0x80) { INST_NAME("32bits SYSCALL"); diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index a97e22c4..555b2eba 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -208,6 +208,12 @@ void native_int(x64emu_t* emu, int num) EmitInterruption(emu, num, (void*)R_RIP); } +void native_wineint(x64emu_t* emu, int num) +{ + emu->test.test = 0; + EmitWineInt(emu, num, (void*)R_RIP); +} + void native_int3(x64emu_t* emu) { EmitSignal(emu, SIGTRAP, NULL, 3); diff --git a/src/dynarec/dynarec_native_functions.h b/src/dynarec/dynarec_native_functions.h index 0df058f2..eca8568f 100644 --- a/src/dynarec/dynarec_native_functions.h +++ b/src/dynarec/dynarec_native_functions.h @@ -57,6 +57,7 @@ void native_br(x64emu_t* emu); void native_priv(x64emu_t* emu); void native_int3(x64emu_t* emu); void native_int(x64emu_t* emu, int num); +void native_wineint(x64emu_t* emu, int num); void native_div0(x64emu_t* emu); // Caches transformation (for loops) // Specific, need to be written par backend diff --git a/src/emu/x87emu_private.c b/src/emu/x87emu_private.c index 5d95a8e5..4936bf6c 100644 --- a/src/emu/x87emu_private.c +++ b/src/emu/x87emu_private.c @@ -476,10 +476,14 @@ void fpu_xsave(x64emu_t* emu, void* ed, int is32bits) void fpu_xrstor(x64emu_t* emu, void* ed, int is32bits) { + uint64_t mask = R_EAX | (((uint64_t)R_EDX)<<32); + return fpu_xrstor_mask(emu, ed, is32bits, mask); +} + +void fpu_xrstor_mask(x64emu_t* emu, void* ed, int is32bits, uint64_t mask) { xsave64_t *p = (xsave64_t*)ed; xsaveheader_t *h = (xsaveheader_t*)(p+1); int compressed = (h->xcomp_bv>>63); - uint64_t mask = R_EAX | (((uint64_t)R_EDX)<<32); uint32_t rfbm = (0b111&mask); uint32_t to_restore = rfbm & h->xstate_bv; uint32_t to_init = rfbm & ~h->xstate_bv; diff --git a/src/emu/x87emu_private.h b/src/emu/x87emu_private.h index 74758acf..ff42d440 100644 --- a/src/emu/x87emu_private.h +++ b/src/emu/x87emu_private.h @@ -219,6 +219,7 @@ void fpu_fxrstor64(x64emu_t* emu, void* ed); void fpu_xsave(x64emu_t* emu, void* ed, int is32bits); void fpu_xsave_mask(x64emu_t* emu, void* ed, int is32bits, uint64_t mask); void fpu_xrstor(x64emu_t* emu, void* ed, int is32bits); +void fpu_xrstor_mask(x64emu_t* emu, void* ed, int is32bits, uint64_t mask); uint32_t cvtf16_32(uint16_t v); uint16_t cvtf32_16(uint32_t v, uint8_t rounding); diff --git a/src/include/emit_signals.h b/src/include/emit_signals.h index 7bc4aa42..ed211fda 100644 --- a/src/include/emit_signals.h +++ b/src/include/emit_signals.h @@ -7,6 +7,7 @@ typedef struct x64emu_s x64emu_t; void EmitSignal(x64emu_t* emu, int sig, void* addr, int code); void EmitInterruption(x64emu_t* emu, int num, void* addr); +void EmitWineInt(x64emu_t* emu, int num, void* addr); void EmitDiv0(x64emu_t* emu, void* addr, int code); void CheckExec(x64emu_t* emu, uintptr_t addr); diff --git a/src/libtools/signal_private.h b/src/libtools/signal_private.h new file mode 100644 index 00000000..6d261c39 --- /dev/null +++ b/src/libtools/signal_private.h @@ -0,0 +1,231 @@ +#ifndef __SIGNAL_PRIVATE_H__ +#define __SIGNAL_PRIVATE_H__ + +typedef uint64_t x64_gregset_t[23]; +enum +{ + X64_R8 = 0, +# define X64_R8 X64_R8 + X64_R9, +# define X64_R9 X64_R9 + X64_R10, +# define X64_R10 X64_R10 + X64_R11, +# define X64_R11 X64_R11 + X64_R12, +# define X64_R12 X64_R12 + X64_R13, +# define X64_R13 X64_R13 + X64_R14, +# define X64_R14 X64_R14 + X64_R15, +# define X64_R15 X64_R15 + X64_RDI, +# define X64_RDI X64_RDI + X64_RSI, +# define X64_RSI X64_RSI + X64_RBP, +# define X64_RBP X64_RBP + X64_RBX, +# define X64_RBX X64_RBX + X64_RDX, +# define X64_RDX X64_RDX + X64_RAX, +# define X64_RAX X64_RAX + X64_RCX, +# define X64_RCX X64_RCX + X64_RSP, +# define X64_RSP X64_RSP + X64_RIP, +# define X64_RIP X64_RIP + X64_EFL, +# define X64_EFL X64_EFL + X64_CSGSFS, /* Actually short cs, gs, fs, __pad0. */ +# define X64_CSGSFS X64_CSGSFS + X64_ERR, +# define X64_ERR X64_ERR + X64_TRAPNO, +# define X64_TRAPNO X64_TRAPNO + X64_OLDMASK, +# define X64_OLDMASK X64_OLDMASK + X64_CR2 +# define X64_CR2 X64_CR2 +}; + +struct x64_fpreg +{ + uint64_t value; +}__attribute__((packed)); + +struct x64_fpxreg +{ + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}__attribute__((packed)); + +struct x64_xmmreg +{ + uint32_t element[4]; +}__attribute__((packed)); + +struct x64_fpstate +{ + /* Regular FPU environment. */ + uint16_t cw; + uint16_t sw; + uint16_t tw; + uint16_t fop; + uint64_t rip; + uint64_t rdp; + uint32_t mxcsr; + uint32_t mxcsr_mask; + struct x64_fpreg _st[8]; + struct x64_xmmreg _xmm[16]; + uint32_t res[24]; +}__attribute__((packed)); + +typedef struct x64_fpstate *x64_fpregset_t; + +typedef struct x64_stack_s +{ + void *ss_sp; + int ss_flags; + size_t ss_size; +} x64_stack_t; + +struct sigcontext_x64 +{ + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t di; + uint64_t si; + uint64_t bp; + uint64_t bx; + uint64_t dx; + uint64_t ax; + uint64_t cx; + uint64_t sp; + uint64_t ip; + uint64_t flags; + uint64_t cs; + uint64_t gs; + uint64_t fs; + uint64_t ss; + uint64_t err; + uint64_t trapno; + uint64_t oldmask; + uint64_t cr2; + uint64_t fpstate; /* Zero when no FPU/extended context */ + uint64_t reserved1[8]; +}; + +struct x64_sigcontext +{ + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rbx; + uint64_t rdx; + uint64_t rax; + uint64_t rcx; + uint64_t rsp; + uint64_t rip; + uint64_t eflags; /* RFLAGS */ + uint16_t cs; + uint16_t gs; + uint16_t fs; + union { + uint16_t ss; /* If UC_SIGCONTEXT_SS */ + uint16_t __pad0; /* Alias name for old (!UC_SIGCONTEXT_SS) user-space */ + }; + uint64_t err; + uint64_t trapno; + uint64_t oldmask; + uint64_t cr2; + struct x64_fpstate *fpstate; /* Zero when no FPU context */ + uint64_t reserved1[8]; +}; + +struct x64_libc_fpstate +{ + /* 64-bit FXSAVE format. */ + uint16_t cwd; + uint16_t swd; + uint16_t ftw; + uint16_t fop; + uint64_t rip; + uint64_t rdp; + uint32_t mxcsr; + uint32_t mxcr_mask; + struct x64_fpxreg st[8]; + struct x64_xmmreg xmm[16]; + uint32_t res1[24]; +}; + +typedef struct x64_mcontext_s +{ + x64_gregset_t gregs; + struct x64_libc_fpstate *fpregs; + uint64_t res[8]; +} x64_mcontext_t; + +// /!\ signal sig_set is different than glibc __sig_set +#ifdef ANDROID +#define _NSIG_WORDS (64 / (sizeof(unsigned long int)*8)) +#else +#define _NSIG_WORDS (1024 / (sizeof(unsigned long int)*8)) +#endif + +typedef struct { + unsigned long int sig[_NSIG_WORDS]; +} x64_sigset_t; + +typedef struct x64_ucontext_s +{ + uint64_t uc_flags; + struct x64_ucontext_s* uc_link; + x64_stack_t uc_stack; + x64_mcontext_t uc_mcontext; + x64_sigset_t uc_sigmask; + struct x64_libc_fpstate xstate; + #ifndef ANDROID + uint64_t ssp[4]; + #endif +} x64_ucontext_t; + +typedef struct x64_sigframe_s { + uintptr_t pretcode; // pointer to retcode + int sig; + x64_mcontext_t cpustate; + struct x64_libc_fpstate xstate; + uintptr_t extramask[64-1]; + char retcode[8]; +} x64_sigframe_t; + +struct kernel_sigaction { + void (*k_sa_handler) (int); + unsigned long sa_flags; + void (*sa_restorer) (void); + unsigned long sa_mask; + unsigned long sa_mask2; +}; + +x64_stack_t* sigstack_getstack(); +uint64_t RunFunctionHandler(x64emu_t* emu, int* exit, int dynarec, x64_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...); + +#endif //__SIGNAL_PRIVATE_H__ \ No newline at end of file diff --git a/src/libtools/signals.c b/src/libtools/signals.c index a24a1c51..a2e56cf9 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -43,230 +43,7 @@ #include "gdbjit.h" #endif - -typedef uint64_t x64_gregset_t[23]; -enum -{ - X64_R8 = 0, -# define X64_R8 X64_R8 - X64_R9, -# define X64_R9 X64_R9 - X64_R10, -# define X64_R10 X64_R10 - X64_R11, -# define X64_R11 X64_R11 - X64_R12, -# define X64_R12 X64_R12 - X64_R13, -# define X64_R13 X64_R13 - X64_R14, -# define X64_R14 X64_R14 - X64_R15, -# define X64_R15 X64_R15 - X64_RDI, -# define X64_RDI X64_RDI - X64_RSI, -# define X64_RSI X64_RSI - X64_RBP, -# define X64_RBP X64_RBP - X64_RBX, -# define X64_RBX X64_RBX - X64_RDX, -# define X64_RDX X64_RDX - X64_RAX, -# define X64_RAX X64_RAX - X64_RCX, -# define X64_RCX X64_RCX - X64_RSP, -# define X64_RSP X64_RSP - X64_RIP, -# define X64_RIP X64_RIP - X64_EFL, -# define X64_EFL X64_EFL - X64_CSGSFS, /* Actually short cs, gs, fs, __pad0. */ -# define X64_CSGSFS X64_CSGSFS - X64_ERR, -# define X64_ERR X64_ERR - X64_TRAPNO, -# define X64_TRAPNO X64_TRAPNO - X64_OLDMASK, -# define X64_OLDMASK X64_OLDMASK - X64_CR2 -# define X64_CR2 X64_CR2 -}; - -struct x64_fpreg -{ - uint64_t value; -}__attribute__((packed)); - -struct x64_fpxreg -{ - unsigned short significand[4]; - unsigned short exponent; - unsigned short padding[3]; -}__attribute__((packed)); - -struct x64_xmmreg -{ - uint32_t element[4]; -}__attribute__((packed)); - -struct x64_fpstate -{ - /* Regular FPU environment. */ - uint16_t cw; - uint16_t sw; - uint16_t tw; - uint16_t fop; - uint64_t rip; - uint64_t rdp; - uint32_t mxcsr; - uint32_t mxcsr_mask; - struct x64_fpreg _st[8]; - struct x64_xmmreg _xmm[16]; - uint32_t res[24]; -}__attribute__((packed)); - -typedef struct x64_fpstate *x64_fpregset_t; - -typedef struct x64_stack_s -{ - void *ss_sp; - int ss_flags; - size_t ss_size; -} x64_stack_t; - -struct sigcontext_x64 -{ - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t di; - uint64_t si; - uint64_t bp; - uint64_t bx; - uint64_t dx; - uint64_t ax; - uint64_t cx; - uint64_t sp; - uint64_t ip; - uint64_t flags; - uint64_t cs; - uint64_t gs; - uint64_t fs; - uint64_t ss; - uint64_t err; - uint64_t trapno; - uint64_t oldmask; - uint64_t cr2; - uint64_t fpstate; /* Zero when no FPU/extended context */ - uint64_t reserved1[8]; -}; - -struct x64_sigcontext -{ - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t rdi; - uint64_t rsi; - uint64_t rbp; - uint64_t rbx; - uint64_t rdx; - uint64_t rax; - uint64_t rcx; - uint64_t rsp; - uint64_t rip; - uint64_t eflags; /* RFLAGS */ - uint16_t cs; - uint16_t gs; - uint16_t fs; - union { - uint16_t ss; /* If UC_SIGCONTEXT_SS */ - uint16_t __pad0; /* Alias name for old (!UC_SIGCONTEXT_SS) user-space */ - }; - uint64_t err; - uint64_t trapno; - uint64_t oldmask; - uint64_t cr2; - struct x64_fpstate *fpstate; /* Zero when no FPU context */ - uint64_t reserved1[8]; -}; - -struct x64_libc_fpstate -{ - /* 64-bit FXSAVE format. */ - uint16_t cwd; - uint16_t swd; - uint16_t ftw; - uint16_t fop; - uint64_t rip; - uint64_t rdp; - uint32_t mxcsr; - uint32_t mxcr_mask; - struct x64_fpxreg st[8]; - struct x64_xmmreg xmm[16]; - uint32_t res1[24]; -}; - -typedef struct x64_mcontext_s -{ - x64_gregset_t gregs; - struct x64_libc_fpstate *fpregs; - uint64_t res[8]; -} x64_mcontext_t; - -// /!\ signal sig_set is different than glibc __sig_set -#ifdef ANDROID -#define _NSIG_WORDS (64 / (sizeof(unsigned long int)*8)) -#else -#define _NSIG_WORDS (1024 / (sizeof(unsigned long int)*8)) -#endif - -typedef struct { - unsigned long int sig[_NSIG_WORDS]; -} x64_sigset_t; - -typedef struct x64_ucontext_s -{ - uint64_t uc_flags; - struct x64_ucontext_s* uc_link; - x64_stack_t uc_stack; - x64_mcontext_t uc_mcontext; - x64_sigset_t uc_sigmask; - struct x64_libc_fpstate xstate; - #ifndef ANDROID - uint64_t ssp[4]; - #endif -} x64_ucontext_t; - -typedef struct x64_sigframe_s { - uintptr_t pretcode; // pointer to retcode - int sig; - x64_mcontext_t cpustate; - struct x64_libc_fpstate xstate; - uintptr_t extramask[64-1]; - char retcode[8]; -} x64_sigframe_t; - -struct kernel_sigaction { - void (*k_sa_handler) (int); - unsigned long sa_flags; - void (*sa_restorer) (void); - unsigned long sa_mask; - unsigned long sa_mask2; -}; +#include "signal_private.h" static void sigstack_destroy(void* p) { @@ -327,7 +104,8 @@ uint64_t RunFunctionHandler(x64emu_t* emu, int* exit, int dynarec, x64_ucontext_ #ifndef USE_CUSTOM_MEM // because a signal can interupt a malloc-like function // Dynarec cannot be used in signal handling unless custom malloc is used - dynarec = 0; + if(dynarec==1) + dynarec = 0; #endif if(!emu) emu = thread_get_emu(); diff --git a/src/os/emit_signals_linux.c b/src/os/emit_signals_linux.c index e5cc6b14..39d209f7 100644 --- a/src/os/emit_signals_linux.c +++ b/src/os/emit_signals_linux.c @@ -1,21 +1,28 @@ #include <errno.h> #include <signal.h> #include <stdlib.h> +#include <stdint.h> #include <string.h> #include <sys/mman.h> +#include <ucontext.h> +#include <setjmp.h> +#include <signal.h> #ifndef ANDROID #include <execinfo.h> #endif + #include "box64context.h" #include "custommem.h" #include "debug.h" #include "elfloader.h" #include "emit_signals.h" #include "emu/x64emu_private.h" +#include "emu/x87emu_private.h" #include "regs.h" -#include "signals.h" #include "x64emu.h" +#include "signals.h" +#include "libtools/signal_private.h" void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db, uintptr_t x64pc); void EmitSignal(x64emu_t* emu, int sig, void* addr, int code) @@ -142,3 +149,141 @@ void EmitDiv0(x64emu_t* emu, void* addr, int code) } my_sigactionhandler_oldcode(emu, SIGSEGV, 0, &info, NULL, NULL, NULL, R_RIP); } + +void EmitWineInt(x64emu_t* emu, int num, void* addr) +{ + siginfo_t info = { 0 }; + info.si_signo = SIGSEGV; + info.si_errno = 0xdead; + info.si_code = num; + info.si_addr = NULL; // addr; + const char* x64name = NULL; + const char* elfname = NULL; + if (BOX64ENV(log) > LOG_INFO || BOX64ENV(dynarec_dump) || BOX64ENV(showsegv)) { + x64name = getAddrFunctionName(R_RIP); + elfheader_t* elf = FindElfAddress(my_context, R_RIP); + if (elf) + elfname = ElfName(elf); + printf_log(LOG_NONE, "Emit Interruption 0x%x at IP=%p(%s / %s) / addr=%p\n", num, (void*)R_RIP, x64name ? x64name : "???", elfname ? elfname : "?", addr); + } + if(box64_is32bits) + my_sigactionhandler_oldcode(emu, SIGSEGV, 0, &info, NULL, NULL, NULL, R_RIP); + else { + uintptr_t frame = R_RSP; + int sig = SIGSEGV; + // stack tracking + x64_stack_t *new_ss = my_context->onstack[sig]?sigstack_getstack():NULL; + int used_stack = 0; + if(new_ss) { + if(new_ss->ss_flags == SS_ONSTACK) { // already using it! + frame = ((uintptr_t)emu->regs[_SP].q[0] - 128) & ~0x0f; + } else { + frame = (uintptr_t)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f); + used_stack = 1; + new_ss->ss_flags = SS_ONSTACK; + } + } else { + frame -= 0x200; // redzone + } + + // TODO: do I need to really setup 2 stack frame? That doesn't seems right! + // setup stack frame + frame -= 512+64+16*16; + void* xstate = (void*)frame; + frame -= sizeof(siginfo_t); + siginfo_t* info2 = (siginfo_t*)frame; + memcpy(info2, &info, sizeof(siginfo_t)); + // try to fill some sigcontext.... + frame -= sizeof(x64_ucontext_t); + x64_ucontext_t *sigcontext = (x64_ucontext_t*)frame; + // get general register + sigcontext->uc_mcontext.gregs[X64_R8] = R_R8; + sigcontext->uc_mcontext.gregs[X64_R9] = R_R9; + sigcontext->uc_mcontext.gregs[X64_R10] = R_R10; + sigcontext->uc_mcontext.gregs[X64_R11] = R_R11; + sigcontext->uc_mcontext.gregs[X64_R12] = R_R12; + sigcontext->uc_mcontext.gregs[X64_R13] = R_R13; + sigcontext->uc_mcontext.gregs[X64_R14] = R_R14; + sigcontext->uc_mcontext.gregs[X64_R15] = R_R15; + sigcontext->uc_mcontext.gregs[X64_RAX] = R_RAX; + sigcontext->uc_mcontext.gregs[X64_RCX] = R_RCX; + sigcontext->uc_mcontext.gregs[X64_RDX] = R_RDX; + sigcontext->uc_mcontext.gregs[X64_RDI] = R_RDI; + sigcontext->uc_mcontext.gregs[X64_RSI] = R_RSI; + sigcontext->uc_mcontext.gregs[X64_RBP] = R_RBP; + sigcontext->uc_mcontext.gregs[X64_RSP] = R_RSP; + sigcontext->uc_mcontext.gregs[X64_RBX] = R_RBX; + sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP; + // flags + ResetFlags(emu); + sigcontext->uc_mcontext.gregs[X64_EFL] = emu->eflags.x64; + // get segments + sigcontext->uc_mcontext.gregs[X64_CSGSFS] = ((uint64_t)(R_CS)) | (((uint64_t)(R_GS))<<16) | (((uint64_t)(R_FS))<<32); + if(R_CS==0x23) { + // trucate regs to 32bits, just in case + #define GO(R) sigcontext->uc_mcontext.gregs[X64_R##R]&=0xFFFFFFFF + GO(AX); + GO(CX); + GO(DX); + GO(DI); + GO(SI); + GO(BP); + GO(SP); + GO(BX); + GO(IP); + #undef GO + } + // get FloatPoint status + sigcontext->uc_mcontext.fpregs = xstate;//(struct x64_libc_fpstate*)&sigcontext->xstate; + fpu_xsave_mask(emu, xstate, 0, 0b111); + memcpy(&sigcontext->xstate, xstate, sizeof(sigcontext->xstate)); + ((struct x64_fpstate*)xstate)->res[12] = 0x46505853; // magic number to signal an XSTATE type of fpregs + ((struct x64_fpstate*)xstate)->res[13] = 0; // offset to xstate after this? + // get signal mask + if(new_ss) { + sigcontext->uc_stack.ss_sp = new_ss->ss_sp; + sigcontext->uc_stack.ss_size = new_ss->ss_size; + sigcontext->uc_stack.ss_flags = new_ss->ss_flags; + } else + sigcontext->uc_stack.ss_flags = SS_DISABLE; + // prepare info2 + info2->si_errno = 0; + info2->si_code = 128; + info2->si_addr = NULL; + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 13; + sigcontext->uc_mcontext.gregs[X64_ERR] = 0x02|(num<<3); + int exits = 0; + int ret; + ret = RunFunctionHandler(emu, &exits, 2, sigcontext, my_context->signals[info2->si_signo], 3, info2->si_signo, info2, sigcontext); + if(used_stack) // release stack + new_ss->ss_flags = 0; + // restore values + // general regs + R_R8 = sigcontext->uc_mcontext.gregs[X64_R8]; + R_R9 = sigcontext->uc_mcontext.gregs[X64_R9]; + R_R10 = sigcontext->uc_mcontext.gregs[X64_R10]; + R_R11 = sigcontext->uc_mcontext.gregs[X64_R11]; + R_R12 = sigcontext->uc_mcontext.gregs[X64_R12]; + R_R13 = sigcontext->uc_mcontext.gregs[X64_R13]; + R_R14 = sigcontext->uc_mcontext.gregs[X64_R14]; + R_R15 = sigcontext->uc_mcontext.gregs[X64_R15]; + R_RAX = sigcontext->uc_mcontext.gregs[X64_RAX]; + R_RCX = sigcontext->uc_mcontext.gregs[X64_RCX]; + R_RDX = sigcontext->uc_mcontext.gregs[X64_RDX]; + R_RDI = sigcontext->uc_mcontext.gregs[X64_RDI]; + R_RSI = sigcontext->uc_mcontext.gregs[X64_RSI]; + R_RBP = sigcontext->uc_mcontext.gregs[X64_RBP]; + R_RSP = sigcontext->uc_mcontext.gregs[X64_RSP]; + R_RBX = sigcontext->uc_mcontext.gregs[X64_RBX]; + R_RIP = sigcontext->uc_mcontext.gregs[X64_RIP]; + // flags + emu->eflags.x64 = sigcontext->uc_mcontext.gregs[X64_EFL]; + // get segments + R_CS = sigcontext->uc_mcontext.gregs[X64_CSGSFS]&0xffff; + R_GS = (sigcontext->uc_mcontext.gregs[X64_CSGSFS]>>16)&0xffff; + R_FS = (sigcontext->uc_mcontext.gregs[X64_CSGSFS]>>32)&0xffff; + // fpu + fpu_xrstor_mask(emu, xstate, 0, 0b111); + } +} + |