diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-07-08 17:21:49 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-07-08 17:21:49 +0200 |
| commit | ab2d68ef45c729134d92e9dad0d78c1fa035a489 (patch) | |
| tree | bd8d00b0d7367eb2523f0abde9ff7b00ba547740 | |
| parent | b7a2d59a61809739f86c2840294adb000a40f38f (diff) | |
| download | box64-ab2d68ef45c729134d92e9dad0d78c1fa035a489.tar.gz box64-ab2d68ef45c729134d92e9dad0d78c1fa035a489.zip | |
Simplyfied internal jmpbuf handling
| -rwxr-xr-x | src/dynarec/dynarec.c | 93 | ||||
| -rwxr-xr-x | src/emu/x64emu_private.h | 1 | ||||
| -rwxr-xr-x | src/include/threads.h | 8 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 76 | ||||
| -rwxr-xr-x | src/libtools/threads.c | 29 |
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); |