Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa guida illustra come usare WinDbg per eseguire il debug di applicazioni in modalità utente. Si praticano le competenze di debug essenziali collegando un processo in esecuzione, impostando punti di interruzione e diagnosticando gli arresti anomali dell'applicazione.
In questo articolo:
- Collega WinDbg al Blocco note ed esplora il debug di base
- Eseguire il debug dell'applicazione e analizzare un arresto anomalo
- Impara i comandi di debug essenziali
Cosa imparerai
- Collegare WinDbg a un processo in esecuzione
- Configurare i file di simboli per l'output di debug leggibile
- Impostare punti di interruzione e controllare l'esecuzione del programma
- Analizzare i guasti di applicazione
- Navigare tra i thread e gli stack di chiamate
Prerequisiti
- WinDbg installato nel computer. Per istruzioni sull'installazione, vedere Scaricare e installare il debugger windows WinDbg.
- Conoscenza di base delle interfacce della riga di comando
- (Facoltativo) Applicazione compilata con simboli di debug per il secondo esercizio
Tempo stimato per il completamento: 30 minuti
Apri il Blocco note e collega 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 notepad.exe si trova generalmente in
C:\Windows\System32). In Nome file immettere notepad.exe. Selezionare Apri.
Configurare i file di simboli in modo che WinDbg possa visualizzare nomi di variabili e funzioni leggibili.
Nella riga di comando nella parte inferiore della finestra winDbg immettere questo comando:
L'output è simile all'esempio seguente:
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRVChe cosa sono i simboli? I file di simboli (PDB) contengono informazioni sui moduli di codice, ad esempio nomi di funzione e nomi di variabili. Senza simboli, vengono visualizzati solo gli indirizzi di memoria.
Immettere quindi questo comando:
Il comando
.reloadindica 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 /fper 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 contiene
main, usare il comando esamina i simboli per elencare i moduli che corrispondono alla maschera:x notepad!wWin*L'output è simile all'esempio seguente:
00007ff6`6e76b0a0 notepad!wWinMain (wWinMain) 00007ff6`6e783db0 notepad!wWinMainCRTStartup (wWinMainCRTStartup)Per inserire un punto di interruzione in
notepad!wWinMain, immettere questo comando:Per verificare di impostare il punto di interruzione, immettere questo comando:
L'output è simile all'esempio seguente:
0 e Disable Clear 00007ff6`6e76b0a0 0001 (0001) 0:**** notepad!wWinMainPer avviare Blocco note, immettere questo comando:
Il Blocco note viene eseguito fino a quando non arriva alla funzione
WinMaine quindi si interrompe nel debugger.Breakpoint 0 hit notepad!wWinMain: 00007ff6`6e76b0a0 488bc4 mov rax,rspPer visualizzare un elenco di moduli di codice attualmente caricati nel processo Blocco Note, immettere questo comando:
L'output è simile all'esempio seguente:
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 all'esempio seguente:
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+0x21Per avviare di nuovo Blocco note, immettere questo comando:
Prossimo: Si interromperà l'esecuzione ed si esploreranno i moduli caricati.
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 di nuovo 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 di
ZwCreateFile. 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 all'esempio seguente:
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 UnfrozenIn 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 all'esempio seguente:
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+0xdaPer 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.
Sul menu File, selezionare Eseguire programma 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
Questi 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 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 all'esempio seguente:
(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=00000000Immettere 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; ...
Passaggi successivi
Dopo aver eseguito il debug di un'applicazione di sistema e del proprio codice, è possibile esplorare scenari di debug più avanzati:
- Introduzione a WinDbg (modalità kernel) - Eseguire il debug di driver e kernel Windows
- Operazione del debugger - Informazioni sui concetti relativi alle operazioni del debugger
- Tecniche di debug - Esplorare i metodi di debug avanzati
Riepilogo dei comandi
Ecco i comandi essenziali usati in questa esercitazione:
Configurazione e simboli:
- .sympath (Set Symbol Path) - Configurare dove WinDbg trova i file di simboli
- .reload (Reload Module) - Caricare i file di simboli
Controllo dell'esecuzione:
- g (Go) - Continuare l'esecuzione del programma
- bu (Imposta punto di interruzione): sospendere l'esecuzione in una funzione specifica
-
Step Into(F11) - Esegui un'istruzione ed entra nelle funzioni
Controllo del programma:
- x (Esamina simboli) - Elencare funzioni e variabili
- lm (Elenca moduli caricati) - Mostra tutte le DLL caricate e tutti i file eseguibili
- k (Display Stack Backtrace) - Visualizzare lo stack di chiamate
- ~ (Stato thread) - Elencare tutti i thread
- !analyze -v - Analisi automatica dei crash
Reference:
- bl (elenco punti di interruzione)
- ~s (Imposta il thread corrente)
- .sympath+
- .srcpath (Imposta percorso di origine)
- qd (esci e scollega)
Vedere anche
Introduzione all'uso con WinDbg (modalità kernel)