Added some x86_64 regs and emu infrastructure

This commit is contained in:
ptitSeb 2021-03-02 11:45:50 +01:00
parent be92787329
commit 997b5c6b50
12 changed files with 1983 additions and 0 deletions

View File

@ -103,6 +103,9 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/elfs/elfloader.c"
"${BOX64_ROOT}/src/elfs/elfparser.c"
"${BOX64_ROOT}/src/elfs/elfload_dump.c"
"${BOX64_ROOT}/src/emu/x64emu.c"
"${BOX64_ROOT}/src/emu/x64int3.c"
"${BOX64_ROOT}/src/emu/x87emu_private.c"
"${BOX64_ROOT}/src/libtools/auxval.c"
"${BOX64_ROOT}/src/tools/box64stack.c"
"${BOX64_ROOT}/src/tools/pathcoll.c"

454
src/emu/x64emu.c Executable file
View File

@ -0,0 +1,454 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64emu_private.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "x64run.h"
#include "x64run_private.h"
//#include "callback.h"
//#include "bridge.h"
#ifdef DYNAREC
#include "custommem.h"
#endif
typedef struct cleanup_s {
void* f;
int arg;
void* a;
} cleanup_t;
static uint32_t x86emu_parity_tab[8] =
{
0x96696996,
0x69969669,
0x69969669,
0x96696996,
0x69969669,
0x96696996,
0x96696996,
0x69969669,
};
uint32_t* GetParityTab()
{
return x86emu_parity_tab;
}
//void PushExit(x64emu_t* emu)
//{
// uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
// Push(emu, endMarker);
//}
//void* GetExit()
//{
// return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
//}
static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
emu->context = context;
// setup cpu helpers
for (int i=0; i<8; ++i)
emu->sbiidx[i] = &emu->regs[i];
emu->sbiidx[4] = &emu->zero;
emu->x86emu_parity_tab = x86emu_parity_tab;
emu->eflags.x32 = 0x202; // default flags?
// own stack?
emu->stack2free = (ownstack)?(void*)stack:NULL;
emu->init_stack = (void*)stack;
emu->size_stack = stacksize;
// set default value
R_RIP = start;
R_RSP = (stack + stacksize) & ~7; // align stack start, always
// fake init of segments...
emu->segs[_CS] = 0x73;
emu->segs[_DS] = emu->segs[_ES] = emu->segs[_SS] = 0x7b;
emu->segs[_FS] = default_fs;
emu->segs[_GS] = 0x33;
// setup fpu regs
reset_fpu(emu);
}
EXPORTDYN
x64emu_t *NewX64Emu(box64context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "Allocate a new X86_64 Emu, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
x64emu_t *emu = (x64emu_t*)calloc(1, sizeof(x64emu_t));
internalX64Setup(emu, context, start, stack, stacksize, ownstack);
return emu;
}
x64emu_t *NewX64EmuFromStack(x64emu_t* emu, box64context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "New X86_64 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
internalX64Setup(emu, context, start, stack, stacksize, ownstack);
return emu;
}
EXPORTDYN
void SetupX86Emu(x64emu_t *emu)
{
printf_log(LOG_DEBUG, "Setup X86_64 Emu\n");
}
void SetTraceEmu(uintptr_t start, uintptr_t end)
{
// if(my_context->zydis) {
// if (end == 0) {
// printf_log(LOG_INFO, "Setting trace\n");
// } else {
// if(end!=1) { // 0-1 is basically no trace, so don't printf it...
// printf_log(LOG_INFO, "Setting trace only between %p and %p\n", (void*)start, (void*)end);
// }
// }
// }
trace_start = start;
trace_end = end;
}
void AddCleanup(x64emu_t *emu, void *p)
{
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
my_context->cleanups[my_context->clean_sz].arg = 0;
my_context->cleanups[my_context->clean_sz].a = NULL;
my_context->cleanups[my_context->clean_sz++].f = p;
}
void AddCleanup1Arg(x64emu_t *emu, void *p, void* a)
{
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
my_context->cleanups[my_context->clean_sz].arg = 1;
my_context->cleanups[my_context->clean_sz].a = a;
my_context->cleanups[my_context->clean_sz++].f = p;
}
//void CallCleanup(x64emu_t *emu, void* p)
//{
// printf_log(LOG_DEBUG, "Calling atexit registered functions for %p mask\n", p);
// for(int i=my_context->clean_sz-1; i>=0; --i) {
// if(p==my_context->cleanups[i].f) {
// printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
// RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
// // now remove the cleanup
// if(i!=my_context->clean_sz-1)
// memmove(my_context->cleanups+i, my_context->cleanups+i+1, (my_context->clean_sz-i-1)*sizeof(cleanup_t));
// --my_context->clean_sz;
// }
// }
//}
//void CallAllCleanup(x64emu_t *emu)
//{
// printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
// for(int i=my_context->clean_sz-1; i>=0; --i) {
// printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
// RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
// }
// my_context->clean_sz = 0;
// free(my_context->cleanups);
// my_context->cleanups = NULL;
//}
static void internalFreeX64(x64emu_t* emu)
{
free(emu->stack2free);
}
EXPORTDYN
void FreeX64Emu(x64emu_t **emu)
{
if(!emu)
return;
printf_log(LOG_DEBUG, "%04d|Free a X86_64 Emu (%p)\n", GetTID(), *emu);
internalFreeX64(*emu);
free(*emu);
*emu = NULL;
}
void FreeX64EmuFromStack(x64emu_t **emu)
{
if(!emu)
return;
printf_log(LOG_DEBUG, "%04d|Free a X86_64 Emu from stack (%p)\n", GetTID(), *emu);
internalFreeX64(*emu);
}
void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
{
memcpy(newemu->regs, emu->regs, sizeof(emu->regs));
memcpy(&newemu->ip, &emu->ip, sizeof(emu->ip));
memcpy(&newemu->eflags, &emu->eflags, sizeof(emu->eflags));
newemu->old_ip = emu->old_ip;
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
memset(newemu->segs_serial, 0, sizeof(newemu->segs_serial));
memcpy(newemu->fpu, emu->fpu, sizeof(emu->fpu));
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
newemu->cw = emu->cw;
newemu->cw_mask_all = emu->cw_mask_all;
memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
newemu->top = emu->top;
newemu->fpu_stack = emu->fpu_stack;
memcpy(&newemu->round, &emu->round, sizeof(emu->round));
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
newemu->mxcsr = emu->mxcsr;
newemu->quit = emu->quit;
newemu->error = emu->error;
// adapt R_RSP to new stack frame
uintptr_t oldst = (uintptr_t)((emu->init_stack)?emu->init_stack:emu->context->stack);
uintptr_t newst = (uintptr_t)((newemu->init_stack)?newemu->init_stack:newemu->context->stack);
newemu->regs[_SP].q[0] = emu->regs[_SP].q[0] + (intptr_t)(newst - oldst);
}
box64context_t* GetEmuContext(x64emu_t* emu)
{
return emu->context;
}
uint32_t GetEAX(x64emu_t *emu)
{
return R_EAX;
}
uint64_t GetRAX(x64emu_t *emu)
{
return R_RAX;
}
void SetEAX(x64emu_t *emu, uint32_t v)
{
R_EAX = v;
}
void SetEBX(x64emu_t *emu, uint32_t v)
{
R_EBX = v;
}
void SetECX(x64emu_t *emu, uint32_t v)
{
R_ECX = v;
}
void SetEDX(x64emu_t *emu, uint32_t v)
{
R_EDX = v;
}
void SetESI(x64emu_t *emu, uint32_t v)
{
R_ESI = v;
}
void SetEDI(x64emu_t *emu, uint32_t v)
{
R_EDI = v;
}
void SetEBP(x64emu_t *emu, uint32_t v)
{
R_EBP = v;
}
//void SetESP(x64emu_t *emu, uint32_t v)
//{
// R_ESP = v;
//}
void SetRAX(x64emu_t *emu, uint64_t v)
{
R_RAX = v;
}
void SetRBX(x64emu_t *emu, uint64_t v)
{
R_RBX = v;
}
void SetRCX(x64emu_t *emu, uint64_t v)
{
R_RCX = v;
}
void SetRDX(x64emu_t *emu, uint64_t v)
{
R_RDX = v;
}
void SetRSI(x64emu_t *emu, uint64_t v)
{
R_RSI = v;
}
void SetRDI(x64emu_t *emu, uint64_t v)
{
R_RDI = v;
}
void SetRBP(x64emu_t *emu, uint64_t v)
{
R_RBP = v;
}
void SetRSP(x64emu_t *emu, uint64_t v)
{
R_RSP = v;
}
void SetRIP(x64emu_t *emu, uint64_t v)
{
R_RIP = v;
}
uint64_t GetRSP(x64emu_t *emu)
{
return R_RSP;
}
void SetFS(x64emu_t *emu, uint16_t v)
{
emu->segs[_FS] = v;
}
uint16_t GetFS(x64emu_t *emu)
{
return emu->segs[_FS];
}
void ResetFlags(x64emu_t *emu)
{
emu->df = d_none;
}
const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
{
static char buff[800];
char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
"R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
char tmp[80];
buff[0] = '\0';
if(trace_emm) {
// do emm reg is needed
for(int i=0; i<8; ++i) {
sprintf(tmp, "mm%d:%016llx", i, emu->mmx[i].q);
strcat(buff, tmp);
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
}
}
if(trace_xmm) {
// do xmm reg is needed
for(int i=0; i<8; ++i) {
sprintf(tmp, "%d:%016llx%016llx", i, emu->xmm[i].q[1], emu->xmm[i].q[0]);
strcat(buff, tmp);
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
}
}
// start with FPU regs...
if(emu->fpu_stack) {
for (int i=0; i<emu->fpu_stack; i++) {
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].d);
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
while(c--) strcat(buff, " ");
if(i==3) strcat(buff, "\n");
}
strcat(buff, "\n");
}
for (int i=_AX; i<=_R15; ++i) {
sprintf(tmp, "%s=%016llx ", regname[i], emu->regs[i].q[0]);
strcat(buff, tmp);
if (i==3) {
if(emu->df) {
strcat(buff, "FLAGS=??????\n");
} else {
#define FLAG_CHAR(f) (ACCESS_FLAG(F_##f##F)) ? #f : "-"
sprintf(tmp, "FLAGS=%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(C), FLAG_CHAR(P), FLAG_CHAR(A), FLAG_CHAR(Z), FLAG_CHAR(S));
strcat(buff, tmp);
#undef FLAG_CHAR
}
}
}
sprintf(tmp, "RIP=%016llx ", ip);
strcat(buff, tmp);
return buff;
}
void StopEmu(x64emu_t* emu, const char* reason)
{
emu->quit = 1;
printf_log(LOG_NONE, "%s", reason);
// dump stuff...
printf_log(LOG_NONE, "CPU Regs=%s\n", DumpCPURegs(emu, R_RIP));
// TODO: stack, memory/instruction around EIP, etc..
}
void UnimpOpcode(x64emu_t* emu)
{
R_RIP = emu->old_ip;
int tid = syscall(SYS_gettid);
printf_log(LOG_NONE, "%04d|%p: Unimplemented Opcode (%02X) %02X %02X %02X %02X %02X %02X %02X %02X\n",
tid, (void*)emu->old_ip, Peek(emu, -1),
Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7));
emu->quit=1;
emu->error |= ERR_UNIMPL;
}
//void EmuCall(x64emu_t* emu, uintptr_t addr)
//{
// uint64_t old_rsp = R_RSP;
// uint64_t old_rbx = R_RBX;
// uint64_t old_rdi = R_RDI;
// uint64_t old_rsi = R_RSI;
// uint64_t old_rbp = R_RBP;
// uint64_t old_rip = R_RIP;
// PushExit(emu);
// R_RIP = addr;
// emu->df = d_none;
// Run(emu, 0);
// emu->quit = 0; // reset Quit flags...
// emu->df = d_none;
// if(emu->quitonlongjmp && emu->longjmp) {
// emu->longjmp = 0; // don't change anything because of the longjmp
// } else {
// R_RBX = old_ebx;
// R_RDI = old_edi;
// R_RSI = old_esi;
// R_RBP = old_ebp;
// R_RSP = old_esp;
// R_RIP = old_eip; // and set back instruction pointer
// }
//}
uint64_t ReadTSC(x64emu_t* emu)
{
//TODO: implement hardware counter read?
// Read the TimeStamp Counter as 64bits.
// this is supposed to be the number of instrunctions executed since last reset
// fall back to gettime...
#ifndef NOGETCLOCK
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
#endif
}
void ResetSegmentsCache(x64emu_t *emu)
{
if(!emu)
return;
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
}

