Implement RtlLookupFunctionTable, RtlLookupFunctionEntry and a usermode/kernelmode...
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 12 Nov 2008 15:24:40 +0000 (15:24 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 12 Nov 2008 15:24:40 +0000 (15:24 +0000)
svn path=/branches/ros-amd64-bringup/; revision=37308

reactos/dll/ntdll/rtl/libsupp.c
reactos/lib/rtl/amd64/stubs.c
reactos/lib/rtl/amd64/unwind.c [new file with mode: 0644]
reactos/lib/rtl/rtl.rbuild
reactos/ntoskrnl/amd64stubs.c
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/rtl/libsupp.c

index 8bae8c6..a617d21 100644 (file)
@@ -14,6 +14,8 @@
 #include <debug.h>
 
 SIZE_T RtlpAllocDeallocQueryBufferSize = PAGE_SIZE;
+#define IMAGE_DOS_MAGIC 0x5a4d
+#define IMAGE_PE_MAGIC 0x00004550
 
 /* FUNCTIONS ***************************************************************/
 
@@ -358,6 +360,62 @@ RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
    return NULL;
 }
 
+PVOID
+NTAPI
+RtlpLookupModuleBase(
+    PVOID Address)
+{
+    NTSTATUS Status;
+    MEMORY_BASIC_INFORMATION MemoryInformation;
+    ULONG_PTR Base, Limit;
+    PIMAGE_DOS_HEADER DosHeader;
+    PIMAGE_NT_HEADERS NtHeader;
+
+    Status = NtQueryVirtualMemory(NtCurrentProcess(),
+                                  Address,
+                                  MemoryBasicInformation,
+                                  &MemoryInformation,
+                                  sizeof(MEMORY_BASIC_INFORMATION),
+                                  NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        return NULL;
+    }
+
+    /* FIXME: remove these checks? */
+    Base = (ULONG_PTR)MemoryInformation.BaseAddress;
+    Limit = Base + MemoryInformation.RegionSize;
+    if ( ((ULONG_PTR)Address < Base) ||
+         ((ULONG_PTR)Address >= Limit) )
+    {
+        /* WTF? */
+        return NULL;
+    }
+
+    /* Check if we got the right kind of memory */
+    if ( (MemoryInformation.State != MEM_COMMIT) ||
+         (MemoryInformation.Type != MEM_IMAGE) )
+    {
+        return NULL;
+    }
+
+    /* Check DOS magic */
+    DosHeader = MemoryInformation.AllocationBase;
+    if (DosHeader->e_magic != IMAGE_DOS_MAGIC)
+    {
+        return NULL;
+    }
+
+    /* Check NT header */
+    NtHeader = (PVOID)((ULONG_PTR)DosHeader + DosHeader->e_lfanew);
+    if (NtHeader->Signature != IMAGE_PE_MAGIC)
+    {
+        return NULL;
+    }
+
+    return MemoryInformation.AllocationBase;
+}
+
 
 /*
  * Ldr Resource support code
index e5ed5f1..fa4a904 100644 (file)
 
 /* PUBLIC FUNCTIONS **********************************************************/
 
-/*
- * @unimplemented
- */
-PVOID
-NTAPI
-RtlLookupFunctionEntry(IN ULONGLONG ControlPC,
-                       OUT PULONGLONG ImageBase,
-                       OUT PULONGLONG TargetGp)
-{
-    UNIMPLEMENTED;
-    return NULL;
-}
-
 /*
  * @unimplemented
  */
diff --git a/reactos/lib/rtl/amd64/unwind.c b/reactos/lib/rtl/amd64/unwind.c
new file mode 100644 (file)
index 0000000..edb2d08
--- /dev/null
@@ -0,0 +1,153 @@
+/* COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * PURPOSE:         Exception related functions
+ * PROGRAMMER:      Timo Kreuzer
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <rtl.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#define UNWIND_HISTORY_TABLE_NONE 0
+#define UNWIND_HISTORY_TABLE_GLOBAL 1
+#define UNWIND_HISTORY_TABLE_LOCAL 2
+
+PVOID
+NTAPI
+RtlpLookupModuleBase(
+    PVOID Address);
+
+/* FUNCTIONS *****************************************************************/
+
+PRUNTIME_FUNCTION
+NTAPI
+RtlLookupFunctionTable(
+    IN DWORD64 ControlPc,
+    OUT PDWORD64 ImageBase,
+    OUT PULONG Length)
+{
+    PIMAGE_DOS_HEADER DosHeader;
+    PIMAGE_NT_HEADERS NtHeader;
+    PIMAGE_DATA_DIRECTORY Directory;
+
+    /* Find ModuleBase */
+    DosHeader = RtlpLookupModuleBase((PVOID)ControlPc);
+    if (!DosHeader)
+    {
+        return NULL;
+    }
+
+    /* Locate NT header and check number of directories */
+    NtHeader = (PVOID)((ULONG64)DosHeader + DosHeader->e_lfanew);
+    if (NtHeader->OptionalHeader.NumberOfRvaAndSizes 
+         < IMAGE_DIRECTORY_ENTRY_EXCEPTION)
+    {
+        return NULL;
+    }
+
+    /* Locate the exception directory */
+    Directory = &NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
+    *Length = Directory->Size / sizeof(RUNTIME_FUNCTION);
+    *ImageBase = (ULONG64)DosHeader;
+    if (!Directory->VirtualAddress)
+    {
+        return NULL;
+    }
+
+    return (PVOID)((ULONG64)DosHeader + Directory->VirtualAddress);
+}
+
+
+// http://msdn.microsoft.com/en-us/library/ms680597(VS.85).aspx
+PRUNTIME_FUNCTION
+NTAPI
+RtlLookupFunctionEntry(
+    IN DWORD64 ControlPc,
+    OUT PDWORD64 ImageBase,
+    OUT PUNWIND_HISTORY_TABLE HistoryTable)
+{
+    PRUNTIME_FUNCTION FunctionTable, FunctionEntry;
+    ULONG TableLength;
+    ULONG IndexLo, IndexHi, IndexMid;
+
+    /* Find the corresponding table */
+    FunctionTable = RtlLookupFunctionTable(ControlPc,
+                                           ImageBase,
+                                           &TableLength);
+
+    /* Fail, if no table is found */
+    if (!FunctionTable)
+    {
+        return (PVOID)1;
+    }
+
+    /* Use relative virtual address */
+    ControlPc -= *ImageBase;
+
+    /* Do a binary search */
+    IndexLo = 0;
+    IndexHi = TableLength;
+
+    while (IndexHi > IndexLo)
+    {
+        IndexMid = (IndexLo + IndexHi) / 2;
+        FunctionEntry = &FunctionTable[IndexMid];
+
+        if ( (ControlPc >= FunctionEntry->BeginAddress) &&
+             (ControlPc < FunctionEntry->EndAddress) )
+        {
+            /* ControlPc is within limits, return entry */
+            return FunctionEntry;
+        }
+
+        if (ControlPc < FunctionEntry->BeginAddress)
+        {
+            /* Continue search in lower half */
+            IndexHi = IndexMid;
+        }
+        else
+        {
+            /* Continue search in upper half */
+            IndexLo = IndexMid + 1;
+        }
+    }
+
+    /* Nothing found, return NULL */
+    return NULL;
+}
+
+
+PEXCEPTION_ROUTINE
+NTAPI
+RtlVirtualUnwind(
+    IN ULONG HandlerType,
+    IN ULONG64 ImageBase,
+    IN ULONG64 ControlPc,
+    IN PRUNTIME_FUNCTION FunctionEntry,
+    IN OUT PCONTEXT ContextRecord,
+    OUT PVOID *HandlerData,
+    OUT PULONG64 EstablisherFrame,
+    IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
+{
+    UNIMPLEMENTED;
+    return 0;
+}
+
+VOID
+NTAPI
+RtlUnwindEx(
+   IN ULONG64 TargetFrame,
+   IN ULONG64 TargetIp,
+   IN PEXCEPTION_RECORD ExceptionRecord,
+   IN PVOID ReturnValue,
+   OUT PCONTEXT OriginalContext,
+   IN PUNWIND_HISTORY_TABLE HistoryTable)
+{
+    UNIMPLEMENTED;
+    return;
+}
+
+
index a39fd2e..719c0f8 100644 (file)
@@ -39,6 +39,7 @@
        <if property="ARCH" value="amd64">
                <directory name="amd64">
                        <file>debug_asm.S</file>
+                       <file>unwind.c</file>
                        <file>stubs.c</file>
                </directory>
                <file>mem.c</file>
index 22e735d..f36c0e8 100644 (file)
@@ -68,14 +68,10 @@ STUB(KiSystemService)
 STUB(KdpGdbStubInit)
 STUB(KdbpSafeReadMemory)
 STUB(RtlFillMemoryUlong)
-STUB(RtlCaptureContext)
-STUB(RtlpGetExceptionAddress)
-STUB(RtlDispatchException)
 STUB(DbgkDebugObjectType)
 STUB(KdbEnterDebuggerException)
 STUB(KdbpCliModuleLoaded)
 STUB(RtlUnwind)
-STUB(RtlInitializeContext)
 STUB(DbgCommandString)
 STUB(ExAcquireRundownProtection)
 STUB(ExAcquireRundownProtectionCacheAware)
@@ -180,7 +176,6 @@ STUB(RtlCompareMemoryUlong)
 STUB(RtlCopyMemory)
 STUB(RtlCopyMemoryNonTemporal)
 STUB(RtlFillMemory)
-STUB(RtlLookupFunctionEntry)
 STUB(RtlMoveMemory)
 STUB(RtlOemStringToUnicodeSize)
 STUB(RtlPcToFileHeader)
@@ -196,8 +191,6 @@ STUB(RtlTraceDatabaseUnlock)
 STUB(RtlTraceDatabaseValidate)
 STUB(RtlUnicodeStringToAnsiSize)
 STUB(RtlUnicodeStringToOemSize)
-STUB(RtlUnwindEx)
-STUB(RtlVirtualUnwind)
 STUB(RtlZeroMemory)
 STUB(SeReportSecurityEvent)
 STUB(SeSetAuditParameter)
index 49f754b..12fdb85 100644 (file)
@@ -1047,6 +1047,18 @@ KiIdleLoop(
     VOID
 );
 
+PVOID
+NTAPI
+KiPcToFileHeader(IN PVOID Eip,
+                 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry,
+                 IN BOOLEAN DriversOnly,
+                 OUT PBOOLEAN InKernel);
+
+PVOID
+NTAPI
+KiRosPcToUserFileHeader(IN PVOID Eip,
+                        OUT PLDR_DATA_TABLE_ENTRY *LdrEntry);
+
 #include "ke_x.h"
 
 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_KE_H */
index d81a3cf..2760a16 100644 (file)
@@ -28,6 +28,30 @@ SIZE_T RtlpAllocDeallocQueryBufferSize = 128;
 
 /* FUNCTIONS *****************************************************************/
 
+PVOID
+NTAPI
+RtlpLookupModuleBase(
+    PVOID Address)
+{
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    BOOLEAN InSystem;
+    PVOID p;
+
+    /* Get the base for this file */
+    if ((ULONG_PTR)Address > (ULONG_PTR)MmHighestUserAddress)
+    {
+        /* We are in kernel */
+        p = KiPcToFileHeader(Address, &LdrEntry, FALSE, &InSystem);
+    }
+    else
+    {
+        /* We are in user land */
+        p = KiRosPcToUserFileHeader(Address, &LdrEntry);
+    }
+
+    return p;
+}
+
 VOID
 NTAPI
 RtlInitializeRangeListPackage(VOID)