diff options
Diffstat (limited to 'src/libtools/signals.c')
| -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)":""); |