Skip to content

Commit

Permalink
Simplified ucontext uc_link managment (closer to glibc handling) ([BO…
Browse files Browse the repository at this point in the history
…X32] too)
  • Loading branch information
ptitSeb committed Dec 20, 2024
1 parent 6ac7d7a commit 8a37b12
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 55 deletions.
13 changes: 0 additions & 13 deletions src/dynarec/dynarec.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,6 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
multiuint_t old_op1 = emu->op1;
multiuint_t old_op2 = emu->op2;
multiuint_t old_res = emu->res;
// uc_link
void* old_uc_link = emu->uc_link;
emu->uc_link = NULL;

#ifdef BOX32
if(box64_is32bits)
Expand All @@ -124,7 +121,6 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
DynaRun(emu);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
emu->uc_link = old_uc_link;
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
Expand Down Expand Up @@ -229,15 +225,6 @@ void DynaRun(x64emu_t* emu)
emu->fork = 0;
emu = x64emu_fork(emu, forktype);
}
if(emu->quit && emu->uc_link) {
emu->quit = 0;
#ifdef BOX32
if(box64_is32bits)
my32_setcontext(emu, emu->uc_link);
else
#endif
my_setcontext(emu, emu->uc_link);
}
}
#endif
if(emu->flags.need_jmpbuf)
Expand Down
4 changes: 0 additions & 4 deletions src/emu/x64emu.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,9 +608,6 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
multiuint_t old_op1 = emu->op1;
multiuint_t old_op2 = emu->op2;
multiuint_t old_res = emu->res;
// uc_link
void* old_uc_link = emu->uc_link;
emu->uc_link = NULL;
//Push64(emu, GetRBP(emu)); // set frame pointer
//SetRBP(emu, GetRSP(emu)); // save RSP
//R_RSP -= 200;
Expand All @@ -626,7 +623,6 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
Run(emu, 0);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
emu->uc_link = old_uc_link;
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
Expand Down
2 changes: 0 additions & 2 deletions src/emu/x64emu_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ typedef struct x64emu_s {
uintptr_t old_savedsp;
#endif

void* uc_link; // to handle setcontext (can be x64_ucontext_t or a i386_ucontext_t)

int type; // EMUTYPE_xxx define
#ifdef BOX32
int libc_err; // copy of errno from libc
Expand Down
16 changes: 2 additions & 14 deletions src/emu/x64run.c
Original file line number Diff line number Diff line change
Expand Up @@ -2253,15 +2253,15 @@ int Run(x64emu_t *emu, int step)
fini:
#ifndef TEST_INTERPRETER
// check the TRACE flag before going to out, in case it's a step by step scenario
if(!emu->quit && !emu->fork && !emu->uc_link && ACCESS_FLAG(F_TF)) {
if(!emu->quit && !emu->fork && ACCESS_FLAG(F_TF)) {
R_RIP = addr;
emit_signal(emu, SIGTRAP, (void*)addr, 1);
if(emu->quit) goto fini;
}
#endif
if(emu->segs[_CS]!=0x33 && emu->segs[_CS]!=0x23) printf_log(LOG_NONE, "Warning, CS is not default value: 0x%x\n", emu->segs[_CS]);
#ifndef TEST_INTERPRETER
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit);
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->quit);
if(unimp) {
//emu->quit = 1;
UnimpOpcode(emu, is32bits);
Expand All @@ -2278,18 +2278,6 @@ if(emu->segs[_CS]!=0x33 && emu->segs[_CS]!=0x23) printf_log(LOG_NONE, "Warning,
return 0;
goto x64emurun;
}
// setcontext handling
else if(emu->quit && emu->uc_link) {
emu->quit = 0;
#ifdef BOX32
if(box64_is32bits)
my32_setcontext(emu, emu->uc_link);
else
#endif
my_setcontext(emu, emu->uc_link);
addr = R_RIP;
goto x64emurun;
}
#else
if(unimp) {
printf_log(LOG_INFO, "Warning, inimplemented opcode in Test Interpreter\n");
Expand Down
43 changes: 28 additions & 15 deletions src/libtools/signal32.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "threads.h"
#include "emu/x87emu_private.h"
#include "custommem.h"
#include "bridge.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "../dynarec/dynablock_private.h"
Expand Down Expand Up @@ -949,8 +950,6 @@ EXPORT int my32_getcontext(x64emu_t* emu, void* ucp)
fpu_savenv(emu, from_ptrv(u->uc_mcontext.fpregs), 1); // it seems getcontext only save fpu env, not fpu regs
// get signal mask
sigprocmask(SIG_SETMASK, NULL, (sigset_t*)&u->uc_sigmask);
// ensure uc_link is properly initialized
u->uc_link = to_ptrv(emu->uc_link);

return 0;
}
Expand All @@ -963,15 +962,15 @@ EXPORT int my32_setcontext(x64emu_t* emu, void* ucp)
emu->init_stack = from_ptrv(u->uc_stack.ss_sp);
emu->size_stack = from_ulong(u->uc_stack.ss_size);
// set general register
R_EAX = u->uc_mcontext.gregs[I386_EAX];
R_ECX = u->uc_mcontext.gregs[I386_ECX];
R_EDX = u->uc_mcontext.gregs[I386_EDX];
R_EDI = u->uc_mcontext.gregs[I386_EDI];
R_ESI = u->uc_mcontext.gregs[I386_ESI];
R_EBP = u->uc_mcontext.gregs[I386_EBP];
R_EIP = u->uc_mcontext.gregs[I386_EIP];
R_ESP = u->uc_mcontext.gregs[I386_ESP];
R_EBX = u->uc_mcontext.gregs[I386_EBX];
R_RAX = u->uc_mcontext.gregs[I386_EAX];
R_RCX = u->uc_mcontext.gregs[I386_ECX];
R_RDX = u->uc_mcontext.gregs[I386_EDX];
R_RDI = u->uc_mcontext.gregs[I386_EDI];
R_RSI = u->uc_mcontext.gregs[I386_ESI];
R_RBP = u->uc_mcontext.gregs[I386_EBP];
R_RIP = u->uc_mcontext.gregs[I386_EIP];
R_RSP = u->uc_mcontext.gregs[I386_ESP];
R_RBX = u->uc_mcontext.gregs[I386_EBX];
// get segments
R_GS = u->uc_mcontext.gregs[I386_GS];
R_FS = u->uc_mcontext.gregs[I386_FS];
Expand All @@ -983,12 +982,22 @@ EXPORT int my32_setcontext(x64emu_t* emu, void* ucp)
fpu_loadenv(emu, from_ptrv(u->uc_mcontext.fpregs), 1);
// set signal mask
sigprocmask(SIG_SETMASK, (sigset_t*)&u->uc_sigmask, NULL);
// set uc_link
emu->uc_link = from_ptrv(u->uc_link);

errno = 0;
return R_EAX;
}

