Wie funktioniert die VC++ mangle lokale statische Variablen-Namen?
Frage
Hier einige code, den ich habe:
MyClass* MyClass::getInstance()
{
static MyClass instance;
return &instance;
}
Ich will in diese anzusehen singleton ' s die aktuellen Werte.Aber ich bin gerade angehalten, drei Stunden in der Ausführung, und der Grund, warum ich angehalten wurde, ist, dass ich aus der Erinnerung.So ich kann nicht setzen Sie einen Haltepunkt in diese Methode, es zu sehen, was das Wert ist.
Meine Frage ist dann, wie bitte dieses instance
Variablen von einem globalen Rahmen.Ich habe versucht, darauf zu verweisen, wie MyClass::getInstance::instance
aber das funktioniert nicht.Ich vermute, getInstance
muss geschmückt werden, irgendwie.Wer weiß, wie?
Dies ist in Visual Studio 2008.
Lösung
Gut, die Funktions-Bereich in statische instance
variable nicht zeigen, bis in ein .map
- Datei generiert cl.exe /Fm
, und es nicht zeigen, bis, wenn ich x programname!*MyClass*
in WinDbg, so dass der verstümmelte name scheint nicht zu enthalten MyClass
an alle.
Option 1:Zerlegen MyClass::getInstance
Dieser Ansatz scheint einfacher:
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
Aus diesem können wir sagen, dass der compiler aufgerufen, das Objekt $S1
.Natürlich kann dieser name wird davon abhängen, wie viele Funktions-Bereich in statische Variablen, die Ihrem Programm hat.
Option 2:Suche Speicher für das Objekt
Erweitern @gbjbaanb Vorschlag, wenn MyClass
hat virtuelle Funktionen, könnten Sie in der Lage sein zu finden, seine Lage auf dem harten Weg:
- Stellen Sie ein vollständiges Speicherabbild des Prozesses.
- Laden Sie die vollständige Speicher dump in WinDbg.
- Verwenden Sie die
x
Befehl, um die Adresse von MyClass ' s vtable:
0:000> x programname!MyClass::`vftable' 00425c64 programname!MyClass::`vftable' =
- Verwenden Sie die
s
Befehl zum suchen des Prozesses, der virtuelle Adressraum (in diesem Beispiel 0-2GB) für Zeiger, MyClass, die 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.............
- Verwenden Sie die
dt
Befehl, um die Klasse zu finden, die vtable-offset, und subtrahieren Sie diese von zurückgegebenen Adressen von der Suche.Dies sind die möglichen Adressen für das Objekt.
0:000> dt programname!MyClass +0x000 __VFN_table : Ptr32 +0x008 x : Int4B +0x010 y : Float
- Verwenden
dt programname!MyClass 0042b360
zum untersuchen des Objekts member-Variablen, die Hypothese geprüft, dass das Objekt befindet sich in 0042b360 (oder eine andere Adresse).Sie werden wahrscheinlich einige false positives, wie ich oben, sondern durch Einsicht in die member-Variablen können Sie in der Lage sein, um herauszufinden, welche Ihre singleton.
Dies ist eine Allgemeine Technik, die für die Suche nach C++ - Objekte, und ist eine Art overkill, wenn Sie nur könnten zerlegen MyClass::getInstance
.
Andere Tipps
In gdb, können Sie einen Beobachtungspunkt auf der verstümmelte name der variable.
Zum Beispiel mit dieser Funktion:
int f() {
static int xyz = 0;
++xyz;
return xyz;
}
Ich kann sehen _ZZ1fvE3xyz (wie entstellt von gcc-3.2.3-oder gcc 4.0.1).
Dass code, der sieht nur so gefährlich...:-)
Aber wie auch immer, Ihre entstellten Namen wird abhängen auf Ihre Aufruf-Konvention Also, bevor Sie Ihre mangle-Namen müssen Sie wissen, was Ihre build-Umgebung wie die Aufruf-Konvention.MSDN hat eine Menge mehr Informationen über die Aufruf-Konvention.
Neben dieser, ein Weg, um herauszufinden, alle Informationen über Ihre Klasse zu überprüfen Sie Ihre VTable, die sich in den ersten 4 bytes des Objekts.Ein raffinierter trick, reversers verwenden ist eine versteckte VC++ Flag reportSingleClassLayout druckt die Klassenstruktur in eine ASCII-Kunst Weise.