mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-08 10:10:25 -10:00
Added FSGSBASE cpu extension
This commit is contained in:
1 parent
8b72b3bf70
commit
2b070086d1
32 files changed
+186
-105
No files matched your search
@@ -20,7 +20,7 @@ arm64_epilog:
|
||||
stp x26, x27, [x0, (8 * 16)] // put back reg value in emu, including EIP (so x27 must be EIP now)
|
||||
//restore all used register
|
||||
#ifdef _WIN32
|
||||
ldr x18, [x0, 3104]
|
||||
ldr x18, [x0, 3088]
|
||||
#endif
|
||||
add sp, x28, 0
|
||||
//vpop {d8-d15}
|
||||
|
||||
@@ -23,7 +23,7 @@ arm64_next:
|
||||
stp x18, x27, [sp, (8 * 10)] // also save x27(rip) to allow change in LinkNext
|
||||
|
||||
#ifdef _WIN32
|
||||
ldr x18, [x0, 3104]
|
||||
ldr x18, [x0, 3088]
|
||||
#endif
|
||||
mov x1, x27 // xRIP, should not be needed most of the time
|
||||
mov x2, x30 // "from" is in lr, so put in x2
|
||||
|
||||
@@ -1689,6 +1689,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = x1;
|
||||
}
|
||||
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZw_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x8F:
|
||||
|
||||
@@ -1774,6 +1774,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("POP FS");
|
||||
POP1z(x2);
|
||||
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_FS]));
|
||||
CBZw_NEXT(x2);
|
||||
MOV32w(x1, _FS);
|
||||
CALL(const_getsegmentbase, -1);
|
||||
break;
|
||||
case 0xA2:
|
||||
INST_NAME("CPUID");
|
||||
@@ -1857,6 +1860,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("POP GS");
|
||||
POP1z(x2);
|
||||
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_GS]));
|
||||
CBZw_NEXT(x2);
|
||||
MOV32w(x1, _GS);
|
||||
CALL(const_getsegmentbase, -1);
|
||||
break;
|
||||
|
||||
case 0xAB:
|
||||
|
||||
@@ -1006,6 +1006,12 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = x1;
|
||||
}
|
||||
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZw_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x8F:
|
||||
|
||||
@@ -730,6 +730,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = x1;
|
||||
}
|
||||
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZw_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x8F:
|
||||
|
||||
@@ -503,15 +503,32 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0xAE:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
case 1:
|
||||
if(rex.is32bits || !MODREG) {
|
||||
INST_NAME("Illegal AE");
|
||||
FAKEED;
|
||||
UDF(0);
|
||||
} else {
|
||||
if(((nextop>>3)&7)==1) {INST_NAME("RDGSBASE");} else {INST_NAME("RDFSBASE");}
|
||||
ed = TO_NAT((nextop & 7) + (rex.b << 3));
|
||||
int seg = _FS + ((nextop>>3)&7);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
|
||||
MOVxw_REG(ed, x4);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("(unsupported) WRFSBASE Ed");
|
||||
FAKEED;
|
||||
UDF(0);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("(unsupported) WRGSBASE Ed");
|
||||
FAKEED;
|
||||
UDF(0);
|
||||
if(rex.is32bits || !MODREG) {
|
||||
INST_NAME("Illegal AE");
|
||||
FAKEED;
|
||||
UDF(0);
|
||||
} else {
|
||||
if(((nextop>>3)&7)==3) {INST_NAME("WRGSBASE");} else {INST_NAME("WRFSBASE");}
|
||||
ed = TO_NAT((nextop & 7) + (rex.b << 3));
|
||||
int seg = _FS + ((nextop>>3)&7)-2;
|
||||
STRx_U12(ed, xEmu, offsetof(x64emu_t, segs_offs[seg]));
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("(unsupported) INCSSPD/INCSSPQ Ed");
|
||||
|
||||
@@ -935,20 +935,7 @@ void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int se
|
||||
MAYUSE(j64);
|
||||
if (modreg) return;
|
||||
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment==_FS)?"FS":"GS");
|
||||
int t2 = x4;
|
||||
if(reg==t2) ++t2;
|
||||
#ifdef _WIN32
|
||||
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
|
||||
#else
|
||||
LDRH_U12(t2, xEmu, offsetof(x64emu_t, segs_old[segment]));
|
||||
LDRH_U12(reg, xEmu, offsetof(x64emu_t, segs[segment]));
|
||||
SUBw_REG(t2, reg, t2);
|
||||
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
|
||||
CBZw_MARKSEG(t2);
|
||||
MOVZw(x1, segment);
|
||||
call_c(dyn, ninst, const_getsegmentbase, t2, reg, 1, 0);
|
||||
MARKSEG;
|
||||
#endif
|
||||
MESSAGE(LOG_DUMP, "----%s Offset\n", (segment==_FS)?"FS":"GS");
|
||||
}
|
||||
|
||||
|
||||
@@ -1282,6 +1282,12 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
ed = x1;
|
||||
}
|
||||
ST_H(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZ_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1, x1, x2);
|
||||
}
|
||||
break;
|
||||
case 0x8F:
|
||||
INST_NAME("POP Ed");
|
||||
|
||||
@@ -739,6 +739,12 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
ed = x1;
|
||||
}
|
||||
ST_H(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZ_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1, x1, x2);
|
||||
}
|
||||
break;
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX, FS:Od");
|
||||
|
||||
@@ -511,6 +511,12 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
ed = x1;
|
||||
}
|
||||
ST_H(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZ_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1, x1, x2);
|
||||
}
|
||||
break;
|
||||
case 0x90:
|
||||
case 0x91:
|
||||
|
||||
@@ -764,17 +764,7 @@ void grab_segdata(dynarec_la64_t* dyn, uintptr_t addr, int ninst, int reg, int s
|
||||
MAYUSE(j64);
|
||||
if (modreg) return;
|
||||
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment == _FS) ? "FS" : "GS");
|
||||
int t1 = x1, t2 = x4;
|
||||
if (reg == t1) ++t1;
|
||||
if (reg == t2) ++t2;
|
||||
LD_H(t2, xEmu, offsetof(x64emu_t, segs_old[segment]));
|
||||
LD_D(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
|
||||
LD_H(t1, xEmu, offsetof(x64emu_t, segs[segment]));
|
||||
SUB_W(t1, t1, t2);
|
||||
CBZ_MARKSEG(t1);
|
||||
MOV64x(x1, segment);
|
||||
call_c(dyn, ninst, const_getsegmentbase, t2, reg, 0, xFlags, x1, 0, 0, 0, 0, 0);
|
||||
MARKSEG;
|
||||
MESSAGE(LOG_DUMP, "----%s Offset\n", (segment == _FS) ? "FS" : "GS");
|
||||
}
|
||||
|
||||
|
||||
@@ -514,6 +514,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
ed = x1;
|
||||
}
|
||||
SH(ed, xEmu, offsetof(x64emu_t, segs[(nextop & 0x38) >> 3]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZ_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1, x1, x2);
|
||||
}
|
||||
break;
|
||||
case 0x8F:
|
||||
INST_NAME("POP Ed");
|
||||
|
||||
@@ -471,6 +471,12 @@ uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
ed = x1;
|
||||
}
|
||||
SH(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZ_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1, x1, x2);
|
||||
}
|
||||
break;
|
||||
case 0x8F:
|
||||
INST_NAME("POP FS:Ed");
|
||||
|
||||
@@ -727,6 +727,12 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
ed = x1;
|
||||
}
|
||||
SH(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((u8==_FS) || (u8==_GS)) {
|
||||
// refresh offset if needed
|
||||
CBZ_NEXT(ed);
|
||||
MOV32w(x1, u8);
|
||||
CALL(const_getsegmentbase, -1, x1, x2);
|
||||
}
|
||||
break;
|
||||
case 0x90:
|
||||
case 0x91:
|
||||
|
||||
@@ -881,17 +881,7 @@ void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int s
|
||||
MAYUSE(j64);
|
||||
if (modreg) return;
|
||||
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment == _FS) ? "FS" : "GS");
|
||||
int t1 = x1, t2 = x4;
|
||||
if (reg == t1) ++t1;
|
||||
if (reg == t2) ++t2;
|
||||
LH(t2, xEmu, offsetof(x64emu_t, segs_old[segment]));
|
||||
LD(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
|
||||
LH(t1, xEmu, offsetof(x64emu_t, segs[segment]));
|
||||
SUBW(t1, t1, t2);
|
||||
CBZ_MARKSEG(t1);
|
||||
MOV64x(x1, segment);
|
||||
call_c(dyn, ninst, const_getsegmentbase, t2, reg, 0, xFlags, x1, 0, 0, 0, 0, 0);
|
||||
MARKSEG;
|
||||
MESSAGE(LOG_DUMP, "----%s Offset\n", (segment == _FS) ? "FS" : "GS");
|
||||
}
|
||||
|
||||
|
||||
+9
-13
@@ -77,8 +77,8 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s
|
||||
} else {
|
||||
emu->segs[_CS] = 0x33;
|
||||
emu->segs[_DS] = emu->segs[_ES] = emu->segs[_SS] = 0x2b;
|
||||
emu->segs[_FS] = 0x43;
|
||||
emu->segs[_GS] = default_gs;
|
||||
emu->segs[_FS] = 0;
|
||||
emu->segs[_GS] = 0;
|
||||
}
|
||||
// init segments
|
||||
for(int i=0; i<16; i++) {
|
||||
@@ -196,7 +196,6 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
|
||||
newemu->old_ip = emu->old_ip;
|
||||
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
|
||||
memcpy(newemu->segs_offs, emu->segs_offs, sizeof(emu->segs_offs));
|
||||
memcpy(newemu->segs_old, emu->segs_old, sizeof(emu->segs_old));
|
||||
memcpy(newemu->seggdt, emu->seggdt, sizeof(newemu->seggdt));
|
||||
memcpy(newemu->segldt, emu->segldt, sizeof(newemu->segldt));
|
||||
memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
|
||||
@@ -228,7 +227,6 @@ void CopyEmu(x64emu_t *newemu, const x64emu_t* emu)
|
||||
newemu->old_ip = emu->old_ip;
|
||||
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
|
||||
memcpy(newemu->segs_offs, emu->segs_offs, sizeof(emu->segs_offs));
|
||||
memcpy(newemu->segs_old, emu->segs_old, sizeof(emu->segs_old));
|
||||
memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
|
||||
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
|
||||
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
|
||||
@@ -425,6 +423,10 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip, int is32bits)
|
||||
if(i!=_GS)
|
||||
strcat(buff, " ");
|
||||
}
|
||||
sprintf(tmp, " FSBASE=%zu", emu->segs_offs[_FS]);
|
||||
strcat(buff, tmp);
|
||||
sprintf(tmp, " GSBASE=%zu", emu->segs_offs[_GS]);
|
||||
strcat(buff, tmp);
|
||||
strcat(buff, "\n");
|
||||
if(is32bits)
|
||||
for (int i=_AX; i<=_RDI; ++i) {
|
||||
@@ -595,13 +597,6 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
|
||||
}
|
||||
}
|
||||
|
||||
void ResetSegmentsCache(x64emu_t *emu)
|
||||
{
|
||||
if(!emu)
|
||||
return;
|
||||
memset(emu->segs_old, 0, sizeof(emu->segs_old));
|
||||
}
|
||||
|
||||
void applyFlushTo0(x64emu_t* emu)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
@@ -1608,9 +1603,10 @@ void free_tlsdatasize(void* p)
|
||||
|
||||
uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg)
|
||||
{
|
||||
if (emu->segs_old[seg] != emu->segs[seg]) {
|
||||
if(emu->segs[seg]) {
|
||||
emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu, emu->segs[seg]);
|
||||
emu->segs_old[seg] = emu->segs[seg];
|
||||
//printf_log(LOG_DEBUG, "%04d|GetSegmentBaseEmu seg=%d(%x), offs=%p\n", GetTID(), seg, emu->segs[seg], (void*)emu->segs_offs[seg]);
|
||||
}
|
||||
|
||||
return emu->segs_offs[seg];
|
||||
}
|
||||
@@ -90,8 +90,6 @@ typedef struct x64emu_s {
|
||||
uint16_t segs[6]; // only 32bits value?
|
||||
uint16_t dummy_seg6, dummy_seg7; // to stay aligned
|
||||
uintptr_t segs_offs[6]; // computed offset associate with segment
|
||||
uint16_t segs_old[6]; // seg needs to refresh the offset if value changed
|
||||
uint16_t dummy2_seg6, dummy2_seg7; // to stay aligned
|
||||
// parent context
|
||||
box64context_t *context;
|
||||
// cpu helpers
|
||||
|
||||
@@ -67,7 +67,6 @@ x64emu_t* x64emu_fork(x64emu_t* emu, int forktype)
|
||||
waitpid(v, NULL, WEXITED);
|
||||
}
|
||||
} else if(v==0) {
|
||||
ResetSegmentsCache(emu);
|
||||
// execute atforks child functions
|
||||
for (int i=0; i<my_context->atfork_sz; --i)
|
||||
if(my_context->atforks[i].child)
|
||||
|
||||
@@ -783,6 +783,8 @@ x64emurun:
|
||||
goto fini;
|
||||
}
|
||||
emu->segs[tmp8u] = ED->word[0];
|
||||
if(((tmp8u==_FS) || (tmp8u==_GS)) && emu->segs[tmp8u])
|
||||
GetSegmentBaseEmu(emu, tmp8u); // refresh segs_offs
|
||||
if(tmp8u==_SS && tf) // disable trace when SS is accessed
|
||||
no_tf = 1;
|
||||
break;
|
||||
|
||||
@@ -1178,6 +1178,8 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
emu->segs[_FS] = Pop32(emu);
|
||||
else
|
||||
emu->segs[_FS] = Pop64(emu);
|
||||
if(emu->segs[_FS])
|
||||
GetSegmentBaseEmu(emu, _FS); // refresh segs_offs
|
||||
break;
|
||||
case 0xA2: /* CPUID */
|
||||
tmp32u = R_EAX;
|
||||
@@ -1255,6 +1257,8 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
emu->segs[_GS] = Pop32(emu);
|
||||
else
|
||||
emu->segs[_GS] = Pop64(emu);
|
||||
if(emu->segs[_GS])
|
||||
GetSegmentBaseEmu(emu, _GS); // refresh segs_offs
|
||||
break;
|
||||
|
||||
case 0xAB: /* BTS Ed,Gd */
|
||||
|
||||
+9
-1
@@ -397,7 +397,15 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 0x8E: /* MOV Seg,Ew */
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
|
||||
tmp8u = (nextop&0x38)>>3;
|
||||
if((tmp8u>5) || (tmp8u==1)) {
|
||||
return 0;
|
||||
}
|
||||
emu->segs[tmp8u] = ED->word[0];
|
||||
if(((tmp8u==_FS) || (tmp8u==_GS)) && emu->segs[tmp8u])
|
||||
GetSegmentBaseEmu(emu, tmp8u); // refresh segs_offs
|
||||
/*if(tmp8u==_SS && tf) // disable trace when SS is accessed
|
||||
no_tf = 1;*/ //TODO?
|
||||
break;
|
||||
case 0x8F: /* POP Ew */
|
||||
nextop = F8;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "x64trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box64context.h"
|
||||
#include "emit_signals.h"
|
||||
#include "bridge.h"
|
||||
|
||||
#include "modrm.h"
|
||||
@@ -351,6 +352,40 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
memcpy(EX, GX, 16); // unaligned...
|
||||
break;
|
||||
|
||||
case 0xAE:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* RDFSBASE */
|
||||
case 1: /* RDGSBASE */
|
||||
if(!rex.is32bits && MODREG) {
|
||||
GETED(0);
|
||||
int seg = _FS+((nextop>>3)&7);
|
||||
uintptr_t addr = emu->segs_offs[seg];
|
||||
if(rex.w)
|
||||
ED->q[0] = addr;
|
||||
else {
|
||||
ED->dword[0] = addr;
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 2: /* WRFSBASE */
|
||||
case 3: /* WRGSBASE */
|
||||
if(!rex.is32bits && MODREG) {
|
||||
GETED(0);
|
||||
int seg = _FS+((nextop>>3)&7)-2;
|
||||
uintptr_t base = rex.w?ED->q[0]:ED->dword[0];
|
||||
emu->segs_offs[seg] = base;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default: return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB8: /* POPCNT Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
|
||||
+10
-12
@@ -94,8 +94,6 @@ uint32_t my_set_thread_area_32(x64emu_t* emu, thread_area_32_t* td)
|
||||
emu->seggdt[idx].is32bits = 1;
|
||||
}
|
||||
|
||||
ResetSegmentsCache(emu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -132,8 +130,6 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
|
||||
emu->segs_offs[_GS] =emu->segldt[idx].base;
|
||||
}
|
||||
|
||||
ResetSegmentsCache(emu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -169,15 +165,21 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr)
|
||||
errno = 0;
|
||||
switch(code) {
|
||||
case ARCH_GET_GS:
|
||||
*(void**)addr = GetSegmentBase(emu, emu->segs[_GS]);
|
||||
*(uintptr_t*)addr = GetSegmentBaseEmu(emu, _GS);
|
||||
return 0;
|
||||
case ARCH_GET_FS:
|
||||
*(void**)addr = GetSegmentBase(emu, emu->segs[_FS]);
|
||||
*(uintptr_t*)addr = GetSegmentBaseEmu(emu, _FS);
|
||||
return 0;
|
||||
case ARCH_SET_FS:
|
||||
case ARCH_SET_GS:
|
||||
seg=(code==ARCH_SET_FS)?_FS:_GS;
|
||||
int idx = -1;
|
||||
if(emu->segs[_CS]!=0x23) {
|
||||
// 64bits version, simply using FSGSBASE....
|
||||
emu->segs[seg] = 0;
|
||||
emu->segs_offs[seg] = (uintptr_t)addr;
|
||||
return 0;
|
||||
}
|
||||
// search if it's a TLS base
|
||||
if(GetSeg43Base(emu)==addr)
|
||||
idx = 0x43>>3;
|
||||
@@ -209,7 +211,6 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr)
|
||||
emu->seggdt[idx].present = 1;
|
||||
}
|
||||
emu->segs_offs[seg] = (uintptr_t)addr;
|
||||
emu->segs_old[seg] = emu->segs[seg];
|
||||
return 0;
|
||||
case ARCH_GET_XCOMP_SUPP:
|
||||
case ARCH_GET_XCOMP_PERM:
|
||||
@@ -382,13 +383,10 @@ void refreshTLSData(x64emu_t* emu)
|
||||
if(box64_is32bits) {
|
||||
if(emu->segs[_GS]==0x33) {
|
||||
emu->segs_offs[_GS] = new_offs;
|
||||
emu->segs_old[_GS] = 0x33;
|
||||
}
|
||||
} else {
|
||||
if(emu->segs[_FS]==0x43) {
|
||||
emu->segs_offs[_FS] = new_offs;
|
||||
emu->segs_old[_FS] = 0x43;
|
||||
}
|
||||
emu->segs_offs[_FS] = new_offs;
|
||||
emu->segs[_FS] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ void print_wrapper_name(int level, x64emu_t* emu);
|
||||
box64context_t* GetEmuContext(x64emu_t* emu);
|
||||
|
||||
void ResetFlags(x64emu_t *emu);
|
||||
void ResetSegmentsCache(x64emu_t *emu);
|
||||
const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip, int is32bits);
|
||||
|
||||
void UnimpOpcode(x64emu_t* emu, int is32bits);
|
||||
|
||||
@@ -368,10 +368,6 @@ uint32_t RunFunctionHandler32(int* exit, int dynarec, i386_ucontext_t* sigcontex
|
||||
emu->test.test = 0;
|
||||
#endif
|
||||
|
||||
/*SetFS(emu, default_fs);*/
|
||||
for (int i=0; i<6; ++i)
|
||||
emu->segs_old[i] = 0;
|
||||
|
||||
int align = nargs&1;
|
||||
|
||||
R_ESP -= nargs * sizeof(ptr_t);
|
||||
@@ -740,8 +736,6 @@ void my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, sigi
|
||||
GO(GS);
|
||||
GO(FS);
|
||||
#undef GO
|
||||
for(int i=0; i<6; ++i)
|
||||
emu->segs_old[i] = 0;
|
||||
printf_log((sig==10)?LOG_DEBUG:log_minimum, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p (resume with %s)\n", (void*)R_RIP, (void*)R_RSP, (skip==3)?"Dynarec":"Interp");
|
||||
if(old_code)
|
||||
*old_code = -1; // re-init the value to allow another segfault at the same place
|
||||
|
||||
+12
-8
@@ -123,10 +123,6 @@ uint64_t RunFunctionHandler(x64emu_t* emu, int* exit, int dynarec, x64_ucontext_
|
||||
emu->test.test = 0;
|
||||
#endif
|
||||
|
||||
/*SetFS(emu, default_fs);*/
|
||||
for (int i=0; i<6; ++i)
|
||||
emu->segs_old[i] = 0;
|
||||
|
||||
int align = nargs&1;
|
||||
|
||||
if(nargs>6)
|
||||
@@ -1229,8 +1225,6 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi
|
||||
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff;
|
||||
GO(FS);
|
||||
#undef GO
|
||||
for(int i=0; i<6; ++i)
|
||||
emu->segs_old[i] = 0;
|
||||
printf_log((sig==10)?LOG_DEBUG:log_minimum, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p (resume with %s)\n", (void*)R_RIP, (void*)R_RSP, (skip==3)?"Dynarec":"Interp");
|
||||
if(old_code)
|
||||
*old_code = -1; // re-init the value to allow another segfault at the same place
|
||||
@@ -1273,7 +1267,7 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi
|
||||
emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
|
||||
uint16_t seg;
|
||||
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff;
|
||||
#define GO(S) emu->segs[_##S]=seg; emu->segs_old[_##S] = 0;
|
||||
#define GO(S) emu->segs[_##S]=seg;
|
||||
GO(CS);
|
||||
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 16)&0xffff;
|
||||
GO(GS);
|
||||
@@ -1326,10 +1320,14 @@ void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo
|
||||
mmx87_regs_t old_mmx[8];
|
||||
mmx87_regs_t old_x87[8];
|
||||
uint32_t old_top = emu->top;
|
||||
uint16_t old_segs[6];
|
||||
uintptr_t old_segs_offs[6];
|
||||
memcpy(old_xmm, emu->xmm, sizeof(old_xmm));
|
||||
memcpy(old_ymm, emu->ymm, sizeof(old_ymm));
|
||||
memcpy(old_mmx, emu->mmx, sizeof(old_mmx));
|
||||
memcpy(old_x87, emu->x87, sizeof(old_x87));
|
||||
memcpy(old_segs, emu->segs, sizeof(old_segs));
|
||||
memcpy(old_segs_offs, emu->segs_offs, sizeof(old_segs_offs));
|
||||
#define GO(A) old_##A = emu->A
|
||||
GO(eflags);
|
||||
GO(df);
|
||||
@@ -1383,6 +1381,8 @@ void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo
|
||||
memcpy(emu->ymm, old_ymm, sizeof(old_ymm));
|
||||
memcpy(emu->mmx, old_mmx, sizeof(old_mmx));
|
||||
memcpy(emu->x87, old_x87, sizeof(old_x87));
|
||||
memcpy(emu->segs, old_segs, sizeof(old_segs));
|
||||
memcpy(emu->segs_offs, old_segs_offs, sizeof(old_segs_offs));
|
||||
emu->top = old_top;
|
||||
}
|
||||
|
||||
@@ -1882,6 +1882,8 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "%04d|Repeated SIGSEGV with Access error on %
|
||||
printf_log_prefix(0, log_minimum, "\n");
|
||||
for (int i=0; i<6; ++i)
|
||||
printf_log_prefix(0, log_minimum, "%s:0x%04x ", seg_name[i], emu->segs[i]);
|
||||
printf_log_prefix(0, log_minimum, "FSBASE=%p ", emu->segs_offs[_FS]);
|
||||
printf_log_prefix(0, log_minimum, "GSBASE=%p", emu->segs_offs[_GS]);
|
||||
}
|
||||
if(rsp!=addr && getProtection((uintptr_t)rsp-4*8) && getProtection((uintptr_t)rsp+4*8))
|
||||
for (int i=-4; i<4; ++i) {
|
||||
@@ -1895,9 +1897,11 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "%04d|Repeated SIGSEGV with Access error on %
|
||||
if(!(i%4)) printf_log_prefix(0, log_minimum, "\n");
|
||||
printf_log_prefix(0, log_minimum, "%s:0x%016llx ", reg_name[i], emu->regs[i].q[0]);
|
||||
}
|
||||
printf_log_prefix(0, log_minimum, "\n");
|
||||
for (int i=0; i<6; ++i)
|
||||
printf_log_prefix(0, log_minimum, "%s:0x%04x ", seg_name[i], emu->segs[i]);
|
||||
printf_log_prefix(0, log_minimum, "FSBASE=%p ", emu->segs_offs[_FS]);
|
||||
printf_log_prefix(0, log_minimum, "GSBASE=%p", emu->segs_offs[_GS]);
|
||||
printf_log_prefix(0, log_minimum, "\n");
|
||||
}
|
||||
zydis_dec_t* dec = emu->segs[_CS] == 0x23 ? my_context->dec32 : my_context->dec;
|
||||
if(sig==X64_SIGILL) {
|
||||
|
||||
@@ -313,7 +313,6 @@ static void* pthread_routine(void* p)
|
||||
add_thread((void*)et->self, et);
|
||||
#endif
|
||||
refreshTLSData(emu);
|
||||
ResetSegmentsCache(emu);
|
||||
Push64(emu, 0); // PUSH 0 (backtrace marker: return address is 0)
|
||||
Push64(emu, 0); // PUSH BP
|
||||
R_RBP = R_RSP; // MOV BP, SP
|
||||
|
||||
+15
-15
@@ -193,21 +193,21 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
|
||||
// extended bits...
|
||||
if(R_ECX==0) {
|
||||
R_EAX = 0;
|
||||
R_EBX =
|
||||
BOX64ENV(avx)<<3 | // BMI1
|
||||
BOX64ENV(avx2)<<5 | //AVX2
|
||||
(BOX64ENV(cputype)?0:1)<<6 | // FDP_EXCPTN_ONLY
|
||||
1<<7 | // SMEP
|
||||
BOX64ENV(avx2)<<8 | //BMI2
|
||||
(BOX64ENV(cputype)?0:1)<<9 | // Enhanced REP MOVSB // is it a good idea?
|
||||
1<<10 | //INVPCID (priviledge instruction
|
||||
(BOX64ENV(cputype)?0:1)<<13 | // Deprecates FPU CS and FPU DS
|
||||
0<<18 | // RDSEED
|
||||
BOX64ENV(avx2)<<19 | //ADX
|
||||
1<<23 | // CLFLUSHOPT
|
||||
1<<24 | // CLWB
|
||||
BOX64ENV(shaext)<<29| // SHA extension
|
||||
0;
|
||||
R_EBX = 1<<0 // FSGSBASE
|
||||
| BOX64ENV(avx)<<3 // BMI1
|
||||
| BOX64ENV(avx2)<<5 //AVX2
|
||||
| (BOX64ENV(cputype)?0:1)<<6 // FDP_EXCPTN_ONLY
|
||||
| 1<<7 // SMEP
|
||||
| BOX64ENV(avx2)<<8 //BMI2
|
||||
| (BOX64ENV(cputype)?0:1)<<9 // Enhanced REP MOVSB // is it a good idea?
|
||||
| 1<<10 //INVPCID (priviledge instruction
|
||||
| (BOX64ENV(cputype)?0:1)<<13 // Deprecates FPU CS and FPU DS
|
||||
| 0<<18 // RDSEED
|
||||
| BOX64ENV(avx2)<<19 //ADX
|
||||
| 1<<23 // CLFLUSHOPT
|
||||
| 1<<24 // CLWB
|
||||
| BOX64ENV(shaext)<<29 // SHA extension
|
||||
;
|
||||
R_RCX =
|
||||
(BOX64ENV(avx)&&BOX64ENV(aes))<<9 | //VAES
|
||||
(BOX64ENV(avx2)&&BOX64ENV(pclmulqdq))<<10 | //VPCLMULQDQ.
|
||||
|
||||
@@ -148,7 +148,9 @@ void SetupInitialStack(x64emu_t *emu)
|
||||
//Push64(emu, sysconf(_SC_CLK_TCK)); Push64(emu, 17); //AT_CLKTCK(17)=times() frequency
|
||||
Push64(emu, real_getauxval(23)); Push64(emu, 23); //AT_SECURE(23)
|
||||
Push64(emu, p_random); Push64(emu, 25); //AT_RANDOM(25)=p_random
|
||||
Push64(emu, 0); Push64(emu, 26); //AT_HWCAP2(26)=0
|
||||
Push64(emu, 0
|
||||
| 1<<1 // FSGSBASE
|
||||
); Push64(emu, 26); //AT_HWCAP2(26)=...
|
||||
Push64(emu, p_arg0); Push64(emu, 31); //AT_EXECFN(31)=p_arg0
|
||||
Push64(emu, emu->context->vsyscall); Push64(emu, 32); //AT_SYSINFO(32)=vsyscall
|
||||
//Push64(emu, 0); Push64(emu, 33); //AT_SYSINFO_EHDR(33)=address of vDSO
|
||||
|
||||
@@ -3763,7 +3763,6 @@ static int clone_fn(void* p)
|
||||
thread_set_emu(emu);
|
||||
if(arg->flags&CLONE_NEWUSER) {
|
||||
init_mutexes(my_context);
|
||||
ResetSegmentsCache(emu);
|
||||
}
|
||||
int ret = RunFunctionWithEmu(emu, 0, arg->fnc, 1, arg->args);
|
||||
int exited = (emu->flags.quitonexit==2);
|
||||
|
||||
@@ -233,7 +233,7 @@ NTSTATUS WINAPI BTCpuProcessInit(void)
|
||||
|
||||
#define STATIC_ASSERT(COND, MSG) typedef char static_assertion_##MSG[(!!(COND)) * 2 - 1]
|
||||
/* otherwise adjust arm64_epilog.S and arm64_next.S */
|
||||
STATIC_ASSERT(offsetof(x64emu_t, win64_teb) == 3104, offset_of_b_must_be_4);
|
||||
STATIC_ASSERT(offsetof(x64emu_t, win64_teb) == 3088, offset_of_b_must_be_4);
|
||||
#undef STATIC_ASSERT
|
||||
|
||||
LoadEnvVariables();
|
||||
|
||||
Reference in new issue
Block a user