959 lines
22 KiB
C
959 lines
22 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
api.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the boot bebugger platform independent remote APIs.
|
||
|
||
Author:
|
||
|
||
Mark Lucovsky (markl) 31-Aug-1990
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "bd.h"
|
||
|
||
VOID
|
||
BdGetVersion(
|
||
IN PDBGKD_MANIPULATE_STATE64 m
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns to the caller a general information packet
|
||
that contains useful information to a debugger. This packet is also
|
||
used for a debugger to determine if the writebreakpointex and
|
||
readbreakpointex apis are available.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
STRING messageHeader;
|
||
|
||
messageHeader.Length = sizeof(*m);
|
||
messageHeader.Buffer = (PCHAR)m;
|
||
RtlZeroMemory(&m->u.GetVersion64, sizeof(m->u.GetVersion64));
|
||
|
||
//
|
||
// the current build number
|
||
//
|
||
// - 4 - tells the debugger this is a "special" OS - the boot loader.
|
||
// The boot loader has a lot of special cases associated with it, like
|
||
// the lack of the DebuggerDataBlock, lack of ntoskrnl, etc ...
|
||
//
|
||
|
||
m->u.GetVersion64.MinorVersion = (short)NtBuildNumber;
|
||
m->u.GetVersion64.MajorVersion = 0x400 |
|
||
(short)((NtBuildNumber >> 28) & 0xFFFFFFF);
|
||
|
||
//
|
||
// Kd protocol version number.
|
||
//
|
||
|
||
m->u.GetVersion64.ProtocolVersion = DBGKD_64BIT_PROTOCOL_VERSION2;
|
||
m->u.GetVersion64.Flags = DBGKD_VERS_FLAG_DATA;
|
||
|
||
#if defined(_M_IX86)
|
||
|
||
m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_I386;
|
||
|
||
#elif defined(_M_MRX000)
|
||
|
||
m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_R4000;
|
||
|
||
#elif defined(_M_ALPHA)
|
||
|
||
m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_ALPHA;
|
||
|
||
#elif defined(_M_PPC)
|
||
|
||
m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_POWERPC;
|
||
|
||
#elif defined(_IA64_)
|
||
|
||
m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_IA64;
|
||
m->u.GetVersion64.Flags |= DBGKD_VERS_FLAG_PTR64;
|
||
|
||
#else
|
||
|
||
#error( "unknown target machine" );
|
||
|
||
#endif
|
||
|
||
m->u.GetVersion64.MaxPacketType = (UCHAR)(PACKET_TYPE_KD_FILE_IO + 1);;
|
||
m->u.GetVersion64.MaxStateChange = (UCHAR)(DbgKdLoadSymbolsStateChange + 1);;
|
||
m->u.GetVersion64.MaxManipulate = (UCHAR)(DbgKdSetBusDataApi + 1);
|
||
|
||
|
||
//
|
||
// address of the loader table
|
||
//
|
||
|
||
m->u.GetVersion64.PsLoadedModuleList = 0;
|
||
m->u.GetVersion64.KernBase = 0;
|
||
//m->u.GetVersion64.ThCallbackStack = 0;
|
||
//m->u.GetVersion64.KiCallUserMode = 0;
|
||
//m->u.GetVersion64.KeUserCallbackDispatcher = 0;
|
||
//m->u.GetVersion64.NextCallback = 0;
|
||
|
||
#if defined(_X86_)
|
||
|
||
//m->u.GetVersion64.FramePointer = 0;
|
||
|
||
#endif
|
||
|
||
//m->u.GetVersion64.BreakpointWithStatus = 0;
|
||
m->u.GetVersion64.DebuggerDataList = 0;
|
||
|
||
//
|
||
// the usual stuff
|
||
//
|
||
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&messageHeader,
|
||
NULL);
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
BdGetContext(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response of a get context state
|
||
manipulation message. Its function is to return the current
|
||
context.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
AdditionalData - Supplies any additional data for the message.
|
||
|
||
Context - Supplies the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PDBGKD_GET_CONTEXT a = &m->u.GetContext;
|
||
STRING MessageHeader;
|
||
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
AdditionalData->Length = sizeof(CONTEXT);
|
||
BdCopyMemory(AdditionalData->Buffer, (PCHAR)Context, sizeof(CONTEXT));
|
||
|
||
//
|
||
// Send reply packet.
|
||
//
|
||
|
||
MessageHeader.Length = sizeof(*m);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
AdditionalData);
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
BdSetContext(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response of a set context state
|
||
manipulation message. Its function is set the current
|
||
context.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
AdditionalData - Supplies any additional data for the message.
|
||
|
||
Context - Supplies the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PDBGKD_SET_CONTEXT a = &m->u.SetContext;
|
||
STRING MessageHeader;
|
||
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
BdCopyMemory((PCHAR)Context, AdditionalData->Buffer, sizeof(CONTEXT));
|
||
|
||
//
|
||
// Send reply packet.
|
||
//
|
||
|
||
MessageHeader.Length = sizeof(*m);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
NULL);
|
||
}
|
||
|
||
VOID
|
||
BdReadVirtualMemory(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response to a read virtual memory 32-bit
|
||
state manipulation message. Its function is to read virtual memory
|
||
and return.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies a pointer to the state manipulation message.
|
||
|
||
AdditionalData - Supplies a pointer to a descriptor for the data to read.
|
||
|
||
Context - Supplies a pointer to the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG Length;
|
||
STRING MessageHeader;
|
||
|
||
//
|
||
// Trim the transfer count to fit in a single message.
|
||
//
|
||
|
||
Length = min(m->u.ReadMemory.TransferCount,
|
||
PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64));
|
||
|
||
//
|
||
// Move the data to the destination buffer.
|
||
//
|
||
|
||
AdditionalData->Length = (USHORT)BdMoveMemory((PCHAR)AdditionalData->Buffer,
|
||
(PCHAR)m->u.ReadMemory.TargetBaseAddress,
|
||
Length);
|
||
|
||
//
|
||
// If all the data is read, then return a success status. Otherwise,
|
||
// return an unsuccessful status.
|
||
//
|
||
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
if (Length != AdditionalData->Length) {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
//
|
||
// Set the actual number of bytes read, initialize the message header,
|
||
// and send the reply packet to the host debugger.
|
||
//
|
||
|
||
m->u.ReadMemory.ActualBytesRead = AdditionalData->Length;
|
||
MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
AdditionalData);
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
BdWriteVirtualMemory(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response of a write virtual memory 32-bit
|
||
state manipulation message. Its function is to write virtual memory
|
||
and return.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies a pointer to the state manipulation message.
|
||
|
||
AdditionalData - Supplies a pointer to a descriptor for the data to write.
|
||
|
||
Context - Supplies a pointer to the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG Length;
|
||
STRING MessageHeader;
|
||
|
||
//
|
||
// Move the data to the destination buffer.
|
||
//
|
||
|
||
Length = BdMoveMemory((PCHAR)m->u.WriteMemory.TargetBaseAddress,
|
||
(PCHAR)AdditionalData->Buffer,
|
||
AdditionalData->Length);
|
||
|
||
//
|
||
// If all the data is written, then return a success status. Otherwise,
|
||
// return an unsuccessful status.
|
||
//
|
||
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
if (Length != AdditionalData->Length) {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
//
|
||
// Set the actual number of bytes written, initialize the message header,
|
||
// and send the reply packet to the host debugger.
|
||
//
|
||
|
||
m->u.WriteMemory.ActualBytesWritten = Length;
|
||
MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
NULL);
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
BdWriteBreakpoint(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response of a write breakpoint state
|
||
manipulation message. Its function is to write a breakpoint
|
||
and return a handle to the breakpoint.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
AdditionalData - Supplies any additional data for the message.
|
||
|
||
Context - Supplies the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PDBGKD_WRITE_BREAKPOINT64 a = &m->u.WriteBreakPoint;
|
||
STRING MessageHeader;
|
||
|
||
|
||
a->BreakPointHandle = BdAddBreakpoint(a->BreakPointAddress);
|
||
if (a->BreakPointHandle != 0) {
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
//
|
||
// Send reply packet.
|
||
//
|
||
|
||
MessageHeader.Length = sizeof(*m);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
NULL);
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
BdRestoreBreakpoint(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response of a restore breakpoint state
|
||
manipulation message. Its function is to restore a breakpoint
|
||
using the specified handle.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
AdditionalData - Supplies any additional data for the message.
|
||
|
||
Context - Supplies the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PDBGKD_RESTORE_BREAKPOINT a = &m->u.RestoreBreakPoint;
|
||
STRING MessageHeader;
|
||
|
||
if (BdDeleteBreakpoint(a->BreakPointHandle)) {
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
//
|
||
// Send reply packet.
|
||
//
|
||
|
||
MessageHeader.Length = sizeof(*m);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
NULL);
|
||
}
|
||
|
||
VOID
|
||
BdReadPhysicalMemory(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response to a read physical memory
|
||
state manipulation message. Its function is to read physical memory
|
||
and return.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
AdditionalData - Supplies any additional data for the message.
|
||
|
||
Context - Supplies the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PDBGKD_READ_MEMORY64 a = &m->u.ReadMemory;
|
||
ULONG Length;
|
||
STRING MessageHeader;
|
||
PVOID VirtualAddress;
|
||
PHYSICAL_ADDRESS Source;
|
||
PUCHAR Destination;
|
||
USHORT NumberBytes;
|
||
USHORT BytesLeft;
|
||
|
||
//
|
||
// Trim transfer count to fit in a single message.
|
||
//
|
||
|
||
Length = min(a->TransferCount,
|
||
PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64));
|
||
|
||
//
|
||
// Since the BdTranslatePhysicalAddress only maps in one physical
|
||
// page at a time, we need to break the memory move up into smaller
|
||
// moves which don't cross page boundaries. There are two cases we
|
||
// need to deal with. The area to be moved may start and end on the
|
||
// same page, or it may start and end on different pages (with an
|
||
// arbitrary number of pages in between)
|
||
//
|
||
|
||
Source.QuadPart = (ULONG_PTR)a->TargetBaseAddress;
|
||
Destination = AdditionalData->Buffer;
|
||
BytesLeft = (USHORT)Length;
|
||
if(PAGE_ALIGN((PUCHAR)a->TargetBaseAddress) ==
|
||
PAGE_ALIGN((PUCHAR)(a->TargetBaseAddress)+Length)) {
|
||
|
||
//
|
||
// Memory move starts and ends on the same page.
|
||
//
|
||
|
||
VirtualAddress=BdTranslatePhysicalAddress(Source);
|
||
if (VirtualAddress == NULL) {
|
||
AdditionalData->Length = 0;
|
||
|
||
} else {
|
||
AdditionalData->Length = (USHORT)BdMoveMemory(Destination,
|
||
VirtualAddress,
|
||
BytesLeft);
|
||
|
||
BytesLeft -= AdditionalData->Length;
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Memory move spans page boundaries
|
||
//
|
||
|
||
VirtualAddress=BdTranslatePhysicalAddress(Source);
|
||
if (VirtualAddress == NULL) {
|
||
AdditionalData->Length = 0;
|
||
|
||
} else {
|
||
NumberBytes = (USHORT)(PAGE_SIZE - BYTE_OFFSET(VirtualAddress));
|
||
AdditionalData->Length = (USHORT)BdMoveMemory(Destination,
|
||
VirtualAddress,
|
||
NumberBytes);
|
||
|
||
Source.LowPart += NumberBytes;
|
||
Destination += NumberBytes;
|
||
BytesLeft -= NumberBytes;
|
||
while(BytesLeft > 0) {
|
||
|
||
//
|
||
// Transfer a full page or the last bit,
|
||
// whichever is smaller.
|
||
//
|
||
|
||
VirtualAddress = BdTranslatePhysicalAddress(Source);
|
||
if (VirtualAddress == NULL) {
|
||
break;
|
||
|
||
} else {
|
||
NumberBytes = (USHORT) ((PAGE_SIZE < BytesLeft) ? PAGE_SIZE : BytesLeft);
|
||
AdditionalData->Length += (USHORT)BdMoveMemory(
|
||
Destination,
|
||
VirtualAddress,
|
||
NumberBytes);
|
||
|
||
Source.LowPart += NumberBytes;
|
||
Destination += NumberBytes;
|
||
BytesLeft -= NumberBytes;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (Length == AdditionalData->Length) {
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
a->ActualBytesRead = AdditionalData->Length;
|
||
|
||
//
|
||
// Send reply packet.
|
||
//
|
||
|
||
MessageHeader.Length = sizeof(*m);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
AdditionalData);
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
BdWritePhysicalMemory(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response to a write physical memory
|
||
state manipulation message. Its function is to write physical memory
|
||
and return.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
AdditionalData - Supplies any additional data for the message.
|
||
|
||
Context - Supplies the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PDBGKD_WRITE_MEMORY64 a = &m->u.WriteMemory;
|
||
ULONG Length;
|
||
STRING MessageHeader;
|
||
PVOID VirtualAddress;
|
||
PHYSICAL_ADDRESS Destination;
|
||
PUCHAR Source;
|
||
USHORT NumberBytes;
|
||
USHORT BytesLeft;
|
||
|
||
MessageHeader.Length = sizeof(*m);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
|
||
//
|
||
// Since the BdTranslatePhysicalAddress only maps in one physical
|
||
// page at a time, we need to break the memory move up into smaller
|
||
// moves which don't cross page boundaries. There are two cases we
|
||
// need to deal with. The area to be moved may start and end on the
|
||
// same page, or it may start and end on different pages (with an
|
||
// arbitrary number of pages in between)
|
||
//
|
||
|
||
Destination.QuadPart = (ULONG_PTR)a->TargetBaseAddress;
|
||
Source = AdditionalData->Buffer;
|
||
BytesLeft = (USHORT) a->TransferCount;
|
||
if(PAGE_ALIGN(Destination.QuadPart) ==
|
||
PAGE_ALIGN(Destination.QuadPart+BytesLeft)) {
|
||
|
||
//
|
||
// Memory move starts and ends on the same page.
|
||
//
|
||
|
||
VirtualAddress=BdTranslatePhysicalAddress(Destination);
|
||
Length = (USHORT)BdMoveMemory(VirtualAddress,
|
||
Source,
|
||
BytesLeft);
|
||
|
||
BytesLeft -= (USHORT) Length;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Memory move spans page boundaries
|
||
//
|
||
|
||
VirtualAddress=BdTranslatePhysicalAddress(Destination);
|
||
NumberBytes = (USHORT) (PAGE_SIZE - BYTE_OFFSET(VirtualAddress));
|
||
Length = (USHORT)BdMoveMemory(VirtualAddress,
|
||
Source,
|
||
NumberBytes);
|
||
|
||
Source += NumberBytes;
|
||
Destination.LowPart += NumberBytes;
|
||
BytesLeft -= NumberBytes;
|
||
while(BytesLeft > 0) {
|
||
|
||
//
|
||
// Transfer a full page or the last bit, whichever is smaller.
|
||
//
|
||
|
||
VirtualAddress = BdTranslatePhysicalAddress(Destination);
|
||
NumberBytes = (USHORT) ((PAGE_SIZE < BytesLeft) ? PAGE_SIZE : BytesLeft);
|
||
Length += (USHORT)BdMoveMemory(VirtualAddress,
|
||
Source,
|
||
NumberBytes);
|
||
|
||
Source += NumberBytes;
|
||
Destination.LowPart += NumberBytes;
|
||
BytesLeft -= NumberBytes;
|
||
}
|
||
}
|
||
|
||
|
||
if (Length == AdditionalData->Length) {
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
a->ActualBytesWritten = Length;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
NULL);
|
||
|
||
return;
|
||
}
|
||
|
||
NTSTATUS
|
||
BdWriteBreakPointEx(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response of a write breakpoint state 'ex'
|
||
manipulation message. Its function is to clear breakpoints, write
|
||
new breakpoints, and continue the target system. The clearing of
|
||
breakpoints is conditional based on the presence of breakpoint handles.
|
||
The setting of breakpoints is conditional based on the presence of
|
||
valid, non-zero, addresses. The continueing of the target system
|
||
is conditional based on a non-zero continuestatus.
|
||
|
||
This api allows a debugger to clear breakpoints, add new breakpoint,
|
||
and continue the target system all in one api packet. This reduces the
|
||
amount of traffic across the wire and greatly improves source stepping.
|
||
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
AdditionalData - Supplies any additional data for the message.
|
||
|
||
Context - Supplies the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PDBGKD_BREAKPOINTEX a = &m->u.BreakPointEx;
|
||
PDBGKD_WRITE_BREAKPOINT64 b;
|
||
STRING MessageHeader;
|
||
ULONG i;
|
||
DBGKD_WRITE_BREAKPOINT64 BpBuf[BREAKPOINT_TABLE_SIZE];
|
||
|
||
|
||
MessageHeader.Length = sizeof(*m);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
|
||
//
|
||
// verify that the packet size is correct
|
||
//
|
||
|
||
if (AdditionalData->Length !=
|
||
a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64)) {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
BdSendPacket(
|
||
PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
AdditionalData
|
||
);
|
||
return m->ReturnStatus;
|
||
}
|
||
|
||
BdMoveMemory((PUCHAR)BpBuf,
|
||
AdditionalData->Buffer,
|
||
a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64));
|
||
|
||
//
|
||
// assume success
|
||
//
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
|
||
//
|
||
// loop thru the breakpoint handles passed in from the debugger and
|
||
// clear any breakpoint that has a non-zero handle
|
||
//
|
||
|
||
b = BpBuf;
|
||
for (i=0; i<a->BreakPointCount; i++,b++) {
|
||
if (b->BreakPointHandle) {
|
||
if (!BdDeleteBreakpoint(b->BreakPointHandle)) {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
b->BreakPointHandle = 0;
|
||
}
|
||
}
|
||
|
||
//
|
||
// loop thru the breakpoint addesses passed in from the debugger and
|
||
// add any new breakpoints that have a non-zero address
|
||
//
|
||
|
||
b = BpBuf;
|
||
for (i=0; i<a->BreakPointCount; i++,b++) {
|
||
if (b->BreakPointAddress) {
|
||
b->BreakPointHandle = BdAddBreakpoint( b->BreakPointAddress );
|
||
if (!b->BreakPointHandle) {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// send back our response
|
||
//
|
||
|
||
BdMoveMemory(AdditionalData->Buffer,
|
||
(PUCHAR)BpBuf,
|
||
a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64));
|
||
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
AdditionalData);
|
||
|
||
//
|
||
// return the caller's continue status value. if this is a non-zero
|
||
// value the system is continued using this value as the continuestatus.
|
||
//
|
||
|
||
return a->ContinueStatus;
|
||
}
|
||
|
||
VOID
|
||
BdRestoreBreakPointEx(
|
||
IN PDBGKD_MANIPULATE_STATE64 m,
|
||
IN PSTRING AdditionalData,
|
||
IN PCONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called in response of a restore breakpoint state 'ex'
|
||
manipulation message. Its function is to clear a list of breakpoints.
|
||
|
||
Arguments:
|
||
|
||
m - Supplies the state manipulation message.
|
||
|
||
AdditionalData - Supplies any additional data for the message.
|
||
|
||
Context - Supplies the current context.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PDBGKD_BREAKPOINTEX a = &m->u.BreakPointEx;
|
||
PDBGKD_RESTORE_BREAKPOINT b;
|
||
STRING MessageHeader;
|
||
ULONG i;
|
||
DBGKD_RESTORE_BREAKPOINT BpBuf[BREAKPOINT_TABLE_SIZE];
|
||
|
||
|
||
MessageHeader.Length = sizeof(*m);
|
||
MessageHeader.Buffer = (PCHAR)m;
|
||
|
||
//
|
||
// verify that the packet size is correct
|
||
//
|
||
|
||
if (AdditionalData->Length !=
|
||
a->BreakPointCount*sizeof(DBGKD_RESTORE_BREAKPOINT)) {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
AdditionalData);
|
||
|
||
return;
|
||
}
|
||
|
||
BdMoveMemory((PUCHAR)BpBuf,
|
||
AdditionalData->Buffer,
|
||
a->BreakPointCount*sizeof(DBGKD_RESTORE_BREAKPOINT));
|
||
|
||
//
|
||
// assume success
|
||
//
|
||
|
||
m->ReturnStatus = STATUS_SUCCESS;
|
||
|
||
//
|
||
// loop thru the breakpoint handles passed in from the debugger and
|
||
// clear any breakpoint that has a non-zero handle
|
||
//
|
||
|
||
b = BpBuf;
|
||
for (i=0; i<a->BreakPointCount; i++,b++) {
|
||
if (!BdDeleteBreakpoint(b->BreakPointHandle)) {
|
||
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
//
|
||
// send back our response
|
||
//
|
||
|
||
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
||
&MessageHeader,
|
||
AdditionalData);
|
||
|
||
return;
|
||
}
|