diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-06 17:54:47 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-06 17:54:47 +0100 |
| commit | 8b456d5a60536fb94108f504602feaaec9fc71c1 (patch) | |
| tree | 32a03219266631f44fbc9ec677022cbebdbf2831 /src | |
| parent | 1b350d24c30657c8ea8afd4f3aeeda960a0a2357 (diff) | |
| download | box64-8b456d5a60536fb94108f504602feaaec9fc71c1.tar.gz box64-8b456d5a60536fb94108f504602feaaec9fc71c1.zip | |
Some work on TLS (not sure it's a good idea to separate 64 FS: prefix there)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/box64context.c | 4 | ||||
| -rw-r--r-- | src/emu/modrm.h | 18 | ||||
| -rwxr-xr-x | src/emu/x64emu.c | 4 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 8 | ||||
| -rw-r--r-- | src/emu/x64run64.c | 96 | ||||
| -rwxr-xr-x | src/emu/x64run_private.c | 48 | ||||
| -rwxr-xr-x | src/emu/x64run_private.h | 4 | ||||
| -rwxr-xr-x | src/emu/x64tls.c | 18 | ||||
| -rwxr-xr-x | src/include/box64context.h | 2 | ||||
| -rwxr-xr-x | src/include/debug.h | 2 | ||||
| -rwxr-xr-x | src/main.c | 2 |
11 files changed, 182 insertions, 24 deletions
diff --git a/src/box64context.c b/src/box64context.c index 4c75e98e..75fb5028 100755 --- a/src/box64context.c +++ b/src/box64context.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); diff --git a/src/emu/modrm.h b/src/emu/modrm.h index af678823..9152dd05 100644 --- a/src/emu/modrm.h +++ b/src/emu/modrm.h @@ -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 diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index 64489f00..80752a0a 100755 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -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); } diff --git a/src/emu/x64run.c b/src/emu/x64run.c index ece834c0..77c6db62 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -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)) { diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c new file mode 100644 index 00000000..92db3f52 --- /dev/null +++ b/src/emu/x64run64.c @@ -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; +} \ No newline at end of file diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 928d531f..a6b900fb 100755 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -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) diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index c2161b3f..b7c7ee5f 100755 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -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); diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c index b76646b5..2396eee6 100755 --- a/src/emu/x64tls.c +++ b/src/emu/x64tls.c @@ -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; } diff --git a/src/include/box64context.h b/src/include/box64context.h index ed8cd118..6e4d9052 100755 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -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]; diff --git a/src/include/debug.h b/src/include/debug.h index 8b440787..873db669 100755 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -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 diff --git a/src/main.c b/src/main.c index d6da7513..2abfc604 100755 --- a/src/main.c +++ b/src/main.c @@ -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; |