46#pragma data_seg(".CRT$XCB")
47void *Debug::PreStatic=&Debug::PreStaticInit;
48#pragma data_seg(".CRT$XCY")
49void *Debug::PostStatic=&Debug::PostStaticInit;
52Debug::LogDescription::LogDescription(
const char *fileOrGroup,
const char *description)
54 Debug::Instance.AddLogGroup(fileOrGroup,description);
61unsigned Debug::curStackFrame;
73void Debug::PreStaticInit(
void)
84 Instance.hrTranslators=
NULL;
85 Instance.numHrTranslators=0;
86 Instance.firstIOFactory=
NULL;
87 Instance.firstCmdGroup=
NULL;
88 memset(Instance.frameHash,0,
sizeof(Instance.frameHash));
89 Instance.nextUnusedFrameHash=
NULL;
90 Instance.numAvailableFrameHash=0;
91 Instance.firstLogGroup=
NULL;
92 memset(Instance.ioBuffer,0,
sizeof(Instance.ioBuffer));
94 *Instance.curSource=0;
95 Instance.disableAssertsEtc=0;
96 Instance.curFrameEntry=
NULL;
97 Instance.firstPatternEntry=
NULL;
98 Instance.lastPatternEntry=
NULL;
99 *Instance.curCommandGroup=0;
100 Instance.alwaysFlush=
false;
101 Instance.timeStamp=
false;
103 Instance.m_fillChar=
' ';
109void Debug::PostStaticInit(
void)
124 GetModuleFileName(
NULL,ioBuffer,
sizeof(ioBuffer));
125 char *
q=strrchr(ioBuffer,
'.');
128 HANDLE h=CreateFile(ioBuffer,GENERIC_READ,0,
NULL,OPEN_EXISTING,
129 FILE_ATTRIBUTE_NORMAL,
NULL);
130 if (h==INVALID_HANDLE_VALUE)
131 h=CreateFile(
"default.dbgcmd",GENERIC_READ,0,
NULL,OPEN_EXISTING,
132 FILE_ATTRIBUTE_NORMAL,
NULL);
133 if (h!=INVALID_HANDLE_VALUE)
136 unsigned long ioCur=0,ioUsed=0,cmdCur=0;
137 ReadFile(h,ioBuffer,
sizeof(ioBuffer),&ioUsed,
NULL);
142 ReadFile(h,ioBuffer,
sizeof(ioBuffer),&ioUsed,
NULL);
145 if (ioCur==ioUsed||ioBuffer[ioCur]==
'\n'||ioBuffer[ioCur]==
'\r')
149 Instance.ExecCommand(cmdBuffer,cmdBuffer+cmdCur);
158 if (cmdCur<
sizeof(cmdBuffer))
159 cmdBuffer[cmdCur++]=ioBuffer[ioCur];
171 const char *
q=strchr(p,
'\n');
176 Instance.ExecCommand(p,
q);
188 "\nYou are using an older version of the DBGHELP.DLL library.\n"
189 "Please update to the newest available version in order to\n"
190 "get reliable stack and symbol information.\n\n";
195 "Hint: The DLL got loaded as:\n" << buf <<
"\n" <<
RepeatChar(
'=',79) <<
"\n\n";
198 Instance.FlushOutput(
false);
202void Debug::StaticExit(
void)
208 Instance.FlushOutput();
209 for (IOFactoryListEntry *io=Instance.firstIOFactory;io;io=io->next)
217 for (CmdInterfaceListEntry *cmd=Instance.firstCmdGroup;cmd;cmd=cmd->next)
220 cmd->cmdif->Delete();
230 memset(help,c.m_char,10);
231 while ((c.m_count-=10)>=0)
234 while (c.m_count-->0)
235 AddOutput(&c.m_char,1);
239Debug::Format::Format(
const char *format, ...)
243 _vsnprintf(m_buffer,
sizeof(m_buffer)-1,format,va);
252static void LocalSETranslator(
unsigned,
struct _EXCEPTION_POINTERS *pExPtrs)
260 _set_se_translator(LocalSETranslator);
267 if (Instance.disableAssertsEtc)
281 FrameHashEntry *e=Instance.LookupFrame(curStackFrame);
287 if (e->status==Unknown)
288 Instance.UpdateFrameStatus(*e);
291 return e->status==Skip;
297 ++Instance.disableAssertsEtc;
301 Instance.FlushOutput();
305 Instance.curFrameEntry=Instance.GetFrameEntry(curStackFrame,FrameTypeAssert,file,line);
306 if (Instance.curFrameEntry->status==NoSkip)
309 Instance.curFrameEntry->fileOrGroup,
310 Instance.curFrameEntry->line);
311 ++Instance.curFrameEntry->hits;
315 const char *p=strstr(file,
"\\code\\");
318 Instance <<
"\n" <<
RepeatChar(
'=',80) <<
"\nAssertion failed in " << p <<
", line " << line
319 <<
",\nexpression " << expr;
335 if (curFrameEntry->hits>1)
336 (*this) <<
" (hit #" << curFrameEntry->hits <<
")";
343 const char *addInfo=
"\nPress 'abort' to abort the program,\n"
344 "'retry' for breaking into the debugger, or\n"
345 "'ignore' for ignoring this assertion for the\n"
346 "time being (stops logging this assertion as well).";
348 strcpy(help,ioBuffer[curType].
buffer+82);
349 strcat(help,addInfo);
352 if (curFrameEntry->hits==1)
355 if (m_stackWalk.StackWalk(sig))
369 int result=MessageBox(
NULL,help,
"Assertion failed",
370 MB_ABORTRETRYIGNORE|MB_ICONSTOP|MB_TASKMODAL|MB_SETFOREGROUND);
381 __ASSERT(strlen(curFrameEntry->fileOrGroup)<190);
382 wsprintf(help,
"%s(%i)",curFrameEntry->fileOrGroup,
383 curFrameEntry->line);
384 AddPatternEntry(FrameTypeAssert,
false,help);
385 curFrameEntry->status=Skip;
404 Instance <<
"Assert hit too often - turning check off.\n";
409 __ASSERT(strlen(curFrameEntry->fileOrGroup)<190);
410 wsprintf(help,
"%s(%i)",curFrameEntry->fileOrGroup,
411 curFrameEntry->line);
412 AddPatternEntry(FrameTypeAssert,
false,help);
414 curFrameEntry->status=Skip;
426 ++Instance.disableAssertsEtc;
430 Instance.FlushOutput();
434 Instance.curFrameEntry=Instance.GetFrameEntry(curStackFrame,FrameTypeCheck,file,line);
435 if (Instance.curFrameEntry->status==NoSkip)
437 ++Instance.curFrameEntry->hits;
439 Instance.curFrameEntry->fileOrGroup,
440 Instance.curFrameEntry->line);
444 const char *p=strstr(file,
"\\code\\");
447 Instance <<
"\n" <<
RepeatChar(
'=',80) <<
"\nCheck failed in " << p <<
", line " << line
448 <<
",\nexpression " << expr;
464 if (curFrameEntry->hits>1)
465 (*this) <<
" (hit #" << curFrameEntry->hits <<
")";
472 if (curFrameEntry->hits==1)
475 if (m_stackWalk.StackWalk(sig))
488 Instance <<
"Check hit too often - turning check off.\n";
493 __ASSERT(strlen(curFrameEntry->fileOrGroup)<190);
494 wsprintf(help,
"%s(%i)",curFrameEntry->fileOrGroup,
495 curFrameEntry->line);
496 AddPatternEntry(FrameTypeCheck,
false,help);
498 curFrameEntry->status=Skip;
509 ++Instance.disableAssertsEtc;
514 Instance.FlushOutput();
518 Instance.curFrameEntry=Instance.GetFrameEntry(curStackFrame,FrameTypeLog,fileOrGroup,0);
519 if (Instance.curFrameEntry->status==NoSkip)
521 ++Instance.curFrameEntry->hits;
526 strcmp(Instance.curSource,Instance.curFrameEntry->fileOrGroup))
527 Instance.FlushOutput();
531 Instance.curFrameEntry->fileOrGroup);
534 Instance.FlushOutput();
552 ++Instance.disableAssertsEtc;
556 Instance.FlushOutput();
560 Instance.curFrameEntry=Instance.GetFrameEntry(curStackFrame,FrameTypeAssert,file,line);
561 if (Instance.curFrameEntry->status==NoSkip)
564 ++Instance.curFrameEntry->hits;
566 Instance <<
"\n" <<
RepeatChar(
'=',80) <<
"\n";
571 const char *p=strstr(file,
"\\code\\");
574 Instance <<
"Crash in " << p <<
", line " << line
592 if (curFrameEntry->hits>1)
593 (*this) <<
" (hit #" << curFrameEntry->hits <<
")";
601 "\nBecause of the severity of this error the "
602 "game will now exit.";
604 if (IsWindowed()&&!die)
606 "\nPress 'abort' to abort the program,\n"
607 "'retry' for breaking into the debugger, or\n"
608 "'ignore' for ignoring this assertion for the\n"
609 "time being (stops logging this assertion as well).";
612 strcpy(help,ioBuffer[curType].
buffer+82);
613 strcat(help,addInfo);
616 if (curFrameEntry->hits==1)
619 if (m_stackWalk.StackWalk(sig))
637 int result=MessageBox(
NULL,help,
"Crash hit",
638 MB_ABORTRETRYIGNORE|MB_ICONSTOP|MB_TASKMODAL|MB_SETFOREGROUND);
649 __ASSERT(strlen(curFrameEntry->fileOrGroup)<190);
650 wsprintf(help,
"%s(%i)",curFrameEntry->fileOrGroup,
651 curFrameEntry->line);
652 AddPatternEntry(FrameTypeAssert,
false,help);
653 curFrameEntry->status=Skip;
672 Instance <<
"Crash hit too often - turning check off.\n";
677 __ASSERT(strlen(curFrameEntry->fileOrGroup)<190);
678 wsprintf(help,
"%s(%i)",curFrameEntry->fileOrGroup,
679 curFrameEntry->line);
680 AddPatternEntry(FrameTypeAssert,
false,help);
682 curFrameEntry->status=Skip;
689 MessageBox(
NULL,help,
"Game crash",
690 MB_OK|MB_ICONSTOP|MB_TASKMODAL|MB_SETFOREGROUND);
713 unsigned len=strlen(str);
718 for (
unsigned k=len;k<m_width;k++)
719 AddOutput(&m_fillChar,1);
732 strncpy(m_prefix,prefix?prefix:
"",
sizeof(m_prefix)-1);
733 m_prefix[
sizeof(m_prefix)-1]=0;
743 AddOutput(m_prefix,strlen(m_prefix));
744 return (*
this) << _itoa(val,help,m_radix);
753 AddOutput(m_prefix,strlen(m_prefix));
754 return (*
this) << _ultoa(val,help,m_radix);
763 AddOutput(m_prefix,strlen(m_prefix));
764 return (*
this) << _itoa(val,help,m_radix);
773 AddOutput(m_prefix,strlen(m_prefix));
774 return (*
this) << _ultoa(val,help,m_radix);
779 return (*
this) << (val?
"true":
"false");
786 _snprintf(help,
sizeof(help),
"%f",val);
787 return (*
this) << help;
794 _snprintf(help,
sizeof(help),
"%f",val);
795 return (*
this) << help;
804 AddOutput(m_prefix,strlen(m_prefix));
805 return (*
this) << _itoa(val,help,m_radix);
814 AddOutput(m_prefix,strlen(m_prefix));
815 return (*
this) << _itoa(val,help,m_radix);
824 AddOutput(m_prefix,strlen(m_prefix));
825 return (*
this) << _i64toa(val,help,m_radix);
834 AddOutput(m_prefix,strlen(m_prefix));
835 return (*
this) << _ui64toa(val,help,m_radix);
844 (*this) <<
"0x" << _ultoa((
unsigned long)ptr,help,16);
865 unsigned itemPerLine=(dump.m_withChars?64:65)/
866 (1+2*dump.m_bytePerItem+(dump.m_withChars?1:0));
871 const unsigned char *cur=dump.m_startPtr;
872 for (
unsigned i=0;i<dump.m_numItems;i+=itemPerLine,cur+=itemPerLine*dump.m_bytePerItem)
876 sprintf(buf,
"%08x",dump.m_absAddr?
unsigned(cur):cur-dump.m_startPtr);
880 const unsigned char *curByte=cur;
881 for (
unsigned k=0;k<itemPerLine;k++,curByte+=dump.m_bytePerItem)
885 if (k+i>=dump.m_numItems)
887 for (
unsigned l=dump.m_bytePerItem;l;--l)
890 else if (IsBadReadPtr(curByte,dump.m_bytePerItem))
892 for (
unsigned l=dump.m_bytePerItem;l;--l)
897 curByte+=dump.m_bytePerItem;
898 for (
unsigned l=0;l<dump.m_bytePerItem;++l)
900 sprintf(buf,
"%02x",*--curByte);
907 if (!dump.m_withChars)
911 for (k=0;k<itemPerLine;k++,curByte+=dump.m_bytePerItem)
913 if (k+i>=dump.m_numItems)
915 else if (IsBadReadPtr(curByte,dump.m_bytePerItem))
917 for (
unsigned l=dump.m_bytePerItem;l;--l)
923 for (
unsigned l=0;l<dump.m_bytePerItem;++l)
925 *buf=curByte[l]>
' '?curByte[l]:
'.';
939 for (
unsigned k=0;k<numHrTranslators;k++)
940 if (hrTranslators[k].func(*
this,hres.m_hresult,hrTranslators[k].user))
942 (*this) <<
"HResult:0x";
944 return (*
this) << _ultoa(hres.m_hresult,help,16);
953 FrameHashEntry *e=Instance.LookupFrame((
unsigned)fileOrGroup);
955 e=Instance.AddFrameEntry((
unsigned)fileOrGroup,FrameTypeLog,fileOrGroup,0);
956 if (e->status==Unknown)
957 Instance.UpdateFrameStatus(*e);
958 return e->status==NoSkip;
974 for (
unsigned k=0;k<Instance.numHrTranslators;++k)
975 if (Instance.hrTranslators[k].prio<prio)
979 Instance.hrTranslators=(HResultTranslatorEntry *)
980 DebugReAllocMemory(Instance.hrTranslators,(Instance.numHrTranslators+1)*
sizeof(
void *));
981 memmove(Instance.hrTranslators+k+1,Instance.hrTranslators+k,(Instance.numHrTranslators-k)*
sizeof(
void *));
984 ++Instance.numHrTranslators;
985 Instance.hrTranslators[k].prio=prio;
986 Instance.hrTranslators[k].func=func;
987 Instance.hrTranslators[k].user=user;
997 for (
unsigned k=0;k<Instance.numHrTranslators;++k)
998 if (Instance.hrTranslators[k].func==func&&
999 Instance.hrTranslators[k].user==user)
1002 memmove(Instance.hrTranslators+k,Instance.hrTranslators+k+1,
1003 (Instance.numHrTranslators-k-1)*
sizeof(
void *));
1004 --Instance.hrTranslators;
1005 Instance.hrTranslators=(HResultTranslatorEntry *)
1017 IOFactoryListEntry *entry=(IOFactoryListEntry *)
1019 entry->next=Instance.firstIOFactory;
1022 entry->factory=func;
1025 entry->inputAlloc=0;
1029 Instance.firstIOFactory=entry;
1037 if (!cmdgroup||!cmdif)
1041 CmdInterfaceListEntry **listptr=&Instance.firstCmdGroup;
1044 if ((*listptr)->cmdif==cmdif)
1047 listptr=&((*listptr)->next);
1051 CmdInterfaceListEntry *entry=(CmdInterfaceListEntry *)
1054 entry->group=cmdgroup;
1070 CmdInterfaceListEntry **listptr=&Instance.firstCmdGroup;
1073 if ((*listptr)->cmdif==cmdif)
1076 CmdInterfaceListEntry *cur=*listptr;
1085 listptr=&((*listptr)->next);
1092 Instance.ExecCommand(cmd,cmd+strlen(cmd));
1098 for (IOFactoryListEntry *cur=Instance.firstIOFactory;cur;cur=cur->next)
1104 bool hadInput=
false;
1107 if (cur->inputAlloc-cur->inputUsed<64)
1110 int numChars=cur->io->Read(cur->input+cur->inputUsed,cur->inputAlloc-cur->inputUsed);
1114 cur->inputUsed+=numChars;
1115 cur->input[cur->inputUsed]=0;
1126 char *p=strchr(cur->input,
'\n');
1130 Instance.ExecCommand(cur->input,p);
1131 strcpy(cur->input,p+1);
1132 cur->inputUsed=strlen(cur->input);
1137Debug::FrameHashEntry* Debug::AddFrameEntry(
unsigned addr,
unsigned type,
1138 const char *fileOrGroup,
int line)
1143 if (!numAvailableFrameHash)
1145 numAvailableFrameHash=FRAME_HASH_ALLOC_COUNT;
1146 nextUnusedFrameHash=(FrameHashEntry *)
1149 FrameHashEntry *e=nextUnusedFrameHash++;
1150 --numAvailableFrameHash;
1153 e->next=frameHash[addr%FRAME_HASH_SIZE];
1161 if (type&FrameTypeLog)
1165 e->fileOrGroup=AddLogGroup(fileOrGroup,
NULL);
1170 e->fileOrGroup=fileOrGroup?strrchr(fileOrGroup,
'\\'):
NULL;
1171 e->fileOrGroup=e->fileOrGroup?e->fileOrGroup+1:fileOrGroup;
1175 frameHash[addr%FRAME_HASH_SIZE]=e;
1179void Debug::UpdateFrameStatus(FrameHashEntry &entry)
1183 if (entry.frameType==FrameTypeAssert||
1184 entry.frameType==FrameTypeCheck)
1185 wsprintf(help,
"%s(%i)",entry.fileOrGroup,entry.line);
1187 strcpy(help,entry.fileOrGroup);
1190 bool active=entry.frameType!=FrameTypeLog;
1191 for (PatternListEntry *cur=firstPatternEntry;cur;cur=cur->next)
1193 if (!(cur->frameTypes&entry.frameType))
1196 active=cur->isActive;
1198 entry.status=active?NoSkip:Skip;
1201const char *Debug::AddLogGroup(
const char *fileOrGroup,
const char *descr)
1207 const char *p=strrchr(fileOrGroup,
'\\');
1208 const char *
q=strchr(p?p:fileOrGroup,
'.');
1213 p=p?p+1:fileOrGroup;
1214 if (!
q)
q=p+strlen(p);
1215 if (
q-p>=
sizeof(help))
1223 for (KnownLogGroupList *cur=firstLogGroup;cur;cur=cur->next)
1225 if (!strcmp(cur->nameGroup,fileOrGroup))
1228 return cur->nameGroup;
1234 cur->next=firstLogGroup;
1236 strcpy(cur->nameGroup,fileOrGroup);
1239 return cur->nameGroup;
1252 wvsprintf(curSource,fmt,va);
1254 __ASSERT(curSource[
sizeof(curSource)-1]==0);
1257void Debug::AddOutput(
const char *str,
unsigned remainingLen)
1264 while (remainingLen)
1274 GetLocalTime(&systime);
1277 wsprintf(ts,
"[%02i:%02i.%02i.%03i] ",systime.wHour,systime.wMinute,
1278 systime.wSecond,systime.wMilliseconds);
1280 unsigned tsLen=strlen(ts);
1281 memcpy(ioBuffer[curType].
buffer+ioBuffer[curType].
used,ts,tsLen+1);
1282 ioBuffer[curType].used+=tsLen;
1286 const char *p=strchr(str,
'\n');
1287 p=p?p+1:str+remainingLen;
1293 if (ioBuffer[curType].
used+len+64>=ioBuffer[curType].
alloc)
1296 ioBuffer[curType].alloc+=len+1024;
1297 ioBuffer[curType].buffer=(
char *)
1302 memcpy(ioBuffer[curType].
buffer+ioBuffer[curType].
used,str,len+1);
1303 ioBuffer[curType].used+=len;
1306 ioBuffer[curType].lastWasCR=str[len-1]==
'\n';
1320void Debug::FlushOutput(
bool defaultLog)
1325 if (!ioBuffer[curType].
used)
1336 bool hadWrite=!defaultLog;
1337 for (IOFactoryListEntry *cur=firstIOFactory;cur;cur=cur->next)
1343 cur->io->Write(curType,curSource,ioBuffer[curType].
buffer);
1346 cur->io->Write(curType,curSource,
NULL);
1355 HANDLE h=CreateFile(
"default.log",GENERIC_WRITE,0,
NULL,
1356 OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,
NULL);
1357 SetFilePointer(h,0,
NULL,FILE_END);
1359 WriteFile(h,ioBuffer[curType].
buffer,strlen(ioBuffer[curType].
buffer),&dwDummy,
NULL);
1365 ioBuffer[curType].used=0;
1366 *ioBuffer[curType].buffer=0;
1371void Debug::AddPatternEntry(
unsigned types,
bool isActive,
const char *pattern)
1376 PatternListEntry *cur=(PatternListEntry *)
1381 cur->frameTypes=types;
1382 cur->isActive=isActive;
1384 strcpy(cur->pattern,pattern);
1387 if (lastPatternEntry)
1388 lastPatternEntry->next=cur;
1390 firstPatternEntry=cur;
1391 lastPatternEntry=cur;
1398 while (*str&&*pattern)
1406 return *str==*pattern;
1410 if (*str++!=*pattern++)
1415 return *str==*pattern;
1419 const char *internalVersion,
1420 const char *buildDate)
1423 strncpy(Instance.m_version,version,
sizeof(Instance.m_version)-1);
1424 if (internalVersion)
1425 strncpy(Instance.m_intVersion,internalVersion,
sizeof(Instance.m_intVersion)-1);
1427 strncpy(Instance.m_buildDate,buildDate,
sizeof(Instance.m_buildDate)-1);
1434 (*this) <<
" " << m_version;
1436 (*this) <<
" internal " << m_intVersion;
1437 #if defined(_INTERNAL)
1439 #elif defined(_DEBUG)
1441 #elif defined(_PROFILE)
1447 (*this) <<
" build " << m_buildDate;
1450void Debug::ExecCommand(
const char *cmdstart,
const char *cmdend)
1456 memcpy(strbuf,cmdstart,cmdend-cmdstart);
1457 strbuf[cmdend-cmdstart]=0;
1464 char *lastNonWhitespace=
NULL;
1484 if (!lastNonWhitespace&&(*cur==
'\''||*cur==
'"'))
1488 if (numParts<
sizeof(parts)/
sizeof(*parts))
1489 parts[numParts++]=cur;
1491 while (*cur&&*cur!=quote)
1496 else if (*cur==
' '||*cur==
'\t'||!*cur||*cur==
';')
1500 if (lastNonWhitespace)
1502 if (numParts<
sizeof(parts)/
sizeof(*parts))
1503 parts[numParts++]=lastNonWhitespace;
1504 lastNonWhitespace=
NULL;
1515 if (!lastNonWhitespace)
1516 lastNonWhitespace=cur;
1526 char *p=strchr(parts[0],
'.');
1527 if (p&&p-parts[0]<
sizeof(curCommandGroup))
1529 memcpy(curCommandGroup,parts[0],p-parts[0]);
1530 curCommandGroup[p-parts[0]]=0;
1536 StartOutput(reply,
"%s.%s",curCommandGroup,p);
1542 AddOutput(cmdstart,cmdend-cmdstart);
1546 for (CmdInterfaceListEntry *cur=firstCmdGroup;cur;cur=cur->next)
1547 if (!strcmp(curCommandGroup,cur->group))
1552 (*this) <<
"Unknown command group " << curCommandGroup;
1561 for (CmdInterfaceListEntry *cur=firstCmdGroup;cur;cur=cur->next)
1563 if (strcmp(curCommandGroup,cur->group))
1566 bool doneCommand=cur->cmdif->Execute(*
this,p,mode,numParts-1,parts+1);
1567 if (doneCommand&&(strcmp(p,
"help")||numParts>1))
1574 if (strcmp(p,
"help"))
1576 else if (numParts>1)
1577 operator<<(
"Unknown command, help not available");
1590static BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM lParam)
1592 *(HWND *)lParam=hwnd;
1596bool Debug::IsWindowed(
void)
1600 return m_isWindowed>0;
1604 EnumThreadWindows(GetCurrentThreadId(),EnumThreadWndProc,(LPARAM)&appHWnd);
1613 m_isWindowed=(GetWindowLong(appHWnd,GWL_STYLE)&WS_CAPTION)?1:-1;
1614 return m_isWindowed>0;
Helper class for writing HRESULTs to the debug stream.
Helper class for performing a raw memory dump.
Repeats a given character N times.
Debug command group interface.
CommandMode
possible command modes
@ Normal
normal command mode
@ Structured
structured command mode
static long __stdcall ExceptionFilter(struct _EXCEPTION_POINTERS *pExPtrs)
void WriteBuildInfo(void)
Write build information into log.
static void Command(const char *cmd)
Issues a debug command.
unsigned used
used buffer size
static void RemoveCommands(DebugCmdInterface *cmdif)
Removes a command group.
Debug & operator<<(Hex &)
static void Update(void)
Update method, must be called on a regular basis.
static Debug & AssertBegin(const char *file, int line, const char *expr)
static bool IsLogEnabled(const char *fileOrGroup)
static void AddHResultTranslator(unsigned prio, HResultTranslator func, void *user=0)
Adds a HRESULT translator.
static bool AddCommands(const char *cmdgroup, DebugCmdInterface *cmdif)
Adds a new command group.
static bool AddIOFactory(const char *io_id, const char *descr, DebugIOInterface *(*func)(void))
Registers a new I/O class factory function.
bool(* HResultTranslator)(Debug &debug, long hresult, void *user)
HRESULT translator callback function type.
static void RemoveHResultTranslator(HResultTranslator func, void *user=0)
Removes a HRESULT translator.
static void InstallExceptionHandler(void)
Installs exception handler for current thread.
static Debug & CheckBegin(const char *file, int line, const char *expr)
void SetPrefixAndRadix(const char *prefix, int radix)
static Debug & LogBegin(const char *fileOrGroup)
friend class DebugCmdInterfaceDebug
unsigned alloc
allocated buffer size
static bool SimpleMatch(const char *str, const char *pattern)
@ MAX_CHECK_HITS
maximum number of times a check can be hit before it is turned off
static Debug & CrashBegin(const char *file, int line)
static bool SkipNext(void)
bool lastWasCR
has last character been CR?
static void SetBuildInfo(const char *version, const char *internalVersion, const char *buildDate)
Tell debug module about build info.
static DebugIOInterface * Create(void)
static DebugIOInterface * Create(void)
StringType
List of possible log string types.
@ Other
some other message
@ CmdReply
Regular command reply.
@ StructuredCmdReply
Structured command reply, see Structured command reply.
static DebugIOInterface * Create(void)
static DebugIOInterface * Create(void)
static void * GetDbghelpHandle(void)
static bool IsOldDbghelp(void)
bool __DebugIncludeInLink1
void __cdecl _heap_abort(void)
void * DebugReAllocMemory(void *oldPtr, unsigned newSize)
void * DebugAllocMemory(unsigned numBytes)
void DebugFreeMemory(void *ptr)
#define DCRASH_RELEASE(msg)
const char * DebugGetDefaultCommands(void)
Determines default commands to be executed at startup.