📄 kdapi.c
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation. All rights reserved.
Module Name:
kdapi.c
Abstract:
Implementation of Kernel Debugger portable remote APIs.
--*/
#include "kdp.h"
extern BOOL fDbgConnected;
//
// included to find the relocated kernel data section
//
extern ROMHDR * const volatile pTOC;
// This routine is called when it receives DbgKdTerminateApi
extern BOOLEAN (*KdpCleanup)(void);
//end
extern VOID KdTerminateTransport(VOID);
extern VOID KdInterruptsOff(VOID);
extern VOID KdInterruptsOn(VOID);
DWORD NkCEProcessorType; // Temp change [GH]: was CEProcessorType
#if defined(x86)
extern PTHREAD g_CurFPUOwner;
#endif
//
// Define external data.
//
extern PVOID KdpImageBase;
CHAR *socketReady;
DWORD packetsIndex;
BOOLEAN KdpSendContext = TRUE;
BOOL fDbgConnected;
BOOL fAtBreakState;
DBGKD_MANIPULATE_STATE ManipulateState;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGEKD, KdpSendWaitContinue)
#pragma alloc_text(PAGEKD, KdpReadVirtualMemory)
#pragma alloc_text(PAGEKD, KdpWriteVirtualMemory)
#pragma alloc_text(PAGEKD, KdpGetContext)
#pragma alloc_text(PAGEKD, KdpSetContext)
#pragma alloc_text(PAGEKD, KdpWriteBreakpoint)
#pragma alloc_text(PAGEKD, KdpRestoreBreakpoint)
#pragma alloc_text(PAGEKD, KdpReportExceptionStateChange)
#pragma alloc_text(PAGEKD, KdpReportLoadSymbolsStateChange)
#pragma alloc_text(PAGEKD, KdpReadPhysicalMemory)
#pragma alloc_text(PAGEKD, KdpWritePhysicalMemory)
#pragma alloc_text(PAGEKD, KdpGetVersion)
#pragma alloc_text(PAGEKD, KdpWriteBreakPointEx)
#pragma alloc_text(PAGEKD, KdpRestoreBreakPointEx)
#endif // ALLOC_PRAGMA
typedef struct {
DBGKD_WAIT_STATE_CHANGE StateChange;
USHORT AdditionalDataLength;
CHAR AdditionalData[80];
} STATE_PACKET;
#define MAX_LOAD_NOTIFICATIONS 45 // wraps around after 45
STATE_PACKET SavedPackets[MAX_LOAD_NOTIFICATIONS];
VOID
SendSavedPackets(VOID)
{
PSTRING AdditionalData = NULL;
STRING MessageHeader;
STRING MessageData;
KCONTINUE_STATUS Status;
CONTEXT ContextRecord;
DWORD i;
for (i = 0; i < (packetsIndex%MAX_LOAD_NOTIFICATIONS); i++) {
do {
MessageHeader.Length = sizeof(DBGKD_WAIT_STATE_CHANGE);
MessageHeader.Buffer = (PCHAR)&SavedPackets[i].StateChange;
if (SavedPackets[i].AdditionalDataLength) {
MessageData.Length = SavedPackets[i].AdditionalDataLength;
MessageData.Buffer = SavedPackets[i].AdditionalData;
AdditionalData = &MessageData;
}
Status = KdpSendWaitContinue(
PACKET_TYPE_KD_STATE_CHANGE,
&MessageHeader,
AdditionalData,
&ContextRecord
);
} while (Status == ContinueProcessorReselected);
}
packetsIndex = 0;
}
KCONTINUE_STATUS
KdpSendWaitContinue (
IN ULONG OutPacketType,
IN PSTRING OutMessageHeader,
IN PSTRING OutMessageData OPTIONAL,
IN OUT CONTEXT * ContextRecord
)
/*++
Routine Description:
This function sends a packet, and then waits for a continue message.
BreakIns received while waiting will always cause a resend of the
packet originally sent out. While waiting, manipulate messages
will be serviced.
A resend always resends the original event sent to the debugger,
not the last response to some debugger command.
Arguments:
OutPacketType - Supplies the type of packet to send.
OutMessageHeader - Supplies a pointer to a string descriptor that describes
the message information.
OutMessageData - Supplies a pointer to a string descriptor that describes
the optional message data.
ContextRecord - Exception context
Return Value:
A value of TRUE is returned if the continue message indicates
success, Otherwise, a value of FALSE is returned.
--*/
{
ULONG Length;
STRING MessageData;
STRING MessageHeader;
USHORT ReturnCode;
NTSTATUS Status;
//
// Loop servicing state manipulation message until a continue message
// is received.
//
MessageHeader.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE);
MessageHeader.Buffer = (PCHAR)&ManipulateState;
MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
MessageData.Buffer = (PCHAR)KdpMessageBuffer;
KdInterruptsOff();
ResendPacket:
//
// Send event notification packet to debugger on host. Come back
// here any time we see a breakin sequence.
//
//DEBUGGERMSG(KDZONE_API, (L"SendPacket\n"));
KdpSendPacket(
OutPacketType,
OutMessageHeader,
OutMessageData
);
//
// After sending packet, if there is no response from debugger
// AND the packet is for reporting symbol (un)load, the debugger
// will be decalred to be not present. Note If the packet is for
// reporting exception, the KdpSendPacket will never stop.
//
if (KdDebuggerNotPresent) {
DEBUGGERMSG(KDZONE_API, (L"Debugger dead\r\n"));
fDbgConnected=FALSE;
KdInterruptsOn();
return ContinueSuccess;
}
fAtBreakState = TRUE;
while (TRUE) {
//
// Wait for State Manipulate Packet without timeout.
//
do {
ReturnCode = KdpReceivePacket(
PACKET_TYPE_KD_STATE_MANIPULATE,
&MessageHeader,
&MessageData,
&Length
);
if (ReturnCode == (USHORT)KDP_PACKET_RESEND) {
goto ResendPacket;
}
} while (ReturnCode == KDP_PACKET_TIMEOUT);
//
// Switch on the return message API number.
//
DEBUGGERMSG(KDZONE_API, (L"Got Api %8.8lx\r\n", ManipulateState.ApiNumber));
switch (ManipulateState.ApiNumber) {
case DbgKdReadVirtualMemoryApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdReadVirtualMemoryApi\r\n"));
KdpReadVirtualMemory(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdWriteVirtualMemoryApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWriteVirtualMemoryApi\r\n"));
KdpWriteVirtualMemory(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdReadPhysicalMemoryApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdReadPhysicalMemoryApi\r\n"));
KdpReadPhysicalMemory(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdWritePhysicalMemoryApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWritePhysicalMemoryApi\r\n"));
KdpWritePhysicalMemory(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdGetContextApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdGetContextApi\r\n"));
KdpGetContext(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdSetContextApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdSetContextApi\r\n"));
KdpSetContext(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdWriteBreakPointApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWriteBreakPointApi\r\n"));
KdpWriteBreakpoint(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdRestoreBreakPointApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdRestoreBreakPointApi\r\n"));
KdpRestoreBreakpoint(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdReadControlSpaceApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdReadControlSpaceApi\r\n"));
KdpReadControlSpace(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdWriteControlSpaceApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWriteControlSpaceApi\r\n"));
KdpWriteControlSpace(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdReadIoSpaceApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdReadIoSpaceApi\r\n"));
KdpReadIoSpace(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdWriteIoSpaceApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWriteIoSpaceApi\r\n"));
KdpWriteIoSpace(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdContinueApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdContinueApi\r\n"));
fAtBreakState = FALSE;
DEBUGGERMSG(KDZONE_API, (L"Continuing target system %8.8lx\r\n", ManipulateState.u.Continue.ContinueStatus));
if (NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus) != FALSE) {
KdInterruptsOn();
return ContinueSuccess;
} else {
KdInterruptsOn();
return ContinueError;
}
break;
case DbgKdTerminateApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdTerminateApi\r\n"));
KdpCleanup();
fDbgConnected=FALSE;
fAtBreakState = FALSE;
KdTerminateTransport();
KdInterruptsOn();
return ContinueSuccess;
case DbgKdContinueApi2:
DEBUGGERMSG( KDZONE_API, (L"DbgKdContinueApi2\r\n"));
fAtBreakState = FALSE;
if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus) != FALSE) {
KdpGetStateChange(&ManipulateState,ContextRecord);
KdInterruptsOn();
return ContinueSuccess;
} else {
KdInterruptsOn();
return ContinueError;
}
break;
case DbgKdRebootApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdRebootApi\r\n"));
if (pKDIoControl) {
pKDIoControl( KD_IOCTL_RESET, NULL, 0);
}
break;
case DbgKdGetVersionApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdGetVersionApi\r\n"));
KdpGetVersion(&ManipulateState);
break;
case DbgKdCauseBugCheckApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdCauseBugCheckApi\r\n"));
MessageData.Length = 0;
ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, &MessageData);
break;
case DbgKdWriteBreakPointExApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWriteBreakPointExApi\r\n"));
Status = KdpWriteBreakPointEx(&ManipulateState,
&MessageData,
ContextRecord);
if (Status) {
ManipulateState.ApiNumber = DbgKdContinueApi;
ManipulateState.u.Continue.ContinueStatus = Status;
KdInterruptsOn();
return ContinueError;
}
break;
case DbgKdRestoreBreakPointExApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdRestoreBreakPointExApi\r\n"));
KdpRestoreBreakPointEx(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdManipulateBreakpoint:
DEBUGGERMSG( KDZONE_API, (L"DbgKdManipulateBreakpoint\r\n"));
Status = KdpManipulateBreakPoint(&ManipulateState,
&MessageData,
ContextRecord);
if (Status) {
ManipulateState.ApiNumber = DbgKdContinueApi;
ManipulateState.u.Continue.ContinueStatus = Status;
KdInterruptsOn();
return ContinueError;
}
break;
//
// Invalid message.
//
default:
DEBUGGERMSG( KDZONE_API, (L"Unknown API ??\r\n"));
MessageData.Length = 0;
ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
KdpSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, &MessageData);
break;
}
}
KdInterruptsOn();
}
VOID
KdpReadVirtualMemory(
IN PDBGKD_MANIPULATE_STATE m,
IN PSTRING AdditionalData,
IN CONTEXT * Context
)
/*++
Routine Description:
This function is called in response of a read virtual memory
state manipulation message. Its function is to read virtual 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_MEMORY a = &m->u.ReadMemory;
ULONG Length;
STRING MessageHeader;
MessageHeader.Length = sizeof(*m);
MessageHeader.Buffer = (PCHAR)m;
//
// make sure that nothing but a read memory message was transmitted
//
KD_ASSERT(AdditionalData->Length == 0);
//
// Trim transfer count to fit in a single message
//
if (a->TransferCount > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE))) {
Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE);
} else {
Length = a->TransferCount;
}
AdditionalData->Length = (USHORT)KdpMoveMemory(
AdditionalData->Buffer,
a->TargetBaseAddress,
Length
);
if (Length == AdditionalData->Length) {
m->ReturnStatus = STATUS_SUCCESS;
} else {
m->ReturnStatus = STATUS_UNSUCCESSFUL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -