From 8f08a141159ce432dc945062bc85213a0864104d Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Mon, 18 Nov 2024 17:18:41 +0100 Subject: [PATCH] Improved Signal handling ([ARM4_DYNAREC] too) --- src/dynarec/arm64/dynarec_arm64_00.c | 9 ++- src/dynarec/dynarec_native_functions.c | 2 +- src/emu/modrm.h | 5 +- src/emu/x64emu.c | 6 +- src/emu/x64run.c | 29 +++++---- src/emu/x64run64.c | 4 +- src/emu/x64run67_32.c | 15 +++++ src/emu/x64run_private.c | 8 +++ src/emu/x64run_private.h | 2 + src/libtools/signal32.c | 90 ++++++++++++++++++++++---- src/libtools/signals.c | 25 ++++--- 11 files changed, 154 insertions(+), 41 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index c777ed3d..807c93cd 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1471,7 +1471,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOV32w(x1, 0x202); ORRw_REG(xFlags, xFlags, x1); SET_DFNONE(x1); - if(box64_wine) { // should this be done all the time? + if(box64_wine || 1) { // should this be done all the time? TBZ_NEXT(xFlags, F_TF); // go to epilog, TF should trigger at end of next opcode, so using Interpreter only jump_to_epilog(dyn, addr, 0, ninst); @@ -2443,7 +2443,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { INST_NAME("INT n"); SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state - GETIP(ip); // priviledged instruction, IP not updated + if(rex.is32bits && u8==0x04) { + GETIP(addr); + } else { + GETIP(ip); // priviledged instruction, IP not updated + } STORE_XEMU_CALL(xRIP); MOV32w(x1,u8); CALL(native_int, -1); @@ -2462,6 +2466,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETIP(addr); TBZ_NEXT(wFlags, F_OF); STORE_XEMU_CALL(xRIP); + MOV32w(x1,4); CALL(native_int, -1); LOAD_XEMU_CALL(xRIP); } diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index f0bf3d08..e2e149f2 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -194,7 +194,7 @@ void native_int3(x64emu_t* emu) void native_div0(x64emu_t* emu) { emu->test.test = 0; - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); } void native_fsave(x64emu_t* emu, uint8_t* ed) diff --git a/src/emu/modrm.h b/src/emu/modrm.h index fcfc7dc6..d62d13c6 100644 --- a/src/emu/modrm.h +++ b/src/emu/modrm.h @@ -11,8 +11,8 @@ #define F64S *(int64_t*)(addr+=8, addr-8) #define PK(a) *(uint8_t*)(addr+a) #ifdef DYNAREC -#define STEP check_exec(emu, addr); if(step) return 0; -#define STEP2 check_exec(emu, addr); if(step) {R_RIP = addr; return 0;} +#define STEP check_exec(emu, addr); if(step && !ACCESS_FLAG(F_TF)) return 0; +#define STEP2 check_exec(emu, addr); if(step && !ACCESS_FLAG(F_TF)) {R_RIP = addr; return 0;} #define STEP3 check_exec(emu, addr); if(*step) (*step)++; #else #define STEP @@ -110,6 +110,7 @@ #define FAKEED32(D) GetEd32O(emu, &addr, rex, nextop, D, 0) #define GETEA(D) GetEA(emu, &addr, rex, nextop, D) #define GETEA32(D) GetEA32(emu, &addr, rex, nextop, D) +#define GETEA32_16(D) GetEA32_16(emu, &addr, rex, nextop, D) #define _GETED(D) oped=GetEd(emu, &addr, rex, nextop, D) #define _GETED_OFFS(D, O) oped=GetEdO(emu, &addr, rex, nextop, D, O) #define _GETED32(D) oped=GetEd32O(emu, &addr, rex, nextop, D, 0) diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index 8eec238b..4441ba53 100644 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -578,15 +578,15 @@ void UnimpOpcode(x64emu_t* emu, int is32bits) R_RIP = emu->old_ip; int tid = syscall(SYS_gettid); - printf_log(LOG_NONE, "%04d|%p: Unimplemented %sOpcode (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + printf_log(LOG_INFO, "%04d|%p: Unimplemented %sOpcode (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", tid, (void*)emu->old_ip, is32bits?"32bits ":"", Peek(emu, -4), Peek(emu, -3), Peek(emu, -2), Peek(emu, -1), Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3), Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7), Peek(emu, 8), Peek(emu, 9), Peek(emu,10), Peek(emu,11), Peek(emu,12), Peek(emu,13), Peek(emu,14)); - emu->quit=1; - emu->error |= ERR_UNIMPL; + //emu->quit=1; + //emu->error |= ERR_UNIMPL; } void EmuCall(x64emu_t* emu, uintptr_t addr) diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 51380c8b..a0939a92 100644 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -245,6 +245,8 @@ x64emurun: } emu->segs[_SS] = Pop32(emu); // no check, no use.... emu->segs_serial[_SS] = 0; + if(ACCESS_FLAG(F_TF)) + tf_next = 1; break; case 0x1E: /* PUSH DS */ @@ -590,10 +592,8 @@ x64emurun: #ifndef TEST_INTERPRETER if(rex.is32bits && box64_ignoreint3) { - F8; } else { - F8; - emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); } STEP; #endif @@ -826,6 +826,8 @@ x64emurun: GETED(0); emu->segs[((nextop&0x38)>>3)] = ED->word[0]; emu->segs_serial[((nextop&0x38)>>3)] = 0; + if(((nextop&0x38)>>3)==_SS && ACCESS_FLAG(F_TF)) + tf_next = 1; break; case 0x8F: /* POP Ed */ nextop = F8; @@ -1544,6 +1546,8 @@ x64emurun: emit_interruption(emu, 0x29, (void*)R_RIP); } else if (tmp8u==0x80) { R_RIP = addr; + if(ACCESS_FLAG(F_TF)) + tf_next = 1; // 32bits syscall #ifndef TEST_INTERPRETER x86Syscall(emu); @@ -1556,6 +1560,9 @@ x64emurun: STEP2; #endif } else { + if(rex.is32bits && tmp8u==0x04) { + R_RIP = addr; + } #ifndef TEST_INTERPRETER emit_interruption(emu, tmp8u, (void*)R_RIP); STEP2; @@ -1572,7 +1579,7 @@ x64emurun: #ifndef TEST_INTERPRETER CHECK_FLAGS(emu); if(ACCESS_FLAG(F_OF)) - emit_signal(emu, SIGSEGV, (void*)R_RIP, 128); + emit_interruption(emu, 4, (void*)R_RIP); STEP2; #endif break; @@ -1954,12 +1961,12 @@ x64emurun: break; case 6: /* DIV Eb */ if(!EB->byte[0]) - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); div8(emu, EB->byte[0]); break; case 7: /* IDIV Eb */ if(!EB->byte[0]) - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); idiv8(emu, EB->byte[0]); break; } @@ -1989,12 +1996,12 @@ x64emurun: break; case 6: /* DIV Ed */ if(!ED->q[0]) - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); div64(emu, ED->q[0]); break; case 7: /* IDIV Ed */ if(!ED->q[0]) - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); idiv64(emu, ED->q[0]); break; } @@ -2029,14 +2036,14 @@ x64emurun: break; case 6: /* DIV Ed */ if(!ED->dword[0]) - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); div32(emu, ED->dword[0]); //emu->regs[_AX].dword[1] = 0; // already put high regs to 0 //emu->regs[_DX].dword[1] = 0; break; case 7: /* IDIV Ed */ if(!ED->dword[0]) - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); idiv32(emu, ED->dword[0]); //emu->regs[_AX].dword[1] = 0; //emu->regs[_DX].dword[1] = 0; @@ -2256,7 +2263,7 @@ if(emu->segs[_CS]!=0x33 && emu->segs[_CS]!=0x23) printf_log(LOG_NONE, "Warning, #ifndef TEST_INTERPRETER printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit); if(unimp) { - emu->quit = 1; + //emu->quit = 1; UnimpOpcode(emu, is32bits); emit_signal(emu, SIGILL, (void*)R_RIP, 0); } diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c index 5433319d..00278e3b 100644 --- a/src/emu/x64run64.c +++ b/src/emu/x64run64.c @@ -792,12 +792,12 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr) break; case 6: /* DIV Eb */ if(!EB->byte[0]) - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); div8(emu, EB->byte[0]); break; case 7: /* IDIV Eb */ if(!EB->byte[0]) - emit_div0(emu, (void*)R_RIP, 0); + emit_div0(emu, (void*)R_RIP, 1); idiv8(emu, EB->byte[0]); break; } diff --git a/src/emu/x64run67_32.c b/src/emu/x64run67_32.c index a1df3ba0..4b7afbea 100644 --- a/src/emu/x64run67_32.c +++ b/src/emu/x64run67_32.c @@ -66,6 +66,21 @@ uintptr_t Run67_32(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) return Run6764_32(emu, rex, rep, _GS, addr); #endif break; + case 0x66: + opcode = F8; + switch(opcode) { + + case 0x8D: /* LEA Gw,M */ + nextop = F8; + GETGW; + tmp32u = GETEA32_16(0); + GW->word[0] = (uint16_t)tmp32u; + break; + + default: + return 0; + } + break; case 0xE0: /* LOOPNZ */ CHECK_FLAGS(emu); diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index a2bc6020..1d80e76a 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -1701,6 +1701,14 @@ uintptr_t GetEA32(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t } else return (uintptr_t)GetECommon32O(emu, addr, rex, m, delta, 0); } +uintptr_t GetEA32_16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return (uintptr_t)&emu->regs[(m&0x07)+(rex.b<<3)]; + } else return (uintptr_t)GetEw16off(emu, addr, rex, m, delta); +} + reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset) { uint8_t m = v&0xC7; // filter Ed diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index e7416b19..35fa99bb 100644 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -115,6 +115,7 @@ static inline void PushExit_32(x64emu_t* emu) reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta); reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset); reg64_t* GetECommon32O(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset); +reg64_t* GetECommon32O_16(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset); reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* TestEb(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); @@ -129,6 +130,7 @@ reg64_t* TestEd8xw(x64test_t *test, int w, uintptr_t* addr, rex_t rex, uint8_t v reg64_t* TestEdt(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); uintptr_t GetEA(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); uintptr_t GetEA32(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +uintptr_t GetEA32_16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* TestEdO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); diff --git a/src/libtools/signal32.c b/src/libtools/signal32.c index 1ce4f822..3f6483fa 100644 --- a/src/libtools/signal32.c +++ b/src/libtools/signal32.c @@ -250,6 +250,61 @@ struct kernel_sigaction { unsigned long sa_mask; unsigned long sa_mask2; }; + +typedef struct __attribute__((packed, aligned(4))) my_siginfo32_s +{ + int si_signo; + int si_errno; + int si_code; + union { + int _pad[128/sizeof(int)-3]; + struct { + __pid_t __si_pid; + __uid_t __si_uid; + } _kill; + struct { + int si_tid; + int __si_overrun; + __sigval_t si_sigval; + } _timer; + struct { + __pid_t __si_pid; + __uid_t __si_uid; + __sigval_t si_sigval; + } _rt; + struct { + __pid_t __si_pid; + __uid_t __si_uid; + int __si_status; + __clock_t __si_utime; + __clock_t __si_stime; + } _sigchld; + struct { + ptr_t __si_addr; + __SI_SIGFAULT_ADDL + short int __si_addr_lsb; + union { + struct { + ptr_t _lower; + ptr_t _upper; + } _addr_bnd; + __uint32_t _pkey; + } _bounds; + } _sigfault; + struct + { + long int __si_band; + int __si_fd; + } _sigpoll; + struct + { + ptr_t _call_addr; + int _syscall; + unsigned int _arch; + } _sigsys; + } _sifields; +} my_siginfo32_t; + #ifdef DYNAREC uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr); #endif @@ -400,7 +455,7 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo int Locks = unlockMutex(); int log_minimum = (box64_showsegv)?LOG_NONE:((sig==SIGSEGV && my_context->is_sigaction[sig])?LOG_DEBUG:LOG_INFO); - printf_log(LOG_DEBUG, "Sigactionhanlder for signal #%d called (jump to %p/%s)\n", sig, (void*)my_context->signals[sig], GetNativeName((void*)my_context->signals[sig])); + printf_log(LOG_INFO/*LOG_DEBUG*/, "Sigactionhanlder32 for signal #%d called (jump to %p/%s)\n", sig, (void*)my_context->signals[sig], GetNativeName((void*)my_context->signals[sig])); uintptr_t restorer = my_context->restorer[sig]; // get that actual ESP first! @@ -462,9 +517,11 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo // setup stack frame frame -= 512+64+16*16; void* xstate = (void*)frame; - frame -= sizeof(siginfo_t); - siginfo_t* info2 = (siginfo_t*)frame; - memcpy(info2, info, sizeof(siginfo_t)); + frame -= sizeof(my_siginfo32_t); + my_siginfo32_t* info2 = (my_siginfo32_t*)frame; + memcpy(info2, info, sizeof(my_siginfo32_t)); + if(sig==SIGILL || sig==SIGFPE || sig==SIGSEGV || sig==SIGBUS) + info2->_sifields._sigfault.__si_addr = to_ptrv(info->si_addr); // try to fill some sigcontext.... frame -= sizeof(i386_ucontext_t); i386_ucontext_t *sigcontext = (i386_ucontext_t*)frame; @@ -580,7 +637,9 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo //bad opcode sigcontext->uc_mcontext.gregs[I386_ERR] = 0; sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 13; + info2->si_code = 128; info2->si_errno = 0; + info2->_sifields._sigfault.__si_addr = 0; } else if (info->si_errno==0xecec) { // no excute bit on segment sigcontext->uc_mcontext.gregs[I386_ERR] = 16;//(real_prot&PROT_READ)?16:1; // EXECUTE_FAULT & READ_FAULT @@ -598,7 +657,7 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo if((info->si_code!=SEGV_ACCERR) && labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[I386_ESP])<16) sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 12; // stack overflow probably else - sigcontext->uc_mcontext.gregs[I386_TRAPNO] = (info->si_code == SEGV_ACCERR)?14:13; + sigcontext->uc_mcontext.gregs[I386_TRAPNO] = (mmapped || ((uintptr_t)info->si_addr<0x10000))?14:13; //I386_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[I386_ERR] = 0x0001; // read error? } @@ -610,8 +669,8 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo // INT x uint8_t int_n = info->si_code; info2->si_errno = 0; - info2->si_code = info->si_code; - info2->si_addr = NULL; + info2->si_code = 128; + info2->_sifields._sigfault.__si_addr = 0; // some special cases... if(int_n==3) { info2->si_signo = SIGTRAP; @@ -624,9 +683,11 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo sigcontext->uc_mcontext.gregs[I386_ERR] = 0x02|(int_n<<3); } else { sigcontext->uc_mcontext.gregs[I386_ERR] = 0x0a|(int_n<<3); + sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 13; } - } else if(info->si_errno==0xcafe) { + } else if(info->si_errno==0xcafe) { //divide by 0 info2->si_errno = 0; + sigcontext->uc_mcontext.gregs[I386_ERR] = 0; sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 0; info2->si_signo = SIGFPE; } @@ -635,15 +696,20 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 4; else sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 19; - } else if(sig==SIGILL) + } else if(sig==SIGILL) { + info2->si_code = 2; sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 6; - else if(sig==SIGTRAP) { - info2->si_code = 128; + } else if(sig==SIGTRAP) { + if(info->si_code==1) { //single step + info2->si_code = 2; + info2->_sifields._sigfault.__si_addr = sigcontext->uc_mcontext.gregs[I386_EIP]; + } else + info2->si_code = 128; sigcontext->uc_mcontext.gregs[I386_TRAPNO] = info->si_code; sigcontext->uc_mcontext.gregs[I386_ERR] = 0; } //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, mmaped:%d\n", sig, (void*)info2->si_addr, sigcontext->uc_mcontext.gregs[I386_TRAPNO], sigcontext->uc_mcontext.gregs[I386_ERR],from_ptrv(sigcontext->uc_mcontext.gregs[I386_EIP]), prot, mmapped); + printf_log((sig==10)?LOG_DEBUG:log_minimum, "Signal32 %d: si_addr=%p, TRAPNO=%d, ERR=%d, RIP=%p, prot:%x, mmaped:%d\n", sig, from_ptrv(info2->_sifields._sigfault.__si_addr), sigcontext->uc_mcontext.gregs[I386_TRAPNO], sigcontext->uc_mcontext.gregs[I386_ERR],from_ptrv(sigcontext->uc_mcontext.gregs[I386_EIP]), prot, mmapped); // call the signal handler i386_ucontext_t sigcontext_copy = *sigcontext; // save old value from emu diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 4dcabee3..820ed1d3 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1161,14 +1161,16 @@ void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo //bad opcode sigcontext->uc_mcontext.gregs[X64_ERR] = 0; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 13; + info2->si_code = 128; info2->si_errno = 0; + info2->si_addr = NULL; } else if (info->si_errno==0xecec) { // no excute bit on segment - sigcontext->uc_mcontext.gregs[X64_ERR] = 16;//(real_prot&PROT_READ)?16:1; // EXECUTE_FAULT & READ_FAULT + sigcontext->uc_mcontext.gregs[X64_ERR] = (real_prot&PROT_READ)?16:1; // EXECUTE_FAULT & READ_FAULT sigcontext->uc_mcontext.gregs[X64_TRAPNO] = mmapped?14:13; info2->si_errno = 0; }else { - sigcontext->uc_mcontext.gregs[X64_ERR] = mmapped?16:1;//(real_prot&PROT_READ)?16:1;//(info->si_errno==0x1234)?0:((info->si_errno==0xdead)?(0x2|(info->si_code<<3)):0x0010); // execution flag issue (probably), unless it's a #GP(0) + sigcontext->uc_mcontext.gregs[X64_ERR] = (real_prot&PROT_READ)?16:1;//(info->si_errno==0x1234)?0:((info->si_errno==0xdead)?(0x2|(info->si_code<<3)):0x0010); // execution flag issue (probably), unless it's a #GP(0) sigcontext->uc_mcontext.gregs[X64_TRAPNO] = mmapped?14:13; //sigcontext->uc_mcontext.gregs[X64_TRAPNO] = ((info->si_code==SEGV_ACCERR) || (info->si_errno==0x1234) || (info->si_errno==0xdead) || ((uintptr_t)info->si_addr==0))?13:14; } @@ -1179,7 +1181,7 @@ void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo if((info->si_code!=SEGV_ACCERR) && labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16) sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 12; // stack overflow probably else - sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?14:13; + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = mmapped?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] = 0x0001; // read error? } @@ -1191,7 +1193,7 @@ void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo // INT x uint8_t int_n = info->si_code; info2->si_errno = 0; - info2->si_code = info->si_code; + info2->si_code = 128; info2->si_addr = NULL; // some special cases... if(int_n==3) { @@ -1205,9 +1207,11 @@ void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo sigcontext->uc_mcontext.gregs[X64_ERR] = 0x02|(int_n<<3); } else { sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0a|(int_n<<3); + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 13; } - } else if(info->si_errno==0xcafe) { + } else if(info->si_errno==0xcafe) { // divide by 0 info2->si_errno = 0; + sigcontext->uc_mcontext.gregs[X64_ERR] = 0; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 0; info2->si_signo = SIGFPE; } @@ -1216,10 +1220,15 @@ void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 4; else sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 19; - } else if(sig==SIGILL) + } else if(sig==SIGILL) { + info2->si_code = 2; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 6; - else if(sig==SIGTRAP) { - info2->si_code = 128; + } else if(sig==SIGTRAP) { + if(info->si_code==1) { //single step + info2->si_code = 2; + info2->si_addr = (void*)sigcontext->uc_mcontext.gregs[X64_RIP]; + } else + info2->si_code = 128; sigcontext->uc_mcontext.gregs[X64_TRAPNO] = info->si_code; sigcontext->uc_mcontext.gregs[X64_ERR] = 0; }