about summary refs log tree commit diff stats
path: root/src/libtools
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-29 18:36:33 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-03-29 18:36:33 +0200
commitd535bf35a844114e91d8a30b58c9225455a6fbf4 (patch)
tree338cf61e4ba77b0a1a0775222a918838ff91d758 /src/libtools
parent17d73a93f107666eca3831f04e73b51b29863a70 (diff)
downloadbox64-d535bf35a844114e91d8a30b58c9225455a6fbf4.tar.gz
box64-d535bf35a844114e91d8a30b58c9225455a6fbf4.zip
Removed x64emu_t structure dedicated to signal handling, using main thread one now
Diffstat (limited to 'src/libtools')
-rwxr-xr-xsrc/libtools/signals.c124
1 files changed, 66 insertions, 58 deletions
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 87373e80..aba21bc8 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -257,12 +257,6 @@ static void sigstack_destroy(void* p)
     free(ss);
 }
 
-static void free_signal_emu(void* p)
-{
-    if(p)
-        FreeX64Emu((x64emu_t**)&p);
-}
-
 static pthread_key_t sigstack_key;
 static pthread_once_t sigstack_key_once = PTHREAD_ONCE_INIT;
 
@@ -270,27 +264,6 @@ static void sigstack_key_alloc() {
 	pthread_key_create(&sigstack_key, sigstack_destroy);
 }
 
