From 0a60add605563b02ed436e8ce2c5e2de68ea2488 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Thu, 25 May 2017 21:59:41 +0200 Subject: [PATCH] winebuild-Fake_Dlls: Merge several further improvements. --- patches/patchinstall.sh | 25 +- ...-tests-Add-basic-tests-for-fake-dlls.patch | 121 ++++++ ...-not-abuse-WOW32Reserved-field-for-1.patch | 4 +- ...te-syscall-thunks-for-ntdll-exports.patch} | 96 ++++- ...ndows-7-WOW64-signature-for-syscall-.patch | 110 ------ ...ltipass-label-system-to-generate-fak.patch | 13 +- ...uild-Add-stub-functions-in-fake-dlls.patch | 360 ++++++++++++++---- ...uild-Add-syscall-thunks-in-fake-dlls.patch | 64 ++-- ...ze-of-relocation-information-in-fake.patch | 6 +- ...-make-sure-RVA-matches-between-fake-.patch | 104 +++++ ...me-file-alignment-for-fake-and-built.patch | 38 ++ 11 files changed, 683 insertions(+), 258 deletions(-) create mode 100644 patches/winebuild-Fake_Dlls/0001-kernel32-tests-Add-basic-tests-for-fake-dlls.patch rename patches/winebuild-Fake_Dlls/{0001-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch => 0003-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch} (74%) delete mode 100644 patches/winebuild-Fake_Dlls/0003-winebuild-Use-Windows-7-WOW64-signature-for-syscall-.patch create mode 100644 patches/winebuild-Fake_Dlls/0008-winebuild-Try-to-make-sure-RVA-matches-between-fake-.patch create mode 100644 patches/winebuild-Fake_Dlls/0009-libs-wine-Use-same-file-alignment-for-fake-and-built.patch diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 873e207c..4e5af45f 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -8635,29 +8635,34 @@ fi # | * [#42741] Various improvements for fake dlls # | # | Modified files: -# | * dlls/dbghelp/cpu_i386.c, dlls/krnl386.exe16/kernel.c, dlls/krnl386.exe16/kernel16_private.h, -# | dlls/krnl386.exe16/ne_module.c, dlls/krnl386.exe16/ne_segment.c, dlls/krnl386.exe16/task.c, dlls/krnl386.exe16/thunk.c, -# | dlls/krnl386.exe16/wowthunk.c, dlls/ntdll/signal_i386.c, dlls/system.drv16/system.c, dlls/toolhelp.dll16/toolhelp.c, -# | dlls/user.exe16/message.c, dlls/user.exe16/user.c, dlls/user.exe16/window.c, include/winternl.h, -# | tools/winebuild/build.h, tools/winebuild/import.c, tools/winebuild/parser.c, tools/winebuild/relay.c, -# | tools/winebuild/res32.c, tools/winebuild/spec16.c, tools/winebuild/spec32.c, tools/winebuild/utils.c +# | * dlls/dbghelp/cpu_i386.c, dlls/kernel32/tests/loader.c, dlls/krnl386.exe16/kernel.c, +# | dlls/krnl386.exe16/kernel16_private.h, dlls/krnl386.exe16/ne_module.c, dlls/krnl386.exe16/ne_segment.c, +# | dlls/krnl386.exe16/task.c, dlls/krnl386.exe16/thunk.c, dlls/krnl386.exe16/wowthunk.c, dlls/ntdll/signal_i386.c, +# | dlls/system.drv16/system.c, dlls/toolhelp.dll16/toolhelp.c, dlls/user.exe16/message.c, dlls/user.exe16/user.c, +# | dlls/user.exe16/window.c, include/winternl.h, libs/wine/loader.c, tools/winebuild/build.h, tools/winebuild/import.c, +# | tools/winebuild/parser.c, tools/winebuild/relay.c, tools/winebuild/res32.c, tools/winebuild/spec16.c, +# | tools/winebuild/spec32.c, tools/winebuild/utils.c # | if test "$enable_winebuild_Fake_Dlls" -eq 1; then - patch_apply winebuild-Fake_Dlls/0001-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch + patch_apply winebuild-Fake_Dlls/0001-kernel32-tests-Add-basic-tests-for-fake-dlls.patch patch_apply winebuild-Fake_Dlls/0002-krnl386.exe16-Do-not-abuse-WOW32Reserved-field-for-1.patch - patch_apply winebuild-Fake_Dlls/0003-winebuild-Use-Windows-7-WOW64-signature-for-syscall-.patch + patch_apply winebuild-Fake_Dlls/0003-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch patch_apply winebuild-Fake_Dlls/0004-winebuild-Use-multipass-label-system-to-generate-fak.patch patch_apply winebuild-Fake_Dlls/0005-winebuild-Add-stub-functions-in-fake-dlls.patch patch_apply winebuild-Fake_Dlls/0006-winebuild-Add-syscall-thunks-in-fake-dlls.patch patch_apply winebuild-Fake_Dlls/0007-winebuild-Fix-size-of-relocation-information-in-fake.patch + patch_apply winebuild-Fake_Dlls/0008-winebuild-Try-to-make-sure-RVA-matches-between-fake-.patch + patch_apply winebuild-Fake_Dlls/0009-libs-wine-Use-same-file-alignment-for-fake-and-built.patch ( - printf '%s\n' '+ { "Michael Müller", "winebuild: Generate syscall thunks for ntdll exports.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "kernel32/tests: Add basic tests for fake dlls.", 1 },'; printf '%s\n' '+ { "Sebastian Lackner", "krnl386.exe16: Do not abuse WOW32Reserved field for 16-bit stack address.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "winebuild: Use Windows 7 WOW64 signature for syscall thunks.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "winebuild: Generate syscall thunks for ntdll exports.", 1 },'; printf '%s\n' '+ { "Michael Müller", "winebuild: Use multipass label system to generate fake dlls.", 1 },'; printf '%s\n' '+ { "Michael Müller", "winebuild: Add stub functions in fake dlls.", 1 },'; printf '%s\n' '+ { "Michael Müller", "winebuild: Add syscall thunks in fake dlls.", 1 },'; printf '%s\n' '+ { "Michael Müller", "winebuild: Fix size of relocation information in fake dlls.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "winebuild: Try to make sure RVA matches between fake and builtin DLLs.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "libs/wine: Use same file alignment for fake and builtin DLLs.", 1 },'; ) >> "$patchlist" fi diff --git a/patches/winebuild-Fake_Dlls/0001-kernel32-tests-Add-basic-tests-for-fake-dlls.patch b/patches/winebuild-Fake_Dlls/0001-kernel32-tests-Add-basic-tests-for-fake-dlls.patch new file mode 100644 index 00000000..6ad75616 --- /dev/null +++ b/patches/winebuild-Fake_Dlls/0001-kernel32-tests-Add-basic-tests-for-fake-dlls.patch @@ -0,0 +1,121 @@ +From ad01f9c17d660452e2e0179cebc930b6a7650a84 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 25 May 2017 07:02:46 +0200 +Subject: kernel32/tests: Add basic tests for fake dlls. + +--- + dlls/kernel32/tests/loader.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 91 insertions(+) + +diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c +index 2587a973031..44c632bdbcf 100644 +--- a/dlls/kernel32/tests/loader.c ++++ b/dlls/kernel32/tests/loader.c +@@ -831,6 +831,96 @@ static void test_Loader(void) + nt_header.FileHeader.Machine = orig_machine; /* restore it for the next tests */ + } + ++static void test_FakeDLL(void) ++{ ++#ifdef __i386__ ++ NTSTATUS (WINAPI *pNtSetEvent)(HANDLE, ULONG *) = NULL; ++ IMAGE_EXPORT_DIRECTORY *dir; ++ HMODULE module = GetModuleHandleA("ntdll.dll"); ++ HANDLE file, map, event; ++ WCHAR path[MAX_PATH]; ++ DWORD *names, *funcs; ++ WORD *ordinals; ++ ULONG size; ++ void *ptr; ++ int i; ++ ++ GetModuleFileNameW(module, path, MAX_PATH); ++ ++ file = CreateFileW(path, GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); ++ ok(file != INVALID_HANDLE_VALUE, "Failed to open %s (error %u)\n", wine_dbgstr_w(path), GetLastError()); ++ ++ map = CreateFileMappingW(file, NULL, PAGE_EXECUTE_READ | SEC_IMAGE, 0, 0, NULL); ++ ok(map != NULL, "CreateFileMapping failed with error %u\n", GetLastError()); ++ ptr = MapViewOfFile(map, FILE_MAP_READ | FILE_MAP_EXECUTE, 0, 0, 0); ++ ok(ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError()); ++ ++ dir = RtlImageDirectoryEntryToData(ptr, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size); ++todo_wine ++ ok(dir != NULL, "RtlImageDirectoryEntryToData failed\n"); ++ if (dir == NULL) goto done; ++ ++ names = RVAToAddr(dir->AddressOfNames, ptr); ++ ordinals = RVAToAddr(dir->AddressOfNameOrdinals, ptr); ++ funcs = RVAToAddr(dir->AddressOfFunctions, ptr); ++ ok(dir->NumberOfNames > 0, "Could not find any exported functions\n"); ++ ++ for (i = 0; i < dir->NumberOfNames; i++) ++ { ++ DWORD map_rva, dll_rva, map_offset, dll_offset; ++ char *func_name = RVAToAddr(names[i], ptr); ++ BYTE *dll_func, *map_func; ++ ++ /* check only Nt functions for now */ ++ if (strncmp(func_name, "Zw", 2) && strncmp(func_name, "Nt", 2)) ++ continue; ++ ++ dll_func = (BYTE *)GetProcAddress(module, func_name); ++ ok(dll_func != NULL, "%s: GetProcAddress returned NULL\n", func_name); ++ if (dll_func[0] == 0x90 && dll_func[1] == 0x90 && ++ dll_func[2] == 0x90 && dll_func[3] == 0x90) ++ { ++ todo_wine ok(0, "%s: Export is a stub-function, skipping\n", func_name); ++ continue; ++ } ++ ++ /* check position in memory */ ++ dll_rva = (DWORD_PTR)dll_func - (DWORD_PTR)module; ++ map_rva = funcs[ordinals[i]]; ++ 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); ++ ++ /* check position in file */ ++ map_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(ptr), ptr, map_rva, NULL) - (DWORD_PTR)ptr; ++ dll_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(module), module, dll_rva, NULL) - (DWORD_PTR)module; ++ ok(map_offset == dll_offset, "%s: File offset of mapped function (0x%x) does not match dll (0x%x)\n", ++ func_name, map_offset, dll_offset); ++ ++ /* check function content */ ++ map_func = RVAToAddr(map_rva, ptr); ++ ok(!memcmp(map_func, dll_func, 0x20), "%s: Function content does not match!\n", func_name); ++ ++ if (!strcmp(func_name, "NtSetEvent")) ++ pNtSetEvent = (void *)map_func; ++ } ++ ++ ok(pNtSetEvent != NULL, "Could not find NtSetEvent export\n"); ++ if (pNtSetEvent) ++ { ++ event = CreateEventA(NULL, TRUE, FALSE, NULL); ++ ok(event != NULL, "CreateEvent failed with error %u\n", GetLastError()); ++ pNtSetEvent(event, 0); ++ ok(WaitForSingleObject(event, 0) == WAIT_OBJECT_0, "Event was not signaled\n"); ++ CloseHandle(event); ++ } ++ ++done: ++ UnmapViewOfFile(ptr); ++ CloseHandle(map); ++ CloseHandle(file); ++#endif ++} ++ + /* Verify linking style of import descriptors */ + static void test_ImportDescriptors(void) + { +@@ -3065,6 +3155,7 @@ START_TEST(loader) + } + + test_Loader(); ++ test_FakeDLL(); + test_ResolveDelayLoadedAPI(); + test_ImportDescriptors(); + test_section_access(); +-- +2.12.2 + diff --git a/patches/winebuild-Fake_Dlls/0002-krnl386.exe16-Do-not-abuse-WOW32Reserved-field-for-1.patch b/patches/winebuild-Fake_Dlls/0002-krnl386.exe16-Do-not-abuse-WOW32Reserved-field-for-1.patch index 2ff0cb21..a0def794 100644 --- a/patches/winebuild-Fake_Dlls/0002-krnl386.exe16-Do-not-abuse-WOW32Reserved-field-for-1.patch +++ b/patches/winebuild-Fake_Dlls/0002-krnl386.exe16-Do-not-abuse-WOW32Reserved-field-for-1.patch @@ -1,4 +1,4 @@ -From 868ea83da0219cff107fbf1bd3bd1311337fb059 Mon Sep 17 00:00:00 2001 +From 7328ffb1e48698e786ff4b1c8330d50ef24b9ac1 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Tue, 16 May 2017 04:37:52 +0200 Subject: krnl386.exe16: Do not abuse WOW32Reserved field for 16-bit stack @@ -470,7 +470,7 @@ index fa49a246ab8..bd69b844607 100644 } } diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c -index d57daa7984f..f071ea3b79b 100644 +index 59dca6cfca0..d0f25ed3ce4 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -990,7 +990,7 @@ static inline void *init_handler( const ucontext_t *sigcontext, WORD *fs, WORD * diff --git a/patches/winebuild-Fake_Dlls/0001-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch b/patches/winebuild-Fake_Dlls/0003-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch similarity index 74% rename from patches/winebuild-Fake_Dlls/0001-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch rename to patches/winebuild-Fake_Dlls/0003-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch index fd3b6a7b..8a7a19a6 100644 --- a/patches/winebuild-Fake_Dlls/0001-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch +++ b/patches/winebuild-Fake_Dlls/0003-winebuild-Generate-syscall-thunks-for-ntdll-exports.patch @@ -1,18 +1,53 @@ -From 93a459d285bde2b97a7c333a76e6a2e788a52a5e Mon Sep 17 00:00:00 2001 +From 5cdd660ebd413914330fa49e9d7014c9056662c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Thu, 11 May 2017 05:32:55 +0200 Subject: winebuild: Generate syscall thunks for ntdll exports. Based on a patch by Erich E. Hoover. --- + dlls/ntdll/signal_i386.c | 2 ++ + include/winternl.h | 2 +- tools/winebuild/build.h | 6 +++++ - tools/winebuild/import.c | 10 ++++---- - tools/winebuild/parser.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ - tools/winebuild/spec16.c | 22 +----------------- - tools/winebuild/spec32.c | 45 ++++++++++++++++++++++++++++++++++++ - tools/winebuild/utils.c | 21 +++++++++++++++++ - 6 files changed, 138 insertions(+), 25 deletions(-) + tools/winebuild/import.c | 10 ++++--- + tools/winebuild/parser.c | 59 +++++++++++++++++++++++++++++++++++++++++ + tools/winebuild/spec16.c | 22 +--------------- + tools/winebuild/spec32.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ + tools/winebuild/utils.c | 21 +++++++++++++++ + 8 files changed, 164 insertions(+), 26 deletions(-) +diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c +index d0f25ed3ce4..cd7d0dff493 100644 +--- a/dlls/ntdll/signal_i386.c ++++ b/dlls/ntdll/signal_i386.c +@@ -481,6 +481,7 @@ static wine_signal_handler handlers[256]; + static BOOL fpux_support; /* whether the CPU supports extended fpu context */ + + extern void DECLSPEC_NORETURN __wine_restore_regs( const CONTEXT *context ); ++extern void DECLSPEC_NORETURN __wine_syscall_dispatcher( void ); + + enum i386_trap_code + { +@@ -2363,6 +2364,7 @@ NTSTATUS signal_alloc_thread( TEB **teb ) + *teb = addr; + (*teb)->Tib.Self = &(*teb)->Tib; + (*teb)->Tib.ExceptionList = (void *)~0UL; ++ (*teb)->WOW32Reserved = __wine_syscall_dispatcher; + thread_data = (struct ntdll_thread_data *)(*teb)->SpareBytes1; + if (!(thread_data->fs = wine_ldt_alloc_fs())) + { +diff --git a/include/winternl.h b/include/winternl.h +index ae3163daeac..6b0624290fa 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -322,7 +322,7 @@ typedef struct _TEB + PVOID CsrClientThread; /* 03c/0070 */ + PVOID Win32ThreadInfo; /* 040/0078 */ + ULONG Win32ClientInfo[31]; /* 044/0080 used for user32 private data in Wine */ +- PVOID WOW32Reserved; /* 0c0/0100 */ ++ PVOID WOW32Reserved; /* 0c0/0100 used for ntdll syscall thunks */ + ULONG CurrentLocale; /* 0c4/0108 */ + ULONG FpSoftwareStatusRegister; /* 0c8/010c */ + PVOID SystemReserved1[54]; /* 0cc/0110 used for krnl386.exe16 private data in Wine */ diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 398d54200c7..e338c9c8024 100644 --- a/tools/winebuild/build.h @@ -230,10 +265,10 @@ index 85bcf099999..54aad5d95b4 100644 entry_point->u.func.nb_args = 0; assert( !spec->ordinals[0] ); diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c -index f3feb0f3300..fbde7ce6937 100644 +index f3feb0f3300..dde1bd0704d 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c -@@ -274,6 +274,50 @@ static void output_relay_debug( DLLSPEC *spec ) +@@ -274,6 +274,73 @@ static void output_relay_debug( DLLSPEC *spec ) } /******************************************************************* @@ -256,42 +291,65 @@ index f3feb0f3300..fbde7ce6937 100644 + ORDDEF *odp = spec->syscalls[i]; + const char *name = odp->link_name; + -+ output( "\t.align %d\n", get_alignment(16) ); ++ output( "\t.balign %d, 0\n", get_alignment(16) ); + output( "\t%s\n", func_declaration(name) ); + output( "%s\n", asm_globl(name) ); + output_cfi( ".cfi_startproc" ); -+ output( "\tmovl $%s, %%eax\n", asm_name(odp->impl_name) ); -+ output( "\tmovl $__wine_syscall_dispatcher, %%edx\n" ); -+ output( "\tcall *%%edx\n" ); -+ output( "\tret $%d\n", get_args_size(odp) ); ++ output( "\t.byte 0xb8\n" ); /* mov eax, SYSCALL */ ++ output( "\t.long %d\n", i ); ++ output( "\t.byte 0x33,0xc9\n" ); /* xor ecx, ecx */ ++ output( "\t.byte 0x8d,0x54,0x24,0x04\n" ); /* lea edx, [esp + 4] */ ++ output( "\t.byte 0x64,0xff,0x15,0xc0,0x00,0x00,0x00\n" ); /* call dword ptr fs:[0C0h] */ ++ output( "\t.byte 0x83,0xc4,0x04\n" ); /* add esp, 4 */ ++ output( "\t.byte 0xc2\n" ); /* ret X */ ++ output( "\t.short %d\n", get_args_size(odp) ); + output_cfi( ".cfi_endproc" ); + output_function_size( name ); + } + ++ for (i = 0; i < 0x20; i++) ++ output( "\t.byte 0\n" ); ++ ++ output( "\n/* syscall table */\n\n" ); ++ output( "\t.data\n" ); ++ output( "%s\n", asm_globl("__wine_syscall_table") ); ++ for (i = 0; i < spec->nb_syscalls; i++) ++ { ++ ORDDEF *odp = spec->syscalls[i]; ++ output ("\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->impl_name) ); ++ } ++ ++ output( "\n/* syscall dispatcher */\n\n" ); ++ output( "\t.text\n" ); + output( "\t.align %d\n", get_alignment(16) ); + output( "\t%s\n", func_declaration("__wine_syscall_dispatcher") ); + output( "%s\n", asm_globl("__wine_syscall_dispatcher") ); + output_cfi( ".cfi_startproc" ); + output( "\tadd $4, %%esp\n" ); -+ output( "\tjmp *%%eax\n" ); ++ if (UsePIC) ++ { ++ output( "\tcall 1f\n" ); ++ output( "1:\tpopl %%ecx\n" ); ++ output( "\tjmpl *(%s-1b)(%%ecx,%%eax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() ); ++ } ++ else output( "\tjmpl *%s(,%%eax,4)\n", asm_name("__wine_syscall_table") ); + output( "\tret\n" ); + output_cfi( ".cfi_endproc" ); + output_function_size( "__wine_syscall_dispatcher" ); -+ output( "\t.previous\n" ); +} + +/******************************************************************* * output_exports * * Output the export table for a Win32 module. -@@ -624,6 +668,7 @@ void BuildSpec32File( DLLSPEC *spec ) +@@ -623,6 +690,7 @@ void BuildSpec32File( DLLSPEC *spec ) + resolve_imports( spec ); output_standard_file_header(); output_module( spec ); - output_stubs( spec ); + output_syscall_thunks( spec ); + output_stubs( spec ); output_exports( spec ); output_imports( spec ); - if (is_undefined( "__wine_call_from_regs" )) output_asm_relays(); diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index 6e01f1a5268..925054b8bb7 100644 --- a/tools/winebuild/utils.c diff --git a/patches/winebuild-Fake_Dlls/0003-winebuild-Use-Windows-7-WOW64-signature-for-syscall-.patch b/patches/winebuild-Fake_Dlls/0003-winebuild-Use-Windows-7-WOW64-signature-for-syscall-.patch deleted file mode 100644 index cd615ebb..00000000 --- a/patches/winebuild-Fake_Dlls/0003-winebuild-Use-Windows-7-WOW64-signature-for-syscall-.patch +++ /dev/null @@ -1,110 +0,0 @@ -From cb2fdb23a11f80c0468e04507b8393eaef5b1bb6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Fri, 12 May 2017 04:05:24 +0200 -Subject: winebuild: Use Windows 7 WOW64 signature for syscall thunks. - ---- - dlls/ntdll/signal_i386.c | 2 ++ - include/winternl.h | 2 +- - tools/winebuild/spec32.c | 37 ++++++++++++++++++++++++++++++------- - 3 files changed, 33 insertions(+), 8 deletions(-) - -diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c -index d0f25ed3ce4..cd7d0dff493 100644 ---- a/dlls/ntdll/signal_i386.c -+++ b/dlls/ntdll/signal_i386.c -@@ -481,6 +481,7 @@ static wine_signal_handler handlers[256]; - static BOOL fpux_support; /* whether the CPU supports extended fpu context */ - - extern void DECLSPEC_NORETURN __wine_restore_regs( const CONTEXT *context ); -+extern void DECLSPEC_NORETURN __wine_syscall_dispatcher( void ); - - enum i386_trap_code - { -@@ -2363,6 +2364,7 @@ NTSTATUS signal_alloc_thread( TEB **teb ) - *teb = addr; - (*teb)->Tib.Self = &(*teb)->Tib; - (*teb)->Tib.ExceptionList = (void *)~0UL; -+ (*teb)->WOW32Reserved = __wine_syscall_dispatcher; - thread_data = (struct ntdll_thread_data *)(*teb)->SpareBytes1; - if (!(thread_data->fs = wine_ldt_alloc_fs())) - { -diff --git a/include/winternl.h b/include/winternl.h -index ae3163daeac..6b0624290fa 100644 ---- a/include/winternl.h -+++ b/include/winternl.h -@@ -322,7 +322,7 @@ typedef struct _TEB - PVOID CsrClientThread; /* 03c/0070 */ - PVOID Win32ThreadInfo; /* 040/0078 */ - ULONG Win32ClientInfo[31]; /* 044/0080 used for user32 private data in Wine */ -- PVOID WOW32Reserved; /* 0c0/0100 */ -+ PVOID WOW32Reserved; /* 0c0/0100 used for ntdll syscall thunks */ - ULONG CurrentLocale; /* 0c4/0108 */ - ULONG FpSoftwareStatusRegister; /* 0c8/010c */ - PVOID SystemReserved1[54]; /* 0cc/0110 used for krnl386.exe16 private data in Wine */ -diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c -index fbde7ce6937..76dcc94bfa1 100644 ---- a/tools/winebuild/spec32.c -+++ b/tools/winebuild/spec32.c -@@ -293,28 +293,51 @@ static void output_syscall_thunks( DLLSPEC *spec ) - ORDDEF *odp = spec->syscalls[i]; - const char *name = odp->link_name; - -- output( "\t.align %d\n", get_alignment(16) ); -+ output( "\t.balign %d, 0\n", get_alignment(16) ); - output( "\t%s\n", func_declaration(name) ); - output( "%s\n", asm_globl(name) ); - output_cfi( ".cfi_startproc" ); -- output( "\tmovl $%s, %%eax\n", asm_name(odp->impl_name) ); -- output( "\tmovl $__wine_syscall_dispatcher, %%edx\n" ); -- output( "\tcall *%%edx\n" ); -- output( "\tret $%d\n", get_args_size(odp) ); -+ output( "\t.byte 0xb8\n" ); /* mov eax, SYSCALL */ -+ output( "\t.long %d\n", i ); -+ output( "\t.byte 0x33,0xc9\n" ); /* xor ecx, ecx */ -+ output( "\t.byte 0x8d,0x54,0x24,0x04\n" ); /* lea edx, [esp + 4] */ -+ output( "\t.byte 0x64,0xff,0x15,0xc0,0x00,0x00,0x00\n" ); /* call dword ptr fs:[0C0h] */ -+ output( "\t.byte 0x83,0xc4,0x04\n" ); /* add esp, 4 */ -+ output( "\t.byte 0xc2\n" ); /* ret X */ -+ output( "\t.short %d\n", get_args_size(odp) ); - output_cfi( ".cfi_endproc" ); - output_function_size( name ); - } - -+ for (i = 0; i < 0x20; i++) -+ output( "\t.byte 0\n" ); -+ -+ output( "\n/* syscall table */\n\n" ); -+ output( "\t.data\n" ); -+ output( "%s\n", asm_globl("__wine_syscall_table") ); -+ for (i = 0; i < spec->nb_syscalls; i++) -+ { -+ ORDDEF *odp = spec->syscalls[i]; -+ output ("\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->impl_name) ); -+ } -+ -+ output( "\n/* syscall dispatcher */\n\n" ); -+ output( "\t.text\n" ); - output( "\t.align %d\n", get_alignment(16) ); - output( "\t%s\n", func_declaration("__wine_syscall_dispatcher") ); - output( "%s\n", asm_globl("__wine_syscall_dispatcher") ); - output_cfi( ".cfi_startproc" ); - output( "\tadd $4, %%esp\n" ); -- output( "\tjmp *%%eax\n" ); -+ if (UsePIC) -+ { -+ output( "\tcall 1f\n" ); -+ output( "1:\tpopl %%ecx\n" ); -+ output( "\tjmpl *(%s-1b)(%%ecx,%%eax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() ); -+ } -+ else output( "\tjmpl *%s(,%%eax,4)\n", asm_name("__wine_syscall_table") ); - output( "\tret\n" ); - output_cfi( ".cfi_endproc" ); - output_function_size( "__wine_syscall_dispatcher" ); -- output( "\t.previous\n" ); - } - - /******************************************************************* --- -2.12.2 - diff --git a/patches/winebuild-Fake_Dlls/0004-winebuild-Use-multipass-label-system-to-generate-fak.patch b/patches/winebuild-Fake_Dlls/0004-winebuild-Use-multipass-label-system-to-generate-fak.patch index 98193094..d5157109 100644 --- a/patches/winebuild-Fake_Dlls/0004-winebuild-Use-multipass-label-system-to-generate-fak.patch +++ b/patches/winebuild-Fake_Dlls/0004-winebuild-Use-multipass-label-system-to-generate-fak.patch @@ -1,4 +1,4 @@ -From dd66c26e64f14e3b72716449147a656a87232482 Mon Sep 17 00:00:00 2001 +From 135039777d3d6a79580661221cf4f394d390d5fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 15 May 2017 02:05:49 +0200 Subject: winebuild: Use multipass label system to generate fake dlls. @@ -6,9 +6,9 @@ Subject: winebuild: Use multipass label system to generate fake dlls. --- tools/winebuild/build.h | 6 ++ tools/winebuild/res32.c | 1 - - tools/winebuild/spec32.c | 144 ++++++++++++++++++++++++++--------------------- + tools/winebuild/spec32.c | 145 +++++++++++++++++++++++++++-------------------- tools/winebuild/utils.c | 92 ++++++++++++++++++++++++++++++ - 4 files changed, 179 insertions(+), 64 deletions(-) + 4 files changed, 180 insertions(+), 64 deletions(-) diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index e338c9c8024..3434cfe9c90 100644 @@ -47,7 +47,7 @@ index 1686f567185..8db3213fbbd 100644 /* output the resource directories */ diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c -index 7e08b756df4..bc47cd7b32e 100644 +index dde1bd0704d..c01ff6d7746 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -702,11 +702,11 @@ void BuildSpec32File( DLLSPEC *spec ) @@ -107,7 +107,7 @@ index 7e08b756df4..bc47cd7b32e 100644 put_dword( 0 ); /* SizeOfUninitializedData */ - put_dword( section_align ); /* AddressOfEntryPoint */ - put_dword( section_align ); /* BaseOfCode */ -+ put_dword( label_rva("text_start") ); /* AddressOfEntryPoint */ ++ put_dword( label_rva("entrypoint") ); /* AddressOfEntryPoint */ + put_dword( label_rva("text_start") ); /* BaseOfCode */ if (get_ptr_size() == 4) put_dword( 0 ); /* BaseOfData */ put_pword( 0x10000000 ); /* ImageBase */ @@ -148,7 +148,7 @@ index 7e08b756df4..bc47cd7b32e 100644 put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_COPYRIGHT] */ put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR] */ -@@ -842,62 +828,94 @@ void output_fake_module( DLLSPEC *spec ) +@@ -842,62 +828,95 @@ void output_fake_module( DLLSPEC *spec ) put_dword( 0 ); put_dword( 0 ); /* DataDirectory[15] */ /* .text section */ @@ -227,6 +227,7 @@ index 7e08b756df4..bc47cd7b32e 100644 - align_output( file_align ); + align_output_rva( file_align, section_align ); + put_label( "text_start" ); ++ put_label( "entrypoint" ); if (spec->characteristics & IMAGE_FILE_DLL) put_data( dll_code_section, sizeof(dll_code_section) ); else diff --git a/patches/winebuild-Fake_Dlls/0005-winebuild-Add-stub-functions-in-fake-dlls.patch b/patches/winebuild-Fake_Dlls/0005-winebuild-Add-stub-functions-in-fake-dlls.patch index be80382c..c286050a 100644 --- a/patches/winebuild-Fake_Dlls/0005-winebuild-Add-stub-functions-in-fake-dlls.patch +++ b/patches/winebuild-Fake_Dlls/0005-winebuild-Add-stub-functions-in-fake-dlls.patch @@ -1,50 +1,136 @@ -From d9cb75b157dd6929d99c5a7b0b37639d87cfa0dd Mon Sep 17 00:00:00 2001 +From 3cb1a8e8983c58da032185ca1d76bc4d3a2a15e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 15 May 2017 16:27:56 +0200 Subject: winebuild: Add stub functions in fake dlls. --- - dlls/ntdll/signal_i386.c | 17 +++++++ - tools/winebuild/build.h | 1 + - tools/winebuild/spec32.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++- - tools/winebuild/utils.c | 10 +++- - 4 files changed, 141 insertions(+), 4 deletions(-) + dlls/kernel32/tests/loader.c | 8 +- + dlls/ntdll/signal_i386.c | 40 +++++++++ + include/winternl.h | 2 +- + tools/winebuild/build.h | 1 + + tools/winebuild/spec32.c | 209 +++++++++++++++++++++++++++++++++++++++++-- + tools/winebuild/utils.c | 10 ++- + 6 files changed, 255 insertions(+), 15 deletions(-) +diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c +index 44c632bdbcf..cfbee0851b5 100644 +--- a/dlls/kernel32/tests/loader.c ++++ b/dlls/kernel32/tests/loader.c +@@ -856,9 +856,7 @@ static void test_FakeDLL(void) + ok(ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError()); + + dir = RtlImageDirectoryEntryToData(ptr, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size); +-todo_wine + ok(dir != NULL, "RtlImageDirectoryEntryToData failed\n"); +- if (dir == NULL) goto done; + + names = RVAToAddr(dir->AddressOfNames, ptr); + ordinals = RVAToAddr(dir->AddressOfNameOrdinals, ptr); +@@ -887,17 +885,20 @@ todo_wine + /* 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); + + /* check position in file */ + map_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(ptr), ptr, map_rva, NULL) - (DWORD_PTR)ptr; + dll_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(module), module, dll_rva, NULL) - (DWORD_PTR)module; ++ todo_wine + ok(map_offset == dll_offset, "%s: File offset of mapped function (0x%x) does not match dll (0x%x)\n", + func_name, map_offset, dll_offset); + + /* check function content */ + map_func = RVAToAddr(map_rva, ptr); ++ todo_wine + ok(!memcmp(map_func, dll_func, 0x20), "%s: Function content does not match!\n", func_name); + + if (!strcmp(func_name, "NtSetEvent")) +@@ -911,10 +912,11 @@ todo_wine + ok(event != NULL, "CreateEvent failed with error %u\n", GetLastError()); + pNtSetEvent(event, 0); + ok(WaitForSingleObject(event, 0) == WAIT_OBJECT_0, "Event was not signaled\n"); ++ pNtSetEvent(event, 0); ++ ok(WaitForSingleObject(event, 0) == WAIT_OBJECT_0, "Event was not signaled\n"); + CloseHandle(event); + } + +-done: + UnmapViewOfFile(ptr); + CloseHandle(map); + CloseHandle(file); diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c -index 115f48d3dd1..3730afd38e0 100644 +index cd7d0dff493..b1ec20e8723 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c -@@ -1904,6 +1904,20 @@ static inline DWORD get_fpu_code( const CONTEXT *context ) - return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */ - } +@@ -483,6 +483,45 @@ static BOOL fpux_support; /* whether the CPU supports extended fpu context */ + extern void DECLSPEC_NORETURN __wine_restore_regs( const CONTEXT *context ); + extern void DECLSPEC_NORETURN __wine_syscall_dispatcher( void ); -+static void fakedll_stub ( CONTEXT *context ) ++/* convert from straight ASCII to Unicode without depending on the current codepage */ ++static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len ) +{ -+ EXCEPTION_RECORD record; -+ -+ record.ExceptionCode = EXCEPTION_WINE_STUB; -+ record.ExceptionFlags = EH_NONCONTINUABLE; -+ record.ExceptionRecord = NULL; -+ record.ExceptionAddress = (void*)context->Eip; -+ record.NumberParameters = 2; -+ record.ExceptionInformation[0] = (ULONG_PTR)context->Ecx; -+ record.ExceptionInformation[1] = (ULONG_PTR)context->Edx; -+ -+ for (;;) NtRaiseException( &record, context, TRUE ); ++ while (len--) *dst++ = (unsigned char)*src++; +} - - /********************************************************************** - * raise_segv_exception -@@ -1963,6 +1977,9 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context - } - break; - case EXCEPTION_WINE_SYSCALL: -+ if (rec->ExceptionInformation[0] == 0xdeadc0de) -+ fakedll_stub( context ); + - FIXME("unimplemented syscall handler for 0x%lx, stack 0x%lx\n", - rec->ExceptionInformation[0], rec->ExceptionInformation[1]); - context->Eax = STATUS_INVALID_SYSTEM_SERVICE; ++static void* WINAPI __wine_fakedll_dispatcher( const char *module, ULONG ord ) ++{ ++ UNICODE_STRING name; ++ NTSTATUS status; ++ HMODULE base; ++ WCHAR *moduleW; ++ void *proc = NULL; ++ DWORD len = strlen(module); ++ ++ TRACE( "(%s, %u)\n", debugstr_a(module), ord ); ++ ++ if (!(moduleW = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) ++ return NULL; ++ ++ ascii_to_unicode( moduleW, module, len ); ++ moduleW[ len ] = 0; ++ RtlInitUnicodeString( &name, moduleW ); ++ ++ status = LdrGetDllHandle( NULL, 0, &name, &base ); ++ if (status == STATUS_DLL_NOT_FOUND) ++ status = LdrLoadDll( NULL, 0, &name, &base ); ++ if (status == STATUS_SUCCESS) ++ status = LdrAddRefDll( LDR_ADDREF_DLL_PIN, base ); ++ if (status == STATUS_SUCCESS) ++ status = LdrGetProcedureAddress( base, NULL, ord, &proc ); ++ ++ if (status) ++ FIXME( "No procedure address found for %s.#%u, status %x\n", debugstr_a(module), ord, status ); ++ ++ RtlFreeHeap( GetProcessHeap(), 0, moduleW ); ++ return proc; ++} ++ + enum i386_trap_code + { + TRAP_x86_UNKNOWN = -1, /* Unknown fault (TRAP_sig not defined) */ +@@ -2365,6 +2404,7 @@ NTSTATUS signal_alloc_thread( TEB **teb ) + (*teb)->Tib.Self = &(*teb)->Tib; + (*teb)->Tib.ExceptionList = (void *)~0UL; + (*teb)->WOW32Reserved = __wine_syscall_dispatcher; ++ (*teb)->Spare3 = __wine_fakedll_dispatcher; + thread_data = (struct ntdll_thread_data *)(*teb)->SpareBytes1; + if (!(thread_data->fs = wine_ldt_alloc_fs())) + { +diff --git a/include/winternl.h b/include/winternl.h +index 6b0624290fa..8b87f37c65c 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -362,7 +362,7 @@ typedef struct _TEB + PVOID WinSockData; /* f6c/1738 */ + ULONG GdiBatchCount; /* f70/1740 */ + ULONG Spare2; /* f74/1744 */ +- PVOID Spare3; /* f78/1748 */ ++ PVOID Spare3; /* f78/1748 used for fakedll thunks */ + PVOID Spare4; /* f7c/1750 */ + PVOID ReservedForOle; /* f80/1758 */ + ULONG WaitingOnLoaderLock; /* f84/1760 */ diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 3434cfe9c90..e76800bb5da 100644 --- a/tools/winebuild/build.h @@ -58,66 +144,106 @@ index 3434cfe9c90..e76800bb5da 100644 extern void align_output_rva( unsigned int file_align, unsigned int rva_align ); extern size_t label_pos( const char *name ); diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c -index bc47cd7b32e..e2f7dcf43e0 100644 +index c01ff6d7746..4367b03b0d2 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c -@@ -701,6 +701,113 @@ void BuildSpec32File( DLLSPEC *spec ) +@@ -701,6 +701,163 @@ void BuildSpec32File( DLLSPEC *spec ) } -+static void create_stub_exports_x86( DLLSPEC *spec ) ++static int needs_stub_exports( DLLSPEC *spec ) ++{ ++ if (target_cpu != CPU_x86) ++ return 0; ++ if (!(spec->characteristics & IMAGE_FILE_DLL)) ++ return 0; ++ if (!spec->nb_entry_points) ++ return 0; ++ return 1; ++} ++ ++ ++static void create_stub_exports_text( DLLSPEC *spec ) +{ -+ static const unsigned char dll_main[] = { 0xb8, 0x01, 0x00, 0x00, 0x00, /* mov eax, 0x1 */ -+ 0xc2, 0x0c, 0x00 }; /* ret 12 */ + int i, nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; -+ -+ /* entry function */ -+ put_data( dll_main, sizeof(dll_main) ); -+ -+ if (!nr_exports) return; -+ -+ /* pic thunk function */ -+ align_output_rva( 16, 16 ); -+ put_label( "_thunk_eax" ); -+ put_byte( 0x8b ); put_byte( 0x04 ); put_byte( 0x24 ); /* mov eax, dword[esp] */ -+ put_byte( 0xc3 ); /* ret */ ++ size_t rva, thunk; + + /* output stub code for exports */ + for (i = 0; i < spec->nb_entry_points; i++) + { + ORDDEF *odp = &spec->entry_points[i]; + const char *name = get_stub_name( odp, spec ); -+ size_t rva; + + align_output_rva( 16, 16 ); + put_label( name ); -+ + put_byte( 0x8b ); put_byte( 0xff ); /* mov edi, edi */ + put_byte( 0x55 ); /* push ebp */ + put_byte( 0x8b ); put_byte( 0xec ); /* mov ebp, esp */ ++ put_byte( 0x68 ); put_dword( 0 ); /* push dword 0 */ ++ put_byte( 0x68 ); put_dword( odp->ordinal ); /* push ORDINAL */ + rva = output_buffer_rva + 5; -+ put_byte( 0xe8 ); put_dword( label_rva("_thunk_eax") - rva ); /* call _thunk_eax */ -+ put_byte( 0x8d ); put_byte( 0x88 ); /* lea ecx, [eax + dll_name] */ -+ put_dword( label_rva("dll_fake_name") - rva ); -+ if (!odp->name || (odp->flags & FLAG_NONAME)) ++ put_byte( 0xe8 ); put_dword( label_rva("_forward") - rva ); /* call _forward */ ++ put_byte( 0x89 ); put_byte( 0xec ); /* mov esp, ebp */ ++ put_byte( 0x5d ); /* pop ebp */ ++ if (odp->type == TYPE_STDCALL || odp->type == TYPE_THISCALL) + { -+ put_byte( 0xba ); put_dword( odp->ordinal ); /* mov edx, ordinal */ ++ put_byte( 0xc2 ); put_word( get_args_size(odp) ); /* ret X */ + } + else + { -+ put_byte( 0x8d ); put_byte( 0x90 ); /* lea edx, [eax + func_name] */ -+ put_dword( label_rva(strmake("str_%s", name)) - rva ); ++ put_byte( 0xc3 ); /* ret */ + } -+ put_byte( 0xb8 ); put_dword( 0xdeadc0de ); /* mov eax, 0xdeadc0de */ -+ put_byte( 0xcd ); put_byte( 0x2e ); /* int 0x2e */ -+ put_byte( 0x5d ); /* pop ebp */ -+ put_byte( 0xc3 ); /* ret */ + } + -+ /* name to show in stub message */ ++ /* output entry point */ + align_output_rva( 16, 16 ); -+ put_label( "dll_fake_name" ); -+ put_str( strmake("(fake) %s", spec->file_name) ); ++ put_label( "entrypoint" ); ++ put_byte( 0xb8 ); put_dword( 1 ); /* mov eax, 1 */ ++ put_byte( 0xc2 ); put_word( 12 ); /* ret 12 */ ++ ++ /* output forward function */ ++ align_output_rva( 16, 16 ); ++ put_label( "_forward" ); ++ put_byte( 0x8b ); put_byte( 0x6d ); put_byte( 0x00 ); /* mov ebp, dword[ebp] */ ++ put_byte( 0x89 ); put_byte( 0x44 ); /* mov dword[esp+8], eax */ ++ put_byte( 0x24 ); put_byte( 0x08 ); ++ put_byte( 0x89 ); put_byte( 0x14 ); put_byte( 0x24 ); /* mov dword[esp], edx */ ++ put_byte( 0x8b ); put_byte( 0x54 ); /* mov edx, dword[esp+4] */ ++ put_byte( 0x24 ); put_byte( 0x04 ); ++ put_byte( 0x89 ); put_byte( 0x4c ); /* mov dword[esp+4], ecx */ ++ put_byte( 0x24 ); put_byte( 0x04 ); ++ put_byte( 0xe8 ); put_dword( 0 ); /* call 1f */ ++ thunk = output_buffer_rva; ++ put_byte( 0x59 ); /* pop ecx */ ++ put_byte( 0x8b ); put_byte( 0x84 ); put_byte( 0x91 ); /* mov eax, dword[_functions + 4 * (edx - BASE)] */ ++ put_dword( label_rva("_functions") - thunk - 4 * spec->base ); ++ put_byte( 0x09 ); put_byte( 0xc0 ); /* or eax, eax */ ++ rva = output_buffer_rva + 2; ++ put_byte( 0x74 ); put_byte( label_rva("_forward_load") - rva ); /* je _forward_load */ ++ ++ put_label( "_forward_done" ); ++ put_byte( 0x89 ); put_byte( 0x44 ); /* mov dword[esp+12], eax */ ++ put_byte( 0x24 ); put_byte( 0x0c ); ++ put_byte( 0x5a ); /* pop edx */ ++ put_byte( 0x59 ); /* pop ecx */ ++ put_byte( 0x58 ); /* pop eax */ ++ put_byte( 0xc3 ); /* ret */ ++ ++ align_output_rva( 16, 16 ); ++ put_label( "_forward_load" ); ++ put_byte( 0x8d ); put_byte( 0x84 ); put_byte( 0x91 ); /* lea eax, [_functions + 4 * (edx - BASE)] */ ++ put_dword( label_rva("_functions") - thunk - 4 * spec->base ); ++ put_byte( 0x50 ); /* push eax */ ++ put_byte( 0x52 ); /* push edx */ ++ put_byte( 0x8d ); put_byte( 0x81 ); /* lea eax, [dll_name] */ ++ put_dword( label_rva("dll_name") - thunk ); ++ put_byte( 0x50 ); /* push eax */ ++ put_byte( 0x64 ); put_byte( 0xff ); /* call dword ptr fs:[0F78h] */ ++ put_byte( 0x15 ); put_dword( 0xf78 ); ++ put_byte( 0x5a ); /* pop edx */ ++ put_byte( 0x89 ); put_byte( 0x02 ); /* mov dword[edx], eax */ ++ rva = output_buffer_rva + 2; ++ put_byte( 0xeb ); put_byte( label_rva("_forward_done") - rva ); /* jmp _forward_done */ + + /* export directory */ + align_output_rva( 16, 16 ); @@ -171,11 +297,39 @@ index bc47cd7b32e..e2f7dcf43e0 100644 + put_label( "export_end" ); +} + ++ ++static void create_stub_exports_data( DLLSPEC *spec ) ++{ ++ int i; ++ ++ put_label( "_functions" ); ++ for (i = spec->base; i <= spec->limit; i++) ++ put_dword( 0 ); ++} ++ + /******************************************************************* * output_fake_module_pass * -@@ -799,7 +906,8 @@ static void output_fake_module_pass( DLLSPEC *spec ) +@@ -719,7 +876,7 @@ static void output_fake_module_pass( DLLSPEC *spec ) + const unsigned int section_align = page_size; + const unsigned int file_align = 0x200; + const unsigned int lfanew = (0x40 + sizeof(fakedll_signature) + 15) & ~15; +- const unsigned int nb_sections = 2 + (spec->nb_resources != 0); ++ const unsigned int nb_sections = 2 + (needs_stub_exports( spec ) != 0) + (spec->nb_resources != 0); + + put_word( 0x5a4d ); /* e_magic */ + put_word( 0x40 ); /* e_cblp */ +@@ -776,7 +933,7 @@ static void output_fake_module_pass( DLLSPEC *spec ) + put_dword( 0 ); /* SizeOfUninitializedData */ + put_dword( label_rva("entrypoint") ); /* AddressOfEntryPoint */ + put_dword( label_rva("text_start") ); /* BaseOfCode */ +- if (get_ptr_size() == 4) put_dword( 0 ); /* BaseOfData */ ++ if (get_ptr_size() == 4) put_dword( label_rva("data_start") ); /* BaseOfData */ + put_pword( 0x10000000 ); /* ImageBase */ + put_dword( section_align ); /* SectionAlignment */ + put_dword( file_align ); /* FileAlignment */ +@@ -799,7 +956,8 @@ static void output_fake_module_pass( DLLSPEC *spec ) put_dword( 0 ); /* LoaderFlags */ put_dword( 16 ); /* NumberOfRvaAndSizes */ @@ -185,22 +339,68 @@ index bc47cd7b32e..e2f7dcf43e0 100644 put_dword( 0 ); put_dword( 0 ); /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */ if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */ { -@@ -873,7 +981,12 @@ static void output_fake_module_pass( DLLSPEC *spec ) - align_output_rva( file_align, section_align ); - put_label( "text_start" ); - if (spec->characteristics & IMAGE_FILE_DLL) -- put_data( dll_code_section, sizeof(dll_code_section) ); +@@ -839,6 +997,21 @@ static void output_fake_module_pass( DLLSPEC *spec ) + put_word( 0 ); /* NumberOfLinenumbers */ + put_dword( 0x60000020 /* CNT_CODE|MEM_EXECUTE|MEM_READ */ ); /* Characteristics */ + ++ /* .data section */ ++ if (needs_stub_exports( spec )) + { -+ if (target_cpu == CPU_x86) -+ create_stub_exports_x86( spec ); -+ else -+ put_data( dll_code_section, sizeof(dll_code_section) ); ++ put_data( ".data\0\0", 8 ); /* Name */ ++ put_dword( label_rva_align("data_end") - label_rva("data_start") ); /* VirtualSize */ ++ put_dword( label_rva("data_start") ); /* VirtualAddress */ ++ put_dword( label_pos("data_end") - label_pos("data_start") ); /* SizeOfRawData */ ++ put_dword( label_pos("data_start") ); /* PointerToRawData */ ++ put_dword( 0 ); /* PointerToRelocations */ ++ put_dword( 0 ); /* PointerToLinenumbers */ ++ put_word( 0 ); /* NumberOfRelocations */ ++ put_word( 0 ); /* NumberOfLinenumbers */ ++ put_dword( 0xc0000040 /* CNT_INITIALIZED_DATA|MEM_READ|MEM_WRITE */ ); /* Characteristics */ ++ } ++ + /* .reloc section */ + put_data( ".reloc\0", 8 ); /* Name */ + put_dword( label_rva_align("reloc_end") - label_rva("reloc_start") ); /* VirtualSize */ +@@ -871,13 +1044,31 @@ static void output_fake_module_pass( DLLSPEC *spec ) + + /* .text contents */ + align_output_rva( file_align, section_align ); +- put_label( "text_start" ); +- put_label( "entrypoint" ); +- if (spec->characteristics & IMAGE_FILE_DLL) +- put_data( dll_code_section, sizeof(dll_code_section) ); ++ if (needs_stub_exports( spec )) ++ { ++ put_label( "text_start" ); ++ create_stub_exports_text( spec ); ++ put_label( "text_end" ); + } else - put_data( exe_code_section, sizeof(exe_code_section) ); - put_label( "text_end" ); +- put_data( exe_code_section, sizeof(exe_code_section) ); +- put_label( "text_end" ); ++ { ++ put_label( "text_start" ); ++ put_label( "entrypoint" ); ++ if (spec->characteristics & IMAGE_FILE_DLL) ++ put_data( dll_code_section, sizeof(dll_code_section) ); ++ else ++ put_data( exe_code_section, sizeof(exe_code_section) ); ++ put_label( "text_end" ); ++ } ++ ++ /* .data contents */ ++ align_output_rva( file_align, section_align ); ++ if (needs_stub_exports( spec )) ++ { ++ put_label( "data_start" ); ++ create_stub_exports_data( spec ); ++ put_label( "data_end" ); ++ } + + /* .reloc contents */ + align_output_rva( file_align, section_align ); diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c -index eada46604ec..b37ce9dc16f 100644 +index eada46604ec..eee5419285a 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -525,7 +525,7 @@ size_t output_buffer_size; @@ -235,7 +435,7 @@ index eada46604ec..b37ce9dc16f 100644 +void put_str( const char *str ) +{ -+ put_data( str, strlen(str)+1 ); ++ put_data( str, strlen(str) + 1 ); +} + void align_output( unsigned int align ) diff --git a/patches/winebuild-Fake_Dlls/0006-winebuild-Add-syscall-thunks-in-fake-dlls.patch b/patches/winebuild-Fake_Dlls/0006-winebuild-Add-syscall-thunks-in-fake-dlls.patch index 46147fb3..777a2552 100644 --- a/patches/winebuild-Fake_Dlls/0006-winebuild-Add-syscall-thunks-in-fake-dlls.patch +++ b/patches/winebuild-Fake_Dlls/0006-winebuild-Add-syscall-thunks-in-fake-dlls.patch @@ -1,35 +1,32 @@ -From 905baa4b802d589ea8a3f52c5566187c4e2dc1d9 Mon Sep 17 00:00:00 2001 +From b58ac41eb56c6e1e0eef8ecfa0d3faeede91ea11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 15 May 2017 17:56:48 +0200 Subject: winebuild: Add syscall thunks in fake dlls. --- - tools/winebuild/spec32.c | 32 ++++++++++++++++++++++++++++++-- - 1 file changed, 30 insertions(+), 2 deletions(-) + dlls/kernel32/tests/loader.c | 1 - + tools/winebuild/spec32.c | 31 +++++++++++++++++++++++++++++-- + 2 files changed, 29 insertions(+), 3 deletions(-) +diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c +index cfbee0851b5..a8f9e1f12d3 100644 +--- a/dlls/kernel32/tests/loader.c ++++ b/dlls/kernel32/tests/loader.c +@@ -898,7 +898,6 @@ static void test_FakeDLL(void) + + /* check function content */ + map_func = RVAToAddr(map_rva, ptr); +- todo_wine + ok(!memcmp(map_func, dll_func, 0x20), "%s: Function content does not match!\n", func_name); + + if (!strcmp(func_name, "NtSetEvent")) diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c -index 2d6117df691..d1bd1683334 100644 +index 4367b03b0d2..5a245b5ae81 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c -@@ -722,10 +722,14 @@ static void create_stub_exports_x86( DLLSPEC *spec ) - for (i = 0; i < spec->nb_entry_points; i++) - { - ORDDEF *odp = &spec->entry_points[i]; -- const char *name = get_stub_name( odp, spec ); -+ const char *name; - size_t rva; - -+ if (odp->flags & FLAG_SYSCALL) -+ continue; -+ - align_output_rva( 16, 16 ); -+ name = get_stub_name( odp, spec ); - put_label( name ); - - put_byte( 0x8b ); put_byte( 0xff ); /* mov edi, edi */ -@@ -750,6 +754,30 @@ static void create_stub_exports_x86( DLLSPEC *spec ) - put_byte( 0xc3 ); /* ret */ - } +@@ -718,13 +718,40 @@ static void create_stub_exports_text( DLLSPEC *spec ) + int i, nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; + size_t rva, thunk; + /* output syscalls */ + for (i = 0; i < spec->nb_syscalls; i++) @@ -38,7 +35,6 @@ index 2d6117df691..d1bd1683334 100644 + + align_output_rva( 16, 16 ); + put_label( odp->link_name ); -+ + put_byte( 0xb8 ); put_dword( i ); /* mov eax, SYSCALL */ + put_byte( 0x33 ); put_byte( 0xc9 ); /* xor ecx, ecx */ + put_byte( 0x8d ); put_byte( 0x54 ); /* lea edx, [esp + 4] */ @@ -55,10 +51,22 @@ index 2d6117df691..d1bd1683334 100644 + put_byte( 0 ); + } + - /* name to show in stub message */ - align_output_rva( 16, 16 ); - put_label( "dll_fake_name" ); -@@ -775,7 +803,7 @@ static void create_stub_exports_x86( DLLSPEC *spec ) + /* output stub code for exports */ + for (i = 0; i < spec->nb_entry_points; i++) + { + ORDDEF *odp = &spec->entry_points[i]; +- const char *name = get_stub_name( odp, spec ); ++ const char *name; ++ ++ if (odp->flags & FLAG_SYSCALL) ++ continue; + + align_output_rva( 16, 16 ); ++ name = get_stub_name( odp, spec ); + put_label( name ); + put_byte( 0x8b ); put_byte( 0xff ); /* mov edi, edi */ + put_byte( 0x55 ); /* push ebp */ +@@ -815,7 +842,7 @@ static void create_stub_exports_text( DLLSPEC *spec ) ORDDEF *odp = spec->ordinals[i]; if (odp) { diff --git a/patches/winebuild-Fake_Dlls/0007-winebuild-Fix-size-of-relocation-information-in-fake.patch b/patches/winebuild-Fake_Dlls/0007-winebuild-Fix-size-of-relocation-information-in-fake.patch index 27767ab4..a396648c 100644 --- a/patches/winebuild-Fake_Dlls/0007-winebuild-Fix-size-of-relocation-information-in-fake.patch +++ b/patches/winebuild-Fake_Dlls/0007-winebuild-Fix-size-of-relocation-information-in-fake.patch @@ -1,4 +1,4 @@ -From ff0ab54bfc6eb41797f5b8e15c48a2ff7a9e8562 Mon Sep 17 00:00:00 2001 +From 72e217f735af13a8a7026688fd46f353c24e93ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Thu, 25 May 2017 03:22:25 +0200 Subject: winebuild: Fix size of relocation information in fake dlls. @@ -8,10 +8,10 @@ Subject: winebuild: Fix size of relocation information in fake dlls. 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c -index d1bd1683334..56de04855d9 100644 +index 5a245b5ae81..4dda31c349b 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c -@@ -1022,8 +1022,8 @@ static void output_fake_module_pass( DLLSPEC *spec ) +@@ -1100,8 +1100,8 @@ static void output_fake_module_pass( DLLSPEC *spec ) /* .reloc contents */ align_output_rva( file_align, section_align ); put_label( "reloc_start" ); diff --git a/patches/winebuild-Fake_Dlls/0008-winebuild-Try-to-make-sure-RVA-matches-between-fake-.patch b/patches/winebuild-Fake_Dlls/0008-winebuild-Try-to-make-sure-RVA-matches-between-fake-.patch new file mode 100644 index 00000000..c17f600e --- /dev/null +++ b/patches/winebuild-Fake_Dlls/0008-winebuild-Try-to-make-sure-RVA-matches-between-fake-.patch @@ -0,0 +1,104 @@ +From c0531d2c7497a915a66919d0c4ef53be24e17909 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 25 May 2017 21:46:27 +0200 +Subject: 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 | 22 +++++++++++++++++++--- + 3 files changed, 30 insertions(+), 6 deletions(-) + +diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c +index a8f9e1f12d3..09ba7d435b0 100644 +--- a/dlls/kernel32/tests/loader.c ++++ b/dlls/kernel32/tests/loader.c +@@ -885,7 +885,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 89ae93503d3..8ace917d91d 100644 +--- a/libs/wine/loader.c ++++ b/libs/wine/loader.c +@@ -395,8 +395,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); +@@ -435,6 +439,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 4dda31c349b..1e4e481e72c 100644 +--- a/tools/winebuild/spec32.c ++++ b/tools/winebuild/spec32.c +@@ -280,14 +280,23 @@ 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( "\t.fill %d\n", page_size ); + ++ output( "\n/* syscall thunks */\n\n" ); + for (i = 0; i < spec->nb_syscalls; i++) + { + ORDDEF *odp = spec->syscalls[i]; +@@ -666,7 +675,14 @@ void output_module( DLLSPEC *spec ) + output( "\t.long 0,0\n" ); /* DataDirectory[12] */ + output( "\t.long 0,0\n" ); /* DataDirectory[13] */ + output( "\t.long 0,0\n" ); /* DataDirectory[14] */ +- output( "\t.long 0,0\n" ); /* DataDirectory[15] */ ++ ++ if (spec->nb_syscalls) /* DataDirectory[15] */ ++ { ++ output( "\t%s __wine_spec_pe_header_syscalls\n", get_asm_ptr_keyword() ); ++ if (get_ptr_size() == 4) output( "\t.long 0\n" ); ++ } ++ else ++ output( "\t.long 0,0\n" ); + + output( "\n\t%s\n", get_asm_string_section() ); + output( "%s\n", asm_globl("__wine_spec_file_name") ); +-- +2.12.2 + diff --git a/patches/winebuild-Fake_Dlls/0009-libs-wine-Use-same-file-alignment-for-fake-and-built.patch b/patches/winebuild-Fake_Dlls/0009-libs-wine-Use-same-file-alignment-for-fake-and-built.patch new file mode 100644 index 00000000..f3d1573f --- /dev/null +++ b/patches/winebuild-Fake_Dlls/0009-libs-wine-Use-same-file-alignment-for-fake-and-built.patch @@ -0,0 +1,38 @@ +From 7a90d53abeb02bc5a7c28f9027bc924c857e1e14 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 25 May 2017 21:56:06 +0200 +Subject: libs/wine: Use same file alignment for fake and builtin DLLs. + +--- + dlls/kernel32/tests/loader.c | 1 - + libs/wine/loader.c | 2 +- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c +index 09ba7d435b0..d923b958734 100644 +--- a/dlls/kernel32/tests/loader.c ++++ b/dlls/kernel32/tests/loader.c +@@ -891,7 +891,6 @@ static void test_FakeDLL(void) + /* check position in file */ + map_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(ptr), ptr, map_rva, NULL) - (DWORD_PTR)ptr; + dll_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(module), module, dll_rva, NULL) - (DWORD_PTR)module; +- todo_wine + ok(map_offset == dll_offset, "%s: File offset of mapped function (0x%x) does not match dll (0x%x)\n", + func_name, map_offset, dll_offset); + +diff --git a/libs/wine/loader.c b/libs/wine/loader.c +index 8ace917d91d..e8922c9333a 100644 +--- a/libs/wine/loader.c ++++ b/libs/wine/loader.c +@@ -450,7 +450,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr ) + sec->SizeOfRawData = data_start - code_start; + sec->Misc.VirtualSize = sec->SizeOfRawData; + sec->VirtualAddress = code_start; +- sec->PointerToRawData = code_start; ++ sec->PointerToRawData = 0x200; /* file alignment */ + sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ); + sec++; + +-- +2.12.2 +