mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
Alex Ionescu <ionucu@videotron.ca>
Various bugcheck code improvements: - Fix bugcheck code and make debugging easier for unhandled exceptions/spinlocks. - Fix a race condition with TAB+B, - Fix irql to be high_level. - Fix calling unsafe function by caching bugcode data. - Fix support for smp by using IPI. - Fix not-breakpointing when no debugger is there. - Implement KeBugCheck callbacks with reason. - Fix callbacks not being called. - Fix proper breakpoint during bugcheck. Filip Navara <xnavara@volny.cz> - Move the bugcheck initialization code into Ke (was in Ex on Alex's branch). svn path=/trunk/; revision=13969
This commit is contained in:
parent
5307ffb9c6
commit
f954a88f34
7 changed files with 414 additions and 191 deletions
|
@ -38,11 +38,11 @@
|
||||||
/* Assert only on "checked" version */
|
/* Assert only on "checked" version */
|
||||||
#ifndef NASSERT
|
#ifndef NASSERT
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), KeBugCheck(0); }
|
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), DbgBreakPoint(); }
|
||||||
#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), KeBugCheck(0); }
|
#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), DbgBreakPoint(); }
|
||||||
#else
|
#else
|
||||||
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
|
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); DbgBreakPoint(); }
|
||||||
#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
|
#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); DbgBreakPoint(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define assertmsg(_c_, _m_) \
|
#define assertmsg(_c_, _m_) \
|
||||||
|
|
|
@ -196,7 +196,7 @@ VOID KeInitDpc(struct _KPCR* Pcr);
|
||||||
VOID KeInitDispatcher(VOID);
|
VOID KeInitDispatcher(VOID);
|
||||||
VOID KeInitializeDispatcher(VOID);
|
VOID KeInitializeDispatcher(VOID);
|
||||||
VOID KiInitializeSystemClock(VOID);
|
VOID KiInitializeSystemClock(VOID);
|
||||||
VOID KeInitializeBugCheck(VOID);
|
VOID KiInitializeBugCheck(VOID);
|
||||||
VOID Phase1Initialization(PVOID Context);
|
VOID Phase1Initialization(PVOID Context);
|
||||||
|
|
||||||
VOID KeInit1(PCHAR CommandLine, PULONG LastKernelAddress);
|
VOID KeInit1(PCHAR CommandLine, PULONG LastKernelAddress);
|
||||||
|
|
|
@ -1,200 +1,445 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/bug.c
|
* FILE: ntoskrnl/ke/bug.c
|
||||||
* PURPOSE: Graceful system shutdown if a bug is detected
|
* PURPOSE: Graceful system shutdown if a bug is detected
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: David Welch (welch@cwcom.net)
|
* PROGRAMMERS: Alex Ionescu - Rewrote Bugcheck Routines and implemented Reason Callbacks.
|
||||||
|
* David Welch (welch@cwcom.net)
|
||||||
* Phillip Susi
|
* Phillip Susi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#include <ntos/bootvid.h>
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
#include "../../hal/halx86/include/hal.h"
|
|
||||||
|
|
||||||
/* GLOBALS ******************************************************************/
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL};
|
static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL};
|
||||||
|
static LIST_ENTRY BugcheckReasonCallbackListHead = {NULL,NULL};
|
||||||
static ULONG InBugCheck;
|
static ULONG InBugCheck;
|
||||||
|
static PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
|
||||||
|
static ULONG KeBugCheckCount = 1;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
VOID
|
||||||
KeInitializeBugCheck(VOID)
|
INIT_FUNCTION
|
||||||
|
KiInitializeBugCheck(VOID)
|
||||||
{
|
{
|
||||||
InitializeListHead(&BugcheckCallbackListHead);
|
PRTL_MESSAGE_RESOURCE_DATA BugCheckData;
|
||||||
InBugCheck = 0;
|
LDR_RESOURCE_INFO ResourceInfo;
|
||||||
|
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Initialize Callbadk Listhead and State */
|
||||||
|
InitializeListHead(&BugcheckCallbackListHead);
|
||||||
|
InitializeListHead(&BugcheckReasonCallbackListHead);
|
||||||
|
InBugCheck = 0;
|
||||||
|
|
||||||
|
/* Cache the Bugcheck Message Strings. Prepare the Lookup Data */
|
||||||
|
ResourceInfo.Type = 11;
|
||||||
|
ResourceInfo.Name = 1;
|
||||||
|
ResourceInfo.Language = 9;
|
||||||
|
|
||||||
|
/* Do the lookup. */
|
||||||
|
Status = LdrFindResource_U((PVOID)KERNEL_BASE,
|
||||||
|
&ResourceInfo,
|
||||||
|
RESOURCE_DATA_LEVEL,
|
||||||
|
&ResourceDataEntry);
|
||||||
|
|
||||||
|
/* Make sure it worked */
|
||||||
|
if (NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
DPRINT1("Found Bugcheck Resource Data!\n");
|
||||||
|
|
||||||
|
/* Now actually get a pointer to it */
|
||||||
|
Status = LdrAccessResource((PVOID)KERNEL_BASE,
|
||||||
|
ResourceDataEntry,
|
||||||
|
(PVOID*)&BugCheckData,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Make sure it worked */
|
||||||
|
if (NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
DPRINT1("Got Pointer to Bugcheck Resource Data!\n");
|
||||||
|
KiBugCodeMessages = BugCheckData;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN STDCALL
|
BOOLEAN
|
||||||
|
STDCALL
|
||||||
KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
|
KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
|
||||||
{
|
{
|
||||||
/* Check the Current State */
|
KIRQL OldIrql;
|
||||||
if (CallbackRecord->State == BufferInserted) {
|
BOOLEAN Status = FALSE;
|
||||||
CallbackRecord->State = BufferEmpty;
|
|
||||||
RemoveEntryList(&CallbackRecord->Entry);
|
/* Raise IRQL to High */
|
||||||
return TRUE;
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
}
|
|
||||||
|
/* Check the Current State */
|
||||||
/* The callback wasn't registered */
|
if (CallbackRecord->State == BufferInserted) {
|
||||||
return FALSE;
|
|
||||||
|
/* Reset state and remove from list */
|
||||||
|
CallbackRecord->State = BufferEmpty;
|
||||||
|
RemoveEntryList(&CallbackRecord->Entry);
|
||||||
|
|
||||||
|
Status = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lower IRQL and return */
|
||||||
|
KeLowerIrql(OldIrql);
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN STDCALL
|
BOOLEAN
|
||||||
KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
|
STDCALL
|
||||||
PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
|
KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
|
||||||
PVOID Buffer,
|
|
||||||
ULONG Length,
|
|
||||||
PUCHAR Component)
|
|
||||||
{
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
BOOLEAN Status = FALSE;
|
||||||
|
|
||||||
|
/* Raise IRQL to High */
|
||||||
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
|
/* Check the Current State */
|
||||||
|
if (CallbackRecord->State == BufferInserted) {
|
||||||
|
|
||||||
/* Check the Current State first so we don't double-register */
|
/* Reset state and remove from list */
|
||||||
if (CallbackRecord->State == BufferEmpty) {
|
CallbackRecord->State = BufferEmpty;
|
||||||
CallbackRecord->Length = Length;
|
RemoveEntryList(&CallbackRecord->Entry);
|
||||||
CallbackRecord->Buffer = Buffer;
|
|
||||||
CallbackRecord->Component = Component;
|
Status = TRUE;
|
||||||
CallbackRecord->CallbackRoutine = CallbackRoutine;
|
}
|
||||||
CallbackRecord->State = BufferInserted;
|
|
||||||
InsertTailList(&BugcheckCallbackListHead, &CallbackRecord->Entry);
|
/* Lower IRQL and return */
|
||||||
|
KeLowerIrql(OldIrql);
|
||||||
return TRUE;
|
return Status;
|
||||||
}
|
|
||||||
|
|
||||||
/* The Callback was already registered */
|
|
||||||
return(FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
/*
|
||||||
KeBugCheckWithTf(ULONG BugCheckCode,
|
* @implemented
|
||||||
ULONG BugCheckParameter1,
|
*/
|
||||||
ULONG BugCheckParameter2,
|
BOOLEAN
|
||||||
ULONG BugCheckParameter3,
|
STDCALL
|
||||||
ULONG BugCheckParameter4,
|
KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
|
||||||
PKTRAP_FRAME Tf)
|
PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
|
||||||
|
PVOID Buffer,
|
||||||
|
ULONG Length,
|
||||||
|
PUCHAR Component)
|
||||||
{
|
{
|
||||||
PRTL_MESSAGE_RESOURCE_ENTRY Message;
|
KIRQL OldIrql;
|
||||||
NTSTATUS Status;
|
BOOLEAN Status = FALSE;
|
||||||
ULONG Mask;
|
|
||||||
KIRQL OldIrql;
|
/* Raise IRQL to High */
|
||||||
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
/* Make sure we're switching back to the blue screen and print messages on it */
|
|
||||||
HalReleaseDisplayOwnership();
|
/* Check the Current State first so we don't double-register */
|
||||||
if (0 == (KdDebugState & KD_DEBUG_GDB))
|
if (CallbackRecord->State == BufferEmpty) {
|
||||||
{
|
|
||||||
KdDebugState |= KD_DEBUG_SCREEN;
|
/* Set the Callback Settings and insert into the list */
|
||||||
|
CallbackRecord->Length = Length;
|
||||||
|
CallbackRecord->Buffer = Buffer;
|
||||||
|
CallbackRecord->Component = Component;
|
||||||
|
CallbackRecord->CallbackRoutine = CallbackRoutine;
|
||||||
|
CallbackRecord->State = BufferInserted;
|
||||||
|
InsertTailList(&BugcheckCallbackListHead, &CallbackRecord->Entry);
|
||||||
|
|
||||||
|
Status = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ke386DisableInterrupts();
|
/* Lower IRQL and return */
|
||||||
DebugLogDumpMessages();
|
KeLowerIrql(OldIrql);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
|
/*
|
||||||
{
|
* @implemented
|
||||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
STDCALL
|
||||||
|
KeRegisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
|
||||||
|
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
|
||||||
|
IN KBUGCHECK_CALLBACK_REASON Reason,
|
||||||
|
IN PUCHAR Component)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
BOOLEAN Status = FALSE;
|
||||||
|
|
||||||
|
/* Raise IRQL to High */
|
||||||
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
|
/* Check the Current State first so we don't double-register */
|
||||||
|
if (CallbackRecord->State == BufferEmpty) {
|
||||||
|
|
||||||
|
/* Set the Callback Settings and insert into the list */
|
||||||
|
CallbackRecord->Component = Component;
|
||||||
|
CallbackRecord->CallbackRoutine = CallbackRoutine;
|
||||||
|
CallbackRecord->State = BufferInserted;
|
||||||
|
CallbackRecord->Reason = Reason;
|
||||||
|
InsertTailList(&BugcheckReasonCallbackListHead, &CallbackRecord->Entry);
|
||||||
|
|
||||||
|
Status = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KeGetCurrentIrql() < DISPATCH_LEVEL)
|
/* Lower IRQL and return */
|
||||||
{
|
KeLowerIrql(OldIrql);
|
||||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
return Status;
|
||||||
}
|
}
|
||||||
DbgPrint("Bug detected (code %x param %x %x %x %x)\n",
|
|
||||||
BugCheckCode,
|
|
||||||
BugCheckParameter1,
|
|
||||||
BugCheckParameter2,
|
|
||||||
BugCheckParameter3,
|
|
||||||
BugCheckParameter4);
|
|
||||||
|
|
||||||
Status = RtlFindMessage((PVOID)KERNEL_BASE, //0xC0000000,
|
VOID
|
||||||
11, //RT_MESSAGETABLE,
|
STDCALL
|
||||||
0x09, //0x409,
|
KeGetBugMessageText(ULONG BugCheckCode, PANSI_STRING OutputString)
|
||||||
BugCheckCode,
|
{
|
||||||
&Message);
|
ULONG i;
|
||||||
if (NT_SUCCESS(Status))
|
ULONG IdOffset;
|
||||||
{
|
ULONG_PTR MessageEntry;
|
||||||
if (Message->Flags == 0)
|
PCHAR BugCode;
|
||||||
DbgPrint(" %s\n", Message->Text);
|
|
||||||
else
|
/* Find the message. This code is based on RtlFindMesssage -- Alex */
|
||||||
DbgPrint(" %S\n", (PWSTR)Message->Text);
|
for (i = 0; i < KiBugCodeMessages->NumberOfBlocks; i++) {
|
||||||
|
|
||||||
|
/* Check if the ID Matches */
|
||||||
|
if ((BugCheckCode >= KiBugCodeMessages->Blocks[i].LowId) &&
|
||||||
|
(BugCheckCode <= KiBugCodeMessages->Blocks[i].HighId)) {
|
||||||
|
|
||||||
|
/* Get Offset to Entry */
|
||||||
|
MessageEntry = (ULONG_PTR)KiBugCodeMessages + KiBugCodeMessages->Blocks[i].OffsetToEntries;
|
||||||
|
IdOffset = BugCheckCode - KiBugCodeMessages->Blocks[i].LowId;
|
||||||
|
|
||||||
|
/* Get offset to ID */
|
||||||
|
for (i = 0; i < IdOffset; i++) {
|
||||||
|
|
||||||
|
/* Advance in the Entries */
|
||||||
|
MessageEntry += ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the final Code */
|
||||||
|
BugCode = ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
|
||||||
|
|
||||||
|
/* Return it in the OutputString */
|
||||||
|
if (OutputString) {
|
||||||
|
|
||||||
|
OutputString->Buffer = BugCode;
|
||||||
|
OutputString->Length = strlen(BugCode) + 1;
|
||||||
|
OutputString->MaximumLength = strlen(BugCode) + 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Direct Output to Screen */
|
||||||
|
DbgPrint("%s\n", BugCode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
DbgPrint(" No message text found!\n\n");
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KiDoBugCheckCallbacks(VOID)
|
||||||
|
{
|
||||||
|
PKBUGCHECK_CALLBACK_RECORD CurrentRecord;
|
||||||
|
PLIST_ENTRY ListHead;
|
||||||
|
PLIST_ENTRY NextEntry;
|
||||||
|
|
||||||
|
/* FIXME: Check Checksum and add support for WithReason Callbacks */
|
||||||
|
|
||||||
|
/* First make sure that the list is Initialized... it might not be */
|
||||||
|
ListHead = &BugcheckCallbackListHead;
|
||||||
|
if (ListHead->Flink && ListHead->Blink) {
|
||||||
|
|
||||||
|
/* Loop the list */
|
||||||
|
NextEntry = ListHead->Flink;
|
||||||
|
while (NextEntry != ListHead) {
|
||||||
|
|
||||||
|
/* Get the Callback Record */
|
||||||
|
CurrentRecord = CONTAINING_RECORD(NextEntry,
|
||||||
|
KBUGCHECK_CALLBACK_RECORD,
|
||||||
|
Entry);
|
||||||
|
|
||||||
|
/* Make sure it's inserted */
|
||||||
|
if (CurrentRecord->State == BufferInserted) {
|
||||||
|
|
||||||
|
/* Call the routine */
|
||||||
|
CurrentRecord->State = BufferStarted;
|
||||||
|
(CurrentRecord->CallbackRoutine)(CurrentRecord->Buffer,
|
||||||
|
CurrentRecord->Length);
|
||||||
|
CurrentRecord->State = BufferFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to next Entry */
|
||||||
|
NextEntry = NextEntry->Flink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Mask = 1 << KeGetCurrentProcessorNumber();
|
}
|
||||||
if (InBugCheck & Mask)
|
|
||||||
{
|
VOID
|
||||||
#ifdef MP
|
STDCALL
|
||||||
DbgPrint("Recursive bug check on CPU%d, halting now\n", KeGetCurrentProcessorNumber());
|
KeBugCheckWithTf(ULONG BugCheckCode,
|
||||||
/*
|
ULONG BugCheckParameter1,
|
||||||
* FIXME:
|
ULONG BugCheckParameter2,
|
||||||
* Send an ipi to all other processors which halt them too.
|
ULONG BugCheckParameter3,
|
||||||
*/
|
ULONG BugCheckParameter4,
|
||||||
#else
|
PKTRAP_FRAME Tf)
|
||||||
DbgPrint("Recursive bug check halting now\n");
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
BOOLEAN GotExtendedCrashInfo = FALSE;
|
||||||
|
PVOID Address = 0;
|
||||||
|
PLIST_ENTRY CurrentEntry;
|
||||||
|
MODULE_TEXT_SECTION* CurrentSection = NULL;
|
||||||
|
extern LIST_ENTRY ModuleTextListHead;
|
||||||
|
|
||||||
|
/* Make sure we're switching back to the blue screen and print messages on it */
|
||||||
|
HalReleaseDisplayOwnership();
|
||||||
|
if (0 == (KdDebugState & KD_DEBUG_GDB)) KdDebugState |= KD_DEBUG_SCREEN;
|
||||||
|
|
||||||
|
/* Try to find out who did this. For this, we need a Trap Frame.
|
||||||
|
* Note: Some special BSODs pass the Frame/EIP as a Param. MSDN has the
|
||||||
|
* info so it eventually needs to be supported.
|
||||||
|
*/
|
||||||
|
if (Tf) {
|
||||||
|
|
||||||
|
/* For now, get Address from EIP */
|
||||||
|
Address = (PVOID)Tf->Eip;
|
||||||
|
|
||||||
|
/* Try to get information on the module */
|
||||||
|
CurrentEntry = ModuleTextListHead.Flink;
|
||||||
|
while (CurrentEntry != &ModuleTextListHead && CurrentEntry != NULL) {
|
||||||
|
|
||||||
|
/* Get the current Section */
|
||||||
|
CurrentSection = CONTAINING_RECORD(CurrentEntry,
|
||||||
|
MODULE_TEXT_SECTION,
|
||||||
|
ListEntry);
|
||||||
|
|
||||||
|
/* Check if this is the right one */
|
||||||
|
if ((Address != NULL && (Address >= (PVOID)CurrentSection->Base &&
|
||||||
|
Address < (PVOID)(CurrentSection->Base + CurrentSection->Length)))) {
|
||||||
|
|
||||||
|
/* We got it */
|
||||||
|
GotExtendedCrashInfo = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop again */
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Raise IRQL to HIGH_LEVEL */
|
||||||
|
Ke386DisableInterrupts();
|
||||||
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
|
/* Disable Interrupts, Dump Debug Messages */
|
||||||
|
DebugLogDumpMessages();
|
||||||
|
|
||||||
|
/* Unload the Kernel Adress Space if we own it */
|
||||||
|
if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
|
||||||
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
|
||||||
|
/* FIXMEs: Use inbv to clear, fill and write to screen. */
|
||||||
|
|
||||||
|
/* Show the STOP Message */
|
||||||
|
DbgPrint("A problem has been detected and ReactOS has been shut down to prevent "
|
||||||
|
"damage to your computer.\n\n");
|
||||||
|
|
||||||
|
/* Show the module name of who caused this */
|
||||||
|
if (GotExtendedCrashInfo) {
|
||||||
|
|
||||||
|
DbgPrint("The problem seems to be caused by the following file: %S\n\n", CurrentSection->Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the Bug Code String */
|
||||||
|
KeGetBugMessageText(BugCheckCode, NULL);
|
||||||
|
|
||||||
|
/* Show the techincal Data */
|
||||||
|
DbgPrint("Technical information:\n\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\n\n",
|
||||||
|
BugCheckCode,
|
||||||
|
BugCheckParameter1,
|
||||||
|
BugCheckParameter2,
|
||||||
|
BugCheckParameter3,
|
||||||
|
BugCheckParameter4);
|
||||||
|
|
||||||
|
/* Show the module name and more data of who caused this */
|
||||||
|
if (GotExtendedCrashInfo) {
|
||||||
|
|
||||||
|
DbgPrint("*** %S - Address 0x%p base at 0x%p, DateStamp 0x%x\n\n",
|
||||||
|
CurrentSection->Name,
|
||||||
|
Address,
|
||||||
|
CurrentSection->Base,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There can only be one Bugcheck per Bootup */
|
||||||
|
if (!InterlockedDecrement(&KeBugCheckCount)) {
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
ULONG i;
|
||||||
|
/* Freeze the other CPUs */
|
||||||
|
for (i = 0; i < KeNumberProcessors; i++) {
|
||||||
|
if (i != KeGetCurrentProcessorNumber()) {
|
||||||
|
|
||||||
|
/* Send the IPI and give them one second to catch up */
|
||||||
|
KiIpiSendRequest(1 << i, IPI_REQUEST_FREEZE);
|
||||||
|
KeStallExecutionProcessor(1000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
Ke386HaltProcessor();
|
|
||||||
}
|
/* Check if we got a Trap Frame */
|
||||||
/*
|
if (Tf) {
|
||||||
* FIXME:
|
|
||||||
* Use InterlockedOr or InterlockedBitSet.
|
/* Dump it */
|
||||||
*/
|
KiDumpTrapFrame(Tf, BugCheckParameter1, BugCheckParameter2);
|
||||||
InBugCheck |= Mask;
|
|
||||||
if (Tf != NULL)
|
} else {
|
||||||
{
|
|
||||||
KiDumpTrapFrame(Tf, BugCheckParameter1, BugCheckParameter2);
|
/* We can only dump the frames */
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
KeDumpStackFrames((PULONG)__builtin_frame_address(0));
|
KeDumpStackFrames((PULONG)__builtin_frame_address(0));
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
__asm push ebp
|
__asm push ebp
|
||||||
__asm call KeDumpStackFrames
|
__asm call KeDumpStackFrames
|
||||||
__asm add esp, 4
|
__asm add esp, 4
|
||||||
#else
|
#else
|
||||||
#error Unknown compiler for inline assembler
|
#error Unknown compiler for inline assembler
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
MmDumpToPagingFile(BugCheckCode, BugCheckParameter1,
|
|
||||||
BugCheckParameter2, BugCheckParameter3,
|
/* Call the Callbacks */;
|
||||||
BugCheckParameter4, Tf);
|
KiDoBugCheckCallbacks();
|
||||||
|
|
||||||
if (KdDebuggerEnabled)
|
/* Dump the BSOD to the Paging File */
|
||||||
{
|
MmDumpToPagingFile(BugCheckCode,
|
||||||
Ke386EnableInterrupts();
|
BugCheckParameter1,
|
||||||
DbgBreakPointNoBugCheck();
|
BugCheckParameter2,
|
||||||
Ke386DisableInterrupts();
|
BugCheckParameter3,
|
||||||
|
BugCheckParameter4,
|
||||||
|
Tf);
|
||||||
|
|
||||||
|
/* Wake up the Debugger */
|
||||||
|
if (KdDebuggerEnabled) {
|
||||||
|
Ke386EnableInterrupts();
|
||||||
|
DbgBreakPointWithStatus(DBG_STATUS_BUGCHECK_SECOND);
|
||||||
|
Ke386DisableInterrupts();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;)
|
/* Halt this CPU now */
|
||||||
{
|
for (;;) Ke386HaltProcessor();
|
||||||
/*
|
|
||||||
* FIXME:
|
|
||||||
* Send an ipi to all other processors which halt them too.
|
|
||||||
*/
|
|
||||||
Ke386HaltProcessor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*
|
||||||
VOID STDCALL
|
|
||||||
KeBugCheckEx(ULONG BugCheckCode,
|
|
||||||
ULONG BugCheckParameter1,
|
|
||||||
ULONG BugCheckParameter2,
|
|
||||||
ULONG BugCheckParameter3,
|
|
||||||
ULONG BugCheckParameter4)
|
|
||||||
/*
|
|
||||||
* FUNCTION: Brings the system down in a controlled manner when an
|
* FUNCTION: Brings the system down in a controlled manner when an
|
||||||
* inconsistency that might otherwise cause corruption has been detected
|
* inconsistency that might otherwise cause corruption has been detected
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
|
@ -202,23 +447,34 @@ KeBugCheckEx(ULONG BugCheckCode,
|
||||||
* BugCheckParameter[1-4] = Additional information about bug
|
* BugCheckParameter[1-4] = Additional information about bug
|
||||||
* RETURNS: Doesn't
|
* RETURNS: Doesn't
|
||||||
*/
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KeBugCheckEx(ULONG BugCheckCode,
|
||||||
|
ULONG BugCheckParameter1,
|
||||||
|
ULONG BugCheckParameter2,
|
||||||
|
ULONG BugCheckParameter3,
|
||||||
|
ULONG BugCheckParameter4)
|
||||||
{
|
{
|
||||||
KeBugCheckWithTf(BugCheckCode, BugCheckParameter1, BugCheckParameter2,
|
/* Call the Trap Frame version without a Trap Frame */
|
||||||
BugCheckParameter3, BugCheckParameter4, NULL);
|
KeBugCheckWithTf(BugCheckCode,
|
||||||
|
BugCheckParameter1,
|
||||||
|
BugCheckParameter2,
|
||||||
|
BugCheckParameter3,
|
||||||
|
BugCheckParameter4,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*
|
||||||
VOID STDCALL
|
|
||||||
KeBugCheck(ULONG BugCheckCode)
|
|
||||||
/*
|
|
||||||
* FUNCTION: Brings the system down in a controlled manner when an
|
* FUNCTION: Brings the system down in a controlled manner when an
|
||||||
* inconsistency that might otherwise cause corruption has been detected
|
* inconsistency that might otherwise cause corruption has been detected
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
* BugCheckCode = Specifies the reason for the bug check
|
* BugCheckCode = Specifies the reason for the bug check
|
||||||
* RETURNS: Doesn't
|
* RETURNS: Doesn't
|
||||||
*/
|
*/
|
||||||
|
VOID STDCALL
|
||||||
|
KeBugCheck(ULONG BugCheckCode)
|
||||||
{
|
{
|
||||||
KeBugCheckEx(BugCheckCode, 0, 0, 0, 0);
|
KeBugCheckEx(BugCheckCode, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,19 +257,6 @@ ExRaiseHardError (
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
BOOLEAN
|
|
||||||
STDCALL
|
|
||||||
KeDeregisterBugCheckReasonCallback(
|
|
||||||
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
@ -283,20 +270,4 @@ KeGetRecommendedSharedDataAlignment(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
BOOLEAN
|
|
||||||
STDCALL
|
|
||||||
KeRegisterBugCheckReasonCallback(
|
|
||||||
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
|
|
||||||
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
|
|
||||||
IN KBUGCHECK_CALLBACK_REASON Reason,
|
|
||||||
IN PUCHAR Component
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id:$
|
/* $Id$
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -34,10 +34,10 @@ DbgBreakPoint(VOID)
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
__asm__(".globl _DbgBreakPointNoBugCheck@0\n\t"
|
__asm__(".globl _DbgBreakPointNoBugCheck@0\n\t"
|
||||||
"_DbgBreakPointNoBugCheck@0:\n\t"
|
"_DbgBreakPointNoBugCheck@0:\n\t"
|
||||||
"int $3\n\t"
|
"int $3\n\t"
|
||||||
"ret\n\t");
|
"ret\n\t");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -355,7 +355,7 @@ KeInit2(VOID)
|
||||||
{
|
{
|
||||||
PKPCR Pcr = KeGetCurrentKPCR();
|
PKPCR Pcr = KeGetCurrentKPCR();
|
||||||
|
|
||||||
KeInitializeBugCheck();
|
KiInitializeBugCheck();
|
||||||
KeInitializeDispatcher();
|
KeInitializeDispatcher();
|
||||||
KiInitializeSystemClock();
|
KiInitializeSystemClock();
|
||||||
|
|
||||||
|
|
|
@ -178,11 +178,7 @@ KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
|
||||||
* FIXME: This depends on gcc assembling this test to a single load from
|
* FIXME: This depends on gcc assembling this test to a single load from
|
||||||
* the spinlock's value.
|
* the spinlock's value.
|
||||||
*/
|
*/
|
||||||
if (*SpinLock >= 2)
|
ASSERT(*SpinLock == 0 || 1);
|
||||||
{
|
|
||||||
DbgPrint("Lock %x has bad value %x\n", SpinLock, *SpinLock);
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((i = InterlockedExchangeUL(SpinLock, 1)) == 1)
|
while ((i = InterlockedExchangeUL(SpinLock, 1)) == 1)
|
||||||
{
|
{
|
||||||
|
@ -199,7 +195,7 @@ KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
|
DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
|
||||||
KEBUGCHECK(0);
|
KEBUGCHECKEX(SPIN_LOCK_ALREADY_OWNED, (ULONG)SpinLock, 0, 0, 0);
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +223,7 @@ KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
|
||||||
if (*SpinLock != 1)
|
if (*SpinLock != 1)
|
||||||
{
|
{
|
||||||
DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
|
DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
|
||||||
KEBUGCHECK(0);
|
KEBUGCHECKEX(SPIN_LOCK_NOT_OWNED, (ULONG)SpinLock, 0, 0, 0);
|
||||||
}
|
}
|
||||||
(void)InterlockedExchangeUL(SpinLock, 0);
|
(void)InterlockedExchangeUL(SpinLock, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue