Erste Schritte mit WinDbg (Benutzermodus)
WinDbg ist ein Kernelmodus- und Benutzermodusdebugger, der in Debugtools für Windows enthalten ist. Die folgenden praktischen Übungen können Ihnen bei den ersten Schritten mit WinDbg als Benutzermodusdebugger helfen.
Informationen darüber, wie Sie Debugging-Tools für Windows erhalten, finden Sie unter Herunterladen und Installieren des WinDbg-Windows-Debuggers.
Suchen Sie nach der Installation der Debuging-Tools die Installationsverzeichnisse für die 64-Bit-Versionen (x64) und 32-Bit (x86) der Tools. Beispiel:
- C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
- C:\Program Files (x86)\Windows Kits\10\Debuggers\x86
Editor und Anfügen von WinDbg öffnen
Wechseln Sie zu Ihrem Installationsverzeichnis, und öffnen Sie WinDbg.exe.
Wählen Sie im Menü Datei die Option Ausführbare Datei starten aus. Wechseln Sie im Dialogfeld Ausführbare Datei starten zu dem Ordner, der die notepad.exe enthält. (Die Datei „notepad.exe“ befindet sich normalerweise unter C:\Windows\System32.) Geben Sie als Dateinamennotepad.exe ein. Wählen Sie Öffnen aus.
Geben Sie in der Befehlszeile am unteren Rand des WinDbg-Fensters den folgenden Befehl ein:
Die Ausgabe ähnelt diesem Beispiel:
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRV
Der Symbolsuchpfad teilt WinDbg mit, wo nach Symboldateien (PDB) gesucht werden soll. Der Debugger benötigt Symboldateien, um Informationen zu Codemodulen wie Funktionsnamen und Variablennamen abzurufen.
Geben Sie dann den folgenden Befehl ein:
Der
.reload
Befehl weist WinDbg an, seine anfängliche Suche durchzuführen, um Symboldateien zu suchen und zu laden.Um die Symbole für das Modul notepad.exe anzuzeigen, geben Sie diesen Befehl ein:
Hinweis
Wenn keine Ausgabe angezeigt wird, geben Sie die
.reload /f
ein, um das Laden des Symbols zu erzwingen. Verwenden Sie !sym noisy, um zusätzliche Informationen zum Laden von Symbolen anzuzeigen.Um Symbole im Modul notepad.exe anzuzeigen, die
main
enthalten, verwenden Sie den Befehl "examine symbols, um Module auflisten, die dem Format entsprechen:x notepad!wWin*
Die Ausgabe ähnelt diesem Beispiel:
00007ff6`6e76b0a0 notepad!wWinMain (wWinMain) 00007ff6`6e783db0 notepad!wWinMainCRTStartup (wWinMainCRTStartup)
Um einen Haltepunkt anzulegen
notepad!wWinMain
, geben Sie diesen Befehl ein:Um zu überprüfen, ob Der Haltepunkt festgelegt wurde, geben Sie folgenden Befehl ein:
Die Ausgabe ähnelt diesem Beispiel:
0 e Disable Clear 00007ff6`6e76b0a0 0001 (0001) 0:**** notepad!wWinMain
Um den Notepad-Prozess zu starten, geben Sie diesen Befehl ein:
Editor wird ausgeführt, bis es zur
WinMain
Funktion kommt, und dann wird er in den Debugger umgebrochen.Breakpoint 0 hit notepad!wWinMain: 00007ff6`6e76b0a0 488bc4 mov rax,rsp
Um eine Liste der Codemodule anzuzeigen, die derzeit im Editor-Prozess geladen sind, geben Sie diesen Befehl ein:
Die Ausgabe ähnelt diesem Beispiel:
0:000> lm start end module name 00007ff6`6e760000 00007ff6`6e798000 notepad (pdb symbols) C:\ProgramData\Dbg\sym\notepad.pdb\BC04D9A431EDE299D4625AD6201C8A4A1\notepad.pdb 00007ff8`066a0000 00007ff8`067ab000 gdi32full (deferred) 00007ff8`067b0000 00007ff8`068b0000 ucrtbase (deferred) 00007ff8`06a10000 00007ff8`06aad000 msvcp_win (deferred) 00007ff8`06ab0000 00007ff8`06ad2000 win32u (deferred) 00007ff8`06b40000 00007ff8`06e08000 KERNELBASE (deferred) 00007ff8`07220000 00007ff8`072dd000 KERNEL32 (deferred) 00007ff8`07420000 00007ff8`07775000 combase (deferred) 00007ff8`07820000 00007ff8`079c0000 USER32 (deferred) 00007ff8`079c0000 00007ff8`079f0000 IMM32 (deferred) 00007ff8`07c00000 00007ff8`07c2a000 GDI32 (deferred) 00007ff8`08480000 00007ff8`085ab000 RPCRT4 (deferred) 00007ff8`085b0000 00007ff8`0864e000 msvcrt (deferred) 00007ff8`08c40000 00007ff8`08cee000 shcore (deferred) 00007ff8`08db0000 00007ff8`08fa5000 ntdll (pdb symbols) C:\ProgramData\Dbg\sym\ntdll.pdb\53F12BFE149A2F50205C8D5D66290B481\ntdll.pdb 00007fff`f8580000 00007fff`f881a000 COMCTL32 (deferred)
Um eine Stapelüberwachung anzuzeigen, geben Sie diesen Befehl ein:
Die Ausgabe ähnelt diesem Beispiel:
0:000> k 00 000000c8`2647f708 00007ff6`6e783d36 notepad!wWinMain 01 000000c8`2647f710 00007ff8`07237034 notepad!__scrt_common_main_seh+0x106 02 000000c8`2647f750 00007ff8`08e02651 KERNEL32!BaseThreadInitThunk+0x14 03 000000c8`2647f780 00000000`00000000 ntdll!RtlUserThreadStart+0x21
Um Notepad erneut ausgeführt zu werden, geben Sie folgenden Befehl ein:
Um in Notepad zu pausieren, wählen Sie im Menü Datei die OptionPause aus.
Um einen Haltepunkt festzulegen und zu
ZwWriteFile
überprüfen, geben Sie die folgenden Befehle ein:Wenn Sie Notepad erneut ausgeführt werden möchten, geben Sie g ein. Geben Sie im Notepad-Fenster einen Text ein. Klicken Sie im Menü File (Datei) auf Save (Speichern). Der ausgeführte Code pausiert, wenn
ZwCreateFile
eintritt. Geben Sie den Befehl k ein, um die Stapelüberwachung anzuzeigen.Im WinDbg-Fenster links neben der Befehlszeile werden die Prozessor- und Threadnummern angezeigt. In diesem Beispiel ist die aktuelle Prozessornummer 0, und die aktuelle Threadnummer ist 11 (
0:011>
). Das Fenster zeigt die Stapelüberwachung für Thread 11 an, die auf Prozessor 0 ausgeführt wird.Um eine Liste aller Threads im Notepad-Prozess anzuzeigen, geben Sie diesen Befehl (die Tilde) ein:
Die Ausgabe ähnelt diesem Beispiel:
0:011> ~ 0 Id: 5500.34d8 Suspend: 1 Teb: 000000c8`262c4000 Unfrozen 1 Id: 5500.3960 Suspend: 1 Teb: 000000c8`262c6000 Unfrozen 2 Id: 5500.5d68 Suspend: 1 Teb: 000000c8`262c8000 Unfrozen 3 Id: 5500.4c90 Suspend: 1 Teb: 000000c8`262ca000 Unfrozen 4 Id: 5500.4ac4 Suspend: 1 Teb: 000000c8`262cc000 Unfrozen 5 Id: 5500.293c Suspend: 1 Teb: 000000c8`262ce000 Unfrozen 6 Id: 5500.53a0 Suspend: 1 Teb: 000000c8`262d0000 Unfrozen 7 Id: 5500.3ca4 Suspend: 1 Teb: 000000c8`262d4000 Unfrozen 8 Id: 5500.808 Suspend: 1 Teb: 000000c8`262da000 Unfrozen 10 Id: 5500.3940 Suspend: 1 Teb: 000000c8`262dc000 Unfrozen . 11 Id: 5500.28b0 Suspend: 1 Teb: 000000c8`262de000 Unfrozen 12 Id: 5500.12bc Suspend: 1 Teb: 000000c8`262e0000 Unfrozen 13 Id: 5500.4c34 Suspend: 1 Teb: 000000c8`262e2000 Unfrozen
In diesem Beispiel haben 14 Threads Indizes von 0 bis 13.
Um die Stapelüberwachung für Thread 0 anzuzeigen, geben Sie die folgenden Befehle ein:
Die Ausgabe ähnelt diesem Beispiel:
0:011> ~0s 0:011> ~0s win32u!NtUserGetProp+0x14: 00007ff8`06ab1204 c3 ret 0:000> k # Child-SP RetAddr Call Site 00 000000c8`2647bd08 00007ff8`07829fe1 win32u!NtUserGetProp+0x14 01 000000c8`2647bd10 00007fff`f86099be USER32!GetPropW+0xd1 02 000000c8`2647bd40 00007ff8`07d12f4d COMCTL32!DefSubclassProc+0x4e 03 000000c8`2647bd90 00007fff`f8609aba SHELL32!CAutoComplete::_EditWndProc+0xb1 04 000000c8`2647bde0 00007fff`f86098b7 COMCTL32!CallNextSubclassProc+0x9a 05 000000c8`2647be60 00007ff8`0782e858 COMCTL32!MasterSubclassProc+0xa7 06 000000c8`2647bf00 00007ff8`0782de1b USER32!UserCallWinProcCheckWow+0x2f8 07 000000c8`2647c090 00007ff8`0782d68a USER32!SendMessageWorker+0x70b 08 000000c8`2647c130 00007ff8`07afa4db USER32!SendMessageW+0xda
Um das Debuggen zu beenden und vom Notepad-Prozess zu trennen, geben Sie diesen Befehl ein:
Öffnen Ihrer eigenen Anwendung und Anfügen von WinDbg
Gehen Sie beispielsweise davon aus, dass Sie diese kleine Konsolenanwendung geschrieben und erstellt haben:
...
void MyFunction(long p1, long p2, long p3)
{
long x = p1 + p2 + p3;
long y = 0;
y = x / p2;
}
void main ()
{
long a = 2;
long b = 0;
MyFunction(a, b, 5);
}
Gehen Sie für diese Übung davon aus, dass sich die integrierte Anwendung (MyApp.exe) und die Symboldatei (MyApp.pdb) in C:\MyApp\x64\Debug befinden. Gehen Sie außerdem davon aus, dass sich der Anwendungsquellcode in C:\MyApp\MyApp befindet und dass der Zielcomputer MyApp.exe kompiliert wurde.
Öffnen Sie WinDbg.
Wählen Sie im Menü Datei die Option Ausführbare Datei starten aus. Wechseln Sie im Dialogfeld Ausführbare Datei starten, navigieren Sie zu C:\MyApp\x64\Debug. Geben Sie als DateinamenMyApp.exe ein. Wählen Sie Öffnen aus.
Geben Sie anschließend diese Befehle ein:
.sympath+ C:\MyApp\x64\Debug
Die Befehle teilen WinDbg mit, wo Symbole und Quellcode für Ihre Anwendung gefunden werden können. In diesem Fall muss der Quellcodespeicherort nicht mithilfe von .srcpath festgelegt werden, da die Symbole vollqualifizierte Pfade zu den Quelldateien aufweisen.
Geben Sie anschließend diese Befehle ein:
Ihre Anwendung wechselt in den Debugger, wenn es um seine
main
Funktion geht.WinDbg zeigt den Quellcode und das Befehlsfenster an.
Wählen Sie im Menü Debug die Option Einzelschritt aus (oder wählen Sie F11 aus). Fahren Sie mit dem Schritt fort, bis Sie zu diesem Schritt gelangen
MyFunction
. Wenn Sie in die Zeiley = x / p2
wechseln, stürzt ihre Anwendung ab und pausiert den Debugger.Die Ausgabe ähnelt diesem Beispiel:
(1450.1424): Integer divide-by-zero - code c0000094 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. MyApp!MyFunction+0x44: 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] ss:00000063`2036f808=00000000
Geben Sie diesen Befehl ein:
WinDbg zeigt eine Analyse des Problems an (in diesem Fall Division durch 0).
FAULTING_IP: MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7] 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 00007ff63be11064 (MyApp!MyFunction+0x0000000000000044) ExceptionCode: c0000094 (Integer divide-by-zero) ExceptionFlags: 00000000 NumberParameters: 0 ... STACK_TEXT: 00000063`2036f7e0 00007ff6`3be110b8 : ... : MyApp!MyFunction+0x44 00000063`2036f800 00007ff6`3be1141d : ... : MyApp!main+0x38 00000063`2036f840 00007ff6`3be1154e : ... : MyApp!__tmainCRTStartup+0x19d 00000063`2036f8b0 00007ffc`b1cf16ad : ... : MyApp!mainCRTStartup+0xe 00000063`2036f8e0 00007ffc`b1fc4629 : ... : KERNEL32!BaseThreadInitThunk+0xd 00000063`2036f910 00000000`00000000 : ... : ntdll!RtlUserThreadStart+0x1d STACK_COMMAND: dt ntdll!LdrpLastDllInitializer BaseDllName ;dt ntdll!LdrpFailureData ;.cxr 0x0 ;kb FOLLOWUP_IP: MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7] 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] FAULTING_SOURCE_LINE: c:\myapp\myapp\myapp.cpp FAULTING_SOURCE_FILE: c:\myapp\myapp\myapp.cpp FAULTING_SOURCE_LINE_NUMBER: 7 FAULTING_SOURCE_CODE: 3: void MyFunction(long p1, long p2, long p3) 4: { 5: long x = p1 + p2 + p3; 6: long y = 0; > 7: y = x / p2; 8: } 9: 10: void main () 11: { 12: long a = 2; ...
Zusammenfassung der Befehle
Contents
Befehl imHelp
Menü- .sympath (Set-Symbolpfad)
- .reload (Modul neu laden)
- x (Symbole überprüfen)
- g (Gehe zu)
Break
Befehl imDebug
Menü- lm (Liste der geladenen Module)
- k (Anzeigestapel-Backtrace)
- bu (Haltepunkt setzen)
- bl (Haltepunktliste)
- ~ (Threadstatus)
- ~s (Aktuellen Thread festlegen)
- .sympath+ (Set Symbol Path) an vorhandenen Symbolpfad anfügen
- .srcpath (Quellpfad festlegen)
Step Into
Befehl imDebug
Menü (F11)- !analyze -v
- qd (Beenden und Trennen)
Siehe auch
Erste Schritte mit WinDbg (Kernel-Modus)