about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndré Zwing <nerv@dawncrow.de>2025-05-25 18:36:14 +0200
committerAndré Zwing <nerv@dawncrow.de>2025-05-25 21:41:23 +0200
commite09adad1b9db271d3f3add3abe6bf1ae3659d0aa (patch)
tree4794a386575390268a9a7d9ca19a6e32d9888d12
parentb6429edf0975f54c533a4a46a7fe332396a3a781 (diff)
downloadbox64-e09adad1b9db271d3f3add3abe6bf1ae3659d0aa.tar.gz
box64-e09adad1b9db271d3f3add3abe6bf1ae3659d0aa.zip
[WOW64] Partially implement BTCpuResetToConsistentState
-rw-r--r--wow64/compiler.h1
-rw-r--r--wow64/wowbox64.c34
2 files changed, 34 insertions, 1 deletions
diff --git a/wow64/compiler.h b/wow64/compiler.h
index e30691fd..a7bf71a7 100644
--- a/wow64/compiler.h
+++ b/wow64/compiler.h
@@ -18,6 +18,7 @@ typedef struct _WOW64_CPURESERVED
 NTSTATUS WINAPI RtlWow64GetCurrentCpuArea(USHORT *, void **, void **);
 NTSTATUS  WINAPI Wow64SystemServiceEx(UINT, UINT*);
 NTSYSAPI NTSTATUS WINAPI LdrGetDllHandle(LPCWSTR, ULONG, const UNICODE_STRING*, HMODULE*);
+NTSYSAPI NTSTATUS WINAPI NtContinue(PCONTEXT, BOOLEAN);
 NTSYSAPI void* WINAPI RtlFindExportedRoutineByName(HMODULE, const char*);
 NTSYSAPI void DECLSPEC_NORETURN WINAPI RtlRaiseStatus(NTSTATUS);
 
diff --git a/wow64/wowbox64.c b/wow64/wowbox64.c
index 6f7f8b46..67cac41b 100644
--- a/wow64/wowbox64.c
+++ b/wow64/wowbox64.c
@@ -12,6 +12,7 @@
 #include "compiler.h"
 #include "os.h"
 #include "custommem.h"
+#include "dynablock.h"
 #include "env.h"
 #include "emu/x64emu_private.h"
 #include "emu/x87emu_private.h"
@@ -166,9 +167,40 @@ STATIC_ASSERT(offsetof(x64emu_t, win64_teb) == 3120, offset_of_b_must_be_4);
     return STATUS_SUCCESS;
 }
 
+static uint8_t box64_is_addr_in_jit(void* addr)
+{
+    if (!addr)
+        return FALSE;
+    return !!FindDynablockFromNativeAddress(addr);
+}
+
 NTSTATUS WINAPI BTCpuResetToConsistentState(EXCEPTION_POINTERS* ptrs)
 {
-    // NYI
+    x64emu_t *emu = NtCurrentTeb()->TlsSlots[0];  // FIXME
+    EXCEPTION_RECORD *rec = ptrs->ExceptionRecord;
+    CONTEXT *ctx = ptrs->ContextRecord;
+
+    if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+    {
+        dynablock_t *db = NULL;
+        void* addr = NULL;
+        uint32_t prot;
+
+        if (rec->NumberParameters == 2 && rec->ExceptionInformation[0] == 1)
+            addr = ULongToPtr(rec->ExceptionInformation[1]);
+
+        if (addr)
+        {
+            unprotectDB((uintptr_t)addr, 1, 1);    // unprotect 1 byte... But then, the whole page will be unprotected
+            NtContinue(ctx, FALSE);
+        }
+    }
+
+    if (!box64_is_addr_in_jit(ULongToPtr(ctx->Pc)))
+        return STATUS_SUCCESS;
+
+    /* Replace the host context with one captured before JIT entry so host code can unwind */
+    memcpy(ctx, NtCurrentTeb()->TlsSlots[WOW64_TLS_MAX_NUMBER], sizeof(*ctx));
     return STATUS_SUCCESS;
 }