Skip to content

Commit

Permalink
Added signal mask handling in setjmp/longjmp functions
Browse files Browse the repository at this point in the history
  • Loading branch information
ptitSeb committed May 18, 2021
1 parent 490a4ab commit bf046a6
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 12 deletions.
8 changes: 4 additions & 4 deletions src/dynarec/dynarec.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
int a;
if((a=setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))) {
if((a=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaCall %d, fs=0x%x\n", a, ejb->emu->segs[_FS]);
addr = R_EIP; // not sure if it should still be inside DynaCall!
if(a==2)
Expand Down Expand Up @@ -129,7 +129,7 @@ void DynaCall(x86emu_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_EIP;
}
Expand Down Expand Up @@ -171,7 +171,7 @@ int DynaRun(x86emu_t* emu)
#ifdef DYNAREC
jmpbuf_reset = 1;
#endif
if((a=setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))) {
if((a=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaRun %d, fs=0x%x\n", a, ejb->emu->segs[_FS]);
if(a==2)
Run(emu, 1); // "single step" next instruction that is doing auto-smc
Expand Down Expand Up @@ -212,7 +212,7 @@ int DynaRun(x86emu_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]);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/libtools/signals.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,13 +570,13 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
GO(CS);
GO(SS);
#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[REG_EIP]!=sigcontext_copy.uc_mcontext.gregs[REG_EIP])?" (EIP changed)":"");
}
Expand Down Expand Up @@ -661,7 +661,7 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
ejb->emu->eflags.x32 = p->uc_mcontext.arm_ip;
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->x86_addr);
}
Expand Down
28 changes: 23 additions & 5 deletions src/wrapped/wrappedlibc.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,9 +650,9 @@ EXPORT void my__longjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p,
EXPORT void my_siglongjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val) __attribute__((alias("my_longjmp")));
EXPORT void my___longjmp_chk(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val) __attribute__((alias("my_longjmp")));

EXPORT int32_t my_setjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p);
EXPORT int32_t my__setjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp")));
EXPORT int32_t my___sigsetjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp")));
//EXPORT int32_t my_setjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p);
//EXPORT int32_t my__setjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp")));
//EXPORT int32_t my___sigsetjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp")));
#if 0
EXPORT void my_exit(x86emu_t *emu, int32_t status)
{
Expand Down Expand Up @@ -2353,13 +2353,16 @@ void EXPORT my_longjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p,
// jmp to saved location, plus restore val to eax
R_EAX = __val;
R_EIP = jpbuff->save_eip;
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(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p)
EXPORT int32_t my___sigsetjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int savesigs)
{
jump_buff_i386_t *jpbuff = &((__jmp_buf_tag_t*)p)->__jmpbuf;
// save the buffer
Expand All @@ -2369,10 +2372,25 @@ EXPORT int32_t my_setjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p
jpbuff->save_ebp = R_EBP;
jpbuff->save_esp = R_ESP+4; // include "return address"
jpbuff->save_eip = *(uint32_t*)(R_ESP);
// 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(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p)
{
return my___sigsetjmp(emu, p, 0);
}
EXPORT int32_t my_setjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p)
{
return my___sigsetjmp(emu, p, 1);
}

EXPORT void my___explicit_bzero_chk(x86emu_t* emu, void* dst, uint32_t len, uint32_t dstlen)
{
memset(dst, 0, len);
Expand Down

0 comments on commit bf046a6

Please sign in to comment.