diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-07-22 20:46:07 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-07-22 20:46:07 +0200 |
| commit | 9b585ef706be906ae8e58916c618fd561351f774 (patch) | |
| tree | b01f8c551fc2e33ee6ccca0ee3cb0e5cba6bc82b /src | |
| parent | 67c9378fb8568b6104979e158ed690e4c6d3bc04 (diff) | |
| download | box64-9b585ef706be906ae8e58916c618fd561351f774.tar.gz box64-9b585ef706be906ae8e58916c618fd561351f774.zip | |
Better handling of int 29/2C/2d with wine ([ARM64_DYNAREC] too)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 19 | ||||
| -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/x64run.c | 8 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 13 | ||||
| -rw-r--r-- | src/emu/x64tls.c | 22 | ||||
| -rw-r--r-- | src/include/signals.h | 1 | ||||
| -rw-r--r-- | src/libtools/signals.c | 33 |
8 files changed, 79 insertions, 24 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 0e4dee33..8f2f6882 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1945,10 +1945,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xCD: u8 = F8; - if(box64_wine && u8==0x2D) { - INST_NAME("INT 2D"); + if(box64_wine && (u8==0x2D || u8==0x2C || u8==0x29)) { + INST_NAME("INT 29/2c/2d"); // lets do nothing - MESSAGE(LOG_INFO, "INT 2D Windows anti-debug hack\n"); + MESSAGE(LOG_INFO, "INT 29/2c/2d Windows interruption\n"); + GETIP(ip); + STORE_XEMU_CALL(xRIP); + MOV32w(x1, u8); + CALL(native_int, -1); + LOAD_XEMU_CALL(xRIP); } else if (u8==0x80) { INST_NAME("32bits SYSCALL"); NOTEST(x1); @@ -1965,14 +1970,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MARK; LOAD_XEMU_REM(); jump_to_epilog(dyn, 0, xRIP, ninst); - } else if(box64_wine && u8==0x29) { - INST_NAME("INT 0x29"); - // __fastfail ignored! - MOV32w(x1, 1); - STRw_U12(x1, xEmu, offsetof(x64emu_t, quit)); - jump_to_epilog(dyn, 0, xRIP, ninst); - *need_epilog = 0; - *ok = 0; } else { INST_NAME("INT n"); SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index 4cd26db8..fd76d640 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -163,6 +163,12 @@ void native_priv(x64emu_t* emu) emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); } +void native_int(x64emu_t* emu, int num) +{ + emu->test.test = 0; + emit_interruption(emu, num, (void*)R_RIP); +} + void native_singlestep(x64emu_t* emu) { emit_signal(emu, SIGTRAP, (void*)R_RIP, 1); diff --git a/src/dynarec/dynarec_native_functions.h b/src/dynarec/dynarec_native_functions.h index e9862598..ed6d0f74 100644 --- a/src/dynarec/dynarec_native_functions.h +++ b/src/dynarec/dynarec_native_functions.h @@ -46,6 +46,7 @@ void native_clflush(x64emu_t* emu, void* p); void native_ud(x64emu_t* emu); void native_priv(x64emu_t* emu); void native_singlestep(x64emu_t* emu); +void native_int(x64emu_t* emu, int num); // Caches transformation (for loops) // Specific, need to be written par backend int CacheNeedsTransform(dynarec_native_t* dyn, int i1); diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 6465ab5e..56496f7a 100644 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -1378,12 +1378,14 @@ x64emurun: if(box64_wine && tmp8u==0x2D) { // lets ignore the INT 2D printf_log(LOG_DEBUG, "INT 2D called\n"); + emit_interruption(emu, 0x2d, (void*)R_RIP); + } else if(box64_wine && tmp8u==0x2c) { + printf_log(LOG_DEBUG, "INT 2c called\n"); + emit_interruption(emu, 0x2c, (void*)R_RIP); } else if(box64_wine && tmp8u==0x29) { // INT 29 is __fastfail printf_log(LOG_DEBUG, "INT 29 called => __fastfail(0x%x)\n", R_ECX); - emu->quit = 1; - R_RIP = addr; - goto fini; + emit_interruption(emu, 0x29, (void*)R_RIP); } else if (tmp8u==0x80) { // 32bits syscall #ifndef TEST_INTERPRETER diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index b17b3e7f..e4213371 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -1094,14 +1094,25 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec) printf_log(LOG_NONE, " STACK_TOP: %p ", (void*)(uintptr_t)*(uint32_t*)(R_RSP)); } else if(peek==0xF3 && PK(1)==0x0F && PK(2)==0x1E && PK(3)==0xFA && !is32bits) { printFunctionAddr(*(uintptr_t*)(R_RSP), " STACK_TOP: "); - } else if(peek==0xE8) { // Call + } else if(peek==0xE8 || peek==0xE9) { // Call & Jmp uintptr_t nextaddr = ip + 5 + PK32(1); printFunctionAddr(nextaddr, "=> "); } else if(peek==0xFF) { if(PK(1)==0x25) { uintptr_t nextaddr = ip + 6 + PK32(2); + if(!printFunctionAddr(nextaddr, "=> ")) + printf_log(LOG_NONE, " => %p", (void*)nextaddr); + } else if((PK(1)==0x14) && (PK(2)==0x25)) { + uintptr_t nextaddr = *(uintptr_t*)(uintptr_t)PK32(3); + printf_log(LOG_NONE, " => %p", (void*)nextaddr); printFunctionAddr(nextaddr, "=> "); + } else if((PK(1)==0x14) && (PK(2)==0xC2) && rex.rex==0x41) { + uintptr_t nextaddr = *(uintptr_t*)(R_R10 + R_RAX*8); + printf_log(LOG_NONE, " => %p", (void*)nextaddr); + printFunctionAddr(nextaddr, "=> "); + } + } printf_log(LOG_NONE, "\n"); } diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c index 12a6836d..3e9e5a1e 100644 --- a/src/emu/x64tls.c +++ b/src/emu/x64tls.c @@ -130,9 +130,21 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size) } static void* GetSeg43Base(); +static const char* arch_prctl_param(int code) +{ + static char ret[10] = {0}; + switch (code) { + case 0x1001: return "ARCH_SET_GS"; + case 0x1002: return "ARCH_SET_FS"; + case 0x1003: return "ARCH_GET_FS"; + case 0x1004: return "ARCH_GET_GS"; + } + sprintf(ret, "0x%x", code); + return ret; +} int my_arch_prctl(x64emu_t *emu, int code, void* addr) { - printf_log(LOG_DEBUG, "%04d| arch_prctl(0x%x, %p) (RSP=%p, FS=0x%x, GS=0x%x)\n", GetTID(), code, addr,(void*)R_RSP, emu->segs[_FS], emu->segs[_GS]); + printf_log(/*LOG_DEBUG*/LOG_INFO, "%04d| arch_prctl(%s, %p) (RSP=%p, FS=0x%x, GS=0x%x)\n", GetTID(), arch_prctl_param(code), addr,(void*)R_RSP, emu->segs[_FS], emu->segs[_GS]); #define ARCH_SET_GS 0x1001 #define ARCH_SET_FS 0x1002 @@ -152,19 +164,19 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr) seg=(code==ARCH_SET_FS)?_FS:_GS; int idx = -1; // search if it's a TLS base + if(GetSeg43Base()==addr) + idx = 0x43>>3; // Is this search only occurs when seg==0? for (int i=9; i<15 && idx==-1; ++i) if(my_context->segtls[i].present && my_context->segtls[i].base==(uintptr_t)addr) idx=i; - if(idx==-1 && GetSeg43Base()==addr) - idx = 0x43>>3; // found... if(idx!=-1) { - printf_log(LOG_DEBUG, "Changing segment selector from 0x%x to 0x%x\n", emu->segs[seg], (idx<<3) +3); + printf_log(/*LOG_DEBUG*/LOG_INFO, "Changing segment selector from 0x%x to 0x%x\n", emu->segs[seg], (idx<<3) +3); emu->segs[seg]=(idx<<3) +3; } if(emu->segs[seg]==0) { - printf_log(LOG_DEBUG, "Warning, set seg, but it's 0!\n"); + printf_log(/*LOG_DEBUG*/LOG_INFO, "Warning, set seg, but it's 0!\n"); errno = EINVAL; return -1; } diff --git a/src/include/signals.h b/src/include/signals.h index f3697f48..3fe8a2f7 100644 --- a/src/include/signals.h +++ b/src/include/signals.h @@ -37,5 +37,6 @@ void init_signal_helper(box64context_t* context); void fini_signal_helper(void); void emit_signal(x64emu_t* emu, int sig, void* addr, int code); +void emit_interruption(x64emu_t* emu, int num, void* addr); #endif //__SIGNALS_H__ diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 468a83f5..1b7de926 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -584,6 +584,9 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void #else (void)ucntx; (void)cur_db; #endif + // setup libc context stack frame, on caller stack + frame = frame&~15; + // stack tracking x64_stack_t *new_ss = my_context->onstack[sig]?(x64_stack_t*)pthread_getspecific(sigstack_key):NULL; int used_stack = 0; @@ -734,8 +737,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 17; else if(sig==SIGSEGV) { if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[X64_RIP]) { - sigcontext->uc_mcontext.gregs[X64_ERR] = (info->si_errno==0x1234)?0:0x0010; // execution flag issue (probably), unless it's a #GP(0) - sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR || (info->si_errno==0x1234) || (uintptr_t)info->si_addr==0)?13:14; + sigcontext->uc_mcontext.gregs[X64_ERR] = (info->si_errno==0x1234)?0:((info->si_errno==0xdead)?(0x2|(info->si_code<<3)):0x0010); // execution flag issue (probably), unless it's a #GP(0) + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR || (info->si_errno==0x1234) || (info->si_errno==0xdead) || (uintptr_t)info->si_addr==0)?13:14; } else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) { sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0002; // write flag issue if(labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16) @@ -831,13 +834,15 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void // get segments uint16_t seg; seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff; - #define GO(S) if(emu->segs[_##S]!=seg) {emu->segs[_##S]=seg; emu->segs_serial[_##S] = 0;} + #define GO(S) if(emu->segs[_##S]!=seg) emu->segs[_##S]=seg GO(CS); seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 16)&0xffff; GO(GS); seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff; GO(FS); #undef GO + for(int i=0; i<6; ++i) + emu->segs_serial[i] = 0; printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p\n", (void*)R_RIP); if(old_code) *old_code = -1; // re-init the value to allow another segfault at the same place @@ -1265,7 +1270,7 @@ exit(-1); } if(log_minimum<=box64_log) { static const char* reg_name[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", " R8", " R9","R10","R11", "R12","R13","R14","R15"}; - static const char* seg_name[] = {"ES", "CS", "SS", "DS", "GS", "FS"}; + static const char* seg_name[] = {"ES", "CS", "SS", "DS", "FS", "GS"}; int shown_regs = 0; #ifdef DYNAREC uint32_t hash = 0; @@ -1386,6 +1391,26 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code) my_sigactionhandler_oldcode(sig, 0, &info, &ctx, NULL, NULL); } +void emit_interruption(x64emu_t* emu, int num, void* addr) +{ + ucontext_t ctx = {0}; + siginfo_t info = {0}; + info.si_signo = SIGSEGV; + info.si_errno = 0xdead; + info.si_code = num; + info.si_addr = addr; + const char* x64name = NULL; + const char* elfname = NULL; + if(box64_log>LOG_INFO) { + 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); + } + my_sigactionhandler_oldcode(SIGSEGV, 0, &info, &ctx, NULL, NULL); +} + EXPORT sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler) { if(signum<0 || signum>=MAX_SIGNAL) |