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 a 32 bit (x86) degli strumenti. Ad esempio:
- C:\Programmi (x86)\Windows Kits\10\Debuggers\x64
- C:\Programmi (x86)\Windows Kits\10\Debuggers\x86
Aprire Blocco note e collegare WinDbg
Passare alla directory di installazione e aprire WinDbg.exe.
Scegliere Avvia eseguibile dal menu File. 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. In Nome file immettere 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
.reload
comando 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 sul caricamento dei simboli.Per visualizzare i simboli nel modulo notepad.exe che contiene
main
, usare il comando esamina i simboli per elencare i moduli che corrispondono 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 il processo di Blocco note, immettere questo comando:
Blocco note viene eseguito fino a quando non arriva alla
WinMain
funzione 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 di 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 eseguire di nuovo, immettere questo comando:
Per entrare in Blocco note, scegliere Interrompi dal menu File.
Per impostare e verificare un punto di interruzione in
ZwWriteFile
, immettere questi comandi:Per avviare di nuovo Blocco note l'esecuzione, immettere g. Nella finestra Blocco note immettere del testo. Scegliere Save (Salva) dal menu File. Il codice in esecuzione si interrompe quando si tratta di
ZwCreateFile
. Immettere il comando k per visualizzare l'analisi 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 di processore corrente è 0 e il numero di thread corrente è 11 (
0:011>
). Nella finestra viene visualizzata l'analisi dello stack per il thread 11 in esecuzione nel processore 0.Per visualizzare un elenco di tutti i thread nel processo di 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 l'analisi 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 processo di debug e disconnettersi dal processo di 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 e che il computer di destinazione compilato MyApp.exe.
Aprire WinDbg.
Scegliere Avvia eseguibile dal menu File. Nella finestra di dialogo Avvia eseguibile passare a C:\MyApp\x64\Debug. In Nome file immettere 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 per i file di origine.
Immettere questi comandi:
L'applicazione si interrompe nel debugger quando si tratta della relativa
main
funzione.WinDbg visualizza il codice sorgente e la finestra Comando.
Nel menu Debug selezionare Esegui istruzione in (o selezionare F11). Continuare a eseguire l'istruzione fino a quando non si esegue l'istruzione in
MyFunction
. Quando si entra nella rigay = x / p2
, l'applicazione si arresta in modo anomalo e si interrompe 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
Contents
comando nelHelp
menu- .sympath (Imposta percorso simbolo)
- Ricaricamento (modulo ricaricamento)
- x (esaminare i simboli)
- g (Vai)
Break
comando nelDebug
menu- lm (elencare i moduli caricati)
- k (Display Stack Backtrace)
- bu (Imposta punto di interruzione)
- bl (elenco punti di interruzione)
- ~ (Stato thread)
- ~s (Imposta thread corrente)
- .sympath+ (Imposta percorso simbolo) accodare al percorso del simbolo esistente
- .srcpath (Imposta percorso di origine)
Step Into
comando nelDebug
menu (F11)- !analyze -v
- qd (esci e scollega)
Vedi anche
Introduzione a WinDbg (modalità kernel)