From eb7f9381fb1109c3468047f604b0e57a1cbb4edb Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Tue, 14 Jul 2020 14:43:01 +0300
Subject: [PATCH] winebuild: Call __wine_syscall_dispatcher through the fixed
 address.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Based on a patch by Erich E. Hoover and Michael Müller.

Helps applications which directly load ntdll.dll from disk and
call syscall thunks from the loaded image.
---
 dlls/ntdll/unix/virtual.c | 6 ++++--
 tools/winebuild/import.c  | 8 ++++----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 9b1ca761e9b..0f4fd8d95ee 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -2594,20 +2594,22 @@ TEB *virtual_alloc_first_teb(void)
     PEB *peb;
     void *ptr;
     NTSTATUS status;
-    SIZE_T data_size = page_size;
+    SIZE_T data_size = page_size * 2;
     SIZE_T peb_size = page_size * (is_win64 ? 1 : 2);
     SIZE_T block_size = signal_stack_mask + 1;
     SIZE_T total = 32 * block_size;
 
     /* reserve space for shared user data */
     status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&user_shared_data, 0, &data_size,
-                                      MEM_RESERVE | MEM_COMMIT, PAGE_READONLY );
+                                      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
     if (status)
     {
         ERR( "wine: failed to map the shared user data: %08x\n", status );
         exit(1);
     }
 
+    *((void **)((char *)user_shared_data + 0x1000)) = __wine_syscall_dispatcher;
+
     NtAllocateVirtualMemory( NtCurrentProcess(), &teb_block, 0, &total,
                              MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
     teb_block_pos = 30;
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 278de20522e..094b9da0ccf 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -1613,10 +1613,10 @@ void output_syscalls( DLLSPEC *spec )
             output( "\t.byte 0xc3\n" );           /* ret */
             output( "\tjmp 1f\n" );
             output( "\t.byte 0xc3\n" );           /* ret */
-            if (target_platform == PLATFORM_WINDOWS)
+            if (target_platform == PLATFORM_WINDOWS || target_platform == PLATFORM_APPLE)
             {
-                output( "1:\t.byte 0xff,0x14,0x25\n" ); /* 2: callq *(__wine_syscall_dispatcher) */
-                output( "\t.long __wine_syscall_dispatcher\n" );
+                output( "1:\t.byte 0xff,0x14,0x25\n" ); /* call *(user_shared_data + 0x1000) */
+                output( "\t.long 0x7ffe1000\n" );
             }
             else
             {
@@ -1653,7 +1653,7 @@ void output_syscalls( DLLSPEC *spec )
         output( "\t.align %d\n", get_alignment(16) );
         output( "\t%s\n", func_declaration("__wine_syscall") );
         output( "%s:\n", asm_name("__wine_syscall") );
-        output( "\tjmp *(%s)\n", asm_name("__wine_syscall_dispatcher") );
+        output( "\tjmp *(0x7ffe1000)\n" );
         output_function_size( "__wine_syscall" );
     }
     output( "\t.data\n" );
-- 
2.27.0