void vFEv_32(x64emu_t *emu, uintptr_t fnc);
EXPORT void my32_start_context(x64emu_t* emu)
{
// this is call indirectly by swapcontext from a makecontext, and will link context or just exit
i386_ucontext_t *u = (i386_ucontext_t*)from_ptriv(R_EBX);
if(u)
my32_setcontext(emu, u);
else
emu->quit = 1;
}

EXPORT void my32_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, int32_t* argv)
{
// printf_log(LOG_NONE, "Warning: call to unimplemented makecontext\n");
Expand All @@ -997,16 +1006,20 @@ EXPORT void my32_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc,
u->uc_mcontext.gregs[I386_ESP] = to_ptr(u->uc_stack.ss_sp + u->uc_stack.ss_size - 4);
// setup the function
u->uc_mcontext.gregs[I386_EIP] = to_ptrv(fnc);
// setup args
uint32_t* esp = (uint32_t*)from_ptr(u->uc_mcontext.gregs[I386_ESP]);
// setup return to private start_context uc_link
*esp = u->uc_link;
u->uc_mcontext.gregs[I386_EBX] = (uintptr_t)esp;
--esp;
// setup args
for (int i=0; i<argc; ++i) {
// push value
--esp;
*esp = argv[(argc-1)-i];
}
// push the return value
--esp;
*esp = to_ptr(my_context->exit_bridge);
*esp = AddCheckBridge(my_context->system, vFEv_32, my32_start_context, 0, "my_start_context");//my_context->exit_bridge;//to_ptr(my_context->exit_bridge);
u->uc_mcontext.gregs[I386_ESP] = (uintptr_t)esp;
}

Expand Down
25 changes: 18 additions & 7 deletions src/libtools/signals.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "threads.h"
#include "emu/x87emu_private.h"
#include "custommem.h"
#include "bridge.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "../dynarec/dynablock_private.h"
Expand Down Expand Up @@ -2291,8 +2292,6 @@ EXPORT int my_getcontext(x64emu_t* emu, void* ucp)

// get signal mask
sigprocmask(SIG_SETMASK, NULL, (sigset_t*)&u->uc_sigmask);
// ensure uc_link is properly initialized
u->uc_link = (x64_ucontext_t*)emu->uc_link;

return 0;
}
Expand Down Expand Up @@ -2331,12 +2330,20 @@ EXPORT int my_setcontext(x64emu_t* emu, void* ucp)
emu->mxcsr.x32 = *(uint32_t*)(ucp + 432);
// set signal mask
sigprocmask(SIG_SETMASK, (sigset_t*)&u->uc_sigmask, NULL);
// set uc_link
emu->uc_link = u->uc_link;
errno = 0;

return R_EAX;
}
void vFEv(x64emu_t *emu, uintptr_t fnc);
EXPORT void my_start_context(x64emu_t* emu)
{
// this is call indirectly by swapcontext from a makecontext, and will link context or just exit
x64_ucontext_t *u = *(x64_ucontext_t**)R_RBX;
if(u)
my_setcontext(emu, u);
else
emu->quit = 1;
}

EXPORT void my_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, int64_t* argv)
{
Expand All @@ -2346,15 +2353,19 @@ EXPORT void my_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, in
uintptr_t* rsp = (uintptr_t*)(u->uc_stack.ss_sp + u->uc_stack.ss_size - sizeof(uintptr_t));
// setup the function
u->uc_mcontext.gregs[X64_RIP] = (intptr_t)fnc;
// setup return to private start_context uc_link
*rsp = (uintptr_t)u->uc_link;
u->uc_mcontext.gregs[X64_RBX] = (uintptr_t)rsp;
--rsp;
// setup args
int n = 3;
int j = 0;
int regs_abi[] = {_DI, _SI, _DX, _CX, _R8, _R9};
for (int i=0; i<argc; ++i) {
// get value first
uint64_t v;
uint32_t v;
if(n<6)
v = emu->regs[regs_abi[n++]].q[0];
v = emu->regs[regs_abi[n++]].dword[0];
else
v = argv[j++];
// push value
Expand All @@ -2372,7 +2383,7 @@ EXPORT void my_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, in
}
// push the return value
--rsp;
*rsp = my_context->exit_bridge;
*rsp = AddCheckBridge(my_context->system, vFEv, my_start_context, 0, "my_start_context");//my_context->exit_bridge;
u->uc_mcontext.gregs[X64_RSP] = (uintptr_t)rsp;
}

Expand Down

0 comments on commit 8a37b12

Please sign in to comment.