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?re…
==============================================================================
--- 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=29…
==============================================================================
--- 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=2933…
==============================================================================
--- 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/nt…
==============================================================================
--- 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
{