From 22a1e1ff59d431352972b8af7fb84bdf8bbccf0a Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Fri, 4 Apr 2014 19:46:13 +0200 Subject: [PATCH] Add proper implementation for dynamic unwind functions, removed stub implementation. --- ...-exception-function-lookup-on-x86_64.patch | 189 +++++++++++++++++ ...ement-dynamic-unwind-table-functions.patch | 198 ++++++++++++++++++ .../bbbf7d25-cca0-4630-9a83-0dec5e53ecb8.def | 3 + ...Stub-RtlInstallFunctionTableCallback.patch | 46 ---- .../6528a473-8246-49d5-b63c-b47d66b85a74.def | 3 - patches/patch-list.patch | 2 +- 6 files changed, 391 insertions(+), 50 deletions(-) create mode 100644 patches/11-Dynamic_Unwind/0001-ntdll-Unify-exception-function-lookup-on-x86_64.patch create mode 100644 patches/11-Dynamic_Unwind/0002-ntdll-Implement-dynamic-unwind-table-functions.patch create mode 100644 patches/11-Dynamic_Unwind/bbbf7d25-cca0-4630-9a83-0dec5e53ecb8.def delete mode 100644 patches/98-Miscellaneous/0001-ntdll-Stub-RtlInstallFunctionTableCallback.patch delete mode 100644 patches/98-Miscellaneous/6528a473-8246-49d5-b63c-b47d66b85a74.def diff --git a/patches/11-Dynamic_Unwind/0001-ntdll-Unify-exception-function-lookup-on-x86_64.patch b/patches/11-Dynamic_Unwind/0001-ntdll-Unify-exception-function-lookup-on-x86_64.patch new file mode 100644 index 00000000..9384292c --- /dev/null +++ b/patches/11-Dynamic_Unwind/0001-ntdll-Unify-exception-function-lookup-on-x86_64.patch @@ -0,0 +1,189 @@ +From 00e4f5ab76c745a28079c634dd9cf76456b81e22 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Fri, 4 Apr 2014 10:11:56 +0200 +Subject: ntdll: Unify exception function lookup on x86_64. + +--- + dlls/ntdll/signal_x86_64.c | 102 +++++++++++++++++++++----------------------- + 1 file changed, 48 insertions(+), 54 deletions(-) + +diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c +index b28cb99..57afe16 100644 +--- a/dlls/ntdll/signal_x86_64.c ++++ b/dlls/ntdll/signal_x86_64.c +@@ -1921,6 +1921,28 @@ static RUNTIME_FUNCTION *find_function_info( ULONG64 pc, HMODULE module, + return NULL; + } + ++/********************************************************************** ++ * lookup_function_info ++ */ ++static RUNTIME_FUNCTION *lookup_function_info( ULONG64 pc, ULONG64 *base, LDR_MODULE **module ) ++{ ++ RUNTIME_FUNCTION *func = NULL; ++ ULONG size; ++ ++ /* PE module or wine module */ ++ if (!LdrFindEntryForAddress( (void *)pc, module )) ++ { ++ *base = (ULONG64)(*module)->BaseAddress; ++ if ((func = RtlImageDirectoryEntryToData( (*module)->BaseAddress, TRUE, ++ IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size ))) ++ { ++ /* lookup in function table */ ++ func = find_function_info( pc, (*module)->BaseAddress, func, size ); ++ } ++ } ++ ++ return func; ++} + + /********************************************************************** + * call_handler +@@ -2002,7 +2024,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex + DISPATCHER_CONTEXT dispatch; + CONTEXT context, new_context; + LDR_MODULE *module; +- DWORD size; + NTSTATUS status; + + context = *orig_context; +@@ -2021,31 +2042,18 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex + + /* first look for PE exception information */ + +- if (!LdrFindEntryForAddress( (void *)context.Rip, &module )) ++ if ((dispatch.FunctionEntry = lookup_function_info( context.Rip, &dispatch.ImageBase, &module ))) + { +- RUNTIME_FUNCTION *dir; +- +- dispatch.ImageBase = (ULONG64)module->BaseAddress; +- if ((dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, +- IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size ))) +- { +- if ((dispatch.FunctionEntry = find_function_info( context.Rip, module->BaseAddress, +- dir, size ))) +- { +- dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, dispatch.ImageBase, +- context.Rip, dispatch.FunctionEntry, +- &new_context, &dispatch.HandlerData, +- &dispatch.EstablisherFrame, NULL ); +- goto unwind_done; +- } +- } +- else if (!(module->Flags & LDR_WINE_INTERNAL)) +- WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) ); ++ dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, dispatch.ImageBase, ++ context.Rip, dispatch.FunctionEntry, ++ &new_context, &dispatch.HandlerData, ++ &dispatch.EstablisherFrame, NULL ); ++ goto unwind_done; + } + + /* then look for host system exception information */ + +- if (!module || (module->Flags & LDR_WINE_INTERNAL)) ++ else if (!module || (module->Flags & LDR_WINE_INTERNAL)) + { + struct dwarf_eh_bases bases; + const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context.Rip - 1), &bases ); +@@ -2065,6 +2073,8 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex + } + } + ++ else WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) ); ++ + /* no exception information, treat as a leaf function */ + + new_context.Rip = *(ULONG64 *)context.Rsp; +@@ -2540,23 +2550,18 @@ PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG64 pc, ULONG64 *base, UNWI + { + LDR_MODULE *module; + RUNTIME_FUNCTION *func; +- ULONG size; + + /* FIXME: should use the history table to make things faster */ + +- if (LdrFindEntryForAddress( (void *)pc, &module )) ++ func = lookup_function_info( pc, base, &module ); ++ if (!func) + { +- WARN( "module not found for %lx\n", pc ); +- return NULL; +- } +- if (!(func = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, +- IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size ))) +- { +- WARN( "no exception table found in module %p pc %lx\n", module->BaseAddress, pc ); +- return NULL; ++ if (module) ++ WARN( "no exception table found in module %p pc %lx\n", module->BaseAddress, pc ); ++ else ++ WARN( "module not found for %lx\n", pc ); + } +- func = find_function_info( pc, module->BaseAddress, func, size ); +- if (func) *base = (ULONG64)module->BaseAddress; ++ + return func; + } + +@@ -2916,7 +2921,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec + CONTEXT new_context; + LDR_MODULE *module; + NTSTATUS status; +- DWORD i, size; ++ DWORD i; + + RtlCaptureContext( context ); + new_context = *context; +@@ -2962,31 +2967,18 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec + + /* first look for PE exception information */ + +- if (!LdrFindEntryForAddress( (void *)context->Rip, &module )) ++ if ((dispatch.FunctionEntry = lookup_function_info( context->Rip, &dispatch.ImageBase, &module ))) + { +- RUNTIME_FUNCTION *dir; +- +- dispatch.ImageBase = (ULONG64)module->BaseAddress; +- if ((dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, +- IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size ))) +- { +- if ((dispatch.FunctionEntry = find_function_info( context->Rip, module->BaseAddress, +- dir, size ))) +- { +- dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_UHANDLER, dispatch.ImageBase, +- context->Rip, dispatch.FunctionEntry, +- &new_context, &dispatch.HandlerData, +- &dispatch.EstablisherFrame, NULL ); +- goto unwind_done; +- } +- } +- else if (!(module->Flags & LDR_WINE_INTERNAL)) +- WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) ); ++ dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_UHANDLER, dispatch.ImageBase, ++ context->Rip, dispatch.FunctionEntry, ++ &new_context, &dispatch.HandlerData, ++ &dispatch.EstablisherFrame, NULL ); ++ goto unwind_done; + } + + /* then look for host system exception information */ + +- if (!module || (module->Flags & LDR_WINE_INTERNAL)) ++ else if (!module || (module->Flags & LDR_WINE_INTERNAL)) + { + struct dwarf_eh_bases bases; + const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context->Rip - 1), &bases ); +@@ -3006,6 +2998,8 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec + } + } + ++ else WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) ); ++ + /* no exception information, treat as a leaf function */ + + new_context.Rip = *(ULONG64 *)context->Rsp; +-- +1.7.9.5 + diff --git a/patches/11-Dynamic_Unwind/0002-ntdll-Implement-dynamic-unwind-table-functions.patch b/patches/11-Dynamic_Unwind/0002-ntdll-Implement-dynamic-unwind-table-functions.patch new file mode 100644 index 00000000..e33956fd --- /dev/null +++ b/patches/11-Dynamic_Unwind/0002-ntdll-Implement-dynamic-unwind-table-functions.patch @@ -0,0 +1,198 @@ +From c9b382af632550740ec72f57a178c16f246d0ca5 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Fri, 4 Apr 2014 19:32:33 +0200 +Subject: ntdll: Implement dynamic unwind table functions. + +--- + dlls/ntdll/ntdll.spec | 1 + + dlls/ntdll/signal_x86_64.c | 127 +++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 126 insertions(+), 2 deletions(-) + +diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec +index 0dd75a2..7a3c3f1 100644 +--- a/dlls/ntdll/ntdll.spec ++++ b/dlls/ntdll/ntdll.spec +@@ -689,6 +689,7 @@ + # @ stub RtlInitializeStackTraceDataBase + @ stub RtlInsertElementGenericTable + # @ stub RtlInsertElementGenericTableAvl ++@ cdecl -arch=x86_64 RtlInstallFunctionTableCallback(long long long ptr ptr ptr) + @ stdcall RtlInt64ToUnicodeString(int64 long ptr) + @ stdcall RtlIntegerToChar(long long long ptr) + @ stdcall RtlIntegerToUnicodeString(long long ptr) +diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c +index 57afe16..5ace5a9 100644 +--- a/dlls/ntdll/signal_x86_64.c ++++ b/dlls/ntdll/signal_x86_64.c +@@ -56,6 +56,7 @@ + #include "winternl.h" + #include "wine/library.h" + #include "wine/exception.h" ++#include "wine/list.h" + #include "ntdll_misc.h" + #include "wine/debug.h" + +@@ -271,6 +272,34 @@ typedef int (*wine_signal_handler)(unsigned int sig); + + static wine_signal_handler handlers[256]; + ++/*********************************************************************** ++ * Dynamic unwind table ++ */ ++ ++struct dynamic_unwind_entry ++{ ++ struct list entry; ++ ++ DWORD64 base; ++ DWORD size; ++ ++ RUNTIME_FUNCTION *table; ++ DWORD table_size; ++ ++ PRUNTIME_FUNCTION (*callback)( DWORD pc, PVOID context ); ++ PVOID context; ++}; ++ ++static struct list dynamic_unwind_list = LIST_INIT(dynamic_unwind_list); ++ ++static RTL_CRITICAL_SECTION dynamic_unwind_section; ++static RTL_CRITICAL_SECTION_DEBUG dynamic_unwind_debug = ++{ ++ 0, 0, &dynamic_unwind_section, ++ { &dynamic_unwind_debug.ProcessLocksList, &dynamic_unwind_debug.ProcessLocksList }, ++ 0, 0, { (DWORD_PTR)(__FILE__ ": dynamic_unwind_section") } ++}; ++static RTL_CRITICAL_SECTION dynamic_unwind_section = { &dynamic_unwind_debug, -1, 0, 0, 0, 0 }; + + /*********************************************************************** + * Definitions for Win32 unwind tables +@@ -1927,6 +1956,7 @@ static RUNTIME_FUNCTION *find_function_info( ULONG64 pc, HMODULE module, + static RUNTIME_FUNCTION *lookup_function_info( ULONG64 pc, ULONG64 *base, LDR_MODULE **module ) + { + RUNTIME_FUNCTION *func = NULL; ++ struct dynamic_unwind_entry *entry; + ULONG size; + + /* PE module or wine module */ +@@ -1940,6 +1970,25 @@ static RUNTIME_FUNCTION *lookup_function_info( ULONG64 pc, ULONG64 *base, LDR_MO + func = find_function_info( pc, (*module)->BaseAddress, func, size ); + } + } ++ else ++ { ++ RtlEnterCriticalSection( &dynamic_unwind_section ); ++ LIST_FOR_EACH_ENTRY( entry, &dynamic_unwind_list, struct dynamic_unwind_entry, entry ) ++ { ++ if (pc >= entry->base && pc < entry->base + entry->size) ++ { ++ *base = entry->base; ++ ++ /* lookup in function table or call callback in signal handler stack */ ++ if (entry->callback) ++ func = entry->callback( pc, entry->context ); ++ else ++ func = find_function_info( pc, (HMODULE)entry->base, entry->table, entry->table_size ); ++ break; ++ } ++ } ++ RtlLeaveCriticalSection( &dynamic_unwind_section ); ++ } + + return func; + } +@@ -2528,7 +2577,31 @@ void signal_init_process(void) + */ + BOOLEAN CDECL RtlAddFunctionTable( RUNTIME_FUNCTION *table, DWORD count, DWORD64 addr ) + { +- FIXME( "%p %u %lx: stub\n", table, count, addr ); ++ struct dynamic_unwind_entry *entry; ++ DWORD size; ++ ++ TRACE( "%p %u %lx\n", table, count, addr ); ++ ++ /* both low-order bits must be unset */ ++ if (((ULONG_PTR)table & 0x3) != 0) ++ return FALSE; ++ ++ size = table[count - 1].EndAddress; ++ entry = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*entry) ); ++ if (!entry) ++ return FALSE; ++ ++ entry->base = addr; ++ entry->size = size; ++ entry->table = table; ++ entry->table_size = count * sizeof(RUNTIME_FUNCTION); ++ entry->callback = NULL; /* unused */ ++ entry->context = NULL; /* unused */ ++ ++ RtlEnterCriticalSection( &dynamic_unwind_section ); ++ list_add_tail( &dynamic_unwind_list, &entry->entry ); ++ RtlLeaveCriticalSection( &dynamic_unwind_section ); ++ + return TRUE; + } + +@@ -2538,7 +2611,57 @@ BOOLEAN CDECL RtlAddFunctionTable( RUNTIME_FUNCTION *table, DWORD count, DWORD64 + */ + BOOLEAN CDECL RtlDeleteFunctionTable( RUNTIME_FUNCTION *table ) + { +- FIXME( "%p: stub\n", table ); ++ struct dynamic_unwind_entry *entry, *old_entry = NULL; ++ ++ TRACE( "%p\n", table ); ++ ++ RtlEnterCriticalSection( &dynamic_unwind_section ); ++ LIST_FOR_EACH_ENTRY( entry, &dynamic_unwind_list, struct dynamic_unwind_entry, entry ) ++ { ++ if (entry->table == table) ++ { ++ old_entry = entry; ++ list_remove( &entry->entry ); ++ break; ++ } ++ } ++ RtlLeaveCriticalSection( &dynamic_unwind_section ); ++ ++ if (old_entry) ++ RtlFreeHeap( GetProcessHeap(), 0, old_entry ); ++ ++ return (old_entry != NULL); ++} ++ ++ ++/********************************************************************** ++ * RtlInstallFunctionTableCallback (NTDLL.@) ++ */ ++BOOLEAN CDECL RtlInstallFunctionTableCallback( DWORD64 table, DWORD64 base, DWORD length, PVOID callback, PVOID context, PCWSTR dll ) ++{ ++ struct dynamic_unwind_entry *entry; ++ ++ TRACE( "%lx %lx %d %p %p %s\n", table, base, length, callback, context, wine_dbgstr_w(dll) ); ++ ++ /* both low-order bits must be set, callback must be provided */ ++ if ((table & 0x3) != 0x3 || !callback) ++ return FALSE; ++ ++ entry = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*entry) ); ++ if (!entry) ++ return FALSE; ++ ++ entry->base = base; ++ entry->size = length; ++ entry->table = (RUNTIME_FUNCTION *)table; ++ entry->table_size = 0; /* unused */ ++ entry->callback = callback; ++ entry->context = context; ++ ++ RtlEnterCriticalSection( &dynamic_unwind_section ); ++ list_add_tail( &dynamic_unwind_list, &entry->entry ); ++ RtlLeaveCriticalSection( &dynamic_unwind_section ); ++ + return TRUE; + } + +-- +1.7.9.5 + diff --git a/patches/11-Dynamic_Unwind/bbbf7d25-cca0-4630-9a83-0dec5e53ecb8.def b/patches/11-Dynamic_Unwind/bbbf7d25-cca0-4630-9a83-0dec5e53ecb8.def new file mode 100644 index 00000000..e6844033 --- /dev/null +++ b/patches/11-Dynamic_Unwind/bbbf7d25-cca0-4630-9a83-0dec5e53ecb8.def @@ -0,0 +1,3 @@ +Revision: 1 +Author: Sebastian Lackner +Title: Add implementation for dynamic unwind tables/callbacks on x86_64. diff --git a/patches/98-Miscellaneous/0001-ntdll-Stub-RtlInstallFunctionTableCallback.patch b/patches/98-Miscellaneous/0001-ntdll-Stub-RtlInstallFunctionTableCallback.patch deleted file mode 100644 index 12b90187..00000000 --- a/patches/98-Miscellaneous/0001-ntdll-Stub-RtlInstallFunctionTableCallback.patch +++ /dev/null @@ -1,46 +0,0 @@ -From dab7a4a879b718afa79f0b1f1f90c5868277d8a8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Sun, 23 Mar 2014 23:17:51 +0100 -Subject: ntdll: Stub RtlInstallFunctionTableCallback - ---- - dlls/ntdll/ntdll.spec | 1 + - dlls/ntdll/signal_x86_64.c | 10 ++++++++++ - 2 files changed, 11 insertions(+) - -diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 3c751ea..df79ed0 100644 ---- a/dlls/ntdll/ntdll.spec -+++ b/dlls/ntdll/ntdll.spec -@@ -689,6 +689,7 @@ - # @ stub RtlInitializeStackTraceDataBase - @ stub RtlInsertElementGenericTable - # @ stub RtlInsertElementGenericTableAvl -+@ cdecl -arch=x86_64 RtlInstallFunctionTableCallback(long long long ptr ptr ptr) - @ stdcall RtlInt64ToUnicodeString(int64 long ptr) - @ stdcall RtlIntegerToChar(long long long ptr) - @ stdcall RtlIntegerToUnicodeString(long long ptr) -diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c -index b28cb99..bd7f2d7 100644 ---- a/dlls/ntdll/signal_x86_64.c -+++ b/dlls/ntdll/signal_x86_64.c -@@ -2534,6 +2534,16 @@ BOOLEAN CDECL RtlDeleteFunctionTable( RUNTIME_FUNCTION *table ) - - - /********************************************************************** -+ * RtlInstallFunctionTableCallback (NTDLL.@) -+ */ -+BOOLEAN CDECL RtlInstallFunctionTableCallback( DWORD64 table, DWORD64 base, DWORD length, PVOID callback, PVOID context, PCWSTR dll ) -+{ -+ FIXME( "%lx %lx %d %p %p %s: stub\n", table, base, length, callback, context, wine_dbgstr_w(dll) ); -+ return TRUE; -+} -+ -+ -+/********************************************************************** - * RtlLookupFunctionEntry (NTDLL.@) - */ - PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG64 pc, ULONG64 *base, UNWIND_HISTORY_TABLE *table ) --- -1.8.3.2 - diff --git a/patches/98-Miscellaneous/6528a473-8246-49d5-b63c-b47d66b85a74.def b/patches/98-Miscellaneous/6528a473-8246-49d5-b63c-b47d66b85a74.def deleted file mode 100644 index 0ad7f51a..00000000 --- a/patches/98-Miscellaneous/6528a473-8246-49d5-b63c-b47d66b85a74.def +++ /dev/null @@ -1,3 +0,0 @@ -Revision: 1 -Author: Michael Müller -Title: Add stub for RtlInstallFunctionTableCallback diff --git a/patches/patch-list.patch b/patches/patch-list.patch index 12088d13..3e790baa 100644 --- a/patches/patch-list.patch +++ b/patches/patch-list.patch @@ -57,10 +57,10 @@ index a273502..5fa0cd5 100644 + { "4cd13e94-7f2d-11e3-b5eb-0090f5c75ad5:1", "Erich E. Hoover", "Support for junction points/reparse points." }, + { "5fb1f5c8-7f17-11e3-9b62-0090f5c75ad5:1", "Erich E. Hoover", "Implement TransmitFile." }, + { "3d7c4774-9e7f-11e3-9cfc-0090f5c75ad5:1", "Erich E. Hoover", "Implement missing fonts expected by Silverlight." }, ++ { "bbbf7d25-cca0-4630-9a83-0dec5e53ecb8:1", "Sebastian Lackner", "Add implementation for dynamic unwind tables/callbacks on x86_64." }, + { "0b21d7ac-0387-4493-aa38-fbafe3e749f5:1", "Michael Müller", "Decrease minimum SetTimer interval from 15 to 5 ms." }, + { "19835498-8d90-4673-867e-2376af4d7c76:1", "Sebastian Lackner", "Allow to set wined3d strictDrawOrdering via environment variable." }, + { "59bd38b7-bbdc-4cfd-9ccd-1c72c4ed84c0:1", "Sebastian Lackner", "Implement X11DRV_FLUSH_GDI_DISPLAY ExtEscape command." }, -+ { "6528a473-8246-49d5-b63c-b47d66b85a74:1", "Michael Müller", "Add stub for RtlInstallFunctionTableCallback" }, + { "acff3012-0f75-4710-9941-08b5ce4c61f3:1", "Erich E. Hoover", "wined3d: Silence repeated resource_check_usage FIXME." }, + { "eec5dea8-879d-417b-9f97-364deaae6576:1", "Sebastian Lackner", "Add tests for IVMRMonitorConfig." }, + { "e46b26df-3c1b-419c-9579-f0d1e1c50bea:1", "Sebastian Lackner", "Workaround for broken implementation of shlwapi url functions." },