Our Properties: Gamasutra GameCareerGuide IndieGames Indie Royale GDC IGF Game Developer Magazine GAO
My Message close
Contents
Monitoring Your Console's Memory Usage, Part Two
 
 
Printer-Friendly VersionPrinter-Friendly Version
 
Latest News
spacer View All spacer
 
February 9, 2012
 
Road to the IGF: Alexander Bruce's Antichamber
 
What Nintendo's 2011 sales mean for Wii U, third parties [7]
 
Report: iPad 3 announcement expected in March
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
February 9, 2012
 
High 5 Games
Senior Mathematician
 
High 5 Games
Mathematician
 
Toys for Bob / Activision
QA Tester - Temporary
 
Radical Entertainment / Activision
AI Programmer (Senior)
 
Sony Computer Entertainment America LLC
Senior On-line Programmer
 
Visual Concepts
Senior Producer, VC China (Shanghai)
spacer
Latest Features
spacer View All spacer
 
February 9, 2012
 
arrow Principles of an Indie Game Bottom Feeder [6]
 
arrow Postmortem: CyberConnect 2's Solatorobo: Red the Hunter [1]
 
arrow Jerked Around by the Magic Circle - Clearing the Air Ten Years Later [34]
 
arrow Building the World of Reckoning [4]
 
arrow SPONSORED FEATURE: TwitchTV - How to Build Community Around Your Game in 2012 [13]
 
arrow Happy Action, Happy Developer: Tim Schafer on Reimagining Double Fine [9]
 
arrow Building an iOS Hit: Phase 1 [11]
 
arrow Postmortem: Appy Entertainment's SpellCraft School of Magic [5]
spacer
Latest Blogs
spacer View All     Post     RSS spacer
 
February 9, 2012
 
Double Fine's Kickstarter Windfall: Will Patronage Supplant Traditional Game Publishing?
 
Did DoubleFine Just break the publishing model for good? [2]
 
The Devil Is in the Details of Action RPGs - Part One: The Logistics of Loot [2]
 
Xbox LIVE Indie Games at it Again
 
Merging Waterfall and SCRUM [3]
spacer
About
spacer Editor-In-Chief/News Director:
Kris Graft
Features Director:
Christian Nutt
Senior Contributing Editor:
Brandon Sheffield
News Editors:
Frank Cifaldi, Tom Curtis, Mike Rose, Eric Caoili, Kris Graft
Editors-At-Large:
Leigh Alexander, Chris Morris
Advertising:
Jennifer Sulik
Recruitment:
Gina Gross
 
Feature Submissions
 
Comment Guidelines
Sponsor
Features
  Monitoring Your Console's Memory Usage, Part Two
by Jelle van der Beek []
Post A Comment Share on Twitter Share on Facebook RSS
 
 
April 16, 2004 Article Start Page 1 of 3 Next
 

In part one I discussed the overview of our tool, MemAnalyze, and how to make a memory dump on Xbox and PS2 consoles. In this part, we will read the memory dump, convert function names to addresses using Map files or PDB files, then we will process the data to create several views on the data. I will also discuss future plans to make MemAnalyze much more powerful.

Converting return addresses to function names


Xbox

In part one, I chose not to output function names to the memory dump, but only the return addresses. This means that if you are using XbMemdump, you might want to turn off the symbol information and do the converting yourself, to make it easier to parse the memory dump. When using symbol information in XbMemdump, the function addresses are replaced with the names and not added. We can turn off the symbol information simply by not supplying a PDB path on the command line.

Before getting into detail on either map or PDB files, I will share a few more details regarding absolute addresses and image- and section base addresses.

Absolute address

The return addresses we store in our memory dump are all absolute addresses.

Image base address

Image base addresses on PCs work differently then on the Xbox. It took me quite some time to figure this out.

On a PC, you can enter a preferred base address for the image (/BASE linker setting), though the operating system can relocate this address when loading the image. The operating system will only relocate the image if there is not enough space to load the image. This only applies when loading DLLs in the same process, not when loading a single executable. For DLLs, the image base address can be tweaked to avoid DLL conflicts and to gain performance.

