windows-nt/Source/XPSP1/NT/base/mvdm/vdmexts/debug.c
2020-09-26 16:20:57 +08:00

452 lines
9 KiB
C

/*++
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;
}
sscanf(lpArgumentString, "%d", &BPNum);
if (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
}