about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-07-22 20:46:07 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-07-22 20:46:07 +0200
commit9b585ef706be906ae8e58916c618fd561351f774 (patch)
treeb01f8c551fc2e33ee6ccca0ee3cb0e5cba6bc82b /src
parent67c9378fb8568b6104979e158ed690e4c6d3bc04 (diff)
downloadbox64-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.c19
-rw-r--r--src/dynarec/dynarec_native_functions.c6
-rw-r--r--src/dynarec/dynarec_native_functions.h1
-rw-r--r--src/emu/x64run.c8
-rw-r--r--src/emu/x64run_private.c13
-rw-r--r--src/emu/x64tls.c22
-rw-r--r--src/include/signals.h1
-rw-r--r--src/libtools/signals.c33
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)