mirror of
https://github.com/ptitSeb/box64.git
synced 2025-05-09 00:21:32 +08:00
Improved jmpbuff handling a bit
This commit is contained in:
parent
e8972efca1
commit
e2077c46ce
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user