diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-07-15 11:03:06 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-07-15 11:03:06 +0200 |
| commit | 35119f8db219ad8b20ccd3f6952fd7164194c600 (patch) | |
| tree | e502aefe606dd59405b7f18b4a080a787f6c3afc /src | |
| parent | c95af7c81bd06f4fe241f8c71ffa8ef66e6b5b71 (diff) | |
| download | box64-35119f8db219ad8b20ccd3f6952fd7164194c600.tar.gz box64-35119f8db219ad8b20ccd3f6952fd7164194c600.zip | |
Handling HLT / CLI / STI has privileged instruction (and so trigger a GPF)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/emu/x64run.c | 15 | ||||
| -rwxr-xr-x | src/emu/x64run_private.c | 5 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 14 |
3 files changed, 25 insertions, 9 deletions
diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 92a0dc11..782ed520 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -1253,8 +1253,9 @@ x64emurun: break; case 0xF4: /* HLT */ - // this is a privilege opcode... should an error be called instead? - sched_yield(); + // this is a privilege opcode... + --R_RIP; + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); STEP; break; case 0xF5: /* CMC */ @@ -1370,10 +1371,16 @@ x64emurun: SET_FLAG(F_CF); break; case 0xFA: /* CLI */ - CLEAR_FLAG(F_IF); //not really handled... + // this is a privilege opcode... + --R_RIP; + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + STEP; break; case 0xFB: /* STI */ - SET_FLAG(F_IF); + // this is a privilege opcode... + --R_RIP; + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + STEP; break; case 0xFC: /* CLD */ CLEAR_FLAG(F_DF); diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index ef697968..20d2c870 100755 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -1000,6 +1000,11 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec) } #endif printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip)); + if(R_RIP==0) { + printf_log(LOG_NONE, "Running at NULL address\n"); + pthread_mutex_unlock(&my_context->mutex_trace); + return; + } if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') { uint64_t a = *(uint64_t*)(ip+3); if(a==0) { diff --git a/src/libtools/signals.c b/src/libtools/signals.c index d56e73ee..6595e3fb 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -303,7 +303,8 @@ uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...) } va_end (va); - EmuCall(emu, fnc); // avoid DynaCall for now + //EmuCall(emu, fnc); // avoid DynaCall for now + DynaCall(emu, fnc); if(nargs>6) R_RSP+=((nargs-6)*4); @@ -555,8 +556,8 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 17; else if(sig==SIGSEGV) { if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[X64_RIP]) { - sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0010; // execution flag issue (probably) - sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14; + sigcontext->uc_mcontext.gregs[X64_ERR] = (info->si_errno==0x1234)?0:0x0010; // execution flag issue (probably), unless it's a #GP(0) + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR || (info->si_errno==0x1234) || (uintptr_t)info->si_addr==0)?13:14; } else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) { sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0002; // write flag issue if(labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16) @@ -643,7 +644,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff; GO(FS); #undef GO - printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu\n"); + printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p\n", (void*)R_RIP); if(old_code) *old_code = -1; // re-init the value to allow another segfault at the same place if(used_stack) // release stack @@ -834,6 +835,9 @@ exit(-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; x64pc = R_RIP; rsp = (void*)R_RSP; #if defined(__aarch64__) && defined(DYNAREC) @@ -927,7 +931,7 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code) void* db = NULL; siginfo_t info = {0}; info.si_signo = sig; - info.si_errno = 0; + info.si_errno = (sig==SIGSEGV)?0x1234:0; // MAark as a sign this is a #GP(0) (like privileged instruction) info.si_code = code; info.si_addr = addr; const char* x64name = NULL; |