93
src/emu/x64emu_private.h Executable file
View File

@ -0,0 +1,93 @@
#ifndef __X86EMU_PRIVATE_H_
#define __X86EMU_PRIVATE_H_
#include "regs.h"
typedef struct box64context_s box64context_t;
//typedef struct i386_ucontext_s i386_ucontext_t;
#define ERR_UNIMPL 1
#define ERR_DIVBY0 2
#define ERR_ILLEGAL 4
#ifdef DYNAREC
#define CSTACK 32
#define CSTACKMASK 31
#endif
typedef struct forkpty_s {
void* amaster;
void* name;
void* termp;
void* winp;
void* f; // forkpty function
} forkpty_t;
typedef struct x64emu_s {
// cpu
reg64_t regs[16];
x86flags_t eflags;
reg64_t ip;
uintptr_t old_ip;
// fpu
fpu_reg_t fpu[9];
uint16_t cw,cw_mask_all;
x87flags_t sw;
uint32_t top; // top is part of sw, but it's faster to have it separatly
int fpu_stack;
fpu_round_t round;
fpu_ld_t fpu_ld[9]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[9]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[9];
// mmx
mmx_regs_t mmx[8];
// sse
sse_regs_t xmm[8];
uint32_t mxcsr;
// defered flags
defered_flags_t df;
uint64_t op1;
uint64_t op2;
uint64_t res;
uint32_t *x86emu_parity_tab; // helper
#ifdef HAVE_TRACE
uintptr_t prev2_ip, prev_ip;
#endif
// segments
uint32_t segs[6]; // only 32bits value?
uintptr_t segs_offs[6]; // computed offset associate with segment
uint64_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
// emu control
int quit;
int error;
int fork; // quit because need to fork
forkpty_t* forkpty_info;
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
// parent context
box64context_t *context;
// cpu helpers
reg64_t zero;
reg64_t *sbiidx[8];
// scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
uint64_t scratch[200];
// local stack, do be deleted when emu is freed
void* stack2free; // this is the stack to free (can be NULL)
void* init_stack; // initial stack (owned or not)
uint32_t size_stack; // stack size (owned or not)
//i386_ucontext_t *uc_link; // to handle setcontext
int type; // EMUTYPE_xxx define
} x64emu_t;
#define EMUTYPE_NONE 0
#define EMUTYPE_MAIN 1
#define EMUTYPE_SIGNAL 2
//#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0; emu->quit=1;}
#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0;} // should rise a SIGFPE and not quit
#endif //__X86EMU_PRIVATE_H_

