📄 kdapi.c
字号:
BOOLEAN
KdpReportLoadSymbolsStateChange (
IN PSTRING PathName,
IN PKD_SYMBOLS_INFO SymbolInfo,
IN BOOLEAN UnloadSymbols,
IN OUT CONTEXT * ContextRecord
)
/*++
Routine Description:
This routine sends a load symbols state change packet to the kernel
debugger and waits for a manipulate state message.
Arguments:
PathName - Supplies a pointer to the pathname of the image whose
symbols are to be loaded.
BaseOfDll - Supplies the base address where the image was loaded.
ProcessId - Unique 32-bit identifier for process that is using
the symbols. -1 for system process.
CheckSum - Unique 32-bit identifier from image header.
UnloadSymbol - TRUE if the symbols that were previously loaded for
the named image are to be unloaded from the debugger.
Return Value:
A value of TRUE is returned if the exception is handled. Otherwise, a
value of FALSE is returned.
--*/
{
PSTRING AdditionalData;
STRING MessageData;
STRING MessageHeader;
DBGKD_WAIT_STATE_CHANGE WaitStateChange;
KCONTINUE_STATUS Status;
if ((KdpUseTCPSockets || KdpUseUDPSockets) && socketReady[0] == '1')
{
if (packetsIndex)
SendSavedPackets();
}
do {
//
// Construct the wait state change message and message descriptor.
//
WaitStateChange.NewState = DbgKdLoadSymbolsStateChange;
WaitStateChange.ProcessorType = 0;
WaitStateChange.Processor = (USHORT)0;
WaitStateChange.NumberProcessors = (ULONG)1;
WaitStateChange.Thread = pCurThread;
WaitStateChange.ProgramCounter = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
KdpSetLoadState(&WaitStateChange, ContextRecord);
WaitStateChange.u.LoadSymbols.UnloadSymbols = UnloadSymbols;
WaitStateChange.u.LoadSymbols.BaseOfDll = SymbolInfo->BaseOfDll;
WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
if (ARGUMENT_PRESENT( PathName )) {
WaitStateChange.u.LoadSymbols.PathNameLength =
KdpMoveMemory(
(PCHAR)KdpMessageBuffer,
(PCHAR)PathName->Buffer,
PathName->Length
) + 1;
MessageData.Buffer = KdpMessageBuffer;
MessageData.Length = (USHORT)WaitStateChange.u.LoadSymbols.PathNameLength;
MessageData.Buffer[MessageData.Length-1] = '\0';
AdditionalData = &MessageData;
} else {
WaitStateChange.u.LoadSymbols.PathNameLength = 0;
AdditionalData = NULL;
}
MessageHeader.Length = sizeof(DBGKD_WAIT_STATE_CHANGE);
MessageHeader.Buffer = (PCHAR)&WaitStateChange;
//
// Send packet to the kernel debugger on the host machine, wait
// for the reply.
//
DEBUGGERMSG(KDZONE_API, (L"Updating symbols for %a %8.8lx %8.8lx\r\n",
PathName->Buffer,
WaitStateChange.u.LoadSymbols.BaseOfDll,
WaitStateChange.u.LoadSymbols.SizeOfImage));
if (!KdpUseTCPSockets && !KdpUseUDPSockets) {
Status = KdpSendWaitContinue(
PACKET_TYPE_KD_STATE_CHANGE,
&MessageHeader,
AdditionalData,
ContextRecord
);
}
else {
if (socketReady[0] == '1') {
// The socket transport is ready. Send packet.
Status = KdpSendWaitContinue(
PACKET_TYPE_KD_STATE_CHANGE,
&MessageHeader,
AdditionalData,
ContextRecord
);
}
else {
// The socket transport is not ready. Save packet.
memcpy(&SavedPackets[packetsIndex%MAX_LOAD_NOTIFICATIONS].StateChange,
&WaitStateChange,
sizeof(DBGKD_WAIT_STATE_CHANGE));
if (AdditionalData) {
SavedPackets[packetsIndex%MAX_LOAD_NOTIFICATIONS].AdditionalDataLength = MessageData.Length;
strncpy(SavedPackets[packetsIndex%MAX_LOAD_NOTIFICATIONS].AdditionalData,
MessageData.Buffer,
MessageData.Length);
}
else
SavedPackets[packetsIndex%MAX_LOAD_NOTIFICATIONS].AdditionalDataLength = 0;
packetsIndex++;
return (BOOLEAN) ContinueSuccess;
}
}
} while (Status == ContinueProcessorReselected);
return (BOOLEAN) Status;
}
VOID
KdpReadPhysicalMemory(
IN PDBGKD_MANIPULATE_STATE m,
IN PSTRING AdditionalData,
IN CONTEXT * 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_MEMORY a = &m->u.ReadMemory;
ULONG Length;
STRING MessageHeader;
PVOID VirtualAddress;
PHYSICAL_ADDRESS Source;
PUCHAR Destination;
USHORT NumberBytes;
USHORT BytesLeft;
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;
}
//
// Since the MmDbgTranslatePhysicalAddress 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 = (ULONG)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 = (PVOID)MmDbgTranslatePhysicalAddress(Source);
AdditionalData->Length = (USHORT)KdpMoveMemory(
Destination,
VirtualAddress,
BytesLeft
);
BytesLeft -= AdditionalData->Length;
} else {
//
// Memory move spans page boundaries
//
VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Source);
NumberBytes = (USHORT)(PAGE_SIZE - BYTE_OFFSET(VirtualAddress));
AdditionalData->Length = (USHORT)KdpMoveMemory(
Destination,
VirtualAddress,
NumberBytes
);
Source += NumberBytes;
Destination += NumberBytes;
BytesLeft -= NumberBytes;
while(BytesLeft > 0) {
//
// Transfer a full page or the last bit,
// whichever is smaller.
//
VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Source);
NumberBytes = (USHORT) ((PAGE_SIZE < BytesLeft) ? PAGE_SIZE : BytesLeft);
AdditionalData->Length += (USHORT)KdpMoveMemory(
Destination,
VirtualAddress,
NumberBytes
);
Source += NumberBytes;
Destination += NumberBytes;
BytesLeft -= NumberBytes;
}
}
if (Length == AdditionalData->Length) {
m->ReturnStatus = STATUS_SUCCESS;
} else {
m->ReturnStatus = STATUS_UNSUCCESSFUL;
}
a->ActualBytesRead = AdditionalData->Length;
KdpSendPacket(
PACKET_TYPE_KD_STATE_MANIPULATE,
&MessageHeader,
AdditionalData
);
UNREFERENCED_PARAMETER(Context);
}
VOID
KdpWritePhysicalMemory(
IN PDBGKD_MANIPULATE_STATE m,
IN PSTRING AdditionalData,
IN CONTEXT * 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_MEMORY 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 MmDbgTranslatePhysicalAddress 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 = (ULONG)a->TargetBaseAddress;
Source = AdditionalData->Buffer;
BytesLeft = (USHORT) a->TransferCount;
if(PAGE_ALIGN((PUCHAR)Destination) ==
PAGE_ALIGN((PUCHAR)(Destination)+BytesLeft)) {
//
// Memory move starts and ends on the same page.
//
VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Destination);
Length = (USHORT)KdpMoveMemory(
VirtualAddress,
Source,
BytesLeft
);
BytesLeft -= (USHORT) Length;
} else {
//
// Memory move spans page boundaries
//
VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Destination);
NumberBytes = (USHORT) (PAGE_SIZE - BYTE_OFFSET(VirtualAddress));
Length = (USHORT)KdpMoveMemory(
VirtualAddress,
Source,
NumberBytes
);
Source += NumberBytes;
Destination += NumberBytes;
BytesLeft -= NumberBytes;
while(BytesLeft > 0) {
//
// Transfer a full page or the last bit,
// whichever is smaller.
//
VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Destination);
NumberBytes = (USHORT) ((PAGE_SIZE < BytesLeft) ? PAGE_SIZE : BytesLeft);
Length += (USHORT)KdpMoveMemory(
VirtualAddress,
Source,
NumberBytes
);
Source += NumberBytes;
Destination += NumberBytes;
BytesLeft -= NumberBytes;
}
}
if (Length == AdditionalData->Length) {
m->ReturnStatus = STATUS_SUCCESS;
} else {
m->ReturnStatus = STATUS_UNSUCCESSFUL;
}
a->ActualBytesWritten = Length;
KdpSendPacket(
PACKET_TYPE_KD_STATE_MANIPULATE,
&MessageHeader,
NULL
);
UNREFERENCED_PARAMETER(Context);
}
const ULONG NtBuildNumber = VER_PRODUCTBUILD | 0xC0000000;
typedef enum _TargetCodeType
{
tcCeUnknown,
tcCeSH3,
tcCeSH4,
tcCeMIPS,
tcCeX86,
tcCeARM,
tcCePPC
} TargetCodeType;
#if defined(SH3)
#define CURRENT_TARGET_CODE (tcCeSH3)
#elif defined(SH4)
#define CURRENT_TARGET_CODE (tcCeSH4)
#elif defined(x86)
#define CURRENT_TARGET_CODE (tcCeX86)
#elif defined(PPC)
#define CURRENT_TARGET_CODE (tcCePPC)
#elif defined(MIPS)
#define CURRENT_TARGET_CODE (tcCeMIPS)
#elif defined(ARM)
#define CURRENT_TARGET_CODE (tcCeARM)
#else
#define CURRENT_TARGET_CODE (tcCeUnknown)
// warning if new cpu architecture is defined: please add new type in TargetCodeType (and in host kernel debugger side too)
#endif
VOID
KdpGetVersion(
IN PDBGKD_MANIPULATE_STATE 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -