Contents
Monitoring Your PC's Memory Usage For Game Development
 
 
Printer-Friendly VersionPrinter-Friendly Version
 
Latest News
spacer View All spacer
 
November 21, 2009
 
Video Game Watchdog National Institute On Media And The Family Shutting Down [10]
 
Modern Warfare 2 Infinity Ward's 'Most Successful PC Version' Yet [12]
 
New Tech, Design Details Of Project Natal To Emerge At Gamefest In February
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
November 21, 2009
 
Sucker Punch Productions
Character Artist
 
Sucker Punch Productions
3D Environment Artist
 
Sucker Punch Productions
Network Programmer
 
Sucker Punch Productions
Texture Artist
 
Sony Online Entertainment
Brand Manager
 
Monolith Productions
Sr. Software Engineer, Engine - Monolith Productions - #113767
 
Crystal Dynamics
Sr. Level Designer
 
Gargantuan Studios
Lead World Designer
spacer
Latest Features
spacer View All spacer
 
November 21, 2009
 
arrow Upping The Craft: Susan O'Connor On Games Writing [6]
 
arrow Small Developers: Minimizing Risks in Large Productions - Part II [6]
 
arrow iPhone Piracy: The Inside Story [48]
 
arrow And Yet It Grows: Analyzing the Size and Growth of the European Game Market [5]
 
arrow NPD: Behind the Numbers, October 2009 [13]
 
arrow Reflecting On Uncharted 2: How They Did It [5]
 
arrow Sponsored Feature: Rasterization on Larrabee -- Adaptive Rasterization Helps Boost Efficiency
 
arrow Postmortem: Wadjet Eye's The Blackwell Convergence [2]
spacer
Latest Blogs
spacer View All     Post     RSS spacer
 
November 21, 2009
 
Accepting the Inherent Value of Games
 
Planckogenesis, Part II: Song Structure & Gravy Train [1]
 
Designing Games Is About Matching Personalities [1]
spacer
About
spacer News Director:
Leigh Alexander
Features Director:
Christian Nutt
Editor At Large:
Chris Remo
Advertising:
John 'Malik' Watson
Recruitment/Education:
Gina Gross
 
Features
  Monitoring Your PC's Memory Usage For Game Development
by Jelle van der Beek
0 comments
Share RSS
 
 
May 31, 2007 Article Start Previous Page 8 of 10 Next
 

Solution 2: Loading symbol information using EnumerateModules64 and SymLoadModule64.

Until know, we discussed how to load symbols using SymInitialize. As stated earlier, this method can actually only be used if you are debugging a local process. Next we will discuss a solution without this limitation.

We can also let the tool request information about the loaded modules from the game when symbol information is required. Console platforms with only a single loaded image can simply return the image base and image name. Other platforms having multiple loaded images can return a list of loaded modules, along with their image bases. What we need to do now is mimic the behaviour of SymInitialize. We can enumerate all loaded modules for a process by using EnumerateModules64. Using this function, we can find the image bases for all of the loaded modules, their names and even the location of the PDB file. Listing 5 shows exactly that:

Advertisement

The program output shows the information that we retrieved from the active modules:

This information can be sent to the tool. Note that this way of requesting image information by the tool does require the network connection to support two-way traffic.

Now that we have the names of our program databases we can load them using SymLoadModule64. The previous article contains a code snippet that loads information using SymLoadModule64.


#include "stdafx.h"
#include
#include
#include
#include

std::string GetSymbolTypeString(SYM_TYPE symType)
{
std::string result;

switch(symType)
{
case SymCoff:
result = "COFF symbols.";
break;
case SymCv:
result = "CodeView symbols.";
break;
case SymDeferred:
result = "Symbol loading deferred.";
break;
case SymDia:
result = "DIA symbols.";
break;
case SymExport:
result = "Symbols generated from a DLL export table.";
break;
case SymNone:
result = "No symbols are loaded.";
break;
case SymPdb:
result = "PDB symbols.";
break;
case SymSym:
result = ".sym file.";
break;
case SymVirtual:
result = "Virtual module.";
break;
}
return result;
}

BOOL CALLBACK Enumerate(
PSTR moduleName,
DWORD64 moduleBase,
ULONG moduleSize,
PVOID userContext)
{
HANDLE currentProcess = GetCurrentProcess();

DWORD64 imageBase = ::SymLoadModule64(
currentProcess,
NULL,
moduleName,
NULL,
moduleBase,
moduleSize);

IMAGEHLP_MODULE64 moduleInfo;
memset(&moduleInfo, 0, sizeof(moduleInfo));
moduleInfo.SizeOfStruct = sizeof(moduleInfo);
::SymGetModuleInfo64(currentProcess, imageBase, &moduleInfo);

::SymUnloadModule64(currentProcess, imageBase);

std::string symbolTypeString = GetSymbolTypeString(moduleInfo.SymType);

std::cout <<
"name: " << moduleName << std::endl <<
" base: " << moduleBase << std::endl <<
" size: " << moduleSize <<<
" symbol type: " << symbolTypeString.c_str() << std::endl <<
" pdb: " << moduleInfo.LoadedPdbName << std::endl <<
std::endl;

return true;
}

void EnumAllModules()
{
char path[_MAX_PATH];
::GetModuleFileNameA(GetModuleHandle(NULL), path, sizeof(path));

char file[_MAX_FNAME], ext[_MAX_EXT];
_splitpath_s(path, NULL, 0, NULL, 0,
file, sizeof(file), ext, sizeof(ext));
strcat_s(file, sizeof(file), ext);

::EnumerateLoadedModules64(GetCurrentProcess(),
(PENUMLOADED_MODULES_CALLBACK64)Enumerate, file);
}

int main(int argc, char* argv[])
{
HANDLE currentProcess = GetCurrentProcess();

::SymInitialize(currentProcess, NULL, FALSE);

EnumAllModules();

::SymCleanup(currentProcess);

return 0;
}

Listing 5: EnumerateModuleInfo program.

name: D:\work\Tests\DisplayLoadedModules\debug\DisplayLoadededModules.exe

base: 4194304

size: 118784

symbol type: PDB symbols.

pdb: .\DisplayLoadedModules.pdb

name: C:\WINDOWS\system32\ntdll.dll

base: 2089811968

size: 745472

symbol type: Symbols generated from a DLL export table.

pdb:

name: C:\WINDOWS\system32\kernel32.dll

base: 2088763392

size: 1040384

symbol type: Symbols generated from a DLL export table.

pdb:

name: D:\work\Tests\DisplayLoadedModules\debug\dbghelp.dll

base: 50331648

size: 1134592

symbol type: Symbols generated from a DLL export table.

pdb:

Note: I wasn’t kidding about downloading the latest version of DbgHelp.dll. I have wasted a lot of time on the bugs from older DbgHelp.dlls. Listing 5 contains a call to SymGetModuleInfo64 and that function simply always returned zero on the 5.1 version of the DLL. Error handling is bad in this library. In the latest version of the DLL, which is 6.6 at the time of writing, there is no way I can get the function SymGetSymbolFile to work. So, I advice you to pay attention when programming for the DbgHelp library, and don’t forget to use the latest DLL.

 
Article Start Previous Page 8 of 10 Next
 
Comments

none
 
Comment:
 


Submit Comment