312
src/emu/x64int3.c Executable file
View File

@ -0,0 +1,312 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <dlfcn.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
//#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x87emu_private.h"
//#include "x64primop.h"
//#include "x64trace.h"
//#include "wrapper.h"
#include "box64context.h"
//#include "librarian.h"
#include <elf.h>
#include "elfloader.h"
#include "elfs/elfloader_private.h"
typedef int32_t (*iFpppp_t)(void*, void*, void*, void*);
//x64emu_t* x64emu_fork(x64emu_t* emu, int forktype)
//{
// // execute atforks prepare functions, in reverse order
// for (int i=my_context->atfork_sz-1; i>=0; --i)
// if(my_context->atforks[i].prepare)
// EmuCall(emu, my_context->atforks[i].prepare);
// int type = emu->type;
// int v;
// if(forktype==2) {
// iFpppp_t forkpty = (iFpppp_t)emu->forkpty_info->f;
// v = forkpty(emu->forkpty_info->amaster, emu->forkpty_info->name, emu->forkpty_info->termp, emu->forkpty_info->winp);
// emu->forkpty_info = NULL;
// } else
// v = fork();
// if(type == EMUTYPE_MAIN)
// thread_set_emu(emu);
// if(v==EAGAIN || v==ENOMEM) {
// // error...
// } else if(v!=0) {
// // execute atforks parent functions
// for (int i=0; i<my_context->atfork_sz; --i)
// if(my_context->atforks[i].parent)
// EmuCall(emu, my_context->atforks[i].parent);
//
// } else if(v==0) {
// // execute atforks child functions
// for (int i=0; i<my_context->atfork_sz; --i)
// if(my_context->atforks[i].child)
// EmuCall(emu, my_context->atforks[i].child);
// }
// R_EAX = v;
// return emu;
//}
extern int errno;
//void x64Int3(x64emu_t* emu)
//{
// if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door"
// {
// R_EIP += 2;
// #ifdef RK3399
// volatile // to avoid addr to be put in an VFPU register
// #endif
// uint32_t addr = Fetch32(emu);
// if(addr==0) {
// //printf_log(LOG_INFO, "%p:Exit x86 emu (emu=%p)\n", *(void**)(R_ESP), emu);
// emu->quit=1; // normal quit
// } else {
// RESET_FLAGS(emu);
// wrapper_t w = (wrapper_t)addr;
// addr = Fetch32(emu);
// /* This party can be used to trace only 1 specific lib (but it is quite slow)
// elfheader_t *h = FindElfAddress(my_context, *(uintptr_t*)(R_ESP));
// int have_trace = 0;
// if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
// if(box86_log>=LOG_DEBUG /*|| have_trace*/) {
// pthread_mutex_lock(&emu->context->mutex_trace);
// int tid = GetTID();
// char buff[256] = "\0";
// char buff2[64] = "\0";
// char buff3[64] = "\0";
// char *tmp;
// int post = 0;
// int perr = 0;
// uint32_t *pu32 = NULL;
// const char *s = NULL;
// {
// Dl_info info;
// if(dladdr((void*)addr, &info))
// s = info.dli_sname;
// }
// if(!s) s = GetNativeName((void*)addr);
// if(addr==(uintptr_t)PltResolver) {
// snprintf(buff, 256, "%s", " ... ");
// } else
// if(strstr(s, "SDL_RWFromFile")==s || strstr(s, "SDL_RWFromFile")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%s, %s)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(strstr(s, "glColor4f")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
// } else if(strstr(s, "glTexCoord2f")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
// } else if(strstr(s, "glVertex2f")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
// } else if(strstr(s, "glVertex3f")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
// } else if(strstr(s, "__open64")==s || strcmp(s, "open64")==0) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
// perr = 1;
// } else if(!strcmp(s, "opendir")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
// perr = 1;
// } else if(strstr(s, "__open")==s || strcmp(s, "open")==0) {
// tmp = *(char**)(R_ESP+4);
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
// perr = 1;
// } else if(strcmp(s, "mkdir")==0) {
// tmp = *(char**)(R_ESP+4);
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
// perr = 1;
// } else if(!strcmp(s, "fopen")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
// perr = 1;
// } else if(!strcmp(s, "freopen")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
// perr = 1;
// } else if(!strcmp(s, "fopen64")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
// perr = 2;
// } else if(!strcmp(s, "chdir")) {
// pu32=*(uint32_t**)(R_ESP+4);
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
// } else if(strstr(s, "getenv")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
// post = 2;
// } else if(strstr(s, "pread")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
// perr = 1;
// } else if(strstr(s, "ioctl")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
// perr = 1;
// } else if(strstr(s, "statvfs64")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
// } else if(strstr(s, "index")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
// } else if(strstr(s, "rindex")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
// } else if(strstr(s, "my___xstat64")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
// perr = 1;
// } else if(strcmp(s, "my___xstat")==0) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
// perr = 1;
// } else if(strstr(s, "my___lxstat64")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
// perr = 1;
// } else if(strstr(s, "sem_timedwait")==s) {
// pu32 = *(uint32_t**)(R_ESP+8);
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?pu32[0]:-1, pu32?pu32[1]:-1);
// perr = 1;
// } else if(strstr(s, "waitpid")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
// perr = 1;
// } else if(strstr(s, "clock_gettime")==s || strstr(s, "__clock_gettime")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
// post = 1;
// pu32 = *(uint32_t**)(R_ESP+8);
// } else if(strstr(s, "semop")==s) {
// int16_t* p16 = *(int16_t**)(R_ESP+8);
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/%d], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
// perr = 1;
// } else if(!strcmp(s, "my_mmap64")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
// perr = 1;
// } else if(!strcmp(s, "my_mmap")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
// perr = 1;
// } else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(strstr(s, "gtk_signal_connect_full")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p, %p, %p, %p, %d, %d)", tid, *(void**)(R_ESP), "gtk_signal_connect_full", *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20), *(void**)(R_ESP+24), *(int32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32));
// } else if(strstr(s, "strcmp")==s || strstr(s, "__strcmp")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(strstr(s, "strstr")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(strstr(s, "strlen")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
// } else if(strstr(s, "my_vsnprintf")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
// pu32 = *(uint32_t**)(R_ESP+4);
// post = 3;
// } else if(strstr(s, "my_vsprintf")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\"...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
// pu32 = *(uint32_t**)(R_ESP+4);
// post = 3;
// } else if(strstr(s, "my_snprintf")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
// pu32 = *(uint32_t**)(R_ESP+4);
// post = 3;
// } else if(strstr(s, "my_sprintf")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
// pu32 = *(uint32_t**)(R_ESP+4);
// post = 3;
// } else if(strstr(s, "my_printf")==s) {
// pu32 = *(uint32_t**)(R_ESP+4);
// if(((uintptr_t)pu32)<0x5) // probably a _chk function
// pu32 = *(uint32_t**)(R_ESP+8);
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
// } else if(strstr(s, "puts")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
// } else if(strstr(s, "fputs")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
// } else if(strstr(s, "my_fprintf")==s) {
// pu32 = *(uint32_t**)(R_ESP+8);
// if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
// pu32 = *(uint32_t**)(R_ESP+12);
// snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
// } else if(strstr(s, "my_vfprintf")==s) {
// pu32 = *(uint32_t**)(R_ESP+8);
// if(((uintptr_t)pu32)<0x5) // probably a _chk function
// pu32 = *(uint32_t**)(R_ESP+12);
// snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
// } else if(strstr(s, "vkGetInstanceProcAddr")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(strstr(s, "vkGetDeviceProcAddr")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(strstr(s, "my_glXGetProcAddress")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
// } else if(strstr(s, "my_sscanf")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(!strcmp(s, "vsscanf")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(strstr(s, "XCreateWindow")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
// } else if(strstr(s, "XLoadQueryFont")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(strstr(s, "pthread_mutex_lock")==s) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
// } else if(!strcmp(s, "fmodf")) {
// post = 4;
// snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
// } else if(!strcmp(s, "fmod")) {
// post = 4;
// snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
// } else if(strstr(s, "SDL_GetWindowSurface")==s) {
// post = 5;
// snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
// } else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
// post = 5;
// snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
// } else if(!strcmp(s, "my_syscall")) {
// snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
// perr = 1;
// } else {
// snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
// }
// printf_log(LOG_NONE, "%s =>", buff);
// pthread_mutex_unlock(&emu->context->mutex_trace);
// w(emu, addr); // some function never come back, so unlock the mutex first!
// pthread_mutex_lock(&emu->context->mutex_trace);
// if(post)
// switch(post) {
// case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
// break;
// case 2: snprintf(buff2, 63, "(%s)", R_EAX?((char*)R_EAX):"nil");
// break;
// case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil");
// break;
// case 4: snprintf(buff2, 63, " (%f)", ST0.d);
// break;
// case 5: {
// uint32_t* p = (uint32_t*)R_EAX;
// if(p)
// snprintf(buff2, 63, " size=%dx%d, pitch=%d, pixels=%p", p[2], p[3], p[4], p+5);
// else
// snprintf(buff2, 63, "NULL Surface");
// }
// break;
// }
// if(perr==1 && ((int)R_EAX)<0)
// snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
// else if(perr==2 && R_EAX==0)
// snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
// printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
// pthread_mutex_unlock(&emu->context->mutex_trace);
// } else
// w(emu, addr);
// }
// return;
// }
// if(my_context->signals[SIGTRAP])
// raise(SIGTRAP);
// else
// printf_log(LOG_INFO, "%04d|Warning, ignoring unsupported Int 3 call @%p\n", GetTID(), (void*)R_EIP);
// //emu->quit = 1;
//}
int GetTID()
{
return syscall(SYS_gettid);
}

