diff --git a/reactos/dll/ntdll/rtl/libsupp.c b/reactos/dll/ntdll/rtl/libsupp.c index 8bae8c6da84..a617d217d5a 100644 --- a/reactos/dll/ntdll/rtl/libsupp.c +++ b/reactos/dll/ntdll/rtl/libsupp.c @@ -14,6 +14,8 @@ #include 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 diff --git a/reactos/lib/rtl/amd64/stubs.c b/reactos/lib/rtl/amd64/stubs.c index e5ed5f15185..fa4a90420b2 100644 --- a/reactos/lib/rtl/amd64/stubs.c +++ b/reactos/lib/rtl/amd64/stubs.c @@ -14,19 +14,6 @@ /* 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 index 00000000000..edb2d086822 --- /dev/null +++ b/reactos/lib/rtl/amd64/unwind.c @@ -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 + +#define NDEBUG +#include + +#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; +} + + diff --git a/reactos/lib/rtl/rtl.rbuild b/reactos/lib/rtl/rtl.rbuild index a39fd2eefb2..719c0f8c5c6 100644 --- a/reactos/lib/rtl/rtl.rbuild +++ b/reactos/lib/rtl/rtl.rbuild @@ -39,6 +39,7 @@ debug_asm.S + unwind.c stubs.c mem.c diff --git a/reactos/ntoskrnl/amd64stubs.c b/reactos/ntoskrnl/amd64stubs.c index 22e735d6fee..f36c0e8267e 100644 --- a/reactos/ntoskrnl/amd64stubs.c +++ b/reactos/ntoskrnl/amd64stubs.c @@ -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) diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 49f754b212d..12fdb85ef92 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -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 */ diff --git a/reactos/ntoskrnl/rtl/libsupp.c b/reactos/ntoskrnl/rtl/libsupp.c index d81a3cf6b97..2760a163ffa 100644 --- a/reactos/ntoskrnl/rtl/libsupp.c +++ b/reactos/ntoskrnl/rtl/libsupp.c @@ -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)