|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
debug.c
Abstract:
This file contains code to manage software breakpoints
Author:
Neil Sandlin (neilsa) 1-Nov-1995
Revision History:
--*/
#include <precomp.h>
#pragma hdrstop
#include <dpmi.h>
#include <dbgsvc.h>
#include <dbginfo.h>
#include <stdio.h>
#define BREAKPOINT_CLEAR 1
#define BREAKPOINT_DISABLE 2
#define BREAKPOINT_ENABLE 3
#define VDMBP_ARRAY "ntvdmd!VdmBreakPoints"
VDM_BREAKPOINT VdmBPCache[MAX_VDM_BREAKPOINTS] = {0}; // BP zero is reserved for internal use
#define TEMP_BP 0
BOOL LoadBreakPointCache( VOID ) { ULONG lpAddress; lpAddress = (*GetExpression)(VDMBP_ARRAY);
if (!lpAddress) { PRINTF("Could not find symbol %s\n",VDMBP_ARRAY); return FALSE; }
if (!READMEM((PVOID)lpAddress, &VdmBPCache, sizeof(VdmBPCache))) { PRINTF("Error reading BP memory\n"); return FALSE; } return TRUE; }
BOOL FlushBreakPointCache( VOID ) { ULONG lpAddress; lpAddress = (*GetExpression)(VDMBP_ARRAY);
if (!lpAddress) { PRINTF("Could not find symbol %s\n",VDMBP_ARRAY); return FALSE; }
if (!WRITEMEM((PVOID)lpAddress, &VdmBPCache, sizeof(VdmBPCache))) { PRINTF("Error writing BP memory\n"); return FALSE; } return TRUE; }
BOOL IsVdmBreakPoint( USHORT selector, ULONG offset, BOOL bProt, PULONG pBpNum, PUCHAR pBpData ) //
// Callers of this function must first call LoadBreakPointCache()
//
{ ULONG BPNum;
for (BPNum = 0; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
if ((VdmBPCache[BPNum].Flags & VDMBP_SET) && (VdmBPCache[BPNum].Seg == selector) && (VdmBPCache[BPNum].Offset == offset)) {
if ((bProt && ~(VdmBPCache[BPNum].Flags & VDMBP_V86)) || (~bProt && (VdmBPCache[BPNum].Flags & VDMBP_V86))) { *pBpNum = BPNum; *pBpData = VdmBPCache[BPNum].Opcode; return TRUE; } } } return FALSE; }
VOID DisableBreakPoint( VDM_BREAKPOINT *pBP ) { int mode; ULONG lpAddress; BYTE byte;
if (!(pBP->Flags & VDMBP_ENABLED)) { // already not enabled
return; }
pBP->Flags &= ~VDMBP_ENABLED;
if (pBP->Flags & VDMBP_PENDING) { pBP->Flags &= ~VDMBP_PENDING; return; }
if (pBP->Flags & VDMBP_V86) { mode = V86_MODE; } else { mode = PROT_MODE; }
lpAddress = GetInfoFromSelector(pBP->Seg, mode, NULL) + GetIntelBase() + pBP->Offset;
if (READMEM((PVOID)lpAddress, &byte, 1)) { if (byte == 0xcc) { WRITEMEM((PVOID)lpAddress, &pBP->Opcode, 1); } }
pBP->Flags |= VDMBP_FLUSH; pBP->Flags &= ~VDMBP_PENDING;
#ifndef i386
if (!InVdmPrompt()) { PRINTF("\n***Warning: command not issued from VDM> prompt.\nOpcode has not been flushed!\n\n"); } #endif
}
VOID EnableBreakPoint( VDM_BREAKPOINT *pBP ) { int mode; ULONG lpAddress; BYTE byte;
if (pBP->Flags & VDMBP_ENABLED) { return; }
EnableDebuggerBreakpoints();
if (pBP->Flags & VDMBP_V86) { mode = V86_MODE; } else { mode = PROT_MODE; }
lpAddress = GetInfoFromSelector(pBP->Seg, mode, NULL) + GetIntelBase() + pBP->Offset;
if (READMEM((PVOID)lpAddress, &byte, 1)) { if (byte != 0xcc) { static BYTE bpOp = 0xcc;
WRITEMEM((PVOID)lpAddress, &bpOp, 1); pBP->Opcode = byte; } } else {
PRINTF("Error enabling breakpoint at %04X:%08X\n", pBP->Seg, pBP->Offset); return; }
pBP->Flags |= (VDMBP_ENABLED | VDMBP_FLUSH); pBP->Flags &= ~VDMBP_PENDING;
#ifndef i386
if (!InVdmPrompt()) { PRINTF("\n***Warning: command not issued from VDM> prompt.\nBP has not been flushed!\n\n"); } #endif
}
VOID UpdateBreakPoint( int Cmd )
{ int BPNum; int count = 0; BOOL DoBreakPoints[MAX_VDM_BREAKPOINTS] = {FALSE}; BOOL DoAll = FALSE;
if (!LoadBreakPointCache()) { return; }
while (GetNextToken()) { if (*lpArgumentString == '*') { DoAll = TRUE; count++; break; } if(sscanf(lpArgumentString, "%d", &BPNum) != 1 || BPNum >= MAX_VDM_BREAKPOINTS) { PRINTF("Invalid breakpoint - %d\n", BPNum); return; } DoBreakPoints[BPNum] = TRUE; count++; SkipToNextWhiteSpace(); }
if (!count) { PRINTF("Please specify a breakpoint #\n"); return; }
for (BPNum=0; BPNum<MAX_VDM_BREAKPOINTS; BPNum++) {
if (!DoBreakPoints[BPNum] && !DoAll) { continue; }
if (!(VdmBPCache[BPNum].Flags & VDMBP_SET)) { continue; } switch(Cmd) {
case BREAKPOINT_CLEAR:
if (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) { DisableBreakPoint(&VdmBPCache[BPNum]); } VdmBPCache[BPNum].Flags &= ~VDMBP_SET; break;
case BREAKPOINT_DISABLE:
if (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) { DisableBreakPoint(&VdmBPCache[BPNum]); } break;
case BREAKPOINT_ENABLE:
if (!(VdmBPCache[BPNum].Flags & VDMBP_ENABLED)) { EnableBreakPoint(&VdmBPCache[BPNum]); } break;
} }
FlushBreakPointCache(); }
VOID bc( CMD_ARGLIST ) { CMD_INIT(); UpdateBreakPoint(BREAKPOINT_CLEAR); }
VOID bd( CMD_ARGLIST ) { CMD_INIT(); UpdateBreakPoint(BREAKPOINT_DISABLE); }
VOID be( CMD_ARGLIST ) { CMD_INIT(); UpdateBreakPoint(BREAKPOINT_ENABLE); }
VOID bl( CMD_ARGLIST ) { int BPNum; int mode; DWORD dist; CHAR sym_text[255];
CMD_INIT();
if (!LoadBreakPointCache()) { return; }
for (BPNum = 0; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
if (VdmBPCache[BPNum].Flags & VDMBP_SET) {
PRINTF("%d %s%s%s ", BPNum, (VdmBPCache[BPNum].Flags & VDMBP_ENABLED) ? "e" : "d", (VdmBPCache[BPNum].Flags & VDMBP_FLUSH) ? "f" : " ", (VdmBPCache[BPNum].Flags & VDMBP_PENDING) ? "p" : " ");
if (VdmBPCache[BPNum].Flags & VDMBP_V86) { mode = V86_MODE; PRINTF("&"); } else { mode = PROT_MODE; PRINTF("#"); }
PRINTF("%04X:", VdmBPCache[BPNum].Seg);
if (VdmBPCache[BPNum].Offset > 0xffff) { PRINTF("%08X", VdmBPCache[BPNum].Offset); } else { PRINTF("%04X", VdmBPCache[BPNum].Offset); }
PRINTF(" %04X:***", VdmBPCache[BPNum].Count);
if (FindSymbol(VdmBPCache[BPNum].Seg, VdmBPCache[BPNum].Offset, sym_text, &dist, BEFORE, mode )) {
if ( dist == 0 ) { PRINTF(" %s", sym_text ); } else { PRINTF(" %s+0x%lx", sym_text, dist ); } } PRINTF("\n"); } } }
VOID bp( CMD_ARGLIST ) { #ifdef _X86_
CMD_INIT(); PRINTF("Error- Use native BP command on x86 platforms\n"); #else
int BPNum; VDMCONTEXT ThreadContext; WORD selector; ULONG offset; USHORT count = 1; int mode; USHORT flags = 0;
CMD_INIT();
if (!LoadBreakPointCache()) { return; }
mode = GetContext( &ThreadContext );
if (!GetNextToken()) { PRINTF("Please enter an address\n"); return; }
if (!ParseIntelAddress(&mode, &selector, &offset)) { return; }
if (mode == V86_MODE) { flags = VDMBP_V86; }
//
// first see if it's set already
//
for (BPNum = 0; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
if (VdmBPCache[BPNum].Flags & VDMBP_SET) { if ((VdmBPCache[BPNum].Seg == selector) && (VdmBPCache[BPNum].Offset == offset) && !(VdmBPCache[BPNum].Flags ^ flags)) {
VdmBPCache[BPNum].Count = count;
if (!(VdmBPCache[BPNum].Flags & VDMBP_ENABLED)) { EnableBreakPoint(&VdmBPCache[BPNum]); }
FlushBreakPointCache(); PRINTF("breakpoint %d redefined\n", BPNum); return;
} } }
//
// Not found, set a new one
for (BPNum = 1; BPNum < MAX_VDM_BREAKPOINTS; BPNum++) {
if (!(VdmBPCache[BPNum].Flags & (VDMBP_SET | VDMBP_FLUSH))) { VdmBPCache[BPNum].Seg = selector; VdmBPCache[BPNum].Offset = offset; VdmBPCache[BPNum].Count = count; VdmBPCache[BPNum].Flags = VDMBP_SET | flags; EnableBreakPoint(&VdmBPCache[BPNum]);
FlushBreakPointCache(); return;
} } #endif
}
|