|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
bdtrap.c
Abstract:
This module contains code to implement the target side of the boot debugger.
Author:
David N. Cutler (davec) 30-Nov-96
Revision History:
--*/
#include "bd.h"
//
// Define forward referenced function prototypes.
//
VOID BdRestoreKframe( IN OUT PKTRAP_FRAME TrapFrame, IN PCONTEXT ContextRecord );
VOID BdSaveKframe( IN PKTRAP_FRAME TrapFrame, IN OUT PCONTEXT ContextRecord );
LOGICAL BdTrap ( IN PEXCEPTION_RECORD ExceptionRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame )
/*++
Routine Description:
This routine is called whenever a exception is dispatched and the boot debugger is active.
Arguments:
ExceptionRecord - Supplies a pointer to an exception record that describes the exception.
ExceptionFrame - Supplies a pointer to an exception frame (NULL).
TrapFrame - Supplies a pointer to a trap frame that describes the trap.
Return Value:
A value of TRUE is returned if the exception is handled. Otherwise a value of FALSE is returned.
--*/
{
LOGICAL Completion; PCONTEXT ContextRecord; ULONG OldEip; STRING Input; STRING Output; PKD_SYMBOLS_INFO SymbolInfo; LOGICAL UnloadSymbols;
//
// Set address of context record and set context flags.
//
ContextRecord = &BdPrcb.ProcessorState.ContextFrame; ContextRecord->ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
//
// Print, prompt, load symbols, and unload symbols are all special cases
// of STATUS_BREAKPOINT.
//
if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK)) {
//
// Switch on the request type.
//
UnloadSymbols = FALSE; switch (ExceptionRecord->ExceptionInformation[0]) {
//
// Print:
//
// ExceptionInformation[1] is a PSTRING which describes the string
// to print.
//
case BREAKPOINT_PRINT: Output.Buffer = (PCHAR)ExceptionRecord->ExceptionInformation[1]; Output.Length = (USHORT)ExceptionRecord->ExceptionInformation[2]; if (BdDebuggerNotPresent == FALSE) { if (BdPrintString(&Output)) { TrapFrame->Eax = (ULONG)(STATUS_BREAKPOINT);
} else { TrapFrame->Eax = STATUS_SUCCESS; }
} else { TrapFrame->Eax = (ULONG)STATUS_DEVICE_NOT_CONNECTED; }
TrapFrame->Eip += 1; return TRUE;
//
// Prompt:
//
// ExceptionInformation[1] is a PSTRING which describes the prompt
// string,
//
// ExceptionInformation[2] is a PSTRING that describes the return
// string.
//
case BREAKPOINT_PROMPT: Output.Buffer = (PCHAR)ExceptionRecord->ExceptionInformation[1]; Output.Length = (USHORT)ExceptionRecord->ExceptionInformation[2]; Input.Buffer = (PCHAR)TrapFrame->Ebx;; Input.MaximumLength = (USHORT)TrapFrame->Edi;
//
// Prompt and keep prompting until no breakin seen.
//
do { } while (BdPromptString(&Output, &Input) != FALSE);
TrapFrame->Eax = Input.Length; TrapFrame->Eip += 1; return TRUE;
//
// Unload symbols:
//
// ExceptionInformation[1] is file name of a module.
// ExceptionInformaiton[2] is the base of the dll.
//
case BREAKPOINT_UNLOAD_SYMBOLS: UnloadSymbols = TRUE;
//
// Fall through to load symbols case.
//
case BREAKPOINT_LOAD_SYMBOLS: BdSaveKframe(TrapFrame, ContextRecord); OldEip = ContextRecord->Eip; SymbolInfo = (PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2]; if (BdDebuggerNotPresent == FALSE) { BdReportLoadSymbolsStateChange((PSTRING)ExceptionRecord->ExceptionInformation[1], SymbolInfo, UnloadSymbols, ContextRecord); }
//
// If the kernel debugger did not update EIP, then increment
// past the breakpoint instruction.
//
if (ContextRecord->Eip == OldEip) { ContextRecord->Eip += 1; }
BdRestoreKframe(TrapFrame, ContextRecord); return TRUE;
//
// Unknown command
//
default: return FALSE; }
} else {
//
// Report state change to kernel debugger on host.
//
BdSaveKframe(TrapFrame, ContextRecord); Completion = BdReportExceptionStateChange(ExceptionRecord, &BdPrcb.ProcessorState.ContextFrame);
BdRestoreKframe(TrapFrame, ContextRecord); BdControlCPressed = FALSE; return TRUE; } }
LOGICAL BdStub ( IN PEXCEPTION_RECORD ExceptionRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame )
/*++
Routine Description:
This routine provides a kernel debugger stub routine to catch debug prints when the boot debugger is not active.
Arguments:
ExceptionRecord - Supplies a pointer to an exception record that describes the exception.
ExceptionFrame - Supplies a pointer to an exception frame (NULL).
TrapFrame - Supplies a pointer to a trap frame that describes the trap.
Return Value:
A value of TRUE is returned if the exception is handled. Otherwise a value of FALSE is returned.
--*/
{
//
// If the exception is a breakpoint and the function is a load symbols,
// unload symbols, or a 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_PRINT))) { TrapFrame->Eip += 1; return TRUE;
} else { return FALSE;
} }
VOID BdRestoreKframe( IN OUT PKTRAP_FRAME TrapFrame, IN PCONTEXT ContextRecord )
/*++
Routine Description:
This functions copie the processor state from a context record and the processor control block into the trap frame.
Arguments:
TrapFrame - Supplies a pointer to a trap frame.
ContextRecord - Supplies a pointer to a context record.
Return Value:
None.
--*/
{
//
// Copy information from context record to trap frame.
//
// Copy control information.
//
TrapFrame->Ebp = ContextRecord->Ebp; TrapFrame->Eip = ContextRecord->Eip; TrapFrame->SegCs = ContextRecord->SegCs; TrapFrame->EFlags = ContextRecord->EFlags;
//
// Copy segment register contents.
//
TrapFrame->SegDs = ContextRecord->SegDs; TrapFrame->SegEs = ContextRecord->SegEs; TrapFrame->SegFs = ContextRecord->SegFs; TrapFrame->SegGs = ContextRecord->SegGs;
//
// Copy integer registers contents.
//
TrapFrame->Edi = ContextRecord->Edi; TrapFrame->Esi = ContextRecord->Esi; TrapFrame->Ebx = ContextRecord->Ebx; TrapFrame->Ecx = ContextRecord->Ecx; TrapFrame->Edx = ContextRecord->Edx; TrapFrame->Eax = ContextRecord->Eax;
//
// Restore processor state.
//
KiRestoreProcessorControlState(&BdPrcb.ProcessorState); return; }
VOID BdSaveKframe( IN PKTRAP_FRAME TrapFrame, IN OUT PCONTEXT ContextRecord )
/*++
Routine Description:
This functions copis the processor state from a trap frame and the processor control block into a context record.
Arguments:
TrapFrame - Supplies a pointer to a trap frame.
ContextRecord - Supplies a pointer to a context record.
Return Value:
None.
--*/
{
//
// Copy information from trap frame to context record.
//
// Copy control information.
//
ContextRecord->Ebp = TrapFrame->Ebp; ContextRecord->Eip = TrapFrame->Eip; ContextRecord->SegCs = TrapFrame->SegCs & SEGMENT_MASK; ContextRecord->EFlags = TrapFrame->EFlags; ContextRecord->Esp = TrapFrame->TempEsp; ContextRecord->SegSs = TrapFrame->TempSegCs;
//
// Copy segment register contents.
//
ContextRecord->SegDs = TrapFrame->SegDs & SEGMENT_MASK; ContextRecord->SegEs = TrapFrame->SegEs & SEGMENT_MASK; ContextRecord->SegFs = TrapFrame->SegFs & SEGMENT_MASK; ContextRecord->SegGs = TrapFrame->SegGs & SEGMENT_MASK;
//
// Copy the integer register contents.
//
ContextRecord->Eax = TrapFrame->Eax; ContextRecord->Ebx = TrapFrame->Ebx; ContextRecord->Ecx = TrapFrame->Ecx; ContextRecord->Edx = TrapFrame->Edx; ContextRecord->Edi = TrapFrame->Edi; ContextRecord->Esi = TrapFrame->Esi;
//
// Copy debug register contents.
//
ContextRecord->Dr0 = TrapFrame->Dr0; ContextRecord->Dr1 = TrapFrame->Dr1; ContextRecord->Dr2 = TrapFrame->Dr2; ContextRecord->Dr3 = TrapFrame->Dr3; ContextRecord->Dr6 = TrapFrame->Dr6; ContextRecord->Dr7 = TrapFrame->Dr7;
//
// Save processor control state.
//
KiSaveProcessorControlState(&BdPrcb.ProcessorState); return; }
|