mirror of
https://github.com/ptitSeb/box64.git
synced 2024-11-24 06:59:53 +00:00
Some work on TLS (not sure it's a good idea to separate 64 FS: prefix there)
This commit is contained in:
parent
1b350d24c3
commit
8b456d5a60
@ -110,6 +110,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/emu/x64primop.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run0f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run64.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run660f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rund9.c"
|
||||
|
@ -107,9 +107,9 @@ box64context_t *NewBox64Context(int argc)
|
||||
pthread_key_create(&context->tlskey, free_tlsdatasize);
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i) context->canary[i] = 1 + getrand(255);
|
||||
for (int i=0; i<8; ++i) context->canary[i] = 1 + getrand(255);
|
||||
context->canary[getrand(4)] = 0;
|
||||
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at GS:0x14, value:%08X\n", *(uint32_t*)context->canary);
|
||||
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x14, value:%08X\n", *(uint32_t*)context->canary);
|
||||
|
||||
initAllHelpers(context);
|
||||
|
||||
|
@ -13,14 +13,16 @@
|
||||
#define STEP
|
||||
#endif
|
||||
|
||||
#define GETED(D) oped=GetEd(emu, rex, nextop, D)
|
||||
#define GETGD opgd=GetGd(emu, rex, nextop)
|
||||
#define GETEB(D) oped=GetEb(emu, rex, nextop, D)
|
||||
#define GETGB opgd=GetGb(emu, rex, nextop)
|
||||
#define GETEW(D) oped=GetEw(emu, rex, nextop, D)
|
||||
#define GETGW opgd=GetGw(emu, rex, nextop)
|
||||
#define GETEX(D) opex=GetEx(emu, rex, nextop, D)
|
||||
#define GETGX opgx=GetGx(emu, rex, nextop)
|
||||
#define GETED(D) oped=GetEd(emu, rex, nextop, D)
|
||||
#define GETED_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
|
||||
#define GETGD opgd=GetGd(emu, rex, nextop)
|
||||
#define GETEB(D) oped=GetEb(emu, rex, nextop, D)
|
||||
#define GETEB_OFFS(D, O) oped=GetEbO(emu, rex, nextop, D, O)
|
||||
#define GETGB opgd=GetGb(emu, rex, nextop)
|
||||
#define GETEW(D) oped=GetEw(emu, rex, nextop, D)
|
||||
#define GETGW opgd=GetGw(emu, rex, nextop)
|
||||
#define GETEX(D) opex=GetEx(emu, rex, nextop, D)
|
||||
#define GETGX opgx=GetGx(emu, rex, nextop)
|
||||
#define ED oped
|
||||
#define GD opgd
|
||||
#define EB oped
|
||||
|
@ -73,8 +73,8 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s
|
||||
// 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;
|
||||
emu->segs[_FS] = 0x33;
|
||||
emu->segs[_GS] = default_gs;
|
||||
// setup fpu regs
|
||||
reset_fpu(emu);
|
||||
}
|
||||
|
@ -237,6 +237,14 @@ x64emurun:
|
||||
else
|
||||
GD->sdword[0] = ED->sdword[0]; // meh?
|
||||
break;
|
||||
case 0x64: /* FS: prefix */
|
||||
if(Run64(emu, rex)) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
|
||||
case 0x66: /* 16bits prefix */
|
||||
if(Run66(emu, rex)) {
|
||||
|
96
src/emu/x64run64.c
Normal file
96
src/emu/x64run64.c
Normal file
@ -0,0 +1,96 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64stack.h"
|
||||
#include "x64emu.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu_private.h"
|
||||
#include "x64run_private.h"
|
||||
#include "x64primop.h"
|
||||
#include "x64trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box64context.h"
|
||||
#include "bridge.h"
|
||||
//#include "signals.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
int Run64(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int16_t tmp16s;
|
||||
uint16_t tmp16u;
|
||||
reg64_t *oped, *opgd;
|
||||
uintptr_t tlsdata = GetFSBaseEmu(emu);
|
||||
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x88: /* MOV Eb,Gb */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(0, tlsdata);
|
||||
GETGB;
|
||||
EB->byte[0] = GB;
|
||||
break;
|
||||
case 0x89: /* MOV Ed,Gd */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
if(rex.w) {
|
||||
ED->q[0] = GD->q[0];
|
||||
} else {
|
||||
//if ED is a reg, than the opcode works like movzx
|
||||
if(MODREG)
|
||||
ED->q[0] = GD->dword[0];
|
||||
else
|
||||
ED->dword[0] = GD->dword[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8B: /* MOV Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->q[0] = ED->q[0];
|
||||
else
|
||||
GD->q[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0xC7: /* MOV Ed,Id */
|
||||
nextop = F8;
|
||||
GETED_OFFS(4, tlsdata);
|
||||
if(rex.w)
|
||||
ED->q[0] = F32S64;
|
||||
else
|
||||
if(MODREG)
|
||||
ED->q[0] = F32;
|
||||
else
|
||||
ED->dword[0] = F32;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1021,6 +1021,32 @@ reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta)
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetECommonO(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base)
|
||||
{
|
||||
if (m<=7) {
|
||||
if(m==0x4) {
|
||||
uint8_t sib = Fetch8(emu);
|
||||
base += ((sib&0x7)==5)?((uint64_t)(int64_t)Fetch32s(emu)):(emu->regs[(sib&0x7)+(rex.b<<3)].q[0]); // base
|
||||
base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sq[0] << (sib>>6));
|
||||
return (reg64_t*)base;
|
||||
} else if (m==0x5) { //disp32
|
||||
base += Fetch32s(emu);
|
||||
return (reg64_t*)(base+R_RIP+delta);
|
||||
}
|
||||
return (reg64_t*)(emu->regs[m+(rex.b<<3)].q[0]);
|
||||
} else {
|
||||
if((m&7)==4) {
|
||||
uint8_t sib = Fetch8(emu);
|
||||
base += emu->regs[(sib&0x7)+(rex.b<<3)].q[0]; // base
|
||||
base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sq[0] << (sib>>6));
|
||||
} else {
|
||||
base += emu->regs[(m&0x7)+(rex.b<<3)].q[0];
|
||||
}
|
||||
base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu);
|
||||
return (reg64_t*)base;
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
// rex ignored here
|
||||
@ -1035,6 +1061,20 @@ reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
|
||||
} else return GetECommon(emu, rex, m, delta);
|
||||
}
|
||||
|
||||
reg64_t* GetEbO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
// rex ignored here
|
||||
uint8_t m = v&0xC7; // filter Eb
|
||||
if(m>=0xC0) {
|
||||
if(rex.rex) {
|
||||
return &emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
int lowhigh = (m&4)>>2;
|
||||
return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //?
|
||||
}
|
||||
} else return GetECommonO(emu, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1043,6 +1083,14 @@ reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
|
||||
} else return GetECommon(emu, rex, m, delta);
|
||||
}
|
||||
|
||||
reg64_t* GetEdO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else return GetECommonO(emu, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
#define GetEw GetEd
|
||||
|
||||
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
|
@ -74,8 +74,11 @@ static inline void Push(x64emu_t *emu, uint64_t v)
|
||||
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
|
||||
|
||||
reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta);
|
||||
reg64_t* GetECommonO(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
|
||||
reg64_t* GetEbO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
|
||||
reg64_t* GetEdO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
#define GetEw GetEd
|
||||
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v);
|
||||
reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset);
|
||||
@ -93,6 +96,7 @@ void UpdateFlags(x64emu_t *emu);
|
||||
#define RESET_FLAGS(emu) emu->df = d_none
|
||||
|
||||
int Run0F(x64emu_t *emu, rex_t rex);
|
||||
int Run64(x64emu_t *emu, rex_t rex);
|
||||
int Run66(x64emu_t *emu, rex_t rex);
|
||||
int Run660F(x64emu_t *emu, rex_t rex);
|
||||
//int Run67(x64emu_t *emu, rex_t rex);
|
||||
|
@ -133,8 +133,8 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
|
||||
static tlsdatasize_t* setupTLSData(box64context_t* context)
|
||||
{
|
||||
// Setup the GS segment:
|
||||
int dtsize = context->elfsize*8;
|
||||
void *ptr = (char*)malloc(context->tlssize+4+POS_TLS+dtsize);
|
||||
int dtsize = context->elfsize*16;
|
||||
void *ptr = (char*)malloc(context->tlssize+8+POS_TLS+dtsize);
|
||||
memcpy(ptr, context->tlsdata, context->tlssize);
|
||||
tlsdatasize_t *data = (tlsdatasize_t*)calloc(1, sizeof(tlsdatasize_t));
|
||||
data->tlsdata = ptr;
|
||||
@ -142,20 +142,20 @@ static tlsdatasize_t* setupTLSData(box64context_t* context)
|
||||
pthread_setspecific(context->tlskey, data);
|
||||
// copy canary...
|
||||
memset((void*)((uintptr_t)ptr+context->tlssize), 0, POS_TLS+dtsize); // set to 0 remining bytes
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, 4); // put canary in place
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, sizeof(void*)); // put canary in place
|
||||
uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, 4);
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, sizeof(void*));
|
||||
uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
|
||||
memcpy((void*)(tlsptr+0x4), &dtp, 4);
|
||||
memcpy((void*)(tlsptr+sizeof(void*)), &dtp, sizeof(void*));
|
||||
if(dtsize) {
|
||||
for (int i=0; i<context->elfsize; ++i) {
|
||||
for (size_t i=0; i<context->elfsize; ++i) {
|
||||
// set pointer
|
||||
dtp = (uintptr_t)ptr + (context->tlssize + GetTLSBase(context->elfs[i]));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8), &dtp, 4);
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8+4), &i, 4); // index
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16), &dtp, sizeof(void*));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16+8), &i, sizeof(void*)); // index
|
||||
}
|
||||
}
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, 4); // address of vsyscall
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, sizeof(void*)); // address of vsyscall
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ typedef struct box64context_s {
|
||||
int atfork_sz;
|
||||
int atfork_cap;
|
||||
|
||||
uint8_t canary[4];
|
||||
uint8_t canary[8];
|
||||
|
||||
uintptr_t signals[MAX_SIGNAL];
|
||||
uintptr_t restorer[MAX_SIGNAL];
|
||||
|
@ -18,7 +18,7 @@ extern int box64_novulkan; // disabling the use of wrapped vulkan
|
||||
extern uintptr_t trace_start, trace_end;
|
||||
extern char* trace_func;
|
||||
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
|
||||
extern uint32_t default_fs;
|
||||
extern uint32_t default_gs;
|
||||
extern int jit_gdb; // launch gdb when a segfault is trapped
|
||||
extern int box64_tcmalloc_minimal; // when using tcmalloc_minimal
|
||||
#define LOG_NONE 0
|
||||
|
@ -53,7 +53,7 @@ uintptr_t trace_start = 0, trace_end = 0;
|
||||
char* trace_func = NULL;
|
||||
uintptr_t fmod_smc_start = 0;
|
||||
uintptr_t fmod_smc_end = 0;
|
||||
uint32_t default_fs = 0;
|
||||
uint32_t default_gs = 0;
|
||||
int jit_gdb = 0;
|
||||
int box64_tcmalloc_minimal = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user