Here's some code I have:
MyClass* MyClass::getInstance()
{
static MyClass instance;
return &instance;
}
I want to look into this singleton's current values. But I'm currently paused three hours into execution, and the reason I'm paused is that I'm out of memory. So I can't put a breakpoint in this method there to see what the value is.
My question then is how to refer to this instance
variable from a global scope. I've tried referring to it as MyClass::getInstance::instance
but that doesn't work. I'm guessing getInstance
has to be decorated somehow. Anyone know how?
This is in Visual Studio 2008.
Well, the function-scoped static instance
variable doesn't show up in a .map
file generated by cl.exe /Fm
, and it doesn't show up when I use x programname!*MyClass*
in WinDbg, so the mangled name doesn't seem to contain MyClass
at all.
Option 1: Disassemble MyClass::getInstance
This approach seems easier:
0:000> uf programname!MyClass::getInstance
programname!MyClass::getInstance [programname.cpp @ 14]:
14 00401050 55 push ebp
14 00401051 8bec mov ebp,esp
15 00401053 a160b34200 mov eax,dword ptr [programname!$S1 (0042b360)]
15 00401058 83e001 and eax,1
15 0040105b 7526 jne funcstat!MyClass::getInstance+0x33 (00401083)
programname!MyClass::getInstance+0xd [programname.cpp @ 15]:
15 0040105d 8b0d60b34200 mov ecx,dword ptr [programname!$S1 (0042b360)]
15 00401063 83c901 or ecx,1
15 00401066 890d60b34200 mov dword ptr [programname!$S1 (0042b360)],ecx
15 0040106c b9b0be4200 mov ecx,offset programname!instance (0042beb0)
15 00401071 e88fffffff call programname!ILT+0(??0MyClassQAEXZ) (00401005)
15 00401076 68e03e4200 push offset programname!`MyClass::getInstance'::`2'::`dynamic atexit destructor for 'instance'' (00423ee0)
15 0040107b e8f3010000 call programname!atexit (00401273)
15 00401080 83c404 add esp,4
programname!MyClass::getInstance+0x33 [programname.cpp @ 16]:
16 00401083 b8b0be4200 mov eax,offset programname!instance (0042beb0)
17 00401088 5d pop ebp
17 00401089 c3 ret
From this we can tell that the compiler called the object $S1
. Of course, this name will depend on how many function-scoped static variables your program has.
Option 2: Search memory for the object
To expand on @gbjbaanb's suggestion, if MyClass
has virtual functions, you might be able to find its location the hard way:
- Make a full memory dump of the process.
- Load the full memory dump into WinDbg.
- Use the
x
command to find the address of MyClass's vtable:
0:000> x programname!MyClass::`vftable'
00425c64 programname!MyClass::`vftable' =
- Use the
s
command to search the process's virtual address space (in this example, 0-2GB) for pointers to MyClass's vtable:
0:000> s -d 0 L?7fffffff 00425c64
004010dc 00425c64 c35de58b cccccccc cccccccc d\B...].........
0040113c 00425c64 8bfc458b ccc35de5 cccccccc d\B..E...]......
0042b360 00425c64 00000000 00000000 00000000 d\B.............
- Use the
dt
command to find the class's vtable offset, and subtract that from the addresses returned from the search. These are possible addresses for the object.
0:000> dt programname!MyClass
+0x000 __VFN_table : Ptr32
+0x008 x : Int4B
+0x010 y : Float
- Use
dt programname!MyClass 0042b360
to examine the object's member variables, testing the hypothesis that the object is located at 0042b360 (or some other address). You will probably get some false positives, as I did above, but by inspecting the member variables you may be able to figure out which one is your singleton.
This is a general technique for finding C++ objects, and is kind of overkill when you could just disassemble MyClass::getInstance
.
In gdb, you can put a watchpoint on the mangled name of the variable.
For example, with this function:
int f() {
static int xyz = 0;
++xyz;
return xyz;
}
I can watch _ZZ1fvE3xyz (as mangled by gcc 3.2.3 or gcc 4.0.1).
That code just looks dangerous... :-)
But anyway, your mangled name is going to depend on your Calling Convention So before you find your mangle name you need to know what your build environment is using as the calling convention. MSDN has a lot more information on calling convention.
Besides this, one way to find out all this information about your class is to inspect your VTable, which is found in the first 4 bytes of your object. A nifty trick that reversers use is a hidden VC++ Flag reportSingleClassLayout that prints the class structure in an ASCII art manner.