diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-09-29 13:31:15 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-09-29 13:31:15 +0200 |
| commit | a37f7d1800b5d1f8c33e7817ee9a57964c453d5e (patch) | |
| tree | c4c773567cb78a89fa4d9b6c791a1e612f4f7429 | |
| parent | 86dde8c1f7f798df0fcf8c0603b75de838b41241 (diff) | |
| download | box64-a37f7d1800b5d1f8c33e7817ee9a57964c453d5e.tar.gz box64-a37f7d1800b5d1f8c33e7817ee9a57964c453d5e.zip | |
[ARM64_DYNAREC] Improved IRET handling of boggus parameters
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_consts.c | 1 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_consts.h | 1 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 53 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_functions.c | 6 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_functions.h | 1 | ||||
| -rw-r--r-- | src/tools/env.c | 2 |
6 files changed, 45 insertions, 19 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_consts.c b/src/dynarec/arm64/dynarec_arm64_consts.c index 5a6e6d78..e208f990 100644 --- a/src/dynarec/arm64/dynarec_arm64_consts.c +++ b/src/dynarec/arm64/dynarec_arm64_consts.c @@ -49,6 +49,7 @@ uintptr_t getConst(arm64_consts_t which) case const_native_br: return (uintptr_t)native_br; case const_native_ud: return (uintptr_t)native_ud; case const_native_priv: return (uintptr_t)native_priv; + case const_native_gpf: return (uintptr_t)native_gpf; case const_native_int3: return (uintptr_t)native_int3; case const_native_int: return (uintptr_t)native_int; case const_native_div0: return (uintptr_t)native_div0; diff --git a/src/dynarec/arm64/dynarec_arm64_consts.h b/src/dynarec/arm64/dynarec_arm64_consts.h index 2543699e..e6620388 100644 --- a/src/dynarec/arm64/dynarec_arm64_consts.h +++ b/src/dynarec/arm64/dynarec_arm64_consts.h @@ -13,6 +13,7 @@ typedef enum arm64_consts_s { const_native_br, const_native_ud, const_native_priv, + const_native_gpf, const_native_int3, const_native_int, const_native_div0, diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index a1d9a93b..4e6b4c02 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -718,42 +718,48 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i // POP IP NOTEST(x2); if(is64bits) { - POP1(xRIP); + POP1(x1); POP1(x2); - POP1(xFlags); + POP1(x3); } else { - POP1_32(xRIP); + POP1_32(x1); POP1_32(x2); - POP1_32(xFlags); + POP1_32(x3); } - // x2 is CS - STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS])); - STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS])); + // check CS is NULL, sgfault if it is + CBZw_MARK3(x1); // clean EFLAGS - MOV32w(x1, 0x3F7FD7); - ANDx_REG(xFlags, xFlags, x1); - ORRx_mask(xFlags, xFlags, 1, 0b111111, 0); // xFlags | 0b10 + MOV32w(x4, 0x3F7FD7); + ANDx_REG(x3, x3, x4); + ORRx_mask(x3, x3, 1, 0b111111, 0); // xFlags | 0b10 SET_DFNONE(); if(is32bits) { - ANDw_mask(x2, x2, 0, 7); // mask 0xff + ANDw_mask(x4, x2, 0, 7); // mask 0xff // check if return segment is 64bits, then restore rsp too - CMPSw_U12(x2, 0x23); + CMPSw_U12(x4, 0x23); B_MARKSEG(cEQ); } // POP RSP if(is64bits) { - POP1(x3); //rsp - POP1(x2); //ss + POP1(x4); //rsp + POP1(x5); //ss } else { - POP1_32(x3); //rsp - POP1_32(x2); //ss + POP1_32(x4); //rsp + POP1_32(x5); //ss } + // check if SS is NULL + CBZw(x5, MARK); // POP SS - STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_SS])); + STRH_U12(x5, xEmu, offsetof(x64emu_t, segs[_SS])); STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS])); // set new RSP - MOVx_REG(xRSP, x3); + MOVx_REG(xRSP, x4); MARKSEG; + // x2 is CS, x1 is IP, x3 is eFlags + STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS])); + STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS])); + MOVx_REG(xRIP, x1); + MOVw_REG(xFlags, x3); // Ret.... // epilog on purpose, CS might have changed! if(dyn->need_reloc) @@ -762,6 +768,17 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i MOV64x(x2, getConst(const_epilog)); BR(x2); CLEARIP(); + MARK; + if(is64bits) + ADDx_U12(xRSP, xRSP, 8*2); + else + ADDx_U12(xRSP, xRSP, 4*2); + MARK3; + if(is64bits) + ADDx_U12(xRSP, xRSP, 8*3); + else + ADDx_U12(xRSP, xRSP, 4*3); + CALL_S(const_native_priv, -1); } void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, int saveflags, int savereg) diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index 49ea4a40..0f8f5a39 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -203,6 +203,12 @@ void native_priv(x64emu_t* emu) EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); } +void native_gpf(x64emu_t* emu) +{ + emu->test.test = 0; + EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // same effect has private opcode? +} + void native_int(x64emu_t* emu, int num) { emu->test.test = 0; diff --git a/src/dynarec/dynarec_native_functions.h b/src/dynarec/dynarec_native_functions.h index 9601fc18..be3b80d5 100644 --- a/src/dynarec/dynarec_native_functions.h +++ b/src/dynarec/dynarec_native_functions.h @@ -55,6 +55,7 @@ void native_clflush(x64emu_t* emu, void* p); void native_ud(x64emu_t* emu); void native_br(x64emu_t* emu); void native_priv(x64emu_t* emu); +void native_gpf(x64emu_t* emu); void native_int3(x64emu_t* emu); void native_int(x64emu_t* emu, int num); void native_wineint(x64emu_t* emu, int num); diff --git a/src/tools/env.c b/src/tools/env.c index 22ed7511..58e312fc 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -804,7 +804,7 @@ done: #define HEADER_SIGN "DynaCache" #define SET_VERSION(MAJ, MIN, REV) (((MAJ)<<24)|((MIN)<<16)|(REV)) #ifdef ARM64 -#define ARCH_VERSION SET_VERSION(0, 0, 5) +#define ARCH_VERSION SET_VERSION(0, 0, 6) #elif defined(RV64) #define ARCH_VERSION SET_VERSION(0, 0, 3) #elif defined(LA64) |