With this knowledge in mind, I checked the Xbox project settings. There is still the /FIXED setting in the advanced link options. This option specifies if you always want to load the image at the preferred base address. If the operating system cannot load it at that address, the load fails. So the /FIXED option is there, but the /BASE setting is not. I figured the linker would default to some static value. So, the first thing I did was look up the base address in the MAP file that is produced by the linker (listing 1).


XyanideD

Timestamp is 4048a4d1 (Fri Mar 05 17:03:29 2004)

Preferred load address is 00400000

Start Length Name Class
0001:00000000 00887928H .textbss DATA

Listing 1: The preferred load address in the map file.

And there it is! Obviously, the preferred load address is 0x400000. Well, not really. There must be some PC legacy involved here. The Xbox image loader works differently, and the 0x400000 value is not used at all. When starting an Xbox application, multiple modules are loaded into the private virtual address space. Other modules, including the kernel and debugging modules, are also loaded. Unlike the PC platform, there is just one process running at a time, so all modules are loaded into the same address space. The image base address is completely determined by the Xbox image loader, which is also why the /BASE setting is not present in the link options. We can retrieve the image base address as described in part one, by calling DmWalkLoadedModules, in the game. An example of the output of DmWalkLoadedModules is shown in listing 2.


--- List of all loaded modules ----

Name: xboxkrnl.exe
BaseAddress:80010000
Size: 1268224

Name: xbdm.dll
BaseAddress:B0011000
Size: 401056

Name: vx.dxt
BaseAddress:B00B2000
Size: 101184

Name: XboxProject.exe
BaseAddress:00010CE0
Size: 285376

--- End of list ----

Listing 2: Output of all loaded modules, while running my test project 'XboxProject'.

In listing 2, we can also see that the system modules are loaded in the space above 2GB--the shared address space. Our own module is loaded near the beginning of the virtual address space. (The first 0x10000 bytes of the virtual address space is reserved by the operating system.)

Section address

Each image consists of a set of sections. These are both DATA and CODE sections. The .text section will contain all your game code. A map file displays a list of all the sections in the image (listing 3).


0001:00000000 00887928H .textbss DATA
0002:00000000 00e2d232H .text CODE
0002:00e2d240 00001eceH .text$x CODE
0002:00e2f110 000e6d24H .text$yc CODE
0002:00f15e40 00039da8H .text$yd CODE
0003:00000000 0000ce65H XMV CODE
0003:0000ce68 00001f03H XMV_RD CODE
0003:0000ed70 0002833cH XMV_RW CODE
0003:000370b0 00002baaH XMV_URW CODE
0004:00000000 0002dc73H XACTENG CODE
0004:0002dc78 000098b6H XACTENG_RD CODE
0004:00037530 000013dfH XACTENG_RW CODE
0004:00038910 000014e7H XACTENG_URW CODE

Listing 3: sections from the map file.

Section addresses are absolute addresses, 32-byte aligned. Figure 1 shows the layout of the virtual memory if a program is loaded into memory.

Figure 1: The status of the virtual memory when an Xbox image is loaded.

Note: the image base address of the game module is never 0x10000, but a couple of hundreds or thousands bytes further in memory (see Listing 2). (This block is not displayed in Figure 1; I have not been able to find out what data resides there.) Also, the start of the first section is never the same as the start of the image base address. In Figure 1, I have displayed this as "Image information". Most likely, this is where the section headers will reside, as the sections themselves are contiguous (mind the section alignment though).

Map files

Map files store their functions in relative virtual addresses. The first question that pops up is: "Relative to what?" Well, map files store their functions along with two relative addresses:

  • Section-relative.
  • Relative to the image base (the column header says rva+base, but we will see why this is incorrect in a moment).

First, we will discuss section-relative conversion.

