Sebastian Lackner : ntdll: Implement RtlAddFunctionTable / RtlDeleteFunctionTable for x86_64.
Alexandre Julliard
julliard at winehq.org
Tue Apr 8 14:02:51 CDT 2014
Module: wine
Branch: master
Commit: 98307b22fba5c0d757be15b9f355b29e97ab1d5c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=98307b22fba5c0d757be15b9f355b29e97ab1d5c
Author: Sebastian Lackner <sebastian at fds-team.de>
Date: Mon Apr 7 00:22:07 2014 +0200
ntdll: Implement RtlAddFunctionTable / RtlDeleteFunctionTable for x86_64.
---
dlls/ntdll/signal_x86_64.c | 84 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 82 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 0e72092..8b4c0ee 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,33 @@ typedef int (*wine_signal_handler)(unsigned int sig);
static wine_signal_handler handlers[256];
+/***********************************************************************
+ * Dynamic unwind table
+ */
+
+struct dynamic_unwind_entry
+{
+ struct list entry;
+
+ /* memory region which matches this entry */
+ DWORD64 base;
+ DWORD size;
+
+ /* lookup table */
+ RUNTIME_FUNCTION *table;
+ DWORD table_size;
+};
+
+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 +1955,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 */
@@ -1941,8 +1970,22 @@ static RUNTIME_FUNCTION *lookup_function_info( ULONG64 pc, ULONG64 *base, LDR_MO
}
}
else
+ {
*module = NULL;
+ 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;
+ func = find_function_info( pc, (HMODULE)entry->base, entry->table, entry->table_size );
+ break;
+ }
+ }
+ RtlLeaveCriticalSection( &dynamic_unwind_section );
+ }
+
return func;
}
@@ -2528,7 +2571,25 @@ 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;
+
+ TRACE( "%p %u %lx\n", table, count, addr );
+
+ /* NOTE: Windows doesn't check if table is aligned or a NULL pointer */
+
+ entry = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*entry) );
+ if (!entry)
+ return FALSE;
+
+ entry->base = addr;
+ entry->size = table[count - 1].EndAddress;
+ entry->table = table;
+ entry->table_size = count * sizeof(RUNTIME_FUNCTION);
+
+ RtlEnterCriticalSection( &dynamic_unwind_section );
+ list_add_tail( &dynamic_unwind_list, &entry->entry );
+ RtlLeaveCriticalSection( &dynamic_unwind_section );
+
return TRUE;
}
@@ -2538,7 +2599,26 @@ 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, *to_free = 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)
+ {
+ to_free = entry;
+ list_remove( &entry->entry );
+ break;
+ }
+ }
+ RtlLeaveCriticalSection( &dynamic_unwind_section );
+
+ if (!to_free)
+ return FALSE;
+
+ RtlFreeHeap( GetProcessHeap(), 0, to_free );
return TRUE;
}
More information about the wine-cvs
mailing list