Some work on TLS (not sure it's a good idea to separate 64 FS: prefix there)

This commit is contained in:
ptitSeb 2021-03-06 17:54:47 +01:00
parent 1b350d24c3
commit 8b456d5a60
12 changed files with 183 additions and 24 deletions

View File

@ -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"

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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
View 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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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];

View File

@ -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

View File

@ -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;