diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-06-07 20:06:02 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-06-07 20:06:02 +0200 |
| commit | 508545aa874ac7c8de5fb589bc03e3f45c70adb5 (patch) | |
| tree | 9bde8c750dbd39210a7012d884b05ae33a213c4f /src | |
| parent | 52d86177c5d7e70df4018ec8c9ef7a7da5bf030a (diff) | |
| download | box64-508545aa874ac7c8de5fb589bc03e3f45c70adb5.tar.gz box64-508545aa874ac7c8de5fb589bc03e3f45c70adb5.zip | |
Added suport for arch_prctl syscall, and GL segment handling ([DYNAREC] too)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/dynarec_arm64_00.c | 6 | ||||
| -rw-r--r-- | src/dynarec/dynarec_arm64_64.c | 38 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 2 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 11 | ||||
| -rw-r--r-- | src/emu/x64run64.c | 4 | ||||
| -rwxr-xr-x | src/emu/x64run_private.h | 2 | ||||
| -rwxr-xr-x | src/emu/x64syscall.c | 6 | ||||
| -rwxr-xr-x | src/emu/x64tls.c | 34 | ||||
| -rwxr-xr-x | src/include/box64context.h | 2 | ||||
| -rwxr-xr-x | src/include/x64tls.h | 2 |
10 files changed, 78 insertions, 29 deletions
diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c index 72d4d32b..c8c3a10b 100755 --- a/src/dynarec/dynarec_arm64_00.c +++ b/src/dynarec/dynarec_arm64_00.c @@ -530,9 +530,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 0x64: - addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog); + break; + case 0x65: + addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog); break; - case 0x66: addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; diff --git a/src/dynarec/dynarec_arm64_64.c b/src/dynarec/dynarec_arm64_64.c index e6f52fcc..546c5ff8 100644 --- a/src/dynarec/dynarec_arm64_64.c +++ b/src/dynarec/dynarec_arm64_64.c @@ -24,7 +24,7 @@ #define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3) -uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog) +uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog) { (void)ip; (void)rep; (void)need_epilog; @@ -61,9 +61,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch(opcode) { case 0x03: - INST_NAME("ADD Gd, FS:Ed"); + INST_NAME("ADD Gd, Seg:Ed"); SETFLAGS(X_ALL, SF_SET); - grab_segdata(dyn, addr, ninst, x4, _FS); + grab_segdata(dyn, addr, ninst, x4, seg); nextop = F8; GETGD; GETEDO(x4, 0); @@ -86,7 +86,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin d0 = sse_get_reg(dyn, ninst, x1, ed); VMOVeD(v0, 0, d0, 0); } else { - grab_segdata(dyn, addr, ninst, x4, _FS); + grab_segdata(dyn, addr, ninst, x4, seg); v0 = sse_get_reg_empty(dyn, ninst, x1, gd); addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0); ADDx_REG(x4, x4, ed); @@ -102,7 +102,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3)); VMOVeS(v0, 0, q0, 0); } else { - grab_segdata(dyn, addr, ninst, x4, _FS); + grab_segdata(dyn, addr, ninst, x4, seg); v0 = sse_get_reg_empty(dyn, ninst, x1, gd); addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0); ADDx_REG(x4, x4, ed); @@ -125,7 +125,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin d0 = sse_get_reg(dyn, ninst, x1, ed); VMOVeD(d0, 0, v0, 0); } else { - grab_segdata(dyn, addr, ninst, x4, _FS); + grab_segdata(dyn, addr, ninst, x4, seg); addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0); ADDx_REG(x4, x4, ed); VSTR64_U12(v0, x4, fixedaddress); @@ -140,7 +140,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3)); VMOVeS(q0, 0, v0, 0); } else { - grab_segdata(dyn, addr, ninst, x4, _FS); + grab_segdata(dyn, addr, ninst, x4, seg); addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0); ADDx_REG(x4, x4, ed); VSTR32_U12(v0, x4, fixedaddress); @@ -157,9 +157,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0x33: - INST_NAME("XOR Gd, FS:Ed"); + INST_NAME("XOR Gd, Seg:Ed"); SETFLAGS(X_ALL, SF_SET); - grab_segdata(dyn, addr, ninst, x4, _FS); + grab_segdata(dyn, addr, ninst, x4, seg); nextop = F8; GETGD; GETEDO(x4, 0); @@ -168,7 +168,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x80: nextop = F8; - grab_segdata(dyn, addr, ninst, x1, _FS); + grab_segdata(dyn, addr, ninst, x1, seg); switch((nextop>>3)&7) { case 0: //ADD INST_NAME("ADD Eb, Ib"); @@ -247,7 +247,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x81: case 0x83: nextop = F8; - grab_segdata(dyn, addr, ninst, x6, _FS); + grab_segdata(dyn, addr, ninst, x6, seg); switch((nextop>>3)&7) { case 0: //ADD if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");} @@ -324,8 +324,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0x89: - INST_NAME("MOV FS:Ed, Gd"); - grab_segdata(dyn, addr, ninst, x4, _FS); + INST_NAME("MOV Seg:Ed, Gd"); + grab_segdata(dyn, addr, ninst, x4, seg); nextop=F8; GETGD; if(MODREG) { // reg <= reg @@ -337,8 +337,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0x8B: - INST_NAME("MOV Gd, FS:Ed"); - grab_segdata(dyn, addr, ninst, x4, _FS); + INST_NAME("MOV Gd, Seg:Ed"); + grab_segdata(dyn, addr, ninst, x4, seg); nextop=F8; GETGD; if(MODREG) { // reg <= reg @@ -350,8 +350,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xC6: - INST_NAME("MOV FS:Eb, Ib"); - grab_segdata(dyn, addr, ninst, x4, _FS); + INST_NAME("MOV Seg:Eb, Ib"); + grab_segdata(dyn, addr, ninst, x4, seg); nextop=F8; if(MODREG) { // reg <= u8 u8 = F8; @@ -373,8 +373,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 0xC7: - INST_NAME("MOV FS:Ed, Id"); - grab_segdata(dyn, addr, ninst, x4, _FS); + INST_NAME("MOV Seg:Ed, Id"); + grab_segdata(dyn, addr, ninst, x4, seg); nextop=F8; if(MODREG) { // reg <= i32 i64 = F32S; diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index 7cbad4c3..ec9ca63c 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -871,7 +871,7 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1); uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); -uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog); +uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog); //uintptr_t dynarec64_65(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog); uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); diff --git a/src/emu/x64run.c b/src/emu/x64run.c index d56b3aa2..0ef1e84e 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -241,14 +241,21 @@ x64emurun: GD->sdword[0] = ED->sdword[0]; // meh? break; case 0x64: /* FS: prefix */ - if(Run64(emu, rex)) { + if(Run64(emu, rex, _FS)) { + unimp = 1; + goto fini; + } + if(emu->quit) + goto fini; + break; + case 0x65: /* GS: prefix */ + if(Run64(emu, rex, _GS)) { unimp = 1; goto fini; } if(emu->quit) goto fini; break; - case 0x66: /* 16bits prefix */ if(Run66(emu, rex, rep)) { unimp = 1; diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c index 1708bb79..c7f2fbec 100644 --- a/src/emu/x64run64.c +++ b/src/emu/x64run64.c @@ -22,7 +22,7 @@ #include "modrm.h" -int Run64(x64emu_t *emu, rex_t rex) +int Run64(x64emu_t *emu, rex_t rex, int seg) { uint8_t opcode; uint8_t nextop; @@ -35,7 +35,7 @@ int Run64(x64emu_t *emu, rex_t rex) reg64_t *oped, *opgd; sse_regs_t *opex, *opgx; int rep; - uintptr_t tlsdata = GetFSBaseEmu(emu); + uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg); opcode = F8; // REX prefix before the F0 are ignored diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index 7f4089fc..bcaea031 100755 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -102,7 +102,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 Run64(x64emu_t *emu, rex_t rex, int seg); int Run66(x64emu_t *emu, rex_t rex, int rep); int Run660F(x64emu_t *emu, rex_t rex); int Run6664(x64emu_t *emu, rex_t rex); diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c index c43e1407..126dfb82 100755 --- a/src/emu/x64syscall.c +++ b/src/emu/x64syscall.c @@ -116,6 +116,7 @@ scwrap_t syscallwrap[] = { { 127, __NR_rt_sigpending, 2}, //{ 131, __NR_sigaltstack, 2}, // wrapped to use my_sigaltstack { 157, __NR_prctl, 5 }, // needs wrapping? + //{ 158, __NR_arch_prctl, 2}, //need wrapping { 186, __NR_gettid, 0 }, //0xBA { 200, __NR_tkill, 2 }, #ifdef __NR_time @@ -324,6 +325,9 @@ void EXPORT x64Syscall(x64emu_t *emu) case 131: // sys_sigaltstack R_EAX = (uint32_t)my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI); break; + case 158: // sys_arch_prctl + R_EAX = (uint32_t)my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI); + break; #ifndef __NR_time case 201: // sys_time R_RAX = (uintptr_t)time((void*)R_RDI); @@ -433,6 +437,8 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu) return (uintptr_t)my_readlink(emu,(void*)R_RSI, (void*)R_RDX, (size_t)R_RCX); case 131: // sys_sigaltstack return (uint32_t)my_sigaltstack(emu, (void*)R_RSI, (void*)R_RDX); + case 158: // sys_arch_prctl + return (uint32_t)my_arch_prctl(emu, (int)R_ESI, (void*)R_RDX); #ifndef __NR_time case 201: // sys_time return (uintptr_t)time((void*)R_RSI); diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c index de573a45..59af88fb 100755 --- a/src/emu/x64tls.c +++ b/src/emu/x64tls.c @@ -8,6 +8,7 @@ #include "debug.h" #include "box64context.h" #include "x64emu.h" +#include "x64emu_private.h" #include "x64tls.h" #include "elfloader.h" @@ -27,6 +28,7 @@ typedef struct thread_area_s 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; static void thread_key_alloc0() { pthread_key_create(&my_context->segtls[0].key, NULL); @@ -37,6 +39,9 @@ static void thread_key_alloc1() { 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); +} uint32_t my_set_thread_area(thread_area_t* td) { @@ -128,6 +133,33 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size) return 0; } +int my_arch_prctl(x64emu_t *emu, int code, void* addr) +{ + #define ARCH_SET_GS 0x1001 + #define ARCH_GET_GS 0x1004 + switch(code) { + case ARCH_GET_GS: + *(void**)addr = GetSegmentBase(emu->segs[_GS]); + return 0; + case ARCH_SET_GS: + if(emu->segs[_GS]!=(0xa<<3)) { + pthread_once(&thread_key_once3, thread_key_alloc3); + emu->segs[_GS] = 0xa<<3; + if(!default_gs) + default_gs = 0xa<<3; + } + 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); + return 0; + } + // other are unsupported + printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr); + return -1; +} + + #define POS_TLS 0x200 /* tls record should looks like: @@ -222,7 +254,7 @@ void* GetSegmentBase(uint32_t desc) if(base==0x6) return GetSeg33Base(); - if(base>6 && base<10 && my_context->segtls[base-7].present) { + if(base>6 && base<11 && my_context->segtls[base-7].present) { void* ptr = pthread_getspecific(my_context->segtls[base-7].key); return ptr; } diff --git a/src/include/box64context.h b/src/include/box64context.h index 7ff6d8c0..4a53fed8 100755 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -156,7 +156,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[3]; // only handling 0/1/2 descriptors + base_segment_t segtls[4]; // only handling 0/1/2 descriptors (3 is internal use) uintptr_t *auxval_start; diff --git a/src/include/x64tls.h b/src/include/x64tls.h index 61f58887..f26827c2 100755 --- a/src/include/x64tls.h +++ b/src/include/x64tls.h @@ -10,4 +10,6 @@ void* fillTLSData(box64context_t *context); void* resizeTLSData(box64context_t *context, void* oldptr); void* GetSegmentBase(uint32_t desc); +int my_arch_prctl(x64emu_t *emu, int code, void* addr); + #endif //__X64_TLS_H__ \ No newline at end of file |