If we take a look at a line of text from a map file (listing 4), column 1 displays the section index and the offset into the section. Column 2 displays the function's decorated name and column 3 displays the offset of the function, relative to the image base. The rest is of no use to us.


0002:008bfb00 ??$Write@V?$TSharedPtr@UIWorldAttachmentProvider@@@GFW@@@
TPointer Converter@GFW@@SAXAAUIPropertySaver@1@PBDABV?
$TShared Ptr@UIWorld AttachmentProvider@@@1@@Z 015325a0 f i
_WaveSpawner.obj

Listing 4: A line of text from the map file.

To compute the absolute address of the function displayed in listing 3, we need the start address of the section. The section index is in front of the section relative address. In listing 4, this is 0002. Unfortunately, the section base addresses are not present in the map file. Don't be thrown off by the list on top of the map file--it does not display the section base addresses. We need to parse the game's executable using ImageBld to obtain section information. We dumped our Xyanide section information on the command line by typing:

ImageBld /dump XyanideD.xbe >XyanideSectionDump.txt

Now we need to parse the section dump (listing 5), find the start address, and add it to the offset of the function. This gives us the absolute start address of the function, but we stored the return addresses! So we first have to compute the size of the function. The map file displays all the functions in order of appearance in memory, so we can simply subtract the address of our function from the address of the next function in the map file.


SECTION HEADER #2 .text
884140 virtual address
F21C18 virtual size
2000 file pointer to raw data
F21C18 size of raw data
000107D2 head shared page reference count address
000107D4 tail shared page reference count address
6 flags
Preload
Executable

Listing 5: Layout of a section of the ImageBld.exe tool. We need to parse the 'virtual address' field.

We have now parsed the section dump from ImageBld, but we could also have used a function from the debug library on the Xbox itself: DmWalkModuleSections. We can save the module section addresses in the memory dump from within the game, just as we did by saving the image base.

To convert the decorated function name to a readable name, use the helper function UnDecorateSymbolName from the DbgHelp library.
Now we know how to convert a function address to a function name. There are two drawbacks to using section relative conversion if you are using ImageBld to parse the executable:

  • If the image base address is relocated by the operating system, the section base addresses are incorrect, because they are provided as absolute addresses. (This code assumes that the default image base is being used.) This has not happened to me yet, but in theory, it is possible.
  • We need to parse two files to find the function name.

By using DmWalkModuleSections, you will only have to parse the MAP file, and it has the advantage that the kernel knows if the image base has been relocated, so the correct absolute addresses are written to file.

Another approach is to use the third column of the map file. This is the image-base relative conversion. The header of the column says this is the rva+base address, meaning it is the absolute address of the function name. Well, that is simply not true. This code also uses the preferred base address of 0x400000. We've just seen that this value is not used, and incorrect. However, we can use it to our advantage! By simply subtracting 0x400000 from this value, we get the address relative to the image base. We can work with image base relative values, because they are independent of the location of the image in memory. So, regardless of whether the OS has relocated the base address, we can find our function name. We only need to use the memory dump's runtime image base address. We already saved this value in part one. Thus, this is how you convert the rva+base column to an absolute address:

AbsFunctionAddress = RvaBase - 0x400000 + RealImageBase

Now we get to the final drawback of map files: Xbox map files do not include static functions! This will sometimes result in incorrect function names. They are usually not completely off; the resulting function name will probably be a function of the same object file, so we are pointed in the right direction. But, we could do even better. We can read Program Databases!

 
Article Start Page 1 of 3 Next
 
Comments


none
 
Comment:
 




UBM Techweb
Game Network
Game Developers Conference | GDC Europe | GDC Online | GDC China | Gamasutra | Game Developer Magazine | Game Advertising Online
Game Career Guide | Independent Games Festival | Indie Royale | IndieGames

Other UBM TechWeb Networks
Business Technology | Business Technology Events | Telecommunications & Communications Providers

Privacy Policy | Terms of Service | Contact Us | Copyright © UBM TechWeb, All Rights Reserved.