windows-nt/Source/XPSP1/NT/base/boot/bd/i386/debug.c

412 lines
9.9 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}