Eseguire il debug dei driver windows step-by-step lab (modalità kernel echo)
Questo lab introduce il debugger del kernel WinDbg. Si usa WinDbg per eseguire il debug del codice del driver di esempio in modalità kernel echo.
Obiettivi del lab
Questo lab include esercizi che introducono gli strumenti di debug, insegnano i comandi di debug comuni, illustrano l'uso dei punti di interruzione e illustrano come usare le estensioni di debug.
In questo lab si usa una connessione di debug del kernel live per esplorare le azioni seguenti:
- Usare i comandi del debugger di Windows
- Usare comandi standard (stack di chiamate, variabili, thread, IRQL)
- Usare i comandi avanzati di debug dei driver (!commands)
- Usare i simboli
- Impostare punti di interruzione nel debug in tempo reale
- Visualizzare gli stack di chiamate
- Visualizzare l'albero dei dispositivi Plug and Play
- Usare il contesto del thread e del processo
Debug in modalità utente e kernel
Quando si usa il debugger Windows, è possibile eseguire due tipi di debug:
Modalità utente: le applicazioni e i sottosistemi vengono eseguiti nel computer in modalità utente. I processi eseguiti in modalità utente eseguono questa operazione all'interno dei propri spazi indirizzi virtuali. Sono limitati a ottenere l'accesso diretto a molte parti del sistema, tra cui hardware di sistema, memoria non allocata per il loro uso e altre parti del sistema che potrebbero compromettere l'integrità del sistema. Poiché i processi eseguiti in modalità utente sono effettivamente isolati dal sistema e da altri processi in modalità utente, non possono interferire con queste risorse.
Modalità kernel: il sistema operativo e i programmi con privilegi vengono eseguiti in modalità kernel. Il codice in modalità kernel ha l'autorizzazione per accedere a qualsiasi parte del sistema. Non è limitato come il codice in modalità utente. Può ottenere l'accesso a qualsiasi parte di qualsiasi altro processo in esecuzione in modalità utente o kernel. Gran parte delle funzionalità principali del sistema operativo e molti driver di dispositivo hardware vengono eseguiti in modalità kernel.
Questo esercizio illustra i comandi di debug usati di frequente durante il debug in modalità utente e in modalità kernel. L'esercizio illustra anche le estensioni di debug, talvolta denominate "bang" !commands, usate per il debug in modalità kernel.
Configurazione del laboratorio
Per completare il lab sono necessari gli hardware seguenti:
- Un computer portatile o desktop (host) che esegue Windows 10
- Un secondo computer portatile o desktop (destinazione) che esegue Windows 10
- Un hub di rete o un router e cavi di rete per connettere i due computer
- Accesso a Internet per scaricare i file di simboli
Per completare il lab, è necessario il software seguente:
- Visual Studio
- Windows Software Development Kit (SDK) per Windows 10
- Windows Driver Kit (WDK) per Windows 10
- Il driver echo di esempio per Windows 10
Il lab include le sezioni seguenti:
- Connettersi a una sessione WinDbg in modalità kernel
- Comandi e tecniche di debug in modalità kernel
- Scaricare e compilare il driver echo KMDF
- Installare l'esempio di driver echo nel sistema di destinazione
- Usare WinDbg per visualizzare informazioni sul driver
- Visualizzare le informazioni sull'albero dei dispositivi Plug and Play
- Usare punti di interruzione e codice sorgente
- Visualizzare variabili e stack di chiamate
- Visualizzare processi e thread
- IRQL, registra e termina la sessione winDbg
- Risorse di debug di Windows
Connettersi a una sessione WinDbg in modalità kernel
In questa sezione configurare il debug di rete nel sistema host e di destinazione.
I computer in questo lab devono essere configurati per usare una connessione di rete Ethernet per il debug del kernel.
Questo lab usa due computer. Il debugger Windows viene eseguito nel sistema host e il driver echo KMDF (Kernel Mode Driver Framework) viene eseguito nel sistema di destinazione .
Usare un hub di rete o un router e cavi di rete per connettere i due computer.
Per usare applicazioni in modalità kernel e usare WinDbg, è consigliabile usare il trasporto KDNET su Ethernet. Per informazioni su come usare il protocollo di trasporto Ethernet, vedere Introduzione a WinDbg (modalità kernel). Per altre informazioni sulla configurazione del computer di destinazione, vedere Preparazione di un computer per la distribuzione manuale dei driver e Configurazione automatica del debug del kernel di rete KDNET.
Configurare il debug in modalità kernel tramite Ethernet
Per abilitare il debug in modalità kernel nel sistema di destinazione:
Nel sistema host aprire una finestra del prompt dei comandi e immettere ipconfig per determinare l'indirizzo IPv4.
Windows IP Configuration Ethernet adapter Ethernet: Connection-specific DNS Suffix . : Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b%3 Autoconfiguration IPv4 Address. . : 169.182.1.1 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . :
Registrare l'indirizzo IP del sistema host: ______________________________________
Nel sistema di destinazione aprire una finestra del prompt dei comandi e usare il comando per verificare la
ping
connettività di rete tra i due sistemi.ping 169.182.1.1
Usare l'indirizzo IP effettivo del sistema host registrato anziché 169.182.1.1 visualizzato nell'output di esempio.
Pinging 169.182.1.1 with 32 bytes of data: Reply from 169.182.1.1: bytes=32 time=1ms TTL=255 Reply from 169.182.1.1: bytes=32 time<1ms TTL=255 Reply from 169.182.1.1: bytes=32 time<1ms TTL=255 Reply from 169.182.1.1: bytes=32 time<1ms TTL=255 Ping statistics for 169.182.1.1: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 0ms, Maximum = 1ms, Average = 0ms
Abilitare il debug in modalità kernel nel sistema di destinazione completando i passaggi seguenti.
Importante
Prima di usare BCDEdit per modificare le informazioni di avvio, potrebbe essere necessario sospendere temporaneamente le funzionalità di sicurezza di Windows, ad esempio BitLocker e Avvio protetto nel computer di test. Riabilitare queste funzionalità di sicurezza al termine del test. Gestire in modo appropriato il computer di test quando le funzionalità di sicurezza sono disabilitate. L'avvio protetto è in genere disabilitato in UEFI. Per accedere all'impostazione UEFI, usa sistema, ripristino, avvio avanzato. Al riavvio selezionare Risoluzione dei problemi, Opzioni avanzate, Impostazioni firmware UEFI. Prestare attenzione, poiché l'impostazione non corretta delle opzioni UEFI o la disabilitazione di BitLocker possono rendere il sistema inutilizzabile.
Nel computer di destinazione aprire una finestra del prompt dei comandi come amministratore. Immettere questo comando per abilitare il debug:
bcdedit /set {default} DEBUG YES
Immettere questo comando per abilitare la firma di test:
bcdedit /set TESTSIGNING ON
Immettere questo comando per impostare l'indirizzo IP del sistema host. Usare l'indirizzo IP del sistema host registrato in precedenza, non quello visualizzato.
bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Avviso
Per aumentare la sicurezza della connessione e ridurre il rischio delle richieste di connessione casuali del debugger client, usare una chiave casuale generata automaticamente. Per altre informazioni, vedere Configurazione automatica del debug del kernel di rete KDNET.
Immettere questo comando per verificare che i valori per
dbgsettings
siano impostati correttamente:bcdedit /dbgsettings
key 2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p debugtype NET hostip 169.168.1.1 port 50000 dhcp Yes The operation completed successfully.
Nota
Se si riceve un messaggio dal firewall e si vuole usare il debugger, selezionare tutte e tre le caselle.
Nel computer host aprire una finestra del prompt dei comandi come amministratore. Questo lab usa la versione x64 di WinDbg.exe di Windows Driver Kit (WDK) installata nell'ambito dell'installazione di Windows Kit. Passare alla directory WinDbg predefinita. Il percorso predefinito è illustrato di seguito.
cd C:\Program Files(x86)\Windows Kits\10\Debuggers\x64
Questo lab presuppone che entrambi i computer eseguano una versione a 64 bit di Windows sia nella destinazione che nell'host. In caso contrario, l'approccio migliore consiste nell'eseguire lo stesso bit degli strumenti nell'host eseguito dalla destinazione. Ad esempio, se la destinazione esegue Windows a 32 bit, eseguire una versione a 32 bit del debugger nell'host. Per altre informazioni, vedere Scelta degli strumenti di debug a 32 bit o a 64 bit.
Aprire WinDbg con il debug dell'utente remoto usando il comando seguente. I valori per la chiave e la porta corrispondono ai valori impostati in precedenza usando BCDEdit nel computer di destinazione.
WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Riavviare il sistema di destinazione.
In un minuto o due, l'output di debug deve essere visualizzato nel sistema host.
Microsoft (R) Windows Debugger Version 10.0.17074.1002 AMD64 Copyright (c) Microsoft Corporation. All rights reserved. Using NET for debugging Opened WinSock 2.0 Waiting to reconnect... Connected to target 169.182.1.1 on port 50005 on local IP 169.182.1.2 You can get the target MAC address by running .kdtargetmac command. Connected to Windows 10 16299 x64 target at (Wed Feb 28 17:16:23.051 2018 (UTC - 8:00)), ptr64 TRUE Kernel Debugger connection established. (Initial Breakpoint requested) Symbol search path is: srv* Executable search path is: Windows 10 Kernel Version 16299 MP (4 procs) Free x64 Product: WinNt, suite: TerminalServer SingleUserTS Built by: 16299.15.amd64fre.rs3_release.170928-1534 Machine Name: Kernel base = 0xfffff800`9540d000 PsLoadedModuleList = 0xfffff800`95774110 Debug session time: Wed Feb 28 17:16:23.816 2018 (UTC - 8:00) System Uptime: 0 days 0:00:20.534
La finestra Comando debugger è la finestra principale delle informazioni di debug in WinDbg. È possibile immettere i comandi del debugger e visualizzare l'output del comando in questa finestra.
La finestra Comando debugger è suddivisa in due riquadri. Immettere i comandi nel riquadro più piccolo, ovvero il riquadro di immissione dei comandi nella parte inferiore della finestra e visualizzare l'output del comando nel riquadro più grande nella parte superiore della finestra.
Nel riquadro della voce di comando usare i tasti freccia SU e Freccia GIÙ per scorrere la cronologia dei comandi. Quando viene visualizzato un comando, è possibile modificarlo o premere INVIO per eseguire il comando.
Comandi e tecniche di debug in modalità kernel
In questa sezione usare i comandi di debug per visualizzare informazioni sul sistema di destinazione.
Alcuni comandi di debug visualizzano testo usando DML (Debugger Markup Language) che è possibile selezionare per raccogliere rapidamente altre informazioni.
Nel sistema host usare CTRL+Scroll Lock in WinDBg per suddividere il codice in esecuzione nel sistema di destinazione. La risposta del sistema di destinazione potrebbe richiedere del tempo.
Immettere il comando seguente per abilitare DML nella finestra Di comando del debugger:
0: kd> .prefer_dml 1 DML versions of commands on by default
È possibile accedere alla Guida del comando di riferimento usando il
.hh
comando . Immettere il comando seguente per visualizzare la Guida di riferimento ai comandi per.prefer_dml
:0: kd> .hh .prefer_dml
Il file della Guida del debugger visualizza la Guida per il
.prefer_dml
comando .Per visualizzare informazioni dettagliate sulla versione nel sistema di destinazione, immettere il comando vertarget (Mostra versione computer di destinazione) nella finestra WinDbg:
0: kd> vertarget Windows 10 Kernel Version 9926 MP (4 procs) Free x64 Product: WinNt, suite: TerminalServer SingleUserTS Built by: 9926.0.amd64fre.fbl_awesome1501.150119-1648 Machine Name: "" Kernel base = 0xfffff801`8d283000 PsLoadedModuleList = 0xfffff801`8d58aef0 Debug session time: Fri Feb 20 10:15:17.807 2015 (UTC - 8:00) System Uptime: 0 days 01:31:58.931
Per verificare di usare il processo in modalità kernel corretto, immettere il comando lm (Elenca moduli caricati) nella finestra WinDbg per visualizzare i moduli caricati:
0: Kd> lm start end module name fffff801`09200000 fffff801`0925f000 volmgrx (no symbols) fffff801`09261000 fffff801`092de000 mcupdate_GenuineIntel (no symbols) fffff801`092de000 fffff801`092ec000 werkernel (export symbols) werkernel.sys fffff801`092ec000 fffff801`0934d000 CLFS (export symbols) CLFS.SYS fffff801`0934d000 fffff801`0936f000 tm (export symbols) tm.sys fffff801`0936f000 fffff801`09384000 PSHED (export symbols) PSHED.dll fffff801`09384000 fffff801`0938e000 BOOTVID (export symbols) BOOTVID.dll fffff801`0938e000 fffff801`093f7000 spaceport (no symbols) fffff801`09400000 fffff801`094cf000 Wdf01000 (no symbols) fffff801`094d9000 fffff801`09561000 CI (export symbols) CI.dll ...
L'output omesso è indicato con "..." in questo lab.
Per richiedere informazioni dettagliate su un modulo specifico, usare l'opzione
v
(dettagliata):0: Kd> lm v m tcpip Browse full module list start end module name fffff801`09eeb000 fffff801`0a157000 tcpip (no symbols) Loaded symbol image file: tcpip.sys Image path: \SystemRoot\System32\drivers\tcpip.sys Image name: tcpip.sys Browse all global symbols functions data Timestamp: Sun Nov 09 18:59:03 2014 (546029F7) CheckSum: 00263DB1 ImageSize: 0026C000 Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4 Unable to enumerate user-mode unloaded modules, Win32 error 0n30
Non sono presenti percorsi di simboli impostati e simboli caricati, quindi nel debugger sono disponibili informazioni limitate.
Scaricare e compilare il driver echo KMDF
In questa sezione scaricare e compilare il driver echo KMDF.
In genere, si sta usando il proprio codice driver quando si usa WinDbg. Per acquisire familiarità con l'operazione WinDbg, questo lab usa il driver di esempio "Echo" del modello KMDF. Il codice sorgente è disponibile per comprendere le informazioni visualizzate in WinDbg. Questo esempio viene usato anche per illustrare come è possibile eseguire codice in modalità kernel nativo in un unico passaggio. Questa tecnica può essere utile per il debug di problemi complessi di codice in modalità kernel.
Per scaricare e compilare il driver audio di esempio Echo:
Scaricare ed estrarre l'esempio Echo kmDF da GitHub.
Visualizzare l'esempio echo in GitHub.
Leggere l'esempio.
Esplora tutti gli esempi di driver di Windows.
L'esempio Echo KMDF si trova nella cartella generale .
Scaricare gli esempi di driver in un unico file ZIP: Esempi di driver
Scaricare il file ZIP nel disco rigido locale.
Selezionare e tenere premuto o fare clic con il pulsante destro del mouse sul file ZIP e scegliere Estrai tutto. Specificare una nuova cartella oppure passare a una cartella esistente per archiviare i file estratti. Ad esempio, è possibile specificare C:\DriverSamples\ come nuova cartella in cui estrarre i file.
Dopo aver estratto i file, passare alla sottocartella seguente: C:\DriverSamples\general\echo\kmdf
In Microsoft Visual Studio selezionare File>Apri>progetto/soluzione e passare alla cartella contenente i file estratti, ad esempio C:\DriverSamples\general\echo\kmdf. Fare doppio clic sul file della soluzione kmdfecho per aprirlo.
In Visual Studio individuare il Esplora soluzioni. Se questa finestra non è già aperta, selezionare Esplora soluzioni dal menu Visualizza. In Esplora soluzioni è possibile visualizzare una soluzione con tre progetti.
Impostare la configurazione e la piattaforma dell'esempio. In Esplora soluzioni selezionare e tenere premuto o fare clic con il pulsante destro del mouse su Soluzione 'kmdfecho' (3 progetti) e selezionare Configuration Manager. Assicurarsi che le impostazioni di configurazione e piattaforma siano le stesse per i tre progetti. Per impostazione predefinita, la configurazione è impostata su Debug Win10 e la piattaforma è impostata su Win64 per tutti i progetti. Se si apportano modifiche alla configurazione o alla piattaforma per un progetto, apportare le stesse modifiche per i tre progetti rimanenti.
Gli esempi di driver devono essere modificati per usare valori che non si sovrappongono ai driver esistenti. Fare riferimento a From Sample Code to Production Driver - What to Change in the Samples on how to create a unique driver sample that will coesistere with existing real drivers installed in Windows.Refer to From Sample Code to Production Driver - What to Change in the Samples on how to create a unique driver sample that will coesiste with existing real drivers installed in Windows.
Impostare la libreria di runtime. Aprire la pagina delle proprietà del driver echo e individuare la generazione di codice C/C++>. Modificare la libreria di runtime in Debug multithread (/MTd). Per altre informazioni sulle opzioni di compilazione, vedere /MD, /MT, /LD (Usare la libreria di runtime).For more information about the build options, see /MD, /MT, /LD (Use Run-Time Library).
Nelle proprietà del driver verificare che la modalità di>firma del driver sia impostata su Test Sign (Firma del driver).
In Visual Studio selezionare Compila soluzione di>compilazione.
Le finestre di compilazione devono visualizzare un messaggio che indica che la compilazione per tutti e tre i progetti è riuscita.
Suggerimento
Se viene visualizzato un messaggio di errore di compilazione, usare il numero di errore di compilazione per determinare una correzione. Ad esempio, l'errore di MSBuild MSB8040 descrive come usare le librerie con mitigazione spectre.
In Esplora file passare alla cartella contenente i file estratti per l'esempio. Ad esempio, passare a C:\DriverSamples\general\echo\kmdf, se si tratta della cartella specificata in precedenza. All'interno di tale cartella, il percorso dei file del driver compilati varia a seconda delle impostazioni di configurazione e piattaforma selezionate in Configuration Manager. Se le impostazioni predefinite sono rimaste invariate, i file del driver compilati vengono salvati in una cartella denominata \x64\Debug per una build di debug a 64 bit.
Passare alla cartella contenente i file compilati per il driver di sincronizzazione automatica: C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.
La cartella deve contenere questi file:
File Descrizione Echo.sys File del driver. Echo.inf File di informazioni (INF) che contiene le informazioni necessarie per installare il driver. Inoltre, il file echoapp.exe è stato compilato e dovrebbe trovarsi qui: C:\DriverSamples\general\echo\kmdf\exe\x64\Debug.
File Descrizione EchoApp.exe File di test eseguibile del prompt dei comandi che comunica con il driver echo.sys. Individuare un'unità usb o configurare una condivisione di rete per copiare i file del driver compilati e il test EchoApp dall'host al sistema di destinazione.
Nella sezione successiva copiare il codice nel sistema di destinazione e installare e testare il driver.
Installare l'esempio di echo driver KMDF nel sistema di destinazione
In questa sezione usare lo strumento DevCon per installare il driver di esempio echo.
Il computer in cui si installa il driver viene chiamato computer di destinazione o computer di test. In genere, questo computer è separato dal computer in cui si sviluppa e si compila il pacchetto driver. Il computer in cui si sviluppa e si compila il driver viene chiamato computer host.
Il processo di spostamento del pacchetto driver nel computer di destinazione e l'installazione del driver viene chiamato distribuzione del driver.
Prima di distribuire un driver firmato per il test, preparare il computer di destinazione abilitando la firma dei test. È anche necessario individuare lo strumento DevCon nell'installazione di WDK e copiarlo nel sistema di destinazione.
Per installare il driver nel sistema di destinazione, seguire questa procedura.
Nel sistema di destinazione abilitare i driver firmati di test:
Aprire Impostazioni di Windows.
In Aggiornamento e sicurezza selezionare Ripristino.
In Avvio avanzato selezionare Riavvia ora.
Al riavvio del computer, selezionare Opzioni di avvio. In Windows 10 selezionare Risoluzione dei problemi Opzioni>avanzate>Impostazioni di avvio, quindi selezionare Riavvia.
Selezionare Disabilita l'imposizione della firma del driver premendo F7.
Riavviare il computer di destinazione.
Nel sistema host passare alla cartella Strumenti nell'installazione di WDK e individuare lo strumento DevCon. Ad esempio, cercare nella cartella seguente: C:\Programmi (x86)\Windows Kits\10\Tools\x64\devcon.exe.
Creare una cartella nella destinazione per il pacchetto driver compilato, ad esempio C:\EchoDriver. Copiare devcon.exe nel sistema di destinazione. Individuare il certificato .cer nel sistema host. Si trova nella stessa cartella del computer host nella cartella che contiene i file del driver compilati. Copiare tutti i file dal driver compilato descritto in precedenza nel computer host e salvarli nella stessa cartella creata nel computer di destinazione.
Nel computer di destinazione selezionare e tenere premuto o fare clic con il pulsante destro del mouse sul file del certificato e selezionare Installa, quindi seguire le istruzioni per installare il certificato di test.
Se sono necessarie istruzioni più dettagliate per la configurazione del computer di destinazione, vedere Preparazione di un computer per la distribuzione manuale dei driver.
Le istruzioni seguenti illustrano come installare e testare il driver di esempio. Ecco la sintassi generale per lo strumento devcon che si usa per installare il driver:
devcon install <INF file> <hardware ID>
Il file INF necessario per l'installazione di questo driver è echo.inf. Il file inf contiene l'ID hardware per l'installazione del echo.sys. Per l'esempio echo, l'ID hardware è root\ECHO.
Nel computer di destinazione aprire una finestra del prompt dei comandi come amministratore. Passare alla cartella del pacchetto driver e immettere il comando seguente:
devcon install echo.inf root\ECHO
Se viene visualizzato un messaggio di errore relativo a devcon non riconosciuto, provare ad aggiungere il percorso allo strumento devcon . Ad esempio, se è stato copiato in una cartella denominata C:\Tools, provare a usare il comando seguente:
c:\tools\devcon install echo.inf root\ECHO
Viene visualizzata una finestra di dialogo che indica che il driver di test è un driver non firmato. Selezionare Installa questo driver comunque per continuare.
Suggerimento
Se si verificano problemi con l'installazione, controllare il file seguente per altre informazioni. %windir%\inf\setupapi.dev.log
Dopo aver installato correttamente il driver di esempio, è possibile testarlo.
Nel computer di destinazione, in una finestra del prompt dei comandi, immettere devmgmt per aprire Gestione dispositivi. In Gestione dispositivi scegliere Dispositivi per tipo dal menu Visualizza. Nell'albero dei dispositivi individuare Sample WDF Echo Driver (Driver Echo WDF di esempio) nel nodo Sample Device (Dispositivo di esempio).
Immettere echoapp per avviare l'app echo di test per verificare che il driver sia funzionante.
C:\Samples\KMDF_Echo_Sample> echoapp
DevicePath: \\?\root#sample#0005#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
512 Pattern Bytes Written successfully
512 Pattern Bytes Read successfully
Pattern Verified successfully
30720 Pattern Bytes Written successfully
30720 Pattern Bytes Read successfully
Pattern Verified successfully
Usare WinDbg per visualizzare informazioni sul driver
In questa sezione impostare il percorso del simbolo e usare i comandi del debugger del kernel per visualizzare informazioni sul driver echo echo kmDF.
Per visualizzare informazioni sul driver:
Nel sistema host, se il debugger è stato chiuso, aprirlo di nuovo usando il comando seguente nella finestra del prompt dei comandi dell'amministratore.
WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Usare CTRL+INTERR (blocco di scorrimento) per suddividere il codice in esecuzione nel sistema di destinazione.
Per impostare il percorso dei simboli sul server dei simboli Microsoft nell'ambiente WinDbg, usare il
.symfix
comando .0: kd> .symfix
Per aggiungere la posizione del simbolo locale per usare i simboli locali, aggiungere il percorso usando
.sympath+
e quindi.reload /f
.0: kd> .sympath+ C:\DriverSamples\general\echo\kmdf 0: kd> .reload /f
Il
.reload
comando con l'opzione/f
force elimina tutte le informazioni sui simboli per il modulo specificato e ricarica i simboli. In alcuni casi, questo comando ricarica o scarica il modulo stesso.
È necessario caricare i simboli appropriati per usare funzionalità avanzate fornite da WinDbg. Se i simboli non sono configurati correttamente, quando si tenta di usare funzionalità dipendenti dai simboli, si ricevono messaggi che indicano che i simboli non sono disponibili.
0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.
Esistono molti approcci che possono essere usati per lavorare con i simboli. In molte situazioni, è possibile configurare il computer per accedere ai simboli da un server di simboli fornito da Microsoft quando sono necessari. Questo lab usa questo approccio. Se i simboli nell'ambiente si trovano in una posizione diversa, modificare i passaggi per usare tale posizione. Per altre informazioni, vedere Percorso dei simboli per il debugger di Windows.
Per eseguire il debug di origine, è necessario compilare una versione controllata (debug) dei file binari. Il compilatore crea file di simboli (file con estensione pdb ). Questi file di simboli mostrano al debugger il modo in cui le istruzioni binarie corrispondono alle righe di origine. Anche i file di origine effettivi devono essere accessibili al debugger.
I file di simboli non contengono il testo del codice sorgente. Per il debug, è preferibile se il linker non ottimizza il codice. Il debug dell'origine e l'accesso alle variabili locali sono più difficili e talvolta quasi impossibili, se il codice è stato ottimizzato. Se si verificano problemi durante la visualizzazione di variabili locali o righe di origine, impostare le opzioni di compilazione seguenti:
set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
Immettere il comando seguente nell'area di comando del debugger per visualizzare informazioni sul driver echo:
0: kd> lm m echo* v Browse full module list start end module name fffff801`4ae80000 fffff801`4ae89000 ECHO (private pdb symbols) C:\Samples\KMDF_ECHO_SAMPLE\echo.pdb Loaded symbol image file: ECHO.sys Image path: \SystemRoot\system32\DRIVERS\ECHO.sys Image name: ECHO.sys ...
Per altre informazioni, vedere lm.
Poiché questo lab impostato
prefer_dml
in precedenza, alcuni elementi dell'output sono collegamenti ad accesso frequente che è possibile selezionare. Selezionare il collegamento Sfoglia tutti i simboli globali nell'output di debug per visualizzare informazioni sui simboli degli elementi che iniziano con la lettera "a".0: kd> x /D Echo!a*
L'esempio echo non contiene simboli che iniziano con la lettera "a", quindi digitare
x ECHO!Echo*
per visualizzare informazioni su tutti i simboli associati al driver echo che iniziano con "Echo".0: kd> x ECHO!Echo* fffff801`0bf95690 ECHO!EchoEvtIoQueueContextDestroy (void *) fffff801`0bf95000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *) fffff801`0bf95ac0 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *) fffff801`0bf9b120 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *) ...
Per altre informazioni, vedere x (Esaminare i simboli).
L'estensione
!lmi
visualizza informazioni dettagliate su un modulo. Immetti!lmi echo
. L'output dovrebbe essere simile al testo illustrato in questo esempio:0: kd> !lmi echo Loaded Module Info: [echo] Module: ECHO Base Address: fffff8010bf94000 Image Name: ECHO.sys …
Usare l'estensione per visualizzare le informazioni sull'intestazione
!dh
, come illustrato in questo esempio:0: kd> !dh echo File Type: EXECUTABLE IMAGE FILE HEADER VALUES 14C machine (i386) 6 number of sections 54AD8A42 time date stamp Wed Jan 07 11:34:26 2015 ...
Immettere quanto segue per modificare la maschera di bit di debug predefinita in modo che tutti i messaggi di debug dal sistema di destinazione vengano visualizzati nel debugger:
0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
Alcuni driver visualizzano informazioni aggiuntive quando viene usata la maschera di 0xFFFFFFFF. Impostare la maschera su 0x00000000 se si vuole ridurre la quantità di informazioni visualizzate.
0: kd> ed nt!Kd_DEFAULT_MASK 0x00000000
Usare il
dd
comando per verificare che la maschera sia impostata per visualizzare tutti i messaggi del debugger.0: kd> dd nt!kd_DEFAULT_MASK fffff802`bb4057c0 ffffffff 00000000 00000000 00000000 fffff802`bb4057d0 00000000 00000000 00000000 00000000 fffff802`bb4057e0 00000001 00000000 00000000 00000000 fffff802`bb4057f0 00000000 00000000 00000000 00000000 fffff802`bb405800 00000000 00000000 00000000 00000000 fffff802`bb405810 00000000 00000000 00000000 00000000 fffff802`bb405820 00000000 00000000 00000000 00000000 fffff802`bb405830 00000000 00000000 00000000 00000000
Visualizzare le informazioni sull'albero dei dispositivi Plug and Play
In questa sezione vengono visualizzate informazioni sul driver di dispositivo echo sample e sulla posizione in cui si trova nell'albero dei dispositivi Plug and Play.
Le informazioni sul driver di dispositivo nell'albero dei dispositivi Plug and Play possono essere utili per la risoluzione dei problemi. Ad esempio, se un driver di dispositivo non è residente nell'albero dei dispositivi, potrebbe verificarsi un problema con l'installazione del driver di dispositivo.
Per altre informazioni sull'estensione di debug del nodo del dispositivo, vedere !devnode.
Nel sistema host immettere il
!devnode 0 1
comando per visualizzare tutti i nodi del dispositivo nell'albero dei dispositivi Plug and Play.0: kd> !devnode 0 1 Dumping IopRootDeviceNode (= 0xffffe0005a3a8d30) DevNode 0xffffe0005a3a8d30 for PDO 0xffffe0005a3a9e50 InstancePath is "HTREE\ROOT\0" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) DevNode 0xffffe0005a3a3d30 for PDO 0xffffe0005a3a4e50 InstancePath is "ROOT\volmgr\0000" ServiceName is "volmgr" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) DevNode 0xffffe0005a324560 for PDO 0xffffe0005bd95ca0… …
Usare CTRL+F per cercare nell'output generato per cercare il nome del driver di dispositivo, echo.
Il driver del dispositivo echo deve essere caricato. Usare il
!devnode 0 1 echo
comando per visualizzare le informazioni di Plug and Play associate al driver di dispositivo echo, come illustrato in questo esempio:0: Kd> !devnode 0 1 echo Dumping IopRootDeviceNode (= 0xffffe0007b725d30) DevNode 0xffffe0007b71a630 for PDO 0xffffe0007b71a960 InstancePath is "ROOT\SAMPLE\0000" ServiceName is "ECHO" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) …
L'output visualizzato nel comando precedente include il PDO associato all'istanza in esecuzione del driver, in questo esempio 0xffffe0007b71a960. Immettere il
!devobj <PDO address>
comando per visualizzare le informazioni di Plug and Play associate al driver di dispositivo echo. Usare l'indirizzo PDO visualizzato!devnode
nel computer, non quello mostrato qui.0: kd> !devobj 0xffffe0007b71a960 Device object (ffffe0007b71a960) is for: 0000000e \Driver\PnpManager DriverObject ffffe0007b727e60 Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040 Dacl ffffc102c9b36031 DevExt 00000000 DevObjExt ffffe0007b71aab0 DevNode ffffe0007b71a630 ExtensionFlags (0x00000800) DOE_DEFAULT_SD_PRESENT Characteristics (0x00000180) FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN AttachedDevice (Upper) ffffe000801fee20 \Driver\ECHO Device queue is not busy.
L'output visualizzato nel
!devnode 0 1
comando include l'indirizzo PDO associato all'istanza in esecuzione del driver, in questo esempio è 0xffffe0007b71a960. Immettere il!devstack <PDO address>
comando per visualizzare le informazioni di Plug and Play associate al driver di dispositivo. Usare l'indirizzo PDO visualizzato!devnode
nel computer, non quello illustrato in questo esempio.0: kd> !devstack 0xffffe0007b71a960 !DevObj !DrvObj !DevExt ObjectName ffffe000801fee20 \Driver\ECHO ffffe0007f72eff0 > ffffe0007b71a960 \Driver\PnpManager 00000000 0000000e !DevNode ffffe0007b71a630 : DeviceInst is "ROOT\SAMPLE\0000" ServiceName is "ECHO"
L'output mostra che si dispone di uno stack di driver di dispositivo abbastanza semplice. Il driver echo è un elemento figlio del nodo PnPManager . PnPManager è un nodo radice.
\Driver\ECHO
\Driver\PnpManager
Questo diagramma mostra un albero dei nodi del dispositivo più complesso.
Per altre informazioni sugli stack di driver più complessi, vedere Stack di driver e nodi del dispositivo e stack di dispositivi.
Usare punti di interruzione e codice sorgente
In questa sezione impostare i punti di interruzione e il codice sorgente in modalità kernel in un unico passaggio.
Per poter eseguire il codice e controllare i valori delle variabili in tempo reale, abilitare i punti di interruzione e impostare un percorso al codice sorgente.
I punti di interruzione arrestano l'esecuzione del codice in una determinata riga di codice. Procedere nel codice da quel punto per eseguire il debug di tale sezione specifica del codice.
Per impostare un punto di interruzione usando un comando di debug, usare uno dei comandi seguenti b
.
Comando | Descrizione |
---|---|
bp |
Imposta un punto di interruzione attivo fino a quando il modulo in cui si trova non viene scaricato. |
bu |
Imposta un punto di interruzione non risolto quando il modulo viene scaricato e riattiva quando il modulo viene ricaricato. |
bm |
Imposta un punto di interruzione per un simbolo. Questo comando usa bu o bp in modo appropriato e consente l'uso di caratteri jolly (* ) per impostare punti di interruzione su ogni simbolo corrispondente, come tutti i metodi di una classe. |
Per altre informazioni, vedere Debug del codice sorgente in WinDbg.
Nel sistema host usare l'interfaccia utente winDbg per verificare che la modalità di origine di debug>sia abilitata nella sessione WinDbg corrente.
Immettere il comando seguente per aggiungere il percorso del codice locale al percorso di origine:
.srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
Immettere il comando seguente per aggiungere la posizione del simbolo locale al percorso del simbolo:
.sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
Usare il
x
comando per esaminare i simboli associati al driver echo per determinare il nome della funzione da usare per il punto di interruzione. È possibile usare un carattere jolly o CTRL+F per individuare il nome dellaDeviceAdd
funzione.0: kd> x ECHO!EchoEvt* 8b4c7490 ECHO!EchoEvtIoQueueContextDestroy (void *) 8b4c7000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *) 8b4c7820 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *) 8b4cb0e0 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *) 8b4c75d0 ECHO!EchoEvtIoWrite (struct WDFQUEUE__ *, struct WDFREQUEST__ *, unsigned int) 8b4cb170 ECHO!EchoEvtDeviceAdd (struct WDFDRIVER__ *, struct …
L'output mostra che il
DeviceAdd
metodo per il driver echo èECHO!EchoEvtDeviceAdd
.In alternativa, esaminare il codice sorgente per trovare il nome della funzione per il punto di interruzione.
Impostare il punto di interruzione con il
bm
comando usando il nome del driver, seguito dal nome della funzione, ad esempio ,AddDevice
dove si vuole impostare il punto di interruzione, separato da un punto esclamativo. Questo lab usaAddDevice
per controllare il driver caricato.0: kd> bm ECHO!EchoEvtDeviceAdd 1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
È possibile usare una sintassi diversa insieme all'impostazione di variabili come
<module>!<symbol>
,<class>::<method>
'<file.cpp>:<line number>'
o ignorare un numero di volte<condition> <#>
. Per altre informazioni, vedere Punti di interruzione condizionali in WinDbg e altri debugger Windows.Elencare i punti di interruzione correnti per verificare che il punto di interruzione sia stato impostato immettendo il
bl
comando :0: kd> bl 1 e fffff801`0bf9b1c0 0001 (0001) ECHO!EchoEvtDeviceAdd
L'output "e" illustrato di seguito indica che il punto di interruzione numero 1 è abilitato per l'attivazione.
Riavviare l'esecuzione del codice nel sistema di destinazione immettendo il
g
comando (vai).Nel sistema di destinazione, in Windows, aprire Gestione dispositivi usando l'icona o immettendo mmc devmgmt.msc. In Gestione dispositivi espandere il nodo Esempi.
Selezionare e tenere premuto o fare clic con il pulsante destro del mouse sulla voce del driver echo KMDF e scegliere Disabilita dal menu.
Selezionare e tenere premuto o fare di nuovo clic con il pulsante destro del mouse sulla voce del driver echo KMDF e scegliere Abilita dal menu.
Nel sistema host, quando il driver è abilitato, verrà attivato il punto di interruzione di debug AddDevice . L'esecuzione del codice driver nel sistema di destinazione deve interrompersi. Quando viene raggiunto il punto di interruzione, l'esecuzione deve essere arrestata all'inizio della routine AddDevice . L'output del comando di debug visualizza
Breakpoint 1 hit
.Scorrere la riga di codice in base alla riga immettendo il
p
comando o premendo F10 fino a raggiungere la fine seguente della routine AddDevice . Il carattere parentesi graffa (}
) è evidenziato come illustrato.
Nella sezione successiva esaminare lo stato delle variabili dopo l'esecuzione del codice DeviceAdd.
È possibile modificare i punti di interruzione esistenti usando i comandi seguenti:
Comando | Descrizione |
---|---|
bl |
Elenca i punti di interruzione. |
bc |
Cancella un punto di interruzione dall'elenco. Utilizzare bc * per cancellare tutti i punti di interruzione. |
bd |
Disabilita un punto di interruzione. Usare bd * per disabilitare tutti i punti di interruzione. |
be |
Abilita un punto di interruzione. Usare be * per abilitare tutti i punti di interruzione. |
In alternativa, è anche possibile modificare i punti di interruzione nell'interfaccia utente di WinDbg.
È anche possibile impostare punti di interruzione attivati quando si accede a una posizione di memoria. Usare il ba
comando (interruzione all'accesso) con la sintassi seguente:
ba <access> <size> <address> {options}
Opzione | Descrizione |
---|---|
e |
execute: quando la CPU recupera un'istruzione dall'indirizzo |
r |
lettura/scrittura: quando la CPU legge o scrive nell'indirizzo |
w |
write: quando la CPU scrive nell'indirizzo |
È possibile impostare solo quattro punti di interruzione dei dati in un determinato momento. Spetta all'utente assicurarsi di allineare correttamente i dati per attivare il punto di interruzione. Le parole devono terminare in indirizzi divisibile per 2, dwords deve essere divisibile per 4 e quad parole per 0 o 8.
Ad esempio, per impostare un punto di interruzione di lettura/scrittura in un indirizzo di memoria specifico, è possibile usare un comando come questo esempio.
ba r 4 0x0003f7bf0
È possibile usare i comandi seguenti per scorrere il codice con i tagli brevi della tastiera associati visualizzati tra parentesi.
- Interrompi (CTRL+INTERR). Questo comando interrompe un sistema finché il sistema è in esecuzione ed è in comunicazione con WinDbg. La sequenza nel debugger del kernel è CTRL+C.
- Esegui fino al cursore (F7 o CTRL+F10). Posizionare il cursore in una finestra di origine o disassembly in cui si desidera interrompere l'esecuzione, quindi premere F7. L'esecuzione del codice viene eseguita a quel punto. Se il flusso di esecuzione del codice non raggiunge il punto indicato dal cursore, WinDbg non interromperà. Questa situazione può verificarsi se un'istruzione IF non viene eseguita.
- Esegui (F5). Eseguire fino a quando non viene rilevato un punto di interruzione o si verifica un evento come un controllo di bug.
- Eseguire il passaggio (F10). Questo comando fa sì che l'esecuzione del codice proceda a un'istruzione o a un'istruzione alla volta. Se viene rilevata una chiamata, l'esecuzione del codice passa attraverso la chiamata senza immettere la routine chiamata. Se il linguaggio di programmazione è C o C++ e WinDbg è in modalità di origine, la modalità di origine può essere attivata o disattivata tramite la modalità di origine di debug>.
- Eseguire l'istruzione in (F11). Questo comando è simile al passaggio, ad eccezione del fatto che l'esecuzione di una chiamata passa alla routine chiamata.
- Esci (MAIUSC+F11). Questo comando causa l'esecuzione e l'uscita dalla routine corrente o dalla posizione corrente nello stack di chiamate. Questo comando è utile se si è visto abbastanza della routine.
Per altre informazioni, vedere Debug del codice sorgente in WinDbg.
Visualizzare variabili e stack di chiamate
In questa sezione vengono visualizzate informazioni sulle variabili e sugli stack di chiamate.
Questo lab presuppone che l'utente venga arrestato nella routine AddDevice usando il processo descritto in precedenza. Per visualizzare l'output illustrato qui, ripetere i passaggi descritti in precedenza, se necessario.
Nel sistema host, per visualizzare le variabili, usare la voce di menu locale di visualizzazione>per visualizzare le variabili locali.
Per trovare la posizione di un indirizzo variabile globale, immettere ? <variable name>
.
- Esci (MAIUSC+F11): questo comando causa l'esecuzione e l'uscita dalla routine corrente (posizione corrente nello stack di chiamate). Questo è utile se hai visto abbastanza della routine.
Per altre informazioni, vedere Debug del codice sorgente in WinDbg (versione classica) nella documentazione di riferimento sul debug.
Sezione 8: Visualizzazione di variabili e stack di chiamate
Nella sezione 8 verranno visualizzate informazioni sulle variabili e sugli stack di chiamate.
Questo lab presuppone che l'utente venga arrestato nella routine AddDevice usando il processo descritto in precedenza. Per visualizzare l'output qui, ripetere i passaggi descritti in precedenza, se necessario.
<- Nel sistema host
Visualizzare le variabili
Usare la voce di menu locale di visualizzazione>per visualizzare le variabili locali.
Variabili globali
È possibile trovare la posizione di un indirizzo di variabile globale digitando ? <nome> della variabile.
Variabili locali
È possibile visualizzare i nomi e i valori di tutte le variabili locali per un determinato frame digitando il comando dv .
Per visualizzare i nomi e i valori di tutte le variabili locali per un frame specifico, immettere il dv
comando :
0: kd> dv
Driver = 0x00001fff`7ff9c838
DeviceInit = 0xffffd001`51978190
status = 0n0
Lo stack di chiamate è la catena di chiamate di funzione che hanno portato alla posizione corrente del contatore del programma. La funzione principale nello stack di chiamate è la funzione corrente e la funzione successiva è la funzione che ha chiamato la funzione corrente e così via.
Per visualizzare lo stack di chiamate, usare i k*
comandi .
Comando | Descrizione |
---|---|
kb |
Visualizza lo stack e i primi tre parametri. |
kp |
Visualizza gli stack e l'elenco completo dei parametri. |
kn |
Consente di visualizzare lo stack con le informazioni sul frame accanto. |
Nel sistema host, se si vuole mantenere disponibile lo stack di chiamate, selezionare Visualizza>stack di chiamate per visualizzarlo. Selezionare le colonne nella parte superiore della finestra per attivare o disattivare la visualizzazione di informazioni aggiuntive.
Usare il
kn
comando per visualizzare lo stack di chiamate durante il debug del codice dell'adattatore di esempio in uno stato di interruzione.3: kd> kn # Child-SP RetAddr Call Site 00 ffffd001`51978110 fffff801`0942f55b ECHO!EchoEvtDeviceAdd+0x66 [c:\Samples\kmdf echo sample\c++\driver\autosync\driver.c @ 138] 01 (Inline Function) --------`-------- Wdf01000!FxDriverDeviceAdd::Invoke+0x30 [d:\wbrtm\minkernel\wdf\framework\shared\inc\private\common\fxdrivercallbacks.hpp @ 61] 02 ffffd001`51978150 fffff801`eed8097d Wdf01000!FxDriver::AddDevice+0xab [d:\wbrtm\minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 72] 03 ffffd001`51978570 fffff801`ef129423 nt!PpvUtilCallAddDevice+0x35 [d:\9142\minkernel\ntos\io\pnpmgr\verifier.c @ 104] 04 ffffd001`519785b0 fffff801`ef0c4112 nt!PnpCallAddDevice+0x63 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 7397] 05 ffffd001`51978630 fffff801`ef0c344f nt!PipCallDriverAddDevice+0x6e2 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 3390] ...
Lo stack di chiamate mostra che il kernel (nt) chiamato nel codice Plug and Play (PnP) che ha chiamato codice del framework driver (WDF) che in seguito ha chiamato la funzione del driver DeviceAdd
echo.
Visualizzare processi e thread
In questa sezione vengono visualizzate informazioni sui processi e sui thread in esecuzione in modalità kernel.
Processi
È possibile visualizzare o impostare le informazioni sul processo usando l'estensione del debugger !process . Impostare un punto di interruzione per esaminare il processo usato quando viene riprodotto un suono.
Nel sistema host immettere il
dv
comando per esaminare le variabili delle impostazioni locali associate allaEchoEvtIo
routine:0: kd> dv ECHO!EchoEvtIo* ECHO!EchoEvtIoQueueContextDestroy ECHO!EchoEvtIoWrite ECHO!EchoEvtIoRead
Cancellare i punti di interruzione precedenti usando
bc *
:0: kd> bc *
Impostare un punto di interruzione dei simboli nelle
EchoEvtIo
routine usando il comando seguente:0: kd> bm ECHO!EchoEvtIo* 2: aade5490 @!”ECHO!EchoEvtIoQueueContextDestroy” 3: aade55d0 @!”ECHO!EchoEvtIoWrite” 4: aade54c0 @!”ECHO!EchoEvtIoRead”
Elencare i punti di interruzione per verificare che il punto di interruzione sia impostato correttamente:
0: kd> bl 1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197] 0001 (0001) ECHO!EchoEvtIoQueueContextDestroy ...
Immettere
g
per riavviare l'esecuzione del codice:0: kd> g
Nel sistema di destinazione eseguire il
EchoApp.exe
programma di test driver nel sistema di destinazione.Nel sistema host, quando viene eseguita l'app di test, viene chiamata la routine di I/O nel driver. Questa chiamata fa sì che il punto di interruzione venga attivato e l'esecuzione del codice driver nel sistema di destinazione si arresta.
Breakpoint 2 hit ECHO!EchoEvtIoWrite: fffff801`0bf95810 4c89442418 mov qword ptr [rsp+18h],r8
Usare il
!process
comando per visualizzare il processo corrente coinvolto nell'esecuzione di echoapp.exe:0: kd> !process PROCESS ffffe0007e6a7780 SessionId: 1 Cid: 03c4 Peb: 7ff7cfec4000 ParentCid: 0f34 DirBase: 1efd1b000 ObjectTable: ffffc001d77978c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000802c79f0 Vads 30 Clone 0 Private 135. Modified 5. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf270050 ElapsedTime 00:00:00.052 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (682, 50, 345) (2728KB, 200KB, 1380KB) PeakWorkingSetSize 652 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 688 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe00080e32080 Cid 03c4.0ec0 Teb: 00007ff7cfece000 Win32Thread: 0000000000000000 RUNNING on processor 1
L'output mostra che il processo è associato al thread echoapp.exe , che era in esecuzione quando è stato raggiunto il punto di interruzione nell'evento di scrittura del driver. Per altre informazioni, vedere !process.
Utilizzare per
!process 0 0
visualizzare le informazioni di riepilogo per tutti i processi. Nell'output usare CTRL+F per individuare lo stesso indirizzo del processo associato all'immagine echoapp.exe . Nell'esempio l'indirizzo del processo èffffe0007e6a7780
.... PROCESS ffffe0007e6a7780 SessionId: 1 Cid: 0f68 Peb: 7ff7cfe7a000 ParentCid: 0f34 DirBase: 1f7fb9000 ObjectTable: ffffc001cec82780 HandleCount: 34. Image: echoapp.exe ...
Registrare l'ID del processo associato a echoapp.exe da usare più avanti in questo lab. È anche possibile usare CTRL+C per copiare l'indirizzo nel buffer di copia per usarlo in un secondo momento.
_____________________________________________________(indirizzo del processo di echoapp.exe)
Immettere
g
come richiesto nel debugger per eseguire il codice in avanti fino al termine dell'esecuzione di echoapp.exe . Raggiunge il punto di interruzione nell'evento di lettura e scrittura più volte. Al termine echoapp.exe , eseguire l'interruzione nel debugger premendo CTRL+SCRLk (CTRL+INTERR).Usare il
!process
comando per verificare che sia in esecuzione un processo diverso. Nell'output illustrato di seguito, il processo con il valore Image di System è diverso dal valore Echo Image.1: kd> !process PROCESS ffffe0007b65d900 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000 DirBase: 001ab000 ObjectTable: ffffc001c9a03000 HandleCount: 786. Image: System VadRoot ffffe0007ce45930 Vads 14 Clone 0 Private 22. Modified 131605. Locked 64. DeviceMap ffffc001c9a0c220 Token ffffc001c9a05530 ElapsedTime 21:31:02.516 ...
L'output mostra che un processo di sistema ffffe0007b65d900 era in esecuzione quando il sistema operativo è stato arrestato.
Usare il
!process
comando per provare a esaminare l'ID processo associato a echoapp.exe registrato in precedenza. Specificare l'indirizzo del processo di echoapp.exe registrato in precedenza, anziché l'indirizzo del processo di esempio illustrato in questo esempio.0: kd> !process ffffe0007e6a7780 TYPE mismatch for process object at 82a9acc0
L'oggetto processo non è più disponibile perché il processo di echoapp.exe non è più in esecuzione.
Threads
I comandi per visualizzare e impostare i thread sono simili ai comandi per i processi. Usare il comando !thread per visualizzare i thread. Usare .thread per impostare i thread correnti.
Nel sistema host immettere
g
nel debugger per riavviare l'esecuzione del codice nel sistema di destinazione.Nel sistema di destinazione eseguire il programma di test del driver EchoApp.exe.
Nel sistema host il punto di interruzione viene raggiunto e l'esecuzione del codice si interrompe.
Breakpoint 4 hit ECHO!EchoEvtIoRead: aade54c0 55 push ebp
Per visualizzare i thread in esecuzione, immettere !thread. Verranno visualizzate informazioni simili all'esempio seguente:
0: kd> !thread THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0008096c900 Image: echoapp.exe ...
Prendere nota del nome dell'immagine di echoapp.exe. Ciò indica che si sta esaminando il thread associato all'app di test.
Usare il
!process
comando per determinare se questo thread è l'unico thread in esecuzione nel processo associato a echoapp.exe. Il numero di thread del thread in esecuzione nel processo è lo stesso thread che esegue il!thread
comando visualizzato.0: kd> !process PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf5dc050 ElapsedTime 00:00:00.048 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (681, 50, 345) (2724KB, 200KB, 1380KB) PeakWorkingSetSize 651 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 686 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
Usare il
!process 0 0
comando per individuare l'indirizzo del processo di due processi correlati e registrare l'indirizzo del processo qui.Cmd.exe: ____________________________________________________________
EchoApp.exe: _______________________________________________________
0: kd> !process 0 0 … PROCESS ffffe0007bbde900 SessionId: 1 Cid: 0f34 Peb: 7ff72dfa7000 ParentCid: 0c64 DirBase: 19c5fa000 ObjectTable: ffffc001d8c2f300 HandleCount: 31. Image: cmd.exe … PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe …
In alternativa, è possibile usare
!process 0 17
per visualizzare informazioni dettagliate su ogni processo. L'output di questo comando può essere lungo. L'output può essere cercato usando CTRL+F.Usare il
!process
comando per elencare le informazioni sul processo per entrambi i processi che eseguono il computer. Specificare l'indirizzo del processo dall'output!process 0 0
, non l'indirizzo illustrato in questo esempio.Questo output di esempio è relativo all'ID del processo cmd.exe registrato in precedenza. Il nome dell'immagine per questo ID processo è cmd.exe.
0: kd> !process ffffe0007bbde900 PROCESS ffffe0007bbde900 SessionId: 1 Cid: 0f34 Peb: 7ff72dfa7000 ParentCid: 0c64 DirBase: 19c5fa000 ObjectTable: ffffc001d8c2f300 HandleCount: 31. Image: cmd.exe VadRoot ffffe0007bb8e7b0 Vads 25 Clone 0 Private 117. Modified 20. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001d8c48050 ElapsedTime 21:33:05.840 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 24656 QuotaPoolUsage[NonPagedPool] 3184 Working Set Sizes (now,min,max) (261, 50, 345) (1044KB, 200KB, 1380KB) PeakWorkingSetSize 616 VirtualSize 2097164 Mb PeakVirtualSize 2097165 Mb PageFaultCount 823 MemoryPriority FOREGROUND BasePriority 8 CommitCharge 381 THREAD ffffe0007cf34880 Cid 0f34.0f1c Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable ffffe0008096c900 ProcessObject Not impersonating ...
Questo output di esempio è relativo all'ID processo echoapp.exe registrato in precedenza.
0: kd> !process ffffe0008096c900 PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf5dc050 ElapsedTime 00:00:00.048 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (681, 50, 345) (2724KB, 200KB, 1380KB) PeakWorkingSetSize 651 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 686 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating ...
Registrare il primo indirizzo del thread associato ai due processi qui.
Cmd.exe: ____________________________________________________
EchoApp.exe: _________________________________________________
Usare il
!Thread
comando per visualizzare informazioni sul thread corrente.0: kd> !Thread THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0008096c900 Image: echoapp.exe Attached Process N/A Image: N/A ...
Come previsto, il thread corrente è il thread associato a echoapp.exe ed è in esecuzione.
Usare il
!Thread
comando per visualizzare informazioni sul thread associato a cmd.exe processo. Specificare l'indirizzo del thread registrato in precedenza.0: kd> !Thread ffffe0007cf34880 THREAD ffffe0007cf34880 Cid 0f34.0f1c Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable ffffe0008096c900 ProcessObject Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0007bbde900 Image: cmd.exe Attached Process N/A Image: N/A Wait Start TickCount 4134621 Ticks: 0 Context Switch Count 4056 IdealProcessor: 0 UserTime 00:00:00.000 KernelTime 00:00:01.421 Win32 Start Address 0x00007ff72e9d6e20 Stack Init ffffd0015551dc90 Current ffffd0015551d760 Base ffffd0015551e000 Limit ffffd00155518000 Call 0 Priority 14 BasePriority 8 UnusualBoost 3 ForegroundBoost 2 IoPriority 2 PagePriority 5 Child-SP RetAddr : Args to Child : Call Site ffffd001`5551d7a0 fffff801`eed184fe : fffff801`eef81180 ffffe000`7cf34880 00000000`fffffffe 00000000`fffffffe : nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109] ffffd001`5551d8e0 fffff801`eed17f79 : ffff03a5`ca56a3c8 000000de`b6a6e990 000000de`b6a6e990 00007ff7`d00df000 : nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347] ffffd001`5551d980 fffff801`eecea340 : ffffd001`5551da18 00000000`00000000 00000000`00000000 00000000`00000388 : nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619] ...
Questo thread è associato a cmd.exe ed è in uno stato di attesa.
Specificare l'indirizzo del thread in attesa CMD.exe thread per modificare il contesto in tale thread in attesa.
0: kd> .Thread ffffe0007cf34880 Implicit thread is now ffffe000`7cf34880
Usare il
k
comando per visualizzare lo stack di chiamate associato al thread in attesa.0: kd> k *** Stack trace for last set context - .thread/.cxr resets it # Child-SP RetAddr Call Site 00 ffffd001`5551d7a0 fffff801`eed184fe nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109] 01 ffffd001`5551d8e0 fffff801`eed17f79 nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347] 02 ffffd001`5551d980 fffff801`eecea340 nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619] 03 ffffd001`5551da00 fffff801`ef02e642 nt!KeWaitForSingleObject+0x2c0 [d:\9142\minkernel\ntos\ke\wait.c @ 683] ...
Gli elementi dello stack di chiamate,
KiCommitThreadWait
ad esempio indicano che questo thread non è in esecuzione come previsto.
Per altre informazioni su thread e processi, vedere i riferimenti seguenti:
IRQL, registra e termina la sessione winDbg
In questa sezione visualizzare il livello di richiesta di interrupt (IRQL) e il contenuto dei registri.
Visualizzare il runtime di integrazione salvato
Il runtime di integrazione viene usato per gestire la priorità di manutenzione degli interrupt. Ogni processore ha un'impostazione IRQL che i thread possono aumentare o ridurre. Gli interrupt che si verificano in corrispondenza o al di sotto dell'impostazione IRQL del processore vengono mascherati e non interferiscono con l'operazione corrente. Gli interrupt che si verificano sopra l'impostazione IRQL del processore hanno la precedenza sull'operazione corrente.
Nel sistema host, l'estensione !irql visualizza il runtime di integrazione nel processore corrente del computer di destinazione prima dell'interruzione del debugger. Quando il computer di destinazione si interrompe nel debugger, il runtime di integrazione viene modificato, ma l'IRQL effettivo immediatamente prima del salvataggio dell'interruzione del debugger viene visualizzato da !irql
.
0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)
Visualizzare i registri
Nel sistema host visualizzare il contenuto dei registri per il thread corrente nel processore corrente usando il comando r (Registri).
0: kd> r
rax=000000000000c301 rbx=ffffe00173eed880 rcx=0000000000000001
rdx=000000d800000000 rsi=ffffe00173eed8e0 rdi=ffffe00173eed8f0
rip=fffff803bb757020 rsp=ffffd001f01f8988 rbp=ffffe00173f0b620
r8=000000000000003e r9=ffffe00167a4a000 r10=000000000000001e
r11=ffffd001f01f88f8 r12=0000000000000000 r13=ffffd001f01efdc0
r14=0000000000000001 r15=0000000000000000
iopl=0 nv up ei pl nz na pe nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000202
nt!DbgBreakPointWithStatus:
fffff803`bb757020 cc int 3
In alternativa, è possibile visualizzare il contenuto dei registri selezionando Visualizza>registri. Per altre informazioni, vedere r (registri).
La visualizzazione del contenuto dei registri può essere utile durante l'esecuzione del codice del linguaggio assembly e in altri scenari. Per altre informazioni sul disassembly del linguaggio di assembly, vedere Disassembly x86 con annotazioni e disassembly x64 con annotazioni.
Per informazioni sul contenuto del registro, vedere Architettura x86 e architettura x64.
Terminare la sessione WinDbg
Se si vuole lasciare il debugger collegato, ma si vuole lavorare sulla destinazione, cancellare eventuali punti di interruzione usando bc *
, in modo che il computer di destinazione non tenti di connettersi al debugger del computer host. Usare quindi il g
comando per consentire l'esecuzione del computer di destinazione.
Per terminare la sessione di debug, nel sistema host, eseguire l'interruzione nel debugger e immettere il qd
comando (Esci e scollega) oppure selezionare Arresta debug dal menu.
0: kd> qd
Per altre informazioni, vedere Terminare una sessione di debug in WinDbg.
Risorse di debug di Windows
Altre informazioni sono disponibili nel debug di Windows. Alcuni di questi libri usano versioni precedenti di Windows come Windows Vista nei relativi esempi, ma i concetti illustrati sono applicabili alla maggior parte delle versioni di Windows.
Libri
- Debug avanzato di Windows di Mario Hewardt e Daniel Pravat
- Debug di Windows: guida pratica al debug e alla traccia di strategie in Windows® di Tarik Soulami
- Windows Internals di Paolo Yosifovich, Alex Ionovich, Mark Russinovich e David Solomon
Video
Fornitori di formazione