about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <seebastien.chev@gmail.com>2023-08-13 12:24:12 +0200
committerptitSeb <seebastien.chev@gmail.com>2023-08-13 12:24:12 +0200
commite2077c46ce334453c567382cb254d1010f733fb1 (patch)
tree84d23a64d703baa121230b17d9f4ae9d99a4f4a1 /src
parente8972efca192e988cdd72fc765ef001defe9a5a4 (diff)
downloadbox64-e2077c46ce334453c567382cb254d1010f733fb1.tar.gz
box64-e2077c46ce334453c567382cb254d1010f733fb1.zip
Improved jmpbuff handling a bit
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/dynarec.c16
-rw-r--r--src/emu/x64emu.c6
-rw-r--r--src/emu/x64emu_private.h15
-rw-r--r--src/libtools/signals.c14
-rw-r--r--src/tools/callback.c6
-rw-r--r--src/wrapped/wrappedlibc.c18
6 files changed, 42 insertions, 33 deletions
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c
index 9c2fb4c0..bb6b3ba9 100644
--- a/src/dynarec/dynarec.c
+++ b/src/dynarec/dynarec.c
@@ -87,9 +87,9 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
     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
+    if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
+        if(emu->flags.quitonlongjmp==1)
+            emu->flags.longjmp = 0;   // don't change anything because of the longjmp
     } else {
         R_RBX = old_rbx;
         R_RDI = old_rdi;
@@ -106,10 +106,12 @@ void DynaRun(x64emu_t* emu)
     struct __jmp_buf_tag jmpbuf[1] = {0};
     int skip = 0;
     struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
+    emu->flags.jmpbuf_ready = 0;
 
     while(!(emu->quit)) {
-        if(!emu->jmpbuf || (emu->need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
+        if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
             emu->jmpbuf = jmpbuf;
+            emu->flags.jmpbuf_ready = 1;
             if((skip=sigsetjmp(emu->jmpbuf, 1))) {
                 printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
                 #ifdef DYNAREC
@@ -121,8 +123,8 @@ void DynaRun(x64emu_t* emu)
                 #endif
             }
         }
-        if(emu->need_jmpbuf)
-            emu->need_jmpbuf = 0;   
+        if(emu->flags.need_jmpbuf)
+            emu->flags.need_jmpbuf = 0;
 
 #ifdef DYNAREC
         if(!box64_dynarec)
@@ -153,7 +155,7 @@ void DynaRun(x64emu_t* emu)
             }
         }
 #endif
-        if(emu->need_jmpbuf)
+        if(emu->flags.need_jmpbuf)
             emu->quit = 0;
     }
     // clear the setjmp
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index 9de4cb18..95077d4a 100644
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -567,9 +567,9 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
     Run(emu, 0);
     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
