23 # define SHOW_CALL_STACK
38 #if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
53 #define _ASSERT(expr) ((void)0)
55 #define _ASSERT(expr) (assert(expr))
62 const char *
p = name+strlen(name)-1;
64 while( (*p!=
'\\') && (*p!=
'/') && (*p!=
':') && (p>= name) )
71 #if defined( SHOW_CALL_STACK )
72 static bool Dump_to_log =
true;
77 enum { BUFFER_SIZE = 32000 } ;
80 void Printf(
const char*
format, ... ) ;
81 void SetWindowText(
HWND hWnd )
const ;
82 char buffer[ BUFFER_SIZE ] ;
84 void Append(
const char* text);
85 void Truncate(
size_t size);
86 void TruncateLines(
int num_allowed_lines);
94 DumpBuffer :: DumpBuffer()
100 void DumpBuffer :: Clear()
106 void DumpBuffer :: Append(
const char* text)
112 void DumpBuffer :: Truncate(
size_t size)
114 if (size >= strlen(
buffer))
122 void DumpBuffer :: TruncateLines(
int num_allowed_lines)
124 Assert(num_allowed_lines > 0);
126 char *lastch = find_from + strlen(
buffer) - 6;
128 while (find_from < lastch)
130 if (num_allowed_lines <= 0)
137 char *
p = strchr(find_from,
'\n');
147 size_t DumpBuffer :: Size()
const
153 void DumpBuffer :: Printf(
const char*
format, ... )
157 int max = BUFFER_SIZE -
pos;
160 if (pos >= BUFFER_SIZE)
163 va_start( argPtr, format ) ;
164 vsnprintf( current, max-1, format, argPtr ) ;
167 current[max-1] =
'\0';
168 current += strlen(current);
172 void DumpBuffer :: SetWindowText(
HWND hWnd )
const
174 SendMessage( hWnd, WM_SETTEXT, 0, (
LPARAM)buffer ) ;
180 static DumpBuffer dumpBuffer;
181 const char* Separator =
"------------------------------------------------------------------\n" ;
187 #if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
189 class SCP_DebugCallStack :
public SCP_IDumpHandler
192 virtual bool ResolveSymbols( )
197 virtual void OnBegin( )
201 virtual void OnEnd( )
205 virtual void OnEntry(
void*
address,
const char* module,
const char* symbol )
207 UNREFERENCED_PARAMETER( address );
211 entry.symbol = symbol;
212 m_stackFrames.push_back( entry );
215 virtual void OnError(
const char* error )
218 UNREFERENCED_PARAMETER( error );
224 for (
size_t i = 0;
i < m_stackFrames.size( );
i++ )
226 callstack += m_stackFrames[
i ].module +
"! " + m_stackFrames[
i ].symbol +
"\n";
241 #elif defined( SHOW_CALL_STACK )
249 int DumpDebugInfo( DumpBuffer& dumpBuffer,
const BYTE* caller,
HINSTANCE hInstance ) ;
253 enum { MAX_MODULENAME_LEN = 512, VA_MAX_FILENAME_LEN = 256 } ;
254 char latestModule[ MAX_MODULENAME_LEN ] ;
255 char latestFile[ VA_MAX_FILENAME_LEN ] ;
259 PIMAGE_DOS_HEADER fileBase ;
261 PIMAGE_NT_HEADERS NT_Header ;
262 PIMAGE_COFF_SYMBOLS_HEADER COFFDebugInfo ;
263 PIMAGE_SYMBOL COFFSymbolTable ;
264 int COFFSymbolCount ;
265 const char* stringTable ;
267 void ClearFileCache() ;
268 void ClearDebugPtrs() ;
269 void MapFileInMemory(
const char* module ) ;
270 void FindDebugInfo() ;
271 void DumpSymbolInfo( DumpBuffer& dumpBuffer,
DWORD relativeAddress ) ;
272 void DumpLineNumber( DumpBuffer& dumpBuffer,
DWORD relativeAddress ) ;
273 PIMAGE_COFF_SYMBOLS_HEADER GetDebugHeader() ;
274 PIMAGE_SECTION_HEADER SectionHeaderFromName(
const char*
name ) ;
275 const char* GetSymbolName( PIMAGE_SYMBOL sym ) ;
281 #define BasedPtr( type, ptr, ofs ) (type)( (DWORD)(ptr) + (DWORD)(ofs) )
284 PE_Debug :: PE_Debug()
288 hFile = INVALID_HANDLE_VALUE ;
295 PE_Debug :: ~PE_Debug()
301 void PE_Debug :: ClearReport()
303 latestModule[ 0 ] = 0 ;
304 latestFile[ 0 ] = 0 ;
308 void PE_Debug :: ClearDebugPtrs()
311 COFFDebugInfo = NULL ;
312 COFFSymbolTable = NULL ;
313 COFFSymbolCount = 0 ;
318 void PE_Debug :: ClearFileCache()
322 UnmapViewOfFile( fileBase ) ;
325 if( hFileMapping != 0 )
327 CloseHandle( hFileMapping ) ;
330 if( hFile != INVALID_HANDLE_VALUE )
332 CloseHandle( hFile ) ;
333 hFile = INVALID_HANDLE_VALUE ;
338 void PE_Debug :: DumpLineNumber( DumpBuffer& dumpBuffer,
DWORD relativeAddress )
340 PIMAGE_LINENUMBER line = BasedPtr( PIMAGE_LINENUMBER, COFFDebugInfo,
341 COFFDebugInfo->LvaToFirstLinenumber ) ;
342 DWORD lineCount = COFFDebugInfo->NumberOfLinenumbers ;
345 DWORD lineNum = none ;
346 for(
DWORD i=0;
i < lineCount;
i++ )
348 if( line->Linenumber != 0 )
351 if( line->Type.VirtualAddress <= relativeAddress &&
352 line->Type.VirtualAddress > maxAddr )
354 maxAddr = line->Type.VirtualAddress ;
355 lineNum = line->Linenumber ;
360 if( lineNum != none ) {
361 dumpBuffer.Printf(
" line %d\r\n", lineNum ) ;
363 mprintf((
" line %d\r\n", lineNum )) ;
371 const char* PE_Debug :: GetSymbolName( PIMAGE_SYMBOL sym )
373 const int NAME_MAX_LEN = 64 ;
374 static char buf[ NAME_MAX_LEN ] ;
375 if( sym->N.Name.Short != 0 )
377 strncpy( buf, (
const char*)sym->N.ShortName, 8 ) ;
382 strncpy( buf, stringTable + sym->N.Name.Long, NAME_MAX_LEN ) ;
383 buf[ NAME_MAX_LEN - 1 ] = 0 ;
388 void unmangle(
char *
dst,
const char *
src)
394 while( (*src) && (*src!=
' ') && (*src!=
'@') ) {
402 typedef struct MemSymbol {
417 Symbols = (MemSymbol *)
vm_malloc(Max_symbols*
sizeof(MemSymbol));
423 void Add_Symbol(
int section,
int offset,
const char *
name,
char *module )
425 if ( Num_symbols >= Max_symbols ) {
429 MemSymbol * sym = &Symbols[Num_symbols++];
431 sym->section = section;
442 int Sym_compare(
const void *
arg1,
const void *
arg2 )
444 MemSymbol * sym1 = (MemSymbol *)arg1;
445 MemSymbol * sym2 = (MemSymbol *)arg2;
447 if ( sym1->section < sym2->section ) {
449 }
else if ( sym1->section > sym2->section ) {
452 if ( sym1->offset > sym2->offset ) {
460 int Sym_compare1(
const void *arg1,
const void *arg2 )
462 MemSymbol * sym1 = (MemSymbol *)arg1;
463 MemSymbol * sym2 = (MemSymbol *)arg2;
465 if ( sym1->size < sym2->size ) {
467 }
else if ( sym1->size > sym2->size ) {
478 insertion_sort( Symbols, Num_symbols,
sizeof(MemSymbol), Sym_compare );
480 for (i=0;i<Num_symbols; i++ ) {
481 MemSymbol * sym1 = &Symbols[
i];
482 MemSymbol * sym2 = &Symbols[i+1];
483 if ( (i<Num_symbols-1) && (sym1->section == sym2->section) ) {
484 sym1->size = sym2->offset-sym1->offset;
490 insertion_sort( Symbols, Num_symbols,
sizeof(MemSymbol), Sym_compare1 );
493 FILE *
fp = fopen(
"dump",
"wt" );
495 fprintf( fp,
"%-100s %10s %10s\n",
"Name",
"Size",
"Total" );
498 for (i=0;i<Num_symbols; i++ ) {
499 MemSymbol * sym = &Symbols[
i];
501 total_size += sym->size;
502 fprintf( fp,
"%-100s %10d %10d\n", sym->name, sym->size, total_size );
513 void PE_Debug::DumpSymbolInfo( DumpBuffer& dumpBuffer,
DWORD relativeAddress )
516 PIMAGE_SYMBOL currentSym = COFFSymbolTable ;
517 PIMAGE_SYMBOL fnSymbol = NULL ;
518 DWORD maxFnAddress = 0 ;
525 PIMAGE_SYMBOL fileSymbol = NULL ;
526 PIMAGE_SYMBOL latestFileSymbol = NULL ;
527 for (
int i = 0; i < COFFSymbolCount; i++ ) {
531 if ( currentSym->StorageClass == IMAGE_SYM_CLASS_FILE ) {
532 latestFileSymbol = currentSym;
537 const char* symName = GetSymbolName( currentSym ) ;
539 if (
strnicmp( symName,
".text", 5 ) == 0 || strcmpi( symName,
"CODE" ) == 0 ) {
540 if ( currentSym->Value <= relativeAddress ) {
541 PIMAGE_AUX_SYMBOL auxSym = (PIMAGE_AUX_SYMBOL)(currentSym + 1) ;
542 if ( currentSym->Value + auxSym->Section.Length >= relativeAddress ) {
543 fileSymbol = latestFileSymbol ;
550 BOOL isFunction = ISFCN( currentSym->Type );
551 if ( isFunction && ( currentSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL || currentSym->StorageClass == IMAGE_SYM_CLASS_STATIC ) ) {
553 if ( currentSym->Value <= relativeAddress && currentSym->Value > maxFnAddress ) {
554 maxFnAddress = currentSym->Value ;
555 fnSymbol = currentSym ;
560 if ( !isFunction && (currentSym->SectionNumber >= 0) ) {
561 if ( (symName[0]==
'_' && symName[1]!=
'$') || (symName[0]==
'?') ) {
563 char pretty_module[1024];
566 const char* auxSym = (
const char*)(latestFileSymbol + 1) ;
567 char tmpFile[ VA_MAX_FILENAME_LEN ] ;
570 char *
p = pretty_module+strlen(pretty_module)-1;
572 while( (*p!=
'\\') && (*p!=
'/') && (*p!=
':') )
575 if ( strlen(p) < 1 ) {
576 strcpy_s( pretty_module,
"<unknown>" );
578 memmove( pretty_module, p, strlen(p)+1 );
584 Add_Symbol( currentSym->SectionNumber, currentSym->Value, symName, pretty_module );
590 i += currentSym->NumberOfAuxSymbols ;
591 currentSym += currentSym->NumberOfAuxSymbols ;
601 const char* auxSym = (
const char*)(fileSymbol + 1) ;
603 if( strcmpi( latestFile, auxSym ) ) {
608 latestFile[ 0 ] = 0 ;
614 unmangle(tmp_name, GetSymbolName( fnSymbol ) );
615 dumpBuffer.Printf(
" %s()", tmp_name ) ;
617 mprintf((
" %s()", tmp_name )) ;
620 dumpBuffer.Printf(
" <unknown>" ) ;
628 PIMAGE_SECTION_HEADER PE_Debug :: SectionHeaderFromName(
const char* name )
630 PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION( NT_Header ) ;
631 for(
unsigned i = 0; i < NT_Header->FileHeader.NumberOfSections; i++ )
633 if(
strnicmp( (
const char*)section->Name, name, IMAGE_SIZEOF_SHORT_NAME ) == 0 )
642 PIMAGE_COFF_SYMBOLS_HEADER PE_Debug :: GetDebugHeader()
646 if( NT_Header->FileHeader.PointerToSymbolTable == 0 )
648 DWORD debugDirRVA = NT_Header->OptionalHeader.
649 DataDirectory[ IMAGE_DIRECTORY_ENTRY_DEBUG ].
651 if( debugDirRVA == 0 )
655 PIMAGE_DEBUG_DIRECTORY debugDir ;
659 PIMAGE_SECTION_HEADER debugHeader = SectionHeaderFromName(
".debug" ) ;
660 if( debugHeader && debugHeader->VirtualAddress == debugDirRVA )
662 debugDir = (PIMAGE_DEBUG_DIRECTORY)(debugHeader->PointerToRawData + (
DWORD)fileBase) ;
663 size = NT_Header->OptionalHeader.
664 DataDirectory[ IMAGE_DIRECTORY_ENTRY_DEBUG ].Size *
665 sizeof( IMAGE_DEBUG_DIRECTORY ) ;
670 debugHeader = SectionHeaderFromName(
".rdata" ) ;
671 if( debugHeader == 0 )
673 size = NT_Header->OptionalHeader.
674 DataDirectory[ IMAGE_DIRECTORY_ENTRY_DEBUG ].Size ;
675 DWORD offsetInto_rdata = debugDirRVA - debugHeader->VirtualAddress ;
676 debugDir = BasedPtr( PIMAGE_DEBUG_DIRECTORY, fileBase,
677 debugHeader->PointerToRawData + offsetInto_rdata ) ;
681 DWORD debugFormats = size /
sizeof( IMAGE_DEBUG_DIRECTORY ) ;
682 for(
DWORD i = 0; i < debugFormats; i++ )
684 if( debugDir->Type == IMAGE_DEBUG_TYPE_COFF )
685 return( (PIMAGE_COFF_SYMBOLS_HEADER)((
DWORD)fileBase + debugDir->PointerToRawData) ) ;
693 void PE_Debug :: FindDebugInfo()
700 if( fileBase->e_magic == IMAGE_DOS_SIGNATURE )
703 NT_Header = BasedPtr( PIMAGE_NT_HEADERS, fileBase, fileBase->e_lfanew ) ;
705 if( NT_Header->Signature == IMAGE_NT_SIGNATURE )
708 COFFDebugInfo = GetDebugHeader() ;
710 if( NT_Header->FileHeader.PointerToSymbolTable )
712 BasedPtr( PIMAGE_SYMBOL, fileBase, NT_Header->FileHeader.PointerToSymbolTable ) ;
713 COFFSymbolCount = NT_Header->FileHeader.NumberOfSymbols ;
715 stringTable = (
const char*)(COFFSymbolTable + COFFSymbolCount) ;
726 void PE_Debug :: MapFileInMemory(
const char* module )
729 hFile = CreateFile( module, GENERIC_READ, FILE_SHARE_READ, NULL,
730 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ) ;
731 if( hFile != INVALID_HANDLE_VALUE )
733 hFileMapping = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL ) ;
734 if( hFileMapping != 0 )
735 fileBase = (PIMAGE_DOS_HEADER)MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 ) ;
741 int PE_Debug::DumpDebugInfo( DumpBuffer& dumpBuffer,
const BYTE* caller,
HINSTANCE hInstance )
746 static char module[ MAX_MODULENAME_LEN ] ;
747 GetModuleFileName( hInstance, module, MAX_MODULENAME_LEN ) ;
750 if( strcmpi( latestModule, module ) ) {
753 MapFileInMemory( module );
757 char pretty_module[1024];
760 char *p = pretty_module+strlen(pretty_module)-1;
762 while( (*p!=
'\\') && (*p!=
'/') && (*p!=
':') )
765 if ( strlen(p) < 1 ) {
766 strcpy_s( pretty_module,
"<unknown>" );
768 memmove( pretty_module, p, strlen(p)+1 );
774 DWORD relativeAddress = caller - (BYTE*)hInstance ;
776 if( COFFSymbolCount != 0 && COFFSymbolTable != NULL ) {
777 DumpSymbolInfo( dumpBuffer, relativeAddress ) ;
779 DumpLineNumber( dumpBuffer, relativeAddress ) ;
784 dumpBuffer.Printf(
" %s %08x()\r\n", pretty_module, caller ) ;
786 mprintf((
" %s %08x()\r\n", pretty_module, caller )) ;
795 dumpBuffer.Printf(
" %s %08x()\r\n", pretty_module, caller ) ;
797 mprintf((
" %s %08x()\r\n", pretty_module, caller )) ;
808 void DumpCallsStack( DumpBuffer& dumpBuffer )
810 static PE_Debug PE_debug ;
812 dumpBuffer.Printf(
"\r\nCall stack:\r\n" ) ;
813 dumpBuffer.Printf( Separator ) ;
820 DWORD parentEBP, retval;
821 MEMORY_BASIC_INFORMATION mbi ;
826 __asm MOV parentEBP, EBP
833 if ( (parentEBP & 3) || IsBadReadPtr((
DWORD*)parentEBP,
sizeof(
DWORD)) ) {
836 parentEBP = *(
DWORD*)parentEBP ;
838 BYTE **NextCaller = ((BYTE**)parentEBP + 1);
840 if (IsBadReadPtr(NextCaller,
sizeof(BYTE *))) {
844 BYTE* caller = *NextCaller;
852 retval = VirtualQuery( caller, &mbi,
sizeof( mbi ) ) ;
855 hInstance = (
HINSTANCE)mbi.AllocationBase ;
857 if( ( retval ==
sizeof( mbi ) ) && hInstance ) {
858 if ( !PE_debug.DumpDebugInfo( dumpBuffer, caller, hInstance ) ) {
868 dumpBuffer.Printf( Separator ) ;
869 PE_debug.ClearReport() ;
872 #endif //SHOW_CALL_STACK
885 int len = strlen(text)+1024;
887 HGLOBAL h_text = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len );
888 if ( !h_text )
return;
889 char *ptr = (
char *)GlobalLock(h_text);
895 if ( (*text ==
'\n') && (last_char !=
'\r') ) {
903 GlobalUnlock(h_text);
906 SetClipboardData(CF_TEXT, h_text);
916 mprintf((
"ASSERTION: \"%s\" at %s:%d\n", text, strrchr(filename,
'\\')+1, linenum ));
919 if (Cmdline_nowarn) {
928 filename = strrchr(filename,
'\\')+1;
929 sprintf( AssertText1,
"Assert: %s\r\nFile: %s\r\nLine: %d\r\n", text, filename, linenum );
931 #if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
933 SCP_DebugCallStack callStack;
934 SCP_DumpStack( dynamic_cast< SCP_IDumpHandler* >( &callStack ) );
938 assertString +=
"\n";
939 assertString += callStack.DumpToString( );
947 assertString +=
"\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
948 assertString +=
"\n\nUse Ok to break into Debugger, Cancel to exit.\n";
951 #elif defined( SHOW_CALL_STACK )
953 dumpBuffer.Printf( AssertText1 );
954 dumpBuffer.Printf(
"\r\n" );
955 DumpCallsStack( dumpBuffer ) ;
961 dumpBuffer.Printf(
"\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
962 dumpBuffer.Printf(
"\r\n\r\nUse Ok to break into Debugger, Cancel to exit.\r\n");
984 memset( AssertText1, 0,
sizeof(AssertText1) );
985 memset( AssertText2, 0,
sizeof(AssertText2) );
987 va_start(args, format);
988 vsnprintf(AssertText2,
sizeof(AssertText2)-1, format, args);
992 mprintf((
"ASSERTION: \"%s\" at %s:%d\n %s\n", text, strrchr(filename,
'\\')+1, linenum, AssertText2 ));
995 if (Cmdline_nowarn) {
1004 filename = strrchr(filename,
'\\')+1;
1005 snprintf( AssertText1,
sizeof(AssertText1)-1,
"Assert: %s\r\nFile: %s\r\nLine: %d\r\n%s\r\n", text, filename, linenum, AssertText2 );
1007 #if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
1009 SCP_DebugCallStack callStack;
1010 SCP_DumpStack( dynamic_cast< SCP_IDumpHandler* >( &callStack ) );
1014 assertString +=
"\n";
1015 assertString += callStack.DumpToString( );
1023 assertString +=
"\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
1024 assertString +=
"\n\nUse Ok to break into Debugger, Cancel to exit.\n";
1027 #elif defined ( SHOW_CALL_STACK )
1029 dumpBuffer.Printf( AssertText1 );
1030 dumpBuffer.Printf(
"\r\n" );
1031 DumpCallsStack( dumpBuffer ) ;
1037 dumpBuffer.Printf(
"\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
1038 dumpBuffer.Printf(
"\r\n\r\nUse Ok to break into Debugger, Cancel to exit.\r\n");
1045 if (val == IDCANCEL)
1057 dumpBuffer.Printf(
"Name:\t\t%s\r\n", ar.name);
1058 dumpBuffer.Printf(
"Name of:\t%s\r\n", ar.namewhat);
1059 dumpBuffer.Printf(
"Function type:\t%s\r\n", ar.what);
1060 dumpBuffer.Printf(
"Defined on:\t%d\r\n", ar.linedefined);
1061 dumpBuffer.Printf(
"Upvalues:\t%d\r\n", ar.nups);
1062 dumpBuffer.Printf(
"\r\n" );
1063 dumpBuffer.Printf(
"Source:\t\t%s\r\n", ar.source);
1064 dumpBuffer.Printf(
"Short source:\t%s\r\n", ar.short_src);
1065 dumpBuffer.Printf(
"Current line:\t%d\r\n", ar.currentline);
1066 dumpBuffer.Printf(
"- Function line:\t%d\r\n", (ar.linedefined ? (1 + ar.currentline - ar.linedefined) : 0));
1071 void LuaError(
struct lua_State *L,
const char *format, ...)
1084 dumpBuffer.Printf(
"LUA ERROR: %s", lua_tostring(L, -1));
1091 memset(AssertText1, 0,
sizeof(AssertText1));
1092 memset(AssertText2, 0,
sizeof(AssertText2));
1094 va_start(args, format);
1095 vsnprintf(AssertText1,
sizeof(AssertText1)-1, format,args);
1098 dumpBuffer.Printf(AssertText1);
1101 dumpBuffer.Printf(
"\r\n" );
1102 dumpBuffer.Printf(
"\r\n" );
1124 dumpBuffer.Printf(Separator);
1125 dumpBuffer.Printf(
"ADE Debug:" );
1126 dumpBuffer.Printf(
"\r\n" );
1127 dumpBuffer.Printf(Separator);
1129 dumpBuffer.Printf(Separator);
1131 dumpBuffer.Printf(
"\r\n" );
1132 dumpBuffer.Printf(
"\r\n" );
1134 AssertText2[0] =
'\0';
1135 dumpBuffer.Printf(Separator);
1138 lua_getglobal(L, LUA_DBLIBNAME);
1140 if (!lua_isnil(L, -1))
1142 dumpBuffer.Printf(
"\r\n" );
1143 lua_getfield(L, -1,
"traceback");
1146 if (lua_pcall(L, 0, 1, 0) != 0)
1147 dumpBuffer.Printf(
"Error while retrieving stack: %s", lua_tostring(L, -1));
1149 dumpBuffer.Printf(lua_tostring(L, -1));
1156 dumpBuffer.Printf(
"LUA Stack:\r\n");
1158 for (i = 0; i < 4; i++) {
1159 if (debug_stack[i][0] !=
'\0')
1160 dumpBuffer.Printf(
"\t%s\r\n", debug_stack[i]);
1163 dumpBuffer.Printf(
"\r\n" );
1165 dumpBuffer.Printf(Separator);
1167 dumpBuffer.Printf( AssertText2 );
1168 dumpBuffer.Printf(
"\r\n" );
1169 dumpBuffer.Printf(Separator);
1176 dumpBuffer.Printf(
"\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
1177 dumpBuffer.Printf(
"\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");
1181 if (val == IDCANCEL ) {
1183 }
else if(val == IDYES) {
1199 memset( AssertText1, 0,
sizeof(AssertText1) );
1200 memset( AssertText2, 0,
sizeof(AssertText2) );
1202 va_start(args, format);
1203 vsnprintf(AssertText1,
sizeof(AssertText1)-1, format, args);
1206 filename = strrchr(filename,
'\\')+1;
1207 snprintf(AssertText2,
sizeof(AssertText2)-1,
"Error: %s\r\nFile: %s\r\nLine: %d\r\n", AssertText1, filename, line);
1208 mprintf((
"ERROR: %s\r\nFile: %s\r\nLine: %d\r\n", AssertText1, filename, line));
1214 #if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
1216 SCP_DebugCallStack callStack;
1217 SCP_DumpStack( dynamic_cast< SCP_IDumpHandler* >( &callStack ) );
1221 assertString +=
"\n";
1222 assertString += callStack.DumpToString( );
1230 assertString +=
"\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
1231 assertString +=
"\n\nUse Ok to break into Debugger, Cancel to exit.\n";
1234 #elif defined( SHOW_CALL_STACK )
1236 dumpBuffer.Printf( AssertText2 );
1237 dumpBuffer.Printf(
"\r\n" );
1238 DumpCallsStack( dumpBuffer ) ;
1244 dumpBuffer.Printf(
"\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
1245 dumpBuffer.Printf(
"\r\n\r\nUse Ok to break into Debugger, Cancel exits.\r\n");
1249 strcat_s(AssertText2,
"\r\n\r\nUse Ok to break into Debugger, Cancel exits.\r\n");
1276 memset(msg, 0,
sizeof(msg));
1278 va_start(args, format);
1279 vsnprintf(msg,
sizeof(msg)-1, format, args);
1299 memset( AssertText1, 0,
sizeof(AssertText1) );
1300 memset( AssertText2, 0,
sizeof(AssertText2) );
1302 va_start(args, format);
1303 vsnprintf(AssertText1,
sizeof(AssertText1) - 1, format, args);
1306 slen = strlen(AssertText1);
1309 for (i = 0; i < slen; i++){
1310 if (AssertText1[i] == (
char)0x0a) {
1311 AssertText2[
i] =
' ';
1313 AssertText2[
i] = AssertText1[
i];
1318 if (AssertText2[slen-1] == (
char)0x20) {
1319 AssertText2[slen-1] =
'\0';
1322 AssertText2[slen] =
'\0';
1325 mprintf((
"WARNING: \"%s\" at %s:%d\n", AssertText2, strrchr(filename,
'\\')+1, line));
1329 if (Cmdline_nowarn) {
1334 filename = strrchr(filename,
'\\')+1;
1335 sprintf(AssertText2,
"Warning: %s\r\nFile: %s\r\nLine: %d\r\n", AssertText1, filename, line );
1341 #if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
1343 SCP_DebugCallStack callStack;
1344 SCP_DumpStack( dynamic_cast< SCP_IDumpHandler* >( &callStack ) );
1348 assertString +=
"\n";
1349 assertString += callStack.DumpToString( );
1357 assertString +=
"\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
1358 assertString +=
"\n\nUse Yes to break into Debugger, No to continue.\nand Cancel to Quit\n";
1361 #elif defined ( SHOW_CALL_STACK )
1363 Dump_to_log =
false;
1366 dumpBuffer.Printf( AssertText2 );
1367 dumpBuffer.Printf(
"\r\n" );
1368 DumpCallsStack( dumpBuffer ) ;
1374 dumpBuffer.Printf(
"\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
1375 dumpBuffer.Printf(
"\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");
1382 strcat_s(AssertText2,
"\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");
1417 memset(AssertText1, 0,
sizeof(AssertText1));
1418 memset(AssertText2, 0,
sizeof(AssertText2));
1420 va_start(args, format);
1421 vsnprintf(AssertText1,
sizeof(AssertText1) - 1, format, args);
1424 slen = strlen(AssertText1);
1427 for (i = 0; i < slen; i++) {
1428 if (AssertText1[i] == (
char)0x0a) {
1429 AssertText2[
i] =
' ';
1432 AssertText2[
i] = AssertText1[
i];
1437 if (AssertText2[slen - 1] == (
char)0x20) {
1438 AssertText2[slen - 1] =
'\0';
1442 AssertText2[slen] =
'\0';
1445 mprintf((
"WARNING: \"%s\" at %s:%d\n", AssertText2, strrchr(filename,
'\\') + 1, line));
1449 if (Cmdline_nowarn) {
1454 filename = strrchr(filename,
'\\') + 1;
1455 sprintf(AssertText2,
"Warning: %s\r\nFile: %s\r\nLine: %d\r\n", AssertText1, filename, line);
1461 #if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
1463 SCP_DebugCallStack callStack;
1464 SCP_DumpStack(dynamic_cast< SCP_IDumpHandler* >(&callStack));
1468 assertString +=
"\n";
1469 assertString += callStack.DumpToString();
1477 assertString +=
"\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
1478 assertString +=
"\n\nUse Yes to break into Debugger, No to continue.\nand Cancel to Quit\n";
1481 #elif defined ( SHOW_CALL_STACK )
1483 Dump_to_log =
false;
1486 dumpBuffer.Printf(AssertText2);
1487 dumpBuffer.Printf(
"\r\n");
1488 DumpCallsStack(dumpBuffer);
1494 dumpBuffer.Printf(
"\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n");
1495 dumpBuffer.Printf(
"\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");
1502 strcat_s(AssertText2,
"\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");
1581 #define nNoMansLandSize 4
1599 #define pHdr(pbData) (((_CrtMemBlockHeader *)pbData)-1)
1617 if ( nBlockUse == _CRT_BLOCK )
1620 _ASSERT( ( nAllocType > 0 ) && ( nAllocType < 4 ) );
1621 _ASSERT( ( nBlockUse >= 0 ) && ( nBlockUse < 5 ) );
1623 if ( nAllocType == 3 ) {
1630 mprintf((
"Memory operation in %s, line %d: %s a %d-byte '%s' block (# %ld)\n",
1631 szFileName, nLine, operation[nAllocType], nSize,
1632 blockType[nBlockUse], lRequest ));
1633 if ( pvData != NULL )
1634 mprintf((
" at %X", pvData ));
1654 DCF_BOOL(watch_malloc, Watch_malloc );
1669 #ifdef _REPORT_MEM_LEAKS
1670 const int MAX_MEM_POINTERS = 50000;
1680 MemPtrInfo mem_ptr_list[MAX_MEM_POINTERS];
1684 const int MAX_MEM_MODULES = 600;
1696 MemBlockInfo mem_block_list[MAX_MEM_MODULES];
1698 int memblockinfo_sort_compare(
const void *arg1,
const void *arg2 )
1700 MemBlockInfo *mbi1 = (MemBlockInfo *) arg1;
1701 MemBlockInfo *mbi2 = (MemBlockInfo *) arg2;
1703 if (mbi1->size > mbi2->size)
1706 if (mbi1->size < mbi2->size)
1712 void memblockinfo_sort()
1714 insertion_sort(mem_block_list, MAX_MEM_MODULES,
sizeof(MemBlockInfo), memblockinfo_sort_compare );
1717 void memblockinfo_sort_get_entry(
int index,
char *
filename,
int *size)
1719 Assert(index < MAX_MEM_MODULES);
1721 strcpy(filename, mem_block_list[index].filename);
1722 *size = mem_block_list[
index].size;
1725 static bool first_time =
true;
1727 void register_malloc(
int size,
char *
filename,
int line,
void *ptr)
1729 if(first_time ==
true)
1731 ZeroMemory(mem_block_list, MAX_MEM_MODULES *
sizeof(MemBlockInfo) );
1735 int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
1738 tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
1741 _CrtSetDbgFlag( tmpFlag );
1743 #ifdef _REPORT_MEM_LEAKS
1744 ZeroMemory(mem_ptr_list, MAX_MEM_POINTERS *
sizeof(MemPtrInfo));
1748 char *
temp = strrchr(filename,
'\\');
1750 filename = temp + 1;
1753 int magic1, magic2,
len = strlen(filename);
1755 magic1 = magic2 = 0;
1757 for(
int c = 0;
c <
len;
c++)
1759 magic1 += filename[
c];
1762 magic2 += filename[
c];
1764 magic2 -= filename[
c];
1767 for(
int i = 0; i < MAX_MEM_MODULES; i++)
1770 if(mem_block_list[i].in_use ==
false)
1772 strcpy_s(mem_block_list[i].filename, filename);
1773 mem_block_list[
i].size =
size;
1774 mem_block_list[
i].magic_num1 = magic1;
1775 mem_block_list[
i].magic_num2 = magic2;
1776 mem_block_list[
i].in_use =
true;
1781 if( mem_block_list[i].magic_num1 == magic1 &&
1782 mem_block_list[i].magic_num2 == magic2 &&
1783 stricmp(mem_block_list[i].filename, filename) == 0)
1785 mem_block_list[
i].size +=
size;
1791 #ifdef _REPORT_MEM_LEAKS
1795 while(mem_ptr_list[count].ptr != NULL)
1799 Assert(count < MAX_MEM_POINTERS);
1801 mem_ptr_list[
count].ptr = ptr;
1802 mem_ptr_list[
count].line = line;
1804 strcpy_s(mem_ptr_list[count].filename, filename);
1809 void memblockinfo_output_memleak()
1817 _RPT1(_CRT_WARN,
"TotalRam bad value!",TotalRam);
1821 _RPT1(_CRT_WARN,
"malloc memory leak of %d\n",TotalRam);
1824 #ifdef _REPORT_MEM_LEAKS
1828 for(
int f = 0;
f < MAX_MEM_POINTERS;
f++)
1830 if(mem_ptr_list[
f].ptr)
1832 _RPT3(_CRT_WARN,
"Memory leaks: (%s line %d) of %d bytes\n", mem_ptr_list[
f].filename, mem_ptr_list[
f].line, mem_ptr_list[
f].size);
1833 total += mem_ptr_list[
f].size;
1837 Assert(TotalRam == total);
1841 for(
int i = 0; i < MAX_MEM_MODULES; i++)
1844 if(mem_block_list[i].size > 0)
1847 _RPT2(_CRT_WARN,
"Possible memory leaks: %s %d\n", mem_block_list[i].filename, mem_block_list[i].size);
1853 void unregister_malloc(
char *filename,
int size,
void *ptr)
1856 int magic1, magic2,
len;
1858 char *temp = strrchr(filename,
'\\');
1860 filename = temp + 1;
1862 len = strlen(filename);
1864 magic1 = magic2 = 0;
1866 for(
int c = 0;
c <
len;
c++)
1868 magic1 += filename[
c];
1871 magic2 += filename[
c];
1873 magic2 -= filename[
c];
1877 #ifdef _REPORT_MEM_LEAKS
1880 for(
int f = 0;
f < MAX_MEM_POINTERS;
f++)
1882 if(mem_ptr_list[
f].ptr == ptr) {
1883 mem_ptr_list[
f].ptr = NULL;
1890 for(
int i = 0; i < MAX_MEM_MODULES; i++)
1893 if( mem_block_list[i].magic_num1 == magic1 &&
1894 mem_block_list[i].magic_num2 == magic2 &&
1895 stricmp(mem_block_list[i].filename, filename) == 0)
1897 mem_block_list[
i].size -=
size;
1906 void *
_vm_malloc(
int size,
char *filename,
int line,
int quiet )
1913 ptr = _malloc_dbg(size, _NORMAL_BLOCK, __FILE__, __LINE__ );
1917 mprintf((
"Malloc failed!!!!!!!!!!!!!!!!!!!\n" ));
1929 register_malloc(size, filename, line, ptr);
1941 int len = strlen(ptr);
1953 char *
_vm_strndup(
const char *ptr,
int size,
char *filename,
int line )
1965 strncpy( dst, ptr, size );
1990 unregister_malloc(filename, nSize, ptr);
1993 _free_dbg(ptr,_NORMAL_BLOCK);
2001 void *
_vm_realloc(
void *ptr,
int size,
char *filename,
int line,
int quiet )
2003 void *
_vm_realloc(
void *ptr,
int size,
int quiet )
2010 void *ret_ptr = NULL;
2019 unregister_malloc(filename, nSize, ptr);
2022 ret_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, __FILE__, __LINE__ );
2024 if (ret_ptr == NULL) {
2025 mprintf((
"realloc failed!!!!!!!!!!!!!!!!!!!\n" ));
2027 if (quiet && (size > 0) && (ptr != NULL)) {
2032 Error(
LOCATION,
"Out of memory. Try closing down other applications, increasing your\n"
2033 "virtual memory size, or installing more physical RAM.\n");
2040 register_malloc(size, filename, line, ret_ptr);
GLenum GLsizei GLenum format
const char * clean_filename(const char *name)
GLuint GLuint GLuint GLuint arg1
void * _vm_malloc(int size, char *filename, int line, int quiet)
struct _CrtMemBlockHeader _CrtMemBlockHeader
char * _vm_strndup(const char *ptr, int size, char *filename, int line)
char * _vm_strdup(const char *ptr, char *filename, int line)
void * _vm_realloc(void *ptr, int size, char *filename, int line, int quiet)
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
void _vm_free(void *ptr, char *filename, int line)
GLint GLint GLsizei GLsizei GLsizei depth
DCF_BOOL(watch_malloc, Watch_malloc)
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
GLenum GLuint GLenum GLsizei const GLchar * buf
int Cmdline_show_mem_usage
void _cdecl Error(const char *filename, int line, const char *format,...)
const int Messagebox_lines
void gr_activate(int active)
#define strnicmp(s1, s2, n)
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
void insertion_sort(void *array_base, size_t array_size, size_t element_size, int(*fncompare)(const void *, const void *))
void truncate_message_lines(SCP_string &text, int num_allowed_lines)
void LuaDebugPrint(lua_Debug &ar)
GLuint const GLchar * name
void ade_stackdump(lua_State *L, char *stackdump)
void _cdecl WarningEx(char *filename, int line, const char *format,...)
void dump_text_to_clipboard(const char *text)
void _cdecl Warning(char *filename, int line, const char *format,...)
int vm_init(int min_heap_size)
void windebug_memwatch_init()
An overhauled/updated debug console to allow monitoring, testing, and general debugging of new featur...
void _cdecl WinAssert(char *text, char *filename, int linenum)
int MessageBox(HWND h, const char *s1, const char *s2, int i)
void LuaError(struct lua_State *L, const char *format,...)
void _cdecl ReleaseWarning(char *filename, int line, const char *format,...)