/*++ Copyright (c) 1990 Microsoft Corporation Module Name: kdtrap.c Abstract: This module contains code to implement the target side of the portable kernel debugger. Author: Bryan M. Willman (bryanwi) 25-Sep-90 Revision History: --*/ #include "kdp.h" #pragma alloc_text(PAGEKD, KdpTrap) #pragma alloc_text(PAGEKD, KdIsThisAKdTrap) BOOLEAN KdpTrap ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChance ) /*++ Routine Description: This routine is called whenever a exception is dispatched and the kernel debugger is active. Arguments: TrapFrame - Supplies a pointer to a trap frame that describes the trap. ExceptionFrame - Supplies a pointer to a exception frame that describes the trap. ExceptionRecord - Supplies a pointer to an exception record that describes the exception. ContextRecord - Supplies the context at the time of the exception. PreviousMode - Supplies the previous processor mode. SecondChance - Supplies a boolean value that determines whether this is the second chance (TRUE) that the exception has been raised. Return Value: A value of TRUE is returned if the exception is handled. Otherwise a value of FALSE is returned. --*/ { BOOLEAN Completion = FALSE; BOOLEAN UnloadSymbols = FALSE; ULONG OldEip; // // Print, Prompt, Load symbols, Unload symbols, are all special // cases of STATUS_BREAKPOINT // if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK)) { // // Switch on the breakpoint code. // OldEip = ContextRecord->Eip; switch (ExceptionRecord->ExceptionInformation[0]) { // // ExceptionInformation[1] - Address of the message. // ExceptionInformation[2] - Length of the message. // ContextRecord->Ebx - the Id of the calling component. // ContextRecord->Edi - the output importance level. // case BREAKPOINT_PRINT: ContextRecord->Eax = KdpPrint((ULONG)ContextRecord->Ebx, (ULONG)ContextRecord->Edi, (PCHAR)ExceptionRecord->ExceptionInformation[1], (USHORT)ExceptionRecord->ExceptionInformation[2], PreviousMode, TrapFrame, ExceptionFrame, &Completion); break; // // ExceptionInformation[1] - Address of the message. // ExceptionInformation[2] - Length of the message. // ContextRecord->Ebx - Address of the reply. // ContextRecord->Edi - Maximum length of reply. // case BREAKPOINT_PROMPT: ContextRecord->Eax = KdpPrompt((PCHAR)ExceptionRecord->ExceptionInformation[1], (USHORT)ExceptionRecord->ExceptionInformation[2], (PCHAR)ContextRecord->Ebx, (USHORT)ContextRecord->Edi, PreviousMode, TrapFrame, ExceptionFrame); Completion = TRUE; break; // // ExceptionInformation[1] is file name of new module. // ExceptionInformation[2] is a pointer to the symbol // information. // case BREAKPOINT_UNLOAD_SYMBOLS: UnloadSymbols = TRUE; // // Fall through // case BREAKPOINT_LOAD_SYMBOLS: KdpSymbol((PSTRING)ExceptionRecord->ExceptionInformation[1], (PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2], UnloadSymbols, PreviousMode, ContextRecord, TrapFrame, ExceptionFrame); Completion = TRUE; break; case BREAKPOINT_COMMAND_STRING: KdpCommandString((PSTRING)ExceptionRecord->ExceptionInformation[1], (PSTRING)ExceptionRecord->ExceptionInformation[2], PreviousMode, ContextRecord, TrapFrame, ExceptionFrame); Completion = TRUE; break; // // Unknown command // default: // return FALSE break; } // // If the kernel debugger did not update the EIP, then increment // past the breakpoint instruction. // if (ContextRecord->Eip == OldEip) { ContextRecord->Eip++; } } else { // // Report state change to the kernel debugger. // Completion = KdpReport(TrapFrame, ExceptionFrame, ExceptionRecord, ContextRecord, PreviousMode, SecondChance); } return Completion; } BOOLEAN KdIsThisAKdTrap ( IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN KPROCESSOR_MODE PreviousMode ) /*++ Routine Description: This routine is called whenever a user-mode exception occurs and it might be a kernel debugger exception (Like DbgPrint/DbgPrompt ). Arguments: ExceptionRecord - Supplies a pointer to an exception record that describes the exception. ContextRecord - Supplies the context at the time of the exception. PreviousMode - Supplies the previous processor mode. Return Value: A value of TRUE is returned if this is for the kernel debugger. Otherwise, a value of FALSE is returned. --*/ { UNREFERENCED_PARAMETER (ContextRecord); UNREFERENCED_PARAMETER (PreviousMode); if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && (ExceptionRecord->NumberParameters > 0) && (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK)) { return TRUE; } else { return FALSE; } } BOOLEAN KdpStub ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChance ) /*++ Routine Description: This routine provides a kernel debugger stub routine to catch debug prints in a checked system when the kernel debugger is not active. Arguments: TrapFrame - Supplies a pointer to a trap frame that describes the trap. ExceptionFrame - Supplies a pointer to a exception frame that describes the trap. ExceptionRecord - Supplies a pointer to an exception record that describes the exception. ContextRecord - Supplies the context at the time of the exception. PreviousMode - Supplies the previous processor mode. SecondChance - Supplies a boolean value that determines whether this is the second chance (TRUE) that the exception has been raised. Return Value: A value of TRUE is returned if the exception is handled. Otherwise a value of FALSE is returned. --*/ { UNREFERENCED_PARAMETER (TrapFrame); UNREFERENCED_PARAMETER (ExceptionFrame); UNREFERENCED_PARAMETER (PreviousMode); UNREFERENCED_PARAMETER (SecondChance); // // If the breakpoint is a debug print, then return TRUE. Otherwise, // return FALSE. // if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && (ExceptionRecord->NumberParameters > 0) && ((ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_LOAD_SYMBOLS) || (ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_UNLOAD_SYMBOLS) || (ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_COMMAND_STRING) || (ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_PRINT))) { ContextRecord->Eip++; return TRUE; } else if (KdPitchDebugger == TRUE) { return FALSE; } else if (KdAutoEnableOnEvent && KdPreviouslyEnabled && !KdDebuggerEnabled) { // If there are multiple disables this may not reenable // the debugger. Check before calling the full trap routine. if (NT_SUCCESS(KdEnableDebugger()) && KdDebuggerEnabled) { return KdpTrap(TrapFrame, ExceptionFrame, ExceptionRecord, ContextRecord, PreviousMode, SecondChance); } else { return KdpCheckTracePoint(ExceptionRecord, ContextRecord); } } else { return KdpCheckTracePoint(ExceptionRecord, ContextRecord); } }