+    if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
+        if(emu->flags.quitonlongjmp==1)
+            emu->flags.longjmp = 0;   // don't change anything because of the longjmp
     } else {
         R_RBX = old_rbx;
         R_RDI = old_rdi;
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index e3a474ca..8076049d 100644
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -36,6 +36,14 @@ typedef struct x64test_s {
     uint8_t     mem[16];
 } x64test_t;
 
+typedef struct emu_flags_s {
+    uint32_t    need_jmpbuf:1;    // need a new jmpbuff for signal handling
+    uint32_t    quitonlongjmp:2;  // quit if longjmp is called
+    uint32_t    quitonexit:2;     // quit if exit/_exit is called
+    uint32_t    longjmp:1;        // if quit because of longjmp
+    uint32_t    jmpbuf_ready:1;   // the jmpbuf in the emu is ok and don't need refresh
+} emu_flags_t;
+
 typedef struct x64emu_s {
     // cpu
 	reg64_t     regs[16];
@@ -83,12 +91,9 @@ 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
-    int         quitonexit;     // quit if exit/_exit is called
-    int         longjmp;        // if quit because of longjmp
+    forkpty_t*  forkpty_info;
+    emu_flags_t flags;
     x64test_t   test;       // used for dynarec testing
     #ifdef HAVE_TRACE
     sse_regs_t  old_xmm[16];
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 5e249432..e47a3dac 100644
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -321,8 +321,8 @@ uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext,
 
     printf_log(LOG_DEBUG, "%04d|signal #%d function handler %p called, RSP=%p\n", GetTID(), R_EDI, (void*)fnc, (void*)R_RSP);
 
-    int oldquitonlongjmp = emu->quitonlongjmp;
-    emu->quitonlongjmp = 2;
+    int oldquitonlongjmp = emu->flags.quitonlongjmp;
+    emu->flags.quitonlongjmp = 2;
     int old_cs = R_CS;
     R_CS = 0x33;
     
@@ -333,13 +333,13 @@ uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext,
     else
         EmuCall(emu, fnc);
 
-    if(nargs>6 && !emu->longjmp)
+    if(nargs>6 && !emu->flags.longjmp)
         R_RSP+=((nargs-6)*sizeof(void*));
 
-    if(!emu->longjmp && R_CS==0x33)
+    if(!emu->flags.longjmp && R_CS==0x33)
         R_CS = old_cs;
 
-    emu->quitonlongjmp = oldquitonlongjmp;
+    emu->flags.quitonlongjmp = oldquitonlongjmp;
 
     #ifdef DYNAREC
     if(box64_dynarec_test)
@@ -347,9 +347,9 @@ uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext,
         emu->test.clean = 0;
     #endif
 
-    if(emu->longjmp) {
+    if(emu->flags.longjmp) {
         // longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
-        emu->longjmp = 0;
+        emu->flags.longjmp = 0;
         if(sigcontext) {
             sigcontext->uc_mcontext.gregs[X64_R8] = R_R8;
             sigcontext->uc_mcontext.gregs[X64_R9] = R_R9;
diff --git a/src/tools/callback.c b/src/tools/callback.c
index f3a6bbbf..162c801f 100644
--- a/src/tools/callback.c
+++ b/src/tools/callback.c
@@ -233,10 +233,10 @@ uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in
 
     uintptr_t oldip = R_RIP;
     int old_quit = emu->quit;
-    int oldlong = emu->quitonlongjmp;
+    int oldlong = emu->flags.quitonlongjmp;
 
     emu->quit = 0;
-    emu->quitonlongjmp = QuitOnLongJump;
+    emu->flags.quitonlongjmp = QuitOnLongJump;
 
     DynaCall(emu, fnc);
 
@@ -246,7 +246,7 @@ uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in
     }
 
     emu->quit = old_quit;
-    emu->quitonlongjmp = oldlong;
+    emu->flags.quitonlongjmp = oldlong;
 
 
     return R_RAX;
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 45758e32..06726923 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -2494,8 +2494,8 @@ void EXPORT my_longjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p,
     if(((__jmp_buf_tag_t*)p)->__mask_was_saved) {
         sigprocmask(SIG_SETMASK, &((__jmp_buf_tag_t*)p)->__saved_mask, NULL);
     }
-    if(emu->quitonlongjmp) {
-        emu->longjmp = 1;
+    if(emu->flags.quitonlongjmp) {
+        emu->flags.longjmp = 1;
         emu->quit = 1;
     }
 }
@@ -2520,8 +2520,10 @@ EXPORT int32_t my___sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/vo
     } 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;
+    if(!emu->flags.jmpbuf_ready) {
+        emu->flags.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)
@@ -3192,10 +3194,10 @@ static int clone_fn(void* p)
     updateGlibcTidCache();  // update cache tid if needed
     x64emu_t *emu = arg->emu;
     R_RSP = arg->stack;
-    emu->quitonexit = 1;
+    emu->flags.quitonexit = 1;
     thread_set_emu(emu);
     int ret = RunFunctionWithEmu(emu, 0, arg->fnc, 1, arg->args);
-    int exited = (emu->quitonexit==2);
+    int exited = (emu->flags.quitonexit==2);
     thread_set_emu(NULL);
     FreeX64Emu(&emu);
     if(arg->stack_clone_used)
@@ -3274,10 +3276,10 @@ EXPORT int my_register_printf_type(x64emu_t* emu, void* f)
 extern int box64_quit;
 EXPORT void my_exit(x64emu_t* emu, int code)
 {
-    if(emu->quitonexit) {
+    if(emu->flags.quitonexit) {
         emu->quit = 1;
         R_EAX = code;
-        emu->quitonexit = 2;
+        emu->flags.quitonexit = 2;
         return;
     }
     emu->quit = 1;