📄 kdapi.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
kdapi.c
Abstract:
Implementation of Kernel Debugger portable remote APIs.
--*/
#include "kdp.h"
DWORD NkCEProcessorType; // Temp change [GH]: was CEProcessorType
union
{
DBGKD_COMMAND Kd;
OSAXS_COMMAND OsAxs;
} g_dbgCmdPacket;
#define g_dbgkdCmdPacket g_dbgCmdPacket.Kd
#define g_dbgOsAxsCmdPacket g_dbgCmdPacket.OsAxs
DWORD g_dwOsAxsProtocolVersion = OSAXS_PROTOCOL_LATEST_VERSION;
BOOL KDIoControl (DWORD dwIoControlCode, LPVOID lpBuf, DWORD nBufSize)
{
BOOL fRet = FALSE;
if (g_kdKernData.pKDIoControl)
{
#if defined(x86)
fRet = KCall (g_kdKernData.pKDIoControl, dwIoControlCode, lpBuf, nBufSize);
KDEnableInt (FALSE, NULL); // Re-Disable interupts (KCall restored them)
#else
fRet = g_kdKernData.pKDIoControl (dwIoControlCode, lpBuf, nBufSize);
#endif
}
return fRet;
}
static void KdpCallOsAccess (OSAXS_COMMAND *, PSTRING);
void KdpResetBps (void)
{
if (g_kdKernData.pKDIoControl)
{
KDIoControl (KD_IOCTL_INIT, NULL, 0);
}
KdpDeleteAllBreakpoints();
}
void
KdpSendKdApiCmdPacket (
IN STRING *MessageHeader,
IN OPTIONAL STRING *MessageData
)
{
KdpSendPacket
(
PACKET_TYPE_KD_CMD,
GUID_KDDBGCLIENT_KDSTUB,
MessageHeader,
MessageData
);
}
/*++
Routine Description:
This function sends a packet, and then handles debugger commands until
a "continue" (resume execution) command.
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.
Return Value:
A value of TRUE is returned if the continue message indicates
success, Otherwise, a value of FALSE is returned.
--*/
BOOLEAN KdpSendNotifAndDoCmdLoop (
IN PSTRING OutMessageHeader,
IN PSTRING OutMessageData OPTIONAL
)
{
ULONG Length;
STRING MessageData;
STRING MessageHeader;
USHORT ReturnCode;
PUCHAR pucDummy;
BOOLEAN fHandled = FALSE;
BOOLEAN fExit = FALSE;
if (!g_fKdbgRegistered)
{ // We never registered KDBG service
// JIT Debugging
EnableHDNotifs (TRUE);
g_fKdbgRegistered = g_kdKernData.pKITLIoCtl(IOCTL_EDBG_REGISTER_DFLT_CLIENT, &pucDummy, KITL_SVC_KDBG, &pucDummy, 0, NULL);
}
if (!g_fKdbgRegistered) return FALSE;
// Loop servicing command message until a continue message is received.
MessageHeader.MaximumLength = sizeof (g_dbgCmdPacket);
MessageHeader.Buffer = (PCHAR) &g_dbgCmdPacket;
MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
MessageData.Buffer = (PCHAR) g_abMessageBuffer;
ResendPacket:
// Send event notification packet to debugger on host. Come back
// here any time we see a breakin sequence.
KdpSendPacket (PACKET_TYPE_KD_NOTIF, GUID_KDDBGCLIENT_KDSTUB, OutMessageHeader, OutMessageData);
while (!fExit)
{
GUID guidClient;
// Make sure these two MaximumLength members never change while in break state
KD_ASSERT (sizeof (g_dbgCmdPacket) == MessageHeader.MaximumLength);
KD_ASSERT (KDP_MESSAGE_BUFFER_SIZE == MessageData.MaximumLength);
ReturnCode = KdpReceiveCmdPacket(
&MessageHeader,
&MessageData,
&Length,
&guidClient
);
if (ReturnCode == (USHORT) KDP_PACKET_RESEND)
{ // This means the host disconnected and reconnected
DEBUGGERMSG(KDZONE_TRAP, (L"++KdpSendNotifAndDoCmdLoop: RESENDING NOTIFICATION\r\n"));
KdpResetBps ();
goto ResendPacket;
}
if (!memcmp (&guidClient, &GUID_KDDBGCLIENT_KDSTUB, sizeof (GUID)))
{
// Insert here flags of supported feature based on host version
if (g_dbgkdCmdPacket.dwSubVersionId >= KDAPI_PROTOCOL_VERSION)
{
// Switch on the return message API number.
DEBUGGERMSG(KDZONE_API, (L"Got Api %8.8lx\r\n", g_dbgkdCmdPacket.dwApiNumber));
switch (g_dbgkdCmdPacket.dwApiNumber)
{
case DbgKdReadVirtualMemoryApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdReadVirtualMemoryApi\r\n"));
KdpReadVirtualMemory (&g_dbgkdCmdPacket, &MessageData);
break;
case DbgKdWriteVirtualMemoryApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWriteVirtualMemoryApi\r\n"));
KdpWriteVirtualMemory (&g_dbgkdCmdPacket, &MessageData);
break;
case DbgKdReadPhysicalMemoryApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdReadPhysicalMemoryApi\r\n"));
KdpReadPhysicalMemory (&g_dbgkdCmdPacket, &MessageData);
break;
case DbgKdWritePhysicalMemoryApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWritePhysicalMemoryApi\r\n"));
KdpWritePhysicalMemory (&g_dbgkdCmdPacket, &MessageData);
break;
case DbgKdSetContextApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdSetContextApi\r\n"));
KdpSetContext(&g_dbgkdCmdPacket,&MessageData);
break;
case DbgKdReadControlSpaceApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdReadControlSpaceApi\r\n"));
KdpReadControlSpace (&g_dbgkdCmdPacket, &MessageData);
break;
case DbgKdWriteControlSpaceApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWriteControlSpaceApi\r\n"));
KdpWriteControlSpace (&g_dbgkdCmdPacket, &MessageData);
break;
case DbgKdReadIoSpaceApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdReadIoSpaceApi\r\n"));
KdpReadIoSpace (&g_dbgkdCmdPacket, &MessageData, TRUE);
break;
case DbgKdWriteIoSpaceApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdWriteIoSpaceApi\r\n"));
KdpWriteIoSpace (&g_dbgkdCmdPacket, &MessageData, TRUE);
break;
case DbgKdContinueApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdContinueApi\r\n"));
DEBUGGERMSG(KDZONE_API, (L"Continuing target system %i\r\n", g_dbgkdCmdPacket.u.Continue.dwContinueStatus));
fHandled = (BOOLEAN) (g_dbgkdCmdPacket.u.Continue.dwContinueStatus == DBG_CONTINUE);
fExit = TRUE;
break;
case DbgKdTerminateApi:
DEBUGGERMSG( KDZONE_API, (L"DbgKdTerminateApi\r\n"));
KdpResetBps ();
if (g_fKdbgRegistered)
{
EnableHDNotifs (FALSE);
g_kdKernData.pKITLIoCtl (IOCTL_EDBG_DEREGISTER_CLIENT, NULL, KITL_SVC_KDBG, NULL, 0, NULL);
g_fKdbgRegistered = FALSE;
}
// Disconnect from hdstub
Hdstub.pfnUnregisterClient (&g_KdstubClient);
// Kernel specific clean ups...
KdCleanup();
g_fDbgConnected = FALSE; // tell KdpTrap to shutdown
fHandled = TRUE;
fExit = TRUE;
break;
case DbgKdManipulateBreakpoint:
DEBUGGERMSG( KDZONE_API, (L"DbgKdManipulateBreakpoint\r\n"));
KdpManipulateBreakPoint (&g_dbgkdCmdPacket, &MessageData);
break;
default: // Invalid message.
DEBUGGERMSG( KDZONE_ALERT, (L" KdpSendNotifAndDoCmdLoop: Unknown API??\r\n"));
MessageData.Length = 0;
g_dbgkdCmdPacket.dwReturnStatus = STATUS_UNSUCCESSFUL;
KdpSendKdApiCmdPacket (&MessageHeader, &MessageData);
break;
}
}
else
{
DEBUGGERMSG( KDZONE_ALERT, (L" KdpSendNotifAndDoCmdLoop: protocol Version not supported\r\n"));
MessageData.Length = 0;
g_dbgkdCmdPacket.dwReturnStatus = STATUS_UNSUCCESSFUL;
KdpSendKdApiCmdPacket (&MessageHeader, &MessageData);
}
}
else if (!memcmp (&guidClient, &GUID_KDDBGCLIENT_OSAXS, sizeof (GUID)))
{
DEBUGGERMSG (KDZONE_API, (L"Calling OsAccess\r\n"));
KdpCallOsAccess (&g_dbgOsAxsCmdPacket, &MessageData);
}
}
return fHandled;
}
static void KdpCallOsAccess (OSAXS_COMMAND *pOsAxsCmd, PSTRING AdditionalData)
{
HRESULT hr;
STRING ResponseHeader;
DEBUGGERMSG (KDZONE_API, (L"++KdpCallOsAccess\r\n"));
ResponseHeader.Length = sizeof (*pOsAxsCmd);
ResponseHeader.Buffer = (BYTE *) pOsAxsCmd;
HandleRequest:
if (pOsAxsCmd->dwVersion == g_dwOsAxsProtocolVersion)
{
switch (pOsAxsCmd->dwApi)
{
case OSAXS_API_GET_FLEXIPTMINFO:
{
// Use tempory DWORD for IOCTL call, since AdditionalData->Length is a USHORT.
DWORD dwSize = AdditionalData->MaximumLength;
DEBUGGERMSG(KDZONE_API, (L" KdpCallOsAccess -> GetFPTMI\r\n"));
// OsAccess requires an output buffer. Need to report the
// size of the buffer to the API call so it won't overflow
hr = Hdstub.pfnCallClientIoctl (OSAXST0_NAME, OSAXST0_IOCTL_GET_FLEXIPTMINFO, (DWORD) &pOsAxsCmd->u.FlexiReq,
(DWORD) &dwSize, (DWORD) AdditionalData->Buffer, 0);
if (SUCCEEDED (hr))
{
AdditionalData->Length = (USHORT) dwSize;
}
else
{
DEBUGGERMSG(KDZONE_ALERT, (TEXT(" KdpCallOsAccess: Failed to get FlexiPTMI info from OsAxsT0, hr = 0x%08X\r\n"),hr));
}
}
break;
case OSAXS_API_GET_STRUCT:
{
// Use tempory DWORD for IOCTL call, since AdditionalData->Length is a USHORT.
DWORD dwSize = AdditionalData->MaximumLength;
DEBUGGERMSG(KDZONE_API, (L" KdpCallOsAccess -> GetStruct @0x%08x\r\n", pOsAxsCmd->u.Struct.StructAddr));
hr = Hdstub.pfnCallClientIoctl (OSAXST1_NAME, OSAXST1_IOCTL_GET_OSSTRUCT, (DWORD) &pOsAxsCmd->u.Struct,
(DWORD) AdditionalData->Buffer, (DWORD) &dwSize, 0);
if (SUCCEEDED (hr))
{
AdditionalData->Length = (USHORT) dwSize;
}
else
{
DEBUGGERMSG(KDZONE_ALERT, (TEXT(" KdpCallOsAccess: Failed to get OsStruct info from OsAxsT1, hr = 0x%08X\r\n"),hr));
}
}
break;
case OSAXS_API_GET_THREADCTX:
{
// Use tempory DWORD for IOCTL call, since AdditionalData->Length is a USHORT.
DWORD dwSize = AdditionalData->MaximumLength;
hr = Hdstub.pfnCallClientIoctl (OSAXST1_NAME, OSAXST1_IOCTL_GET_THREADCTX, (DWORD) pOsAxsCmd->u.Addr,
(DWORD) &AdditionalData->Buffer, (DWORD) &dwSize, 0);
if (SUCCEEDED (hr))
{
AdditionalData->Length = (USHORT) dwSize;
}
else
{
DEBUGGERMSG(KDZONE_ALERT, (TEXT(" KdpCallOsAccess: Failed to get ThreadCtx info from OsAxsT1, hr = 0x%08X\r\n"),hr));
}
}
break;
case OSAXS_API_SET_THREADCTX:
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -