about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-07-30 22:12:30 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-07-30 22:12:30 +0200
commitfb0e8ee9c6237993c393f3737e528199be41c23c (patch)
tree77f2805581337ebd007d72399270d5cd0e2956b7 /src
parent6a8cc8ace371c0a683fb3f57048be6b642a56187 (diff)
downloadbox64-fb0e8ee9c6237993c393f3737e528199be41c23c.tar.gz
box64-fb0e8ee9c6237993c393f3737e528199be41c23c.zip
Change again a bit how jmpbuffer and resuming of signal is handled
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/dynarec.c139
-rw-r--r--src/emu/x64emu_private.h1
-rw-r--r--src/include/x64run.h2
-rw-r--r--src/wrapped/wrappedlibc.c3
4 files changed, 48 insertions, 97 deletions
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c
index ab7a21ae..0d2c63f1 100644
--- a/src/dynarec/dynarec.c
+++ b/src/dynarec/dynarec.c
@@ -73,114 +73,63 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
 }
 #endif
 
-#ifdef __GNUC__
-// Disable "clobbered" warnings
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wclobbered"
-#endif
 void DynaCall(x64emu_t* emu, uintptr_t addr)
 {
-    // prepare setjump for signal handling
-    struct __jmp_buf_tag jmpbuf[1] = {0};
-    int skip = 0;
-    struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
-    emu->jmpbuf = jmpbuf;
-
-    if((skip = sigsetjmp(emu->jmpbuf, 1))) {
-        printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", emu->segs[_FS]);
-        addr = R_RIP;   // not sure if it should still be inside DynaCall!
-        #ifdef DYNAREC
-        if(box64_dynarec_test) {
-            if(emu->test.clean)
-                x64test_check(emu, R_RIP);
-            emu->test.clean = 0;
-        }
-        #endif
-    }
-#ifdef DYNAREC
-    if(!box64_dynarec)
-#endif
-        EmuCall(emu, addr);
-#ifdef DYNAREC
-    else {
-        uint64_t old_rsp = R_RSP;
-        uint64_t old_rbx = R_RBX;
-        uint64_t old_rdi = R_RDI;
-        uint64_t old_rsi = R_RSI;
-        uint64_t old_rbp = R_RBP;
-        uint64_t old_rip = R_RIP;
-        PushExit(emu);
-        R_RIP = addr;
-        emu->df = d_none;
-        while(!emu->quit) {
-            int is32bits = (emu->segs[_CS]==0x23);
-            dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
-            if(!block || !block->block || !block->done) {
-                skip = 0;
-                // no block, of block doesn't have DynaRec content (yet, temp is not null)
-                // Use interpreter (should use single instruction step...)
-                dynarec_log(LOG_DEBUG, "%04d|Calling Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
-                if(box64_dynarec_test)
-                    emu->test.clean = 0;
-                Run(emu, 1);
-            } else {
-                dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->hash, emu);
-                CHECK_FLAGS(emu);
-                // block is here, let's run it!
-                native_prolog(emu, block->block);
-            }
-            if(emu->fork) {
-                int forktype = emu->fork;
-                emu->quit = 0;
-                emu->fork = 0;
-                emu = x64emu_fork(emu, forktype);
-            }
-        }
-        emu->quit = 0;  // reset Quit flags...
-        emu->df = d_none;
-        if(emu->quitonlongjmp && emu->longjmp) {
-            if(emu->quitonlongjmp==1)
-                emu->longjmp = 0;   // don't change anything because of the longjmp
-        } else {
-            R_RBX = old_rbx;
-            R_RDI = old_rdi;
-            R_RSI = old_rsi;
-            R_RBP = old_rbp;
-            R_RSP = old_rsp;
-            R_RIP = old_rip;  // and set back instruction pointer
-        }
+    uint64_t old_rsp = R_RSP;
+    uint64_t old_rbx = R_RBX;
+    uint64_t old_rdi = R_RDI;
+    uint64_t old_rsi = R_RSI;
+    uint64_t old_rbp = R_RBP;
+    uint64_t old_rip = R_RIP;
+    PushExit(emu);
+    R_RIP = addr;
+    emu->df = d_none;
+    DynaRun(emu);
+    emu->quit = 0;  // reset Quit flags...
+    emu->df = d_none;
+    if(emu->quitonlongjmp && emu->longjmp) {
+        if(emu->quitonlongjmp==1)
+            emu->longjmp = 0;   // don't change anything because of the longjmp
+    } else {
+        R_RBX = old_rbx;
+        R_RDI = old_rdi;
+        R_RSI = old_rsi;
+        R_RBP = old_rbp;
+        R_RSP = old_rsp;
+        R_RIP = old_rip;  // and set back instruction pointer
     }
-#endif
-    // clear the setjmp
-    emu->jmpbuf = old_jmpbuf;
 }
 
-int DynaRun(x64emu_t* emu)
+void DynaRun(x64emu_t* emu)
 {
     // prepare setjump for signal handling
     struct __jmp_buf_tag jmpbuf[1] = {0};
     int skip = 0;
     struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
-    emu->jmpbuf = jmpbuf;
 
-    if((skip=sigsetjmp(emu->jmpbuf, 1))) {
-        printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
-        #ifdef DYNAREC
-        if(box64_dynarec_test) {
-            if(emu->test.clean)
-                x64test_check(emu, R_RIP);
-            emu->test.clean = 0;
+    while(!(emu->quit)) {
+        if(!emu->jmpbuf || (emu->need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
+            emu->jmpbuf = jmpbuf;
+            if((skip=sigsetjmp(emu->jmpbuf, 1))) {
+                printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
+                #ifdef DYNAREC
+                if(box64_dynarec_test) {
+                    if(emu->test.clean)
+                        x64test_check(emu, R_RIP);
+                    emu->test.clean = 0;
+                }
+                #endif
+            }
         }
-        #endif
-    }
+        if(emu->need_jmpbuf)
+            emu->need_jmpbuf = 0;   
 
 #ifdef DYNAREC
-    if(!box64_dynarec)
+        if(!box64_dynarec)
 #endif
-        return Run(emu, 0);
+            Run(emu, 0);
 #ifdef DYNAREC
-    else {
-        while(!emu->quit) {
+        else {
             int is32bits = (emu->segs[_CS]==0x23);
             dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
             if(!block || !block->block || !block->done) {
@@ -202,13 +151,11 @@ int DynaRun(x64emu_t* emu)
                 emu->fork = 0;
                 emu = x64emu_fork(emu, forktype);
             }
+            if(emu->need_jmpbuf)
+                emu->quit = 0;
         }
     }
     // clear the setjmp
     emu->jmpbuf = old_jmpbuf;
-    return 0;
 #endif
 }
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 250d8cee..8ace8abf 100644
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -83,6 +83,7 @@ typedef struct x64emu_s {
     int         quit;
     int         error;
     int         fork;   // quit because need to fork
+    int         need_jmpbuf;    // need a new jmpbuff for signal handling
     forkpty_t*  forkpty_info;
     int         exit;
     int         quitonlongjmp;  // quit if longjmp is called
diff --git a/src/include/x64run.h b/src/include/x64run.h
index 11f07cfa..b6c9e960 100644
--- a/src/include/x64run.h
+++ b/src/include/x64run.h
@@ -6,7 +6,7 @@ typedef struct x64emu_s x64emu_t;
 typedef struct x64test_s x64test_t;
 int Run(x64emu_t *emu, int step); // 0 if run was successfull, 1 if error in x86 world
 int RunTest(x64test_t *test);
-int DynaRun(x64emu_t *emu);
+void DynaRun(x64emu_t *emu);
 
 uint32_t LibSyscall(x64emu_t *emu);
 void PltResolver(x64emu_t* emu);
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 59953d9c..45758e32 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -2519,6 +2519,9 @@ EXPORT int32_t my___sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/vo
             ((__jmp_buf_tag_t*)p)->__mask_was_saved = 1;
     } else
         ((__jmp_buf_tag_t*)p)->__mask_was_saved = 0;
+    // quit emulation loop and create a new jumpbuf if needed
+    emu->need_jmpbuf = 1;
+    emu->quit = 1;
     return 0;
 }
 EXPORT int32_t my_sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int savesigs)