VOID KiRestoreProcessorState ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ) /*++ Routine Description: This function moves processor register state from the current processor context structure in the processor block to the specified trap and exception frames. Arguments: TrapFrame - Supplies a pointer to a trap frame. ExceptionFrame - Supplies a pointer to an exception frame. Return Value: None. --*/ { PKPRCB Prcb; // // Get the address of the current processor block and move the // specified register state from the processor context structure // to the specified trap and exception frames // Prcb = KeGetCurrentPrcb(); #if !defined(NT_UP) KeContextToKframes(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame, CONTEXT_FULL, KernelMode); #endif // // Restore the current processor control state. // Currently, the primary use is to allow the kernel // debugger to set hardware debug registers. Still // investigating whether this is required for MP systems. // KiRestoreProcessorControlState(&Prcb->ProcessorState); return; }
VOID NTAPI KdpSymbol(IN PSTRING DllPath, IN PKD_SYMBOLS_INFO SymbolInfo, IN BOOLEAN Unload, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame) { BOOLEAN Enable; PKPRCB Prcb = KeGetCurrentPrcb(); /* Check if we need to do anything */ if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return; /* Enter the debugger */ Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); /* Save the CPU Control State and save the context */ KiSaveProcessorControlState(&Prcb->ProcessorState); RtlCopyMemory(&Prcb->ProcessorState.ContextFrame, ContextRecord, sizeof(CONTEXT)); /* Report the new state */ KdpReportLoadSymbolsStateChange(DllPath, SymbolInfo, Unload, &Prcb->ProcessorState.ContextFrame); /* Restore the processor state */ RtlCopyMemory(ContextRecord, &Prcb->ProcessorState.ContextFrame, sizeof(CONTEXT)); KiRestoreProcessorControlState(&Prcb->ProcessorState); /* Exit the debugger and return */ KdExitDebugger(Enable); }
VOID NTAPI KdpCommandString(IN PSTRING NameString, IN PSTRING CommandString, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame) { BOOLEAN Enable; PKPRCB Prcb = KeGetCurrentPrcb(); /* Check if we need to do anything */ if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return; /* Enter the debugger */ Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); /* Save the CPU Control State and save the context */ KiSaveProcessorControlState(&Prcb->ProcessorState); RtlCopyMemory(&Prcb->ProcessorState.ContextFrame, ContextRecord, sizeof(CONTEXT)); /* Send the command string to the debugger */ KdpReportCommandStringStateChange(NameString, CommandString, &Prcb->ProcessorState.ContextFrame); /* Restore the processor state */ RtlCopyMemory(ContextRecord, &Prcb->ProcessorState.ContextFrame, sizeof(CONTEXT)); KiRestoreProcessorControlState(&Prcb->ProcessorState); /* Exit the debugger and return */ KdExitDebugger(Enable); }
VOID KiRestoreProcessorState ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ) /*++ Routine Description: This function restores the processor state to the specified exception and trap frames, and restores the processor control state. Arguments: TrapFrame - Supplies a pointer to a trap frame. ExceptionFrame - Supplies a pointer to an exception frame. Return Value: None. --*/ { #if !defined(NT_UP) PKPRCB Prcb; KPROCESSOR_MODE PreviousMode; // // Get the address of the current processor block, move the specified // register state from the processor context structure to the specified // trap and exception frames, and restore the processor control state. // if ((TrapFrame->SegCs & MODE_MASK) != 0) { PreviousMode = UserMode; } else { PreviousMode = KernelMode; } Prcb = KeGetCurrentPrcb(); KeContextToKframes(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame, CONTEXT_FULL, PreviousMode); KiRestoreProcessorControlState(&Prcb->ProcessorState); #else UNREFERENCED_PARAMETER(TrapFrame); UNREFERENCED_PARAMETER(ExceptionFrame); #endif return; }
BOOLEAN NTAPI KdpReport(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN SecondChanceException) { BOOLEAN Enable, Handled; PKPRCB Prcb; NTSTATUS ExceptionCode = ExceptionRecord->ExceptionCode; /* * Determine whether to pass the exception to the debugger. * First, check if this is a "debug exception", meaning breakpoint * (including debug service), single step and assertion failure exceptions. */ if ((ExceptionCode == STATUS_BREAKPOINT) || (ExceptionCode == STATUS_SINGLE_STEP) || (ExceptionCode == STATUS_ASSERTION_FAILURE)) { /* This is a debug exception; we always pass them to the debugger */ } else if (NtGlobalFlag & FLG_STOP_ON_EXCEPTION) { /* * Not a debug exception, but the stop-on-exception flag is set, * meaning the debugger requests that we pass it first chance * exceptions. However, some exceptions are always passed to the * exception handler first, namely exceptions with a code that isn't * an error or warning code, and also exceptions with the special * STATUS_PORT_DISCONNECTED code (an error code). */ if ((SecondChanceException == FALSE) && ((ExceptionCode == STATUS_PORT_DISCONNECTED) || (NT_SUCCESS(ExceptionCode)))) { /* Let the exception handler, if any, try to handle it */ return FALSE; } } else if (SecondChanceException == FALSE) { /* * This isn't a debug exception and the stop-on-exception flag isn't * set, so don't bother */ return FALSE; } /* Enter the debugger */ Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); /* * Get the KPRCB and save the CPU Control State manually instead of * using KiSaveProcessorState, since we already have a valid CONTEXT. */ Prcb = KeGetCurrentPrcb(); KiSaveProcessorControlState(&Prcb->ProcessorState); RtlCopyMemory(&Prcb->ProcessorState.ContextFrame, ContextRecord, sizeof(CONTEXT)); /* Report the new state */ Handled = KdpReportExceptionStateChange(ExceptionRecord, &Prcb->ProcessorState. ContextFrame, SecondChanceException); /* Now restore the processor state, manually again. */ RtlCopyMemory(ContextRecord, &Prcb->ProcessorState.ContextFrame, sizeof(CONTEXT)); KiRestoreProcessorControlState(&Prcb->ProcessorState); /* Exit the debugger and clear the CTRL-C state */ KdExitDebugger(Enable); KdpControlCPressed = FALSE; return Handled; }