You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1441 lines
38 KiB
1441 lines
38 KiB
5 years ago
|
//========= 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 );
|
||
|
}
|