Introduzione a WinDbg (modalità utente)
WinDbg è un debugger in modalità kernel e in modalità utente incluso in Strumenti di debug per Windows. Gli esercizi pratici seguenti consentono di iniziare a usare WinDbg come debugger in modalità utente.
Per informazioni su come ottenere gli strumenti di debug per Windows, vedere Scaricare e installare il debugger windows WinDbg.
Dopo aver installato gli strumenti di debug, trovare le directory di installazione per le versioni a 64 bit (x64) e ARM a 64 bit degli strumenti. Per esempio:
- C:\Programmi (x86)\Windows Kits\10\Debuggers\x64
- C:\Programmi (x86)\Windows Kits\10\Debuggers\arm64
Aprire il Blocco note e collegare WinDbg
Vai alla directory di installazione e apri WinDbg.exe.
Sul menu File, selezionare Eseguire programma eseguibile. Nella finestra di dialogo Avvia eseguibile passare alla cartella che contiene notepad.exe. Il file notepad.exe si trova in genere in C:\Windows\System32. Per Nome fileimmettere notepad.exe. Selezionare Apri.
Nella riga di comando nella parte inferiore della finestra winDbg immettere questo comando:
L'output è simile a questo esempio:
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRV
Il percorso di ricerca dei simboli indica a WinDbg dove cercare i file di simboli (PDB). Il debugger necessita di file di simboli per ottenere informazioni sui moduli di codice, ad esempio nomi di funzione e nomi di variabili.
Immettere quindi questo comando:
Il comando
.reload
indica a WinDbg di eseguire la ricerca iniziale per trovare e caricare i file di simboli.Per visualizzare i simboli per il modulo notepad.exe, immettere questo comando:
Nota
Se non viene visualizzato alcun output, immettere
.reload /f
per tentare di forzare il caricamento del simbolo. Usare !sym noisy per visualizzare informazioni aggiuntive riguardanti il caricamento dei simboli.Per visualizzare i simboli nel modulo notepad.exe che contengono
main
, usare il comando esaminare i simboli per elencare i moduli corrispondenti alla maschera:x notepad!wWin*
L'output è simile a questo esempio:
00007ff6`6e76b0a0 notepad!wWinMain (wWinMain) 00007ff6`6e783db0 notepad!wWinMainCRTStartup (wWinMainCRTStartup)
Per inserire un punto di interruzione in
notepad!wWinMain
, immettere questo comando:Per verificare che il punto di interruzione sia stato impostato, immettere questo comando:
L'output è simile a questo esempio:
0 e Disable Clear 00007ff6`6e76b0a0 0001 (0001) 0:**** notepad!wWinMain
Per avviare Blocco note, immettere questo comando:
Il Blocco note viene eseguito fino a quando non arriva alla funzione
WinMain
e quindi si interrompe nel debugger.Breakpoint 0 hit notepad!wWinMain: 00007ff6`6e76b0a0 488bc4 mov rax,rsp
Per visualizzare un elenco di moduli di codice attualmente caricati nel processo Blocco Note, immettere questo comando:
L'output è simile a questo esempio:
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)
Per visualizzare un'analisi dello stack, immettere questo comando:
L'output è simile a questo esempio:
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
Per avviare di nuovo Blocco note, immettere questo comando:
Per accedere a Blocco note, nel menu File selezionare Interrompi.
Per impostare e verificare un punto di interruzione in
ZwWriteFile
, immettere questi comandi:Per avviare nuovamente l'esecuzione del Blocco note, immettere g. Nella finestra del Blocco note, inserisci del testo. Nel menu file
selezionare Salva . Il codice in esecuzione si interrompe quando si tratta diZwCreateFile
. Immettere il comando k per visualizzare la traccia dello stack.Nella finestra WinDbg, a sinistra della riga di comando, vengono visualizzati i numeri del processore e del thread. In questo esempio il numero corrente del processore è 0 e il numero di thread corrente è 11 (
0:011>
). Nella finestra viene visualizzata la traccia dello stack per il thread 11 in esecuzione sul processore 0.Per visualizzare un elenco di tutti i thread nel processo blocco note, immettere questo comando (la tilde):
L'output è simile a questo esempio:
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 questo esempio, 14 thread hanno indici da 0 a 13.
Per esaminare la traccia dello stack per il thread 0, immettere questi comandi:
L'output è simile a questo esempio:
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
Per uscire dal debug e scollegarsi dal processo del Blocco note, immettere questo comando:
Aprire un'applicazione personalizzata e collegare WinDbg
Si supponga, ad esempio, di aver scritto e compilato questa piccola applicazione console:
...
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);
}
Per questo esercizio si supponga che l'applicazione compilata (MyApp.exe) e il file di simboli (MyApp.pdb) si trovino in C:\MyApp\x64\Debug. Si supponga inoltre che il codice sorgente dell'applicazione si trova in C:\MyApp\MyApp and that the target machine compiled MyApp.exe.
Apri WinDbg.
Nel menu File , selezionare Avvia eseguibile . Nella finestra di dialogo 'Avvia eseguibile', passare a C:\MyApp\x64\Debug. Per Nome file, inserire MyApp.exe. Selezionare Apri.
Immettere questi comandi:
.sympath+ C:\MyApp\x64\Debug
I comandi indicano a WinDbg dove trovare simboli e codice sorgente per l'applicazione. In questo caso, non è necessario impostare il percorso del codice sorgente usando .srcpath perché i simboli hanno percorsi completi ai file di origine.
Immettere questi comandi:
L'applicazione si interrompe nel debugger quando raggiunge la funzione
main
.WinDbg visualizza il codice sorgente e la finestra Comando.
Nel menu Debug, selezionare Step Into (o selezionare F11). Continuare a camminare fino a quando non si entra in
MyFunction
. Quando si arriva alla rigay = x / p2
, l'applicazione si arresta in modo anomalo ed entra nel debugger.L'output è simile a questo esempio:
(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
Immettere questo comando:
WinDbg visualizza un'analisi del problema (in questo caso, divisione per 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; ...
Riepilogo dei comandi
- comando
Contents
nel menuHelp
- .sympath (Imposta percorso simbolo)
- ricarica (Modulo di ricarica)
- x (esaminare i simboli)
- g (Go)
- comando
Break
nel menuDebug
- lm (elenco dei moduli caricati)
- k (Visualizzazione del Backtrace dello Stack)
- bu (Imposta punto di interruzione)
- bl (elenco punti di interruzione)
- ~ (stato discussione)
- ~s (Imposta il thread corrente)
- .sympath+ (Imposta percorso simbolo) aggiungi al percorso simbolo esistente
- .srcpath (Set Source Path)
-
Step Into
comando nel menuDebug
(F11) - !analyze -v
- qd (esci e scollega)
Vedere anche
Introduzione all' WinDbg (modalità kernel)