about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-02-17 17:56:33 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-02-17 17:56:33 +0100
commit2200c4af6b38c771c7d44f8cbf606809915ae1d8 (patch)
tree53b2590d323869e8542787e79c8bae50f7c18c91 /src
parent838dfa453c4e1596ef3a9b60aed05a7cc34bee8e (diff)
downloadbox64-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-xsrc/emu/x64emu.c5
-rwxr-xr-xsrc/libtools/signals.c205
-rwxr-xr-xsrc/libtools/threads.c9
-rw-r--r--src/mallochook.c1
-rwxr-xr-xsrc/tools/box64stack.c5
-rwxr-xr-xsrc/wrapped/wrappedlibc.c64
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;