StackWalk64 auf Windows - symbol-Namen Bekommen
Okay, zweite Frage SO in einem Tag. Sieht aus wie der Windows-Programmierung macht mich glücklich... : S
Ich versuche momentan, um die Funktion " call-stack auf einem Win32-executable.
Heute morgen habe ich auch eine Frage dazu:
Nun, ich bin mir ziemlich sicher, dass die StackWalk64
Funktion ist der Schlüssel für diese.
Ich habe einige Artikel auf, wie es zu benutzen, als auch die MS-Dokumentation.
Tatsächlich zeigt Bilder auf meinem test-Programm, so dass es ein bisschen Arbeit...
Das problem ist, dass ich nicht in der Lage zum abrufen der Namen eines symbols vom stack-Informationen.
Ich bin mit der SymGetSymFromAddr64
- Funktion, mit UnDecorateSymbolName
. Aber bekomme ich nur falsche Zeichen.
Hier ist mein code. Hoffe, nicht zu chaotisch, wie ich bin nicht verwendet, um die Windows-Programmierung:
void printStack( void )
{
BOOL result;
HANDLE process;
HANDLE thread;
CONTEXT context;
STACKFRAME64 stack;
ULONG frame;
IMAGEHLP_SYMBOL64 symbol;
DWORD64 displacement;
char name[ 256 ];
RtlCaptureContext( &context );
memset( &stack, 0, sizeof( STACKFRAME64 ) );
process = GetCurrentProcess();
thread = GetCurrentThread();
displacement = 0;
stack.AddrPC.Offset = context.Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = context.Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
for( frame = 0; ; frame++ )
{
result = StackWalk64
(
IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack,
&context,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL
);
symbol.SizeOfStruct = sizeof( IMAGEHLP_SYMBOL64 );
symbol.MaxNameLength = 255;
SymGetSymFromAddr64( process, ( ULONG64 )stack.AddrPC.Offset, &displacement, &symbol );
UnDecorateSymbolName( symbol.Name, ( PSTR )name, 256, UNDNAME_COMPLETE );
printf
(
"Frame %lu:\n"
" Symbol name: %s\n"
" PC address: 0x%08LX\n"
" Stack address: 0x%08LX\n"
" Frame address: 0x%08LX\n"
"\n",
frame,
symbol.Name,
( ULONG64 )stack.AddrPC.Offset,
( ULONG64 )stack.AddrStack.Offset,
( ULONG64 )stack.AddrFrame.Offset
);
if( !result )
{
break;
}
}
}
Die tatsächliche Ausgabe ist:
Frame 0:
Symbol name: ╠╠╠╠╠╠╠╠╠╠╠╠
PC address: 0x00BA2763
Stack address: 0x00000000
Frame address: 0x0031F7E8
Frame 1:
Symbol name: ╠╠╠╠╠╠╠╠╠╠╠╠☺
PC address: 0x00BB4FFF
Stack address: 0x00000000
Frame address: 0x0031F940
Frame 2:
Symbol name: ╠╠╠╠╠╠╠╠╠╠╠╠☻
PC address: 0x00BB4E2F
Stack address: 0x00000000
Frame address: 0x0031F990
Frame 3:
Symbol name: ╠╠╠╠╠╠╠╠╠╠╠╠♥
PC address: 0x75BE3677
Stack address: 0x00000000
Frame address: 0x0031F998
Frame 4:
Symbol name: ╠╠╠╠╠╠╠╠╠╠╠╠♦
PC address: 0x770F9D72
Stack address: 0x00000000
Frame address: 0x0031F9A4
Frame 5:
Symbol name: ╠╠╠╠╠╠╠╠╠╠╠╠♣
PC address: 0x770F9D45
Stack address: 0x00000000
Frame address: 0x0031F9E4
Frame 6:
Symbol name: ╠╠╠╠╠╠╠╠╠╠╠╠♠
PC address: 0x770F9D45
Stack address: 0x00000000
Frame address: 0x0031F9E4
Scheint seltsam, dass die stack-Adresse ist stets 0, die durch die Art und Weise... Jede Hilfe dankbar : )
Danke an alle!
BEARBEITEN
Ich bin auf der Suche nach einem einfachen C-Lösung, ohne Bibliotheken von Drittanbietern...
- Haben Sie überprüft, die return-codes von
SymGetSymFromAddr64
undUnDecorateSymbolName
? - Sie müssen rufen Sie SymInitialize, wie erwähnt, durch Muqker
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den Sie festgelegt haben
symbol.MaxNameLength
bis 255, aber Sie reservierten "symbol" auf dem Stapel mitIMAGEHLP_SYMBOL64 symbol;
. Ist definiert als:Beachten Sie, dass das Name-Feld nur ein Zeichen standardmäßig. Wenn Sie möchten, speichern größeren Namen, müssen Sie etwas tun, wie:
Ansonsten
SymGetSymFromAddr64()
ist wahrscheinlich zu überschreiben Speicher. Hier ist, was die Hilfe-Seite für die Struktur sagt (Hervorhebung Hinzugefügt):CaptureStackBackTrace
Funktion. Es dauert eineSYMBOL_INFO
struct als Parameter, die initialisiert werden muss, die gleiche Weise, wieIMAGEHLP_SYMBOL64
. Also ich bin akzeptieren Sie Ihre Antwort. Vielen Dank für die Hilfe!malloc(offsetof(IMAGEHLP_SYMBOL64, Name[MaxNameLen]))
. Im Gegensatz addition der einzelnen Größen, diese Konten für padding und Ausrichtung.Check-out die Stackwalker Projekt auf codeplex - es ist open-source. Funktioniert gut.
Ich Ihren code benutzt, und es auch nicht funktionieren, bis ich bemerkte, in der Dokumentation, die Sie zuerst benötigen, rufen Sie SymInitialize, wie SymInitialize(process, NULL, TRUE) . Rufen Sie diese, bevor RtlCaptureContext.
Gibt es zwei Probleme erste:
1) Name muss vorbelegte wie bereits von AShelly. Sie brauchen nicht malloc, es zu tun:
2) Seine nicht ok RtlCaptureContext() auf, um Kontext in 32-bit-builds. Wenn Sie 64-bit-Rechner, dann ändern Sie IMAGE_FILE_MACHINE_I386 zu den entsprechenden 64-bit-Typ. Wenn Sie 32-bit-bauen, dann verwenden Sie inline-Montage richtig fest, EBP, ESP und EIP. Hier ist ein Weg, es zu tun:
Kleiner Punkt - SymGetSymFromAddr64 ist ok, aber es wird empfohlen, zu verwenden SymFromAddr statt.
Viel Glück an alle diejenigen, die tracing-stack auf Windows.
Siehe diese Antwort auf das, was ist im wesentlichen die gleiche Frage:
https://stackoverflow.com/a/28276227/10592
Beachten Sie, dass Sie müssen sicherstellen, dass Ihre Benutzer haben .pdb-Datei, und, dass Ihr Prozess es finden können - finden Sie, dass die Antwort für weitere details.