236
src/emu/x64run_private.h Executable file
View File

@ -0,0 +1,236 @@
#ifndef __X86RUN_PRIVATE_H_
#define __X86RUN_PRIVATE_H_
#include <stdint.h>
#include "regs.h"
#include "x64emu_private.h"
typedef struct x64emu_s x64emu_t;
static inline uint8_t Fetch8(x64emu_t *emu) {return *(uint8_t*)(R_RIP++);}
static inline int8_t Fetch8s(x64emu_t *emu) {return *(int8_t*)(R_RIP++);}
static inline uint16_t Fetch16(x64emu_t *emu)
{
uint16_t val = *(uint16_t*)R_RIP;
R_RIP+=2;
return val;
}
static inline int16_t Fetch16s(x64emu_t *emu)
{
int16_t val = *(int16_t*)R_RIP;
R_RIP+=2;
return val;
}
static inline uint32_t Fetch32(x64emu_t *emu)
{
uint32_t val = *(uint32_t*)R_RIP;
R_RIP+=4;
return val;
}
static inline int32_t Fetch32s(x64emu_t *emu)
{
int32_t val = *(int32_t*)R_RIP;
R_RIP+=4;
return val;
}
static inline uint64_t Fetch64(x64emu_t *emu)
{
uint64_t val = *(uint64_t*)R_RIP;
R_RIP+=8;
return val;
}
static inline int64_t Fetch64s(x64emu_t *emu)
{
int64_t val = *(int64_t*)R_RIP;
R_RIP+=8;
return val;
}
static inline uint8_t Peek(x64emu_t *emu, int offset){return *(uint8_t*)(R_RIP + offset);}
static inline uint64_t Pop(x64emu_t *emu)
{
uint64_t* st = ((uint64_t*)(R_RSP));
R_RSP += 8;
return *st;
}
static inline void Push(x64emu_t *emu, uint64_t v)
{
R_RSP -= 8;
*((uint64_t*)R_RSP) = v;
}
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
//static inline reg32_t* GetECommon(x64emu_t* emu, uint32_t m)
//{
// if (m<=7) {
// if(m==0x4) {
// uint8_t sib = Fetch8(emu);
// uintptr_t base = ((sib&0x7)==5)?Fetch32(emu):(emu->regs[(sib&0x7)].dword[0]); // base
// base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6));
// return (reg32_t*)base;
// } else if (m==0x5) { //disp32
// return (reg32_t*)Fetch32(emu);
// }
// return (reg32_t*)(emu->regs[m].dword[0]);
// } else {
// uintptr_t base;
// if((m&7)==4) {
// uint8_t sib = Fetch8(emu);
// base = emu->regs[(sib&0x7)].dword[0]; // base
// base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6));
// } else {
// base = emu->regs[(m&0x7)].dword[0];
// }
// base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu);
// return (reg32_t*)base;
// }
//}
//static inline reg32_t* GetEb(x64emu_t *emu, uint32_t v)
//{
// uint32_t m = v&0xC7; // filter Eb
// if(m>=0xC0) {
// int lowhigh = (m&4)>>2;
// return (reg32_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //?
// } else return GetECommon(emu, m);
//}
//static inline reg32_t* GetEd(x64emu_t *emu, uint32_t v)
//{
// uint32_t m = v&0xC7; // filter Ed
// if(m>=0xC0) {
// return &emu->regs[(m&0x07)];
// } else return GetECommon(emu, m);
//}
#define GetEw GetEd
//static inline reg32_t* GetEw16(x64emu_t *emu, uint32_t v)
//{
// uint32_t m = v&0xC7; // filter Ed
// if(m>=0xC0) {
// return &emu->regs[(m&0x07)];
// } else {
// uint32_t base = 0;
// switch(m&7) {
// case 0: base = R_BX+R_SI; break;
// case 1: base = R_BX+R_DI; break;
// case 2: base = R_BP+R_SI; break;
// case 3: base = R_BP+R_DI; break;
// case 4: base = R_SI; break;
// case 5: base = R_DI; break;
// case 6: base = R_BP; break;
// case 7: base = R_BX; break;
// }
// switch((m>>6)&3) {
// case 0: if(m==6) base = Fetch16(emu); break;
// case 1: base += Fetch8s(emu); break;
// case 2: base += Fetch16s(emu); break;
// // case 3 is C0..C7, already dealt with
// }
// return (reg32_t*)base;
// }
//}
//static inline reg32_t* GetEw16off(x64emu_t *emu, uint32_t v, uintptr_t offset)
//{
// uint32_t m = v&0xC7; // filter Ed
// if(m>=0xC0) {
// return &emu->regs[(m&0x07)];
// } else {
// uint32_t base = 0;
// switch(m&7) {
// case 0: base = R_BX+R_SI; break;
// case 1: base = R_BX+R_DI; break;
// case 2: base = R_BP+R_SI; break;
// case 3: base = R_BP+R_DI; break;
// case 4: base = R_SI; break;
// case 5: base = R_DI; break;
// case 6: base = R_BP; break;
// case 7: base = R_BX; break;
// }
// switch((m>>6)&3) {
// case 0: if(m==6) base = Fetch16(emu); break;
// case 1: base += Fetch8s(emu); break;
// case 2: base += Fetch16s(emu); break;
// // case 3 is C0..C7, already dealt with
// }
// return (reg32_t*)(base+offset);
// }
//}
//static inline mmx_regs_t* GetEm(x64emu_t *emu, uint32_t v)
//{
// uint32_t m = v&0xC7; // filter Ed
// if(m>=0xC0) {
// return &emu->mmx[m&0x07];
// } else return (mmx_regs_t*)GetECommon(emu, m);
//}
//static inline sse_regs_t* GetEx(x64emu_t *emu, uint32_t v)
//{
// uint32_t m = v&0xC7; // filter Ed
// if(m>=0xC0) {
// return &emu->xmm[m&0x07];
// } else return (sse_regs_t*)GetECommon(emu, m);
//}
//static inline reg32_t* GetG(x64emu_t *emu, uint32_t v)
//{
// return &emu->regs[((v&0x38)>>3)];
//}
//static inline reg32_t* GetGb(x64emu_t *emu, uint32_t v)
//{
// uint8_t m = (v&0x38)>>3;
// return (reg32_t*)&emu->regs[m&3].byte[m>>2];
//}
//static inline mmx_regs_t* GetGm(x64emu_t *emu, uint32_t v)
//{
// uint8_t m = (v&0x38)>>3;
// return &emu->mmx[m&7];
//}
//static inline sse_regs_t* GetGx(x64emu_t *emu, uint32_t v)
//{
// uint8_t m = (v&0x38)>>3;
// return &emu->xmm[m&7];
//}
//void UpdateFlags(x64emu_t *emu);
//#define CHECK_FLAGS(emu) if(emu->df) UpdateFlags(emu)
#define RESET_FLAGS(emu) emu->df = d_none
//void Run67(x64emu_t *emu);
//void Run0F(x64emu_t *emu);
//void Run660F(x64emu_t *emu);
//void Run66D9(x64emu_t *emu); // x87
//void Run6766(x64emu_t *emu);
//void RunGS(x64emu_t *emu);
//void RunFS(x64emu_t *emu);
//void RunFS66(x64emu_t *emu, uintptr_t tlsdata);
//void RunLock(x64emu_t *emu);
//void RunLock66(x64emu_t *emu);
//void x86Syscall(x64emu_t *emu);
//void x86Int3(x64emu_t* emu);
//x64emu_t* x64emu_fork(x64emu_t* e, int forktype);
//uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg);
#define GetGSBaseEmu(emu) GetSegmentBaseEmu(emu, _GS)
#define GetFSBaseEmu(emu) GetSegmentBaseEmu(emu, _FS)
#define GetESBaseEmu(emu) GetSegmentBaseEmu(emu, _ES)
#define GetDSBaseEmu(emu) GetSegmentBaseEmu(emu, _DS)
//const char* GetNativeName(void* p);
#ifdef HAVE_TRACE
void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec);
#endif
#endif //__X86RUN_PRIVATE_H_

