diff options
Diffstat (limited to 'utils/xbox/vxconsole/show_memdump.cpp')
| -rw-r--r-- | utils/xbox/vxconsole/show_memdump.cpp | 1440 |
1 files changed, 1440 insertions, 0 deletions
diff --git a/utils/xbox/vxconsole/show_memdump.cpp b/utils/xbox/vxconsole/show_memdump.cpp new file mode 100644 index 0000000..fc86833 --- /dev/null +++ b/utils/xbox/vxconsole/show_memdump.cpp @@ -0,0 +1,1440 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// SHOW_MEMDUMP.CPP +// +// Show Mem Dump Display. +//=====================================================================================// +#include "vxconsole.h" + +#define ID_SHOWMEMDUMP_LISTVIEW 100 + +// column id, pool mode +#define ID_DUMPPOOL_POOL 0 +#define ID_DUMPPOOL_SIZE 1 +#define ID_DUMPPOOL_ALLOCATED 2 +#define ID_DUMPPOOL_FREE 3 +#define ID_DUMPPOOL_COMMITTED 4 +#define ID_DUMPPOOL_COMMITTEDSIZE 5 + +// column id, detailed mode +#define ID_DUMPDETAIL_ALLOCATION 0 +#define ID_DUMPDETAIL_CURRENTSIZE 1 +#define ID_DUMPDETAIL_PEAKSIZE 2 +#define ID_DUMPDETAIL_TOTALSIZE 3 +#define ID_DUMPDETAIL_OVERHEAD 4 +#define ID_DUMPDETAIL_PEAKOVERHEAD 5 +#define ID_DUMPDETAIL_TIME 6 +#define ID_DUMPDETAIL_CURRENTCOUNT 7 +#define ID_DUMPDETAIL_PEAKCOUNT 8 +#define ID_DUMPDETAIL_TOTALCOUNT 9 +#define ID_DUMPDETAIL_LTE16 10 +#define ID_DUMPDETAIL_LTE32 11 +#define ID_DUMPDETAIL_LTE128 12 +#define ID_DUMPDETAIL_LTE1024 13 +#define ID_DUMPDETAIL_GT1024 14 + +#define SHOW_BYTES 0 +#define SHOW_KILOBYTES 1 +#define SHOW_MEGABYTES 2 + +#define FORMAT_POOLS 0 +#define FORMAT_DETAILS 1 + +struct MemoryPool_t +{ + int pool; + char poolBuff[32]; + int size; + char sizeBuff[32]; + int allocated; + char allocatedBuff[32]; + int free; + char freeBuff[32]; + int committed; + char committedBuff[32]; + int committedSize; + char committedSizeBuff[32]; +}; + +struct MemoryDetail_t +{ + char *pAllocationName; + int currentSize; + char currentSizeBuff[32]; + int peakSize; + char peakSizeBuff[32]; + int totalSize; + char totalSizeBuff[32]; + int overheadSize; + char overheadSizeBuff[32]; + int peakOverheadSize; + char peakOverheadSizeBuff[32]; + int time; + char timeBuff[32]; + int currentCount; + char currentCountBuff[32]; + int peakCount; + char peakCountBuff[32]; + int totalCount; + char totalCountBuff[32]; + int lte16; + char lte16Buff[32]; + int lte32; + char lte32Buff[32]; + int lte128; + char lte128Buff[32]; + int lte1024; + char lte1024Buff[32]; + int gt1024; + char gt1024Buff[32]; +}; + +struct memory_t +{ + int listIndex; + MemoryPool_t pool; + MemoryDetail_t detail; +}; + +struct label_t +{ + const CHAR* name; + int width; + int subItemIndex; + CHAR nameBuff[64]; +}; + +HWND g_showMemDump_hWnd; +HWND g_showMemDump_hWndListView; +RECT g_showMemDump_windowRect; +int g_showMemDump_sortColumn; +int g_showMemDump_sortDescending; +memory_t *g_showMemDump_pMemory; +int g_showMemDump_numMemory; +int g_showMemDump_showBytes; +bool g_showMemDump_bCollapseOutput; +char g_showMemDump_currentFilename[MAX_PATH]; +int g_showMemDump_format; + +void ShowMemDump_Parse( const char *pBuffer, int fileSize ); + +label_t g_showMemDump_PoolLabels[] = +{ + {"Pool", 120, ID_DUMPPOOL_POOL}, + {"Size", 120, ID_DUMPPOOL_SIZE}, + {"Allocated Count", 120, ID_DUMPPOOL_ALLOCATED}, + {"Free Count", 120, ID_DUMPPOOL_FREE}, + {"Committed Count", 120, ID_DUMPPOOL_COMMITTED}, + {"Committed Size", 120, ID_DUMPPOOL_COMMITTEDSIZE}, +}; + +label_t g_showMemDump_DetailLabels[] = +{ + {"Allocation", 200, ID_DUMPDETAIL_ALLOCATION}, + {"Current Size", 120, ID_DUMPDETAIL_CURRENTSIZE}, + {"Peak Size", 120, ID_DUMPDETAIL_PEAKSIZE}, + {"Total Allocations", 120, ID_DUMPDETAIL_TOTALSIZE}, + {"Overhead Size", 120, ID_DUMPDETAIL_OVERHEAD}, + {"Peak Overhead Size", 120, ID_DUMPDETAIL_PEAKOVERHEAD}, + {"Time (ms)", 120, ID_DUMPDETAIL_TIME}, + {"Current Count", 120, ID_DUMPDETAIL_CURRENTCOUNT}, + {"Peak Count", 120, ID_DUMPDETAIL_PEAKCOUNT}, + {"Total Count", 120, ID_DUMPDETAIL_TOTALCOUNT}, + {"<=16 bytes", 100, ID_DUMPDETAIL_LTE16}, + {"17-32 bytes", 100, ID_DUMPDETAIL_LTE32}, + {"33-128 bytes", 100, ID_DUMPDETAIL_LTE128}, + {"129-1024 bytes", 100, ID_DUMPDETAIL_LTE1024}, + {"> 1024 bytes", 100, ID_DUMPDETAIL_GT1024}, +}; + +//----------------------------------------------------------------------------- +// ShowMemDump_FormatSize +// +//----------------------------------------------------------------------------- +char *ShowMemDump_FormatSize( int size, char *pBuff, bool bUnits ) +{ + switch ( g_showMemDump_showBytes ) + { + case SHOW_BYTES: + sprintf( pBuff, "%d", size ); + break; + + case SHOW_KILOBYTES: + sprintf( pBuff, "%.2f", (float)size/1024.0f ); + if ( bUnits ) + strcat( pBuff, " K"); + break; + + case SHOW_MEGABYTES: + sprintf( pBuff, "%.2f", (float)size/(1024.0f*1024.0f) ); + if ( bUnits ) + strcat( pBuff, " MB"); + break; + } + + return pBuff; +} + + +//----------------------------------------------------------------------------- +// ShowMemDump_SaveConfig +// +//----------------------------------------------------------------------------- +void ShowMemDump_SaveConfig() +{ + char buff[256]; + + Sys_SetRegistryInteger( "showMemDumpSortColumn", g_showMemDump_sortColumn ); + Sys_SetRegistryInteger( "showMemDumpSortDescending", g_showMemDump_sortDescending ); + Sys_SetRegistryInteger( "showMemDumpShowBytes", g_showMemDump_showBytes ); + + WINDOWPLACEMENT wp; + memset( &wp, 0, sizeof( wp ) ); + wp.length = sizeof( WINDOWPLACEMENT ); + GetWindowPlacement( g_showMemDump_hWnd, &wp ); + g_showMemDump_windowRect = wp.rcNormalPosition; + + sprintf( buff, "%d %d %d %d", g_showMemDump_windowRect.left, g_showMemDump_windowRect.top, g_showMemDump_windowRect.right, g_showMemDump_windowRect.bottom ); + Sys_SetRegistryString( "showMemDumpWindowRect", buff ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_LoadConfig +// +//----------------------------------------------------------------------------- +void ShowMemDump_LoadConfig() +{ + int numArgs; + char buff[256]; + + Sys_GetRegistryInteger( "showMemDumpSortColumn", 0, g_showMemDump_sortColumn ); + Sys_GetRegistryInteger( "showMemDumpSortDescending", false, g_showMemDump_sortDescending ); + Sys_GetRegistryInteger( "showMemDumpShowBytes", SHOW_KILOBYTES, g_showMemDump_showBytes ); + + Sys_GetRegistryString( "showMemDumpWindowRect", buff, "", sizeof( buff ) ); + numArgs = sscanf( buff, "%d %d %d %d", &g_showMemDump_windowRect.left, &g_showMemDump_windowRect.top, &g_showMemDump_windowRect.right, &g_showMemDump_windowRect.bottom ); + if ( numArgs != 4 || g_showMemDump_windowRect.left < 0 || g_showMemDump_windowRect.top < 0 || g_showMemDump_windowRect.right < 0 || g_showMemDump_windowRect.bottom < 0 ) + memset( &g_showMemDump_windowRect, 0, sizeof( g_showMemDump_windowRect ) ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_Clear +// +//----------------------------------------------------------------------------- +void ShowMemDump_Clear() +{ + // delete all the list view entries + if ( g_showMemDump_hWnd ) + { + ListView_DeleteAllItems( g_showMemDump_hWndListView ); + } + + if ( !g_showMemDump_pMemory ) + return; + + for ( int i=0; i<g_showMemDump_numMemory; i++ ) + { + delete [] g_showMemDump_pMemory[i].detail.pAllocationName; + } + + Sys_Free( g_showMemDump_pMemory ); + + g_showMemDump_pMemory = NULL; + g_showMemDump_numMemory = 0; +} + +//----------------------------------------------------------------------------- +// ShowMemDump_Export +// +//----------------------------------------------------------------------------- +void ShowMemDump_Export() +{ + OPENFILENAME ofn; + char logFilename[MAX_PATH]; + int retval; + FILE* fp; + int i; + char buff[64]; + + if ( g_showMemDump_format != FORMAT_DETAILS ) + { + return; + } + + memset( &ofn, 0, sizeof( ofn ) ); + ofn.lStructSize = sizeof( ofn ); + ofn.hwndOwner = g_showMemDump_hWnd; + ofn.lpstrFile = logFilename; + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = sizeof( logFilename ); + ofn.lpstrFilter = "Excel CSV\0*.CSV\0All Files\0*.*\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = "c:\\"; + ofn.Flags = OFN_PATHMUSTEXIST; + + // display the Open dialog box. + retval = GetOpenFileName( &ofn ); + if ( !retval ) + return; + + Sys_AddExtension( ".csv", logFilename, sizeof( logFilename ) ); + + fp = fopen( logFilename, "wt+" ); + if ( !fp ) + return; + + // labels + fprintf( fp, "Allocation Type" ); + fprintf( fp, ",Current Size" ); + fprintf( fp, ",Peak Size" ); + fprintf( fp, ",Total Allocations" ); + fprintf( fp, ",Overhead Size" ); + fprintf( fp, ",Peak Overhead Size" ); + fprintf( fp, ",Time(ms)" ); + fprintf( fp, ",Current Count" ); + fprintf( fp, ",Peak Count" ); + fprintf( fp, ",Total Count" ); + fprintf( fp, ",<=16 Byte Allocations" ); + fprintf( fp, ",17-32 Byte Allocations" ); + fprintf( fp, ",33-128 Byte Allocations" ); + fprintf( fp, ",129-1024 Byte Allocations" ); + fprintf( fp, ",>1024 Byte Allocations" ); + fprintf( fp, "\n" ); + + // dump to the log + for ( i=0; i<g_showMemDump_numMemory; i++ ) + { + fprintf( fp, "\"%s\"", g_showMemDump_pMemory[i].detail.pAllocationName ); + fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.currentSize, buff, false ) ); + fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakSize, buff, false ) ); + fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.totalSize, buff, false ) ); + fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.overheadSize, buff, false ) ); + fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakOverheadSize, buff, false ) ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.time ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.currentCount ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.peakCount ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.totalCount ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte16 ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte32 ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte128 ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte1024 ); + fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.gt1024 ); + fprintf( fp, "\n" ); + } + + fclose( fp ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_Summary +// +//----------------------------------------------------------------------------- +void ShowMemDump_Summary() +{ + char buff[1024]; + int i; + + if ( g_showMemDump_format != FORMAT_DETAILS ) + { + return; + } + + int currentSize = 0; + int peakSize = 0; + int totalSize = 0; + int overheadSize = 0; + int peakOverheadSize = 0; + int time = 0; + int currentCount = 0; + int peakCount = 0; + int totalCount = 0; + int lte16 = 0; + int lte32 = 0; + int lte128 = 0; + int lte1024 = 0; + int gt1024 = 0; + + // tally the totals + for (i=0; i<g_showMemDump_numMemory; i++) + { + if ( !strnicmp( g_showMemDump_pMemory[i].detail.pAllocationName, "Totals,", 7 ) ) + continue; + + currentSize += g_showMemDump_pMemory[i].detail.currentSize; + peakSize += g_showMemDump_pMemory[i].detail.peakSize; + totalSize += g_showMemDump_pMemory[i].detail.totalSize; + overheadSize += g_showMemDump_pMemory[i].detail.overheadSize; + peakOverheadSize += g_showMemDump_pMemory[i].detail.peakOverheadSize; + time += g_showMemDump_pMemory[i].detail.time; + currentCount += g_showMemDump_pMemory[i].detail.currentCount; + peakCount += g_showMemDump_pMemory[i].detail.peakCount; + totalCount += g_showMemDump_pMemory[i].detail.totalCount; + lte16 += g_showMemDump_pMemory[i].detail.lte16; + lte32 += g_showMemDump_pMemory[i].detail.lte32; + lte128 += g_showMemDump_pMemory[i].detail.lte128; + lte1024 += g_showMemDump_pMemory[i].detail.lte1024; + gt1024 += g_showMemDump_pMemory[i].detail.gt1024; + } + + sprintf( + buff, + "Entries:\t\t\t%d\n" + "Current Size:\t\t%.2f MB\n" + "Peak Size:\t\t%.2f MB\n" + "Total Size:\t\t%.2f MB\n" + "Overhead Size:\t\t%d\n" + "Peak Overhead Size:\t%d\n" + "Time:\t\t\t%d\n" + "Current Count:\t\t%d\n" + "Peak Count:\t\t%d\n" + "Total Count:\t\t%d\n" + "<= 16:\t\t\t%d\n" + "17-32:\t\t\t%d\n" + "33-128:\t\t\t%d\n" + "129-1024:\t\t%d\n" + "> 1024:\t\t\t%d\n", + g_showMemDump_numMemory, + (float)currentSize/( 1024.0F*1024.0F ), + (float)peakSize/( 1024.0F*1024.0F ), + (float)totalSize/( 1024.0F*1024.0F ), + overheadSize, + peakOverheadSize, + time, + currentCount, + peakCount, + totalCount, + lte16, + lte32, + lte128, + lte1024, + gt1024 ); + + MessageBox( g_showMemDump_hWnd, buff, "Memory Dump Summary", MB_OK|MB_APPLMODAL ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_SetTitle +// +//----------------------------------------------------------------------------- +void ShowMemDump_SetTitle() +{ + if ( g_showMemDump_hWnd ) + { + SetWindowText( g_showMemDump_hWnd, "Memory Dump" ); + } +} + +//----------------------------------------------------------------------------- +// ShowMemDump_CompareFunc +// +//----------------------------------------------------------------------------- +int CALLBACK ShowMemDump_CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ) +{ + memory_t* pMemoryA = (memory_t*)lParam1; + memory_t* pMemoryB = (memory_t*)lParam2; + + int sort = 0; + + if ( g_showMemDump_format == FORMAT_POOLS ) + { + switch ( g_showMemDump_sortColumn ) + { + case ID_DUMPPOOL_POOL: + sort = pMemoryA->pool.pool - pMemoryB->pool.pool; + break; + + case ID_DUMPPOOL_SIZE: + sort = pMemoryA->pool.size - pMemoryB->pool.size; + break; + + case ID_DUMPPOOL_ALLOCATED: + sort = pMemoryA->pool.allocated - pMemoryB->pool.allocated; + break; + + case ID_DUMPPOOL_FREE: + sort = pMemoryA->pool.free - pMemoryB->pool.free; + break; + + case ID_DUMPPOOL_COMMITTED: + sort = pMemoryA->pool.committed - pMemoryB->pool.committed; + break; + + case ID_DUMPPOOL_COMMITTEDSIZE: + sort = pMemoryA->pool.committedSize - pMemoryB->pool.committedSize; + break; + } + } + else + { + switch ( g_showMemDump_sortColumn ) + { + case ID_DUMPDETAIL_ALLOCATION: + sort = stricmp( pMemoryA->detail.pAllocationName, pMemoryB->detail.pAllocationName ); + break; + + case ID_DUMPDETAIL_CURRENTSIZE: + sort = pMemoryA->detail.currentSize - pMemoryB->detail.currentSize; + break; + + case ID_DUMPDETAIL_PEAKSIZE: + sort = pMemoryA->detail.peakSize - pMemoryB->detail.peakSize; + break; + + case ID_DUMPDETAIL_TOTALSIZE: + sort = pMemoryA->detail.totalSize - pMemoryB->detail.totalSize; + break; + + case ID_DUMPDETAIL_OVERHEAD: + sort = pMemoryA->detail.overheadSize - pMemoryB->detail.overheadSize; + break; + + case ID_DUMPDETAIL_PEAKOVERHEAD: + sort = pMemoryA->detail.peakOverheadSize - pMemoryB->detail.peakOverheadSize; + break; + + case ID_DUMPDETAIL_TIME: + sort = pMemoryA->detail.time - pMemoryB->detail.time; + break; + + case ID_DUMPDETAIL_CURRENTCOUNT: + sort = pMemoryA->detail.currentCount - pMemoryB->detail.currentCount; + break; + + case ID_DUMPDETAIL_PEAKCOUNT: + sort = pMemoryA->detail.peakCount - pMemoryB->detail.peakCount; + break; + + case ID_DUMPDETAIL_TOTALCOUNT: + sort = pMemoryA->detail.totalCount - pMemoryB->detail.totalCount; + break; + + case ID_DUMPDETAIL_LTE16: + sort = pMemoryA->detail.lte16 - pMemoryB->detail.lte16; + break; + + case ID_DUMPDETAIL_LTE32: + sort = pMemoryA->detail.lte32 - pMemoryB->detail.lte32; + break; + + case ID_DUMPDETAIL_LTE128: + sort = pMemoryA->detail.lte128 - pMemoryB->detail.lte128; + break; + + case ID_DUMPDETAIL_LTE1024: + sort = pMemoryA->detail.lte1024 - pMemoryB->detail.lte1024; + break; + + case ID_DUMPDETAIL_GT1024: + sort = pMemoryA->detail.gt1024 - pMemoryB->detail.gt1024; + break; + } + } + + // flip the sort order + if ( g_showMemDump_sortDescending ) + { + sort *= -1; + } + + return ( sort ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_SortItems +// +//----------------------------------------------------------------------------- +void ShowMemDump_SortItems() +{ + LVITEM lvitem; + memory_t *pMemory; + int i; + + if ( !g_showMemDump_hWnd ) + { + // only sort if window is visible + return; + } + + ListView_SortItems( g_showMemDump_hWndListView, ShowMemDump_CompareFunc, 0 ); + + memset( &lvitem, 0, sizeof( lvitem ) ); + lvitem.mask = LVIF_PARAM; + + // get each item and reset its list index + int itemCount = ListView_GetItemCount( g_showMemDump_hWndListView ); + for ( i=0; i<itemCount; i++ ) + { + lvitem.iItem = i; + ListView_GetItem( g_showMemDump_hWndListView, &lvitem ); + + pMemory = (memory_t*)lvitem.lParam; + pMemory->listIndex = i; + } + + int count; + label_t* pLabels; + if ( g_showMemDump_format == FORMAT_POOLS ) + { + count = sizeof( g_showMemDump_PoolLabels )/sizeof( g_showMemDump_PoolLabels[0] ); + pLabels = g_showMemDump_PoolLabels; + } + else + { + count = sizeof( g_showMemDump_DetailLabels )/sizeof( g_showMemDump_DetailLabels[0] ); + pLabels = g_showMemDump_DetailLabels; + } + + // update list view columns with sort key + for ( i = 0; i < count; i++ ) + { + char symbol; + LVCOLUMN lvc; + + if ( i == g_showMemDump_sortColumn ) + symbol = g_showMemDump_sortDescending ? '<' : '>'; + else + symbol = ' '; + sprintf( pLabels[i].nameBuff, "%s %c", pLabels[i].name, symbol ); + + memset( &lvc, 0, sizeof( lvc ) ); + lvc.mask = LVCF_TEXT; + lvc.pszText = (LPSTR)pLabels[i].nameBuff; + + ListView_SetColumn( g_showMemDump_hWndListView, i, &lvc ); + } +} + +//----------------------------------------------------------------------------- +// ShowMemDump_FormatItems +// +//----------------------------------------------------------------------------- +void ShowMemDump_FormatItems() +{ + if ( g_showMemDump_format == FORMAT_POOLS ) + { + for ( int i = 0; i < g_showMemDump_numMemory; i++ ) + { + sprintf( g_showMemDump_pMemory[i].pool.sizeBuff, "%d", g_showMemDump_pMemory[i].pool.size ); + ShowMemDump_FormatSize( g_showMemDump_pMemory[i].pool.committedSize, g_showMemDump_pMemory[i].pool.committedSizeBuff, true ); + } + } + else + { + for ( int i = 0; i < g_showMemDump_numMemory; i++ ) + { + ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.currentSize, g_showMemDump_pMemory[i].detail.currentSizeBuff, true ); + ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakSize, g_showMemDump_pMemory[i].detail.peakSizeBuff, true ); + ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.totalSize, g_showMemDump_pMemory[i].detail.totalSizeBuff, true ); + ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.overheadSize, g_showMemDump_pMemory[i].detail.overheadSizeBuff, true ); + ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakOverheadSize, g_showMemDump_pMemory[i].detail.peakOverheadSizeBuff, true ); + } + } + + ShowMemDump_SortItems(); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_AddViewItem +// +//----------------------------------------------------------------------------- +void ShowMemDump_AddViewItem( memory_t* pMemory ) +{ + LVITEM lvi; + + if ( !g_showMemDump_hWnd ) + { + // only valid if log window is visible + return; + } + + // update the text callback buffers + if ( g_showMemDump_format == FORMAT_POOLS ) + { + sprintf( pMemory->pool.sizeBuff, "%d", pMemory->pool.size ); + sprintf( pMemory->pool.poolBuff, "%d", pMemory->pool.pool ); + sprintf( pMemory->pool.allocatedBuff, "%d", pMemory->pool.allocated ); + sprintf( pMemory->pool.freeBuff, "%d", pMemory->pool.free ); + sprintf( pMemory->pool.committedBuff, "%d", pMemory->pool.committed ); + ShowMemDump_FormatSize( pMemory->pool.committedSize, pMemory->pool.committedSizeBuff, true ); + } + else + { + ShowMemDump_FormatSize( pMemory->detail.currentSize, pMemory->detail.currentSizeBuff, true ); + ShowMemDump_FormatSize( pMemory->detail.peakSize, pMemory->detail.peakSizeBuff, true ); + ShowMemDump_FormatSize( pMemory->detail.totalSize, pMemory->detail.totalSizeBuff, true ); + ShowMemDump_FormatSize( pMemory->detail.overheadSize, pMemory->detail.overheadSizeBuff, true ); + ShowMemDump_FormatSize( pMemory->detail.peakOverheadSize, pMemory->detail.peakOverheadSizeBuff, true ); + sprintf( pMemory->detail.timeBuff, "%d", pMemory->detail.time ); + sprintf( pMemory->detail.currentCountBuff, "%d", pMemory->detail.currentCount ); + sprintf( pMemory->detail.peakCountBuff, "%d", pMemory->detail.peakCount ); + sprintf( pMemory->detail.totalCountBuff, "%d", pMemory->detail.totalCount ); + sprintf( pMemory->detail.lte16Buff, "%d", pMemory->detail.lte16 ); + sprintf( pMemory->detail.lte32Buff, "%d", pMemory->detail.lte32 ); + sprintf( pMemory->detail.lte128Buff, "%d", pMemory->detail.lte128 ); + sprintf( pMemory->detail.lte1024Buff, "%d", pMemory->detail.lte1024 ); + sprintf( pMemory->detail.gt1024Buff, "%d", pMemory->detail.gt1024 ); + } + + int itemCount = ListView_GetItemCount( g_showMemDump_hWndListView ); + + // setup and insert at end of list + memset( &lvi, 0, sizeof( lvi ) ); + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; + lvi.iItem = itemCount; + lvi.iSubItem = 0; + lvi.state = 0; + lvi.stateMask = 0; + lvi.pszText = LPSTR_TEXTCALLBACK; + lvi.lParam = (LPARAM)pMemory; + + // insert and set the real index + pMemory->listIndex = ListView_InsertItem( g_showMemDump_hWndListView, &lvi ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_Refresh +// +//----------------------------------------------------------------------------- +void ShowMemDump_Refresh() +{ + // send the command to application which replies with list data + if ( g_connectedToApp ) + { + ProcessCommand( "mem_dump" ); + } +} + +//----------------------------------------------------------------------------- +// ShowMemDump_RefreshView +// +//----------------------------------------------------------------------------- +void ShowMemDump_RefreshView() +{ + if ( strlen( g_showMemDump_currentFilename ) == 0 ) + { + // first time + ShowMemDump_Refresh(); + return; + } + + // get current file + int fileSize; + char *pBuffer; + bool bSuccess = LoadTargetFile( g_showMemDump_currentFilename, &fileSize, (void **)&pBuffer ); + if ( !bSuccess ) + { + // stale, try again + ShowMemDump_Refresh(); + return; + } + + // parse and update view + ShowMemDump_Parse( pBuffer, fileSize ); + + Sys_Free( pBuffer ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_PopulateList +// +//----------------------------------------------------------------------------- +void ShowMemDump_PopulateList() +{ + // delete previous labels + while ( 1 ) + { + if ( !ListView_DeleteColumn( g_showMemDump_hWndListView, 0 ) ) + { + break; + } + } + + int count; + label_t* pLabels; + if ( g_showMemDump_format == FORMAT_POOLS ) + { + count = sizeof( g_showMemDump_PoolLabels )/sizeof( g_showMemDump_PoolLabels[0] ); + pLabels = g_showMemDump_PoolLabels; + } + else + { + count = sizeof( g_showMemDump_DetailLabels )/sizeof( g_showMemDump_DetailLabels[0] ); + pLabels = g_showMemDump_DetailLabels; + } + + // init list view columns + for ( int i = 0; i < count; i++ ) + { + LVCOLUMN lvc; + memset( &lvc, 0, sizeof( lvc ) ); + + lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM; + lvc.iSubItem = 0; + lvc.cx = pLabels[i].width; + lvc.fmt = LVCFMT_LEFT; + lvc.pszText = ( LPSTR )pLabels[i].name; + + ListView_InsertColumn( g_showMemDump_hWndListView, i, &lvc ); + } + + // populate list view + for ( int i = 0; i < g_showMemDump_numMemory; i++ ) + { + ShowMemDump_AddViewItem( &g_showMemDump_pMemory[i] ); + } + + ShowMemDump_SortItems(); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_SizeWindow +// +//----------------------------------------------------------------------------- +void ShowMemDump_SizeWindow( HWND hwnd, int cx, int cy ) +{ + if ( cx==0 || cy==0 ) + { + RECT rcClient; + GetClientRect( hwnd, &rcClient ); + cx = rcClient.right; + cy = rcClient.bottom; + } + + // position the ListView + SetWindowPos( g_showMemDump_hWndListView, NULL, 0, 0, cx, cy, SWP_NOZORDER ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_WndProc +// +//----------------------------------------------------------------------------- +LRESULT CALLBACK ShowMemDump_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) +{ + WORD wID = LOWORD( wParam ); + memory_t* pMemory; + + switch ( message ) + { + case WM_CREATE: + return 0L; + + case WM_DESTROY: + ShowMemDump_SaveConfig(); + + g_showMemDump_hWnd = NULL; + return 0L; + + case WM_INITMENU: + CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_BYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_BYTES ? MF_CHECKED : MF_UNCHECKED ) ); + CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_KILOBYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_KILOBYTES ? MF_CHECKED : MF_UNCHECKED ) ); + CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_MEGABYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_MEGABYTES ? MF_CHECKED : MF_UNCHECKED ) ); + CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_COLLAPSEOUTPUT, MF_BYCOMMAND | ( g_showMemDump_bCollapseOutput ? MF_CHECKED : MF_UNCHECKED ) ); + return 0L; + + case WM_SIZE: + ShowMemDump_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) ); + return 0L; + + case WM_NOTIFY: + switch ( ( ( LPNMHDR )lParam )->code ) + { + case LVN_COLUMNCLICK: + NMLISTVIEW* pnmlv; + pnmlv = ( NMLISTVIEW* )lParam; + if ( g_showMemDump_sortColumn == pnmlv->iSubItem ) + { + // user has clicked on same column - flip the sort + g_showMemDump_sortDescending ^= 1; + } + else + { + // sort by new column + g_showMemDump_sortColumn = pnmlv->iSubItem; + } + ShowMemDump_SortItems(); + return 0L; + + case LVN_GETDISPINFO: + NMLVDISPINFO* plvdi; + plvdi = (NMLVDISPINFO*)lParam; + pMemory = (memory_t*)plvdi->item.lParam; + + if ( g_showMemDump_format == FORMAT_POOLS ) + { + switch ( plvdi->item.iSubItem ) + { + case ID_DUMPPOOL_POOL: + plvdi->item.pszText = pMemory->pool.poolBuff; + return 0L; + + case ID_DUMPPOOL_SIZE: + plvdi->item.pszText = pMemory->pool.sizeBuff; + return 0L; + + case ID_DUMPPOOL_ALLOCATED: + plvdi->item.pszText = pMemory->pool.allocatedBuff; + return 0L; + + case ID_DUMPPOOL_FREE: + plvdi->item.pszText = pMemory->pool.freeBuff; + return 0L; + + case ID_DUMPPOOL_COMMITTED: + plvdi->item.pszText = pMemory->pool.committedBuff; + return 0L; + + case ID_DUMPPOOL_COMMITTEDSIZE: + plvdi->item.pszText = pMemory->pool.committedSizeBuff; + return 0L; + } + } + else + { + switch ( plvdi->item.iSubItem ) + { + case ID_DUMPDETAIL_ALLOCATION: + plvdi->item.pszText = pMemory->detail.pAllocationName; + return 0L; + + case ID_DUMPDETAIL_CURRENTSIZE: + plvdi->item.pszText = pMemory->detail.currentSizeBuff; + return 0L; + + case ID_DUMPDETAIL_PEAKSIZE: + plvdi->item.pszText = pMemory->detail.peakSizeBuff; + return 0L; + + case ID_DUMPDETAIL_TOTALSIZE: + plvdi->item.pszText = pMemory->detail.totalSizeBuff; + return 0L; + + case ID_DUMPDETAIL_OVERHEAD: + plvdi->item.pszText = pMemory->detail.overheadSizeBuff; + return 0L; + + case ID_DUMPDETAIL_PEAKOVERHEAD: + plvdi->item.pszText = pMemory->detail.peakOverheadSizeBuff; + return 0L; + + case ID_DUMPDETAIL_TIME: + plvdi->item.pszText = pMemory->detail.timeBuff; + return 0L; + + case ID_DUMPDETAIL_CURRENTCOUNT: + plvdi->item.pszText = pMemory->detail.currentCountBuff; + return 0L; + + case ID_DUMPDETAIL_PEAKCOUNT: + plvdi->item.pszText = pMemory->detail.peakCountBuff; + return 0L; + + case ID_DUMPDETAIL_TOTALCOUNT: + plvdi->item.pszText = pMemory->detail.totalCountBuff; + return 0L; + + case ID_DUMPDETAIL_LTE16: + plvdi->item.pszText = pMemory->detail.lte16Buff; + return 0L; + + case ID_DUMPDETAIL_LTE32: + plvdi->item.pszText = pMemory->detail.lte32Buff; + return 0L; + + case ID_DUMPDETAIL_LTE128: + plvdi->item.pszText = pMemory->detail.lte128Buff; + return 0L; + + case ID_DUMPDETAIL_LTE1024: + plvdi->item.pszText = pMemory->detail.lte1024Buff; + return 0L; + + case ID_DUMPDETAIL_GT1024: + plvdi->item.pszText = pMemory->detail.gt1024Buff; + return 0L; + + default: + break; + } + } + break; + } + break; + + case WM_COMMAND: + switch ( wID ) + { + case IDM_OPTIONS_REFRESH: + ShowMemDump_Refresh(); + return 0L; + + case IDM_OPTIONS_EXPORT: + ShowMemDump_Export(); + return 0L; + + case IDM_OPTIONS_SUMMARY: + ShowMemDump_Summary(); + return 0L; + + case IDM_OPTIONS_BYTES: + g_showMemDump_showBytes = SHOW_BYTES; + ShowMemDump_FormatItems(); + return 0L; + + case IDM_OPTIONS_KILOBYTES: + g_showMemDump_showBytes = SHOW_KILOBYTES; + ShowMemDump_FormatItems(); + return 0L; + + case IDM_OPTIONS_MEGABYTES: + g_showMemDump_showBytes = SHOW_MEGABYTES; + ShowMemDump_FormatItems(); + return 0L; + + case IDM_OPTIONS_COLLAPSEOUTPUT: + g_showMemDump_bCollapseOutput = !g_showMemDump_bCollapseOutput; + ShowMemDump_RefreshView(); + return 0L; + } + break; + } + + return ( DefWindowProc( hwnd, message, wParam, lParam ) ); +} + +//----------------------------------------------------------------------------- +// ShowMemDump_Init +// +//----------------------------------------------------------------------------- +bool ShowMemDump_Init() +{ + // set up our window class + WNDCLASS wndclass; + + memset( &wndclass, 0, sizeof( wndclass ) ); + wndclass.style = 0; + wndclass.lpfnWndProc = ShowMemDump_WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = g_hInstance; + wndclass.hIcon = g_hIcons[ICON_APPLICATION]; + wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); + wndclass.hbrBackground = g_hBackgroundBrush; + wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_SHOWMEMORYDUMP ); + wndclass.lpszClassName = "SHOWMEMDUMPCLASS"; + if ( !RegisterClass( &wndclass ) ) + return false; + + ShowMemDump_LoadConfig(); + + return true; +} + +//----------------------------------------------------------------------------- +// ShowMemDump_Open +// +//----------------------------------------------------------------------------- +void ShowMemDump_Open() +{ + RECT clientRect; + HWND hWnd; + + if ( g_showMemDump_hWnd ) + { + // only one instance + if ( IsIconic( g_showMemDump_hWnd ) ) + ShowWindow( g_showMemDump_hWnd, SW_RESTORE ); + SetForegroundWindow( g_showMemDump_hWnd ); + return; + } + + hWnd = CreateWindowEx( + WS_EX_CLIENTEDGE, + "SHOWMEMDUMPCLASS", + "", + WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX, + 0, + 0, + 700, + 400, + g_hDlgMain, + NULL, + g_hInstance, + NULL ); + g_showMemDump_hWnd = hWnd; + + GetClientRect( g_showMemDump_hWnd, &clientRect ); + hWnd = CreateWindow( + WC_LISTVIEW, + "", + WS_VISIBLE|WS_CHILD|LVS_REPORT, + 0, + 0, + clientRect.right-clientRect.left, + clientRect.bottom-clientRect.top, + g_showMemDump_hWnd, + ( HMENU )ID_SHOWMEMDUMP_LISTVIEW, + g_hInstance, + NULL ); + g_showMemDump_hWndListView = hWnd; + + ListView_SetBkColor( g_showMemDump_hWndListView, g_backgroundColor ); + ListView_SetTextBkColor( g_showMemDump_hWndListView, g_backgroundColor ); + + DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP; + ListView_SetExtendedListViewStyleEx( g_showMemDump_hWndListView, style, style ); + + ShowMemDump_PopulateList(); + + ShowMemDump_SetTitle(); + + if ( g_showMemDump_windowRect.right && g_showMemDump_windowRect.bottom ) + MoveWindow( g_showMemDump_hWnd, g_showMemDump_windowRect.left, g_showMemDump_windowRect.top, g_showMemDump_windowRect.right-g_showMemDump_windowRect.left, g_showMemDump_windowRect.bottom-g_showMemDump_windowRect.top, FALSE ); + ShowWindow( g_showMemDump_hWnd, SHOW_OPENWINDOW ); + + // get data from application + ShowMemDump_Refresh(); +} + +//----------------------------------------------------------------------------- +// MatchAllocationName +// +//----------------------------------------------------------------------------- +void MatchAllocationName( memory_t *&pMemory ) +{ + memory_t *curEntry = g_showMemDump_pMemory; + for ( int i=0; i<g_showMemDump_numMemory; ++i ) + { + if ( !strcmp( curEntry->detail.pAllocationName, pMemory->detail.pAllocationName ) ) + { + pMemory = curEntry; + return; + } + ++curEntry; + } +} + +//----------------------------------------------------------------------------- +// ShowMemDump_Parse +// +//----------------------------------------------------------------------------- +void ShowMemDump_Parse( const char *pBuffer, int fileSize ) +{ + char *ptr; + char *pToken; + char *pLineStart; + int numLines; + int size; + memory_t *pMemory; + + // remove old entries + ShowMemDump_Clear(); + + if ( !pBuffer || !fileSize ) + { + // no valid data + return; + } + + Sys_SetScriptData( pBuffer, fileSize ); + + // skip first line, column headers + Sys_SkipRestOfLine(); + + Sys_SaveParser(); + + // count lines + numLines = 0; + while ( 1 ) + { + pToken = Sys_GetToken( true ); + if ( !pToken || !pToken[0] ) + break; + numLines++; + Sys_SkipRestOfLine(); + } + + // each line represents one complete entry + g_showMemDump_pMemory = (memory_t *)Sys_Alloc( numLines * sizeof( memory_t ) ); + + Sys_RestoreParser(); + + pMemory = g_showMemDump_pMemory; + + int format = 0; + if ( !V_strnicmp( g_sys_scriptptr, "pool ", 5 ) ) + { + // parse as pool stats + format = FORMAT_POOLS; + + while ( 1 ) + { + // find start of relevant data + bool bFound = false; + while ( 1 ) + { + pToken = Sys_GetToken( true ); + if ( !pToken || !pToken[0] ) + break; + if ( !V_stricmp( pToken, "size:" ) ) + { + bFound = true; + break; + } + } + if ( !bFound ) + { + break; + } + + memset( pMemory, 0, sizeof( memory_t ) ); + + pMemory->pool.pool = g_showMemDump_numMemory; + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->pool.size = atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + if ( !V_stricmp( pToken, "allocated:" ) ) + { + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->pool.allocated = atoi( pToken ); + } + else + { + break; + } + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + if ( !V_stricmp( pToken, "free:" ) ) + { + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->pool.free = atoi( pToken ); + } + else + { + break; + } + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + if ( !V_stricmp( pToken, "committed:" ) ) + { + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->pool.committed = atoi( pToken ); + } + else + { + break; + } + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + if ( !V_stricmp( pToken, "committedsize:" ) ) + { + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->pool.committedSize = atoi( pToken ); + } + else + { + break; + } + + pMemory++; + g_showMemDump_numMemory++; + if ( g_showMemDump_numMemory >= numLines ) + break; + } + } + else + { + // parse as detail stats + format = FORMAT_DETAILS; + + while ( 1 ) + { + pLineStart = g_sys_scriptptr; + + // can't tokenize, find start of parsable data + ptr = V_stristr( g_sys_scriptptr, ", line " ); + if ( !ptr ) + break; + g_sys_scriptptr = ptr + strlen( ", line " ); + + // advance past the expected line number + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + + if ( !g_showMemDump_bCollapseOutput ) + { + size = g_sys_scriptptr-pLineStart; + } + else + { + size = ptr-pLineStart; + } + + memset( pMemory, 0, sizeof(memory_t) ); + memory_t *pCurRecordStart = pMemory; + + pMemory->detail.pAllocationName = new char[size+1]; + memcpy( pMemory->detail.pAllocationName, pLineStart, size ); + pMemory->detail.pAllocationName[size] = '\0'; + Sys_NormalizePath( pMemory->detail.pAllocationName, false ); + + if ( g_showMemDump_bCollapseOutput ) + { + MatchAllocationName( pMemory ); + } + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.currentSize += (int)(1024.0f*atof( pToken )); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.peakSize += (int)(1024.0f*atof( pToken )); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.totalSize += (int)(1024.0f*atof( pToken )); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.overheadSize += (int)(1024.0f*atof( pToken )); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.peakOverheadSize += (int)(1024.0f*atof( pToken )); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.time += atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.currentCount += atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.peakCount += atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.totalCount += atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.lte16 += atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.lte32 += atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.lte128 += atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.lte1024 += atoi( pToken ); + + pToken = Sys_GetToken( false ); + if ( !pToken || !pToken[0] ) + break; + pMemory->detail.gt1024 += atoi( pToken ); + + Sys_SkipRestOfLine(); + + if( pMemory == pCurRecordStart ) + { + pMemory++; + g_showMemDump_numMemory++; + } + else + { + pMemory = pCurRecordStart; + } + + if ( g_showMemDump_numMemory >= numLines ) + break; + } + } + + if ( g_showMemDump_format != format ) + { + // format change will cause list view change + g_showMemDump_format = format; + g_showMemDump_sortColumn = 0; + g_showMemDump_sortDescending = 0; + } + + ShowMemDump_PopulateList(); +} + +//----------------------------------------------------------------------------- +// rc_MemDump +// +// Sent from application with memory dump file +//----------------------------------------------------------------------------- +int rc_MemDump( char *pCommand ) +{ + char* pToken; + int retVal; + int errCode = -1; + int fileSize; + char *pBuffer; + + // get name of file + pToken = GetToken( &pCommand ); + if ( !pToken[0] ) + goto cleanUp; + + // get file + strcpy( g_showMemDump_currentFilename, pToken ); + retVal = LoadTargetFile( g_showMemDump_currentFilename, &fileSize, (void **)&pBuffer ); + + DebugCommand( "0x%8.8x = MemDump( %s )\n", retVal, g_showMemDump_currentFilename ); + + // parse and update view + ShowMemDump_Parse( pBuffer, fileSize ); + + Sys_Free( pBuffer ); + + // success + errCode = 0; + +cleanUp: + return ( errCode ); +} |