From b9dbb8650b4b339de5e71cf5dab5c3ec321def58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 25 May 2017 21:46:27 +0200
Subject: [PATCH] winebuild: Try to make sure RVA matches between fake and
 builtin DLLs.

---
 dlls/kernel32/tests/loader.c |  1 -
 libs/wine/loader.c           | 13 +++++++++++--
 tools/winebuild/spec32.c     | 17 +++++++++++++++--
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 96cd67ff4..3a441bf7b 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -1579,7 +1579,6 @@ static void test_FakeDLL(void)
         /* check position in memory */
         dll_rva = (DWORD_PTR)dll_func - (DWORD_PTR)module;
         map_rva = funcs[ordinals[i]];
-    todo_wine
         ok(map_rva == dll_rva, "%s: Rva of mapped function (0x%x) does not match dll (0x%x)\n",
            func_name, dll_rva, map_rva);
 
diff --git a/libs/wine/loader.c b/libs/wine/loader.c
index 8f40ea049..163125c9e 100644
--- a/libs/wine/loader.c
+++ b/libs/wine/loader.c
@@ -405,8 +405,12 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
     assert( size <= page_size );
 
     /* module address must be aligned on 64K boundary */
-    addr = (BYTE *)((nt_descr->OptionalHeader.ImageBase + 0xffff) & ~0xffff);
-    if (wine_anon_mmap( addr, page_size, PROT_READ|PROT_WRITE, MAP_FIXED ) != addr) return NULL;
+    addr = *(BYTE **)&nt_descr->OptionalHeader.DataDirectory[15];
+    if (!addr || ((ULONG_PTR)addr & 0xffff) || mprotect( addr, page_size, PROT_READ | PROT_WRITE ))
+    {
+        addr = (BYTE *)((nt_descr->OptionalHeader.ImageBase + 0xffff) & ~0xffff);
+        if (wine_anon_mmap( addr, page_size, PROT_READ|PROT_WRITE, MAP_FIXED ) != addr) return NULL;
+    }
 
     dos    = (IMAGE_DOS_HEADER *)addr;
     nt     = (IMAGE_NT_HEADERS *)(dos + 1);
@@ -453,6 +457,11 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
     nt->OptionalHeader.SizeOfImage                 = data_end;
     nt->OptionalHeader.ImageBase                   = (ULONG_PTR)addr;
 
+    /* Clear DataDirectory[15] */
+
+    nt->OptionalHeader.DataDirectory[15].VirtualAddress = 0;
+    nt->OptionalHeader.DataDirectory[15].Size = 0;
+
     /* Build the code section */
 
     memcpy( sec->Name, ".text", sizeof(".text") );
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 75b2474fa..d0b1367ef 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -378,14 +378,25 @@ static void output_relay_debug( DLLSPEC *spec )
  */
 static void output_syscall_thunks( DLLSPEC *spec )
 {
+    const unsigned int page_size = get_page_size();
     int i;
 
     if (!spec->nb_syscalls)
         return;
 
-    output( "\n/* syscall thunks */\n\n" );
-    output( "\t.text\n" );
+    /* Reserve space for PE header directly before syscalls. */
+    if (target_platform == PLATFORM_APPLE)
+        output( "\t.text\n" );
+    else
+        output( "\n\t.section \".text.startup\"\n" );
+
+    output( "\t.align %d\n", get_alignment(65536) );
+    output( "__wine_spec_pe_header_syscalls:\n" );
+    output( "__wine_spec_pe_header_syscalls_end:\n" );
+    output( "\t.byte 0\n" );
+    output( "\t.balign %d, 0\n", page_size );
 
+    output( "\n/* syscall thunks */\n\n" );
     for (i = 0; i < spec->nb_syscalls; i++)
     {
         ORDDEF *odp = spec->syscalls[i];
@@ -765,6 +776,8 @@ void output_module( DLLSPEC *spec )
         data_dirs[1] = ".L__wine_spec_imports";   /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
     if (spec->nb_resources)
         data_dirs[2] = ".L__wine_spec_resources"; /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
+    if (spec->nb_syscalls)
+        data_dirs[15] = "__wine_spec_pe_header_syscalls";
 
     output_data_directories( data_dirs );
 
-- 
2.20.1