307
src/emu/x87emu_private.c Executable file
View File

@ -0,0 +1,307 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "debug.h"
#include "x64emu_private.h"
#include "x87emu_private.h"
//#include "x64run_private.h"
void reset_fpu(x64emu_t* emu)
{
memset(emu->fpu, 0, sizeof(emu->fpu));
memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
emu->cw = 0x37F;
emu->sw.x16 = 0x0000;
emu->top = 0;
emu->fpu_stack = 0;
for(int i=0; i<9; ++i)
emu->p_regs[i].tag = 0b11; // STx is empty
}
void fpu_fbst(x64emu_t* emu, uint8_t* d) {
// very aproximative... but should not be much used...
uint8_t p;
uint8_t sign = 0x00;
double tmp, v = ST0.d;
if(ST0.d<0.0)
{
sign = 0x80;
v = -v;
}
for (int i=0; i<9; ++i) {
tmp = floor(v/10.0);
p = (v - 10.0*tmp);
v = tmp;
tmp = floor(v/10.0);
p |= ((uint8_t)(v - 10.0*tmp))<<4;
v = tmp;
*(d++)=p;
}
tmp = floor(v/10.0);
p = (v - 10.0*tmp);
p |= sign;
*(d++)=p;
// no flags....
}
void fpu_fbld(x64emu_t* emu, uint8_t* s) {
uint8_t p;
uint64_t tmp = 0;
uint64_t m = 1;
for (int i=0; i<9; ++i) {
p =*(s++);
tmp += m * (p&0x0f);
m *= 10;
tmp += m * ((p>>4)&0x0f);
m *= 10;
}
ST0.d = tmp;
p =*(s++);
ST0.d += m * (p&0x0f);
if(p&0x80)
ST0.d = -ST0.d;
}
#define FPU_t fpu_reg_t
#define BIAS80 16383
#define BIAS64 1023
// long double (80bits) -> double (64bits)
void LD2D(void* ld, void* d)
{
FPU_t result;
#pragma pack(push, 1)
struct {
FPU_t f;
int16_t b;
} val;
#pragma pack(pop)
#if 1
memcpy(&val, ld, 10);
#else
val.f.l.lower = *(uint32_t*)ld;
val.f.l.upper = *(uint32_t*)(char*)(ld+4);
val.b = *(int16_t*)((char*)ld+8);
#endif
int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64);
int32_t exp64final = exp64&0x7ff;
// do specific value first (0, infinite...)
// bit 63 is "integer part"
// bit 62 is sign
if((uint32_t)(val.b&0x7fff)==0x7fff) {
// infinity and nans
int t = 0; //nan
switch((val.f.l.upper>>30)) {
case 0: if((val.f.l.upper&(1<<29))==0) t = 1;
break;
case 2: if((val.f.l.upper&(1<<29))==0) t = 1;
break;
}
if(t) { // infinite
result.d = HUGE_VAL;
} else { // NaN
result.l.upper = 0x7ff << 20;
result.l.lower = 0;
}
if(val.b&0x8000)
result.l.upper |= 0x80000000;
*(uint64_t*)d = result.ll;
return;
}
if(((uint32_t)(val.b&0x7fff)==0) || (exp64<=0)) {
//if(val.f.ll==0)
// zero
//if(val.f.ll!=0)
// denormal, but that's to small value for double
uint64_t r = 0;
if(val.b&0x8000)
r |= 0x8000000000000000LL;
*(uint64_t*)d = r;
return;
}
if(exp64>=0x7ff) {
// to big value...
result.d = HUGE_VAL;
if(val.b&0x8000)
result.l.upper |= 0x80000000;
*(uint64_t*)d = result.ll;
return;
}
uint64_t mant64 = (val.f.ll >> 11) & 0xfffffffffffffLL;
uint32_t sign = (val.b&0x8000)?1:0;
result.ll = mant64;
result.l.upper |= (sign <<31)|((exp64final&0x7ff) << 20);
*(uint64_t*)d = result.ll;
}
// double (64bits) -> long double (80bits)
void D2LD(void* d, void* ld)
{
#pragma pack(push, 1)
struct {
FPU_t f;
int16_t b;
} val;
#pragma pack(pop)
FPU_t s;
s.ll = *(uint64_t*)d; // use memcpy to avoid risk of Bus Error?
// do special value first
if((s.ll&0x7fffffffffffffffLL)==0) {
// zero...
val.f.ll = 0;
if(s.l.upper&0x8000)
val.b = 0x8000;
else
val.b = 0;
memcpy(ld, &val, 10);
return;
}
int32_t sign80 = (s.l.upper&0x80000000)?1:0;
int32_t exp80 = s.l.upper&0x7ff00000;
int32_t exp80final = (exp80>>20);
int64_t mant80 = s.ll&0x000fffffffffffffLL;
int64_t mant80final = (mant80 << 11);
if(exp80final==0x7ff) {
// NaN and Infinite
exp80final = 0x7fff;
if(mant80==0x0)
mant80final = 0x8000000000000000LL; //infinity
else
mant80final = 0xc000000000000000LL; //(quiet)NaN
} else {
if(exp80!=0){
mant80final |= 0x8000000000000000LL;
exp80final += (BIAS80 - BIAS64);
}
}
val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
val.f.ll = mant80final;
memcpy(ld, &val, 10);
/*memcpy(ld, &f.ll, 8);
memcpy((char*)ld + 8, &val.b, 2);*/
}
double FromLD(void* ld)
{
double ret;
LD2D(ld, &ret);
return ret;
}
void fpu_loadenv(x64emu_t* emu, char* p, int b16)
{
emu->cw = *(uint16_t*)p;
p+=(b16)?2:4;
emu->sw.x16 = *(uint16_t*)p;
emu->top = emu->sw.f.F87_TOP;
p+=(b16)?2:4;
// tagword: 2bits*8
// tags... (only full = 0b11 / free = 0b00)
uint16_t tags = *(uint16_t*)p;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = (tags>>(i*2))&0b11;
// intruction pointer: 16bits
// data (operand) pointer: 16bits
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
}
void fpu_savenv(x64emu_t* emu, char* p, int b16)
{
emu->sw.f.F87_TOP = emu->top&7;
*(uint16_t*)p = emu->cw;
p+=2;
if(!b16) {*(uint16_t*)p = 0; p+=2;}
*(uint16_t*)p = emu->sw.x16;
p+=2;
if(!b16) {*(uint16_t*)p = 0; p+=2;}
// tagword: 2bits*8
// tags...
uint16_t tags = 0;
for (int i=0; i<8; ++i)
tags |= (emu->p_regs[i].tag)<<(i*2);
*(uint16_t*)p = tags;
// other stuff are not pushed....
}
typedef struct xsave_s {
uint16_t ControlWord; /* 000 */
uint16_t StatusWord; /* 002 */
uint8_t TagWord; /* 004 */
uint8_t Reserved1; /* 005 */
uint16_t ErrorOpcode; /* 006 */
uint32_t ErrorOffset; /* 008 */
uint16_t ErrorSelector; /* 00c */
uint16_t Reserved2; /* 00e */
uint32_t DataOffset; /* 010 */
uint16_t DataSelector; /* 014 */
uint16_t Reserved3; /* 016 */
uint32_t MxCsr; /* 018 */
uint32_t MxCsr_Mask; /* 01c */
sse_regs_t FloatRegisters[8];/* 020 */ // fpu/mmx are store in 128bits here
sse_regs_t XmmRegisters[16]; /* 0a0 */
uint8_t Reserved4[96]; /* 1a0 */
} xsave_t;
void fpu_fxsave(x64emu_t* emu, void* ed)
{
xsave_t *p = (xsave_t*)ed;
// should save flags & all
emu->sw.f.F87_TOP = emu->top&7;
p->ControlWord = emu->cw;
p->StatusWord = emu->sw.x16;
uint8_t tags = 0;
for (int i=0; i<8; ++i)
tags |= ((emu->p_regs[i].tag)<<(i*2)==0b11)?0:1;
p->TagWord = tags;
p->ErrorOpcode = 0;
p->ErrorOffset = 0;
p->ErrorSelector = 0;
p->DataOffset = 0;
p->DataSelector = 0;
p->MxCsr = 0;
p->MxCsr_Mask = 0;
// copy MMX regs...
for(int i=0; i<8; ++i)
memcpy(&p->FloatRegisters[i].q[0], &emu->mmx[0], sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
// put also FPU regs in a reserved area... on XMM 8-15
for(int i=0; i<8; ++i)
memcpy(&p->XmmRegisters[8+i].q[0], &emu->fpu[0], sizeof(emu->fpu[0]));
// put a magic sign in reserved area, box86 specific
((unsigned int *)p->Reserved4)[11] = 0x50515253;
}
void fpu_fxrstor(x64emu_t* emu, void* ed)
{
xsave_t *p = (xsave_t*)ed;
emu->cw = p->ControlWord;
emu->sw.x16 = p->StatusWord;
emu->top = emu->sw.f.F87_TOP;
uint8_t tags = p->TagWord;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
// check the box86 magic sign in reserved area
if(((unsigned int *)p->Reserved4)[11] == 0x50515253) {
// also FPU regs where a reserved area... on XMM 8-15?
for(int i=0; i<8; ++i)
memcpy(&emu->fpu[0], &p->XmmRegisters[8+i].q[0], sizeof(emu->fpu[0]));
} else {
// copy the mmx to fpu...
for(int i=0; i<8; ++i)
memcpy(&emu->fpu[0], &emu->mmx[i], sizeof(emu->mmx[0]));
}
}

201
src/emu/x87emu_private.h Executable file
View File

@ -0,0 +1,201 @@
#ifndef __X87RUN_PRIVATE_H_
#define __X87RUN_PRIVATE_H_
#include <stdint.h>
#include <math.h>
#include "regs.h"
#include "x64run_private.h"
#include "debug.h"
typedef struct x64emu_s x64emu_t;
#define PI 3.14159265358979323846
#define L2E 1.4426950408889634
#define L2T 3.3219280948873623
#define LN2 0.69314718055994531
#define LG2 0.3010299956639812
//void Run66D9(x64emu_t *emu);
//void Run66DD(x64emu_t *emu);
//void RunDF(x64emu_t *emu);
#define ST0 emu->fpu[emu->top]
#define ST1 emu->fpu[(emu->top+1)&7]
#define ST(a) emu->fpu[(emu->top+(a))&7]
#define STld(a) emu->fpu_ld[(emu->top+(a))&7]
#define STll(a) emu->fpu_ll[(emu->top+(a))&7]
static inline void fpu_do_push(x64emu_t* emu)
{
int newtop = (emu->top-1)&7;
/*if(emu->p_regs[newtop].tag!=0b11) {// not empty, overflow!
printf_log(LOG_NONE, "Warning: %p: FPU Stack overflow\n", (void*)emu->old_ip); // probably better to raise something
//emu->quit = 1;
return;
}*/
if(emu->fpu_stack<8)
++emu->fpu_stack;
emu->p_regs[newtop].tag = 0; // full
emu->top = newtop;
}
static inline void fpu_do_pop(x64emu_t* emu)
{
int curtop = (emu->top)&7;
/*if(emu->p_regs[(emu->top)&7].tag==0b11) {// underflow
printf_log(LOG_NONE, "Warning: %p: FPU Stack underflow\n", (void*)emu->old_ip); // probably better to raise something
//emu->quit = 1;
return;
}*/
if(emu->fpu_stack>0)
--emu->fpu_stack;
emu->p_regs[curtop].tag = 0b11; // empty
emu->top = (emu->top+1)&7;
}
static inline void fpu_do_free(x64emu_t* emu, int i)
{
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
// check if all empty
for(int i=0; i<8; ++i)
if(emu->p_regs[i].tag != 0b11)
return;
emu->fpu_stack = 0;
}
void reset_fpu(x64emu_t* emu);
static inline void fpu_fcom(x64emu_t* emu, double b)
{
emu->sw.f.F87_C1 = 0;
if(isnan(ST0.d) || isnan(b)) {
emu->sw.f.F87_C0 = 1;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C3 = 1;
} else if (isgreater(ST0.d, b)) {
emu->sw.f.F87_C0 = 0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C3 = 0;
} else if (isless(ST0.d, b)) {
emu->sw.f.F87_C0 = 1;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C3 = 0;
}
else {
emu->sw.f.F87_C0 = 0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C3 = 1;
}
}
static inline void fpu_fcomi(x64emu_t* emu, double b)
{
RESET_FLAGS(emu);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_SF);
emu->sw.f.F87_C1 = 0;
if(isnan(ST0.d) || isnan(b)) {
SET_FLAG(F_CF);
SET_FLAG(F_PF);
SET_FLAG(F_ZF);
} else if (isgreater(ST0.d, b)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CLEAR_FLAG(F_ZF);
} else if (isless(ST0.d, b)) {
SET_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CLEAR_FLAG(F_ZF);
}
else {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
SET_FLAG(F_ZF);
}
}
static inline double fpu_round(x64emu_t* emu, double d) {
if (!isfinite(d))
return d;
switch(emu->round) {
case ROUND_Nearest:
return nearbyint(d);
case ROUND_Down:
return floor(d);
case ROUND_Up:
return ceil(d);
case ROUND_Chop:
default:
return trunc(d);
}
}
static inline void fpu_fxam(x64emu_t* emu) {
emu->sw.f.F87_C1 = (ST0.l.upper&0x80000000)?1:0;
if(!emu->fpu_stack) {
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = 1;
return;
}
if(isinf(ST0.d))
{ // TODO: Unsuported and denormal not analysed...
emu->sw.f.F87_C3 = 0;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C0 = 1;
return;
}
if(isnan(ST0.d))
{ // TODO: Unsuported and denormal not analysed...
emu->sw.f.F87_C3 = 0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = 1;
return;
}
if(ST0.d==0.0)
{
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = 0;
return;
}
// normal...
emu->sw.f.F87_C3 = 0;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C0 = 0;
}
static inline void fpu_ftst(x64emu_t* emu) {
emu->sw.f.F87_C1 = 0;
if(isinf(ST0.d) || isnan(ST0.d))
{ // TODO: Unsuported and denormal not analysed...
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C0 = 1;
return;
}
if(ST0.d==0.0)
{
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = 0;
return;
}
// normal...
emu->sw.f.F87_C3 = 0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (ST0.l.upper&0x80000000)?1:0;
}
void fpu_fbst(x64emu_t* emu, uint8_t* d);
void fpu_fbld(x64emu_t* emu, uint8_t* s);
void fpu_loadenv(x64emu_t* emu, char* p, int b16);
void fpu_savenv(x64emu_t* emu, char* p, int b16);
void fpu_fxsave(x64emu_t* emu, void* ed);
void fpu_fxrstor(x64emu_t* emu, void* ed);
#endif //__X87RUN_PRIVATE_H_

