📄 kdbreak.c
字号:
// Examine each entry in the table in turn
for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++)
{
if (g_aBreakpointTable [Index].wRefCount &&
(g_aBreakpointTable [Index].Flags & KD_BREAKPOINT_SUSPENDED))
{
int bph = KdpInstantiateSwBreakpoint (Index + 1); // Attempt instantiations
if (bph <= KD_BPHND_INVALID_GEN_ERR)
{
DEBUGGERMSG (KDZONE_SWBP, (L" KdpReinstateSuspendedBreakpoints: Reinstate failed for BP %i (Addr=0x%08X)!\r\n",
Index, g_aBreakpointTable [Index].Address));
}
}
}
}
/*++
Routine Description:
Suspend the breakpoint, if one exists, at the specified location. It is assumed this routine
will be called if the debugger "trips" over one of its own breakpoints which was set in code
intended to be shared by KdStub. This should allow stepping through such code.
Note: currently, this function will not suspend more than one (1) breakpoint, under the
assumption that KdpAddBreakpoint will not instantiate multiple breakpoints at the same location.
Arguments:
Address - the address of the instruction that was just hit
Return Value:
TRUE - there was a breakpoint at that location and it was suspended
FALSE - otherwise
--*/
BOOLEAN KdpSuspendBreakpointIfHitByKd (void * pvAddress)
{ // TODO: Replace this with a call to KdpSuspendAllBreakpoints(). There is no reason to suspend only one.
BOOLEAN fRet = FALSE;
ULONG Index;
BYTE* pbKAddr;
DEBUGGERMSG (KDZONE_SWBP, (L"++KdpSuspendBreakpointIfHitByKd (0x%08X)\r\n", (DWORD) pvAddress));
if (Is16BitSupported)
{
pvAddress = (void *) (((DWORD) pvAddress) & ~1);
}
pbKAddr = (BYTE *) MapToDebuggeeCtxKernEquivIfAcc ((BYTE *) pvAddress, FALSE); // Kernel equivalent
for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++)
{
BYTE *pbBpKAddr = MapToDebuggeeCtxKernEquivIfAcc ((BYTE *) (g_aBreakpointTable [Index].Address), TRUE);
if (g_aBreakpointTable [Index].wRefCount &&
!(g_aBreakpointTable [Index].Flags & KD_BREAKPOINT_SUSPENDED) &&
(pbBpKAddr == pbKAddr))
{
fRet = KdpSuspendBreakpoint (Index);
}
}
DEBUGGERMSG (KDZONE_SWBP, (L"--KdpSuspendBreakpointIfHitByKd (%d)\r\n", (int) fRet));
return fRet;
}
/*++
Routine Description:
Sanitize a region of memory. If the specified region of memory contains a breakpoint, write the data
into the output buffer as it would appear if there were no breakpoints.
The memory address (pvAddress) is "slotized" relative to the current process' address space before being
compared with addresses of breakpoints.
Arguments:
pbClean: Output buffer to which sanitized memory is written
pvAddress: First virtual address of the region of memory to be cleaned. This must be the actual
address of the memory (so it can be matched against the breakpoint table) and it must
be readable.
nSize: Size of both the output buffer and the memory to be cleaned
fAlwaysCopy: Copy the memory into the output buffer regardless of whether the memory contains a
breakpoint. Normally, the memory is only copied if a breakpoint was present.
Return Value:
TRUE - there was a breakpoint in the specified range and it has been sanitized in the output buffer
FALSE - otherwise
--*/
BOOL KdpSanitize (BYTE* pbClean, VOID* pvAddress, ULONG nSize, BOOL fAlwaysCopy)
{
BOOL fRet = FALSE;
ULONG iBp;
BYTE* pbKAddr = (BYTE*) MapToDebuggeeCtxKernEquivIfAcc ((BYTE *) pvAddress, TRUE); // Kernel equivalent
if (pbKAddr)
{
if (fAlwaysCopy)
{ // initialize the buffer
KdpMoveMemory (pbClean, pbKAddr, nSize);
}
for (iBp = 0; iBp < BREAKPOINT_TABLE_SIZE; iBp++)
{
if (g_aBreakpointTable[iBp].wRefCount &&
!(g_aBreakpointTable[iBp].Flags & KD_BREAKPOINT_SUSPENDED))
{
BYTE *pbBpKAddr = MapToDebuggeeCtxKernEquivIfAcc ((BYTE *) (g_aBreakpointTable [iBp].Address), TRUE);
if (pbBpKAddr)
{
ULONG nBpSize = sizeof (KDP_BREAKPOINT_TYPE);
#if defined(MIPSII) || defined(THUMBSUPPORT)
if (Is16BitSupported && (g_aBreakpointTable[iBp].Flags & KD_BREAKPOINT_16BIT))
{
nBpSize = sizeof (KDP_BREAKPOINT_16BIT_TYPE);
}
#endif
if ((pbKAddr < (pbBpKAddr + nBpSize)) &&
((pbKAddr + nSize) > pbBpKAddr))
{
ULONG nCommonBytes = nBpSize;
BYTE* pbSrc = (BYTE*) &g_aBreakpointTable [iBp].Content;
BYTE* pbDst = pbClean + (pbBpKAddr - pbKAddr);
LONG lDiff;
DEBUGGERMSG (KDZONE_SWBP, (L" KdpSanitize: cleaning BP h=%d, addr=0x%08X\r\n", iBp + 1, pbBpKAddr));
// check for memory buffer beginning in the middle of the breakpoint
lDiff = pbKAddr - pbBpKAddr;
if (lDiff > 0)
{
pbSrc += lDiff;
pbDst += lDiff;
nCommonBytes -= lDiff;
}
// check for memory buffer ending in the middle of the breakpoint
lDiff = (pbBpKAddr + nBpSize) - (pbKAddr + nSize);
if (lDiff > 0)
{
nCommonBytes -= lDiff;
}
KD_ASSERT ((nCommonBytes > 0) && (nCommonBytes <= nBpSize));
KD_ASSERT ((pbClean <= pbDst) && ((pbDst + nCommonBytes) <= (pbClean + nSize)));
DEBUGGERMSG (KDZONE_SWBP, (L" KdpSanitize: copy %d byte(s) from 0x%08X to 0x%08X\r\n", nCommonBytes, (DWORD)pbSrc, (DWORD)pbDst));
// initialize the clean buffer if it hasn't been done by now
if (!fRet && !fAlwaysCopy) memcpy (pbClean, pvAddress, nSize);
KdpMoveMemory (pbDst, pbSrc, nCommonBytes);
fRet = TRUE;
}
}
else
{
g_aBreakpointTable [iBp].Flags |= KD_BREAKPOINT_SUSPENDED; // Assume that it is suspended since page is out (faster handling next time)
}
}
}
}
return fRet;
}
VOID
KdpManipulateBreakPoint(
IN DBGKD_COMMAND *pdbgkdCmdPacket,
IN PSTRING AdditionalData
)
/*++
Routine Description:
This function is called in response of a manipulate breakpoint
message. Its function is to query/write/set a breakpoint
and return a handle to the breakpoint.
Arguments:
pdbgkdCmdPacket - Supplies the command message.
AdditionalData - Supplies any additional data for the message.
Return Value:
None.
--*/
{
// TODO: Add support for physical address breakpoints
DBGKD_MANIPULATE_BREAKPOINT *a = &pdbgkdCmdPacket->u.ManipulateBreakPoint;
STRING MessageHeader;
BOOL fSuccess = FALSE;
DWORD dwExpAddDataSize;
DWORD i;
BOOL fHALBP=FALSE;
KD_BPINFO bpInfo;
MessageHeader.Length = sizeof (*pdbgkdCmdPacket);
MessageHeader.Buffer = (PCHAR) pdbgkdCmdPacket;
DEBUGGERMSG(KDZONE_BREAK, (L"++KdpManipulateBreakPoint\r\n"));
if (a->dwMBpFlags & DBGKD_MBP_FLAG_DATABP)
{
dwExpAddDataSize = sizeof (DBGKD_DATA_BREAKPOINT_ELEM1);
}
else
{
dwExpAddDataSize = sizeof (DBGKD_CODE_BREAKPOINT_ELEM1);
}
dwExpAddDataSize *= a->dwBpCount;
if (AdditionalData->Length != dwExpAddDataSize)
{
pdbgkdCmdPacket->dwReturnStatus = STATUS_UNSUCCESSFUL;
KdpSendKdApiCmdPacket (&MessageHeader, AdditionalData);
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Length mismatch\n"));
}
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: dwBpCount = %ld\n", a->dwBpCount));
for (i = 0; i < a->dwBpCount; i++)
{
if (a->dwMBpFlags & DBGKD_MBP_FLAG_DATABP)
{ // DATA BP
// TODO: Add support for triggering on Register change and Data
DBGKD_DATA_BREAKPOINT_ELEM1 *b = (DBGKD_DATA_BREAKPOINT_ELEM1 *) AdditionalData->Buffer;
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Address = %08X Flags=%08X dwBpHandle=%08X\n", b[i].dwAddress, b[i].wBpFlags, b[i].dwBpHandle));
if (g_kdKernData.pKDIoControl)
{ // Try to Hardware Data BP
if (a->dwMBpFlags & DBGKD_MBP_FLAG_SET)
{
bpInfo.nVersion = 1;
bpInfo.ulAddress = ZeroPtr (b[i].dwAddress);
bpInfo.ulFlags = 0;
bpInfo.ulHandle = 0;
if (KDIoControl (KD_IOCTL_SET_DBP, &bpInfo, sizeof (KD_BPINFO)))
{
fSuccess = TRUE;
fHALBP = TRUE;
b[i].dwBpHandle = bpInfo.ulHandle | 0x80000000;
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Set Hard DBP Address = %08X wBpFlags=%08X dwBpHandle=%08X\n", b[i].dwAddress, b[i].wBpFlags, b[i].dwBpHandle));
}
}
else if (b[i].dwBpHandle & 0x80000000)
{
fHALBP = TRUE;
bpInfo.nVersion = 1;
bpInfo.ulHandle = b[i].dwBpHandle & 0x7FFFFFFF;
bpInfo.ulFlags = 0;
bpInfo.ulAddress = 0;
if (KDIoControl (KD_IOCTL_CLEAR_DBP, &bpInfo, sizeof(KD_BPINFO)))
{
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Clear Hard DBP Address = %08X wBpFlags=%08X dwBpHandle=%08X\n", b[i].dwAddress, b[i].wBpFlags, b[i].dwBpHandle));
fSuccess = TRUE;
}
}
}
if (!fHALBP)
{ // SW Data BP
// TODO: Add support for DATA BP emulation
}
}
else
{ // CODE BP
DBGKD_CODE_BREAKPOINT_ELEM1 *b = (DBGKD_CODE_BREAKPOINT_ELEM1 *) AdditionalData->Buffer;
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Address = %08X Flags=%08X dwBpHandle=%08X\n", b[i].dwAddress, b[i].wBpFlags, b[i].dwBpHandle));
if ((b[i].wBpFlags == DBGKD_BP_FLAG_SOFTWARE) && g_kdKernData.pKDIoControl)
{ // Try to Hardware Code BP
if (a->dwMBpFlags & DBGKD_MBP_FLAG_SET)
{
bpInfo.nVersion = 1;
bpInfo.ulAddress = ZeroPtr (b[i].dwAddress);
bpInfo.ulFlags = 0;
if (KDIoControl (KD_IOCTL_SET_CBP, &bpInfo, sizeof (KD_BPINFO)))
{
fSuccess = TRUE;
fHALBP = TRUE;
b[i].dwBpHandle = bpInfo.ulHandle | 0x80000000;
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Set Hard CBP Address = %08X wBpFlags=%08X dwBpHandle=%08X\n", b[i].dwAddress, b[i].wBpFlags, b[i].dwBpHandle));
}
}
else if (b[i].dwBpHandle & 0x80000000)
{
fHALBP = TRUE;
bpInfo.nVersion = 1;
bpInfo.ulHandle = b[i].dwBpHandle & 0x7FFFFFFF;
bpInfo.ulFlags = 0;
if (KDIoControl (KD_IOCTL_CLEAR_CBP, &bpInfo, sizeof(KD_BPINFO)))
{
fSuccess = TRUE;
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Clear Hard CBP Address = %08X wBpFlags=%08X dwBpHandle=%08X\n", b[i].dwAddress, b[i].wBpFlags, b[i].dwBpHandle));
}
}
}
if (!fHALBP)
{ // SW Data BP
if (a->dwMBpFlags & DBGKD_MBP_FLAG_SET)
{
b[i].wBpFlags |= DBGKD_BP_FLAG_SOFTWARE;
if (Is16BitSupported && (b[i].wBpExecMode == DBGKD_EXECMODE_16BIT)) b[i].dwAddress |= 0x1;
if (b[i].dwBpHandle = KdpAddBreakpoint ((PVOID) b[i].dwAddress))
{
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Set Soft CBP Address = %08X wBpFlags=%08X dwBpHandle=%08X\n", b[i].dwAddress, b[i].wBpFlags, b[i].dwBpHandle));
fSuccess = TRUE;
}
}
else
{
if (KdpDeleteBreakpoint (b[i].dwBpHandle))
{
DEBUGGERMSG(KDZONE_BREAK, (L" KdpManipulateBreakPoint: Clear Soft CBP dwBpHandle=%08X\n", b[i].dwBpHandle));
fSuccess = TRUE;
}
}
}
}
}
if (fSuccess)
{
pdbgkdCmdPacket->dwReturnStatus = fSuccess ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
a->NbBpAvail.dwNbHwCodeBpAvail = 0; // TODO: Get this from OAL
a->NbBpAvail.dwNbSwCodeBpAvail = BREAKPOINT_TABLE_SIZE - g_nTotalNumDistinctSwCodeBps;
a->NbBpAvail.dwNbHwDataBpAvail = 0; // TODO: Get this from OAL
a->NbBpAvail.dwNbSwDataBpAvail = 0;
DEBUGGERMSG (KDZONE_BREAK, (L"--KdpManipulateBreakPoint Status = %ld\n", pdbgkdCmdPacket->dwReturnStatus));
KdpSendKdApiCmdPacket (&MessageHeader, AdditionalData);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -