Author: ion Date: Wed Aug 30 10:52:10 2006 New Revision: 23795
URL: http://svn.reactos.org/svn/reactos?rev=23795&view=rev Log: - Implement RtlCaptureStackBackTrace and RtlWalkFrameChain and add definitions to ntifs.h - Get rid of KeRosGetStackFrames and replace usage by RtlWalkFrameChain or RtlCaptureStackBackTrace, depending. - Remove this entry from Kernel Fun.
Modified: trunk/reactos/dll/ntdll/rtl/libsupp.c trunk/reactos/include/ddk/ntifs.h trunk/reactos/lib/rtl/exception.c trunk/reactos/lib/rtl/rtlp.h trunk/reactos/ntoskrnl/KrnlFun.c trunk/reactos/ntoskrnl/ke/bug.c trunk/reactos/ntoskrnl/mm/ppool.c trunk/reactos/ntoskrnl/ntoskrnl.def trunk/reactos/ntoskrnl/rtl/libsupp.c
Modified: trunk/reactos/dll/ntdll/rtl/libsupp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/rtl/libsupp.c?rev... ============================================================================== --- trunk/reactos/dll/ntdll/rtl/libsupp.c (original) +++ trunk/reactos/dll/ntdll/rtl/libsupp.c Wed Aug 30 10:52:10 2006 @@ -171,6 +171,18 @@ IN ULONG Size) { /* Exception logging is not done in user-mode */ +} + +BOOLEAN +NTAPI +RtlpCaptureStackLimits(IN ULONG_PTR Ebp, + IN ULONG_PTR *StackBegin, + IN ULONG_PTR *StackEnd) +{ + /* FIXME: Verify */ + *StackBegin = (ULONG_PTR)NtCurrentTeb()->Tib.StackLimit; + *StackEnd = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase; + return TRUE; }
/* RTL Atom Tables ************************************************************/
Modified: trunk/reactos/include/ddk/ntifs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/ntifs.h?rev=237... ============================================================================== --- trunk/reactos/include/ddk/ntifs.h (original) +++ trunk/reactos/include/ddk/ntifs.h Wed Aug 30 10:52:10 2006 @@ -3676,6 +3676,16 @@ );
NTSYSAPI +USHORT +NTAPI +RtlCaptureStackBackTrace ( + IN ULONG FramesToSkip, + IN ULONG FramesToCapture, + OUT PVOID *BackTrace, + OUT PULONG BackTraceHash OPTIONAL +); + +NTSYSAPI NTSTATUS NTAPI RtlCompressBuffer (
Modified: trunk/reactos/lib/rtl/exception.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/exception.c?rev=237... ============================================================================== --- trunk/reactos/lib/rtl/exception.c (original) +++ trunk/reactos/lib/rtl/exception.c Wed Aug 30 10:52:10 2006 @@ -110,8 +110,92 @@ }
/* -* @unimplemented -*/ + * @implemented + */ +ULONG +NTAPI +RtlWalkFrameChain(OUT PVOID *Callers, + IN ULONG Count, + IN ULONG Flags) +{ + PULONG Stack, NewStack; + ULONG Eip; + ULONG_PTR StackBegin, StackEnd; + BOOLEAN Result, StopSearch = FALSE; + ULONG i = 0; + + /* Get current EBP */ +#if defined __GNUC__ + __asm__("mov %%ebp, %0" : "=r" (Stack) : ); +#elif defined(_MSC_VER) + __asm mov Stack, ebp +#endif + + /* Set it as the stack begin limit as well */ + StackBegin = (ULONG_PTR)Stack; + + /* Check if we're called for non-logging mode */ + if (!Flags) + { + /* Get the actual safe limits */ + Result = RtlpCaptureStackLimits((ULONG_PTR)Stack, + &StackBegin, + &StackEnd); + if (!Result) return 0; + } + + /* Loop the frames */ + for (i = 0; i < Count; i++) + { + /* Check if we're past the stack */ + if ((ULONG_PTR)Stack >= StackEnd) break; + + /* Check if this is the first entry */ +#if 0 + if (!i) + { + if ((ULONG_PTR)Stack != StackBegin) break; + } + else + { + if ((ULONG_PTR)Stack == StackBegin) break; + } +#endif + + /* Make sure there's enough frames */ + if ((StackEnd - (ULONG_PTR)Stack) < (2 * sizeof(ULONG_PTR))) break; + + /* Get new stack and EIP */ + NewStack = (PULONG)Stack[0]; + Eip = Stack[1]; + + /* Check if the new pointer is above the oldone and past the end */ + if (!((Stack < NewStack) && ((ULONG_PTR)NewStack < StackEnd))) + { + /* Stop searching after this entry */ + StopSearch = TRUE; + } + + /* Also make sure that the EIP isn't a stack address */ + if ((StackBegin < Eip) && (Eip < StackEnd)) break; + + /* Save this frame */ + Callers[i] = (PVOID)Eip; + + /* Check if we should continue */ + if (StopSearch) break; + + /* Move to the next stack */ + Stack = NewStack; + } + + /* Return frames parsed */ + return i; +} + +/* + * @implemented + */ USHORT NTAPI RtlCaptureStackBackTrace(IN ULONG FramesToSkip, @@ -119,21 +203,39 @@ OUT PVOID *BackTrace, OUT PULONG BackTraceHash OPTIONAL) { - UNIMPLEMENTED; - return 0; -} - -/* -* @unimplemented -*/ -ULONG -NTAPI -RtlWalkFrameChain(OUT PVOID *Callers, - IN ULONG Count, - IN ULONG Flags) -{ - UNIMPLEMENTED; - return 0; + PVOID Frames[2 * 64]; + ULONG FrameCount; + ULONG Hash = 0, i; + + /* Skip a frame for the caller */ + FramesToSkip++; + + /* Don't go past the limit */ + if ((FramesToCapture + FramesToSkip) >= 128) return 0; + + /* Do the back trace */ + FrameCount = RtlWalkFrameChain(Frames, FramesToCapture + FramesToSkip, 0); + + /* Make sure we're not skipping all of them */ + if (FrameCount <= FramesToSkip) return 0; + + /* Loop all the frames */ + for (i = 0; i < FramesToCapture; i++) + { + /* Don't go past the limit */ + if ((FramesToSkip + i) >= FrameCount) break; + + /* Save this entry and hash it */ + BackTrace[i] = Frames[FramesToSkip + i]; + Hash += PtrToUlong(BackTrace[i]); + } + + /* Write the hash */ + if (BackTraceHash) *BackTraceHash = Hash; + + /* Clear the other entries and return count */ + RtlFillMemoryUlong(Frames, 128, 0); + return (USHORT)i; }
/*
Modified: trunk/reactos/lib/rtl/rtlp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/rtlp.h?rev=23795&am... ============================================================================== --- trunk/reactos/lib/rtl/rtlp.h (original) +++ trunk/reactos/lib/rtl/rtlp.h Wed Aug 30 10:52:10 2006 @@ -32,6 +32,14 @@ KPROCESSOR_MODE NTAPI RtlpGetMode(VOID); + +BOOLEAN +NTAPI +RtlpCaptureStackLimits( + IN ULONG_PTR Ebp, + IN ULONG_PTR *StackBegin, + IN ULONG_PTR *StackEnd +);
NTSTATUS NTAPI
Modified: trunk/reactos/ntoskrnl/KrnlFun.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=2379... ============================================================================== --- trunk/reactos/ntoskrnl/KrnlFun.c (original) +++ trunk/reactos/ntoskrnl/KrnlFun.c Wed Aug 30 10:52:10 2006 @@ -25,7 +25,6 @@ // - Use Object Type Mutex/Lock. // // Ke: -// - Clean up exp.c (remove all stack functions and use RtlWalkFrameChain/RtlCaptureStackBacktrace) // - Sanitize some context fields during conversions // - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord). // - Forward exceptions to user-mode debugger.
Modified: trunk/reactos/ntoskrnl/ke/bug.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/bug.c?rev=23795... ============================================================================== --- trunk/reactos/ntoskrnl/ke/bug.c (original) +++ trunk/reactos/ntoskrnl/ke/bug.c Wed Aug 30 10:52:10 2006 @@ -83,83 +83,22 @@ return(FALSE); }
-ULONG -NTAPI -KeRosGetStackFrames(PULONG Frames, - ULONG FrameCount) -{ - ULONG Count = 0; - PULONG StackBase, StackEnd, Frame; - MEMORY_BASIC_INFORMATION mbi; - ULONG ResultLength = sizeof(mbi); - NTSTATUS Status; - - _SEH_TRY - { -#if defined __GNUC__ - __asm__("mov %%ebp, %0" : "=r" (Frame) : ); -#elif defined(_MSC_VER) - __asm mov [Frame], ebp -#endif - - Status = MiQueryVirtualMemory ( - (HANDLE)-1, - Frame, - MemoryBasicInformation, - &mbi, - sizeof(mbi), - &ResultLength ); - if ( !NT_SUCCESS(Status) ) - { - DPRINT1("Can't get stack frames: MiQueryVirtualMemory() failed: %x\n", Status ); - return 0; - } - - StackBase = Frame; - StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize); - - while ( Count < FrameCount && Frame >= StackBase && Frame < StackEnd ) - { - Frames[Count++] = Frame[1]; - StackBase = Frame; - Frame = (PULONG)Frame[0]; - } - } - _SEH_HANDLE - { - } - _SEH_END; - return Count; -} - -VOID -NTAPI -KeDumpStackFrames(PULONG Frame) -{ - /* Just call the extended version */ - KeRosDumpStackFrames(Frame, 0); -} - VOID NTAPI KeRosDumpStackFrames(IN PULONG Frame OPTIONAL, IN ULONG FrameCount OPTIONAL) { ULONG Frames[32]; - ULONG Count, i, Addr; - - /* Don't let anyone ask more then 32 frames */ - if (FrameCount > 32) return; + ULONG i, Addr;
/* If the caller didn't ask, assume 32 frames */ if (!FrameCount) FrameCount = 32;
- /* Get the current frames, and make sure caller didn't ask too many */ - Count = KeRosGetStackFrames(Frames, FrameCount); // <= should be replaced with Rtl - if (FrameCount > Count) FrameCount = Count; + /* Get the current frames */ + FrameCount = RtlCaptureStackBackTrace(2, FrameCount, (PVOID*)Frames, NULL);
/* Now loop them (skip the two. One for the dumper, one for the caller) */ - for (i = 2; i < FrameCount; i++) + for (i = 0; i < FrameCount; i++) { /* Get the EIP */ Addr = Frames[i]; @@ -177,9 +116,6 @@
/* Print it out */ if (!KeRosPrintAddress((PVOID)Addr)) DbgPrint("<%X>", Addr); - - /* Break out of invalid addresses */ - if (Addr == 0 || Addr == 0xDEADBEEF) break;
/* Go to the next frame */ DbgPrint("\n");
Modified: trunk/reactos/ntoskrnl/mm/ppool.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ppool.c?rev=237... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ppool.c (original) +++ trunk/reactos/ntoskrnl/mm/ppool.c Wed Aug 30 10:52:10 2006 @@ -34,7 +34,7 @@ #define R_PRINT_ADDRESS(addr) KeRosPrintAddress(addr) #define R_PANIC() KeBugCheck(0) #define R_DEBUG DbgPrint -#define R_GET_STACK_FRAMES(ptr,cnt) KeRosGetStackFrames(ptr,cnt) +#define R_GET_STACK_FRAMES(ptr,cnt) RtlWalkFrameChain((PVOID*)ptr,cnt, 0)
#include "rpoolmgr.h"
Modified: trunk/reactos/ntoskrnl/ntoskrnl.def URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.def?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl.def (original) +++ trunk/reactos/ntoskrnl/ntoskrnl.def Wed Aug 30 10:52:10 2006 @@ -977,7 +977,6 @@ READ_REGISTER_BUFFER_USHORT@12 KiRosPrintAddress@4 KeRosDumpStackFrames@8 -KeRosGetStackFrames@8 RtlAbsoluteToSelfRelativeSD@12 RtlAddAccessAllowedAce@16 RtlAddAce@20
Modified: trunk/reactos/ntoskrnl/rtl/libsupp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/rtl/libsupp.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/rtl/libsupp.c (original) +++ trunk/reactos/ntoskrnl/rtl/libsupp.c Wed Aug 30 10:52:10 2006 @@ -186,6 +186,34 @@
/* Not in DPC stack */ return FALSE; +} + +BOOLEAN +NTAPI +RtlpCaptureStackLimits(IN ULONG_PTR Ebp, + IN ULONG_PTR *StackBegin, + IN ULONG_PTR *StackEnd) +{ + PKTHREAD Thread = KeGetCurrentThread(); + + /* FIXME: Super native implementation */ + + /* FIXME: ROS HACK */ + if (!Thread) return FALSE; + + /* Start with defaults */ + *StackBegin = Thread->StackLimit; + *StackEnd = (ULONG_PTR)Thread->StackBase; + + /* Check if we seem to be on the DPC stack */ + if ((*StackBegin > Ebp) || (Ebp > *StackEnd)) + { + /* FIXME: TODO */ + ASSERT(FALSE); + } + + /* Return success */ + return TRUE; }
/* RTL Atom Tables ************************************************************/