diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-05-07 22:50:37 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-07 16:50:37 +0200 |
| commit | 5d14413b89d7bb78023307fc59d2d9da182554a4 (patch) | |
| tree | 3822c9835ff42632837da6dde40a292e7048247f /src | |
| parent | ec549690944d2768b811340bc999abdfbc60ca2c (diff) | |
| download | box64-5d14413b89d7bb78023307fc59d2d9da182554a4.tar.gz box64-5d14413b89d7bb78023307fc59d2d9da182554a4.zip | |
[DYNAREC] Use PE volatile metadata in dynarec (#2610)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 11 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_private.h | 8 | ||||
| -rw-r--r-- | src/dynarec/dynarec_helper.h | 102 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_pass.c | 23 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 6 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.c | 10 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 6 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_private.h | 8 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 10 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_private.h | 8 | ||||
| -rw-r--r-- | src/include/env.h | 187 | ||||
| -rw-r--r-- | src/include/pe_tools.h | 8 | ||||
| -rw-r--r-- | src/tools/pe_tools.c | 53 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibc.c | 18 |
18 files changed, 290 insertions, 192 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 34913701..351e1e0a 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2387,7 +2387,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next i32 = F16; - retn_to_epilog(dyn, ninst, rex, i32); + retn_to_epilog(dyn, ip, ninst, rex, i32); *need_epilog = 0; *ok = 0; break; @@ -2398,7 +2398,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next - ret_to_epilog(dyn, ninst, rex); + ret_to_epilog(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -2724,7 +2724,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("IRET"); SETFLAGS(X_ALL, SF_SET_NODF); // Not a hack, EFLAGS are restored BARRIER(BARRIER_FLOAT); - iret_to_epilog(dyn, ninst, rex.is32bits, rex.w); + iret_to_epilog(dyn, ip, ninst, rex.is32bits, rex.w); *need_epilog = 0; *ok = 0; break; diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 51f619b2..32f03214 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -30,7 +30,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u { MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta); - if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); } + if (l == LOCK_LOCK) { + dyn->insts[ninst].lock_prefixed = 1; + DMB_ISH(); + } if(rex.is32bits) return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s); @@ -617,7 +620,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 #endif } -void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex) +void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex) { MAYUSE(dyn); MAYUSE(ninst); MESSAGE(LOG_DUMP, "Ret to epilog\n"); @@ -658,7 +661,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex) CLEARIP(); } -void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n) +void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n) { MAYUSE(dyn); MAYUSE(ninst); MESSAGE(LOG_DUMP, "Retn to epilog\n"); @@ -705,7 +708,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n) CLEARIP(); } -void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits) +void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits) { int64_t j64; //#warning TODO: is64bits diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index fa3cff10..f36601e6 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1479,9 +1479,9 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, // generic x64 helper void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits); -void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex); -void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n); -void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits); +void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex); +void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n); +void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits); void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg); void call_i(dynarec_arm_t* dyn, int ninst, void* fnc); void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w); diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index ae615571..60c24aa2 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -109,9 +109,11 @@ typedef struct instruction_arm64_s { uint16_t ymm0_out; // the ymm0 at th end of the opcode uint16_t ymm0_pass2, ymm0_pass3; uint8_t barrier_maybe; - uint8_t will_write:2; // [strongmem] will write to memory - uint8_t last_write:1; // [strongmem] the last write in a SEQ - uint8_t lock:1; // [strongmem] lock semantic + uint8_t will_write:2; // [strongmem] will write to memory + uint8_t will_read:1; // [strongmem] will read from memory + uint8_t last_write:1; // [strongmem] the last write in a SEQ + uint8_t lock:1; // [strongmem] lock semantic + uint8_t lock_prefixed:1; // [strongmem] the opcode is lock prefixed uint8_t wfe:1; // opcode uses sevl + wfe uint8_t set_nat_flags; // 0 or combinaison of native flags define uint8_t use_nat_flags; // 0 or combinaison of native flags define diff --git a/src/dynarec/dynarec_helper.h b/src/dynarec/dynarec_helper.h index d8b0eb52..f5fbfeee 100644 --- a/src/dynarec/dynarec_helper.h +++ b/src/dynarec/dynarec_helper.h @@ -1,6 +1,10 @@ #ifndef __DYNAREC_HELPER__H_ #define __DYNAREC_HELPER__H_ +#include "env.h" +#include "pe_tools.h" +#include "debug.h" + /* Box64 Strong Memory Model Emulation * * Definition of a SEQ: @@ -32,6 +36,8 @@ #define STRONGMEM_LAST_WRITE 1 // The level of a barrier before the last guest memory store will be put #define STRONGMEM_SEQ_WRITE 3 // The level of a barrier at every third memory store will be put +#define STRONGMEM_LEVEL() (box64_wine && VolatileRangesContains(ip) ? 0 : BOX64DRENV(dynarec_strongmem)) + #if STEP == 1 #define SMWRITE() \ @@ -49,15 +55,20 @@ SMWRITE(); \ } while (0) -#define SMWRITE2() \ - do { \ - if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SIMD_WRITE) { \ - dyn->smwrite = 1; \ - dyn->insts[ninst].will_write = 2; \ - } \ +#define SMWRITE2() \ + do { \ + if (STRONGMEM_LEVEL() >= STRONGMEM_SIMD_WRITE) { \ + dyn->smwrite = 1; \ + dyn->insts[ninst].will_write = 2; \ + } \ + } while (0) + +#define SMREAD() \ + do { \ + /* Mark that current opcode read from guest memory. */ \ + dyn->insts[ninst].will_read = 1; \ } while (0) -#define SMREAD() #define SMREADLOCK(lock) #define WILLWRITE() #define WILLWRITELOCK(lock) @@ -71,7 +82,7 @@ #define SMEND() \ do { \ /* If there is any guest memory write, which is a SEQ, then compute the last_write. */ \ - if (dyn->smwrite && (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_LAST_WRITE)) { \ + if (dyn->smwrite && (STRONGMEM_LEVEL() >= STRONGMEM_LAST_WRITE)) { \ int i = ninst; \ while (i >= 0 && !dyn->insts[i].will_write) \ --i; \ @@ -85,22 +96,23 @@ #else // An opcode writes guest memory, this need to be put after the STORE instruction manually. It will also end the SEQ automaticaly on last_write immediatly -#define SMWRITE() \ - do { \ - if(dyn->insts[ninst].last_write) { \ - dyn->smwrite = 1; \ - SMEND(); \ - } else { \ - /* Put a barrier at every third memory write. */ \ - if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SEQ_WRITE) { \ - if (++dyn->smwrite >= 3 /* Every third memory write */) { \ - DMB_ISH(); \ - dyn->smwrite = 1; \ - } \ - } else { \ - /* Mark that current sequence writes to guest memory. */ \ - dyn->smwrite = 1; \ - } } \ +#define SMWRITE() \ + do { \ + if (dyn->insts[ninst].last_write) { \ + dyn->smwrite = 1; \ + SMEND(); \ + } else { \ + /* Put a barrier at every third memory write. */ \ + if (STRONGMEM_LEVEL() >= STRONGMEM_SEQ_WRITE) { \ + if (++dyn->smwrite >= 3 /* Every third memory write */) { \ + DMB_ISH(); \ + dyn->smwrite = 1; \ + } \ + } else { \ + /* Mark that current sequence writes to guest memory. */ \ + dyn->smwrite = 1; \ + } \ + } \ } while (0) // Similar to SMWRITE, but checks lock. @@ -114,10 +126,10 @@ } while (0) // Similar to SMWRITE, but for SIMD instructions. -#define SMWRITE2() \ - do { \ - if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SIMD_WRITE) \ - SMWRITE(); \ +#define SMWRITE2() \ + do { \ + if (STRONGMEM_LEVEL() >= STRONGMEM_SIMD_WRITE) \ + SMWRITE(); \ } while (0) // An opcode reads guest memory, this need to be put before the LOAD instruction manually. @@ -134,22 +146,22 @@ } while (0) // An opcode will write memory, this will be put before the STORE instruction automatically. -#define WILLWRITE() \ - do { \ - if (BOX64DRENV(dynarec_strongmem) >= dyn->insts[ninst].will_write && dyn->smwrite == 0) { \ - /* Will write but never written, this is the start of a SEQ, put a barrier. */ \ - if (BOX64ENV(dynarec_weakbarrier)) \ - DMB_ISHLD(); \ - else \ - DMB_ISH(); \ - } else if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_LAST_WRITE && BOX64ENV(dynarec_weakbarrier) != 2 \ - && dyn->insts[ninst].last_write) { \ - /* Last write, put a barrier */ \ - if (BOX64ENV(dynarec_weakbarrier)) \ - DMB_ISHST(); \ - else \ - DMB_ISH(); \ - } \ +#define WILLWRITE() \ + do { \ + if (STRONGMEM_LEVEL() >= dyn->insts[ninst].will_write && dyn->smwrite == 0) { \ + /* Will write but never written, this is the start of a SEQ, put a barrier. */ \ + if (BOX64ENV(dynarec_weakbarrier)) \ + DMB_ISHLD(); \ + else \ + DMB_ISH(); \ + } else if (STRONGMEM_LEVEL() >= STRONGMEM_LAST_WRITE && BOX64ENV(dynarec_weakbarrier) != 2 \ + && dyn->insts[ninst].last_write) { \ + /* Last write, put a barrier */ \ + if (BOX64ENV(dynarec_weakbarrier)) \ + DMB_ISHST(); \ + else \ + DMB_ISH(); \ + } \ } while (0) // Similar to WILLWRITE, but checks lock. @@ -171,7 +183,7 @@ // Will be put at the end of the SEQ #define SMEND() \ do { \ - if (BOX64DRENV(dynarec_strongmem)) { \ + if (STRONGMEM_LEVEL()) { \ /* It's a SEQ, put a barrier here. */ \ if (dyn->smwrite) { \ /* Check if the next instruction has a end loop mark */ \ diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 1f55ada4..eab3e10b 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -18,6 +18,7 @@ #include "dynablock_private.h" #include "custommem.h" #include "x64test.h" +#include "pe_tools.h" #include "dynarec_arch.h" #include "dynarec_helper.h" @@ -132,6 +133,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } else if (dyn->insts[ninst].will_write) { WILLWRITE(); } + + int is_opcode_volatile = box64_wine && VolatileRangesContains(ip); + if (is_opcode_volatile && !dyn->insts[ninst].lock_prefixed) { + if (dyn->insts[ninst].will_write) + DMB_ISH(); + else if (dyn->insts[ninst].will_read) + DMB_ISHLD(); + } #endif if((dyn->insts[ninst].x64.need_before&~X_PEND) && !ninst) { READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND); @@ -149,7 +158,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int if (BOX64DRENV(dynarec_dump) && (!BOX64ENV(dynarec_dump_range_end) || (ip >= BOX64ENV(dynarec_dump_range_start) && ip < BOX64ENV(dynarec_dump_range_end)))) { dyn->need_dump = BOX64DRENV(dynarec_dump); } -#ifdef HAVE_TRACE + #ifdef HAVE_TRACE else if(my_context->dec && BOX64ENV(dynarec_trace)) { if((trace_end == 0) || ((ip >= trace_start) && (ip < trace_end))) { @@ -160,7 +169,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int MESSAGE(LOG_DUMP, "----------\n"); } } -#endif + #endif rep = 0; uint8_t pk = PK(0); @@ -187,6 +196,16 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int if(dyn->abort) return ip; INST_EPILOG; + + #if STEP > 1 + if (is_opcode_volatile && !dyn->insts[ninst].lock_prefixed) { + if (dyn->insts[ninst].will_write) + DMB_ISHST(); + else if (dyn->insts[ninst].will_read) + DMB_ISHLD(); + } + #endif + fpu_reset_scratch(dyn); int next = ninst+1; #if STEP > 0 diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index b44b3e75..4811bbac 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -1854,7 +1854,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next i32 = F16; - retn_to_epilog(dyn, ninst, rex, i32); + retn_to_epilog(dyn, ip, ninst, rex, i32); *need_epilog = 0; *ok = 0; break; @@ -1864,7 +1864,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next - ret_to_epilog(dyn, ninst, rex); + ret_to_epilog(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -2032,7 +2032,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("IRET"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored BARRIER(BARRIER_FLOAT); - iret_to_epilog(dyn, ninst, rex.w); + iret_to_epilog(dyn, ip, ninst, rex.w); *need_epilog = 0; *ok = 0; break; diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index c76690d9..b6fc31c2 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -35,6 +35,10 @@ uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, MAYUSE(ninst); MAYUSE(delta); + if (l == LOCK_LOCK) { + dyn->insts[ninst].lock_prefixed = 1; + } + if (rex.is32bits) return geted_32(dyn, addr, ninst, nextop, ed, hint, scratch, fixaddress, l, i12); @@ -572,7 +576,7 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 JIRL((dyn->insts[ninst].x64.has_callret ? xRA : xZR), x2, 0x0); // save LR... } -void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex) +void ret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex) { MAYUSE(dyn); MAYUSE(ninst); @@ -611,7 +615,7 @@ void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex) CLEARIP(); } -void retn_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex, int n) +void retn_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n) { MAYUSE(dyn); MAYUSE(ninst); @@ -656,7 +660,7 @@ void retn_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex, int n) CLEARIP(); } -void iret_to_epilog(dynarec_la64_t* dyn, int ninst, int is64bits) +void iret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, int is64bits) { // #warning TODO: is64bits MAYUSE(ninst); diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 7d472bf6..8dfa9970 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -1011,9 +1011,9 @@ uintptr_t geted32(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop void jump_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_epilog_fast(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits); -void ret_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex); -void retn_to_epilog(dynarec_la64_t* dyn, int ninst, rex_t rex, int n); -void iret_to_epilog(dynarec_la64_t* dyn, int ninst, int is64bits); +void ret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex); +void retn_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n); +void iret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, int is64bits); void call_c(dynarec_la64_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg); void grab_segdata(dynarec_la64_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg); void emit_cmp8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6); diff --git a/src/dynarec/la64/dynarec_la64_private.h b/src/dynarec/la64/dynarec_la64_private.h index 2244b122..4bc621bd 100644 --- a/src/dynarec/la64/dynarec_la64_private.h +++ b/src/dynarec/la64/dynarec_la64_private.h @@ -93,9 +93,11 @@ typedef struct instruction_la64_s { uint16_t ymm0_out; // the ymm0 at th end of the opcode uint16_t ymm0_pass2, ymm0_pass3; uint8_t barrier_maybe; - uint8_t will_write; - uint8_t last_write; - uint8_t lock; + uint8_t will_write:2; // [strongmem] will write to memory + uint8_t will_read:1; // [strongmem] will read from memory + uint8_t last_write:1; // [strongmem] the last write in a SEQ + uint8_t lock:1; // [strongmem] lock semantic + uint8_t lock_prefixed:1; // [strongmem] the opcode is lock prefixed uint8_t df_notneeded; uint8_t nat_flags_fusion:1; uint8_t nat_flags_nofusion:1; diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 2dfa119e..c10742db 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -285,7 +285,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next i32 = F16; - retn_to_epilog(dyn, ninst, rex, i32); + retn_to_epilog(dyn, ip, ninst, rex, i32); *need_epilog = 0; *ok = 0; break; @@ -296,7 +296,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next - ret_to_epilog(dyn, ninst, rex); + ret_to_epilog(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -553,7 +553,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("IRET"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored BARRIER(BARRIER_FLOAT); - iret_to_epilog(dyn, ninst, rex.w); + iret_to_epilog(dyn, ip, ninst, rex.w); *need_epilog = 0; *ok = 0; break; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index f436ea18..4d584d35 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -34,6 +34,10 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, MAYUSE(ninst); MAYUSE(delta); + if (l == LOCK_LOCK) { + dyn->insts[ninst].lock_prefixed = 1; + } + if (rex.is32bits) return geted_32(dyn, addr, ninst, nextop, ed, hint, scratch, fixaddress, l, i12); @@ -601,7 +605,7 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 #endif } -void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex) +void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) { MAYUSE(dyn); MAYUSE(ninst); @@ -664,7 +668,7 @@ void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex) CLEARIP(); } -void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n) +void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n) { MAYUSE(dyn); MAYUSE(ninst); @@ -732,7 +736,7 @@ void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n) CLEARIP(); } -void iret_to_epilog(dynarec_rv64_t* dyn, int ninst, int is64bits) +void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits) { // #warning TODO: is64bits MAYUSE(ninst); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 48886fbd..900245fb 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1434,9 +1434,9 @@ uintptr_t geted32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst); void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits); -void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex); -void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n); -void iret_to_epilog(dynarec_rv64_t* dyn, int ninst, int is64bits); +void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex); +void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n); +void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits); void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int savereg, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w); void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg); diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 80507b49..16ea574f 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -125,9 +125,11 @@ typedef struct instruction_rv64_s { uint16_t ymm0_out; // the ymm0 at th end of the opcode uint16_t ymm0_pass2, ymm0_pass3; int barrier_maybe; - uint8_t will_write; - uint8_t last_write; - uint8_t lock; + uint8_t will_write:2; // [strongmem] will write to memory + uint8_t will_read:1; // [strongmem] will read from memory + uint8_t last_write:1; // [strongmem] the last write in a SEQ + uint8_t lock:1; // [strongmem] lock semantic + uint8_t lock_prefixed:1; // [strongmem] the opcode is lock prefixed uint8_t df_notneeded; uint8_t nat_flags_fusion:1; uint8_t nat_flags_nofusion:1; diff --git a/src/include/env.h b/src/include/env.h index 991840aa..0d4b2f5c 100644 --- a/src/include/env.h +++ b/src/include/env.h @@ -24,99 +24,100 @@ extern char* ftrace_name; #define DEFAULT_LOG_LEVEL (ftrace_name ? LOG_INFO : (isatty(fileno(stdout)) ? LOG_INFO : LOG_NONE)) -#define ENVSUPER1() \ - STRING(BOX64_ADDLIBS, addlibs) \ - BOOLEAN(BOX64_ALLOWMISSINGLIBS, allow_missing_libs, 0) \ - STRING(BOX64_ARGS, args) \ - STRING(BOX64_BASH, bash) \ - BOOLEAN(BOX64_CEFDISABLEGPU, cefdisablegpu, 0) \ - BOOLEAN(BOX64_CEFDISABLEGPUCOMPOSITOR, cefdisablegpucompositor, 0) \ - INTEGER(BOX64_CPUTYPE, cputype, 0, 0, 1) \ - BOOLEAN(BOX64_CRASHHANDLER, dummy_crashhandler, 1) \ - BOOLEAN(BOX64_DLSYM_ERROR, dlsym_error, 0) \ - INTEGER(BOX64_DUMP, dump, 0, 0, 2) \ - BOOLEAN(BOX64_DYNAREC_ALIGNED_ATOMICS, dynarec_aligned_atomics, 0) \ - INTEGER(BOX64_DYNAREC_BIGBLOCK, dynarec_bigblock, 2, 0, 3) \ - BOOLEAN(BOX64_DYNAREC_BLEEDING_EDGE, dynarec_bleeding_edge, 1) \ - INTEGER(BOX64_DYNAREC_CALLRET, dynarec_callret, 0, 0, 2) \ - BOOLEAN(BOX64_DYNAREC_DF, dynarec_df, 1) \ - INTEGER(BOX64_DYNAREC_DIRTY, dynarec_dirty, 0, 0, 2) \ - BOOLEAN(BOX64_DYNAREC_DIV0, dynarec_div0, 0) \ - INTEGER(BOX64_DYNAREC_DUMP, dynarec_dump, 0, 0, 2) \ - STRING(BOX64_DYNAREC_DUMP_RANGE, dynarec_dump_range) \ - BOOLEAN(BOX64_DYNAREC_FASTNAN, dynarec_fastnan, 1) \ - INTEGER(BOX64_DYNAREC_FASTROUND, dynarec_fastround, 1, 0, 2) \ - INTEGER(BOX64_DYNAREC_FORWARD, dynarec_forward, 128, 0, 1024) \ - STRING(BOX64_DYNAREC_GDBJIT, dynarec_gdbjit_str) \ - INTEGER(BOX64_DYNAREC_LOG, dynarec_log, 0, 0, 3) \ - INTEGER(BOX64_DYNAREC_MISSING, dynarec_missing, 0, 0, 2) \ - BOOLEAN(BOX64_DYNAREC_NATIVEFLAGS, dynarec_nativeflags, 1) \ - INTEGER(BOX64_DYNAREC_PAUSE, dynarec_pause, 0, 0, 3) \ - BOOLEAN(BOX64_DYNAREC_PERFMAP, dynarec_perf_map, 0) \ - INTEGER(BOX64_DYNAREC_SAFEFLAGS, dynarec_safeflags, 1, 0, 2) \ - INTEGER(BOX64_DYNAREC_STRONGMEM, dynarec_strongmem, 0, 0, 3) \ - BOOLEAN(BOX64_DYNAREC_TBB, dynarec_tbb, 1) \ - STRING(BOX64_DYNAREC_TEST, dynarec_test_str) \ - BOOLEAN(BOX64_DYNAREC_TRACE, dynarec_trace, 0) \ - BOOLEAN(BOX64_DYNAREC_WAIT, dynarec_wait, 1) \ - BOOLEAN(BOX64_DYNAREC_WEAKBARRIER, dynarec_weakbarrier, 1) \ - INTEGER(BOX64_DYNAREC_X87DOUBLE, dynarec_x87double, 0, 0, 2) \ - STRING(BOX64_EMULATED_LIBS, emulated_libs) \ - STRING(BOX64_ENV, env) \ - STRING(BOX64_ENV1, env1) \ - STRING(BOX64_ENV2, env2) \ - STRING(BOX64_ENV3, env3) \ - STRING(BOX64_ENV4, env4) \ - STRING(BOX64_ENV5, env5) \ - BOOLEAN(BOX64_EXIT, exit, 0) \ - BOOLEAN(BOX64_FIX_64BIT_INODES, fix_64bit_inodes, 0) \ - BOOLEAN(BOX64_IGNOREINT3, ignoreint3, 0) \ - STRING(BOX64_INSERT_ARGS, insert_args) \ - BOOLEAN(BOX64_INPROCESSGPU, inprocessgpu, 0) \ - INTEGER(BOX64_JITGDB, jitgdb, 0, 0, 3) \ - BOOLEAN(BOX64_JVM, jvm, 1) \ - STRING(BOX64_LD_LIBRARY_PATH, ld_library_path) \ - BOOLEAN(BOX64_LIBCEF, libcef, 1) \ - STRING(BOX64_LIBGL, libgl) \ - ADDRESS(BOX64_LOAD_ADDR, load_addr) \ - INTEGER(BOX64_LOG, log, DEFAULT_LOG_LEVEL, 0, 3) \ - INTEGER(BOX64_MALLOC_HACK, malloc_hack, 0, 0, 2) \ - INTEGER(BOX64_MAXCPU, new_maxcpu, 0, 0, 100) \ - BOOLEAN(BOX64_NOBANNER, nobanner, (isatty(fileno(stdout)) ? 0 : 1)) \ - STRING(BOX64_NODYNAREC, nodynarec) \ - BOOLEAN(BOX64_NOGTK, nogtk, 0) \ - BOOLEAN(BOX64_NOPULSE, nopulse, 0) \ - BOOLEAN(BOX64_NORCFILES, noenvfiles, 0) \ - BOOLEAN(BOX64_NOSANDBOX, nosandbox, 0) \ - BOOLEAN(BOX64_NOSIGSEGV, nosigsegv, 0) \ - BOOLEAN(BOX64_NOSIGILL, nosigill, 0) \ - BOOLEAN(BOX64_NOVULKAN, novulkan, 0) \ - STRING(BOX64_PATH, path) \ - BOOLEAN(BOX64_PREFER_EMULATED, prefer_emulated, 0) \ - BOOLEAN(BOX64_PREFER_WRAPPED, prefer_wrapped, 0) \ - STRING(BOX64_RCFILE, envfile) \ - BOOLEAN(BOX64_RDTSC_1GHZ, rdtsc_1ghz, 0) \ - BOOLEAN(BOX64_RESERVE_HIGH, reserve_high, 0) \ - INTEGER(BOX64_ROLLING_LOG, cycle_log, 0, 0, 2048) \ - BOOLEAN(BOX64_SDL2_JGUID, sdl2_jguid, 0) \ - BOOLEAN(BOX64_SHAEXT, shaext, 1) \ - BOOLEAN(BOX64_SHOWBT, showbt, 0) \ - BOOLEAN(BOX64_SHOWSEGV, showsegv, 0) \ - BOOLEAN(BOX64_SSE_FLUSHTO0, sse_flushto0, 0) \ - BOOLEAN(BOX64_SSE42, sse42, 1) \ - BOOLEAN(BOX64_SYNC_ROUNDING, sync_rounding, 0) \ - BOOLEAN(BOX64_TRACE_COLOR, trace_regsdiff, 0) \ - BOOLEAN(BOX64_TRACE_EMM, trace_emm, 0) \ - STRING(BOX64_TRACE_FILE, trace_file) \ - STRING(BOX64_TRACE_INIT, trace_init) \ - INTEGER64(BOX64_TRACE_START, start_cnt, 0) \ - BOOLEAN(BOX64_TRACE_XMM, trace_xmm, 0) \ - STRING(BOX64_TRACE, trace) \ - BOOLEAN(BOX64_UNITYPLAYER, unityplayer, 1) \ - BOOLEAN(BOX64_WRAP_EGL, wrap_egl, 0) \ - BOOLEAN(BOX64_X11GLX, x11glx, 1) \ - BOOLEAN(BOX64_X11SYNC, x11sync, 0) \ - BOOLEAN(BOX64_X11THREADS, x11threads, 0) \ +#define ENVSUPER1() \ + STRING(BOX64_ADDLIBS, addlibs) \ + BOOLEAN(BOX64_ALLOWMISSINGLIBS, allow_missing_libs, 0) \ + STRING(BOX64_ARGS, args) \ + STRING(BOX64_BASH, bash) \ + BOOLEAN(BOX64_CEFDISABLEGPU, cefdisablegpu, 0) \ + BOOLEAN(BOX64_CEFDISABLEGPUCOMPOSITOR, cefdisablegpucompositor, 0) \ + INTEGER(BOX64_CPUTYPE, cputype, 0, 0, 1) \ + BOOLEAN(BOX64_CRASHHANDLER, dummy_crashhandler, 1) \ + BOOLEAN(BOX64_DLSYM_ERROR, dlsym_error, 0) \ + INTEGER(BOX64_DUMP, dump, 0, 0, 2) \ + BOOLEAN(BOX64_DYNAREC_ALIGNED_ATOMICS, dynarec_aligned_atomics, 0) \ + INTEGER(BOX64_DYNAREC_BIGBLOCK, dynarec_bigblock, 2, 0, 3) \ + BOOLEAN(BOX64_DYNAREC_BLEEDING_EDGE, dynarec_bleeding_edge, 1) \ + INTEGER(BOX64_DYNAREC_CALLRET, dynarec_callret, 0, 0, 2) \ + BOOLEAN(BOX64_DYNAREC_DF, dynarec_df, 1) \ + INTEGER(BOX64_DYNAREC_DIRTY, dynarec_dirty, 0, 0, 2) \ + BOOLEAN(BOX64_DYNAREC_DIV0, dynarec_div0, 0) \ + INTEGER(BOX64_DYNAREC_DUMP, dynarec_dump, 0, 0, 2) \ + STRING(BOX64_DYNAREC_DUMP_RANGE, dynarec_dump_range) \ + BOOLEAN(BOX64_DYNAREC_FASTNAN, dynarec_fastnan, 1) \ + INTEGER(BOX64_DYNAREC_FASTROUND, dynarec_fastround, 1, 0, 2) \ + INTEGER(BOX64_DYNAREC_FORWARD, dynarec_forward, 128, 0, 1024) \ + STRING(BOX64_DYNAREC_GDBJIT, dynarec_gdbjit_str) \ + INTEGER(BOX64_DYNAREC_LOG, dynarec_log, 0, 0, 3) \ + INTEGER(BOX64_DYNAREC_MISSING, dynarec_missing, 0, 0, 2) \ + BOOLEAN(BOX64_DYNAREC_NATIVEFLAGS, dynarec_nativeflags, 1) \ + INTEGER(BOX64_DYNAREC_PAUSE, dynarec_pause, 0, 0, 3) \ + BOOLEAN(BOX64_DYNAREC_PERFMAP, dynarec_perf_map, 0) \ + INTEGER(BOX64_DYNAREC_SAFEFLAGS, dynarec_safeflags, 1, 0, 2) \ + INTEGER(BOX64_DYNAREC_STRONGMEM, dynarec_strongmem, 0, 0, 3) \ + BOOLEAN(BOX64_DYNAREC_TBB, dynarec_tbb, 1) \ + STRING(BOX64_DYNAREC_TEST, dynarec_test_str) \ + BOOLEAN(BOX64_DYNAREC_TRACE, dynarec_trace, 0) \ + BOOLEAN(BOX64_DYNAREC_VOLATILE_METADATA, dynarec_volatile_metadata, 0) \ + BOOLEAN(BOX64_DYNAREC_WAIT, dynarec_wait, 1) \ + BOOLEAN(BOX64_DYNAREC_WEAKBARRIER, dynarec_weakbarrier, 1) \ + INTEGER(BOX64_DYNAREC_X87DOUBLE, dynarec_x87double, 0, 0, 2) \ + STRING(BOX64_EMULATED_LIBS, emulated_libs) \ + STRING(BOX64_ENV, env) \ + STRING(BOX64_ENV1, env1) \ + STRING(BOX64_ENV2, env2) \ + STRING(BOX64_ENV3, env3) \ + STRING(BOX64_ENV4, env4) \ + STRING(BOX64_ENV5, env5) \ + BOOLEAN(BOX64_EXIT, exit, 0) \ + BOOLEAN(BOX64_FIX_64BIT_INODES, fix_64bit_inodes, 0) \ + BOOLEAN(BOX64_IGNOREINT3, ignoreint3, 0) \ + STRING(BOX64_INSERT_ARGS, insert_args) \ + BOOLEAN(BOX64_INPROCESSGPU, inprocessgpu, 0) \ + INTEGER(BOX64_JITGDB, jitgdb, 0, 0, 3) \ + BOOLEAN(BOX64_JVM, jvm, 1) \ + STRING(BOX64_LD_LIBRARY_PATH, ld_library_path) \ + BOOLEAN(BOX64_LIBCEF, libcef, 1) \ + STRING(BOX64_LIBGL, libgl) \ + ADDRESS(BOX64_LOAD_ADDR, load_addr) \ + INTEGER(BOX64_LOG, log, DEFAULT_LOG_LEVEL, 0, 3) \ + INTEGER(BOX64_MALLOC_HACK, malloc_hack, 0, 0, 2) \ + INTEGER(BOX64_MAXCPU, new_maxcpu, 0, 0, 100) \ + BOOLEAN(BOX64_NOBANNER, nobanner, (isatty(fileno(stdout)) ? 0 : 1)) \ + STRING(BOX64_NODYNAREC, nodynarec) \ + BOOLEAN(BOX64_NOGTK, nogtk, 0) \ + BOOLEAN(BOX64_NOPULSE, nopulse, 0) \ + BOOLEAN(BOX64_NORCFILES, noenvfiles, 0) \ + BOOLEAN(BOX64_NOSANDBOX, nosandbox, 0) \ + BOOLEAN(BOX64_NOSIGSEGV, nosigsegv, 0) \ + BOOLEAN(BOX64_NOSIGILL, nosigill, 0) \ + BOOLEAN(BOX64_NOVULKAN, novulkan, 0) \ + STRING(BOX64_PATH, path) \ + BOOLEAN(BOX64_PREFER_EMULATED, prefer_emulated, 0) \ + BOOLEAN(BOX64_PREFER_WRAPPED, prefer_wrapped, 0) \ + STRING(BOX64_RCFILE, envfile) \ + BOOLEAN(BOX64_RDTSC_1GHZ, rdtsc_1ghz, 0) \ + BOOLEAN(BOX64_RESERVE_HIGH, reserve_high, 0) \ + INTEGER(BOX64_ROLLING_LOG, cycle_log, 0, 0, 2048) \ + BOOLEAN(BOX64_SDL2_JGUID, sdl2_jguid, 0) \ + BOOLEAN(BOX64_SHAEXT, shaext, 1) \ + BOOLEAN(BOX64_SHOWBT, showbt, 0) \ + BOOLEAN(BOX64_SHOWSEGV, showsegv, 0) \ + BOOLEAN(BOX64_SSE_FLUSHTO0, sse_flushto0, 0) \ + BOOLEAN(BOX64_SSE42, sse42, 1) \ + BOOLEAN(BOX64_SYNC_ROUNDING, sync_rounding, 0) \ + BOOLEAN(BOX64_TRACE_COLOR, trace_regsdiff, 0) \ + BOOLEAN(BOX64_TRACE_EMM, trace_emm, 0) \ + STRING(BOX64_TRACE_FILE, trace_file) \ + STRING(BOX64_TRACE_INIT, trace_init) \ + INTEGER64(BOX64_TRACE_START, start_cnt, 0) \ + BOOLEAN(BOX64_TRACE_XMM, trace_xmm, 0) \ + STRING(BOX64_TRACE, trace) \ + BOOLEAN(BOX64_UNITYPLAYER, unityplayer, 1) \ + BOOLEAN(BOX64_WRAP_EGL, wrap_egl, 0) \ + BOOLEAN(BOX64_X11GLX, x11glx, 1) \ + BOOLEAN(BOX64_X11SYNC, x11sync, 0) \ + BOOLEAN(BOX64_X11THREADS, x11threads, 0) \ BOOLEAN(BOX64_X87_NO80BITS, x87_no80bits, 0) #ifdef ARM64 diff --git a/src/include/pe_tools.h b/src/include/pe_tools.h index 54c3d42e..d52f1438 100644 --- a/src/include/pe_tools.h +++ b/src/include/pe_tools.h @@ -1,7 +1,13 @@ #ifndef __PE_TOOLS_H__ #define __PE_TOOLS_H__ - +// Parse the PE file and extract the volatile metadata, which contains volatile opcode entries and volatile ranges. void ParseVolatileMetadata(char* filename, void* addr); +// Check if a given address is contained within the volatile ranges. +int VolatileRangesContains(uintptr_t addr); + +// Check if a given address is contained within the volatile opcode entries. +int VolatileOpcodesHas(uintptr_t addr); + #endif // __PE_TOOLS_H__ diff --git a/src/tools/pe_tools.c b/src/tools/pe_tools.c index 46c8a203..5d8bc2b4 100644 --- a/src/tools/pe_tools.c +++ b/src/tools/pe_tools.c @@ -6,6 +6,8 @@ #include <stddef.h> #include "debug.h" +#include "khash.h" +#include "rbtree.h" typedef uint8_t BYTE; typedef uint16_t WORD; @@ -182,6 +184,14 @@ typedef struct _IMAGE_VOLATILE_RANGE_METADATA { ULONG Size; } IMAGE_VOLATILE_RANGE_METADATA, *PIMAGE_VOLATILE_RANGE_METADATA; +KHASH_SET_INIT_STR(string); +KHASH_SET_INIT_INT64(volatileopcode); + +static kh_string_t* dllNames = NULL; // never freed +static kh_volatileopcode_t* volatileOpcodes = NULL; // never freed + +static rbtree_t* volatileRanges = NULL; // never freed + static int HasSuffix(const char* str, const char* suffix) { size_t lenstr = strlen(str); @@ -211,6 +221,22 @@ void ParseVolatileMetadata(char* filename, void* addr) return; } + if (!dllNames) dllNames = kh_init(string); + if (!volatileOpcodes) volatileOpcodes = kh_init(volatileopcode); + if (!volatileRanges) volatileRanges = rbtree_init("volatileRanges"); + + char* baseName = strrchr(filename, '/'); + if (!baseName) + return; + else + baseName++; + + khint_t k = kh_get(string, dllNames, baseName); + if (k != kh_end(dllNames)) return; + + int ret; + k = kh_put(string, dllNames, strdup(baseName), &ret); + FILE* file = fopen(filename, "rb"); if (!file) return; @@ -280,7 +306,7 @@ void ParseVolatileMetadata(char* filename, void* addr) PIMAGE_VOLATILE_METADATA volatileMetadata = (PIMAGE_VOLATILE_METADATA)(buffer + volatileMetadataOffset); if (volatileMetadata->VolatileAccessTable && volatileMetadata->VolatileAccessTableSize) { - printf_log(LOG_INFO, "Parsing volatile metadata of file: %s\n", filename); + printf_log(LOG_INFO, "Parsing volatile metadata of file %s loaded at %p\n", baseName, addr); DWORD volatileAccessTableOffset = RVAToFileOffset(sectionHeaders, numberOfSections, volatileMetadata->VolatileAccessTable, (BYTE*)buffer, ntHeaders64->OptionalHeader.SizeOfImage); if (volatileAccessTableOffset == 0) { @@ -292,8 +318,10 @@ void ParseVolatileMetadata(char* filename, void* addr) PIMAGE_VOLATILE_RVA_METADATA volatileAccessTable = (PIMAGE_VOLATILE_RVA_METADATA)(buffer + volatileAccessTableOffset); for (DWORD i = 0; i < numEntries; i++) { - ULONG entry = volatileAccessTable[i].Rva; - printf_log(LOG_INFO, "Volatile Access Table Entry %d: %08X\n", i, entry); + ULONGLONG entry = volatileAccessTable[i].Rva + (ULONGLONG)addr; + int ret; + khint_t _ = kh_put(volatileopcode, volatileOpcodes, entry, &ret); + printf_log(LOG_DEBUG, "Volatile access table [%d]: %08lX\n", i, entry); } } @@ -308,9 +336,22 @@ void ParseVolatileMetadata(char* filename, void* addr) PIMAGE_VOLATILE_RANGE_METADATA volatileRangeMetadata = (PIMAGE_VOLATILE_RANGE_METADATA)(buffer + volatileInfoRangeTableOffset); for (DWORD i = 0; i < numEntries; i++) { - ULONG Rva = volatileRangeMetadata[i].Rva; - ULONG Size = volatileRangeMetadata[i].Size; - printf_log(LOG_INFO, "Volatile Range Metadata Entry %d: %08X Size: %08X\n", i, Rva, Size); + ULONGLONG rva = volatileRangeMetadata[i].Rva + (ULONGLONG)addr; + ULONGLONG size = volatileRangeMetadata[i].Size; + rb_set(volatileRanges, rva, rva + size, i); + printf_log(LOG_DEBUG, "Volatile range metadata [%d]: %08lX-%08lX\n", i, rva, rva + size); } } } + +int VolatileRangesContains(uintptr_t addr) +{ + if (!volatileRanges) return 0; + return rb_get(volatileRanges, addr) != 0; +} + +int VolatileOpcodesHas(uintptr_t addr) +{ + if (!volatileOpcodes) return 0; + return kh_get(volatileopcode, volatileOpcodes, addr) != kh_end(volatileOpcodes); +} diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 4815f57d..fbfc9b21 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -3033,14 +3033,16 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, size_t length, int prot, int f #endif if(ret!=MAP_FAILED) { if(emu && !(flags&MAP_ANONYMOUS) && (fd>0)) { - char filename[4096]; - char buf[128]; - sprintf(buf, "/proc/self/fd/%d", fd); - ssize_t r = readlink(buf, filename, sizeof(filename) - 1); - if (r != -1) filename[r] = 0; - - DetectUnityPlayer(filename); - // ParseVolatileMetadata(filename, addr); + if ((box64_wine && BOX64ENV(dynarec_volatile_metadata)) || BOX64ENV(unityplayer)) { + char filename[4096]; + char buf[128]; + sprintf(buf, "/proc/self/fd/%d", fd); + ssize_t r = readlink(buf, filename, sizeof(filename) - 1); + if (r != -1) filename[r] = 0; + + if (BOX64ENV(unityplayer)) DetectUnityPlayer(filename); + if (box64_wine && BOX64ENV(dynarec_volatile_metadata)) ParseVolatileMetadata(filename, addr); + } // the last_mmap will allow mmap created by wine, even those that have hole, to be fully tracked as one single mmap if((ret>=last_mmap_addr[0]) && ret+length<(last_mmap_addr[0]+last_mmap_len[0])) RecordEnvMappings((uintptr_t)last_mmap_addr[0], last_mmap_len[0], fd); |