mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 22:55:41 +00:00
- 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. svn path=/trunk/; revision=29332
This commit is contained in:
parent
bb7d880c70
commit
fe7669dea4
6 changed files with 283 additions and 106 deletions
|
@ -15,6 +15,19 @@
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
RtlWalkFrameChain(OUT PVOID *Callers,
|
||||||
|
IN ULONG Count,
|
||||||
|
IN ULONG Flags)
|
||||||
|
{
|
||||||
|
/* Not implemented for user-mode */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlpCheckForActiveDebugger(BOOLEAN Type)
|
RtlpCheckForActiveDebugger(BOOLEAN Type)
|
||||||
|
|
|
@ -448,6 +448,15 @@ RtlUnwind(
|
||||||
//
|
//
|
||||||
// Tracing Functions
|
// Tracing Functions
|
||||||
//
|
//
|
||||||
|
NTSYSAPI
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
RtlWalkFrameChain(
|
||||||
|
OUT PVOID *Callers,
|
||||||
|
IN ULONG Count,
|
||||||
|
IN ULONG Flags
|
||||||
|
);
|
||||||
|
|
||||||
NTSYSAPI
|
NTSYSAPI
|
||||||
USHORT
|
USHORT
|
||||||
NTAPI
|
NTAPI
|
||||||
|
|
|
@ -113,110 +113,6 @@ RtlRaiseStatus(NTSTATUS Status)
|
||||||
RtlRaiseStatus(Status);
|
RtlRaiseStatus(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -136,6 +136,97 @@ KiRosPrintAddress(PVOID address)
|
||||||
return(FALSE);
|
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
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
KeRosDumpStackFrames(IN PULONG Frame OPTIONAL,
|
KeRosDumpStackFrames(IN PULONG Frame OPTIONAL,
|
||||||
|
@ -176,10 +267,41 @@ KeRosDumpStackFrames(IN PULONG Frame OPTIONAL,
|
||||||
Addr -= (ULONG_PTR)LdrEntry->DllBase;
|
Addr -= (ULONG_PTR)LdrEntry->DllBase;
|
||||||
DbgPrint("<%wZ: %x>", &LdrEntry->FullDllName, Addr);
|
DbgPrint("<%wZ: %x>", &LdrEntry->FullDllName, Addr);
|
||||||
}
|
}
|
||||||
|
else if (Addr)
|
||||||
|
{
|
||||||
|
/* Print only the address */
|
||||||
|
DbgPrint("<%x>", Addr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Go to the next frame */
|
/* Go to the next frame */
|
||||||
DbgPrint("\n");
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
/* Finish the output */
|
/* Finish the output */
|
||||||
DbgPrint("\n");
|
DbgPrint("\n");
|
||||||
|
|
|
@ -255,6 +255,144 @@ RtlpCaptureStackLimits(IN ULONG_PTR Ebp,
|
||||||
return TRUE;
|
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 ************************************************************/
|
/* RTL Atom Tables ************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -1543,8 +1543,7 @@ UserSystemParametersInfo_StructGet(
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
/* remove this when all spi are implement */
|
DPRINT("UserSystemParametersInfo_StructGet SPI Action 0x%x (uiParam: 0x%x, fWinIni: 0x%x)\n",uiAction, uiParam, fWinIni);
|
||||||
DPRINT1("UserSystemParametersInfo_StructGet SPI Action 0x%x (uiParam: 0x%x, fWinIni: 0x%x)\n",uiAction, uiParam, fWinIni);
|
|
||||||
|
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue