603 lines
15 KiB
C
603 lines
15 KiB
C
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
vrdebug.h
|
|
|
|
Abstract:
|
|
|
|
Contains defines for Vdm Redir Debugging info
|
|
|
|
Author:
|
|
|
|
Richard L Firth (rfirth) 13-Feb-1992
|
|
|
|
Notes:
|
|
|
|
Add new category for each new group of functions added for which external
|
|
debug control is required
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
//
|
|
// COMPILE-time debugging options:
|
|
// definitions for debug flags. Each bit enables diagnostic printing/specific
|
|
// debugging of corresponding module. Also overridden at run-time in DBG
|
|
// version by having these flags in the VR= environment variable
|
|
//
|
|
|
|
#define DEBUG_MAILSLOT 0x00000001L // general Mailslots
|
|
#define DEBUG_NAMEPIPE 0x00000002L // general Named Pipe
|
|
#define DEBUG_NETAPI 0x00000004L // general NETAPI
|
|
#define DEBUG_NETBIOS 0x00000008L // general NETBIOS
|
|
#define DEBUG_DLC 0x00000010L // general DLC
|
|
#define DEBUG_DOS_CCB_IN 0x00000020L // input DOS CCBs & parameter tables
|
|
#define DEBUG_DOS_CCB_OUT 0x00000040L // output DOS CCBs & parameter tables
|
|
#define DEBUG_NT_CCB_IN 0x00000080L // input NT CCBs & parameter tables
|
|
#define DEBUG_NT_CCB_OUT 0x00000100L // output NT CCBs & parameter tables
|
|
#define DEBUG_DLC_BUFFERS 0x00000200L // DLC buffer pools
|
|
#define DEBUG_DLC_TX_DATA 0x00000400L // DLC transmit data
|
|
#define DEBUG_DLC_RX_DATA 0x00000800L // DLC received data
|
|
#define DEBUG_DLC_ASYNC 0x00001000L // DLC async call-backs
|
|
#define DEBUG_TRANSACT_TX 0x00002000L // Transaction send data buffer(s)
|
|
#define DEBUG_TRANSACT_RX 0x00004000L // Transaction receive data buffer(s)
|
|
#define DEBUG_DLC_ALLOC 0x00008000L // dump alloc/free calls in DLC
|
|
#define DEBUG_READ_COMPLETE 0x00010000L // dump CCB when READ completes
|
|
#define DEBUG_ASYNC_EVENT 0x00020000L // dump asynchronous event info
|
|
#define DEBUG_CMD_COMPLETE 0x00040000L // dump command complete event info
|
|
#define DEBUG_TX_COMPLETE 0x00080000L // dump transmit complete event info
|
|
#define DEBUG_RX_DATA 0x00100000L // dump data received event info
|
|
#define DEBUG_STATUS_CHANGE 0x00200000L // dump DLC status change event info
|
|
#define DEBUG_EVENT_QUEUE 0x00400000L // dump PutEvent, GetEvent and PeekEvent
|
|
#define DEBUG_DOUBLE_TICKS 0x00800000L // multiply timer tick counts by 2
|
|
#define DEBUG_DUMP_FREE_BUF 0x01000000L // dump buffer header on BUFFER.FREE
|
|
#define DEBUG_CRITSEC 0x02000000L // dump enter/leave critical section info
|
|
#define DEBUG_HW_INTERRUPTS 0x04000000L // dump simulated hardware interrupt info
|
|
#define DEBUG_CRITICAL 0x08000000L // where #ifdef CRITICAL_DEBUGGING used to be
|
|
#define DEBUG_TIME 0x10000000L // display relative time of events
|
|
#define DEBUG_TO_FILE 0x20000000L // dump output to file VRDEBUG.LOG
|
|
#define DEBUG_DLL 0x40000000L // general DLL stuff - init, terminate
|
|
#define DEBUG_BREAKPOINT 0x80000000L // break everywhere there's a DEBUG_BREAK
|
|
|
|
#define DEBUG_DOS_CCB (DEBUG_DOS_CCB_IN | DEBUG_DOS_CCB_OUT)
|
|
|
|
#define VRDEBUG_FILE "VRDEBUG.LOG"
|
|
|
|
#if DBG
|
|
#include <stdio.h>
|
|
extern DWORD VrDebugFlags;
|
|
extern FILE* hVrDebugLog;
|
|
|
|
extern VOID DbgOut(LPSTR, ...);
|
|
|
|
#define IF_DEBUG(type) if (VrDebugFlags & DEBUG_##type)
|
|
#define DEBUG_BREAK() IF_DEBUG(BREAKPOINT) { \
|
|
DbgPrint("BP %s.%d\n", __FILE__, __LINE__); \
|
|
DbgBreakPoint(); \
|
|
}
|
|
#define DBGPRINT DbgOut
|
|
#define DPUT(s) DBGPRINT(s)
|
|
#define DPUT1(s, a) DBGPRINT(s, a)
|
|
#define DPUT2(s, a, b) DBGPRINT(s, a, b)
|
|
#define DPUT3(s, a, b, c) DBGPRINT(s, a, b, c)
|
|
#define DPUT4(s, a, b, c, d) DBGPRINT(s, a, b, c, d)
|
|
#define DPUT5(s, a, b, c, d, e) DBGPRINT(s, a, b, c, d, e)
|
|
#define CRITDUMP(x) DbgPrint x
|
|
#define DUMPCCB DumpCcb
|
|
#else
|
|
#define IF_DEBUG(type) if (0)
|
|
#define DEBUG_BREAK()
|
|
#define DBGPRINT
|
|
#define DPUT(s)
|
|
#define DPUT1(s, a)
|
|
#define DPUT2(s, a, b)
|
|
#define DPUT3(s, a, b, c)
|
|
#define DPUT4(s, a, b, c, d)
|
|
#define DPUT5(s, a, b, c, d, e)
|
|
#define CRITDUMP(x)
|
|
#define DUMPCCB
|
|
#endif
|
|
|
|
//
|
|
// defaults
|
|
//
|
|
|
|
#define DEFAULT_STACK_DUMP 32
|
|
|
|
//
|
|
// numbers
|
|
//
|
|
|
|
#define NUMBER_OF_VR_GROUPS 5
|
|
#define NUMBER_OF_CPU_REGISTERS 14
|
|
#define MAX_ID_LEN 40
|
|
#define MAX_DESC_LEN 256
|
|
|
|
//
|
|
// environment strings - shortened since they all go through to dos & dos can
|
|
// only handle 1K of environment
|
|
//
|
|
|
|
#define ES_VRDEBUG "VRDBG" // "__VRDEBUG"
|
|
#define ES_MAILSLOT "MS" // "MAILSLOT"
|
|
#define ES_NAMEPIPE "NP" // "NAMEPIPE"
|
|
#define ES_LANMAN "LM" // "LANMAN"
|
|
#define ES_NETBIOS "NB" // "NETBIOS"
|
|
#define ES_DLC "DLC" // "DLC"
|
|
|
|
//
|
|
// diagnostic controls - in same numerical order as TOKEN!!!
|
|
//
|
|
|
|
#define DC_BREAK "BRK" // "BREAK"
|
|
#define DC_DISPLAYNAME "DN" // "DISPLAYNAME"
|
|
#define DC_DLC ES_DLC
|
|
#define DC_DUMPMEM "DM" // "DUMPMEM"
|
|
#define DC_DUMPREGS "DR" // "DUMPREGS"
|
|
#define DC_DUMPSTACK "DK" // "DUMPSTACK"
|
|
#define DC_DUMPSTRUCT "DS" // "DUMPSTRUCT"
|
|
#define DC_ERROR "E" // "ERROR"
|
|
#define DC_ERRORBREAK "EB" // "ERRORBREAK"
|
|
#define DC_INFO "I" // "INFO"
|
|
#define DC_LANMAN ES_LANMAN
|
|
#define DC_MAILSLOT ES_MAILSLOT
|
|
#define DC_NAMEPIPE ES_NAMEPIPE
|
|
#define DC_NETBIOS ES_NETBIOS
|
|
#define DC_PAUSEBREAK "PB" // "PAUSEBREAK"
|
|
#define DC_WARN "W" // "WARN"
|
|
|
|
//
|
|
// diagnostic categories (groups)
|
|
//
|
|
|
|
#define DG_ALL -1L // catch first enabled set
|
|
#define DG_NONE 0 // no category
|
|
#define DG_MAILSLOT 0x00000001L
|
|
#define DG_NAMEPIPE 0x00000002L
|
|
#define DG_LANMAN 0x00000004L
|
|
#define DG_NETBIOS 0x00000008L
|
|
#define DG_DLC 0x00000010L
|
|
|
|
//
|
|
// diagnostic index (in VrDiagnosticGroups array)
|
|
//
|
|
|
|
#define DI_MAILSLOT 0
|
|
#define DI_NAMEPIPE 1
|
|
#define DI_LANMAN 2
|
|
#define DI_NETBIOS 3
|
|
#define DI_DLC 4
|
|
|
|
//
|
|
// diagnostic control manifests
|
|
//
|
|
|
|
#define DM_INFORMATION 0x00010000L // display all info, warning and error messages
|
|
#define DM_WARNING 0x00020000L // display warning and error messages
|
|
#define DM_ERROR 0x00030000L // display error messages only
|
|
#define DM_ERRORBREAK 0x00100000L // DbgBreakPoint() on error
|
|
#define DM_PAUSEBREAK 0x00200000L // DbgBreakPoint() on pause (wait for developer)
|
|
#define DM_DUMPREGS 0x00800000L // dump x86 registers when routine entered
|
|
#define DM_DUMPREGSDBG 0x01000000L // dump x86 registers when routine entered, debug style
|
|
#define DM_DUMPMEM 0x02000000L // dump DOS memory when routine entered
|
|
#define DM_DUMPSTACK 0x04000000L // dump DOS stack when routine entered
|
|
#define DM_DUMPSTRUCT 0x08000000L // dump a structure when routine entered
|
|
#define DM_DISPLAYNAME 0x10000000L // display the function name
|
|
#define DM_BREAK 0x80000000L // break when routine entered
|
|
|
|
#define DM_DISPLAY_MASK 0x000f0000L
|
|
|
|
//
|
|
// enumerated types
|
|
//
|
|
|
|
////
|
|
//// GPREG - General Purpose REGisters
|
|
////
|
|
//
|
|
//typedef enum {
|
|
// AX = 0,
|
|
// BX,
|
|
// CX,
|
|
// DX,
|
|
// SI,
|
|
// DI,
|
|
// BP,
|
|
// SP
|
|
//} GPREG;
|
|
//
|
|
////
|
|
//// SEGREG - SEGment REGisters
|
|
////
|
|
//
|
|
//typedef enum {
|
|
// CS = 8,
|
|
// DS,
|
|
// ES,
|
|
// SS
|
|
//} SEGREG;
|
|
//
|
|
////
|
|
//// SPREG - Special Purpose REGisters
|
|
////
|
|
//
|
|
//typedef enum {
|
|
// IP = 12,
|
|
// FLAGS
|
|
//} SPREG;
|
|
//
|
|
//typedef union {
|
|
// SEGREG SegReg;
|
|
// GPREG GpReg;
|
|
// SPREG SpReg;
|
|
//} REGISTER;
|
|
|
|
typedef enum {
|
|
AX = 0,
|
|
BX = 1,
|
|
CX = 2,
|
|
DX = 3,
|
|
SI = 4,
|
|
DI = 5,
|
|
BP = 6,
|
|
SP = 7,
|
|
CS = 8,
|
|
DS = 9,
|
|
ES = 10,
|
|
SS = 11,
|
|
IP = 12,
|
|
FLAGS = 13
|
|
} REGISTER;
|
|
|
|
//
|
|
// REGVAL - keeps a 16-bit value or a register specification, depending on
|
|
// sense of IsRegister
|
|
//
|
|
|
|
typedef struct {
|
|
BOOL IsRegister;
|
|
union {
|
|
REGISTER Register;
|
|
WORD Value;
|
|
} RegOrVal;
|
|
} REGVAL, *LPREGVAL;
|
|
|
|
//
|
|
// structures
|
|
//
|
|
|
|
//
|
|
// CONTROL - keeps correspondence between control keyword and control flag
|
|
//
|
|
|
|
typedef struct {
|
|
char* Keyword;
|
|
DWORD Flag;
|
|
} CONTROL;
|
|
|
|
//
|
|
// OPTION - keeps correspondence between diagnostic option and option type
|
|
//
|
|
|
|
typedef struct {
|
|
char* Keyword;
|
|
DWORD Flag;
|
|
} OPTION;
|
|
|
|
//
|
|
// REGDEF - defines a register - keeps correspondence between name and type
|
|
//
|
|
|
|
typedef struct {
|
|
char RegisterName[3];
|
|
REGISTER Register;
|
|
} REGDEF, *LPREGDEF;
|
|
|
|
//
|
|
// GROUPDEF - keeps correspondence between group name and index in
|
|
// VrDiagnosticGroups array
|
|
//
|
|
|
|
typedef struct {
|
|
char* Name;
|
|
DWORD Index;
|
|
} GROUPDEF;
|
|
|
|
//
|
|
// MEMORY_INFO - for each each memory dump we keep a record of its type, length
|
|
// and starting address
|
|
//
|
|
|
|
typedef struct _MEMORY_INFO {
|
|
struct _MEMORY_INFO* Next;
|
|
REGVAL Segment;
|
|
REGVAL Offset;
|
|
REGVAL DumpCount;
|
|
BYTE DumpType;
|
|
} MEMORY_INFO, *LPMEMORY_INFO;
|
|
|
|
//
|
|
// STRUCT_INFO - for each structure to be dumped we keep record of the segment
|
|
// and offset registers and the string which describes the structure to be
|
|
// dumped. The descriptor is similar to (but NOT THE SAME AS) the Rap
|
|
// descriptor stuff
|
|
//
|
|
|
|
typedef struct _STRUCT_INFO {
|
|
struct _STRUCTINFO* Next;
|
|
char StructureDescriptor[MAX_DESC_LEN+1];
|
|
REGVAL Segment;
|
|
REGVAL Offset;
|
|
} STRUCT_INFO, *LPSTRUCT_INFO;
|
|
|
|
//
|
|
// DIAGNOSTIC_INFO - information common to GROUP_DIAGNOSTIC and FUNCTION_DIAGNOSTIC
|
|
//
|
|
|
|
typedef struct {
|
|
DWORD OnControl;
|
|
DWORD OffControl;
|
|
MEMORY_INFO StackInfo; // special case of MemoryInfo
|
|
MEMORY_INFO MemoryInfo;
|
|
STRUCT_INFO StructInfo;
|
|
} DIAGNOSTIC_INFO, *LPDIAGNOSTIC_INFO;
|
|
|
|
//
|
|
// GROUP_DIAGNOSTIC - because the groups are predefined, we don't keep any
|
|
// name information, or a list - just NUMBER_OF_VR_GROUPS elements in an
|
|
// array of GROUP_DIAGNOSTIC structures
|
|
//
|
|
|
|
typedef struct {
|
|
char GroupName[MAX_ID_LEN+1];
|
|
DIAGNOSTIC_INFO Diagnostic;
|
|
} GROUP_DIAGNOSTIC, *LPGROUP_DIAGNOSTIC;
|
|
|
|
//
|
|
// FUNCTION_DIAGNOSTIC - if we want to diagnose a particular named function,
|
|
// then we generate one of these. We keep a (unsorted) list of these if a
|
|
// function description is parsed from the environment string(s)
|
|
//
|
|
|
|
typedef struct _FUNCTION_DIAGNOSTIC {
|
|
struct _FUNCTION_DIAGNOSTIC* Next;
|
|
char FunctionName[MAX_ID_LEN+1];
|
|
DIAGNOSTIC_INFO Diagnostic;
|
|
} FUNCTION_DIAGNOSTIC, *LPFUNCTION_DIAGNOSTIC;
|
|
|
|
//
|
|
// structure descriptor characters (general purpose data descriptors)
|
|
//
|
|
|
|
#define SD_BYTE 'B' // 8-bits, displayed as hex (0a)
|
|
#define SD_WORD 'W' // 16-bits, displayed as hex (0abc)
|
|
#define SD_DWORD 'D' // 32-bits, displayed as hex (0abc1234)
|
|
#define SD_POINTER 'P' // 32-bits, displayed as pointer (0abc:1234)
|
|
#define SD_ASCIZ 'A' // asciz string, displayed as string "this is a string"
|
|
#define SD_ASCII 'a' // asciz pointer, displayed as pointer, string 0abc:1234 "this is a string"
|
|
#define SD_CHAR 'C' // ascii character, displayed as character 'c'
|
|
#define SD_NUM 'N' // 8-bits, displayed as unsigned byte (0 to 255)
|
|
#define SD_INT 'I' // 16-bits, displayed as unsigned word (0 to 65,535)
|
|
#define SD_LONG 'L' // 32-bits, displayed as unsigned long (0 to 4,294,967,295)
|
|
#define SD_SIGNED '-' // convert I,L,N to signed
|
|
#define SD_DELIM ':' // name delimiter
|
|
#define SD_FIELDSEP ';' // separates named fields
|
|
#define SD_NAMESEP '/' // separates structure name from fields
|
|
|
|
#define SD_CHARS {SD_BYTE, \
|
|
SD_WORD, \
|
|
SD_DWORD, \
|
|
SD_POINTER, \
|
|
SD_ASCIZ, \
|
|
SD_ASCII,\
|
|
SD_CHAR, \
|
|
SD_NUM, \
|
|
SD_INT, \
|
|
SD_LONG, \
|
|
SD_SIGNED}
|
|
|
|
#define MD_CHARS {SD_BYTE, SD_WORD, SD_DWORD, SD_POINTER}
|
|
|
|
//
|
|
// token stuff
|
|
//
|
|
|
|
//
|
|
// TOKEN - enumerated, alphabetically ordered tokens
|
|
//
|
|
|
|
typedef enum {
|
|
TLEFTPAREN = -6, // (
|
|
TRIGHTPAREN = -5, // )
|
|
TREGISTER = -4,
|
|
TNUMBER = -3,
|
|
TEOS = -2, // end of string
|
|
TUNKNOWN = -1, // unknown lexeme, assume routine name?
|
|
|
|
//
|
|
// tokens from here on down are also the index into DiagnosticTokens which
|
|
// describe them
|
|
//
|
|
|
|
TBREAK = 0,
|
|
TDISPLAYNAME,
|
|
TDLC,
|
|
TDUMPMEM,
|
|
TDUMPREGS,
|
|
TDUMPSTACK,
|
|
TDUMPSTRUCT,
|
|
TERROR,
|
|
TERRORBREAK,
|
|
TINFO,
|
|
TLANMAN,
|
|
TMAILSLOT,
|
|
TNAMEPIPE,
|
|
TNETBIOS,
|
|
TPAUSEBREAK,
|
|
TWARN
|
|
} TOKEN;
|
|
|
|
//
|
|
// TIB (Token Info Bucket) - Contains info describing token found. Only filled
|
|
// in when we find an identifier, number or a register
|
|
//
|
|
|
|
typedef struct {
|
|
LPSTR TokenStream;
|
|
TOKEN Token;
|
|
union {
|
|
REGVAL RegVal;
|
|
char Id[MAX_DESC_LEN+1];
|
|
} RegValOrId;
|
|
} TIB, *LPTIB;
|
|
|
|
//
|
|
// DEBUG_TOKEN - maps from lexeme to token
|
|
//
|
|
|
|
typedef struct {
|
|
char* TokenString;
|
|
TOKEN Token;
|
|
} DEBUG_TOKEN;
|
|
|
|
//
|
|
// what to expect when parsing strings
|
|
//
|
|
|
|
#define EXPECTING_NOTHING 0x00
|
|
#define EXPECTING_REGVAL 0x01
|
|
#define EXPECTING_MEMDESC 0x02
|
|
#define EXPECTING_STRUCTDESC 0x04
|
|
#define EXPECTING_LEFTPAREN 0x08
|
|
#define EXPECTING_RIGHTPAREN 0x10
|
|
#define EXPECTING_EOS 0x20
|
|
#define EXPECTING_NO_ARGS 0x40
|
|
|
|
//
|
|
// data (defined in vrdebug.c)
|
|
//
|
|
|
|
//
|
|
// VrDiagnosticGroups - an array of GROUP_DIAGNOSTIC structures
|
|
//
|
|
|
|
GROUP_DIAGNOSTIC VrDiagnosticGroups[NUMBER_OF_VR_GROUPS];
|
|
|
|
//
|
|
// FunctionList - linked list of FUNCTION_DIAGNOSTIC structures
|
|
//
|
|
|
|
LPFUNCTION_DIAGNOSTIC FunctionList;
|
|
|
|
//
|
|
// prototypes (in vrdebug.c)
|
|
//
|
|
|
|
VOID
|
|
VrDebugInit(
|
|
VOID
|
|
);
|
|
|
|
LPDIAGNOSTIC_INFO
|
|
VrDiagnosticEntryPoint(
|
|
IN LPSTR FunctionName,
|
|
IN DWORD FunctionCategory,
|
|
OUT LPDIAGNOSTIC_INFO Info
|
|
);
|
|
|
|
VOID
|
|
VrPauseBreak(
|
|
LPDIAGNOSTIC_INFO Info
|
|
);
|
|
|
|
VOID
|
|
VrErrorBreak(
|
|
LPDIAGNOSTIC_INFO Info
|
|
);
|
|
|
|
VOID
|
|
VrPrint(
|
|
IN DWORD Level,
|
|
IN LPDIAGNOSTIC_INFO Context,
|
|
IN LPSTR Format,
|
|
IN ...
|
|
);
|
|
|
|
VOID
|
|
VrDumpRealMode16BitRegisters(
|
|
IN BOOL DebugStyle
|
|
);
|
|
|
|
VOID
|
|
VrDumpDosMemory(
|
|
IN BYTE Type,
|
|
IN DWORD Iterations,
|
|
IN WORD Segment,
|
|
IN WORD Offset
|
|
);
|
|
|
|
VOID
|
|
VrDumpDosMemoryStructure(
|
|
IN LPSTR Descriptor,
|
|
IN WORD Segment,
|
|
IN WORD Offset
|
|
);
|
|
|
|
//
|
|
//VOID
|
|
//VrDumpDosStack(
|
|
// IN DWORD Depth
|
|
// )
|
|
//
|
|
///*++
|
|
//
|
|
//Routine Description:
|
|
//
|
|
// Dumps <Depth> words from the Vdm stack, as addressed by getSS():getSP().
|
|
// Uses VrDumpDosMemory to dump stack contents
|
|
//
|
|
//Arguments:
|
|
//
|
|
// Depth - number of 16-bit words to dump from DOS memory stack
|
|
//
|
|
//Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--*/
|
|
//
|
|
|
|
#define VrDumpDosStack(Depth) VrDumpDosMemory('W', Depth, getSS(), getSP())
|
|
|
|
//
|
|
// macros used in routines to be diagnosed
|
|
//
|
|
|
|
#if DBG
|
|
#define DIAGNOSTIC_ENTRY VrDiagnosticEntryPoint
|
|
#define DIAGNOSTIC_EXIT VrDiagnosticExitPoint
|
|
#define BREAK_ON_PAUSE VrPauseBreak
|
|
#define BREAK_ON_ERROR VrErrorBreak
|
|
//#define INFORM(s, ...) VrPrint(DM_INFORMATION, s, ...)
|
|
//#define WARN(s, ...) VrPrint(DM_WARNING, s, ...)
|
|
//#define ERROR(s, ...) VrPrint(DM_ERROR, s, ...)
|
|
|
|
#else
|
|
|
|
//
|
|
// macros used in routines to be diagnosed - don't expand to anything in non-debug
|
|
//
|
|
|
|
#define DIAGNOSTIC_ENTRY
|
|
#define DIAGNOSTIC_EXIT
|
|
#define BREAK_ON_PAUSE
|
|
#define BREAK_ON_ERROR
|
|
//#define INFORM
|
|
//#define WARN
|
|
//#define ERROR
|
|
#endif
|