[2/2] ntdll: Implement RtlLookupFunctionEntry on ARM

André Hentschel nerv at dawncrow.de
Sat Mar 23 11:24:04 CDT 2013


---
 dlls/kernel32/kernel32.spec |  2 +-
 dlls/ntdll/ntdll.spec       |  2 +-
 dlls/ntdll/signal_arm.c     | 68 +++++++++++++++++++++++++++++++++++++++++++++
 include/winnt.h             |  1 +
 4 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index a07a9ff..72c1697 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1034,7 +1034,7 @@
 @ stdcall -arch=x86_64 RtlCompareMemory(ptr ptr long) ntdll.RtlCompareMemory
 @ cdecl -arch=arm,x86_64 RtlDeleteFunctionTable(ptr) ntdll.RtlDeleteFunctionTable
 @ stdcall RtlFillMemory(ptr long long) ntdll.RtlFillMemory
-@ stdcall -arch=x86_64 RtlLookupFunctionEntry(long ptr ptr) ntdll.RtlLookupFunctionEntry
+@ stdcall -arch=arm,x86_64 RtlLookupFunctionEntry(long ptr ptr) ntdll.RtlLookupFunctionEntry
 @ stdcall RtlMoveMemory(ptr ptr long) ntdll.RtlMoveMemory
 @ stdcall -arch=x86_64,arm RtlPcToFileHeader(ptr ptr) ntdll.RtlPcToFileHeader
 @ stdcall -arch=arm -register RtlRaiseException(ptr) ntdll.RtlRaiseException
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index d67c85e..b0cb43a 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -738,7 +738,7 @@
 @ stdcall RtlLookupAtomInAtomTable(ptr wstr ptr)
 @ stub RtlLookupElementGenericTable
 # @ stub RtlLookupElementGenericTableAvl
-@ stdcall -arch=x86_64 RtlLookupFunctionEntry(long ptr ptr)
+@ stdcall -arch=arm,x86_64 RtlLookupFunctionEntry(long ptr ptr)
 @ stdcall RtlMakeSelfRelativeSD(ptr ptr ptr)
 @ stdcall RtlMapGenericMask(long ptr)
 # @ stub RtlMapSecurityErrorToNtStatus
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
index f9cde38..bf144a0 100644
--- a/dlls/ntdll/signal_arm.c
+++ b/dlls/ntdll/signal_arm.c
@@ -47,6 +47,8 @@
 # include <sys/signal.h>
 #endif
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
 #include "windef.h"
@@ -100,6 +102,15 @@ typedef int (*wine_signal_handler)(unsigned int sig);
 
 static wine_signal_handler handlers[256];
 
+
+struct UNWIND_INFO
+{
+    WORD function_length;
+    WORD unknown1 : 7;
+    WORD count : 5;
+    WORD unknown2 : 4;
+};
+
 /***********************************************************************
  *           dispatch_signal
  */
@@ -933,6 +944,63 @@ BOOLEAN CDECL RtlDeleteFunctionTable( RUNTIME_FUNCTION *table )
     return TRUE;
 }
 
+/**********************************************************************
+ *              find_function_info
+ */
+static RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, HMODULE module,
+                                             RUNTIME_FUNCTION *func, ULONG size )
+{
+    int min = 0;
+    int max = size/sizeof(*func) - 1;
+
+    while (min <= max)
+    {
+        int pos = (min + max) / 2;
+        DWORD begin = (func[pos].BeginAddress & ~1), end;
+        if (func[pos].u.s.Flag)
+            end = begin + func[pos].u.s.FunctionLength * 2;
+        else
+        {
+            struct UNWIND_INFO *info;
+            info = (struct UNWIND_INFO *)((char *)module + func[pos].u.UnwindData);
+            end = begin + info->function_length * 2;
+        }
+
+        if ((char *)pc < (char *)module + begin) max = pos - 1;
+        else if ((char *)pc >= (char *)module + end) min = pos + 1;
+        else return func + pos;
+    }
+    return NULL;
+}
+
+/**********************************************************************
+ *              RtlLookupFunctionEntry   (NTDLL.@)
+ */
+PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG_PTR pc, DWORD *base,
+                                                 UNWIND_HISTORY_TABLE *table )
+{
+    LDR_MODULE *module;
+    RUNTIME_FUNCTION *func;
+    ULONG size;
+
+    /* FIXME: should use the history table to make things faster */
+
+    if (LdrFindEntryForAddress( (void *)pc, &module ))
+    {
+        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;
+    }
+    func = find_function_info( pc, module->BaseAddress, func, size );
+    if (func) *base = (DWORD)module->BaseAddress;
+    return func;
+}
+
 /***********************************************************************
  *            RtlUnwind  (NTDLL.@)
  */
diff --git a/include/winnt.h b/include/winnt.h
index a40ff75..79e91c0 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -1710,6 +1710,7 @@ typedef struct _CONTEXT {
 
 BOOLEAN CDECL            RtlAddFunctionTable(RUNTIME_FUNCTION*,DWORD,DWORD);
 BOOLEAN CDECL            RtlDeleteFunctionTable(RUNTIME_FUNCTION*);
+PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry(ULONG_PTR,DWORD*,UNWIND_HISTORY_TABLE*);
 
 #endif /* __arm__ */
 
-- 
1.8.0


-- 

Best Regards, André Hentschel


More information about the wine-patches mailing list