View File

@ -5,6 +5,7 @@
#include "pathcoll.h"
typedef struct elfheader_s elfheader_t;
typedef struct cleanup_s cleanup_t;
typedef void* (*procaddess_t)(const char* name);
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
@ -55,6 +56,12 @@ typedef struct box64context_s {
void* tlsdata; // the initial global tlsdata
int32_t tlssize; // wanted size of tlsdata
uintptr_t *auxval_start;
cleanup_t *cleanups; // atexit functions
int clean_sz;
int clean_cap;
//zydis_dec_t *dec; // trace
uint8_t canary[4];

290
src/include/regs.h Executable file
View File

@ -0,0 +1,290 @@
#ifndef __REGS_H_
#define __REGS_H_
enum {
_AX, _CX, _DX, _BX,
_SP, _BP, _SI, _DI,
_R8, _R9,_R10,_R11,
_R12,_R13,_R14,_R15
};
enum {
_CS, _DS, _SS, _ES, _FS, _GS
};
typedef union {
int64_t sq[1];
uint64_t q[1];
int32_t sdword[2];
uint32_t dword[2];
int16_t sword[4];
uint16_t word[4];
int8_t sbyte[8];
uint8_t byte[8];
} reg64_t;
typedef struct {
uint32_t tag;
} fpu_p_reg_t;
typedef enum {
ROUND_Nearest = 0,
ROUND_Down = 1,
ROUND_Up = 2,
ROUND_Chop = 3
} fpu_round_t;
typedef enum {
d_none = 0,
d_add8,
d_add16,
d_add32,
d_and8,
d_and16,
d_and32,
d_dec8,
d_dec16,
d_dec32,
d_inc8, //10
d_inc16,
d_inc32,
d_imul8,
d_imul16,
d_imul32,
d_or8,
d_or16,
d_or32,
d_mul8,
d_mul16, //20
d_mul32,
d_neg8,
d_neg16,
d_neg32,
d_shl8,
d_shl16,
d_shl32,
d_shr8,
d_shr16,
d_shr32, //30
d_sar8,
d_sar16,
d_sar32,
d_sub8,
d_sub16,
d_sub32,
d_xor8,
d_xor16,
d_xor32,
d_cmp8, //40 // thoses are used only with Dynarec
d_cmp16,
d_cmp32,
d_tst8,
d_tst16,
d_tst32,
d_adc8,
d_adc16,
d_adc32,
d_sbb8,
d_sbb16,
d_sbb32,
d_rol8,
d_rol16,
d_rol32,
d_ror8,
d_ror16,
d_ror32,
d_rcl8,
d_rcl16,
d_rcl32,
d_rcr8,
d_rcr16,
d_rcr32,
d_unknown //46
} defered_flags_t;
#pragma pack(push, 1)
typedef union {
double d;
struct {
uint32_t lower;
uint32_t upper;
} l;
struct {
float lower;
float upper;
} f;
int64_t ll;
} fpu_reg_t;
typedef union {
//long double ld; // works only if 80bits!
struct {
uint64_t lower;
uint16_t upper;
} l;
} longdouble_t;
typedef struct {
#ifdef HAVE_LD80BITS
long double ld;
#else
longdouble_t ld;
#endif
uint64_t ref;
} fpu_ld_t;
typedef struct {
int64_t ll;
int64_t ref;
} fpu_ll_t;
typedef union {
struct __attribute__ ((__packed__)) {
unsigned int _F_CF:1;
unsigned int _F_res1:1;
unsigned int _F_PF:1;
unsigned int _F_res2:1;
unsigned int _F_AF:1;
unsigned int _F_res3:1;
unsigned int _F_ZF:1;
unsigned int _F_SF:1;
unsigned int _F_TF:1;
unsigned int _F_IF:1;
unsigned int _F_DF:1;
unsigned int _F_OF:1;
unsigned int _F_IOPL:2;
unsigned int _F_NT:1;
unsigned int _F_dummy:1;
unsigned int _F_RF:1;
unsigned int _F_VM:1;
unsigned int _F_AC:1;
unsigned int _F_VIF:1;
unsigned int _F_VIP:1;
unsigned int _F_ID:1;
} f;
uint32_t x32;
} x86flags_t;
typedef enum {
F_CF = 0,
F_res1,
F_PF,
F_res2,
F_AF,
F_res3,
F_ZF,
F_SF,
F_TF,
F_IF,
F_DF,
F_OF,
F_IOPL, // double
F_NT = 14,
F_dummy,
F_RF,
F_VM,
F_AC,
F_VIF,
F_VIP,
F_ID,
F_LAST
} flags_names_t;
typedef union {
struct __attribute__ ((__packed__)) {
unsigned int F87_IE:1;
unsigned int F87_DE:1;
unsigned int F87_ZE:1;
unsigned int F87_OE:1;
unsigned int F87_UE:1;
unsigned int F87_PE:1;
unsigned int F87_SF:1;
unsigned int F87_ES:1;
unsigned int F87_C0:1;
unsigned int F87_C1:1;
unsigned int F87_C2:1;
unsigned int F87_TOP:3;
unsigned int F87_C3:1;
unsigned int F87_B:1;
} f;
uint16_t x16;
} x87flags_t;
typedef union {
uint64_t q;
int64_t sq;
uint32_t ud[2];
int32_t sd[2];
uint16_t uw[4];
int16_t sw[4];
uint8_t ub[8];
int8_t sb[8];
} mmx_regs_t;
typedef union {
uint64_t q[2];
int64_t sq[2];
double d[2];
float f[4];
uint32_t ud[4];
int32_t sd[4];
uint16_t uw[8];
int16_t sw[8];
uint8_t ub[16];
int8_t sb[16];
} sse_regs_t;
#pragma pack(pop)
#define R_RIP emu->ip.q[0]
#define R_RAX emu->regs[_AX].q[0]
#define R_RBX emu->regs[_BX].q[0]
#define R_RCX emu->regs[_CX].q[0]
#define R_RDX emu->regs[_DX].q[0]
#define R_RDI emu->regs[_DI].q[0]
#define R_RSI emu->regs[_SI].q[0]
#define R_RSP emu->regs[_SP].q[0]
#define R_RBP emu->regs[_BP].q[0]
#define R_R8 emu->regs[_R8].q[0]
#define R_R9 emu->regs[_R9].q[0]
#define R_R10 emu->regs[_R10].q[0]
#define R_R11 emu->regs[_R11].q[0]
#define R_R12 emu->regs[_R12].q[0]
#define R_R13 emu->regs[_R13].q[0]
#define R_R14 emu->regs[_R14].q[0]
#define R_R15 emu->regs[_R15].q[0]
#define R_EAX emu->regs[_AX].dword[0]
#define R_EBX emu->regs[_BX].dword[0]
#define R_ECX emu->regs[_CX].dword[0]
#define R_EDX emu->regs[_DX].dword[0]
#define R_EDI emu->regs[_DI].dword[0]
#define R_ESI emu->regs[_SI].dword[0]
#define R_ESP emu->regs[_SP].dword[0]
#define R_EBP emu->regs[_BP].dword[0]
#define R_AX emu->regs[_AX].word[0]
#define R_BX emu->regs[_BX].word[0]
#define R_CX emu->regs[_CX].word[0]
#define R_DX emu->regs[_DX].word[0]
#define R_DI emu->regs[_DI].word[0]
#define R_SI emu->regs[_SI].word[0]
#define R_SP emu->regs[_SP].word[0]
#define R_BP emu->regs[_BP].word[0]
#define R_AL emu->regs[_AX].byte[0]
#define R_AH emu->regs[_AX].byte[1]
#define R_CX emu->regs[_CX].word[0]
#define R_CL emu->regs[_CX].byte[0]
#define R_CS emu->segs[_CS]
#define R_DS emu->segs[_DS]
#define R_SS emu->segs[_SS]
#define R_ES emu->segs[_ES]
#define R_FS emu->segs[_FS]
#define R_GS emu->segs[_GS]
#define ACCESS_FLAG(F) emu->eflags.f._##F
#define SET_FLAG(F) emu->eflags.f._##F = 1
#define CLEAR_FLAG(F) emu->eflags.f._##F = 0
#define CONDITIONAL_SET_FLAG(COND, F) emu->eflags.f._##F = (COND)?1:0
#endif //__REGS_H_

63
src/include/x64emu.h Executable file
View File

@ -0,0 +1,63 @@
#ifndef __X86EMU_H_
#define __X86EMU_H_
typedef struct x64emu_s x64emu_t;
typedef struct box64context_s box64context_t;
x64emu_t *NewX86Emu(box64context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack);
x64emu_t *NewX86EmuFromStack(x64emu_t* emu, box64context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack);
void SetupX86Emu(x64emu_t *emu);
void FreeX86Emu(x64emu_t **x64emu);
void FreeX86EmuFromStack(x64emu_t **emu);
void CloneEmu(x64emu_t *newemu, const x64emu_t* emu);
void SetTraceEmu(uintptr_t trace_start, uintptr_t trace_end);
box64context_t* GetEmuContext(x64emu_t* emu);
uint32_t* GetParityTab();
uint32_t GetEAX(x64emu_t *emu);
uint64_t GetRAX(x64emu_t *emu);
void SetEAX(x64emu_t *emu, uint32_t v);
void SetEBX(x64emu_t *emu, uint32_t v);
void SetECX(x64emu_t *emu, uint32_t v);
void SetEDX(x64emu_t *emu, uint32_t v);
void SetEDI(x64emu_t *emu, uint32_t v);
void SetESI(x64emu_t *emu, uint32_t v);
void SetEBP(x64emu_t *emu, uint32_t v);
//void SetESP(x64emu_t *emu, uint32_t v);
void SetRAX(x64emu_t *emu, uint64_t v);
void SetRBX(x64emu_t *emu, uint64_t v);
void SetRCX(x64emu_t *emu, uint64_t v);
void SetRDX(x64emu_t *emu, uint64_t v);
void SetRDI(x64emu_t *emu, uint64_t v);
void SetRSI(x64emu_t *emu, uint64_t v);
void SetRBP(x64emu_t *emu, uint64_t v);
void SetRSP(x64emu_t *emu, uint64_t v);
void SetRIP(x64emu_t *emu, uint64_t v);
void SetFS(x64emu_t *emu, uint16_t v);
uint16_t GetFS(x64emu_t *emu);
uint64_t GetRSP(x64emu_t *emu);
void ResetFlags(x64emu_t *emu);
void ResetSegmentsCache(x64emu_t *emu);
const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip);
void StopEmu(x64emu_t* emu, const char* reason);
//void PushExit(x64emu_t* emu);
//void* GetExit();
void EmuCall(x64emu_t* emu, uintptr_t addr);
void AddCleanup(x64emu_t *emu, void *p);
void AddCleanup1Arg(x64emu_t *emu, void *p, void* a);
void CallCleanup(x64emu_t *emu, void* p);
void CallAllCleanup(x64emu_t *emu);
void UnimpOpcode(x64emu_t* emu);
uint64_t ReadTSC(x64emu_t* emu);
double FromLD(void* ld); // long double (80bits pointer) -> double
void LD2D(void* ld, void* d); // long double (80bits) -> double (64bits)
void D2LD(void* d, void* ld); // double (64bits) -> long double (64bits)
void printFunctionAddr(uintptr_t nextaddr, const char* text);
const char* getAddrFunctionName(uintptr_t addr);
#endif //__X86EMU_H_

14
src/include/x64run.h Executable file
View File

@ -0,0 +1,14 @@
#ifndef __X64RUN_H_
#define __X64RUN_H_
#include <stdint.h>
typedef struct x64emu_s x64emu_t;
//int Run(x64emu_t *emu, int step); // 0 if run was successfull, 1 if error in x86 world
//int DynaRun(x64emu_t *emu);
//uint32_t LibSyscall(x64emu_t *emu);
//void PltResolver(x64emu_t* emu);
//extern uintptr_t pltResolver;
int GetTID();
#endif //__X64RUN_H_

View File

@ -817,6 +817,9 @@ int main(int argc, const char **argv, const char **env) {
FreeCollection(&ld_preload);
return -1;
}
// init x86_64 emu
//x64emu_t *emu = NewX64Emu(my_context, my_context->ep, (uintptr_t)my_context->stack, my_context->stacksz, 0);
return 0;
}