X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fkd%2Fkdmain.c;h=4a17c744fe84772b414b350adfe401b2cb8e328f;hp=3569c06690e9f1702e2d6554c6b5a9dd973bab71;hb=cc5c0a08164f732809d06487a52217e788cd0324;hpb=e4be245882646b6d30ac1a0e15725175403c3f8e diff --git a/reactos/ntoskrnl/kd/kdmain.c b/reactos/ntoskrnl/kd/kdmain.c index 3569c06690e..4a17c744fe8 100644 --- a/reactos/ntoskrnl/kd/kdmain.c +++ b/reactos/ntoskrnl/kd/kdmain.c @@ -2,63 +2,60 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Kernel * FILE: ntoskrnl/kd/kdinit.c - * PURPOSE: Kernel Debugger Initializtion + * PURPOSE: Kernel Debugger Initialization * * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ #include #define NDEBUG -#include +#include /* VARIABLES ***************************************************************/ -BOOLEAN EXPORTED KdDebuggerEnabled = FALSE; -BOOLEAN EXPORTED KdEnteredDebugger = FALSE; -BOOLEAN EXPORTED KdDebuggerNotPresent = TRUE; -BOOLEAN EXPORTED KiEnableTimerWatchdog = FALSE; -ULONG EXPORTED KiBugCheckData; -BOOLEAN KdpBreakPending; -VOID STDCALL PspDumpThreads(BOOLEAN SystemThreads); +BOOLEAN KdDebuggerEnabled = FALSE; +BOOLEAN KdEnteredDebugger = FALSE; +BOOLEAN KdDebuggerNotPresent = TRUE; +BOOLEAN KdBreakAfterSymbolLoad = FALSE; +BOOLEAN KdpBreakPending = FALSE; +BOOLEAN KdPitchDebugger = TRUE; +BOOLEAN KdIgnoreUmExceptions = FALSE; +VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads); + +typedef struct +{ + ULONG ComponentId; + ULONG Level; +} KD_COMPONENT_DATA; +#define MAX_KD_COMPONENT_TABLE_ENTRIES 128 +KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES]; +ULONG KdComponentTableEntries = 0; + +ULONG Kd_DEFAULT_MASK = 1 << DPFLTR_ERROR_LEVEL; /* PRIVATE FUNCTIONS *********************************************************/ ULONG -STDCALL +NTAPI KdpServiceDispatcher(ULONG Service, - PVOID Context1, - PVOID Context2) + PVOID Buffer1, + ULONG Buffer1Length) { ULONG Result = 0; switch (Service) { - case 1: /* DbgPrint */ - Result = KdpPrintString ((PANSI_STRING)Context1); + case BREAKPOINT_PRINT: /* DbgPrint */ + Result = KdpPrintString(Buffer1, Buffer1Length); break; - case TAG('R', 'o', 's', ' '): /* ROS-INTERNAL */ +#if DBG + case ' soR': /* ROS-INTERNAL */ { - switch ((ULONG)Context1) + switch ((ULONG_PTR)Buffer1) { - case DumpNonPagedPool: - MiDebugDumpNonPagedPool(FALSE); - break; - case ManualBugCheck: - KEBUGCHECK(MANUALLY_INITIATED_CRASH); - break; - - case DumpNonPagedPoolStats: - MiDebugDumpNonPagedPoolStats(FALSE); - break; - - case DumpNewNonPagedPool: - MiDebugDumpNonPagedPool(TRUE); - break; - - case DumpNewNonPagedPoolStats: - MiDebugDumpNonPagedPoolStats(TRUE); + KeBugCheck(MANUALLY_INITIATED_CRASH); break; case DumpAllThreads: @@ -72,12 +69,24 @@ KdpServiceDispatcher(ULONG Service, case EnterDebugger: DbgBreakPoint(); break; + + case ThatsWhatSheSaid: + MmDumpPfnDatabase(); + break; default: break; } + break; } + /* Special case for stack frame dumps */ + case 'DsoR': + { + KeRosDumpStackFrames((PULONG)Buffer1, Buffer1Length); + break; + } +#endif default: HalDisplayString ("Invalid debug service call!\n"); break; @@ -86,17 +95,126 @@ KdpServiceDispatcher(ULONG Service, return Result; } -KD_CONTINUE_TYPE -STDCALL -KdpEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, - KPROCESSOR_MODE PreviousMode, - PCONTEXT Context, - PKTRAP_FRAME TrapFrame, - BOOLEAN FirstChance, - BOOLEAN Gdb) +BOOLEAN +NTAPI +KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context, + IN KPROCESSOR_MODE PreviousMode, + IN BOOLEAN SecondChance) +{ + KD_CONTINUE_TYPE Return = kdHandleException; + ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0]; + + /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */ + if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && + (ExceptionRecord->NumberParameters > 0) && + ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) || + (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) || + (ExceptionCommand == BREAKPOINT_COMMAND_STRING) || + (ExceptionCommand == BREAKPOINT_PRINT) || + (ExceptionCommand == BREAKPOINT_PROMPT))) + { + /* Check if this is a debug print */ + if (ExceptionCommand == BREAKPOINT_PRINT) + { + /* Print the string */ + KdpServiceDispatcher(BREAKPOINT_PRINT, + (PVOID)ExceptionRecord->ExceptionInformation[1], + ExceptionRecord->ExceptionInformation[2]); + + /* Return success */ + KeSetContextReturnRegister(Context, STATUS_SUCCESS); + } +#ifdef KDBG + else if (ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) + { + PLDR_DATA_TABLE_ENTRY LdrEntry; + + /* Load symbols. Currently implemented only for KDBG! */ + if(KdbpSymFindModule(((PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2])->BaseOfDll, NULL, -1, &LdrEntry)) + KdbSymProcessSymbols(LdrEntry); + } + else if (ExceptionCommand == BREAKPOINT_PROMPT) + { + ULONG ReturnValue; + LPSTR OutString; + USHORT OutStringLength; + + /* Get the response string and length */ + OutString = (LPSTR)Context->Ebx; + OutStringLength = (USHORT)Context->Edi; + + /* Call KDBG */ + ReturnValue = KdpPrompt((LPSTR)ExceptionRecord-> + ExceptionInformation[1], + (USHORT)ExceptionRecord-> + ExceptionInformation[2], + OutString, + OutStringLength); + + /* Return the number of characters that we received */ + Context->Eax = ReturnValue; + } +#endif + + /* This we can handle: simply bump the Program Counter */ + KeSetContextPc(Context, KeGetContextPc(Context) + KD_BREAKPOINT_SIZE); + return TRUE; + } + +#ifdef KDBG + /* Check if this is an assertion failure */ + if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE) + { + /* Warn about it */ + DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n", + (PVOID)Context->Eip); + + /* Bump EIP to the instruction following the int 2C and return */ + Context->Eip += 2; + return TRUE; + } +#endif + + /* Get out of here if the Debugger isn't connected */ + if (KdDebuggerNotPresent) return FALSE; + +#ifdef KDBG + /* Call KDBG if available */ + Return = KdbEnterDebuggerException(ExceptionRecord, + PreviousMode, + Context, + TrapFrame, + !SecondChance); +#else /* not KDBG */ + if (WrapperInitRoutine) + { + /* Call GDB */ + Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord, + Context, + TrapFrame); + } +#endif /* not KDBG */ + + /* Debugger didn't handle it, please handle! */ + if (Return == kdHandleException) return FALSE; + + /* Debugger handled it */ + return TRUE; +} + +BOOLEAN +NTAPI +KdpCallGdb(IN PKTRAP_FRAME TrapFrame, + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context) { - /* Get out of here if the Debugger isn't enabled */ - if (!KdDebuggerEnabled) return kdHandleException; + KD_CONTINUE_TYPE Return = kdDoNotHandleException; + + /* Get out of here if the Debugger isn't connected */ + if (KdDebuggerNotPresent) return FALSE; /* FIXME: * Right now, the GDB wrapper seems to handle exceptions differntly @@ -104,21 +222,28 @@ KdpEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, * one is only called once and that's it. I don't really have the knowledge * to fix the GDB stub, so until then, we'll be using this hack */ - if (Gdb) + if (WrapperInitRoutine) { - /* Call the registered wrapper */ - if (WrapperInitRoutine) return WrapperTable. - KdpExceptionRoutine(ExceptionRecord, - Context, - TrapFrame); + Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord, + Context, + TrapFrame); } - /* Call KDBG if available */ - return KdbEnterDebuggerException(ExceptionRecord, - PreviousMode, - Context, - TrapFrame, - FirstChance); + /* Debugger didn't handle it, please handle! */ + if (Return == kdHandleException) return FALSE; + + /* Debugger handled it */ + return TRUE; +} + +BOOLEAN +NTAPI +KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context, + IN KPROCESSOR_MODE PreviousMode) +{ + /* KDBG has its own mechanism for ignoring user mode exceptions */ + return FALSE; } /* PUBLIC FUNCTIONS *********************************************************/ @@ -126,8 +251,21 @@ KdpEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, /* * @implemented */ -VOID -STDCALL +BOOLEAN +NTAPI +KdRefreshDebuggerNotPresent(VOID) +{ + UNIMPLEMENTED; + + /* Just return whatever was set previously -- FIXME! */ + return KdDebuggerNotPresent; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI KdDisableDebugger(VOID) { KIRQL OldIrql; @@ -142,13 +280,16 @@ KdDisableDebugger(VOID) /* Lower the IRQL */ KeLowerIrql(OldIrql); + + /* Return success */ + return STATUS_SUCCESS; } /* * @implemented */ -VOID -STDCALL +NTSTATUS +NTAPI KdEnableDebugger(VOID) { KIRQL OldIrql; @@ -163,43 +304,150 @@ KdEnableDebugger(VOID) /* Lower the IRQL */ KeLowerIrql(OldIrql); + + /* Return success */ + return STATUS_SUCCESS; } /* * @implemented */ BOOLEAN -STDCALL +NTAPI KdPollBreakIn(VOID) { return KdpBreakPending; } /* - * @implemented + * @unimplemented */ -VOID -STDCALL -KeEnterKernelDebugger(VOID) +NTSTATUS +NTAPI +KdPowerTransition(ULONG PowerState) { - HalDisplayString("\n\n *** Entered kernel debugger ***\n"); - - /* Set the Variable */ - KdEnteredDebugger = TRUE; - - /* Halt the CPU */ - for (;;) Ke386HaltProcessor(); + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } /* * @unimplemented */ NTSTATUS -STDCALL -KdPowerTransition(ULONG PowerState) +NTAPI +KdChangeOption(IN KD_OPTION Option, + IN ULONG InBufferLength OPTIONAL, + IN PVOID InBuffer, + IN ULONG OutBufferLength OPTIONAL, + OUT PVOID OutBuffer, + OUT PULONG OutBufferRequiredLength OPTIONAL) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } + +NTSTATUS +NTAPI +NtQueryDebugFilterState(IN ULONG ComponentId, + IN ULONG Level) +{ + ULONG i; + + /* Convert Level to mask if it isn't already one */ + if (Level < 32) + Level = 1 << Level; + + /* Check if it is not the default component */ + if (ComponentId != DPFLTR_DEFAULT_ID) + { + /* No, search for an existing entry in the table */ + for (i = 0; i < KdComponentTableEntries; i++) + { + /* Check if it is the right component */ + if (ComponentId == KdComponentTable[i].ComponentId) + { + /* Check if mask are matching */ + return (Level & KdComponentTable[i].Level) ? TRUE : FALSE; + } + } + } + + /* Entry not found in the table, use default mask */ + return (Level & Kd_DEFAULT_MASK) ? TRUE : FALSE; +} + +NTSTATUS +NTAPI +NtSetDebugFilterState(IN ULONG ComponentId, + IN ULONG Level, + IN BOOLEAN State) +{ + ULONG i; + + /* Convert Level to mask if it isn't already one */ + if (Level < 32) + Level = 1 << Level; + Level &= ~DPFLTR_MASK; + + /* Check if it is the default component */ + if (ComponentId == DPFLTR_DEFAULT_ID) + { + /* Yes, modify the default mask */ + if (State) + Kd_DEFAULT_MASK |= Level; + else + Kd_DEFAULT_MASK &= ~Level; + + return STATUS_SUCCESS; + } + + /* Search for an existing entry */ + for (i = 0; i < KdComponentTableEntries; i++ ) + { + if (ComponentId == KdComponentTable[i].ComponentId) + break; + } + + /* Check if we have found an existing entry */ + if (i == KdComponentTableEntries) + { + /* Check if we have enough space in the table */ + if (i == MAX_KD_COMPONENT_TABLE_ENTRIES) + return STATUS_INVALID_PARAMETER_1; + + /* Add a new entry */ + ++KdComponentTableEntries; + KdComponentTable[i].ComponentId = ComponentId; + KdComponentTable[i].Level = Kd_DEFAULT_MASK; + } + + /* Update entry table */ + if (State) + KdComponentTable[i].Level |= Level; + else + KdComponentTable[i].Level &= ~Level; + + return STATUS_SUCCESS; +} + +/* + * @unimplemented + */ +NTSTATUS +NTAPI +KdSystemDebugControl(IN SYSDBG_COMMAND Command, + IN PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer, + IN ULONG OutputBufferLength, + IN OUT PULONG ReturnLength, + IN KPROCESSOR_MODE PreviousMode) +{ + /* HACK */ + return KdpServiceDispatcher(Command, InputBuffer, InputBufferLength); +} + +PKDEBUG_ROUTINE KiDebugRoutine = KdpEnterDebuggerException; + /* EOF */