Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1346 lines
30 KiB

#include "precomp.h"
#pragma hdrstop
SetFile()
BREAKPOINT masterBP = {0L,0L};
PBREAKPOINT bpList = &masterBP;
extern HTHDX thdList;
extern CRITICAL_SECTION csThreadProcList;
PBREAKPOINT
GetNewBp(
HPRCX hprc,
HTHDX hthd,
BPTP BpType,
BPNS BpNotify,
ADDR *AddrBp,
HPID id,
PBREAKPOINT BpUse
)
/*++
Routine Description:
Allocates a BREAKPOINT structure and initializes it. Note that
this does NOT add the structure to the breakpoint list (bplist).
If it is not an address bp (i.e. it is a watchpoint), the hwalk
field must be initialized later.
Arguments:
hprc - Supplies process to put BP in
hthd - Supplies optional thread
AddrBp - Supplies address structure for the breakpoint
id - Supplies EM id for BP
BpUse - Supplies other BP on same address (so we can steal the
original code from it instead of reading).
This last one is optional.
Return Value:
PBREAKPOINT - Pointer to allocated and initialized structure.
--*/
{
PBREAKPOINT Bp;
ADDR Addr;
DWORD i;
assert( !BpUse || ( BpUse->hthd != hthd ) );
Bp = (PBREAKPOINT)malloc(sizeof(BREAKPOINT));
assert( Bp );
if ( Bp ) {
assert( bpList );
Bp->next = NULL;
Bp->hprc = hprc;
Bp->hthd = hthd;
Bp->id = id;
Bp->instances = 1;
Bp->isStep = FALSE;
Bp->hBreakPoint = 0;
Bp->bpType = BpType;
Bp->bpNotify = BpNotify;
Bp->hWalk = NULL;
memset(&Bp->addr, 0, sizeof(Bp->addr));
//
// Get the opcode from the indicated address
//
if ( BpUse ) {
Bp->instr1 = BpUse->instr1;
} else if (AddrBp) {
Bp->instr1 = 0;
Addr = *AddrBp;
Bp->addr = *AddrBp;
//
// Check to make sure that what we have is not a linker index
// number in the address structure. If it is then we can not
// currently set this breakpoint due to the fact that we
// don't have a real address
//
if ( ADDR_IS_LI(Addr) ) {
assert(!"Addr is LI");
free( Bp );
Bp = NULL;
}
else if (!AddrReadMemory(hprc, hthd, &Addr, &(Bp->instr1), BP_SIZE,
&i) ||
(i != BP_SIZE)) {
#ifdef KERNEL
Bp->instr1 = 0;
#else
assert(!"AddrReadMemory failed");
free(Bp);
Bp = NULL;
#endif
}
}
}
return Bp;
}
PBREAKPOINT
SetBP(
HPRCX hprc,
HTHDX hthd,
BPTP bptype,
BPNS bpnotify,
LPADDR paddr,
HPID id
)
/*++
Routine Description:
Set a breakpoint, or increment instance count on an existing bp.
if hthd is non-NULL, BP is only for that thread.
Arguments:
hprc - Supplies process to put BP in
hthd - Supplies optional thread
bptype - Supplies OSDEBUG BP type
paddr - Supplies address structure for the breakpoint
id - Supplies EM id for BP
Return Value:
pointer to bp structure, or NULL for failure
--*/
{
PBREAKPOINT pbp;
PBREAKPOINT pbpT;
ADDR addr;
ADDR addr2;
if (!hprc) {
return (PBREAKPOINT)NULL;
}
EnterCriticalSection(&csThreadProcList);
/*
* First let's try to find a breakpoint that
* matches this description
*/
pbpT = FindBP(hprc, hthd, bptype, bpnotify, paddr, FALSE);
/*
* If this thread has a breakpoint here,
* increment reference count.
*/
if (pbpT && pbpT->hthd == hthd) {
pbp = pbpT;
pbp->instances++;
} else if ( pbp = GetNewBp( hprc, hthd, bptype, bpnotify, paddr, id, pbpT )) {
if ( !pbpT ) {
//
// Now write the cpu-specific breakpoint code.
//
assert(!ADDR_IS_LI(pbp->addr));
if ( WriteBreakPoint(pbp) ) {
AddBpToList(pbp);
} else {
free( pbp );
pbp = NULL;
}
} else {
//
// Breakpoint exists, but for wrong thread.
//
*pbp = *pbpT;
pbp->hthd = hthd;
pbp->instances = 1;
}
/*
* Make it a linear address to start with
*/
addr2 = *paddr;
TranslateAddress(hprc, hthd, &addr2, TRUE);
/*
* Check with the threads to see if we are at this address. If so then
* we need to set the BP field so we don't hit the bp imeadiately
*/
if (hthd) {
AddrFromHthdx(&addr, hthd);
if ((hthd->tstate & ts_stopped) &&
(AtBP(hthd) == NULL) &&
AreAddrsEqual(hprc, hthd, &addr, &addr2)) {
SetBPFlag(hthd, pbp);
}
} else {
for (hthd = hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
AddrFromHthdx(&addr, hthd);
if ((hthd->tstate & ts_stopped) &&
(AtBP(hthd) == NULL) &&
AreAddrsEqual(hprc, hthd, &addr, &addr2)) {
SetBPFlag(hthd, pbp);
}
}
}
}
LeaveCriticalSection(&csThreadProcList);
return pbp;
} /* SetBP() */
#ifdef KERNEL
BOOL
SetBPEx(
HPRCX hprc,
HTHDX hthd,
HPID id,
DWORD Count,
ADDR *Addrs,
PBREAKPOINT *Bps,
DWORD ContinueStatus
)
/*++
Routine Description:
Allocates a bunch of breakpoints from a given list of linear offsets.
Arguments:
hprc - Supplies process to put BP in
hthd - Supplies optional thread
Count - Supplies count of breakpoints to set
Addrs - Supplies list with Count addresses
Bps - Supplies buffer to be filled with Count pointers to
BREAKPOINT structures. Original contents is
overwritten.
ContinueStatus -
Return Value:
BOOL - If TRUE, then ALL breakpoints were set.
If FALSE, then NONE of the breakpoints were set.
NOTENOTE - Not sure of what will happen if the list contains duplicated
addresses!
--*/
{
PDBGKD_WRITE_BREAKPOINT DbgKdBp;
PDBGKD_RESTORE_BREAKPOINT DbgKdBpRes;
DWORD SetCount = 0;
DWORD NewCount = 0;
DWORD i;
DWORD j;
PBREAKPOINT BpT;
BOOL Ok;
ADDR Addr;
ADDR Addr2;
if (!hprc) {
assert(!"hprc == NULL is SetBPEx");
return FALSE;
}
assert( Count > 0 );
assert( Addrs );
assert( Bps );
if ( Count == 1 ) {
//
// Only one breakpoint, faster to simply call SetBP
//
Bps[0] = SetBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[0], id );
return ( Bps[0] != NULL );
}
EnterCriticalSection(&csThreadProcList);
AddrInit( &Addr, 0, 0, 0, TRUE, TRUE, FALSE, FALSE );
//
// Allocate space for Count breakpoints
//
DbgKdBp = (PDBGKD_WRITE_BREAKPOINT)
malloc( sizeof(DBGKD_WRITE_BREAKPOINT) * Count );
assert( DbgKdBp );
if ( !DbgKdBp ) {
LeaveCriticalSection(&csThreadProcList);
return FALSE;
}
for ( i=0; i<Count; i++ ) {
//
// See if we already have a breakpoint at this address.
//
Bps[i] = FindBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], FALSE );
if ( !Bps[i] ) {
DbgKdBp[ NewCount ].BreakPointAddress =
(PVOID)GetAddrOff(Addrs[i]);
DbgKdBp[ NewCount++ ].BreakPointHandle = (ULONG)NULL;
Bps[i] = GetNewBp( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL );
assert( Bps[i] );
} else if (Bps[i]->hthd != hthd ) {
BpT = Bps[i];
Bps[i] = GetNewBp( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL );
// BUGBUG kentf should instances be changed?
*Bps[i] = *BpT;
Bps[i]->hthd = hthd;
}
}
Ok = TRUE;
if ( NewCount > 0 ) {
//
// Set all new breakpoints
//
assert( NewCount <= Count );
Ok = WriteBreakPointEx( hthd, NewCount, DbgKdBp, ContinueStatus );
}
if ( Ok ) {
//
// Fill in the breakpoint list
//
j = 0;
for ( i=0; i<Count; i++ ) {
if ( Bps[i] && Bps[i]->hBreakPoint && Bps[i]->hthd == hthd ) {
//
// Will reuse BP, just increment reference count.
//
Bps[i]->instances++;
} else {
assert( (PVOID)GetAddrOff(Addrs[i]) ==
DbgKdBp[j].BreakPointAddress );
//
// Allocate new BP structure and get handle from
// the breakpoint packet. Note that we rely on the
// order of the breakpoints in the breakpoint packet.
//
Bps[i]->hBreakPoint = DbgKdBp[j].BreakPointHandle;
AddBpToList(Bps[i]);
j++;
}
SetCount++;
//
// Check with the threads to see if we are at this address.
// If so then we need to set the BP field so we don't hit
// the bp imeadiately
//
Addr2 = Bps[i]->addr;
if ( hthd ) {
AddrFromHthdx( &Addr, hthd );
if ((hthd->tstate & ts_stopped) &&
(AtBP(hthd) == NULL) &&
AreAddrsEqual(hprc, hthd, &Addr, &Addr2 )) {
SetBPFlag(hthd, Bps[i]);
}
} else {
for (hthd=hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
AddrFromHthdx( &Addr, hthd );
if ((hthd->tstate & ts_stopped) &&
(AtBP(hthd) == NULL) &&
AreAddrsEqual(hprc, hthd, &Addr, &Addr2)) {
SetBPFlag(hthd, Bps[i]);
}
}
}
}
assert( j == NewCount );
} else {
//
// Clean up any breakpoints that were set.
//
DbgKdBpRes = (PDBGKD_RESTORE_BREAKPOINT)
malloc( sizeof(DBGKD_RESTORE_BREAKPOINT) * NewCount );
assert( DbgKdBpRes );
if ( DbgKdBpRes ) {
//
// Put all breakpoints with a valid handle on the list of
// breakpoints to be removed.
//
j = 0;
for ( i=0; i<NewCount;i++) {
if ( DbgKdBp[i].BreakPointHandle != (ULONG)NULL ) {
DbgKdBpRes[j++].BreakPointHandle =
DbgKdBp[i].BreakPointHandle;
}
}
//
// Now remove them
//
if ( j > 0 ) {
assert( j <= NewCount );
RestoreBreakPointEx( j, DbgKdBpRes );
}
free( DbgKdBpRes );
//
// Remove allocated BP structures
//
for ( i=0; i<Count; i++ ) {
if ( Bps[i] && !Bps[i]->hBreakPoint ) {
assert( !Bps[i]->next );
free( Bps[i] );
Bps[i] = NULL;
}
}
}
}
free( DbgKdBp );
LeaveCriticalSection(&csThreadProcList);
return (SetCount == Count);
}
#else // KERNEL
BOOL
SetBPEx(
HPRCX hprc,
HTHDX hthd,
HPID id,
DWORD Count,
ADDR *Addrs,
PBREAKPOINT *Bps,
DWORD ContinueStatus
)
/*++
Routine Description:
Allocates a bunch of breakpoints from a given list of linear offsets.
Arguments:
hprc - Supplies process to put BP in
hthd - Supplies optional thread
Count - Supplies count of breakpoints to set
Addrs - Supplies list with Count addresses
Bps - Supplies buffer to be filled with Count pointers to
BREAKPOINT structures. Original contents is
overwritten.
ContinueStatus -
Return Value:
BOOL - If TRUE, then ALL breakpoints were set.
If FALSE, then NONE of the breakpoints were set.
NOTENOTE - Not sure of what will happen if the list contains duplicated
addresses!
--*/
{
DWORD SetCount = 0;
DWORD NewCount = 0;
DWORD i;
DWORD j;
DWORD k;
ADDR Addr;
ADDR Addr2;
BP_UNIT opcode = BP_OPCODE;
if (!hprc) {
assert(!"hprc == NULL in SetBPEx");
return FALSE;
}
assert( Count > 0 );
assert( Addrs );
assert( Bps );
if ( Count == 1 ) {
//
// Only one breakpoint, faster to simply call SetBP
//
Bps[0] = SetBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[0], id );
return ( Bps[0] != NULL );
}
EnterCriticalSection(&csThreadProcList);
for ( i=0; i<Count; i++ ) {
//
// See if we already have a breakpoint at this address.
//
Bps[i] = FindBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], FALSE );
if ( Bps[i] && Bps[i]->hthd == hthd ) {
//
// Reuse this breakpoint
//
Bps[i]->instances++;
assert( Bps[i]->instances > 1 );
} else {
//
// Get new breakpoint
//
Bps[i] = GetNewBp(hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL);
if ( !Bps[i] ) {
assert(!"GetNewBp failed in SetBPEx");
break;
}
if ( !ADDR_IS_LI(Bps[i]->addr) ) {
if ( !AddrWriteMemory(hprc, hthd, &Bps[i]->addr,
(LPBYTE) &opcode, BP_SIZE, &j) ) {
free( Bps[i] );
Bps[i] = NULL;
assert(!"DbgWriteMemory failed in SetBPEx");
break;
}
}
}
}
if ( i < Count ) {
//
// Something went wrong, will backtrack
//
assert(!"i < Count in SetBPEx");
for ( j=0; j<i; j++ ) {
assert( Bps[j] );
Bps[j]->instances--;
if ( Bps[j]->instances == 0 ) {
if ( !ADDR_IS_LI(Bps[j]->addr) ) {
AddrWriteMemory(hprc, hthd, &Bps[j]->addr,
(LPBYTE) &Bps[j]->instr1, BP_SIZE, &k);
}
free( Bps[j] );
Bps[j] = NULL;
}
}
} else {
//
// Add all the new breakpoints to the list
//
for ( i=0; i<Count; i++ ) {
if ( Bps[i]->instances == 1 ) {
AddBpToList(Bps[i]);
}
//
// Check with the threads to see if we are at this address. If so then
// we need to set the BP field so we don't hit the bp imeadiately
//
Addr2 = Bps[i]->addr;
if ( hthd ) {
AddrFromHthdx( &Addr, hthd );
if ((hthd->tstate & ts_stopped) &&
(AtBP(hthd) == NULL) &&
AreAddrsEqual(hprc, hthd, &Addr, &Addr2 )) {
SetBPFlag(hthd, Bps[i]);
}
} else {
for (hthd=hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
AddrFromHthdx( &Addr, hthd );
if ((hthd->tstate & ts_stopped) &&
(AtBP(hthd) == NULL) &&
AreAddrsEqual(hprc, hthd, &Addr, &Addr2)) {
SetBPFlag(hthd, Bps[i]);
}
}
}
}
SetCount = Count;
}
LeaveCriticalSection(&csThreadProcList);
return (SetCount == Count);
}
#endif // KERNEL
BOOL
BPInRange(
HPRCX hprc,
HTHDX hthd,
PBREAKPOINT bp,
LPADDR paddrStart,
DWORD cb,
LPDWORD offset,
BP_UNIT * instr
)
{
ADDR addr1;
ADDR addr2;
/*
* If the breakpoint has a Loader index address then we can not
* possibly match it
*/
assert (!ADDR_IS_LI(*paddrStart) );
if (ADDR_IS_LI(bp->addr)) {
return FALSE;
}
*offset = 0;
/*
* Now check for "equality" of the addresses.
*
* Need to include size of BP in the address range check. Since
* the address may start half way through a breakpoint.
*/
if ((ADDR_IS_FLAT(*paddrStart) == TRUE) &&
(ADDR_IS_FLAT(bp->addr) == TRUE)) {
if ((GetAddrOff(*paddrStart) - sizeof(BP_UNIT) + 1 <=
GetAddrOff(bp->addr)) &&
(GetAddrOff(bp->addr) < GetAddrOff(*paddrStart) + cb)) {
*offset = (DWORD) GetAddrOff(bp->addr) -
(DWORD) GetAddrOff(*paddrStart);
*instr = bp->instr1;
return TRUE;
}
return FALSE;
}
/*
* The two addresses did not start out as flat addresses. So change
* them to linear addresses so that we can see if the addresses are
* are really the same
*/
addr1 = *paddrStart;
if (!TranslateAddress(hprc, hthd, &addr1, TRUE)) {
return FALSE;
}
addr2 = bp->addr;
if (!TranslateAddress(hprc, hthd, &addr2, TRUE)) {
return FALSE;
}
if ((GetAddrOff(addr1) - sizeof(BP_UNIT) + 1 <= GetAddrOff(addr2)) &&
(GetAddrOff(addr2) < GetAddrOff(addr1) + cb)) {
*offset = (DWORD) GetAddrOff(addr2) - (DWORD) GetAddrOff(addr1);
*instr = bp->instr1;
return TRUE;
}
return FALSE;
}
PBREAKPOINT
FindBP(
HPRCX hprc,
HTHDX hthd,
BPTP bptype,
BPNS bpnotify,
LPADDR paddr,
BOOL fExact
)
/*++
Routine Description:
Find and return a pointer to a BP struct. Always returns a BP that
matches hthd thread if one exists; if fExact is FALSE and there is no
exact match, a BP matching only hprc and address will succeed.
Arguments:
hprc - Supplies process
hthd - Supplies thread
bptype - Supplies OSDEBUG BP type
paddr - Supplies address
fExact - Supplies TRUE if must be for a certain thread
Return Value:
pointer to BREAKPOINT struct, or NULL if not found.
--*/
{
PBREAKPOINT pbp;
PBREAKPOINT pbpFound = NULL;
ADDR addr;
EnterCriticalSection(&csThreadProcList);
/*
* Pre-translate the address to a linear address
*/
addr = *paddr;
TranslateAddress(hprc, hthd, &addr, TRUE);
/*
* Check for an equivalent breakpoint. Breakpoints will be equal if
*
* 1. The process is the same
* 2. The addresses of the breakpoints are the same
*/
for (pbp=bpList->next; pbp; pbp=pbp->next) {
if ((pbp->hprc == hprc) &&
AreAddrsEqual(hprc, hthd, &pbp->addr, &addr)) {
pbpFound = pbp;
if (pbp->hthd == hthd) {
break;
}
}
}
LeaveCriticalSection(&csThreadProcList);
if (!fExact || (pbpFound && pbpFound->hthd == hthd)) {
return pbpFound;
} else {
return NULL;
}
} /* FindBP() */
PBREAKPOINT
BPNextHprcPbp(
HPRCX hprc,
PBREAKPOINT pbp
)
/*++
Routine Description:
Find the next breakpoint for the given process after pbp.
If pbp is NULL start at the front of the list, for a find
first, find next behaviour.
Arguments:
hprc - Supplies the process handle to match breakpoints for
pbp - Supplies pointer to breakpoint item to start searching after
Return Value:
NULL if no matching breakpoint is found else a pointer to the
matching breakpoint
--*/
{
EnterCriticalSection(&csThreadProcList);
if (pbp == NULL) {
pbp = bpList->next;
} else {
pbp = pbp->next;
}
for ( ; pbp; pbp = pbp->next ) {
if (pbp->hprc == hprc) {
break;
}
}
LeaveCriticalSection(&csThreadProcList);
return pbp;
} /* BPNextHprcPbp() */
PBREAKPOINT
BPNextHthdPbp(
HTHDX hthd,
PBREAKPOINT pbp
)
/*++
Routine Description:
Find the next breakpoint for the given thread after pbp.
If pbp is NULL start at the front of the list for find
first, find next behaviour.
Arguments:
hthd - Supplies the thread handle to match breakpoints for
pbp - Supplies pointer to breakpoint item to start searching after
Return Value:
NULL if no matching breakpoint is found else a pointer to the
matching breakpoint
--*/
{
EnterCriticalSection(&csThreadProcList);
if (pbp == NULL) {
pbp = bpList->next;
} else {
pbp = pbp->next;
}
for ( ; pbp; pbp = pbp->next ) {
if (pbp->hthd == hthd) {
break;
}
}
LeaveCriticalSection(&csThreadProcList);
return pbp;
} /* BPNextHthdPbp() */
BOOL
RemoveBPHelper(
PBREAKPOINT pbp,
BOOL fRestore
)
{
PBREAKPOINT pbpPrev;
PBREAKPOINT pbpCur;
PBREAKPOINT pbpT;
HTHDX hthd;
BOOL rVal = FALSE;
//
// first, is it real?
//
if (!pbp || pbp == EMBEDDED_BP) {
return FALSE;
}
EnterCriticalSection(&csThreadProcList);
/* Decrement the instances counter */
if (--pbp->instances) {
/*
* BUGBUG: jimsch -- Feb 29 1993
* This piece of code is most likely incorrect. We need to
* know if we are the DM freeing a breakpoint or the user
* freeing a breakpoint before we clear the step bit. Otherwise
* we may be in the following situation
*
* Set a thread specific breakpoint on an address
* Step the thread so that the address is the destination is
* where the step ends up (but it takes some time such
* as over a function call)
* Clear the thread specific breakpoint
*
* This will cause the step breakpoint to be cleared so we will
* stop at the address instead of just continuing stepping.
*/
pbp->isStep = FALSE;
LeaveCriticalSection(&csThreadProcList);
return FALSE;
}
/* Search the list for the specified breakpoint */
for ( pbpPrev = bpList, pbpCur = bpList->next;
pbpCur;
pbpPrev = pbpCur, pbpCur = pbpCur->next) {
if (pbpCur == pbp) {
/*
* Remove this bp from the list:
*/
pbpPrev->next = pbpCur->next;
/*
* see if there is another bp on the same address:
*/
pbpT = FindBP(pbpCur->hprc,
pbpCur->hthd,
pbpCur->bpType,
pbpCur->bpNotify,
&pbpCur->addr,
FALSE);
if (!pbpT && pbpCur->bpType == bptpExec) {
/*
* if this was the only one, put the
* opcode back where it belongs.
*/
if ( fRestore ) {
RestoreBreakPoint( pbpCur );
}
}
/*
* Now we have to go through all the threads to see
* if any of them are on this breakpoint and clear
* the breakpoint indicator on these threads
*/
/*
* Could be on any thread:
*/
/*
* (We are already in the ThreadProcList critical section)
*/
for (hthd = thdList->next; hthd; hthd = hthd->next) {
if (hthd->atBP == pbpCur) {
hthd->atBP = pbpT;
}
}
free(pbpCur);
rVal = TRUE;
break;
}
}
LeaveCriticalSection(&csThreadProcList);
return rVal;
}
BOOL
RemoveBP(
PBREAKPOINT pbp
)
{
return RemoveBPHelper( pbp, TRUE );
}
#ifdef KERNEL
BOOL
RemoveBPEx(
DWORD Count,
PBREAKPOINT *Bps
)
{
PDBGKD_RESTORE_BREAKPOINT DbgKdBp;
DWORD RestoreCount = 0;
DWORD GoneCount = 0;
DWORD i;
PBREAKPOINT BpCur;
PBREAKPOINT BpOther;
assert( Count > 0 );
if ( Count == 1 ) {
//
// Only one breakpoint, its faster to simply call RemoveBP
//
return RemoveBP( Bps[0] );
}
EnterCriticalSection(&csThreadProcList);
DbgKdBp = (PDBGKD_RESTORE_BREAKPOINT)malloc( sizeof(DBGKD_RESTORE_BREAKPOINT) * Count );
assert( DbgKdBp );
if ( DbgKdBp ) {
//
// Find out what breakpoints we have to restore and put them in
// the list.
//
for ( i=0; i<Count;i++ ) {
assert( Bps[i] != EMBEDDED_BP );
for ( BpCur = bpList->next; BpCur; BpCur = BpCur->next) {
if ( BpCur == Bps[i] ) {
//
// See if there is another bp on the same address.
//
for ( BpOther = bpList->next; BpOther; BpOther = BpOther->next ) {
if ( (BpOther != BpCur) &&
AreAddrsEqual( BpCur->hprc, BpCur->hthd, &BpCur->addr, &BpOther->addr ) ) {
break;
}
}
if ( !BpOther ) {
//
// If this was the only one, put it in the list.
//
DbgKdBp[GoneCount++].BreakPointHandle = Bps[i]->hBreakPoint;
}
break;
}
}
}
//
// Restore the breakpoints in the list.
//
if ( GoneCount > 0 ) {
assert( GoneCount <= Count );
RestoreBreakPointEx( GoneCount, DbgKdBp );
}
//
// All breakpoints that were to be restored have been
// restored, now go ahead and do the cleaning up stuff.
//
for ( i=0; i<Count;i++ ) {
RemoveBPHelper( Bps[i], FALSE );
RestoreCount++;
}
free( DbgKdBp );
}
LeaveCriticalSection(&csThreadProcList);
return ( RestoreCount == Count );
}
#else // KERNEL
BOOL
RemoveBPEx(
DWORD Count,
PBREAKPOINT *Bps
)
{
DWORD i;
assert( Count > 0 );
for ( i=0; i<Count;i++ ) {
RemoveBPHelper( Bps[i], TRUE );
}
return TRUE;
}
#endif // KERNEL
void
SetBPFlag(
HTHDX hthd,
PBREAKPOINT bp
)
{
hthd->atBP = bp;
}
PBREAKPOINT
AtBP(
HTHDX hthd
)
{
return hthd->atBP;
}
void
ClearBPFlag(
HTHDX hthd
)
{
hthd->atBP = NULL;
}
void
RestoreInstrBP(
HTHDX hthd,
PBREAKPOINT bp
)
/*++
Routine Description:
Replace the instruction for a breakpoint. If it was not
the debugger's BP, skip the IP past it.
Arguments:
hthd - Thread
bp - breakpoint data
Return Value:
--*/
{
//
// Check if this is an embedded breakpoint
//
if (bp == EMBEDDED_BP) {
//
// It was, so there is no instruction to restore,
// just increment the EIP
//
IncrementIP(hthd);
return;
}
if (bp->hWalk) {
//
// This is really a hardware breakpoint. Let the
// walk manager fix this.
//
ExprBPClearBPForStep(hthd);
} else {
//
// Replace the breakpoint current in memory with the correct
// instruction
//
RestoreBreakPoint( bp );
bp->hBreakPoint = 0;
}
return;
}
VOID
DeleteAllBps(
VOID
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PBREAKPOINT pbp, bpn;
EnterCriticalSection(&csThreadProcList);
pbp = bpList->next;
while (pbp) {
bpn = pbp->next;
if (bpn) {
free( pbp );
}
pbp = bpn;
}
bpList->next = NULL;
bpList->hprc = NULL;
LeaveCriticalSection(&csThreadProcList);
}
void
AddBpToList(
PBREAKPOINT pbp
)
{
assert(bpList);
EnterCriticalSection(&csThreadProcList);
pbp->next = bpList->next;
bpList->next = pbp;
LeaveCriticalSection(&csThreadProcList);
}
PBREAKPOINT
FindBpForWalk(
PVOID pWalk
)
{
PBREAKPOINT pbp;
EnterCriticalSection(&csThreadProcList);
pbp = bpList;
while (pbp) {
if (IsWalkInGroup(pbp->hWalk, pWalk)) {
break;
}
pbp = pbp->next;
}
LeaveCriticalSection(&csThreadProcList);
return pbp;
}
PBREAKPOINT
SetWP(
HPRCX hprc,
HTHDX hthd,
BPTP bptype,
BPNS bpnotify,
ADDR addr
)
{
return (PBREAKPOINT)0;
}