You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
411 lines
10 KiB
411 lines
10 KiB
/*++
|
|
|
|
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;
|
|
}
|