diff options
Diffstat (limited to 'src/libtools')
| -rw-r--r-- | src/libtools/signal32.c | 90 | ||||
| -rw-r--r-- | src/libtools/signals.c | 25 |
2 files changed, 95 insertions, 20 deletions
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; } |