diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-09-01 11:00:34 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-09-01 11:00:34 +0200 |
| commit | 1edd0eb47d207b21af0586db36abfc3625d1a849 (patch) | |
| tree | 9f8b104579156c27f56bc78d7eac4fa57060c3d7 | |
| parent | f46987b6af1459046a9fbc590e6814a9e8800125 (diff) | |
| download | box64-1edd0eb47d207b21af0586db36abfc3625d1a849.tar.gz box64-1edd0eb47d207b21af0586db36abfc3625d1a849.zip | |
Allow resuming signal directly on dynarec instead of interpretor when possible
| -rw-r--r-- | src/libtools/signals.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 7fa41e7b..7f99c182 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -986,6 +986,7 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi uint32_t mmapped = memExist((uintptr_t)info->si_addr); uint32_t sysmapped = (info->si_addr<(void*)box64_pagesize)?1:mmapped; uint32_t real_prot = 0; + int skip = 1; // in case sigjump is used to restore exectuion, 1 will switch to interpreter, 3 will switch to dynarec if(prot&PROT_READ) real_prot|=PROT_READ; if(prot&PROT_WRITE) real_prot|=PROT_WRITE; if(prot&PROT_EXEC) real_prot|=PROT_WRITE; @@ -1010,6 +1011,7 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi if(!mmapped) info2->si_code = 1; info2->si_errno = 0; } else if (info->si_errno==0xb09d) { + // bound exception sigcontext->uc_mcontext.gregs[X64_ERR] = 0; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 5; info2->si_errno = 0; @@ -1035,6 +1037,7 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi info2->si_code = 128; info2->si_addr = NULL; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 13; + skip = 3; // can resume in dynarec // some special cases... if(int_n==3) { info2->si_signo = X64_SIGTRAP; @@ -1054,12 +1057,14 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi sigcontext->uc_mcontext.gregs[X64_ERR] = 0; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 0; info2->si_signo = X64_SIGFPE; + skip = 3; // can resume in dynarec } } else if(sig==X64_SIGFPE) { if (info->si_code == FPE_INTOVF) sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 4; else sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 19; + skip = 3; } else if(sig==X64_SIGILL) { info2->si_code = 2; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 6; @@ -1071,6 +1076,8 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi info2->si_code = 128; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = info->si_code; sigcontext->uc_mcontext.gregs[X64_ERR] = 0; + } else { + skip = 3; // other signal can resume in interpretor } //TODO: SIGABRT generate what? printf_log((sig==10)?LOG_DEBUG:log_minimum, "Signal %d: si_addr=%p, TRAPNO=%d, ERR=%d, RIP=%p, prot=%x, mmapped:%d\n", sig, (void*)info2->si_addr, sigcontext->uc_mcontext.gregs[X64_TRAPNO], sigcontext->uc_mcontext.gregs[X64_ERR],sigcontext->uc_mcontext.gregs[X64_RIP], prot, mmapped); @@ -1140,6 +1147,8 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi GO(R14); GO(R15); #undef GO + if((skip==1) && (emu->ip.q[0]!=sigcontext->uc_mcontext.gregs[X64_RIP])) + skip = 3; // if it jumps elsewhere, it can resume with dynarec... emu->ip.q[0]=sigcontext->uc_mcontext.gregs[X64_RIP]; // flags emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL]; @@ -1155,7 +1164,7 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi #undef GO for(int i=0; i<6; ++i) emu->segs_serial[i] = 0; - printf_log((sig==10)?LOG_DEBUG:log_minimum, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p\n", (void*)R_RIP, (void*)R_RSP); + printf_log((sig==10)?LOG_DEBUG:log_minimum, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p (resume with %s)\n", (void*)R_RIP, (void*)R_RSP, (skip==3)?"Dynarec":"Interp"); if(old_code) *old_code = -1; // re-init the value to allow another segfault at the same place //relockMutex(Locks); // do not relock mutex, because of the siglongjmp, whatever was running is canceled @@ -1167,9 +1176,9 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi emu->xSPSave = emu->old_savedsp; #endif #ifdef ANDROID - siglongjmp(*emu->jmpbuf, 1); + siglongjmp(*emu->jmpbuf, skip); #else - siglongjmp(emu->jmpbuf, 1); + siglongjmp(emu->jmpbuf, skip); #endif } 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)":""); |