diff options
Diffstat (limited to 'src/libtools/signals.c')
| -rw-r--r-- | src/libtools/signals.c | 199 |
1 files changed, 133 insertions, 66 deletions
diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 39dc190e..468a83f5 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <stdint.h> @@ -269,7 +270,7 @@ static void sigstack_key_alloc() { //1<<8 is mutex_dyndump #define is_dyndump_locked (1<<8) -uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...) +uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...) { if(fnc==0 || fnc==1) { va_list va; @@ -295,8 +296,6 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc if(box64_dynarec_test) emu->test.test = 0; #endif - - printf_log(LOG_DEBUG, "%04d|signal function handler %p called, RSP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP); /*SetFS(emu, default_fs);*/ for (int i=0; i<6; ++i) @@ -320,14 +319,26 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc } va_end (va); + 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 old_cs = R_CS; + R_CS = 0x33; - EmuCall(emu, fnc); // avoid DynaCall for now - //DynaCall(emu, fnc); - if(nargs>6) + emu->eflags.x64 &= ~(1<<F_TF); // this one needs to cleared + + if(dynarec) + DynaCall(emu, fnc); + else + EmuCall(emu, fnc); + + if(nargs>6 && !emu->longjmp) R_RSP+=((nargs-6)*sizeof(void*)); + if(!emu->longjmp && R_CS==0x33) + R_CS = old_cs; + emu->quitonlongjmp = oldquitonlongjmp; #ifdef DYNAREC @@ -449,6 +460,25 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr) } while(db->instsize[i].x64 || db->instsize[i].nat); return x64addr; } +x64emu_t* getEmuSignal(x64emu_t* emu, ucontext_t* p, dynablock_t* db) +{ +#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 + return emu; +} #endif void copyUCTXreg2Emu(x64emu_t* emu, ucontext_t* p, uintptr_t ip) { @@ -713,16 +743,21 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void else sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 14; // PAGE_FAULT } else { - sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14; + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?14:13; //X64_ERR seems to be INT:8 CODE:8. So for write access segfault it's 0x0002 For a read it's 0x0004 (and 8 for exec). For an int 2d it could be 0x2D01 for example sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0004; // read error? there is no execute control in box64 anyway } if(info->si_code == SEGV_ACCERR && old_code) *old_code = -1; - } else if(sig==SIGFPE) - sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 19; - else if(sig==SIGILL) + } else if(sig==SIGFPE) { + if (info->si_code == FPE_INTOVF) + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 4; + else + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 19; + } else if(sig==SIGILL) sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 6; + else if(sig==SIGTRAP) + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = info->si_code; //TODO: SIGABRT generate what? // call the signal handler x64_ucontext_t sigcontext_copy = *sigcontext; @@ -744,10 +779,15 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void int exits = 0; int ret; - if (simple) - ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 1, sig); - else - ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 3, sig, info2, sigcontext); + int dynarec = 0; + #ifdef DYNAREC + if(sig!=SIGSEGV && !(Locks&is_dyndump_locked)) + dynarec = 1; + #endif + /*if (simple) + ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[sig], 1, sig); + else*/ + ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[sig], 3, sig, info2, sigcontext); // restore old value from emu if(used_stack) // release stack new_ss->ss_flags = 0; @@ -763,9 +803,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); @@ -775,7 +814,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); @@ -785,14 +824,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); @@ -809,7 +848,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)":""); } @@ -854,13 +893,23 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void exit(ret); } if(restorer) - RunFunctionHandler(&exits, NULL, restorer, 0); + RunFunctionHandler(&exits, 0, NULL, restorer, 0); relockMutex(Locks); } extern void* current_helper; -#ifdef DYNAREC +#define USE_SIGNAL_MUTEX +#ifdef USE_SIGNAL_MUTEX +#ifdef USE_CUSTOM_MUTEX static uint32_t mutex_dynarec_prot = 0; +#else +static pthread_mutex_t mutex_dynarec_prot = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; +#endif +#define lock_signal() mutex_lock(&mutex_dynarec_prot) +#define unlock_signal() mutex_unlock(&mutex_dynarec_prot) +#else // USE_SIGNAL_MUTEX +#define lock_signal() +#define unlock_signal() #endif extern int box64_quit; @@ -876,6 +925,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; @@ -915,14 +965,14 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) #endif #ifdef DYNAREC if((Locks & is_dyndump_locked) && (sig==SIGSEGV) && current_helper) { - relockMutex(Locks); CancelBlock64(0); cancelFillBlock(); // Segfault inside a Fillblock, cancel it's creation... + relockMutex(Locks); } dynablock_t* db = NULL; int db_searched = 0; if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) { - mutex_lock(&mutex_dynarec_prot); + lock_signal(); // check if SMC inside block db = FindDynablockFromNativeAddress(pc); db_searched = 1; @@ -939,31 +989,33 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) } // access error, unprotect the block (and mark them dirty) unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected - if(db && ((addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) || getNeedTest((uintptr_t)db->x64_addr))) { + 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 - 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]; - } + //TODO: Need proper SIMD/x87 register traking! + /*if(fpsimd) { + 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 @@ -974,25 +1026,24 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) dynarec_log(LOG_INFO, "Dynablock unprotected, getting out!\n"); } //relockMutex(Locks); - mutex_unlock(&mutex_dynarec_prot); - #ifdef DYNAREC + unlock_signal(); if(Locks & is_dyndump_locked) CancelBlock64(1); - #endif - 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); } // done - if((prot&PROT_WRITE) || (prot&PROT_DYNAREC)) { - mutex_unlock(&mutex_dynarec_prot); + if((prot&PROT_WRITE)/*|| (prot&PROT_DYNAREC)*/) { + unlock_signal(); // if there is no write permission, don't return and continue to program signal handling relockMutex(Locks); return; } - mutex_unlock(&mutex_dynarec_prot); + unlock_signal(); } else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && ((prot&(PROT_READ|PROT_WRITE))==(PROT_READ|PROT_WRITE))) { - mutex_lock(&mutex_dynarec_prot); + lock_signal(); db = FindDynablockFromNativeAddress(pc); db_searched = 1; if(db && db->x64_addr>= addr && (db->x64_addr+db->x64_size)<addr) { @@ -1011,7 +1062,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) glitch_addr = addr; glitch_prot = prot; relockMutex(Locks); - mutex_unlock(&mutex_dynarec_prot); + unlock_signal(); return; // try again } dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x\n", pc, addr, db, prot); @@ -1033,14 +1084,14 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for refreshProtection((uintptr_t)addr); relockMutex(Locks); sched_yield(); // give time to the other process - mutex_unlock(&mutex_dynarec_prot); + unlock_signal(); return; // try again } glitch2_pc = NULL; glitch2_addr = NULL; glitch2_prot = 0; } - mutex_unlock(&mutex_dynarec_prot); + unlock_signal(); } else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC_R)) { // unprotect and continue to signal handler, because Write is not there on purpose unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected @@ -1081,7 +1132,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; @@ -1089,9 +1139,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]; @@ -1218,6 +1265,7 @@ exit(-1); } if(log_minimum<=box64_log) { static const char* reg_name[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", " R8", " R9","R10","R11", "R12","R13","R14","R15"}; + static const char* seg_name[] = {"ES", "CS", "SS", "DS", "GS", "FS"}; int shown_regs = 0; #ifdef DYNAREC uint32_t hash = 0; @@ -1239,8 +1287,11 @@ exit(-1); if(!(i%4)) printf_log(log_minimum, "\n"); printf_log(log_minimum, "%s:0x%016llx ", reg_name[i], p->uc_mcontext.regs[10+i]); } + printf_log(log_minimum, "\n"); + for (int i=0; i<6; ++i) + printf_log(log_minimum, "%s:0x%04x ", seg_name[i], emu->segs[i]); } - if(rsp!=addr) + if(rsp!=addr && getProtection((uintptr_t)rsp-4*8) && getProtection((uintptr_t)rsp+4*8)) for (int i=-4; i<4; ++i) { printf_log(log_minimum, "%sRSP%c0x%02x:0x%016lx", (i%4)?" ":"\n", i<0?'-':'+', abs(i)*8, *(uintptr_t*)(rsp+i*8)); } @@ -1251,8 +1302,11 @@ exit(-1); if(!(i%4)) printf_log(log_minimum, "\n"); printf_log(log_minimum, "%s:0x%016llx ", reg_name[i], p->uc_mcontext.__gregs[16+i]); } + printf_log(log_minimum, "\n"); + for (int i=0; i<6; ++i) + printf_log(log_minimum, "%s:0x%04x ", seg_name[i], emu->segs[i]); } - if(rsp!=addr) + if(rsp!=addr && getProtection((uintptr_t)rsp-4*8) && getProtection((uintptr_t)rsp+4*8)) for (int i=-4; i<4; ++i) { printf_log(log_minimum, "%sRSP%c0x%02x:0x%016lx", (i%4)?" ":"\n", i<0?'-':'+', abs(i)*8, *(uintptr_t*)(rsp+i*8)); } @@ -1262,11 +1316,15 @@ exit(-1); #else printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code); #endif - if(!shown_regs) + if(!shown_regs) { for (int i=0; i<16; ++i) { if(!(i%4)) printf_log(log_minimum, "\n"); printf_log(log_minimum, "%s:0x%016llx ", reg_name[i], emu->regs[i].q[0]); } + printf_log(log_minimum, "\n"); + for (int i=0; i<6; ++i) + printf_log(log_minimum, "%s:0x%04x ", seg_name[i], emu->segs[i]); + } if(sig==SIGILL) printf_log(log_minimum, " opcode=%02X %02X %02X %02X %02X %02X %02X %02X (%02X %02X %02X %02X %02X)\n", ((uint8_t*)pc)[0], ((uint8_t*)pc)[1], ((uint8_t*)pc)[2], ((uint8_t*)pc)[3], ((uint8_t*)pc)[4], ((uint8_t*)pc)[5], ((uint8_t*)pc)[6], ((uint8_t*)pc)[7], ((uint8_t*)x64pc)[0], ((uint8_t*)x64pc)[1], ((uint8_t*)x64pc)[2], ((uint8_t*)x64pc)[3], ((uint8_t*)x64pc)[4]); else if(sig==SIGBUS) @@ -1360,6 +1418,7 @@ EXPORT sighandler_t my_sysv_signal(x64emu_t* emu, int signum, sighandler_t handl int EXPORT my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x64_sigaction_t *oldact) { + printf_log(LOG_DEBUG, "Sigaction(signum=%d, act=%p(f=%p, flags=0x%x), old=%p)\n", signum, act, act?act->_u._sa_handler:NULL, act?act->sa_flags:0, oldact); if(signum<0 || signum>=MAX_SIGNAL) { errno = EINVAL; return -1; @@ -1372,6 +1431,7 @@ int EXPORT my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x return 0; struct sigaction newact = {0}; struct sigaction old = {0}; + uintptr_t old_handler = my_context->signals[signum]; if(act) { newact.sa_mask = act->sa_mask; newact.sa_flags = act->sa_flags&~0x04000000; // No sa_restorer... @@ -1404,6 +1464,8 @@ int EXPORT my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x oldact->_u._sa_sigaction = old.sa_sigaction; //TODO should wrap... else oldact->_u._sa_handler = old.sa_handler; //TODO should wrap... + if((uintptr_t)oldact->_u._sa_sigaction == (uintptr_t)my_sigactionhandler && old_handler) + oldact->_u._sa_sigaction = (void*)old_handler; oldact->sa_restorer = NULL; // no handling for now... } return ret; @@ -1471,7 +1533,7 @@ int EXPORT my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigactio struct sigaction newact = {0}; struct sigaction old = {0}; if(act) { - printf_log(LOG_DEBUG, " New action flags=0x%x mask=0x%lx\n", act->sa_flags, *(uint64_t*)&act->sa_mask); + printf_log(LOG_DEBUG, " New action for signal #%d flags=0x%x mask=0x%lx\n", signum, act->sa_flags, *(uint64_t*)&act->sa_mask); newact.sa_mask = act->sa_mask; newact.sa_flags = act->sa_flags&~0x04000000; // No sa_restorer... if(act->sa_flags&0x04) { @@ -1648,7 +1710,7 @@ EXPORT int my_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, int } // push the return value --rsp; - *rsp = (uintptr_t)GetExit(); + *rsp = my_context->exit_bridge; u->uc_mcontext.gregs[X64_RSP] = (uintptr_t)rsp; return 0; @@ -1663,10 +1725,15 @@ EXPORT int my_swapcontext(x64emu_t* emu, void* ucp1, void* ucp2) my_setcontext(emu, ucp2); return 0; } -#ifdef DYNAREC +#ifdef USE_SIGNAL_MUTEX static void atfork_child_dynarec_prot(void) { + #ifdef USE_CUSTOM_MUTEX native_lock_store(&mutex_dynarec_prot, 0); + #else + pthread_mutex_t tmp = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; + memcpy(&mutex_dynarec_prot, &tmp, sizeof(mutex_dynarec_prot)); + #endif } #endif void init_signal_helper(box64context_t* context) @@ -1690,7 +1757,7 @@ void init_signal_helper(box64context_t* context) sigaction(SIGABRT, &action, NULL); pthread_once(&sigstack_key_once, sigstack_key_alloc); -#ifdef DYNAREC +#ifdef USE_SIGNAL_MUTEX atfork_child_dynarec_prot(); pthread_atfork(NULL, NULL, atfork_child_dynarec_prot); #endif |