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