Author: fireball Date: Mon Oct 1 21:58:49 2007 New Revision: 29332
URL: http://svn.reactos.org/svn/reactos?rev=29332&view=rev Log: - KeRosCaptureUserStackBackTrace is now created, which calls RtlWalkFrameChain with the user-mode flag, meaning that bugchecks finally show the user-mode stack again! - KeRosDumpStackFrames is fixed so that if the EIP can't be found in a module list, it's still displayed (just without the module name). Previously the EIP would not be shown, resulting in code running on the heap/stack/somewhere else not being shown as part of the trace.
Modified: trunk/reactos/dll/ntdll/rtl/libsupp.c (contents, props changed) trunk/reactos/include/ndk/rtlfuncs.h trunk/reactos/lib/rtl/exception.c trunk/reactos/ntoskrnl/ke/bug.c trunk/reactos/ntoskrnl/rtl/libsupp.c trunk/reactos/subsystems/win32/win32k/ntuser/misc.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 Mon Oct 1 21:58:49 2007 @@ -14,6 +14,19 @@ #include <debug.h>
/* FUNCTIONS ***************************************************************/ + +/* + * @implemented + */ +ULONG +NTAPI +RtlWalkFrameChain(OUT PVOID *Callers, + IN ULONG Count, + IN ULONG Flags) +{ + /* Not implemented for user-mode */ + return 0; +}
BOOLEAN NTAPI
Propchange: trunk/reactos/dll/ntdll/rtl/libsupp.c ------------------------------------------------------------------------------ --- svn:needs-lock (original) +++ svn:needs-lock (removed) @@ -1,1 +1,0 @@ -*
Modified: trunk/reactos/include/ndk/rtlfuncs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtlfuncs.h?rev=... ============================================================================== --- trunk/reactos/include/ndk/rtlfuncs.h (original) +++ trunk/reactos/include/ndk/rtlfuncs.h Mon Oct 1 21:58:49 2007 @@ -449,6 +449,15 @@ // Tracing Functions // NTSYSAPI +ULONG +NTAPI +RtlWalkFrameChain( + OUT PVOID *Callers, + IN ULONG Count, + IN ULONG Flags +); + +NTSYSAPI USHORT NTAPI RtlLogStackBackTrace(
Modified: trunk/reactos/lib/rtl/exception.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/exception.c?rev=293... ============================================================================== --- trunk/reactos/lib/rtl/exception.c (original) +++ trunk/reactos/lib/rtl/exception.c Mon Oct 1 21:58:49 2007 @@ -116,110 +116,6 @@ /* * @implemented */ -ULONG -NTAPI -RtlWalkFrameChain(OUT PVOID *Callers, - IN ULONG Count, - IN ULONG Flags) -{ - ULONG_PTR Stack, NewStack, StackBegin, StackEnd; - ULONG Eip; - BOOLEAN Result, StopSearch = FALSE; - ULONG i = 0; - - /* Get current EBP */ -#if defined(_M_IX86) -#if defined __GNUC__ - __asm__("mov %%ebp, %0" : "=r" (Stack) : ); -#elif defined(_MSC_VER) - __asm mov Stack, ebp -#endif -#elif defined(_M_MIPS) - __asm__("move $sp, %0" : "=r" (Stack) : ); -#elif defined(_M_PPC) - __asm__("mr %0,1" : "=r" (Stack) : ); -#else -#error Unknown architecture -#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; - } - - /* Use a SEH block for maximum protection */ - _SEH_TRY - { - /* Loop the frames */ - for (i = 0; i < Count; i++) - { - /* - * Leave if we're past the stack, - * if we're before the stack, - * or if we've reached ourselves. - */ - if ((Stack >= StackEnd) || - (!i ? (Stack < StackBegin) : (Stack <= StackBegin)) || - ((StackEnd - Stack) < (2 * sizeof(ULONG_PTR)))) - { - /* We're done or hit a bad address */ - break; - } - - /* Get new stack and EIP */ - NewStack = *(PULONG_PTR)Stack; - Eip = *(PULONG_PTR)(Stack + sizeof(ULONG_PTR)); - - /* Check if the new pointer is above the oldone and past the end */ - if (!((Stack < NewStack) && (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; - - /* Check if we reached a user-mode address */ - if (!(Flags) && !(Eip & 0x80000000)) break; - - /* Save this frame */ - Callers[i] = (PVOID)Eip; - - /* Check if we should continue */ - if (StopSearch) - { - /* Return the next index */ - i++; - break; - } - - /* Move to the next stack */ - Stack = NewStack; - } - } - _SEH_HANDLE - { - /* No index */ - i = 0; - } - _SEH_END; - - /* Return frames parsed */ - return i; -} - -/* - * @implemented - */ USHORT NTAPI RtlCaptureStackBackTrace(IN ULONG FramesToSkip,
Modified: trunk/reactos/ntoskrnl/ke/bug.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/bug.c?rev=29332... ============================================================================== --- trunk/reactos/ntoskrnl/ke/bug.c (original) +++ trunk/reactos/ntoskrnl/ke/bug.c Mon Oct 1 21:58:49 2007 @@ -136,6 +136,97 @@ return(FALSE); }
+PVOID +NTAPI +KiRosPcToUserFileHeader(IN PVOID Eip, + OUT PLDR_DATA_TABLE_ENTRY *LdrEntry) +{ + PVOID ImageBase, EipBase = NULL; + PLDR_DATA_TABLE_ENTRY Entry; + PLIST_ENTRY ListHead, NextEntry; + + /* + * We know this is valid because we should only be called after a + * succesfull address from RtlWalkFrameChain for UserMode, which + * validates everything for us. + */ + ListHead = &KeGetCurrentThread()-> + Teb->ProcessEnvironmentBlock->Ldr->InLoadOrderModuleList; + + /* Set list pointers and make sure it's valid */ + NextEntry = ListHead->Flink; + if (NextEntry) + { + /* Start loop */ + while (NextEntry != ListHead) + { + /* Get the loader entry */ + Entry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + /* Move to the next entry */ + NextEntry = NextEntry->Flink; + ImageBase = Entry->DllBase; + + /* Check if this is the right one */ + if (((ULONG_PTR)Eip >= (ULONG_PTR)Entry->DllBase) && + ((ULONG_PTR)Eip < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage))) + { + /* Return this entry */ + *LdrEntry = Entry; + EipBase = ImageBase; + break; + } + } + } + + /* Return the base address */ + return EipBase; +} + +USHORT +NTAPI +KeRosCaptureUserStackBackTrace(IN ULONG FramesToSkip, + IN ULONG FramesToCapture, + OUT PVOID *BackTrace, + OUT PULONG BackTraceHash OPTIONAL) +{ + 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, 1); + + /* 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; +} + VOID NTAPI KeRosDumpStackFrames(IN PULONG Frame OPTIONAL, @@ -176,7 +267,38 @@ Addr -= (ULONG_PTR)LdrEntry->DllBase; DbgPrint("<%wZ: %x>", &LdrEntry->FullDllName, Addr); } - + else if (Addr) + { + /* Print only the address */ + DbgPrint("<%x>", Addr); + } + + /* Go to the next frame */ + DbgPrint("\n"); + } + + /* Get the current frames */ + FrameCount = KeRosCaptureUserStackBackTrace(-1, 32, (PVOID*)Frames, NULL); + + /* Now loop them */ + for (i = 0; i < FrameCount; i++) + { + /* Get the EIP */ + Addr = Frames[i]; + + /* Get the base for this file */ + if (KiRosPcToUserFileHeader((PVOID)Addr, &LdrEntry)) + { + /* Print out the module name */ + Addr -= (ULONG_PTR)LdrEntry->DllBase; + DbgPrint("<%wZ: %x>", &LdrEntry->FullDllName, Addr); + } + else if (Addr) + { + /* Print only the address */ + DbgPrint("<%x>", Addr); + } + /* Go to the next frame */ DbgPrint("\n"); }
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 Mon Oct 1 21:58:49 2007 @@ -255,6 +255,144 @@ return TRUE; }
+/* + * @implemented + */ +ULONG +NTAPI +RtlWalkFrameChain(OUT PVOID *Callers, + IN ULONG Count, + IN ULONG Flags) +{ + ULONG_PTR Stack, NewStack, StackBegin, StackEnd; + ULONG Eip; + BOOLEAN Result, StopSearch = FALSE; + ULONG i = 0; + PKTHREAD Thread = KeGetCurrentThread(); + PTEB Teb; + PKTRAP_FRAME TrapFrame; + + /* Get current EBP */ +#if defined(_M_IX86) +#if defined __GNUC__ + __asm__("mov %%ebp, %0" : "=r" (Stack) : ); +#elif defined(_MSC_VER) + __asm mov Stack, ebp +#endif +#elif defined(_M_MIPS) + __asm__("move $sp, %0" : "=r" (Stack) : ); +#elif defined(_M_PPC) + __asm__("mr %0,1" : "=r" (Stack) : ); +#else +#error Unknown architecture +#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; + } + + /* Use a SEH block for maximum protection */ + _SEH_TRY + { + /* Check if we want the user-mode stack frame */ + if (Flags == 1) + { + /* Get the trap frame and TEB */ + TrapFrame = Thread->TrapFrame; + Teb = Thread->Teb; + + /* Make sure we can trust the TEB and trap frame */ + if (!(Teb) || + !((PVOID)((ULONG_PTR)TrapFrame & 0x80000000)) || + ((PVOID)TrapFrame <= (PVOID)Thread->StackLimit) || + ((PVOID)TrapFrame >= (PVOID)Thread->StackBase) || + (KeIsAttachedProcess()) || + (KeGetCurrentIrql() >= DISPATCH_LEVEL)) + { + /* Invalid or unsafe attempt to get the stack */ + return 0; + } + + /* Get the stack limits */ + StackBegin = (ULONG_PTR)Teb->Tib.StackLimit; + StackEnd = (ULONG_PTR)Teb->Tib.StackBase; + Stack = TrapFrame->Ebp; + + /* Validate them */ + if (StackEnd <= StackBegin) return 0; + ProbeForRead((PVOID)StackBegin, + StackEnd - StackBegin, + sizeof(CHAR)); + } + + /* Loop the frames */ + for (i = 0; i < Count; i++) + { + /* + * Leave if we're past the stack, + * if we're before the stack, + * or if we've reached ourselves. + */ + if ((Stack >= StackEnd) || + (!i ? (Stack < StackBegin) : (Stack <= StackBegin)) || + ((StackEnd - Stack) < (2 * sizeof(ULONG_PTR)))) + { + /* We're done or hit a bad address */ + break; + } + + /* Get new stack and EIP */ + NewStack = *(PULONG_PTR)Stack; + Eip = *(PULONG_PTR)(Stack + sizeof(ULONG_PTR)); + + /* Check if the new pointer is above the oldone and past the end */ + if (!((Stack < NewStack) && (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; + + /* Check if we reached a user-mode address */ + if (!(Flags) && !(Eip & 0x80000000)) break; + + /* Save this frame */ + Callers[i] = (PVOID)Eip; + + /* Check if we should continue */ + if (StopSearch) + { + /* Return the next index */ + i++; + break; + } + + /* Move to the next stack */ + Stack = NewStack; + } + } + _SEH_HANDLE + { + /* No index */ + i = 0; + } + _SEH_END; + + /* Return frames parsed */ + return i; +} + /* RTL Atom Tables ************************************************************/
NTSTATUS
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/misc.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/misc.c Mon Oct 1 21:58:49 2007 @@ -1543,8 +1543,7 @@ { NTSTATUS Status = STATUS_SUCCESS;
- /* remove this when all spi are implement */ - DPRINT1("UserSystemParametersInfo_StructGet SPI Action 0x%x (uiParam: 0x%x, fWinIni: 0x%x)\n",uiAction, uiParam, fWinIni); + DPRINT("UserSystemParametersInfo_StructGet SPI Action 0x%x (uiParam: 0x%x, fWinIni: 0x%x)\n",uiAction, uiParam, fWinIni);
_SEH_TRY {