about summary refs log tree commit diff stats
path: root/wow64
diff options
context:
space:
mode:
authorAndré Zwing <nerv@dawncrow.de>2025-05-22 21:19:16 +0200
committerAndré Zwing <nerv@dawncrow.de>2025-05-22 21:27:02 +0200
commitfa874ffcbca0908493aea5e45503d52df998b099 (patch)
tree92153d2d823c013b6c66584786fac0dd6da4b85a /wow64
parentb729e3e37b37b5c14ab556d674aa71c24edcdffe (diff)
downloadbox64-fa874ffcbca0908493aea5e45503d52df998b099.tar.gz
box64-fa874ffcbca0908493aea5e45503d52df998b099.zip
[WOW64] Implement syscalls
Diffstat (limited to 'wow64')
-rw-r--r--wow64/compiler.h3
-rw-r--r--wow64/wowbox64.c87
2 files changed, 90 insertions, 0 deletions
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 4d6d7263..b3147404 100644
--- a/wow64/wowbox64.c
+++ b/wow64/wowbox64.c
@@ -18,6 +18,7 @@
 #include "x64trace.h"
 #include "box64context.h"
 #include "box64cpu.h"
+#include "box64cpu_util.h"
 #include "rbtree.h"
 #include "wine/debug.h"
 
@@ -240,6 +241,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)