-static pthread_key_t sigemu_key;
-static pthread_once_t sigemu_key_once = PTHREAD_ONCE_INIT;
-
-static void sigemu_key_alloc() {
-	pthread_key_create(&sigemu_key, free_signal_emu);
-}
-
-static x64emu_t* get_signal_emu()
-{
-    x64emu_t *emu = (x64emu_t*)pthread_getspecific(sigemu_key);
-    if(!emu) {
-        const int stsize = 8*1024;  // small stack for signal handler
-        void* stack = mmap(NULL, stsize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
-        emu = NewX64Emu(my_context, 0, (uintptr_t)stack, stsize, 1);
-        emu->type = EMUTYPE_SIGNAL;
-        pthread_setspecific(sigemu_key, emu);
-    }
-    return emu;
-}
-
-
 uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
 {
     if(fnc==0 || fnc==1) {
@@ -298,16 +271,11 @@ uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
         return 0;
     }
     uintptr_t old_start = trace_start, old_end = trace_end;
-//    trace_start = 0; trace_end = 1; // disabling trace, globably for now...
+    //trace_start = 0; trace_end = 1; // disabling trace, globably for now...
 
-    x64emu_t *emu = get_signal_emu();
-    x64emu_t *thread_emu = thread_get_emu();
-    x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
-    if(!new_ss) {
-        // no alternate stack, so signal RSP needs to match thread RSP!
-        R_RSP = thread_emu->regs[_SP].q[0];
-    }
-    printf_log(LOG_DEBUG, "%04d|signal function handler %p  (%s alternate stack) called, RSP=%p\n", GetTID(), (void*)fnc, new_ss?"with":"without", (void*)R_RSP);
+    x64emu_t *emu = thread_get_emu();
+
+    printf_log(LOG_DEBUG, "%04d|signal function handler %p called, RSP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP);
     
     /*SetFS(emu, default_fs);*/
     for (int i=0; i<6; ++i)
@@ -351,13 +319,12 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
         errno = EFAULT;
         return -1;
     }
-    x64emu_t *sigemu = get_signal_emu();
 	x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
     if(!ss) {
         if(!new_ss) {
             oss->ss_flags = SS_DISABLE;
-            oss->ss_sp = sigemu->init_stack;
-            oss->ss_size = sigemu->size_stack;
+            oss->ss_sp = emu->init_stack;
+            oss->ss_size = emu->size_stack;
         } else {
             oss->ss_flags = new_ss->ss_flags;
             oss->ss_sp = new_ss->ss_sp;
@@ -376,15 +343,14 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
             free(new_ss);
         pthread_setspecific(sigstack_key, NULL);
 
-        sigemu->regs[_SP].dword[0] = ((uintptr_t)sigemu->init_stack + sigemu->size_stack) & ~7;
-        
         return 0;
     }
+
     if(oss) {
         if(!new_ss) {
             oss->ss_flags = SS_DISABLE;
-            oss->ss_sp = sigemu->init_stack;
-            oss->ss_size = sigemu->size_stack;
+            oss->ss_sp = emu->init_stack;
+            oss->ss_size = emu->size_stack;
         } else {
             oss->ss_flags = new_ss->ss_flags;
             oss->ss_sp = new_ss->ss_sp;
@@ -398,8 +364,6 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
 
 	pthread_setspecific(sigstack_key, new_ss);
 
-    sigemu->regs[_SP].dword[0] = ((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f;
-
     return 0;
 }
 
@@ -408,11 +372,31 @@ void my_sighandler(int32_t sig)
 {
     pthread_mutex_unlock(&my_context->mutex_trace);   // just in case
     printf_log(LOG_DEBUG, "Sighanlder for signal #%d called (jump to %p)\n", sig, (void*)my_context->signals[sig]);
+    // save values
+    x64emu_t *emu = thread_get_emu();
     uintptr_t restorer = my_context->restorer[sig];
+    uintptr_t old_regs[16] = {0};
+    uintptr_t old_ip = emu->ip.q[0];
+    uint64_t old_flags = emu->eflags.x64;
+    for(int i=0; i<16; ++i)
+        old_regs[i] = emu->regs[i].q[0];
+
+    x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
+    if(new_ss) {
+        // no alternate stack, so signal RSP needs to match thread RSP!
+        R_RSP = (uintptr_t)(new_ss->ss_sp+new_ss->ss_size-32);
+    }
+
     int exits = 0;
     int ret = RunFunctionHandler(&exits, my_context->signals[sig], 1, sig);
+    // restore regs
+    emu->ip.q[0] = old_ip;
+    emu->eflags.x64 = old_flags;
+    for(int i=0; i<16; ++i)
+        emu->regs[i].q[0] = old_regs[i];
     if(exits)
         exit(ret);
+    // what about the restored regs?
     if(restorer)
         RunFunctionHandler(&exits, restorer, 0);
 }
@@ -461,12 +445,11 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
     }
 #endif
     // stack tracking
-    x64emu_t *sigemu = get_signal_emu();
 	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!
-            frame = (uintptr_t*)sigemu->regs[_SP].q[0];
+            frame = (uintptr_t*)emu->regs[_SP].q[0];
         } else {
             frame = (uintptr_t*)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
             used_stack = 1;
@@ -529,11 +512,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
     //((unsigned int *)(&sigcontext.xstate.fpstate.padding))[8*4+12] = 0x46505853;  // not yet, when XSAVE / XRSTR will be ready
     // get signal mask
 
-    if(!new_ss) {
-        sigcontext->uc_stack.ss_sp = sigemu->init_stack;
-        sigcontext->uc_stack.ss_size = sigemu->size_stack;
-        sigcontext->uc_stack.ss_flags = SS_DISABLE;
-    } else {
+    if(new_ss) {
         sigcontext->uc_stack.ss_sp = new_ss->ss_sp;
         sigcontext->uc_stack.ss_size = new_ss->ss_size;
         sigcontext->uc_stack.ss_flags = new_ss->ss_flags;
@@ -588,10 +567,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
     x64_ucontext_t sigcontext_copy = *sigcontext;
 
     // set stack pointer
-    sigemu->regs[_SP].dword[0] = (uintptr_t)frame;
-
-    // set segments
-    memcpy(sigemu->segs, emu->segs, sizeof(sigemu->segs));
+    emu->regs[_SP].dword[0] = (uintptr_t)frame;
 
     int exits = 0;
     int ret = RunFunctionHandler(&exits, my_context->signals[sig], 3, sig, info, sigcontext);
@@ -642,11 +618,44 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
         }
         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].dword[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].dword[0]=sigcontext->uc_mcontext.gregs[X64_##R]
+    GO(R8);
+    GO(R9);
+    GO(R10);
+    GO(R11);
+    GO(R12);
+    GO(R13);
+    GO(R14);
+    GO(R15);
+    #undef GO
+    emu->ip.dword[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;
+    #define GO(S) emu->segs[_##S]=seg; emu->segs_serial[_##S] = 0;
+    GO(CS);
+    seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 16)&0xffff;
+    GO(GS);
+    seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff;
+    GO(FS);
+    #undef GO
+
     printf_log(LOG_DEBUG, "Sigactionhanlder main function returned (exit=%d, restorer=%p)\n", exits, (void*)restorer);
     if(exits)
         exit(ret);
     if(restorer)
-        RunFunctionHandler(&exits, restorer, 0);
+        RunFunctionHandler(&exits, 0, restorer, 0);
     if(used_stack)  // release stack
         new_ss->ss_flags = 0;
 }
@@ -1176,7 +1185,6 @@ void init_signal_helper(box64context_t* context)
     sigaction(SIGILL, &action, NULL);
 
 	pthread_once(&sigstack_key_once, sigstack_key_alloc);
-	pthread_once(&sigemu_key_once, sigemu_key_alloc);
 }
 
 void fini_signal_helper()