diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-05-18 11:13:18 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-05-18 11:13:18 +0200 |
| commit | e35b25015bc457428cc27b5bfeec5c16a4dd9b22 (patch) | |
| tree | 811ebe98fcd88b2edb21c94c65d8dd4309cbd103 /src | |
| parent | 422844f84260b34d1f5da8aa99ff0d2d5247bcee (diff) | |
| download | box64-e35b25015bc457428cc27b5bfeec5c16a4dd9b22.tar.gz box64-e35b25015bc457428cc27b5bfeec5c16a4dd9b22.zip | |
Added signal mask handling in setjmp/longjmp functions
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/dynarec.c | 8 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 6 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibc.c | 32 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibc_private.h | 4 |
4 files changed, 34 insertions, 16 deletions
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c index a142f91d..94745bdd 100755 --- a/src/dynarec/dynarec.c +++ b/src/dynarec/dynarec.c @@ -81,7 +81,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr) ejb->emu = emu; ejb->jmpbuf_ok = 1; jmpbuf_reset = 1; - if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) { + if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) { printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]); addr = R_RIP; // not sure if it should still be inside DynaCall! } @@ -130,7 +130,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr) ejb->emu = emu; ejb->jmpbuf_ok = 1; jmpbuf_reset = 1; - if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) { + if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) { printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]); addr = R_RIP; } @@ -171,7 +171,7 @@ int DynaRun(x64emu_t* emu) #ifdef DYNAREC jmpbuf_reset = 1; #endif - if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) + if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]); } } @@ -208,7 +208,7 @@ int DynaRun(x64emu_t* emu) ejb->emu = emu; ejb->jmpbuf_ok = 1; jmpbuf_reset = 1; - if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) + if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]); } } diff --git a/src/libtools/signals.c b/src/libtools/signals.c index fd5f643e..a540f282 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -643,13 +643,13 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff; GO(FS); #undef GO - printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing longjmp to resume emu\n"); + printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu\n"); if(old_code) *old_code = -1; // re-init the value to allow another segfault at the same place if(used_stack) // release stack new_ss->ss_flags = 0; relockMutex(Locks); - longjmp(ejb->jmpbuf, 1); + siglongjmp(ejb->jmpbuf, 1); } 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)":""); } @@ -753,7 +753,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) ejb->emu->eflags.x64 = p->uc_mcontext.regs[26]; dynarec_log(LOG_DEBUG, "Auto-SMC detected, getting out of current Dynablock!\n"); relockMutex(Locks); - longjmp(ejb->jmpbuf, 2); + siglongjmp(ejb->jmpbuf, 2); } dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr); } diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index ced6a6cc..caf22c3c 100755 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -534,9 +534,9 @@ EXPORT void my__longjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, EXPORT void my_siglongjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val) __attribute__((alias("my_longjmp"))); EXPORT void my___longjmp_chk(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val) __attribute__((alias("my_longjmp"))); -EXPORT int32_t my_setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p); -EXPORT int32_t my__setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp"))); -EXPORT int32_t my___sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp"))); +//EXPORT int32_t my_setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p); +//EXPORT int32_t my__setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp"))); +//EXPORT int32_t my___sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp"))); EXPORT int my_printf(x64emu_t *emu, void* fmt, void* b) { myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 1); @@ -1851,16 +1851,19 @@ void EXPORT my_longjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, R_R14 = jpbuff->save_r14; R_R15 = jpbuff->save_r15; R_RSP = jpbuff->save_rsp; - // jmp to saved location, plus restore val to eax - R_EAX = __val; + // jmp to saved location, plus restore val to rax + R_RAX = __val; R_RIP = jpbuff->save_rip; + if(((__jmp_buf_tag_t*)p)->__mask_was_saved) { + sigprocmask(SIG_SETMASK, &((__jmp_buf_tag_t*)p)->__saved_mask, NULL); + } if(emu->quitonlongjmp) { emu->longjmp = 1; emu->quit = 1; } } -EXPORT int32_t my_setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) +EXPORT int32_t my___sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int savesigs) { jump_buff_x64_t *jpbuff = &((__jmp_buf_tag_t*)p)->__jmpbuf; // save the buffer @@ -1872,10 +1875,25 @@ EXPORT int32_t my_setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p jpbuff->save_r15 = R_R15; jpbuff->save_rsp = R_RSP+sizeof(uintptr_t); // include "return address" jpbuff->save_rip = *(uintptr_t*)(R_RSP); - // and that's it.. Nothing more for now + if(savesigs) { + if(sigprocmask(SIG_SETMASK, NULL, &((__jmp_buf_tag_t*)p)->__saved_mask)) + ((__jmp_buf_tag_t*)p)->__mask_was_saved = 0; + else + ((__jmp_buf_tag_t*)p)->__mask_was_saved = 1; + } else + ((__jmp_buf_tag_t*)p)->__mask_was_saved = 0; return 0; } +EXPORT int32_t my__setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) +{ + return my___sigsetjmp(emu, p, 0); +} +EXPORT int32_t my_setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) +{ + return my___sigsetjmp(emu, p, 1); +} + EXPORT void my___explicit_bzero_chk(x64emu_t* emu, void* dst, uint32_t len, uint32_t dstlen) { (void)emu; (void)dstlen; diff --git a/src/wrapped/wrappedlibc_private.h b/src/wrapped/wrappedlibc_private.h index fb26171c..2c8fc470 100755 --- a/src/wrapped/wrappedlibc_private.h +++ b/src/wrapped/wrappedlibc_private.h @@ -1689,7 +1689,7 @@ GO(siggetmask, iFv) //GO(sigisemptyset, //GO(__sigismember, GO(sigismember, iFpi) -//GOW(siglongjmp, +GOM(siglongjmp, iFEpi) GOM(signal, pFEip) //Weak //GO(signalfd, GO(__signbit, iFd) @@ -1704,7 +1704,7 @@ GOW(sigprocmask, iFipp) //GO(sigrelse, //GOW(sigreturn, GOM(sigset, pFEip) -GOM(__sigsetjmp, iFEp) +GOM(__sigsetjmp, iFEpi) //GOW(sigsetmask, //GO(sigstack, GO(__sigsuspend, iFp) |