diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-06-17 11:32:56 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-06-17 11:32:56 +0200 |
| commit | bf9e5b8e6e3b42768a787f1a3d3c1f423d1fb38f (patch) | |
| tree | 77430b88dda5a324dcf00055c0ffe90cbef6bdb8 /src | |
| parent | 7e282c9027a3c7e563b4492a0004174b42de0819 (diff) | |
| download | box64-bf9e5b8e6e3b42768a787f1a3d3c1f423d1fb38f.tar.gz box64-bf9e5b8e6e3b42768a787f1a3d3c1f423d1fb38f.zip | |
Added support for creating 32bits selector (no 32bits execution yet)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/box64context.c | 16 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_00.c | 16 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_helper.c | 5 | ||||
| -rwxr-xr-x | src/dynarec/dynarec.c | 6 | ||||
| -rwxr-xr-x | src/emu/x64emu.c | 6 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 24 | ||||
| -rwxr-xr-x | src/emu/x64run_private.h | 1 | ||||
| -rwxr-xr-x | src/emu/x64syscall.c | 2 | ||||
| -rwxr-xr-x | src/emu/x64tls.c | 178 | ||||
| -rwxr-xr-x | src/emu/x86syscall.c | 284 | ||||
| -rwxr-xr-x | src/include/box64context.h | 6 | ||||
| -rwxr-xr-x | src/include/x64tls.h | 2 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 7 | ||||
| -rwxr-xr-x | src/main.c | 2 |
14 files changed, 482 insertions, 73 deletions
diff --git a/src/box64context.c b/src/box64context.c index fc626305..ff65391c 100755 --- a/src/box64context.c +++ b/src/box64context.c @@ -243,6 +243,22 @@ box64context_t *NewBox64Context(int argc) context->canary[getrand(4)] = 0; printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x28, value:%08X\n", *(uint32_t*)context->canary); + // init segments + for(int i=0; i<16; i++) { + context->segtls[i].limit = (uintptr_t)-1LL; + } + context->segtls[10].key_init = 0; // 0x53 selector + context->segtls[10].present = 1; + context->segtls[8].key_init = 0; // 0x43 selector + context->segtls[8].present = 1; + context->segtls[6].key_init = 0; // 0x33 selector + context->segtls[6].present = 1; + context->segtls[5].key_init = 0; // 0x2b selector + context->segtls[5].present = 1; + context->segtls[4].key_init = 0; // 0x23 selector + context->segtls[4].present = 1; + context->segtls[4].is32bits = 1; + initAllHelpers(context); return context; diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index e33b2b01..2d621ef6 100755 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1816,6 +1816,22 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(box64_wine && u8==0x2D) { // lets do nothing MESSAGE(LOG_INFO, "INT 2D Windows anti-debug hack\n"); + } else if (u8==0x80) { + INST_NAME("32bits SYSCALL"); + NOTEST(x1); + SMEND(); + GETIP(addr); + STORE_XEMU_CALL(xRIP); + CALL_S(x86Syscall, -1); + LOAD_XEMU_CALL(xRIP); + TABLE64(x3, addr); // expected return address + CMPSx_REG(xRIP, x3); + B_MARK(cNE); + LDRw_U12(w1, xEmu, offsetof(x64emu_t, quit)); + CBZw_NEXT(w1); + MARK; + LOAD_XEMU_REM(); + jump_to_epilog(dyn, 0, xRIP, ninst); } else { SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state GETIP(ip); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 29442c1f..e141655a 100755 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -545,9 +545,8 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits) // POP CS POP1(x2); STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS])); - MOVZw(x1, 0); - STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_CS])); - STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_SS])); + STRx_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS])); + STRx_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS])); // POP EFLAGS POP1(xFlags); MOV32w(x1, 0x3F7FD7); diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c index 05d5b5ad..e430fa04 100755 --- a/src/dynarec/dynarec.c +++ b/src/dynarec/dynarec.c @@ -121,7 +121,8 @@ void DynaCall(x64emu_t* emu, uintptr_t addr) R_RIP = addr; emu->df = d_none; while(!emu->quit) { - dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1); + int is32bits = (emu->segs[_CS]==0x23); + dynablock_t* block = (skip || is32bits)?NULL:DBGetBlock(emu, R_RIP, 1); if(!block || !block->block || !block->done) { skip = 0; // no block, of block doesn't have DynaRec content (yet, temp is not null) @@ -208,7 +209,8 @@ int DynaRun(x64emu_t* emu) #ifdef DYNAREC else { while(!emu->quit) { - dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1); + int is32bits = (emu->segs[_CS]==0x23); + dynablock_t* block = (skip || is32bits)?NULL:DBGetBlock(emu, R_RIP, 1); if(!block || !block->block || !block->done) { skip = 0; // no block, of block doesn't have DynaRec content (yet, temp is not null) diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index 620bea97..05ec337f 100755 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -75,9 +75,9 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s 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] = 0x33; + emu->segs[_CS] = 0x33; + emu->segs[_DS] = emu->segs[_ES] = emu->segs[_SS] = 0x2b; + emu->segs[_FS] = 0x43; emu->segs[_GS] = default_gs; // setup fpu regs reset_fpu(emu); diff --git a/src/emu/x64run.c b/src/emu/x64run.c index c6523ed7..016e4922 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -52,6 +52,12 @@ int Run(x64emu_t *emu, int step) rex_t rex; int rep; // 0 none, 1=F2 prefix, 2=F3 prefix int unimp = 0; + int is32bits = (emu->segs[_CS]==0x23); + if(is32bits) { + printf_log(LOG_INFO, "Error, 32bits execution not yet supported\n"); + emu->quit = 1; + return 0; + } if(emu->quit) return 0; @@ -62,7 +68,7 @@ int Run(x64emu_t *emu, int step) return 0; } //ref opcode: http://ref.x64asm.net/geek32.html#xA1 - printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)addr, (void*)R_RSP); + printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p is32bits=%D\n", emu, (void*)addr, (void*)R_RSP, is32bits); x64emurun: #ifndef TEST_INTERPRETER @@ -89,10 +95,11 @@ x64emurun: while((opcode==0x3E) || (opcode==0x26)) //Branch Taken Hint ignored opcode = F8; rex.rex = 0; - while(opcode>=0x40 && opcode<=0x4f) { - rex.rex = opcode; - opcode = F8; - } + if(!is32bits) + while(opcode>=0x40 && opcode<=0x4f) { + rex.rex = opcode; + opcode = F8; + } switch(opcode) { @@ -1158,6 +1165,12 @@ x64emurun: if(box64_wine && tmp8u==0x2D) { // lets ignore the INT 2D printf_log(LOG_DEBUG, "INT 2D called\n"); + } else if (tmp8u==0x80) { + // 32bits syscall + #ifndef TEST_INTERPRETER + x86Syscall(emu); + STEP; + #endif } else { #ifndef TEST_INTERPRETER emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); @@ -1681,6 +1694,7 @@ x64emurun: fini: +if(emu->segs[_CS]!=0x33) 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); if(unimp) { diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index 23750022..37947164 100755 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -147,6 +147,7 @@ uintptr_t TestF30F(x64test_t *test, rex_t rex, uintptr_t addr); void x64Syscall(x64emu_t *emu); void x64Int3(x64emu_t* emu, uintptr_t* addr); x64emu_t* x64emu_fork(x64emu_t* e, int forktype); +void x86Syscall(x64emu_t *emu); //32bits syscall uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg); #define GetGSBaseEmu(emu) GetSegmentBaseEmu(emu, _GS) diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c index 242184b3..4f9d6c88 100755 --- a/src/emu/x64syscall.c +++ b/src/emu/x64syscall.c @@ -77,7 +77,7 @@ typedef struct scwrap_s { int nbpars; } scwrap_t; -scwrap_t syscallwrap[] = { +static scwrap_t syscallwrap[] = { //{ 0, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc //{ 1, __NR_write, 3 }, // same //{ 2, __NR_open, 3 }, // flags need transformation diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c index 4673b4a3..af7c4aa0 100755 --- a/src/emu/x64tls.c +++ b/src/emu/x64tls.c @@ -15,7 +15,7 @@ typedef struct thread_area_s { int entry_number; - uintptr_t base_addr; + uintptr_t base_addr; unsigned int limit; unsigned int seg_32bit:1; unsigned int contents:2; @@ -24,28 +24,77 @@ typedef struct thread_area_s unsigned int seg_not_present:1; unsigned int useable:1; } thread_area_t; +typedef struct thread_area_32_s +{ + int entry_number; + uint32_t base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; +} thread_area_32_t; -static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT; -static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT; -static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT; -static pthread_once_t thread_key_once3 = PTHREAD_ONCE_INIT; +uint32_t my_set_thread_area(thread_area_t* td) +{ + printf_log(/*LOG_DEBUG*/LOG_NONE, "set_thread_area(%p[%d/base=%p/limit=%u/32bits:%u/%u/%u...])\n", td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only); -static void thread_key_alloc0() { - pthread_key_create(&my_context->segtls[0].key, NULL); -} -static void thread_key_alloc1() { - pthread_key_create(&my_context->segtls[1].key, NULL); -} -static void thread_key_alloc2() { - pthread_key_create(&my_context->segtls[2].key, NULL); -} -static void thread_key_alloc3() { - pthread_key_create(&my_context->segtls[3].key, NULL); + int isempty = 0; + // first, check if the "user_desc", here td, is "empty" + if(td->read_exec_only==1 && td->seg_not_present==1) + if( !td->base_addr + && !td->limit + && !td->seg_32bit + && !td->contents + && !td->limit_in_pages + && !td->useable) + isempty = 1; + int idx = td->entry_number; + if(idx==-1) { + // find a free one + for (int i=9; i<15 && idx==-1; ++i) + if(!my_context->segtls[i].present) + idx=i; + if(idx==-1) { + errno = ESRCH; + return (uint32_t)-1; + } + td->entry_number = idx; + } + if(isempty && (td->entry_number<9 || td->entry_number>15)) { + errno = EINVAL; + return (uint32_t)-1; + } + if(isempty) { + memset(&my_context->segtls[td->entry_number], 0, sizeof(base_segment_t)); + return 0; + } + if((idx<9 || idx>15)) { + errno = EINVAL; + return (uint32_t)-1; + } + + my_context->segtls[idx].base = td->base_addr; + my_context->segtls[idx].limit = td->limit; + my_context->segtls[idx].present = 1; + my_context->segtls[idx].is32bits = 0; + if(!my_context->segtls[idx].key_init) { + pthread_key_create(&my_context->segtls[idx].key, NULL); + my_context->segtls[idx].key_init = 1; + } + + pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base); + + ResetSegmentsCache(thread_get_emu()); + + return 0; } -uint32_t my_set_thread_area(thread_area_t* td) +uint32_t my_set_thread_area_32(thread_area_32_t* td) { - printf_log(LOG_DEBUG, "set_thread_area(%p[%d/base=%p/limit=%u/32bits:%u/%u/%u...])\n", td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only); + printf_log(LOG_DEBUG, "set_thread_area(%p[%d/base=%p/limit=%u/32bits:%u/%u/%u...])\n", td, td->entry_number, (void*)(uintptr_t)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only); int isempty = 0; // first, check if the "user_desc", here td, is "empty" @@ -60,39 +109,38 @@ uint32_t my_set_thread_area(thread_area_t* td) int idx = td->entry_number; if(idx==-1) { // find a free one - for (int i=0; i<3 && idx==-1; ++i) + for (int i=9; i<15 && idx==-1; ++i) if(!my_context->segtls[i].present) idx=i; if(idx==-1) { errno = ESRCH; return (uint32_t)-1; } - idx+=7; td->entry_number = idx; } - if(isempty && (td->entry_number<7 || td->entry_number>7+2)) { + if(isempty && (td->entry_number<9 || td->entry_number>15)) { errno = EINVAL; return (uint32_t)-1; } if(isempty) { - memset(&my_context->segtls[td->entry_number-7], 0, sizeof(base_segment_t)); + memset(&my_context->segtls[td->entry_number], 0, sizeof(base_segment_t)); return 0; } - if((idx<7 || idx>7+2)) { + if((idx<9 || idx>15)) { errno = EINVAL; return (uint32_t)-1; } - my_context->segtls[idx-7].base = td->base_addr; - my_context->segtls[idx-7].limit = td->limit; - my_context->segtls[idx-7].present = 1; - switch (idx-7) { - case 0: pthread_once(&thread_key_once0, thread_key_alloc0); break; - case 1: pthread_once(&thread_key_once1, thread_key_alloc1); break; - case 2: pthread_once(&thread_key_once2, thread_key_alloc2); break; + my_context->segtls[idx].base = td->base_addr; + my_context->segtls[idx].limit = td->limit; + my_context->segtls[idx].present = 1; + my_context->segtls[idx].is32bits = 1; + if(!my_context->segtls[idx].key_init) { + pthread_key_create(&my_context->segtls[idx].key, NULL); + my_context->segtls[idx].key_init = 1; } - pthread_setspecific(my_context->segtls[idx-7].key, (void*)my_context->segtls[idx-7].base); + pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base); ResetSegmentsCache(thread_get_emu()); @@ -116,8 +164,8 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size) return (uint32_t)-1; } - int idx = td->entry_number - 7; - if(idx<0 || idx>2) { + int idx = td->entry_number; + if(idx<9 || idx>15) { errno = EINVAL; return (uint32_t)-1; } @@ -133,35 +181,52 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size) return 0; } +int GetTID(); int my_arch_prctl(x64emu_t *emu, int code, void* addr) { - //printf_log(LOG_INFO, "%04d| arch_prctl(0x%x, %p) (RSP=%p)\n", GetTID(), code, addr,(void*)R_RSP); + printf_log(LOG_DEBUG, "%04d| arch_prctl(0x%x, %p) (RSP=%p, FS=0x%x, GS=0x%x)\n", GetTID(), code, addr,(void*)R_RSP, emu->segs[_FS], emu->segs[_GS]); #define ARCH_SET_GS 0x1001 #define ARCH_SET_FS 0x1002 #define ARCH_GET_FS 0x1003 #define ARCH_GET_GS 0x1004 + int seg = 0; + int idx = 0; switch(code) { case ARCH_GET_GS: *(void**)addr = GetSegmentBase(emu->segs[_GS]); return 0; - case ARCH_SET_GS: - pthread_once(&thread_key_once3, thread_key_alloc3); - if(emu->segs[_GS]!=(0xa<<3)) - emu->segs[_GS] = 0xa<<3; // should not move! - emu->segs_serial[_GS] = 0; - my_context->segtls[3].base = (uintptr_t)addr; - my_context->segtls[3].limit = 0; - my_context->segtls[3].present = 1; - pthread_setspecific(my_context->segtls[3].key, (void*)my_context->segtls[3].base); - ResetSegmentsCache(emu); - return 0; case ARCH_GET_FS: *(void**)addr = GetSegmentBase(emu->segs[_FS]); return 0; + case ARCH_SET_FS: + case ARCH_SET_GS: + seg=(code==ARCH_SET_FS)?_FS:_GS; + if(emu->segs[seg]==0) { + errno = EINVAL; + return -1; + } + idx = emu->segs[seg] >> 3; + if(idx<0 || idx>15) { + errno = EINVAL; + return -1; + } + emu->segs_serial[seg] = 0; + my_context->segtls[idx].base = (uintptr_t)addr; + my_context->segtls[idx].limit = 0; + my_context->segtls[idx].present = 1; + if(idx>8 && !my_context->segtls[idx].key_init) { + pthread_key_create(&my_context->segtls[idx].key, NULL); + my_context->segtls[idx].key_init = 1; + } + if(my_context->segtls[idx].key_init) + pthread_setspecific(my_context->segtls[idx].key, addr); + ResetSegmentsCache(emu); + return 0; } // other are unsupported printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr); + errno = ENOSYS; return -1; } @@ -286,7 +351,7 @@ tlsdatasize_t* getTLSData(box64context_t *context) return ptr; } -static void* GetSeg33Base() +static void* GetSeg43Base() { tlsdatasize_t* ptr = getTLSData(my_context); return ptr->data; @@ -299,16 +364,17 @@ void* GetSegmentBase(uint32_t desc) return NULL; } int base = desc>>3; - if(base==0xe || base==0xf) - return NULL; // regular value... - if(base==0x6) - return GetSeg33Base(); - - if(base>6 && base<11 && my_context->segtls[base-7].present) { - void* ptr = pthread_getspecific(my_context->segtls[base-7].key); + if(base==0x8 && !my_context->segtls[base].key_init) + return GetSeg43Base(); + if(base>15) { + printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc); + return NULL; + } + if(my_context->segtls[base].key_init) { + void* ptr = pthread_getspecific(my_context->segtls[base].key); return ptr; } - - printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc); - return NULL; + + void* ptr = (void*)my_context->segtls[base].base; + return ptr; } diff --git a/src/emu/x86syscall.c b/src/emu/x86syscall.c new file mode 100755 index 00000000..c1f7bce2 --- /dev/null +++ b/src/emu/x86syscall.c @@ -0,0 +1,284 @@ +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/syscall.h> /* For SYS_xxx definitions */ +#include <unistd.h> +#include <time.h> +#include <sys/mman.h> +#include <sys/select.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <asm/stat.h> +#include <errno.h> +#include <sched.h> +#include <sys/wait.h> +#include <sys/utsname.h> +#ifndef __NR_socketcall +#include <linux/net.h> +#include <sys/socket.h> +#endif +#include <sys/resource.h> +#include <poll.h> + +#include "debug.h" +#include "box64stack.h" +#include "x64emu.h" +#include "x64run.h" +#include "x64emu_private.h" +#include "x64trace.h" +#include "myalign.h" +#include "box64context.h" +#include "callback.h" +#include "signals.h" +#include "x64tls.h" + + +// Syscall table for x86_64 can be found +typedef struct scwrap_s { + uint32_t x86s; + int nats; + int nbpars; +} scwrap_t; + +static scwrap_t syscallwrap[] = { + //{ 2, __NR_fork, 1 }, + //{ 3, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc + //{ 4, __NR_write, 3 }, // same + //{ 5, __NR_open, 3 }, // flags need transformation + //{ 6, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc + //{ 7, __NR_waitpid, 3 }, + //{ 10, __NR_unlink, 1 }, + //{ 12, __NR_chdir, 1 }, + //{ 13, __NR_time, 1 }, + //{ 15, __NR_chmod, 2 }, + //{ 19, __NR_lseek, 3 }, + //{ 20, __NR_getpid, 0 }, + //{ 24, __NR_getuid, 0 }, + //{ 33, __NR_access, 2 }, + //{ 37, __NR_kill, 2 }, + //{ 38, __NR_rename, 2 }, + //{ 39, __NR_mkdir, 2 }, + //{ 40, __NR_rmdir, 1 }, + //{ 41, __NR_dup, 1 }, + //{ 42, __NR_pipe, 1 }, + //{ 45, __NR_brk, 1 }, + //{ 47, __NR_getgid, 0 }, + //{ 49, __NR_geteuid, 0 }, + //{ 50, __NR_getegid, 0 }, + //{ 54, __NR_ioctl, 3 }, // should be wrapped to allow SA_RESTART handling by libc, but syscall is only 3 arguments, ioctl can be 5 + //{ 55, __NR_fcntl, 3 }, // wrapped to allow filter of F_SETFD + //{ 60, __NR_umask, 1 }, + //{ 63, __NR_dup2, 2 }, + //{ 64, __NR_getppid, 0 }, + //{ 66, __NR_setsid, 0 }, + //{ 75, __NR_setrlimit, 2 }, + //{ 76, __NR_getrlimit, 2 }, + //{ 77, __NR_getrusage, 2 }, + //{ 78, __NR_gettimeofday, 2 }, + //{ 83, __NR_symlink, 2 }, + //{ 82, __NR_select, 5 }, + //{ 85, __NR_readlink, 3 }, + //{ 91, __NR_munmap, 2 }, + //{ 94, __NR_fchmod, 2 }, + //{ 99, __NR_statfs, 2 }, + //{ 102, __NR_socketcall, 2 }, + //{ 104, __NR_setitimer, 3 }, + //{ 105, __NR_getitimer, 2 }, + //{ 106, __NR_newstat, 2 }, + //{ 106, __NR_stat, 2 }, + //{ 107, __NR_newlstat, 2 }, + //{ 107, __NR_lstat, 2 }, + //{ 108, __NR_newfstat, 2 }, + //{ 108, __NR_fstat, 2 }, + //{ 109, __NR_olduname, 1 }, + //{ 110, __NR_iopl, 1 }, + //{ 114, __NR_wait4, 4 }, //TODO: check struct rusage alignment + //{ 117, __NR_ipc, 6 }, + //{ 119, __NR_sigreturn, 0}, + //{ 120, __NR_clone, 5 }, // need works + //{ 122, __NR_uname, 1 }, + //{ 123, __NR_modify_ldt }, + //{ 125, __NR_mprotect, 3 }, + //{ 136, __NR_personality, 1 }, + //{ 140, __NR__llseek, 5 }, + //{ 141, __NR_getdents, 3 }, + //{ 142, __NR__newselect, 5 }, + //{ 143, __NR_flock, 2 }, + //{ 144, __NR_msync, 3 }, + //{ 145, __NR_readv, 3 }, + //{ 146, __NR_writev, 3 }, + //{ 148, __NR_fdatasync, 1 }, + //{ 149, __NR__sysctl, 1 }, // need wrapping? + //{ 156, __NR_sched_setscheduler, 3 }, + //{ 157, __NR_sched_getscheduler, 1 }, + //{ 158, __NR_sched_yield, 0 }, + //{ 162, __NR_nanosleep, 2 }, + //{ 164, __NR_setresuid, 3 }, + //{ 168, __NR_poll, 3 }, // wrapped to allow SA_RESTART wrapping by libc + //{ 172, __NR_prctl, 5 }, + //{ 173, __NR_rt_sigreturn, 0 }, + //{ 175, __NR_rt_sigprocmask, 4 }, + //{ 179, __NR_rt_sigsuspend, 2 }, + //{ 183, __NR_getcwd, 2 }, + //{ 184, __NR_capget, 2}, + //{ 185, __NR_capset, 2}, + //{ 186, __NR_sigaltstack, 2 }, // neeed wrap or something? + //{ 191, __NR_ugetrlimit, 2 }, +// { 192, __NR_mmap2, 6}, + //{ 195, __NR_stat64, 2 }, // need proprer wrap because of structure size change + //{ 196, __NR_lstat64, 2 }, // need proprer wrap because of structure size change + //{ 197, __NR_fstat64, 2 }, // need proprer wrap because of structure size change + //{ 199, __NR_getuid32, 0 }, + //{ 200, __NR_getgid32, 0 }, + //{ 201, __NR_geteuid32, 0 }, + //{ 202, __NR_getegid32, 0 }, + //{ 208, __NR_setresuid32, 3 }, + //{ 209, __NR_getresuid32, 3 }, + //{ 210, __NR_setresgid32, 3 }, + //{ 211, __NR_getresgid32, 3 }, + //{ 220, __NR_getdents64, 3 }, + //{ 221, __NR_fcntl64, 3 }, + { 224, __NR_gettid, 0 }, + //{ 240, __NR_futex, 6 }, + //{ 241, __NR_sched_setaffinity, 3 }, + //{ 242, __NR_sched_getaffinity, 3 }, + //{ 252, __NR_exit_group, 1 }, + //{ 254, __NR_epoll_create, 1 }, + //{ 255, __NR_epoll_ctl, 4 }, + //{ 256, __NR_epoll_wait, 4 }, + //{ 265, __NR_clock_gettime, 2 }, + //{ 266, __NR_clock_getres, 2 }, + //{ 270, __NR_tgkill, 3 }, + //{ 271, __NR_utimes, 2 }, + //{ 291, __NR_inotify_init, 0}, + //{ 292, __NR_inotify_add_watch, 3}, + //{ 293, __NR_inotify_rm_watch, 2}, + //{ 311, __NR_set_robust_list, 2 }, + //{ 312, __NR_get_robust_list, 4 }, + //{ 318, __NR_getcpu, 3}, + //{ 328, __NR_eventfd2, 2}, + //{ 329, __NR_epoll_create1, 1 }, + //{ 331, __NR_pipe2, 2}, + //{ 332, __NR_inotify_init1, 1}, + //{ 355, __NR_getrandom, 3 }, + //{ 356, __NR_memfd_create, 2}, + //{ 449, __NR_futex_waitv, 5}, +}; + +struct mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +#undef st_atime +#undef st_ctime +#undef st_mtime + +struct x64_pt_regs { + long ebx; + long ecx; + long edx; + long esi; + long edi; + long ebp; + long eax; + int xds; + int xes; + int xfs; + int xgs; + long orig_eax; + long eip; + int xcs; + long eflags; + long esp; + int xss; +}; + +#ifndef __NR_olduname +struct oldold_utsname { + char sysname[9]; + char nodename[9]; + char release[9]; + char version[9]; + char machine[9]; +}; +#endif +struct old_utsname { + char sysname[65]; + char nodename[65]; + char release[65]; + char version[65]; + char machine[65]; +}; + +struct i386_user_desc { + unsigned int entry_number; + unsigned long base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; +}; + +void EXPORT x86Syscall(x64emu_t *emu) +{ + uint32_t s = R_EAX; + printf_log(LOG_DEBUG, "%p: Calling 32bits syscall 0x%02X (%d) %p %p %p %p %p", (void*)R_RIP, s, s, (void*)(uintptr_t)R_EBX, (void*)(uintptr_t)R_ECX, (void*)(uintptr_t)R_EDX, (void*)(uintptr_t)R_ESI, (void*)(uintptr_t)R_EDI); + // check wrapper first + int cnt = sizeof(syscallwrap) / sizeof(scwrap_t); + for (int i=0; i<cnt; i++) { + if(syscallwrap[i].x86s == s) { + int sc = syscallwrap[i].nats; + switch(syscallwrap[i].nbpars) { + case 0: *(int32_t*)&R_EAX = syscall(sc); break; + case 1: *(int32_t*)&R_EAX = syscall(sc, R_EBX); break; + case 2: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX); break; + case 3: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX); break; + case 4: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI); break; + case 5: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break; + case 6: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP); break; + default: + printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars); + emu->quit = 1; + return; + } + if(R_EAX==0xffffffff && errno>0) + R_EAX = (uint32_t)-errno; + printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX); + return; + } + } + switch (s) { + case 1: // sys_exit + emu->quit = 1; + emu->exit = 1; + //R_EAX = syscall(__NR_exit, R_EBX); // the syscall should exit only current thread + R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the thread now + break; + /*case 123: // SYS_modify_ldt + R_EAX = my_modify_ldt(emu, R_EBX, (thread_area_t*)(uintptr_t)R_ECX, R_EDX); + if(R_EAX==0xffffffff && errno>0) + R_EAX = (uint32_t)-errno; + break;*/ + case 243: // set_thread_area + R_EAX = my_set_thread_area_32((thread_area_32_t*)(uintptr_t)R_EBX); + if(R_EAX==0xffffffff && errno>0) + R_EAX = (uint32_t)-errno; + break; + default: + printf_log(LOG_INFO, "Warning: Unsupported Syscall 0x%02Xh (%d)\n", s, s); + R_EAX = (uint32_t)-ENOSYS; + return; + } + printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX); +} diff --git a/src/include/box64context.h b/src/include/box64context.h index 9b38fa83..2f82e010 100755 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -69,8 +69,10 @@ void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name); typedef struct base_segment_s { uintptr_t base; uint64_t limit; - int present; pthread_key_t key; + uint8_t present; + uint8_t is32bits; + uint8_t key_init; } base_segment_t; typedef struct box64context_s { @@ -174,7 +176,7 @@ typedef struct box64context_s { pthread_key_t tlskey; // then tls key to have actual tlsdata void* tlsdata; // the initial global tlsdata int64_t tlssize; // wanted size of tlsdata - base_segment_t segtls[4]; // only handling 0/1/2 descriptors (3 is internal use) + base_segment_t segtls[16]; uintptr_t *auxval_start; diff --git a/src/include/x64tls.h b/src/include/x64tls.h index 9ca97efb..b99e3bc0 100755 --- a/src/include/x64tls.h +++ b/src/include/x64tls.h @@ -2,8 +2,10 @@ #define __X64_TLS_H__ typedef struct thread_area_s thread_area_t; +typedef struct thread_area_32_s thread_area_32_t; uint32_t my_set_thread_area(thread_area_t* td); +uint32_t my_set_thread_area_32(thread_area_32_t* td); uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size); tlsdatasize_t* getTLSData(box64context_t *context); diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 2bbe6bb2..76fd50eb 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1242,6 +1242,7 @@ exit(-1); } if(log_minimum<=box64_log) { static const char* reg_name[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", " R8", " R9","R10","R11", "R12","R13","R14","R15"}; + static const char* seg_name[] = {"CS", "DS", "SS", "ES", "GS", "FS"}; int shown_regs = 0; #ifdef DYNAREC uint32_t hash = 0; @@ -1263,6 +1264,9 @@ exit(-1); if(!(i%4)) printf_log(log_minimum, "\n"); printf_log(log_minimum, "%s:0x%016llx ", reg_name[i], p->uc_mcontext.regs[10+i]); } + for (int i=0; i<3; ++i) { + printf_log(log_minimum, "%s:0x%x ", seg_name[i], emu->segs[i]); + } } if(rsp!=addr && getProtection((uintptr_t)rsp-4*8) && getProtection((uintptr_t)rsp+4*8)) for (int i=-4; i<4; ++i) { @@ -1275,6 +1279,9 @@ exit(-1); if(!(i%4)) printf_log(log_minimum, "\n"); printf_log(log_minimum, "%s:0x%016llx ", reg_name[i], p->uc_mcontext.__gregs[16+i]); } + for (int i=0; i<3; ++i) { + printf_log(log_minimum, "%s:0x%x ", seg_name[i], emu->segs[i]); + } } if(rsp!=addr && getProtection((uintptr_t)rsp-4*8) && getProtection((uintptr_t)rsp+4*8)) for (int i=-4; i<4; ++i) { diff --git a/src/main.c b/src/main.c index b3983abd..9fb48f7d 100755 --- a/src/main.c +++ b/src/main.c @@ -121,7 +121,7 @@ int box64_isglibc234 = 0; char* box64_libGL = NULL; uintptr_t fmod_smc_start = 0; uintptr_t fmod_smc_end = 0; -uint32_t default_gs = 0xa<<3; +uint32_t default_gs = 0x53; int jit_gdb = 0; int box64_tcmalloc_minimal = 0; |