diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-02-17 17:56:33 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-02-17 17:56:33 +0100 |
| commit | 2200c4af6b38c771c7d44f8cbf606809915ae1d8 (patch) | |
| tree | 53b2590d323869e8542787e79c8bae50f7c18c91 /src | |
| parent | 838dfa453c4e1596ef3a9b60aed05a7cc34bee8e (diff) | |
| download | box64-2200c4af6b38c771c7d44f8cbf606809915ae1d8.tar.gz box64-2200c4af6b38c771c7d44f8cbf606809915ae1d8.zip | |
Various improvment to backtrace, protection tracking, and SHOWBT. Also SIGABRT is tracked like SIGSEGV, SIGILL and SIGBUS
Diffstat (limited to 'src')
| -rwxr-xr-x | src/emu/x64emu.c | 5 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 205 | ||||
| -rwxr-xr-x | src/libtools/threads.c | 9 | ||||
| -rw-r--r-- | src/mallochook.c | 1 | ||||
| -rwxr-xr-x | src/tools/box64stack.c | 5 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibc.c | 64 |
6 files changed, 208 insertions, 81 deletions
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index 2f46472c..9a328bb0 100755 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -31,6 +31,9 @@ #warning Architecture cannot follow SSE Flush to 0 flag #endif +// from src/wrapped/wrappedlibc.c +int my_munmap(x64emu_t* emu, void* addr, unsigned long length); + typedef struct cleanup_s { void* f; int arg; @@ -192,7 +195,7 @@ void CallAllCleanup(x64emu_t *emu) static void internalFreeX64(x64emu_t* emu) { if(emu && emu->stack2free) - munmap(emu->stack2free, emu->size_stack); + my_munmap(NULL, emu->stack2free, emu->size_stack); } EXPORTDYN diff --git a/src/libtools/signals.c b/src/libtools/signals.c index c364ac05..aca02ba9 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -256,7 +256,7 @@ struct kernel_sigaction { static void sigstack_destroy(void* p) { - x64_stack_t *ss = (x64_stack_t*)p; + x64_stack_t *ss = (x64_stack_t*)p; box_free(ss); } @@ -264,7 +264,7 @@ static pthread_key_t sigstack_key; static pthread_once_t sigstack_key_once = PTHREAD_ONCE_INIT; static void sigstack_key_alloc() { - pthread_key_create(&sigstack_key, sigstack_destroy); + pthread_key_create(&sigstack_key, sigstack_destroy); } //1<<8 is mutex_dyndump @@ -373,7 +373,7 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss errno = EFAULT; return -1; } - x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key); + x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key); if(oss) { if(!new_ss) { oss->ss_flags = SS_DISABLE; @@ -408,7 +408,7 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss new_ss->ss_sp = ss->ss_sp; new_ss->ss_size = ss->ss_size; - pthread_setspecific(sigstack_key, new_ss); + pthread_setspecific(sigstack_key, new_ss); return 0; } @@ -441,6 +441,50 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr) } #endif +void copyUCTXreg2Emu(x64emu_t* emu, ucontext_t* p, uintptr_t ip) { +#ifdef ARM64 + emu->regs[_AX].q[0] = p->uc_mcontext.regs[10]; + emu->regs[_CX].q[0] = p->uc_mcontext.regs[11]; + emu->regs[_DX].q[0] = p->uc_mcontext.regs[12]; + emu->regs[_BX].q[0] = p->uc_mcontext.regs[13]; + emu->regs[_SP].q[0] = p->uc_mcontext.regs[14]; + emu->regs[_BP].q[0] = p->uc_mcontext.regs[15]; + emu->regs[_SI].q[0] = p->uc_mcontext.regs[16]; + emu->regs[_DI].q[0] = p->uc_mcontext.regs[17]; + emu->regs[_R8].q[0] = p->uc_mcontext.regs[18]; + emu->regs[_R9].q[0] = p->uc_mcontext.regs[19]; + emu->regs[_R10].q[0] = p->uc_mcontext.regs[20]; + emu->regs[_R11].q[0] = p->uc_mcontext.regs[21]; + emu->regs[_R12].q[0] = p->uc_mcontext.regs[22]; + emu->regs[_R13].q[0] = p->uc_mcontext.regs[23]; + emu->regs[_R14].q[0] = p->uc_mcontext.regs[24]; + emu->regs[_R15].q[0] = p->uc_mcontext.regs[25]; + emu->ip.q[0] = ip; + emu->eflags.x64 = p->uc_mcontext.regs[26]; +#elif defined(LA464) + emu->regs[_AX].q[0] = p->uc_mcontext.__gregs[12]; + emu->regs[_CX].q[0] = p->uc_mcontext.__gregs[13]; + emu->regs[_DX].q[0] = p->uc_mcontext.__gregs[14]; + emu->regs[_BX].q[0] = p->uc_mcontext.__gregs[15]; + emu->regs[_SP].q[0] = p->uc_mcontext.__gregs[16]; + emu->regs[_BP].q[0] = p->uc_mcontext.__gregs[17]; + emu->regs[_SI].q[0] = p->uc_mcontext.__gregs[18]; + emu->regs[_DI].q[0] = p->uc_mcontext.__gregs[19]; + emu->regs[_R8].q[0] = p->uc_mcontext.__gregs[23]; + emu->regs[_R9].q[0] = p->uc_mcontext.__gregs[24]; + emu->regs[_R10].q[0] = p->uc_mcontext.__gregs[25]; + emu->regs[_R11].q[0] = p->uc_mcontext.__gregs[26]; + emu->regs[_R12].q[0] = p->uc_mcontext.__gregs[27]; + emu->regs[_R13].q[0] = p->uc_mcontext.__gregs[28]; + emu->regs[_R14].q[0] = p->uc_mcontext.__gregs[29]; + emu->regs[_R15].q[0] = p->uc_mcontext.__gregs[30]; + emu->ip.q[0] = ip; + emu->eflags.x64 = p->uc_mcontext.__gregs[31]; +#else +#error Unsupported architecture +#endif +} + void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db) { int Locks = unlockMutex(); @@ -473,7 +517,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void (void)ucntx; (void)cur_db; #endif // stack tracking - x64_stack_t *new_ss = my_context->onstack[sig]?(x64_stack_t*)pthread_getspecific(sigstack_key):NULL; + x64_stack_t *new_ss = my_context->onstack[sig]?(x64_stack_t*)pthread_getspecific(sigstack_key):NULL; int used_stack = 0; if(new_ss) { if(new_ss->ss_flags == SS_ONSTACK) { // already using it! @@ -621,6 +665,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 19; else if(sig==SIGILL) sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 6; + //TODO: SIGABRT generate what? // call the signal handler x64_ucontext_t sigcontext_copy = *sigcontext; // save old value from emu @@ -711,17 +756,15 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void 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)":""); } // restore regs... - #define GO(R) emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_R##R] - GO(AX); - GO(CX); - GO(DX); - GO(DI); - GO(SI); - GO(BP); - GO(SP); - GO(BX); - #undef GO - #define GO(R) emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_##R] + #define GO(R) R_##R=sigcontext->uc_mcontext.gregs[X64_##R] + GO(RAX); + GO(RCX); + GO(RDX); + GO(RDI); + GO(RSI); + GO(RBP); + GO(RSP); + GO(RBX); GO(R8); GO(R9); GO(R10); @@ -730,8 +773,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void GO(R13); GO(R14); GO(R15); + GO(RIP); #undef GO - emu->ip.q[0]=sigcontext->uc_mcontext.gregs[X64_RIP]; emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL]; uint16_t seg; seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff; @@ -766,7 +809,7 @@ extern int box64_quit; void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) { - // sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here! + // sig==SIGSEGV || sig==SIGBUS || sig==SIGILL || sig==SIGABRT here! int log_minimum = (box64_showsegv)?LOG_NONE:((my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_DEBUG:LOG_INFO); if((sig==SIGSEGV || sig==SIGBUS) && box64_quit) { printf_log(LOG_INFO, "Sigfault/Segbus while quitting, exiting silently\n"); @@ -832,56 +875,21 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) // dynablock got auto-dirty! need to get out of it!!! emu_jmpbuf_t* ejb = GetJmpBuf(); if(ejb->jmpbuf_ok) { + copyUCTXreg2Emu(ejb->emu, p, getX64Address(db, (uintptr_t)pc)); #ifdef ARM64 - ejb->emu->regs[_AX].q[0] = p->uc_mcontext.regs[10]; - ejb->emu->regs[_CX].q[0] = p->uc_mcontext.regs[11]; - ejb->emu->regs[_DX].q[0] = p->uc_mcontext.regs[12]; - ejb->emu->regs[_BX].q[0] = p->uc_mcontext.regs[13]; - ejb->emu->regs[_SP].q[0] = p->uc_mcontext.regs[14]; - ejb->emu->regs[_BP].q[0] = p->uc_mcontext.regs[15]; - ejb->emu->regs[_SI].q[0] = p->uc_mcontext.regs[16]; - ejb->emu->regs[_DI].q[0] = p->uc_mcontext.regs[17]; - ejb->emu->regs[_R8].q[0] = p->uc_mcontext.regs[18]; - ejb->emu->regs[_R9].q[0] = p->uc_mcontext.regs[19]; - ejb->emu->regs[_R10].q[0] = p->uc_mcontext.regs[20]; - ejb->emu->regs[_R11].q[0] = p->uc_mcontext.regs[21]; - ejb->emu->regs[_R12].q[0] = p->uc_mcontext.regs[22]; - ejb->emu->regs[_R13].q[0] = p->uc_mcontext.regs[23]; - ejb->emu->regs[_R14].q[0] = p->uc_mcontext.regs[24]; - ejb->emu->regs[_R15].q[0] = p->uc_mcontext.regs[25]; if(fpsimd) { ejb->emu->xmm[0].u128 = fpsimd->vregs[0]; ejb->emu->xmm[1].u128 = fpsimd->vregs[1]; ejb->emu->xmm[2].u128 = fpsimd->vregs[2]; ejb->emu->xmm[3].u128 = fpsimd->vregs[3]; } - ejb->emu->ip.q[0] = getX64Address(db, (uintptr_t)pc); - ejb->emu->eflags.x64 = p->uc_mcontext.regs[26]; #elif defined(LA464) - ejb->emu->regs[_AX].q[0] = p->uc_mcontext.__gregs[12]; - ejb->emu->regs[_CX].q[0] = p->uc_mcontext.__gregs[13]; - ejb->emu->regs[_DX].q[0] = p->uc_mcontext.__gregs[14]; - ejb->emu->regs[_BX].q[0] = p->uc_mcontext.__gregs[15]; - ejb->emu->regs[_SP].q[0] = p->uc_mcontext.__gregs[16]; - ejb->emu->regs[_BP].q[0] = p->uc_mcontext.__gregs[17]; - ejb->emu->regs[_SI].q[0] = p->uc_mcontext.__gregs[18]; - ejb->emu->regs[_DI].q[0] = p->uc_mcontext.__gregs[19]; - ejb->emu->regs[_R8].q[0] = p->uc_mcontext.__gregs[23]; - ejb->emu->regs[_R9].q[0] = p->uc_mcontext.__gregs[24]; - ejb->emu->regs[_R10].q[0] = p->uc_mcontext.__gregs[25]; - ejb->emu->regs[_R11].q[0] = p->uc_mcontext.__gregs[26]; - ejb->emu->regs[_R12].q[0] = p->uc_mcontext.__gregs[27]; - ejb->emu->regs[_R13].q[0] = p->uc_mcontext.__gregs[28]; - ejb->emu->regs[_R14].q[0] = p->uc_mcontext.__gregs[29]; - ejb->emu->regs[_R15].q[0] = p->uc_mcontext.__gregs[30]; /*if(fpsimd) { ejb->emu->xmm[0].u128 = fpsimd->vregs[0]; ejb->emu->xmm[1].u128 = fpsimd->vregs[1]; ejb->emu->xmm[2].u128 = fpsimd->vregs[2]; ejb->emu->xmm[3].u128 = fpsimd->vregs[3]; }*/ - ejb->emu->ip.q[0] = getX64Address(db, (uintptr_t)pc); - ejb->emu->eflags.x64 = p->uc_mcontext.__gregs[31]; #else #error Unsupported architecture #endif @@ -966,7 +974,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for static void* old_pc = 0; static void* old_addr = 0; static int old_tid = 0; - const char* signame = (sig==SIGSEGV)?"SIGSEGV":((sig==SIGBUS)?"SIGBUS":"SIGILL"); + const char* signame = (sig==SIGSEGV)?"SIGSEGV":((sig==SIGBUS)?"SIGBUS":((sig==SIGILL)?"SIGILL":"SIGABRT")); if(old_code==info->si_code && old_pc==pc && old_addr==addr && old_tid==GetTID()) { printf_log(log_minimum, "%04d|Double %s (code=%d, pc=%p, addr=%p)!\n", GetTID(), signame, old_code, old_pc, old_addr); exit(-1); @@ -1061,9 +1069,33 @@ exit(-1); free(strings); } else printf_log(log_minimum, "NativeBT: none (%d/%s)\n", errno, strerror(errno)); - extern int my_backtrace(x64emu_t* emu, void** buffer, int size); // in wrappedlibc + extern int my_backtrace_ip(x64emu_t* emu, void** buffer, int size); // in wrappedlibc extern char** my_backtrace_symbols(x64emu_t* emu, uintptr_t* buffer, int size); - nptrs = my_backtrace(emu, buffer, BT_BUF_SIZE); + // save and set real RIP/RSP + #define GO(A) uintptr_t old_##A = R_##A; + GO(RAX); + GO(RBX); + GO(RCX); + GO(RDX); + GO(RBP); + GO(RSP); + GO(RDI); + GO(RSI); + GO(R8); + GO(R9); + GO(R10); + GO(R11); + GO(R12); + GO(R13); + GO(R14); + GO(R15); + GO(RIP); + #undef GO + #ifdef DYNAREC + if(db) + copyUCTXreg2Emu(emu, p, x64pc); + #endif + nptrs = my_backtrace_ip(emu, buffer, BT_BUF_SIZE); strings = my_backtrace_symbols(emu, (uintptr_t*)buffer, nptrs); if(strings) { for (int j = 0; j < nptrs; j++) @@ -1071,7 +1103,28 @@ exit(-1); free(strings); } else printf_log(log_minimum, "EmulatedBT: none\n"); + #define GO(A) R_##A = old_##A + GO(RAX); + GO(RBX); + GO(RCX); + GO(RDX); + GO(RBP); + GO(RSP); + GO(RDI); + GO(RSI); + GO(R8); + GO(R9); + GO(R10); + GO(R11); + GO(R12); + GO(R13); + GO(R14); + GO(R15); + GO(RIP); + #undef GO } + static const char* reg_name[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", " R8", " R9","R10","R11", "R12","R13","R14","R15"}; + int shown_regs = 0; #ifdef DYNAREC uint32_t hash = 0; if(db) @@ -1086,12 +1139,13 @@ exit(-1); (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash, (void*)my_context->signals[sig]); #if defined(ARM64) - static const char* reg_name[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", " R8", " R9","R10","R11", "R12","R13","R14","R15"}; - if(db) + if(db) { + shown_regs = 1; for (int i=0; i<16; ++i) { if(!(i%4)) printf_log(log_minimum, "\n"); printf_log(log_minimum, "%s:0x%016llx ", reg_name[i], p->uc_mcontext.regs[10+i]); } + } if(rsp!=addr) for (int i=-4; i<4; ++i) { printf_log(log_minimum, "%sRSP%c0x%02x:0x%016lx", (i%4)?" ":"\n", i<0?'-':'+', abs(i)*8, *(uintptr_t*)(rsp+i*8)); @@ -1102,6 +1156,11 @@ exit(-1); #else printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code); #endif + if(!shown_regs) + for (int i=0; i<16; ++i) { + if(!(i%4)) printf_log(log_minimum, "\n"); + printf_log(log_minimum, "%s:0x%016llx ", reg_name[i], emu->regs[i].q[0]); + } if(sig==SIGILL) printf_log(log_minimum, " opcode=%02X %02X %02X %02X %02X %02X %02X %02X (%02X %02X %02X %02X %02X)\n", ((uint8_t*)pc)[0], ((uint8_t*)pc)[1], ((uint8_t*)pc)[2], ((uint8_t*)pc)[3], ((uint8_t*)pc)[4], ((uint8_t*)pc)[5], ((uint8_t*)pc)[6], ((uint8_t*)pc)[7], ((uint8_t*)x64pc)[0], ((uint8_t*)x64pc)[1], ((uint8_t*)x64pc)[2], ((uint8_t*)x64pc)[3], ((uint8_t*)x64pc)[4]); else if(sig==SIGBUS) @@ -1116,7 +1175,7 @@ exit(-1); } // no handler (or double identical segfault) // set default and that's it, instruction will restart and default segfault handler will be called... - if(my_context->signals[sig]!=1 || sig==SIGSEGV || sig==SIGILL || sig==SIGFPE) { + if(my_context->signals[sig]!=1 || sig==SIGSEGV || sig==SIGILL || sig==SIGFPE || sig==SIGABRT) { signal(sig, (void*)my_context->signals[sig]); } } @@ -1174,7 +1233,7 @@ EXPORT sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler) my_context->restorer[signum] = 0; my_context->onstack[signum] = 0; - if(signum==SIGSEGV || signum==SIGBUS || signum==SIGILL) + if(signum==SIGSEGV || signum==SIGBUS || signum==SIGILL || signum==SIGABRT) return 0; if(handler!=NULL && handler!=(sighandler_t)1) { @@ -1227,7 +1286,7 @@ int EXPORT my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x my_context->onstack[signum] = (act->sa_flags&SA_ONSTACK)?1:0; } int ret = 0; - if(signum!=SIGSEGV && signum!=SIGBUS && signum!=SIGILL) + if(signum!=SIGSEGV && signum!=SIGBUS && signum!=SIGILL && signum!=SIGABRT) ret = sigaction(signum, act?&newact:NULL, oldact?&old:NULL); if(oldact) { oldact->sa_flags = old.sa_flags; @@ -1332,7 +1391,7 @@ int EXPORT my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigactio } int ret = 0; - if(signum!=SIGSEGV && signum!=SIGBUS && signum!=SIGILL) + if(signum!=SIGSEGV && signum!=SIGBUS && signum!=SIGILL && signum!=SIGABRT) ret = sigaction(signum, act?&newact:NULL, oldact?&old:NULL); if(oldact && ret==0) { oldact->sa_flags = old.sa_flags; @@ -1507,18 +1566,21 @@ void init_signal_helper(box64context_t* context) for(int i=0; i<MAX_SIGNAL; ++i) { context->signals[i] = 0; // SIG_DFL } - struct sigaction action = {0}; - action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; - action.sa_sigaction = my_box64signalhandler; + struct sigaction action = {0}; + action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; + action.sa_sigaction = my_box64signalhandler; sigaction(SIGSEGV, &action, NULL); - action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; - action.sa_sigaction = my_box64signalhandler; + action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; + action.sa_sigaction = my_box64signalhandler; sigaction(SIGBUS, &action, NULL); - action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; - action.sa_sigaction = my_box64signalhandler; + action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; + action.sa_sigaction = my_box64signalhandler; sigaction(SIGILL, &action, NULL); + action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; + action.sa_sigaction = my_box64signalhandler; + sigaction(SIGABRT, &action, NULL); - pthread_once(&sigstack_key_once, sigstack_key_alloc); + pthread_once(&sigstack_key_once, sigstack_key_alloc); #ifdef DYNAREC atfork_child_dynarec_prot(); pthread_atfork(NULL, NULL, atfork_child_dynarec_prot); @@ -1530,4 +1592,5 @@ void fini_signal_helper() signal(SIGSEGV, SIG_DFL); signal(SIGBUS, SIG_DFL); signal(SIGILL, SIG_DFL); + signal(SIGABRT, SIG_DFL); } diff --git a/src/libtools/threads.c b/src/libtools/threads.c index 711db947..0d15debf 100755 --- a/src/libtools/threads.c +++ b/src/libtools/threads.c @@ -46,6 +46,9 @@ void _pthread_cleanup_pop(void* buffer, int exec); // it will be pthread_kill@GLIBC_2.17 on aarch64, but it's GLIBC_2.2.5 on x86_64 static iFli_t real_phtread_kill_old = NULL; +// from src/wrapped/wrappedlibc.c +void* my_mmap(x64emu_t* emu, void* addr, unsigned long length, int prot, int flags, int fd, int64_t offset); + typedef struct threadstack_s { void* stack; size_t stacksize; @@ -210,7 +213,7 @@ x64emu_t* thread_get_emu() stacksize = stack_size; pthread_attr_destroy(&attr); } - void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); + void* stack = my_mmap(NULL, NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); x64emu_t *emu = NewX64Emu(my_context, 0, (uintptr_t)stack, stacksize, 1); SetupX64Emu(emu); thread_set_emu(emu); @@ -481,7 +484,7 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou stacksize = attr_stacksize; own = 0; } else { - stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); + stack = my_mmap(NULL, NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); own = 1; } @@ -506,7 +509,7 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet) { int stacksize = (ssize)?ssize:(2*1024*1024); //default stack size is 2Mo - void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); + void* stack = my_mmap(NULL, NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); emuthread_t *et = (emuthread_t*)box_calloc(1, sizeof(emuthread_t)); x64emu_t *emuthread = NewX64Emu(emu->context, (uintptr_t)f, (uintptr_t)stack, stacksize, 1); SetupX64Emu(emuthread); diff --git a/src/mallochook.c b/src/mallochook.c index 4faa8c08..33141f49 100644 --- a/src/mallochook.c +++ b/src/mallochook.c @@ -228,6 +228,7 @@ EXPORT void* pvalloc(size_t size) EXPORT void cfree(void* p) { +printf_log(LOG_INFO, "cfree(%p)\n", p); box_free(p); } diff --git a/src/tools/box64stack.c b/src/tools/box64stack.c index 174a2d09..42412e29 100755 --- a/src/tools/box64stack.c +++ b/src/tools/box64stack.c @@ -12,6 +12,9 @@ #include "emu/x64run_private.h" #include "auxval.h" +// from src/wrapped/wrappedlibc.c +void* my_mmap(x64emu_t* emu, void* addr, unsigned long length, int prot, int flags, int fd, int64_t offset); + EXPORTDYN int CalcStackSize(box64context_t *context) { @@ -21,7 +24,7 @@ int CalcStackSize(box64context_t *context) CalcStack(context->elfs[i], &context->stacksz, &context->stackalign); //if (posix_memalign((void**)&context->stack, context->stackalign, context->stacksz)) { - context->stack = mmap(NULL, context->stacksz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); + context->stack = my_mmap(NULL, NULL, context->stacksz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); if (context->stack==(void*)-1) { printf_log(LOG_NONE, "Cannot allocate aligned memory (0x%lx/0x%zx) for stack\n", context->stacksz, context->stackalign); return 1; diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 0dfe617d..4f4c208d 100755 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -2851,11 +2851,11 @@ EXPORT int my_backtrace(x64emu_t* emu, void** buffer, int size) buffer[idx] = (void*)ret_addr; success = 2; // See elfdwarf_private.c for the register mapping - unwind->regs[6] = unwind->regs[7]; // mov rsp, rbp - unwind->regs[7] = *(uint64_t*)unwind->regs[6]; // pop rbp - unwind->regs[6] += 8; - ret_addr = *(uint64_t*)unwind->regs[6]; // ret - unwind->regs[6] += 8; + unwind->regs[7] = unwind->regs[6]; // mov rsp, rbp + unwind->regs[6] = *(uint64_t*)unwind->regs[7]; // pop rbp + unwind->regs[7] += 8; + ret_addr = *(uint64_t*)unwind->regs[7]; // ret + unwind->regs[7] += 8; if (++idx < size) buffer[idx] = (void*)ret_addr; } else if (!success) break; else buffer[idx] = (void*)ret_addr; @@ -2865,6 +2865,60 @@ EXPORT int my_backtrace(x64emu_t* emu, void** buffer, int size) return idx; } +// special version, called in signal with SHOWBT +EXPORT int my_backtrace_ip(x64emu_t* emu, void** buffer, int size) +{ + if (!size) return 0; + dwarf_unwind_t *unwind = init_dwarf_unwind_registers(emu); + int idx = 0; + char success = 1; + uintptr_t addr = R_RIP; + buffer[0] = (void*)addr; + while ((++idx < size) && success) { + uintptr_t ret_addr = get_parent_registers(unwind, FindElfAddress(my_context, addr), addr, &success); + if (ret_addr == (uintptr_t)GetExit()) { + // TODO: do something to be able to get the function name + buffer[idx] = (void*)ret_addr; + success = 2; + // See elfdwarf_private.c for the register mapping + unwind->regs[7] = unwind->regs[6]; // mov rsp, rbp + unwind->regs[6] = *(uint64_t*)unwind->regs[7]; // pop rbp + unwind->regs[7] += 8; + ret_addr = *(uint64_t*)unwind->regs[7]; // ret + unwind->regs[7] += 8; + if (++idx < size) buffer[idx] = (void*)ret_addr; + } else if (!success) { + if(getProtection((uintptr_t)addr)&(PROT_READ)) { + if(getProtection((uintptr_t)addr-19) && *(uint8_t*)(addr-19)==0xCC && *(uint8_t*)(addr-19+1)=='S' && *(uint8_t*)(addr-19+2)=='C') { + buffer[idx-1] = (void*)(addr-19); + success = 2; + if(idx==1) + unwind->regs[7] -= 8; + ret_addr = *(uint64_t*)unwind->regs[7]; // ret + unwind->regs[7] += 8; + buffer[idx] = (void*)ret_addr; + } else { + // try a simple end of function epilog + unwind->regs[7] = unwind->regs[6]; // mov rsp, rbp + if(getProtection(unwind->regs[7])&(PROT_READ)) { + unwind->regs[6] = *(uint64_t*)unwind->regs[7]; // pop rbp + unwind->regs[7] += 8; + ret_addr = *(uint64_t*)unwind->regs[7]; // ret + unwind->regs[7] += 8; + buffer[idx] = (void*)ret_addr; + success = 2; + } else + break; + } + } else + break; + } else buffer[idx] = (void*)ret_addr; + addr = ret_addr; + } + free_dwarf_unwind_registers(&unwind); + return idx; +} + EXPORT char** my_backtrace_symbols(x64emu_t* emu, uintptr_t* buffer, int size) { (void)emu; |