Improved jmpbuff handling a bit

This commit is contained in:
ptitSeb 2023-08-13 12:24:12 +02:00
parent e8972efca1
commit e2077c46ce
7 changed files with 43 additions and 34 deletions

View File

@ -87,9 +87,9 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
DynaRun(emu);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
if(emu->quitonlongjmp==1)
emu->longjmp = 0; // don't change anything because of the longjmp
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
} else {
R_RBX = old_rbx;
R_RDI = old_rdi;
@ -106,10 +106,12 @@ void DynaRun(x64emu_t* emu)
struct __jmp_buf_tag jmpbuf[1] = {0};
int skip = 0;
struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
emu->flags.jmpbuf_ready = 0;
while(!(emu->quit)) {
if(!emu->jmpbuf || (emu->need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
emu->jmpbuf = jmpbuf;
emu->flags.jmpbuf_ready = 1;
if((skip=sigsetjmp(emu->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
#ifdef DYNAREC
@ -121,8 +123,8 @@ void DynaRun(x64emu_t* emu)
#endif
}
}
if(emu->need_jmpbuf)
emu->need_jmpbuf = 0;
if(emu->flags.need_jmpbuf)
emu->flags.need_jmpbuf = 0;
#ifdef DYNAREC
if(!box64_dynarec)
@ -153,7 +155,7 @@ void DynaRun(x64emu_t* emu)
}
}
#endif
if(emu->need_jmpbuf)
if(emu->flags.need_jmpbuf)
emu->quit = 0;
}
// clear the setjmp

View File

@ -567,9 +567,9 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
Run(emu, 0);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
if(emu->quitonlongjmp==1)
emu->longjmp = 0; // don't change anything because of the longjmp
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
} else {
R_RBX = old_rbx;
R_RDI = old_rdi;

View File

@ -36,6 +36,14 @@ typedef struct x64test_s {
uint8_t mem[16];
} x64test_t;
typedef struct emu_flags_s {
uint32_t need_jmpbuf:1; // need a new jmpbuff for signal handling
uint32_t quitonlongjmp:2; // quit if longjmp is called
uint32_t quitonexit:2; // quit if exit/_exit is called
uint32_t longjmp:1; // if quit because of longjmp
uint32_t jmpbuf_ready:1; // the jmpbuf in the emu is ok and don't need refresh
} emu_flags_t;
typedef struct x64emu_s {
// cpu
reg64_t regs[16];
@ -83,12 +91,9 @@ typedef struct x64emu_s {
int quit;
int error;
int fork; // quit because need to fork
int need_jmpbuf; // need a new jmpbuff for signal handling
forkpty_t* forkpty_info;
int exit;
int quitonlongjmp; // quit if longjmp is called
int quitonexit; // quit if exit/_exit is called
int longjmp; // if quit because of longjmp
forkpty_t* forkpty_info;
emu_flags_t flags;
x64test_t test; // used for dynarec testing
#ifdef HAVE_TRACE
sse_regs_t old_xmm[16];

View File

@ -321,8 +321,8 @@ uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext,
printf_log(LOG_DEBUG, "%04d|signal #%d function handler %p called, RSP=%p\n", GetTID(), R_EDI, (void*)fnc, (void*)R_RSP);
int oldquitonlongjmp = emu->quitonlongjmp;
emu->quitonlongjmp = 2;
int oldquitonlongjmp = emu->flags.quitonlongjmp;
emu->flags.quitonlongjmp = 2;
int old_cs = R_CS;
R_CS = 0x33;
@ -333,13 +333,13 @@ uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext,
else
EmuCall(emu, fnc);
if(nargs>6 && !emu->longjmp)
if(nargs>6 && !emu->flags.longjmp)
R_RSP+=((nargs-6)*sizeof(void*));
if(!emu->longjmp && R_CS==0x33)
if(!emu->flags.longjmp && R_CS==0x33)
R_CS = old_cs;
emu->quitonlongjmp = oldquitonlongjmp;
emu->flags.quitonlongjmp = oldquitonlongjmp;
#ifdef DYNAREC
if(box64_dynarec_test)
@ -347,9 +347,9 @@ uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext,
emu->test.clean = 0;
#endif
if(emu->longjmp) {
if(emu->flags.longjmp) {
// longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
emu->longjmp = 0;
emu->flags.longjmp = 0;
if(sigcontext) {
sigcontext->uc_mcontext.gregs[X64_R8] = R_R8;
sigcontext->uc_mcontext.gregs[X64_R9] = R_R9;

View File

@ -233,10 +233,10 @@ uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in
uintptr_t oldip = R_RIP;
int old_quit = emu->quit;
int oldlong = emu->quitonlongjmp;
int oldlong = emu->flags.quitonlongjmp;
emu->quit = 0;
emu->quitonlongjmp = QuitOnLongJump;
emu->flags.quitonlongjmp = QuitOnLongJump;
DynaCall(emu, fnc);
@ -246,7 +246,7 @@ uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in
}
emu->quit = old_quit;
emu->quitonlongjmp = oldlong;
emu->flags.quitonlongjmp = oldlong;
return R_RAX;

View File

@ -2494,8 +2494,8 @@ void EXPORT my_longjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p,
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;
if(emu->flags.quitonlongjmp) {
emu->flags.longjmp = 1;
emu->quit = 1;
}
}
@ -2520,8 +2520,10 @@ EXPORT int32_t my___sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/vo
} else
((__jmp_buf_tag_t*)p)->__mask_was_saved = 0;
// quit emulation loop and create a new jumpbuf if needed
emu->need_jmpbuf = 1;
emu->quit = 1;
if(!emu->flags.jmpbuf_ready) {
emu->flags.need_jmpbuf = 1;
emu->quit = 1;
}
return 0;
}
EXPORT int32_t my_sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int savesigs)
@ -3192,10 +3194,10 @@ static int clone_fn(void* p)
updateGlibcTidCache(); // update cache tid if needed
x64emu_t *emu = arg->emu;
R_RSP = arg->stack;
emu->quitonexit = 1;
emu->flags.quitonexit = 1;
thread_set_emu(emu);
int ret = RunFunctionWithEmu(emu, 0, arg->fnc, 1, arg->args);
int exited = (emu->quitonexit==2);
int exited = (emu->flags.quitonexit==2);
thread_set_emu(NULL);
FreeX64Emu(&emu);
if(arg->stack_clone_used)
@ -3274,10 +3276,10 @@ EXPORT int my_register_printf_type(x64emu_t* emu, void* f)
extern int box64_quit;
EXPORT void my_exit(x64emu_t* emu, int code)
{
if(emu->quitonexit) {
if(emu->flags.quitonexit) {
emu->quit = 1;
R_EAX = code;
emu->quitonexit = 2;
emu->flags.quitonexit = 2;
return;
}
emu->quit = 1;

View File

@ -63,7 +63,7 @@ BOX64_EMULATED_LIBS=libopenal.so.1
BOX64_DYNAREC_SAFEFLAGS=0
BOX64_DYNAREC_BIGBLOCK=3
BOX64_DYNAREC_FORWARD=1024
BOX64_DYNAREC_CALLRET=1
#BOX64_DYNAREC_CALLRET=1 #New jmpbuf handling tend to break this optim!
[pressure-vessel-wrap]
BOX64_NOGTK=1