about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-07-15 11:03:06 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-07-15 11:03:06 +0200
commit35119f8db219ad8b20ccd3f6952fd7164194c600 (patch)
treee502aefe606dd59405b7f18b4a080a787f6c3afc /src
parentc95af7c81bd06f4fe241f8c71ffa8ef66e6b5b71 (diff)
downloadbox64-35119f8db219ad8b20ccd3f6952fd7164194c600.tar.gz
box64-35119f8db219ad8b20ccd3f6952fd7164194c600.zip
Handling HLT / CLI / STI has privileged instruction (and so trigger a GPF)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/emu/x64run.c15
-rwxr-xr-xsrc/emu/x64run_private.c5
-rwxr-xr-xsrc/libtools/signals.c14
3 files changed, 25 insertions, 9 deletions
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 92a0dc11..782ed520 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -1253,8 +1253,9 @@ x64emurun:
             break;
 
         case 0xF4:                      /* HLT */
-            // this is a privilege opcode... should an error be called instead?
-            sched_yield();
+            // this is a privilege opcode...
+            --R_RIP;
+            emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
             STEP;
             break;
         case 0xF5:                      /* CMC */
@@ -1370,10 +1371,16 @@ x64emurun:
             SET_FLAG(F_CF);
             break;
         case 0xFA:                      /* CLI */
-            CLEAR_FLAG(F_IF);   //not really handled...
+            // this is a privilege opcode...
+            --R_RIP;
+            emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
+            STEP;
             break;
         case 0xFB:                      /* STI */
-            SET_FLAG(F_IF);
+            // this is a privilege opcode...
+            --R_RIP;
+            emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
+            STEP;
             break;
         case 0xFC:                      /* CLD */
             CLEAR_FLAG(F_DF);
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index ef697968..20d2c870 100755
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -1000,6 +1000,11 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
         }
 #endif
         printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
+        if(R_RIP==0) {
+            printf_log(LOG_NONE, "Running at NULL address\n");
+            pthread_mutex_unlock(&my_context->mutex_trace);
+            return;
+        }
         if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
             uint64_t a = *(uint64_t*)(ip+3);
             if(a==0) {
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index d56e73ee..6595e3fb 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -303,7 +303,8 @@ uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
     }
     va_end (va);
 
-    EmuCall(emu, fnc);  // avoid DynaCall for now
+    //EmuCall(emu, fnc);  // avoid DynaCall for now
+    DynaCall(emu, fnc);
     if(nargs>6)
         R_RSP+=((nargs-6)*4);
 
@@ -555,8 +556,8 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
         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] = 0x0010;    // execution flag issue (probably)
-            sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
+            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;
         } 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)
@@ -643,7 +644,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
             seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff;
             GO(FS);
             #undef GO
-            printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu\n");
+            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
             if(used_stack)  // release stack
@@ -834,6 +835,9 @@ exit(-1);
         const char* x64name = NULL;
         const char* elfname = NULL;
         x64emu_t* emu = thread_get_emu();
+        // Adjust RIP for special case of NULL function run
+        if(sig==SIGSEGV && R_RIP==0x1 && (uintptr_t)info->si_addr==0x0)
+            R_RIP = 0x0;
         x64pc = R_RIP;
         rsp = (void*)R_RSP;
 #if defined(__aarch64__) && defined(DYNAREC)
@@ -927,7 +931,7 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
     void* db = NULL;
     siginfo_t info = {0};
     info.si_signo = sig;
-    info.si_errno = 0;
+    info.si_errno = (sig==SIGSEGV)?0x1234:0;    // MAark as a sign this is a #GP(0) (like privileged instruction)
     info.si_code = code;
     info.si_addr = addr;
     const char* x64name = NULL;