782 lines
22 KiB
C
782 lines
22 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
break.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements machine dependent functions to add and delete
|
|||
|
breakpoints from the kernel debugger breakpoint table.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
David N. Cutler 2-Aug-1990
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "bd.h"
|
|||
|
|
|||
|
LOGICAL BreakpointsSuspended = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Define external references.
|
|||
|
//
|
|||
|
|
|||
|
LOGICAL
|
|||
|
BdLowWriteContent(
|
|||
|
ULONG Index
|
|||
|
);
|
|||
|
|
|||
|
LOGICAL
|
|||
|
BdLowRestoreBreakpoint(
|
|||
|
ULONG Index
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
BdAddBreakpoint (
|
|||
|
IN ULONG64 Address
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine adds an entry to the breakpoint table and returns a handle
|
|||
|
to the breakpoint table entry.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Address - Supplies the address where to set the breakpoint.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A value of zero is returned if the specified address is already in the
|
|||
|
breakpoint table, there are no free entries in the breakpoint table, the
|
|||
|
specified address is not correctly aligned, or the specified address is
|
|||
|
not valid. Otherwise, the index of the assigned breakpoint table entry
|
|||
|
plus one is returned as the function value.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
BD_BREAKPOINT_TYPE Content;
|
|||
|
ULONG Index;
|
|||
|
BOOLEAN Accessible;
|
|||
|
#if defined(_IA64_)
|
|||
|
HARDWARE_PTE Opaque;
|
|||
|
#endif
|
|||
|
|
|||
|
//DPRINT(("KD: Setting breakpoint at 0x%08x\n", Address));
|
|||
|
//
|
|||
|
// If the specified address is not properly aligned, then return zero.
|
|||
|
//
|
|||
|
|
|||
|
if (((ULONG_PTR)Address & BD_BREAKPOINT_ALIGN) != 0) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the instruction to be replaced. If the instruction cannot be read,
|
|||
|
// then mark the breakpoint as not accessible.
|
|||
|
//
|
|||
|
|
|||
|
if (BdMoveMemory((PCHAR)&Content,
|
|||
|
(PCHAR)Address,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE) ) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
Accessible = FALSE;
|
|||
|
//DPRINT(("KD: memory inaccessible\n"));
|
|||
|
|
|||
|
} else {
|
|||
|
//DPRINT(("KD: memory readable...\n"));
|
|||
|
Accessible = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the specified address is not write accessible, then return zero.
|
|||
|
//
|
|||
|
|
|||
|
if (Accessible && BdWriteCheck((PVOID)Address) == NULL) {
|
|||
|
//DPRINT(("KD: memory not writable!\n"));
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Search the breakpoint table for a free entry and check if the specified
|
|||
|
// address is already in the breakpoint table.
|
|||
|
//
|
|||
|
|
|||
|
for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) {
|
|||
|
if (BdBreakpointTable[Index].Flags == 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If a free entry was found, then write breakpoint and return the handle
|
|||
|
// value plus one. Otherwise, return zero.
|
|||
|
//
|
|||
|
|
|||
|
if (Index == BREAKPOINT_TABLE_SIZE) {
|
|||
|
//DPRINT(("KD: ran out of breakpoints!\n"));
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//DPRINT(("KD: using Index %d\n", Index));
|
|||
|
|
|||
|
#if defined(_IA64_)
|
|||
|
if (Accessible) {
|
|||
|
BD_BREAKPOINT_TYPE mBuf;
|
|||
|
PVOID BundleAddress;
|
|||
|
|
|||
|
// change template to type 0 if current instruction is MLI
|
|||
|
|
|||
|
// read in intruction template if current instruction is NOT slot 0.
|
|||
|
// check for two-slot MOVL instruction. Reject request if attempt to
|
|||
|
// set break in slot 2 of MLI template.
|
|||
|
|
|||
|
if (((ULONG_PTR)Address & 0xf) != 0) {
|
|||
|
(ULONG_PTR)BundleAddress = (ULONG_PTR)Address & ~(0xf);
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)&mBuf,
|
|||
|
(PCHAR)BundleAddress,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: read 0x%08x template failed\n", BundleAddress));
|
|||
|
// MmDbgReleaseAddress((PVOID) Address, &Opaque);
|
|||
|
return 0;
|
|||
|
} else {
|
|||
|
if (((mBuf & INST_TEMPL_MASK) >> 1) == 0x2) {
|
|||
|
if (((ULONG_PTR)Address & 0xf) == 4) {
|
|||
|
// if template= type 2 MLI, change to type 0
|
|||
|
mBuf &= ~((INST_TEMPL_MASK >> 1) << 1);
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_IA64_MOVL;
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)BundleAddress,
|
|||
|
(PCHAR)&mBuf,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: write to 0x%08x template failed\n", BundleAddress));
|
|||
|
// MmDbgReleaseAddress((PVOID) Address, &Opaque);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
else {
|
|||
|
//DPRINT(("KD: change MLI template to type 0 at 0x%08x set\n", Address));
|
|||
|
}
|
|||
|
} else {
|
|||
|
// set breakpoint at slot 2 of MOVL is illegal
|
|||
|
//DPRINT(("KD: illegal to set BP at slot 2 of MOVL at 0x%08x\n", BundleAddress));
|
|||
|
// MmDbgReleaseAddress((PVOID) Address, &Opaque);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// insert break instruction
|
|||
|
|
|||
|
BdBreakpointTable[Index].Address = Address;
|
|||
|
BdBreakpointTable[Index].Content = Content;
|
|||
|
BdBreakpointTable[Index].Flags &= ~(BD_BREAKPOINT_STATE_MASK);
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_IN_USE;
|
|||
|
#if 0
|
|||
|
if (Address < (PVOID)GLOBAL_BREAKPOINT_LIMIT) {
|
|||
|
BdBreakpointTable[Index].DirectoryTableBase =
|
|||
|
KeGetCurrentThread()->ApcState.Process->DirectoryTableBase[0];
|
|||
|
}
|
|||
|
#endif
|
|||
|
switch ((ULONG_PTR)Address & 0xf) {
|
|||
|
case 0:
|
|||
|
Content = (Content & ~(INST_SLOT0_MASK)) | (BdBreakpointInstruction << 5);
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
Content = (Content & ~(INST_SLOT1_MASK)) | (BdBreakpointInstruction << 14);
|
|||
|
break;
|
|||
|
|
|||
|
case 8:
|
|||
|
Content = (Content & ~(INST_SLOT2_MASK)) | (BdBreakpointInstruction << 23);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
// MmDbgReleaseAddress((PVOID) Address, &Opaque);
|
|||
|
//DPRINT(("KD: BdAddBreakpoint bad instruction slot#\n"));
|
|||
|
return 0;
|
|||
|
}
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)Address,
|
|||
|
(PCHAR)&Content,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
|
|||
|
// MmDbgReleaseAddress((PVOID) Address, &Opaque);
|
|||
|
//DPRINT(("KD: BdMoveMemory failed writing BP!\n"));
|
|||
|
return 0;
|
|||
|
}
|
|||
|
else {
|
|||
|
//DPRINT(("KD: breakpoint at 0x%08x set\n", Address));
|
|||
|
}
|
|||
|
// MmDbgReleaseAddress((PVOID) Address, &Opaque);
|
|||
|
|
|||
|
} else { // memory not accessible
|
|||
|
BdBreakpointTable[Index].Address = Address;
|
|||
|
BdBreakpointTable[Index].Flags &= ~(BD_BREAKPOINT_STATE_MASK);
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_IN_USE;
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_WRITE;
|
|||
|
//DPRINT(("KD: breakpoint write deferred\n"));
|
|||
|
}
|
|||
|
#else // _IA64_
|
|||
|
if (Accessible) {
|
|||
|
BdBreakpointTable[Index].Address = Address;
|
|||
|
BdBreakpointTable[Index].Content = Content;
|
|||
|
BdBreakpointTable[Index].Flags = BD_BREAKPOINT_IN_USE;
|
|||
|
if (BdMoveMemory((PCHAR)Address,
|
|||
|
(PCHAR)&BdBreakpointInstruction,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
|
|||
|
//DPRINT(("KD: BdMoveMemory failed writing BP!\n"));
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
BdBreakpointTable[Index].Address = Address;
|
|||
|
BdBreakpointTable[Index].Flags = BD_BREAKPOINT_IN_USE | BD_BREAKPOINT_NEEDS_WRITE;
|
|||
|
//DPRINT(("KD: breakpoint write deferred\n"));
|
|||
|
}
|
|||
|
#endif // _IA64_
|
|||
|
|
|||
|
return Index + 1;
|
|||
|
}
|
|||
|
|
|||
|
LOGICAL
|
|||
|
BdLowWriteContent (
|
|||
|
IN ULONG Index
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine attempts to replace the code that a breakpoint is
|
|||
|
written over. This routine, BdAddBreakpoint,
|
|||
|
BdLowRestoreBreakpoint and KdSetOwedBreakpoints are responsible
|
|||
|
for getting data written as requested. Callers should not
|
|||
|
examine or use BdOweBreakpoints, and they should not set the
|
|||
|
NEEDS_WRITE or NEEDS_REPLACE flags.
|
|||
|
|
|||
|
Callers must still look at the return value from this function,
|
|||
|
however: if it returns FALSE, the breakpoint record must not be
|
|||
|
reused until KdSetOwedBreakpoints has finished with it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Index - Supplies the index of the breakpoint table entry
|
|||
|
which is to be deleted.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns TRUE if the breakpoint was removed, FALSE if it was deferred.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
#if defined(_IA64_)
|
|||
|
BD_BREAKPOINT_TYPE mBuf;
|
|||
|
PVOID BundleAddress;
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Do the contents need to be replaced at all?
|
|||
|
//
|
|||
|
|
|||
|
if (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_NEEDS_WRITE) {
|
|||
|
|
|||
|
//
|
|||
|
// The breakpoint was never written out. Clear the flag
|
|||
|
// and we are done.
|
|||
|
//
|
|||
|
|
|||
|
BdBreakpointTable[Index].Flags &= ~BD_BREAKPOINT_NEEDS_WRITE;
|
|||
|
//DPRINT(("KD: Breakpoint at 0x%08x never written; flag cleared.\n",
|
|||
|
// BdBreakpointTable[Index].Address));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
#if !defined(_IA64_)
|
|||
|
if (BdBreakpointTable[Index].Content == BdBreakpointInstruction) {
|
|||
|
|
|||
|
//
|
|||
|
// The instruction is a breakpoint anyway.
|
|||
|
//
|
|||
|
|
|||
|
//DPRINT(("KD: Breakpoint at 0x%08x; instr is really BP; flag cleared.\n",
|
|||
|
// BdBreakpointTable[Index].Address));
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Restore the instruction contents.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(_IA64_)
|
|||
|
// Read in memory since adjancent instructions in the same bundle may have
|
|||
|
// been modified after we save them.
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)&mBuf,
|
|||
|
(PCHAR)BdBreakpointTable[Index].Address,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: read 0x%08x failed\n", BdBreakpointTable[Index].Address));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_REPLACE;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
|
|||
|
switch ((ULONG_PTR)BdBreakpointTable[Index].Address & 0xf) {
|
|||
|
case 0:
|
|||
|
mBuf = (mBuf & ~(INST_SLOT0_MASK))
|
|||
|
| (BdBreakpointTable[Index].Content & INST_SLOT0_MASK);
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
mBuf = (mBuf & ~(INST_SLOT1_MASK))
|
|||
|
| (BdBreakpointTable[Index].Content & INST_SLOT1_MASK);
|
|||
|
break;
|
|||
|
|
|||
|
case 8:
|
|||
|
mBuf = (mBuf & ~(INST_SLOT2_MASK))
|
|||
|
| (BdBreakpointTable[Index].Content & INST_SLOT2_MASK);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
//DPRINT(("KD: illegal instruction address 0x%08x\n", BdBreakpointTable[Index].Address));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)BdBreakpointTable[Index].Address,
|
|||
|
(PCHAR)&mBuf,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: write to 0x%08x failed\n", BdBreakpointTable[Index].Address));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_REPLACE;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)&mBuf,
|
|||
|
(PCHAR)BdBreakpointTable[Index].Address,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)) == sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("\tcontent after memory move = 0x%08x 0x%08x\n", (ULONG)(mBuf >> 32), (ULONG)mBuf));
|
|||
|
}
|
|||
|
|
|||
|
// restore template to MLI if displaced instruction was MOVL
|
|||
|
|
|||
|
if (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_IA64_MOVL) {
|
|||
|
(ULONG_PTR)BundleAddress = (ULONG_PTR)BdBreakpointTable[Index].Address & ~(0xf);
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)&mBuf,
|
|||
|
(PCHAR)BundleAddress,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: read template 0x%08x failed\n", BdBreakpointTable[Index].Address));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_REPLACE;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
mBuf &= ~((INST_TEMPL_MASK >> 1) << 1); // set template to MLI
|
|||
|
mBuf |= 0x4;
|
|||
|
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)BundleAddress,
|
|||
|
(PCHAR)&mBuf,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: write template to 0x%08x failed\n", BdBreakpointTable[Index].Address));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_REPLACE;
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
//DPRINT(("KD: Breakpoint at 0x%08x cleared.\n",
|
|||
|
// BdBreakpointTable[Index].Address));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else { // not MOVL
|
|||
|
//DPRINT(("KD: Breakpoint at 0x%08x cleared.\n",
|
|||
|
// BdBreakpointTable[Index].Address));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#else // _IA64_
|
|||
|
if (BdMoveMemory( (PCHAR)BdBreakpointTable[Index].Address,
|
|||
|
(PCHAR)&BdBreakpointTable[Index].Content,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE) ) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_REPLACE;
|
|||
|
//DPRINT(("KD: Breakpoint at 0x%08x; unable to clear, flag set.\n",
|
|||
|
//BdBreakpointTable[Index].Address));
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
//DPRINT(("KD: Breakpoint at 0x%08x cleared.\n",
|
|||
|
//BdBreakpointTable[Index].Address));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
#endif // _IA64_
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
LOGICAL
|
|||
|
BdDeleteBreakpoint (
|
|||
|
IN ULONG Handle
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine deletes an entry from the breakpoint table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Handle - Supplies the index plus one of the breakpoint table entry
|
|||
|
which is to be deleted.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A value of FALSE is returned if the specified handle is not a valid
|
|||
|
value or the breakpoint cannot be deleted because the old instruction
|
|||
|
cannot be replaced. Otherwise, a value of TRUE is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Index = Handle - 1;
|
|||
|
|
|||
|
//
|
|||
|
// If the specified handle is not valid, then return FALSE.
|
|||
|
//
|
|||
|
|
|||
|
if ((Handle == 0) || (Handle > BREAKPOINT_TABLE_SIZE)) {
|
|||
|
//DPRINT(("KD: Breakpoint %d invalid.\n", Index));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the specified breakpoint table entry is not valid, then return FALSE.
|
|||
|
//
|
|||
|
|
|||
|
if (BdBreakpointTable[Index].Flags == 0) {
|
|||
|
//DPRINT(("KD: Breakpoint %d already clear.\n", Index));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the breakpoint is already suspended, just delete it from the table.
|
|||
|
//
|
|||
|
|
|||
|
if (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_SUSPENDED) {
|
|||
|
//DPRINT(("KD: Deleting suspended breakpoint %d \n", Index));
|
|||
|
if ( !(BdBreakpointTable[Index].Flags & BD_BREAKPOINT_NEEDS_REPLACE) ) {
|
|||
|
//DPRINT(("KD: already clear.\n"));
|
|||
|
BdBreakpointTable[Index].Flags = 0;
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Replace the instruction contents.
|
|||
|
//
|
|||
|
|
|||
|
if (BdLowWriteContent(Index)) {
|
|||
|
|
|||
|
//
|
|||
|
// Delete breakpoint table entry
|
|||
|
//
|
|||
|
|
|||
|
//DPRINT(("KD: Breakpoint %d deleted successfully.\n", Index));
|
|||
|
BdBreakpointTable[Index].Flags = 0;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
LOGICAL
|
|||
|
BdDeleteBreakpointRange (
|
|||
|
IN ULONG64 Lower,
|
|||
|
IN ULONG64 Upper
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine deletes all breakpoints falling in a given range
|
|||
|
from the breakpoint table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Lower - inclusive lower address of range from which to remove BPs.
|
|||
|
|
|||
|
Upper - include upper address of range from which to remove BPs.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if any breakpoints removed, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Index;
|
|||
|
BOOLEAN ReturnStatus = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Examine each entry in the table in turn
|
|||
|
//
|
|||
|
|
|||
|
for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++) {
|
|||
|
|
|||
|
if ( (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_IN_USE) &&
|
|||
|
((BdBreakpointTable[Index].Address >= Lower) &&
|
|||
|
(BdBreakpointTable[Index].Address <= Upper))
|
|||
|
) {
|
|||
|
|
|||
|
//
|
|||
|
// Breakpoint is in use and falls in range, clear it.
|
|||
|
//
|
|||
|
|
|||
|
ReturnStatus = ReturnStatus || BdDeleteBreakpoint(Index+1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ReturnStatus;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdSuspendBreakpoint (
|
|||
|
ULONG Handle
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Index = Handle - 1;
|
|||
|
|
|||
|
if ( (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_IN_USE) &&
|
|||
|
!(BdBreakpointTable[Index].Flags & BD_BREAKPOINT_SUSPENDED) ) {
|
|||
|
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_SUSPENDED;
|
|||
|
BdLowWriteContent(Index);
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdSuspendAllBreakpoints (
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
ULONG Handle;
|
|||
|
|
|||
|
BreakpointsSuspended = TRUE;
|
|||
|
|
|||
|
for ( Handle = 1; Handle <= BREAKPOINT_TABLE_SIZE; Handle++ ) {
|
|||
|
BdSuspendBreakpoint(Handle);
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
LOGICAL
|
|||
|
BdLowRestoreBreakpoint (
|
|||
|
IN ULONG Index
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine attempts to write a breakpoint instruction.
|
|||
|
The old contents must have already been stored in the
|
|||
|
breakpoint record.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Index - Supplies the index of the breakpoint table entry
|
|||
|
which is to be written.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns TRUE if the breakpoint was written, FALSE if it was
|
|||
|
not and has been marked for writing later.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BD_BREAKPOINT_TYPE Content;
|
|||
|
|
|||
|
#if defined(_IA64_)
|
|||
|
BD_BREAKPOINT_TYPE mBuf;
|
|||
|
PVOID BundleAddress;
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Does the breakpoint need to be written at all?
|
|||
|
//
|
|||
|
|
|||
|
if (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_NEEDS_REPLACE) {
|
|||
|
|
|||
|
//
|
|||
|
// The breakpoint was never removed. Clear the flag
|
|||
|
// and we are done.
|
|||
|
//
|
|||
|
|
|||
|
BdBreakpointTable[Index].Flags &= ~BD_BREAKPOINT_NEEDS_REPLACE;
|
|||
|
return TRUE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if !defined(_IA64_)
|
|||
|
if (BdBreakpointTable[Index].Content == BdBreakpointInstruction) {
|
|||
|
|
|||
|
//
|
|||
|
// The instruction is a breakpoint anyway.
|
|||
|
//
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Replace the instruction contents.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(_IA64_)
|
|||
|
|
|||
|
// read in intruction in case the adjacent instruction has been modified.
|
|||
|
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)&mBuf,
|
|||
|
(PCHAR)BdBreakpointTable[Index].Address,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: read 0x%p template failed\n", BdBreakpointTable[Index].Address));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_WRITE;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
switch ((ULONG_PTR)BdBreakpointTable[Index].Address & 0xf) {
|
|||
|
case 0:
|
|||
|
mBuf = (mBuf & ~(INST_SLOT0_MASK)) | (BdBreakpointInstruction << 5);
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
mBuf = (mBuf & ~(INST_SLOT1_MASK)) | (BdBreakpointInstruction << 14);
|
|||
|
break;
|
|||
|
|
|||
|
case 8:
|
|||
|
mBuf = (mBuf & ~(INST_SLOT2_MASK)) | (BdBreakpointInstruction << 23);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
//DPRINT(("KD: BdAddBreakpoint bad instruction slot#\n"));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)BdBreakpointTable[Index].Address,
|
|||
|
(PCHAR)&mBuf,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
|
|||
|
//DPRINT(("KD: BdMoveMemory failed writing BP!\n"));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_WRITE;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
|
|||
|
// check for two-slot MOVL instruction. Reject request if attempt to
|
|||
|
// set break in slot 2 of MLI template.
|
|||
|
// change template to type 0 if current instruction is MLI
|
|||
|
|
|||
|
if (((ULONG_PTR)BdBreakpointTable[Index].Address & 0xf) != 0) {
|
|||
|
(ULONG_PTR)BundleAddress = (ULONG_PTR)BdBreakpointTable[Index].Address & ~(0xf);
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)&mBuf,
|
|||
|
(PCHAR)BundleAddress,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: read template failed at 0x%08x\n", BundleAddress));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_WRITE;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
if (((mBuf & INST_TEMPL_MASK) >> 1) == 0x2) {
|
|||
|
if (((ULONG_PTR)BdBreakpointTable[Index].Address & 0xf) == 4) {
|
|||
|
// if template= type 2 MLI, change to type 0
|
|||
|
mBuf &= ~((INST_TEMPL_MASK >> 1) << 1);
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_IA64_MOVL;
|
|||
|
if (BdMoveMemory(
|
|||
|
(PCHAR)BundleAddress,
|
|||
|
(PCHAR)&mBuf,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE)
|
|||
|
) != sizeof(BD_BREAKPOINT_TYPE)) {
|
|||
|
//DPRINT(("KD: write to 0x%08x template failed\n", BundleAddress));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_WRITE;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
//DPRINT(("KD: change MLI template to type 0 at 0x%08x set\n", Address));
|
|||
|
}
|
|||
|
} else {
|
|||
|
// set breakpoint at slot 2 of MOVL is illegal
|
|||
|
//DPRINT(("KD: illegal to set BP at slot 2 of MOVL at 0x%08x\n", BundleAddress));
|
|||
|
BdBreakpointTable[Index].Flags |= BD_BREAKPOINT_NEEDS_WRITE;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//DPRINT(("KD: breakpoint at 0x%08x set\n", Address));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
#else // _IA64_
|
|||
|
|
|||
|
BdMoveMemory((PCHAR)BdBreakpointTable[Index].Address,
|
|||
|
(PCHAR)&BdBreakpointInstruction,
|
|||
|
sizeof(BD_BREAKPOINT_TYPE));
|
|||
|
return TRUE;
|
|||
|
#endif // _IA64_
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdRestoreAllBreakpoints (
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Index;
|
|||
|
|
|||
|
BreakpointsSuspended = FALSE;
|
|||
|
|
|||
|
for ( Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++ ) {
|
|||
|
|
|||
|
if ((BdBreakpointTable[Index].Flags & BD_BREAKPOINT_IN_USE) &&
|
|||
|
(BdBreakpointTable[Index].Flags & BD_BREAKPOINT_SUSPENDED) ) {
|
|||
|
|
|||
|
BdBreakpointTable[Index].Flags &= ~BD_BREAKPOINT_SUSPENDED;
|
|||
|
BdLowRestoreBreakpoint(Index);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|