about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-07-08 17:21:49 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-07-08 17:21:49 +0200
commitab2d68ef45c729134d92e9dad0d78c1fa035a489 (patch)
treebd8d00b0d7367eb2523f0abde9ff7b00ba547740 /src
parentb7a2d59a61809739f86c2840294adb000a40f38f (diff)
downloadbox64-ab2d68ef45c729134d92e9dad0d78c1fa035a489.tar.gz
box64-ab2d68ef45c729134d92e9dad0d78c1fa035a489.zip
Simplyfied internal jmpbuf handling
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/dynarec.c93
-rwxr-xr-xsrc/emu/x64emu_private.h1
-rwxr-xr-xsrc/include/threads.h8
-rwxr-xr-xsrc/libtools/signals.c76
-rwxr-xr-xsrc/libtools/threads.c29
5 files changed, 77 insertions, 130 deletions
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c
index 0aa12c58..ab7a21ae 100755
--- a/src/dynarec/dynarec.c
+++ b/src/dynarec/dynarec.c
@@ -81,27 +81,21 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
 void DynaCall(x64emu_t* emu, uintptr_t addr)
 {
     // prepare setjump for signal handling
-    emu_jmpbuf_t *ejb = NULL;
-    int jmpbuf_reset = 0;
+    struct __jmp_buf_tag jmpbuf[1] = {0};
     int skip = 0;
-    if(emu->type == EMUTYPE_MAIN) {
-        ejb = GetJmpBuf();
-        if(!ejb->jmpbuf_ok) {
-            ejb->emu = emu;
-            ejb->jmpbuf_ok = 1;
-            jmpbuf_reset = 1;
-            if((skip = sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
-                printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->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
-            }
+    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)
@@ -140,16 +134,6 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
                 emu->quit = 0;
                 emu->fork = 0;
                 emu = x64emu_fork(emu, forktype);
-                if(emu->type == EMUTYPE_MAIN) {
-                    ejb = GetJmpBuf();
-                    ejb->emu = emu;
-                    ejb->jmpbuf_ok = 1;
-                    jmpbuf_reset = 1;
-                    if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
-                        printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
-                        addr = R_RIP;
-                    }
-                }
             }
         }
         emu->quit = 0;  // reset Quit flags...
@@ -168,38 +152,28 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
     }
 #endif
     // clear the setjmp
-    if(ejb && jmpbuf_reset)
-        ejb->jmpbuf_ok = 0;
+    emu->jmpbuf = old_jmpbuf;
 }
 
 int DynaRun(x64emu_t* emu)
 {
     // prepare setjump for signal handling
-    emu_jmpbuf_t *ejb = NULL;
-    int skip;
-#ifdef DYNAREC
-    int jmpbuf_reset = 1;
-#endif
-    if(emu->type == EMUTYPE_MAIN) {
-        ejb = GetJmpBuf();
-        if(!ejb->jmpbuf_ok) {
-            ejb->emu = emu;
-            ejb->jmpbuf_ok = 1;
-#ifdef DYNAREC
-            jmpbuf_reset = 1;
-#endif
-            if((skip=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
-                printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
-                #ifdef DYNAREC
-                if(box64_dynarec_test) {
-                    if(emu->test.clean)
-                        x64test_check(emu, R_RIP);
-                    emu->test.clean = 0;
-                }
-                #endif
-            }
+    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;
         }
+        #endif
     }
+
 #ifdef DYNAREC
     if(!box64_dynarec)
 #endif
@@ -227,20 +201,11 @@ int DynaRun(x64emu_t* emu)
                 emu->quit = 0;
                 emu->fork = 0;
                 emu = x64emu_fork(emu, forktype);
-                if(emu->type == EMUTYPE_MAIN) {
-                    ejb = GetJmpBuf();
-                    ejb->emu = emu;
-                    ejb->jmpbuf_ok = 1;
-                    jmpbuf_reset = 1;
-                    if((skip = sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)))
-                        printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
-                }
             }
         }
     }
     // clear the setjmp
-    if(ejb && jmpbuf_reset)
-        ejb->jmpbuf_ok = 0;
+    emu->jmpbuf = old_jmpbuf;
     return 0;
 #endif
 }
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 9e7b599e..250d8cee 100755
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -98,6 +98,7 @@ typedef struct x64emu_s {
     void*       stack2free; // this is the stack to free (can be NULL)
     void*       init_stack; // initial stack (owned or not)
     uint32_t    size_stack; // stack size (owned or not)
+    struct __jmp_buf_tag *jmpbuf;
 
     x64_ucontext_t *uc_link; // to handle setcontext
 
diff --git a/src/include/threads.h b/src/include/threads.h
index ec133d16..af58046b 100755
--- a/src/include/threads.h
+++ b/src/include/threads.h
@@ -4,16 +4,8 @@
 typedef struct box64context_s box64context_t;
 typedef struct x64emu_s x64emu_t;
 
-typedef struct emu_jmpbuf_s {
-    x64emu_t*   emu;
-	void* 	    jmpbuf;
-	int 	    jmpbuf_ok;
-} emu_jmpbuf_t;
-
 void CleanStackSize(box64context_t* context);
 
-emu_jmpbuf_t* GetJmpBuf(void);
-
 void init_pthread_helper(void);
 void fini_pthread_helper(box64context_t* context);
 
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index de014cfe..b3a18d8d 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -527,6 +527,28 @@ void copyUCTXreg2Emu(x64emu_t* emu, ucontext_t* p, uintptr_t ip) {
 #endif
 }
 
+x64emu_t* getEmuSignal(x64emu_t* emu, ucontext_t* p, dynablock_t* db)
+{
+#if defined(DYNAREC)
+#if defined(ARM64)
+        if(db && p->uc_mcontext.regs[0]>0x10000) {
+            emu = (x64emu_t*)p->uc_mcontext.regs[0];
+        }
+#elif defined(LA464)
+        if(db && p->uc_mcontext.__gregs[4]>0x10000) {
+            emu = (x64emu_t*)p->uc_mcontext.__gregs[4];
+        }
+#elif defined(RV64)
+        if(db && p->uc_mcontext.__gregs[10]>0x10000) {
+            emu = (x64emu_t*)p->uc_mcontext.__gregs[10];
+        }
+#else
+#error Unsupported Architecture
+#endif //arch
+#endif //DYNAREC
+    return emu;
+}
+
 void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db)
 {
     int Locks = unlockMutex();
@@ -784,9 +806,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
     #undef GO
 
     if(memcmp(sigcontext, &sigcontext_copy, sizeof(x64_ucontext_t))) {
-        emu_jmpbuf_t* ejb = GetJmpBuf();
-        if(ejb->jmpbuf_ok) {
-            #define GO(R)   ejb->emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
+        if(emu->jmpbuf) {
+            #define GO(R)   emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
             GO(AX);
             GO(CX);
             GO(DX);
@@ -796,7 +817,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
             GO(SP);
             GO(BX);
             #undef GO
-            #define GO(R)   ejb->emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_##R]
+            #define GO(R)   emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_##R]
             GO(R8);
             GO(R9);
             GO(R10);
@@ -806,14 +827,14 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
             GO(R14);
             GO(R15);
             #undef GO
-            ejb->emu->ip.q[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
+            emu->ip.q[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
             sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
             // flags
-            ejb->emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
+            emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
             // get segments
             uint16_t seg;
             seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff;
-            #define GO(S) if(ejb->emu->segs[_##S]!=seg)  {ejb->emu->segs[_##S]=seg; ejb->emu->segs_serial[_##S] = 0;}
+            #define GO(S) if(emu->segs[_##S]!=seg)  {emu->segs[_##S]=seg; emu->segs_serial[_##S] = 0;}
             GO(CS);
             seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 16)&0xffff;
             GO(GS);
@@ -830,7 +851,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
             if(Locks & is_dyndump_locked)
                 CancelBlock64(1);
             #endif
-            siglongjmp(ejb->jmpbuf, 1);
+            siglongjmp(emu->jmpbuf, 1);
         }
         printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP])?" (EIP changed)":"");
     }
@@ -907,6 +928,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
     ucontext_t *p = (ucontext_t *)ucntx;
     void* addr = (void*)info->si_addr;  // address that triggered the issue
     void* rsp = NULL;
+    x64emu_t* emu = thread_get_emu();
 #ifdef __aarch64__
     void * pc = (void*)p->uc_mcontext.pc;
     struct fpsimd_context *fpsimd = NULL;
@@ -972,31 +994,31 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
         unprotectDB((uintptr_t)addr, 1, 1);    // unprotect 1 byte... But then, the whole page will be unprotected
         int db_need_test = (db && !box64_dynarec_fastpage)?getNeedTest((uintptr_t)db->x64_addr):0;
         if(db && ((addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) || db_need_test)) {
+            emu = getEmuSignal(emu, p, db);
             // dynablock got auto-dirty! need to get out of it!!!
-            emu_jmpbuf_t* ejb = GetJmpBuf();
-            if(ejb->jmpbuf_ok) {
-                copyUCTXreg2Emu(ejb->emu, p, getX64Address(db, (uintptr_t)pc));
+            if(emu->jmpbuf) {
+                copyUCTXreg2Emu(emu, p, getX64Address(db, (uintptr_t)pc));
 #ifdef ARM64
                 //TODO: Need proper SIMD/x87 register traking!
                 /*if(fpsimd) {
-                    ejb->emu->xmm[0].u128 = fpsimd->vregs[0];
-                    ejb->emu->xmm[1].u128 = fpsimd->vregs[1];
-                    ejb->emu->xmm[2].u128 = fpsimd->vregs[2];
-                    ejb->emu->xmm[3].u128 = fpsimd->vregs[3];
+                    emu->xmm[0].u128 = fpsimd->vregs[0];
+                    emu->xmm[1].u128 = fpsimd->vregs[1];
+                    emu->xmm[2].u128 = fpsimd->vregs[2];
+                    emu->xmm[3].u128 = fpsimd->vregs[3];
                 }*/
 #elif defined(LA464)
                 /*if(fpsimd) {
-                    ejb->emu->xmm[0].u128 = fpsimd->vregs[0];
-                    ejb->emu->xmm[1].u128 = fpsimd->vregs[1];
-                    ejb->emu->xmm[2].u128 = fpsimd->vregs[2];
-                    ejb->emu->xmm[3].u128 = fpsimd->vregs[3];
+                    emu->xmm[0].u128 = fpsimd->vregs[0];
+                    emu->xmm[1].u128 = fpsimd->vregs[1];
+                    emu->xmm[2].u128 = fpsimd->vregs[2];
+                    emu->xmm[3].u128 = fpsimd->vregs[3];
                 }*/
 #elif defined(RV64)
                 /*if(fpsimd) {
-                    ejb->emu->xmm[0].u128 = fpsimd->vregs[0];
-                    ejb->emu->xmm[1].u128 = fpsimd->vregs[1];
-                    ejb->emu->xmm[2].u128 = fpsimd->vregs[2];
-                    ejb->emu->xmm[3].u128 = fpsimd->vregs[3];
+                    emu->xmm[0].u128 = fpsimd->vregs[0];
+                    emu->xmm[1].u128 = fpsimd->vregs[1];
+                    emu->xmm[2].u128 = fpsimd->vregs[2];
+                    emu->xmm[3].u128 = fpsimd->vregs[3];
                 }*/
 #else
 #error  Unsupported architecture
@@ -1010,8 +1032,8 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
                 unlock_signal();
                 if(Locks & is_dyndump_locked)
                     CancelBlock64(1);
-                ejb->emu->test.clean = 0;
-                siglongjmp(ejb->jmpbuf, 2);
+                emu->test.clean = 0;
+                siglongjmp(emu->jmpbuf, 2);
             }
             dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr);
         }
@@ -1113,7 +1135,6 @@ exit(-1);
         uintptr_t x64pc = (uintptr_t)-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;
@@ -1121,9 +1142,6 @@ exit(-1);
         rsp = (void*)R_RSP;
 #if defined(DYNAREC)
 #if defined(ARM64)
-        if(db && p->uc_mcontext.regs[0]>0x10000) {
-            emu = (x64emu_t*)p->uc_mcontext.regs[0];
-        }
         if(db) {
             x64pc = getX64Address(db, (uintptr_t)pc);
             rsp = (void*)p->uc_mcontext.regs[10+_SP];
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index c2c6dfb1..d70851f6 100755
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -1066,28 +1066,6 @@ EXPORT int my_pthread_barrier_init(x64emu_t* emu, pthread_barrier_t* bar, my_bar
 
 #endif
 
-static void emujmpbuf_destroy(void* p)
-{
-	emu_jmpbuf_t *ej = (emu_jmpbuf_t*)p;
-	if(ej) {
-		box_free(ej->jmpbuf);
-		box_free(ej);
-	}
-}
-
-static pthread_key_t jmpbuf_key;
-
-emu_jmpbuf_t* GetJmpBuf()
-{
-	emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
-	if(!ejb) {
-		ejb = (emu_jmpbuf_t*)box_calloc(1, sizeof(emu_jmpbuf_t));
-		ejb->jmpbuf = box_calloc(1, sizeof(struct __jmp_buf_tag));
-		pthread_setspecific(jmpbuf_key, ejb);
-	}
-	return ejb;
-}
-
 void init_pthread_helper()
 {
 	real_pthread_cleanup_push_defer = (vFppp_t)dlsym(NULL, "_pthread_cleanup_push_defer");
@@ -1108,8 +1086,6 @@ void init_pthread_helper()
 	}
 
 	InitCancelThread();
-	pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
-	pthread_setspecific(jmpbuf_key, NULL);
 	pthread_key_create(&thread_key, emuthread_destroy);
 	pthread_setspecific(thread_key, NULL);
 }
@@ -1118,11 +1094,6 @@ void fini_pthread_helper(box64context_t* context)
 {
 	FreeCancelThread(context);
 	CleanStackSize(context);
-	emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
-	if(ejb) {
-		pthread_setspecific(jmpbuf_key, NULL);
-		emujmpbuf_destroy(ejb);
-	}
 	emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
 	if(et) {
 		pthread_setspecific(thread_key, NULL);