diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-05-22 23:02:12 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-22 23:02:12 +0200 |
| commit | 18a02fafb1a14d70affb16cee2cb59c1c1e7849e (patch) | |
| tree | c2233c1e8fffb0ccede744c2fe8b716a10ee6c6e | |
| parent | 5916869329fc3bf00885be33be98f9cfbe6073de (diff) | |
| parent | 06d4fc79ec22cdc93ca4577bd01fc496c3eb6c0e (diff) | |
| download | box64-18a02fafb1a14d70affb16cee2cb59c1c1e7849e.tar.gz box64-18a02fafb1a14d70affb16cee2cb59c1c1e7849e.zip | |
Merge pull request #2660 from AndreRH/wowbox64
wow64 part4 (dont squash)
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 19 | ||||
| -rw-r--r-- | src/dynarec/dynablock.c | 2 | ||||
| -rw-r--r-- | src/include/os.h | 2 | ||||
| -rw-r--r-- | wow64/compiler.h | 3 | ||||
| -rw-r--r-- | wow64/wowbox64.c | 92 |
5 files changed, 115 insertions, 3 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 351e1e0a..3ab1e5c4 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2646,6 +2646,25 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xCD: u8 = F8; +#ifdef _WIN32 + NOTEST(x1); + SMEND(); + GETIP(addr); + STORE_XEMU_CALL(xRIP); + MOV32w(x1, u8); + LDRx_U12(xR8, xEmu, offsetof(x64emu_t, win64_teb)); + CALL_S(x86Int, -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); + break; +#endif if(box64_wine && (u8==0x2D || u8==0x2C || u8==0x29)) { INST_NAME("INT 29/2c/2d"); // lets do nothing diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 4ecdf768..2556f137 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -223,11 +223,13 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t return block; } } +#ifndef _WIN32 if((getProtection_fast(addr)&req_prot)!=req_prot) {// cannot be run, get out of the Dynarec if(need_lock) mutex_unlock(&my_context->mutex_dyndump); return NULL; } +#endif block = AddNewDynablock(addr); // fill the block diff --git a/src/include/os.h b/src/include/os.h index 1257cc48..f141e99e 100644 --- a/src/include/os.h +++ b/src/include/os.h @@ -26,6 +26,8 @@ void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) int munmap(void* addr, size_t length); int mprotect(void* addr, size_t len, int prot); +void x86Int(void* emu, int code); + void* WinMalloc(size_t size); void* WinRealloc(void* ptr, size_t size); void* WinCalloc(size_t nmemb, size_t size); diff --git a/wow64/compiler.h b/wow64/compiler.h index 9abafa74..e30691fd 100644 --- a/wow64/compiler.h +++ b/wow64/compiler.h @@ -7,6 +7,7 @@ #define ThreadWow64Context (29) #define WOW64_TLS_CPURESERVED (1) #define WOW64_TLS_MAX_NUMBER (19) +#define WOW64_CPURESERVED_FLAG_RESET_STATE (1) typedef struct _WOW64_CPURESERVED { @@ -15,8 +16,10 @@ typedef struct _WOW64_CPURESERVED } WOW64_CPURESERVED; NTSTATUS WINAPI RtlWow64GetCurrentCpuArea(USHORT *, void **, void **); +NTSTATUS WINAPI Wow64SystemServiceEx(UINT, UINT*); NTSYSAPI NTSTATUS WINAPI LdrGetDllHandle(LPCWSTR, ULONG, const UNICODE_STRING*, HMODULE*); NTSYSAPI void* WINAPI RtlFindExportedRoutineByName(HMODULE, const char*); +NTSYSAPI void DECLSPEC_NORETURN WINAPI RtlRaiseStatus(NTSTATUS); static inline uintptr_t calculate_fs(void) { diff --git a/wow64/wowbox64.c b/wow64/wowbox64.c index 23839b64..6f7f8b46 100644 --- a/wow64/wowbox64.c +++ b/wow64/wowbox64.c @@ -18,6 +18,8 @@ #include "x64trace.h" #include "box64context.h" #include "box64cpu.h" +#include "box64cpu_util.h" +#include "rbtree.h" #include "wine/debug.h" uintptr_t box64_pagesize = 4096; @@ -125,7 +127,6 @@ NTSTATUS WINAPI BTCpuProcessInit(void) HMODULE module; UNICODE_STRING str; void **p__wine_unix_call_dispatcher; - __wine_dbg_output("[BOX64] BTCpuProcessInit\n"); #define STATIC_ASSERT(COND, MSG) typedef char static_assertion_##MSG[(!!(COND))*2-1] /* otherwise adjust arm64_epilog.S and arm64_next.S */ @@ -140,6 +141,7 @@ STATIC_ASSERT(offsetof(x64emu_t, win64_teb) == 3120, offset_of_b_must_be_4); unxcode[0] = 0x2ecd; init_custommem_helper(&box64_context); + box64_context.db_sizes = rbtree_init("db_sizes"); if ((ULONG_PTR)bopcode >> 32 || (ULONG_PTR)unxcode >> 32) { @@ -161,7 +163,6 @@ STATIC_ASSERT(offsetof(x64emu_t, win64_teb) == 3120, offset_of_b_must_be_4); InitX64Trace(&box64_context); - __wine_dbg_output("[BOX64] BTCpuProcessInit done\n"); return STATUS_SUCCESS; } @@ -215,7 +216,6 @@ NTSTATUS WINAPI BTCpuThreadInit(void) { WOW64_CONTEXT *ctx; x64emu_t *emu = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*emu) ); - __wine_dbg_output("[BOX64] BTCpuThreadInit\n"); RtlWow64GetCurrentCpuArea( NULL, (void **)&ctx, NULL ); emu->context = &box64_context; @@ -238,6 +238,92 @@ NTSTATUS WINAPI BTCpuTurboThunkControl(ULONG enable) return STATUS_SUCCESS; } +void x86IntImpl(x64emu_t *emu, int code) +{ + int inst_off = box64env.dynarec ? 2 : 0; + + if (code == 0x2e) /* NT syscall */ + { + WOW64_CPURESERVED *cpu = NtCurrentTeb()->TlsSlots[WOW64_TLS_CPURESERVED]; + WOW64_CONTEXT *ctx = (WOW64_CONTEXT *)(cpu + 1); + int id = R_EAX; + BOOL is_unix_call = FALSE; + + if (ULongToPtr(R_RIP-inst_off) == &unxcode) + is_unix_call = TRUE; + else if (ULongToPtr(R_RIP-inst_off) != &bopcode) + return; + + R_RIP = Pop32(emu); + ctx->Eip = R_RIP; + ctx->Esp = R_ESP; + ctx->Ebx = R_EBX; + ctx->Esi = R_ESI; + ctx->Edi = R_EDI; + ctx->Ebp = R_EBP; + ctx->EFlags = emu->eflags.x64; + cpu->Flags = 0; + + if (is_unix_call) + { + uintptr_t handle_low = Pop32(emu); + uintptr_t handle_high = Pop32(emu); + unsigned int code = Pop32(emu); + uintptr_t args = Pop32(emu); + + ctx->Esp = R_ESP; + R_EAX = __wine_unix_call_dispatcher( handle_low | (handle_high << 32), code, (void *)args ); + } + else + { + R_EAX = Wow64SystemServiceEx( id, ULongToPtr(ctx->Esp+4) ); + } + + R_EBX = ctx->Ebx; + R_ESI = ctx->Esi; + R_EDI = ctx->Edi; + R_EBP = ctx->Ebp; + R_ESP = ctx->Esp; + R_RIP = ctx->Eip; + if (cpu->Flags & WOW64_CPURESERVED_FLAG_RESET_STATE) + { + cpu->Flags &= ~WOW64_CPURESERVED_FLAG_RESET_STATE; + R_EAX = ctx->Eax; + R_ECX = ctx->Ecx; + R_EDX = ctx->Edx; + R_FS = ctx->SegFs & 0xffff; + emu->segs_offs[_FS] = calculate_fs(); + emu->eflags.x64 = ctx->EFlags; + } + } + else + { + RtlRaiseStatus( STATUS_ACCESS_VIOLATION ); + } +} + +/* Calls a 2-argument function `Func` setting the parent unwind frame information to the given SP and PC */ +static void __attribute__((naked)) SEHFrameTrampoline2Args(void* Arg0, int Arg1, void* Func, uint64_t Sp, uint64_t Pc) +{ + asm( ".seh_proc SEHFrameTrampoline2Args\n\t" + "stp x3, x4, [sp, #-0x10]!\n\t" + ".seh_pushframe\n\t" + "stp x29, x30, [sp, #-0x10]!\n\t" + ".seh_save_fplr_x 16\n\t" + ".seh_endprologue\n\t" + "blr x2\n\t" + "ldp x29, x30, [sp], 0x20\n\t" + "ret\n\t" + ".seh_endproc" ); +} + +void x86Int(void* emu, int code) +{ + CONTEXT *entry_context = NtCurrentTeb()->TlsSlots[WOW64_TLS_MAX_NUMBER]; + SEHFrameTrampoline2Args(emu, code, (void*)x86IntImpl, entry_context->Sp, entry_context->Pc); + NtCurrentTeb()->TlsSlots[WOW64_TLS_MAX_NUMBER] = entry_context; +} + NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE); BOOL WINAPI DllMainCRTStartup(HINSTANCE inst, DWORD reason, void* reserved) |