Condividi tramite


Driver di debug - Step by Step Lab (modalità kernel Sysvad)

Questo lab fornisce esercizi pratici che illustrano come eseguire il debug del driver di dispositivo in modalità kernel sysvad audio.

Microsoft Windows Debugger (WinDbg) è un potente strumento di debug basato su Windows che è possibile usare per eseguire il debug in modalità utente e in modalità kernel. WinDbg fornisce il debug a livello di origine per il kernel Windows, i driver in modalità kernel e i servizi di sistema, nonché applicazioni e driver in modalità utente.

WinDbg può eseguire il codice sorgente, impostare punti di interruzione, visualizzare le variabili (inclusi gli oggetti C++), le tracce dello stack e la memoria. La finestra Di comando debugger consente all'utente di eseguire un'ampia gamma di comandi.

Configurazione del lab

Per completare il lab, è necessario disporre dell'hardware seguente:

  • Un computer portatile o desktop (host) che esegue Windows 10
  • Un computer portatile o desktop (destinazione) che esegue Windows 10
  • Un hub di rete/router e cavi di rete per connettere i due PC
  • Accesso a Internet per scaricare i file di simboli

Per completare il lab, sarà necessario il software seguente.

  • Microsoft Visual Studio 2017
  • Windows Software Development Kit (SDK) per Windows 10
  • Windows Driver Kit (WDK) per Windows 10
  • Driver audio Sysvad di esempio per Windows 10

Per informazioni sul download e l'installazione di WDK, vedere Scaricare Windows Driver Kit (WDK).

Procedura dettagliata per il debug di Sysvad

Questo lab illustra il processo di debug di un driver in modalità kernel. Gli esercizi usano l'esempio di driver audio virtuale Syvad. Poiché il driver audio Syvad non interagisce con l'hardware audio effettivo, può essere usato nella maggior parte dei dispositivi. Il lab illustra le attività seguenti:

Laboratorio del driver Echo

Il driver Echo è un driver più semplice rispetto al driver audio Sysvad. Se non si ha esperienza con WinDbg, è consigliabile prima completare il debug dei driver universali - Step-by-Step Lab (modalità kernel Echo). Questo lab riutilizza le istruzioni di configurazione di tale lab, quindi, se il lab è stato completato, è possibile ignorare le sezioni 1 e 2 qui.

Sezione 1: Connessione a una sessione WinDbg in modalità kernel

Nella sezione 1 si configurerà il debug di rete nel sistema host e di destinazione.

I PC in questo lab devono essere configurati per usare una connessione di rete Ethernet per il debug del kernel.

Questo lab usa due computer. WinDbg viene eseguito nel sistema host e il driver Sysvad viene eseguito nel sistema di destinazione .

Usare un hub di rete/router e cavi di rete per connettere i due PC.

Diagramma che mostra due PC connessi tramite un hub di rete/router.

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, seguire questa procedura.

<- Nel sistema host

  1. Aprire un prompt dei comandi nel sistema host e digitare ipconfig /all per determinarne l'indirizzo IP.
C:\>ipconfig /all
Windows IP Configuration

 Host Name . . . . . . . . . . . . : TARGETPC
...

Ethernet adapter Ethernet:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b3
   Autoconfiguration IPv4 Address. . : 169.182.1.1
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . :
  1. Registrare l'indirizzo IP del sistema host: ______________________________________

  2. Registrare il nome host del sistema host: ______________________________________

-> Nel sistema di destinazione

  1. Aprire un prompt dei comandi nel sistema di destinazione e usare il comando ping per confermare la connettività di rete tra i due sistemi. Usare l'indirizzo IP effettivo del sistema host registrato anziché 169.182.1.1 visualizzato nell'output di esempio.
C:\> ping 169.182.1.1

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

Per usare l'utilità KDNET per abilitare il debug in modalità kernel nel sistema di destinazione, eseguire la procedura seguente.

  1. Nel sistema host individuare la directory WDK KDNET. Per impostazione predefinita, si trova qui.

    C:\Programmi (x86)\Windows Kits\10\Debuggers\x64

Questo lab presuppone che entrambi i PC eseguano una versione a 64 bit di Windowson sia la destinazione che l'host. In caso contrario, l'approccio migliore consiste nell'eseguire la stessa "bitness" degli strumenti nell'host in cui è in esecuzione la destinazione. Ad esempio, se la destinazione esegue Windows a 32 bit, eseguire una versione 32 del debugger nell'host. Per altre informazioni, vedere Scelta degli strumenti di debug a 32 bit o a 64 bit.

  1. Individuare questi due file e copiarli in una condivisione di rete o in un'unità personale, in modo che siano disponibili nel computer di destinazione.

    kdnet.exe

    VerifiedNICList.xml

  2. Nel computer di destinazione aprire una finestra del prompt dei comandi come Amministrazione istrator. Immettere questo comando per verificare che la scheda di interfaccia di rete nel PC di destinazione sia suportata.

C:\KDNET>kdnet

Network debugging is supported on the following NICs:
busparams=0.25.0, Intel(R) 82579LM Gigabit Network Connection, KDNET is running on this NIC.kdnet.exe
  1. Digitare questo comando per impostare l'indirizzo IP del sistema host. Usare l'indirizzo IP effettivo del sistema host registrato anziché 169.182.1.1 visualizzato nell'output di esempio. Selezionare un indirizzo di porta univoco per ogni coppia di destinazione/host utilizzata, ad esempio 50010.
C:\>kdnet 169.182.1.1 50010

Enabling network debugging on Intel(R) 82577LM Gigabit Network Connection.
Key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

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 PC di test. Riabilitare queste funzionalità di sicurezza al termine del test e gestire in modo appropriato il PC 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.

  1. Digitare questo comando per verificare che le impostazioni dbgsettings siano impostate correttamente.
C:\> bcdedit /dbgsettings
busparams               0.25.0
key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
debugtype               NET
hostip                  169.182.1.1
port                    50010
dhcp                    Yes
The operation completed successfully.

Copiare la chiave univoca generata automaticamente in un file di testo per evitare di dover digitarla nel PC host. Copiare il file di testo con la chiave su nel sistema host.

NotaFirewall e debugger

Se si riceve un messaggio popup dal firewall e si vuole usare il debugger, selezionare tutte e tre le caselle.

Screenshot di Sicurezza di Windows Avviso che indica che Windows Firewall ha bloccato alcune funzionalità di un'app.

<- Nel sistema host

  1. Nel computer host aprire una finestra del prompt dei comandi come Amministrazione istrator. Passare alla directory WinDbg.exe. Useremo la versione x64 di WinDbg.exe da Windows Driver Kit (WDK) installata come parte dell'installazione del kit di Windows.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 
  1. Avviare WinDbg con il debug dell'utente remoto usando il comando seguente. Il valore per la chiave e la porta corrispondono a quanto impostato in precedenza usando BCDEdit nella destinazione.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

->Nel sistema di destinazione

Riavviare il sistema di destinazione.

<-Nel sistema host

In un minuto o due, l'output di debug deve essere visualizzato nel sistema host.

Screenshot di Windows Debugger che mostra l'output della finestra di comando da una connessione kernel dinamica.

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. I comandi vengono digitati nel riquadro più piccolo (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.

Sezione 2: Comandi e tecniche di debug in modalità kernel

Nella sezione 2 si useranno i comandi di debug per visualizzare informazioni sul sistema di destinazione.

<- Nel sistema host

Abilitare Debugger Markup Language (DML) con .prefer_dml

Alcuni comandi di debug visualizzano testo usando debugger markup language che è possibile selezionare per raccogliere rapidamente altre informazioni.

  1. Usare CTRL+INTERR (blocco di scorrimento) in WinDBg per suddividere il codice in esecuzione nel sistema di destinazione. La risposta del sistema di destinazione potrebbe richiedere un po' di tempo.
  2. Digitare il comando seguente per abilitare DML nella finestra Di comando del debugger.
0: kd> .prefer_dml 1
DML versions of commands on by default

Usare .hh per ottenere assistenza

È possibile accedere alla Guida del comando di riferimento usando il comando .hh .

  1. Digitare 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 visualizzerà la Guida per il comando .prefer_dml .

Screenshot dell'applicazione della Guida del debugger che mostra la Guida per il comando .prefer-dml.

Visualizzare la versione di Windows nel sistema di destinazione

  1. Visualizzare informazioni dettagliate sulla versione nel sistema di destinazione digitando 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

Elencare i moduli caricati

  1. È possibile verificare di usare il processo in modalità kernel corretto visualizzando i moduli caricati digitando il comando lm (Elenca moduli caricati) nella finestra WinDbg.
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
...

Si noti che l'output omesso è indicato con "... " in questo lab.

Poiché è ancora necessario impostare il percorso del simbolo e i simboli caricati, nel debugger sono disponibili informazioni limitate.

Sezione 3: Scaricare e compilare il driver audio Sysvad

Nella sezione 3 si scaricherà e si compilerà il driver audio Sysvad.

In genere, si sta usando il proprio codice driver quando si usa WinDbg. Per acquisire familiarità con il debug dei driver audio, viene usato il driver di esempio audio virtuale Sysvad. Questo esempio viene usato per illustrare come è possibile eseguire un singolo passaggio attraverso il codice in modalità kernel nativo. Questa tecnica può essere molto utile per il debug di problemi complessi di codice in modalità kernel.

Per scaricare e compilare il driver audio di esempio Sysvad, seguire questa procedura.

  1. Scaricare ed estrarre l'esempio audio Sysvad da GitHub

    È possibile usare un browser per visualizzare l'esempio Sysvad e Readme.md file qui:

    https://github.com/Microsoft/Windows-driver-samples/tree/main/audio/sysvad

    Screenshot del repository GitHub che mostra la cartella generale e il pulsante Scarica ZIP.

    Questo lab illustra come scaricare gli esempi di driver universali in un unico file ZIP.

    a. Scaricare il file master.zip nel disco rigido locale.

    https://github.com/Microsoft/Windows-driver-samples/archive/master.zip

    b. Selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) Windows-driver-samples-master.zip e scegliere Estrai tutto. Specificare una nuova cartella o passare a una cartella esistente che archivierà i file estratti. Ad esempio, è possibile specificare C:\WDK_Samples\ come nuova cartella in cui vengono estratti i file.

    c. Dopo aver estratto i file, passare alla sottocartella seguente.

    C:\WDK_Samples\Sysvad

  2. Aprire la soluzione driver in Visual Studio

    In Visual Studio selezionare File>Apri>progetto/soluzione e passare alla cartella contenente i file estratti, ad esempio C:\WDK_Samples\Sysvad. Fare doppio clic sul file di soluzione Syvad .

    In Visual Studio individuare il Esplora soluzioni. Se non è già aperto, scegliere Esplora soluzioni dal menu Visualizza. In Esplora soluzioni è possibile visualizzare una soluzione con diversi progetti.

    Screenshot di Visual Studio con il file adapter.cpp caricato dal progetto Sysvad.

  3. Impostare la configurazione e la piattaforma dell'esempio

    In Esplora soluzioni selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) Soluzione 'sysvad' (7 di 7 progetti) e scegliere Configuration Manager. Assicurarsi che le impostazioni di configurazione e piattaforma siano le stesse per i quattro 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 e/o alla piattaforma per un progetto, è necessario apportare le stesse modifiche per i tre progetti rimanenti.

    Nota Questo lab presuppone che venga usato Windows a 64 bit. Se si usa Windows a 32 bit, compilare il driver per 32 bit.

  4. Controllare la firma del driver

    Individuare TabletAudioSample. Aprire la pagina delle proprietà del driver Sysvad e assicurarsi che la modalità di firma>del driver sia impostata su Test Sign (Firma driver).

  5. 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.

  6. Compilare l'esempio con Visual Studio

    In Visual Studio selezionare Compila soluzione di>compilazione.

    Le finestre di compilazione devono visualizzare un messaggio che indica che la compilazione per tutti e sei 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.

  1. Individuare i file del driver compilati

    In Esplora file passare alla cartella contenente i file estratti per l'esempio. Ad esempio, passare a C:\WDK_Samples\Sysvad, 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. Ad esempio, se le impostazioni predefinite sono state lasciate invariate, i file del driver compilati verranno salvati in una cartella denominata \x64\Debug per una build di debug a 64 bit.

    Passare alla cartella che contiene i file compilati per il driver TabletAudioSample:

    C:\WDK_Samples\Sysvad\TabletAudioSample\x64\Debug. La cartella conterrà il driver TabletAudioSample .SYS, il file pdp dei simboli e il file inf. Sarà anche necessario individuare i file dll DelayAPO, KWSApo e KeywordDetectorContosoAdapter e file di simboli.

    Per installare il driver, sono necessari i file seguenti.

    File name Descrizione
    TabletAudioSample.sys File del driver.
    TabletAudioSample.pdb File di simboli del driver.
    tabletaudiosample.inf File di informazioni (INF) che contiene le informazioni necessarie per installare il driver.
    KeywordDetectorContosoAdapter.dll Rilevatore di parole chiave di esempio.
    KeywordDetectorContosoAdapter.pdb File di simboli del rilevatore di parole chiave di esempio.
    DelayAPO.dll Apo ritardo di esempio.
    DelayAPO.pdb File di simboli APO ritardato.
    KWSApo.dll APO con parole chiave di esempio.
    KWSApo.pdb File di simboli spotter della parola chiave.
    TabletAudioSample.cer File di certificato TabletAudioSample.
  2. Individuare un'unità usb o configurare una condivisione di rete per copiare i file del driver compilati dall'host nel sistema di destinazione.

Nella sezione successiva si copierà il codice nel sistema di destinazione e si installerà e testerà il driver.

Sezione 4: Installare l'esempio di driver audio Sysvad nel sistema di destinazione

Nella sezione 4 si userà devcon per installare il driver audio Sysvad.

-> Nel sistema di destinazione

Il computer in cui si installa il driver viene chiamato computer di destinazione o computer di test. In genere, si tratta di un 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, è necessario preparare il computer di destinazione attivando la firma di test. Dopo che si è pronti per eseguire l'esempio di driver compilato nel sistema di destinazione.

Per installare il driver nel sistema di destinazione, seguire questa procedura.

  1. Abilitare i driver firmati di test

    Per abilitare la possibilità di eseguire driver firmati di test:

    1. Aprire Windows Impostazioni.

    2. In Aggiornamento e sicurezza selezionare Ripristino.

    3. In Avvio avanzato selezionare Riavvia ora.

    4. Al riavvio del PC, selezionare Risoluzione dei problemi.

    5. Selezionare Quindi Opzioni avanzate, Impostazioni di avvio e quindi selezionare Riavvia.

    6. Selezionare Disabilita l'imposizione della firma del driver premendo F7.

    7. Il PC inizierà con i nuovi valori sul posto.

  2. -> Nel sistema di destinazione

    Installare il driver

    Le istruzioni seguenti illustrano come installare e testare il driver di esempio.

    Il file INF necessario per l'installazione di questo driver è TabletAudioSample.inf. Nel computer di destinazione aprire una finestra del prompt dei comandi come Amministrazione istrator. Passare alla cartella del pacchetto driver, fare clic con il pulsante destro del mouse sul file TabletAudioSample.inf e quindi scegliere Installa.

    Verrà visualizzata una finestra di dialogo che indica che il driver di test è un driver non firmato. Selezionare Installa questo driver comunque per continuare.

    Screenshot di Sicurezza di Windows avviso che informa che Windows non è in grado di verificare l'autore.

    Suggerimento

     Se si verificano problemi con l'installazione, controllare il file seguente per altre informazioni. %windir%\inf\setupapi.dev.log

    Per istruzioni più dettagliate, vedere Configurazione di un computer per la distribuzione, il test e il debug dei driver.

    Il file INF contiene l'ID hardware per l'installazione del tabletaudiosample.sys. Per l'esempio Syvad, l'ID hardware è: root\sysvad_TabletAudioSample

  3. Esaminare il driver in Gestione dispositivi

    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 del dispositivo individuare Virtual Audio Device (WDM) - Tablet Sample nel nodo Dispositivo audio. Si trova in genere sotto il nodo Controller audio, video e gioco . Verificare che sia installato e attivo.

    Evidenziare il driver per l'hardware effettivo nel PC in Gestione dispositivi. Selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) sul driver e scegliere Disabilita per disabilitare il driver.

    Confermare in Gestione dispositivi che il driver hardware audio visualizza la freccia giù, a indicare che è disabilitato.

    Screenshot dell'albero Gestione dispositivi con l'esempio di tablet del dispositivo audio virtuale evidenziato.

    Dopo aver installato correttamente il driver di esempio, è ora possibile testarlo.

Testare il driver audio Sysvad

  1. 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 del dispositivo individuare Virtual Audio Device (WDM) - Tablet Sample (Esempio di tablet).

  2. Aprire Pannello di controllo e passare a Hardware e suono>Gestisci dispositivi audio. Nella finestra di dialogo Suono selezionare l'icona dell'altoparlante etichettata come Virtual Audio Device (WDM) - Tablet Sample e quindi selezionare Imposta impostazione predefinita, ma non selezionare OK. In questo modo verrà aperta la finestra di dialogo Suono.

  3. Individuare un file MP3 o un altro file audio nel computer di destinazione e fare doppio clic per riprodurlo. Quindi, nella finestra di dialogo Suono verificare che sia presente un'attività nell'indicatore del livello di volume associato al driver Virtual Audio Device (WDM) - Tablet Sample .

Sezione 5: Usare WinDbg per visualizzare informazioni sul driver

Nella sezione 5 si imposta il percorso del simbolo e si useranno i comandi del debugger del kernel per visualizzare informazioni sul driver di esempio Sysvad.

I simboli consentono a WinDbg di visualizzare informazioni aggiuntive, ad esempio nomi di variabili, che possono essere preziosi durante il debug. WinDbg usa i formati di simboli di debug di Microsoft Visual Studio per il debug a livello di origine. Può accedere a qualsiasi simbolo o variabile da un modulo con file di simboli PDB.

Per caricare il debugger, seguire questa procedura.

<-Nel sistema host

  1. Se il debugger è stato chiuso, aprirlo di nuovo usando il comando seguente nella finestra del prompt dei comandi dell'amministratore. Sostituire la chiave e la porta con quello configurato in precedenza.

    C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Usare CTRL+INTERR (blocco di scorrimento) per suddividere il codice in esecuzione nel sistema di destinazione.

Impostare il percorso del simbolo

  1. Per impostare il percorso dei simboli sul server dei simboli Microsoft nell'ambiente WinDbg, usare il comando con estensione symfix .

    0: kd> .symfix
    
  2. Per aggiungere la posizione del simbolo locale per usare i simboli locali, aggiungere il percorso usando .sympath+ e quindi ricaricare /f.

    0: kd> .sympath+ C:\WDK_Samples\Sysvad
    0: kd> .reload /f
    

    Nota Il comando .reload 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.

Nota È necessario caricare i simboli appropriati per usare funzionalità avanzate fornite da WinDbg. Se i simboli non sono configurati correttamente, si riceveranno messaggi che indicano che i simboli non sono disponibili quando si tenta di usare la funzionalità dipendente dai simboli.

0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.

Nota Serverdi simboli

Esistono diversi approcci che possono essere usati per lavorare con i simboli. In molte situazioni, è possibile configurare il PC per accedere ai simboli da un server di simboli fornito da Microsoft quando sono necessari. Questa procedura dettagliata presuppone che venga usato 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.

NotaInformazioni sui requisiti dei simboli del codice sorgente

Per eseguire il debug di origine, è necessario compilare una versione controllata (debug) dei file binari. Il compilatore creerà file di simboli (file con estensione pdb). Questi file di simboli mostreranno 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 delle variabili locali o delle righe di origine, impostare le opzioni di compilazione seguenti.

set COMPILE_DEBUG=1

set ENABLE_OPTIMIZER=0

  1. Digitare quanto segue nell'area dei comandi del debugger per visualizzare informazioni sul driver Sysvad.

    0: kd> lm m tabletaudiosample v
    Browse full module list
    start             end                 module name
    fffff801`14b40000 fffff801`14b86000   tabletaudiosample   (private pdb symbols)  C:\Debuggers\sym\TabletAudioSample.pdb\E992C4803EBE48C7B23DC1596495CE181\TabletAudioSample.pdb
        Loaded symbol image file: tabletaudiosample.sys
        Image path: \SystemRoot\system32\drivers\tabletaudiosample.sys
        Image name: tabletaudiosample.sys
        Browse all global symbols  functions  data
        Timestamp:        Thu Dec 10 12:20:26 2015 (5669DE8A)
        CheckSum:         0004891E
    ...  
    

    Per altre informazioni, vedere lm.

  2. 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.

  3. Poiché DML è abilitato, alcuni elementi dell'output sono collegamenti attivi che è possibile selezionare. Selezionare il collegamento dati nell'output di debug per visualizzare informazioni sui simboli degli elementi che iniziano con la lettera a.

    0: kd> x /D /f tabletaudiosample!a*
     A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    
    fffff806`9adb1000 tabletaudiosample!AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)
    

    Per informazioni, vedere x (Esaminare i simboli).For information, see x (Examine Symbols).

  4. L'estensione !lmi visualizza informazioni dettagliate su un modulo. Digitare !lmi tabletaudiosample. L'output dovrebbe essere simile al testo illustrato di seguito.

    0: kd> !lmi tabletaudiosample
    Loaded Module Info: [tabletaudiosample] 
             Module: tabletaudiosample
       Base Address: fffff8069ad90000
         Image Name: tabletaudiosample.sys
       Machine Type: 34404 (X64)
         Time Stamp: 58ebe848 Mon Apr 10 13:17:12 2017
               Size: 48000
           CheckSum: 42df7
    Characteristics: 22  
    Debug Data Dirs: Type  Size     VA  Pointer
                 CODEVIEW    a7,  e5f4,    d1f4 RSDS - GUID: {5395F0C5-AE50-4C56-AD31-DD5473BD318F}
                   Age: 1, Pdb: C:\Windows-driver-samples-master\audio\sysvad\TabletAudioSample\x64\Debug\TabletAudioSample.pdb
                       ??   250,  e69c,    d29c [Data not mapped]
         Image Type: MEMORY   - Image read successfully from loaded memory.
        Symbol Type: PDB      - Symbols loaded successfully from image header.
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
           Compiler: Resource - front end [0.0 bld 0] - back end [14.0 bld 24210]
        Load Report: private symbols & lines, not source indexed 
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
    
  5. Usare l'estensione !dh per visualizzare le informazioni sull'intestazione, come illustrato di seguito.

    0: kd> !dh tabletaudiosample 
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
        8664 machine (X64)
           9 number of sections
    5669DE8A time date stamp Thu Dec 10 12:20:26 2015
    
           0 file pointer to symbol table
           0 number of symbols
          F0 size of optional header
          22 characteristics
                Executable
                App can handle >2gb addresses
    ...
    

Sezione 6: Visualizzazione delle informazioni sull'albero dei dispositivi Plug and Play

Nella sezione 6 verranno visualizzate informazioni sul driver di dispositivo di esempio Sysvad 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

  1. Per visualizzare tutti i nodi del dispositivo nell'albero dei dispositivi Plug and Play, immettere il comando !devnode 0 1 . L'esecuzione di questo comando può richiedere un minuto o due. Durante questo periodo, "*Occupato" verrà visualizzato nell'area di stato di WinDbg.

    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…
    ...
    
  2. Usare CTRL+F per cercare nell'output generato per cercare il nome del driver di dispositivo, sysvad.

    Finestra di dialogo Trova con il termine

    Una voce del sysvad_TabletAudioSample nodo del dispositivo con un nome sarà presente nell'output !devnode per Syvad.

      DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
        InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
        ServiceName is "sysvad_tabletaudiosample"
        State = DeviceNodeStarted (0x308)
    ...
    

    Si noti che vengono visualizzati l'indirizzo PDO e l'indirizzo DevNode.

  3. Usare il !devnode 0 1 sysvad_TabletAudioSample comando per visualizzare le informazioni di Plug and Play associate al driver di dispositivo Sysvad.

    0: kd> !devnode 0 1 sysvad_TabletAudioSample
    Dumping IopRootDeviceNode (= 0xffffe00082df8d30)
    DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
      InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe000897fb650 for PDO 0xffffe00089927e30
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{64097438-cdc0-4007-a19e-62e789062e20}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00086d2f5f0 for PDO 0xffffe00089939ae0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{78880f4e-9571-44a4-a9df-960bde446487}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00089759bb0 for PDO 0xffffe000875aa060
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{7cad07f2-d0a0-4b9b-8100-8dc735e9c447}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00087735010 for PDO 0xffffe000872068c0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{fc38551b-e69f-4b86-9661-ae6da78bc3c6}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088457670 for PDO 0xffffe0008562b830
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{0894b831-c9fe-4c56-86a6-092380fc5628}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000893dbb70 for PDO 0xffffe00089d68060
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{15eb6b5c-aa54-47b8-959a-0cff2c1500db}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088e6f250 for PDO 0xffffe00089f6e990
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{778c07f0-af9f-43f2-8b8d-490024f87239}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000862eb4b0 for PDO 0xffffe000884443a0
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{e4b72c7c-be50-45df-94f5-0f2922b85983}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
    
  4. L'output visualizzato nel comando precedente include il PDO associato all'istanza in esecuzione del driver, in questo esempio è 0xffffe00089c575a0. Immettere il comando !devobj<PDO address> per visualizzare le informazioni di Plug and Play associate al driver di dispositivo Sysvad. Usa l'indirizzo PDO visualizzato da !devnode nel PC, non quello mostrato qui.

    0: kd> !devobj 0xffffe00089c575a0
    Device object (ffffe00089c575a0) is for:
    0000004e \Driver\PnpManager DriverObject ffffe00082d47e60
    Current Irp 00000000 RefCount 65 Type 0000001d Flags 00001040
    SecurityDescriptor ffffc102b0f6d171 DevExt 00000000 DevObjExt ffffe00089c576f0 DevNode ffffe00086e68190 
    ExtensionFlags (0000000000)  
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe00088386a50 \Driver\sysvad_tabletaudiosample
    Device queue is not busy.
    
  5. L'output visualizzato nel comando !devobj include il nome del dispositivo collegato: \Driver\sysvad_tabletaudiosample. Usare il comando !drvobj con una maschera di bit pari a 2 per visualizzare le informazioni associate al dispositivo collegato.

    0: kd> !drvobj \Driver\sysvad_tabletaudiosample 2
    Driver object (ffffe0008834f670) is for:
    \Driver\sysvad_tabletaudiosample
    DriverEntry:   fffff80114b45310  tabletaudiosample!FxDriverEntry
    DriverStartIo: 00000000 
    DriverUnload:  fffff80114b5fea0                tabletaudiosample!DriverUnload
    AddDevice:     fffff80114b5f000  tabletaudiosample!AddDevice
    
    Dispatch routines:
    [00] IRP_MJ_CREATE                      fffff80117b49a20             portcls!DispatchCreate
    [01] IRP_MJ_CREATE_NAMED_PIPE           fffff8015a949a00          nt!IopInvalidDeviceRequest
    [02] IRP_MJ_CLOSE                       fffff80115e26f90                ks!DispatchCleanup
    [03] IRP_MJ_READ                        fffff80115e32710                ks!DispatchRead
    [04] IRP_MJ_WRITE                       fffff80115e327e0              ks!DispatchWrite
    [05] IRP_MJ_QUERY_INFORMATION           fffff8015a949a00         nt!IopInvalidDeviceRequest
    [06] IRP_MJ_SET_INFORMATION             fffff8015a949a00              nt!IopInvalidDeviceRequest
    [07] IRP_MJ_QUERY_EA                    fffff8015a949a00         nt!IopInvalidDeviceRequest
    [08] IRP_MJ_SET_EA                      fffff8015a949a00              nt!IopInvalidDeviceRequest
    [09] IRP_MJ_FLUSH_BUFFERS               fffff80115e32640  ks!DispatchFlush
    [0a] IRP_MJ_QUERY_VOLUME_INFORMATION    fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0b] IRP_MJ_SET_VOLUME_INFORMATION      fffff8015a949a00               nt!IopInvalidDeviceRequest
    [0c] IRP_MJ_DIRECTORY_CONTROL           fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0d] IRP_MJ_FILE_SYSTEM_CONTROL         fffff8015a949a00         nt!IopInvalidDeviceRequest
    [0e] IRP_MJ_DEVICE_CONTROL              fffff80115e27480               ks!DispatchDeviceIoControl
    [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     fffff8015a949a00   nt!IopInvalidDeviceRequest
    [10] IRP_MJ_SHUTDOWN                    fffff8015a949a00      nt!IopInvalidDeviceRequest
    [11] IRP_MJ_LOCK_CONTROL                fffff8015a949a00  nt!IopInvalidDeviceRequest
    [12] IRP_MJ_CLEANUP                     fffff8015a949a00           nt!IopInvalidDeviceRequest
    [13] IRP_MJ_CREATE_MAILSLOT             fffff8015a949a00               nt!IopInvalidDeviceRequest
    [14] IRP_MJ_QUERY_SECURITY              fffff80115e326a0 ks!DispatchQuerySecurity
    [15] IRP_MJ_SET_SECURITY                fffff80115e32770      ks!DispatchSetSecurity
    [16] IRP_MJ_POWER                       fffff80117b3dce0            portcls!DispatchPower
    [17] IRP_MJ_SYSTEM_CONTROL              fffff80117b13d30              portcls!PcWmiSystemControl
    [18] IRP_MJ_DEVICE_CHANGE               fffff8015a949a00 nt!IopInvalidDeviceRequest
    [19] IRP_MJ_QUERY_QUOTA                 fffff8015a949a00  nt!IopInvalidDeviceRequest
    [1a] IRP_MJ_SET_QUOTA                   fffff8015a949a00       nt!IopInvalidDeviceRequest
    [1b] IRP_MJ_PNP                         fffff80114b5f7d0 tabletaudiosample!PnpHandler
    
  6. Immettere il comando !devstack PDO address (Indirizzo> PDO devstack<) per visualizzare le informazioni di Plug and Play associate al driver di dispositivo. L'output visualizzato nel comando !devnode 0 1 include l'indirizzo PDO associato all'istanza in esecuzione del driver. In questo esempio è 0xffffe00089c575a0. Usa l'indirizzo PDO visualizzato da !devnode nel PC, non quello mostrato di seguito.

    0: kd> !devstack 0xffffe00089c575a0
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe00088d212e0  \Driver\ksthunk    ffffe00088d21430  0000007b
      ffffe00088386a50  \Driver\sysvad_tabletaudiosampleffffe00088386ba0  0000007a
    > ffffe00089c575a0  \Driver\PnpManager 00000000  0000004e
    !DevNode ffffe00086e68190 :
      DeviceInst is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
    

L'output mostra che abbiamo uno stack di driver di dispositivo molto semplice. Il driver sysvad_TabletAudioSample è figlio del nodo PnPManager. PnPManager è un nodo radice.

Questo diagramma mostra un albero dei nodi del dispositivo più complesso.

Diagramma di un albero dei nodi del dispositivo costituito da circa 20 nodi.

Nota Per altre informazioni sugli stack di driver più complessi, vedere Stack di driver e nodi del dispositivo e stack di dispositivi.

Sezione 7: Utilizzo dei punti di interruzione

Nella sezione 7 verranno usati punti di interruzione per arrestare l'esecuzione del codice in punti specifici.

Impostazione di punti di interruzione tramite comandi

I punti di interruzione vengono usati per arrestare l'esecuzione del codice in una determinata riga di codice. È quindi possibile 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 b seguenti.

bp

Imposta un punto di interruzione che sarà 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 userà bu o bp in modo appropriato e consente l'uso di caratteri jolly * per impostare punti di interruzione su tutti i simboli che corrispondono (come tutti i metodi in una classe).

  1. Usare l'interfaccia utente di WinDbg per verificare che la modalità di origine di debug>sia abilitata nella sessione WinDbg corrente.

  2. Aggiungere il percorso del codice locale al percorso di origine digitando il comando seguente.

    .sympath+ C:\WDK_Samples\Sysvad
    
  3. Aggiungere la posizione del simbolo locale al percorso del simbolo digitando il comando seguente.

    .sympath+ C:\WDK_Samples\Sysvad
    
  4. Impostare la maschera di debug

    Mentre si lavora con un driver può essere utile visualizzare tutti i messaggi che potrebbero essere visualizzati. Digitare 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
    
  5. Impostare il punto di interruzione con il comando bm usando il nome del driver, seguito dal nome della funzione (AddDevice) in cui si vuole impostare il punto di interruzione, separato da un punto esclamativo.

    0: kd> bm tabletaudiosample!AddDevice
    breakpoint 1 redefined
      1: fffff801`14b5f000 @!"tabletaudiosample!AddDevice"
    

    È possibile usare una sintassi diversa insieme all'impostazione di variabili come <il modulo>.<simbolo>, <classe>::<method>,'<file.cpp>:<numero> di riga', o ignorare un numero di volte <condizione><#>. Per altre informazioni, vedere Using Breakpoints.

  6. Elencare i punti di interruzione correnti per verificare che il punto di interruzione sia stato impostato digitando il comando bl .

    0: kd> bl
    1 e fffff801`14b5f000     0001 (0001) tabletaudiosample!AddDevice
    
  7. Riavviare l'esecuzione del codice nel sistema di destinazione digitando il comando go g.

  8. ->Nel sistema di destinazione

    In Windows aprire Gestione dispositivi usando l'icona o immettendo mmc devmgmt.msc. In Gestione dispositivi espandere il nodo Controller audio, video e gioco. Selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) sulla voce del driver audio virtuale e scegliere Disabilita dal menu.

  9. Selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) sulla voce del driver audio virtuale e scegliere Abilita dal menu.

  10. <- Nel sistema host

    In questo modo Windows deve ricaricare il driver, che chiama AddDevice. In questo modo il punto di interruzione di debug AddDevice verrà attivato e l'esecuzione del codice driver nel sistema di destinazione dovrebbe interrompersi.

    Breakpoint 1 hit
    tabletaudiosample!AddDevice:
    fffff801`14baf000 4889542410      mov     qword ptr [rsp+10h],rdx
    

    Se il percorso di origine è impostato correttamente, è consigliabile arrestarsi nella routine AddDevice in adapter.cpp

    {
        PAGED_CODE();
    
        NTSTATUS        ntStatus;
        ULONG           maxObjects;
    
        DPF(D_TERSE, ("[AddDevice]"));
    
        maxObjects = g_MaxMiniports;
    
        #ifdef SYSVAD_BTH_BYPASS
        // 
        // Allow three (3) Bluetooth hands-free profile devices.
        //
        maxObjects += g_MaxBthHfpMiniports * 3; 
        #endif // SYSVAD_BTH_BYPASS
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
        return ntStatus;
    } // AddDevice
    
  11. Riga per riga nel codice digitando il comando p o premendo F10. È possibile eseguire un'istruzione in avanti dal codice sysvad AddDevice a PpvUtilCall, PnpCallAddDevice e quindi al codice PipCallDriverAddDevice di Windows. È possibile specificare un numero al comando p per inoltrare più righe, ad esempio p 5.

  12. Al termine dell'esecuzione del codice, usare il comando go g per riavviare l'esecuzione nel sistema di destinazione.

Impostazione dei punti di interruzione dell'accesso alla memoria

È anche possibile impostare punti di interruzione attivati quando si accede a una posizione di memoria. Usare il comando ba (break on access) 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)

Si noti che è possibile impostare solo quattro punti di interruzione dei dati in un determinato momento ed è necessario assicurarsi di allineare correttamente i dati o di non attivare il punto di interruzione (le parole devono terminare in indirizzi divisibili per 2, dwords deve essere divisibile per 4 e quadwords per 0 o 8)

Ad esempio, per impostare un punto di interruzione di lettura/scrittura in un indirizzo di memoria specifico, usare un comando simile al seguente.

ba r 4 fffff800`7bc9eff0

Modifica dello stato del punto di interruzione

È possibile modificare i punti di interruzione esistenti usando i comandi seguenti.

bl

Elenca i punti di interruzione.

Bc

Cancella un punto di interruzione dall'elenco. Usare 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 selezionando Modifica>punti di interruzione. Si noti che la finestra di dialogo punto di interruzione funziona solo con i punti di interruzione esistenti. È necessario impostare nuovi punti di interruzione dalla riga di comando.

Impostare un punto di interruzione in MixerVolume

Diverse parti del codice del driver audio vengono chiamate per rispondere a vari eventi, dopo il caricamento del driver di dispositivo. Nella sezione successiva viene impostato un punto di interruzione che verrà attivato quando l'utente regola il controllo del volume per il driver audio virtuale.

Per impostare un punto di interruzione in MixerVolume, seguire questa procedura.

  1. <- Nel sistema host

    Per individuare il metodo che modifica il volume, usare il comando x per elencare i simboli in CAdapterCommon, che contengono il volume stringa.

    kd> x tabletaudiosample!CAdapterCommon::*
    ...
    fffff800`7bce26a0 tabletaudiosample!CAdapterCommon::MixerVolumeWrite (unsigned long, unsigned long, long)
    …
    

    Usare CTRL+F per cercare verso l'alto nell'output il volume e individuare il metodo MixerVolumeWrite.

  2. Cancellare i punti di interruzione precedenti usando bc *.

  3. Impostare un punto di interruzione dei simboli nella routine CAdapterCommon::MixerVolumeWrite usando il comando seguente.

    kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite
      1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"
    
  4. Elencare i punti di interruzione per verificare che il punto di interruzione sia impostato correttamente.

    kd> bl
    1 e fffff801`177b26a0 [c:\WDK_Samples\audio\sysvad\common.cpp @ 1668]    0001 (0001) tabletaudiosample!CAdapterCommon::MixerVolumeWrite
    
  5. Riavviare l'esecuzione del codice nel sistema di destinazione digitando il comando go g.

  6. In Pannello di controllo selezionare Hardware e suono>. Selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) Sink Description Sample (Esempio di descrizione sink) e selezionare Proprietà. Selezionare la scheda Livelli . Regolare il volume del dispositivo di scorrimento.

  7. Ciò dovrebbe causare l'arresto del punto di interruzione di debug SetMixerVolume e l'esecuzione del codice driver nel sistema di destinazione.

    kd> g
    Breakpoint 1 hit
    tabletaudiosample!CAdapterCommon::MixerVolumeWrite:
    fffff801`177b26a0 44894c2420      mov     dword ptr [rsp+20h],r9d
    

    È consigliabile fermarsi a questa riga in common.cpp

    {
        if (m_pHW)
        {
            m_pHW->SetMixerVolume(Index, Channel, Value);
        }
    } // MixerVolumeWrite
    
  8. Usare il comando dv per visualizzare le variabili correnti e i relativi valori. Altre informazioni sulle variabili sono disponibili nella sezione successiva di questo lab.

    2: kd> dv
               this = 0x00000000`00000010
             ulNode = 0x344
          ulChannel = 0x210a45f8
            lVolume = 0n24
    
  9. Premere F10 per eseguire un singolo passaggio attraverso il codice.

  10. Premere F5 per completare l'esecuzione del codice MixerVolumeWrite.

Riepilogo- Esecuzione del codice istruzione/istruzione dalla finestra di comando del debugger

Di seguito sono riportati i comandi che è possibile usare per scorrere il codice (con i tagli brevi della tastiera associati visualizzati tra parentesi).

  • Interruzione (CTRL+INTERRUZIONE): questo comando interromperà un sistema purché il sistema sia in esecuzione e sia in comunicazione con WinDbg (la sequenza nel debugger del kernel è CTRL+C).

  • Passaggio (F10): questo comando causa l'esecuzione del codice per procedere con un'istruzione o 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 Modalità di debug>origine).

  • Passaggio 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 (posizione corrente nello stack di chiamate). Questo è utile se hai visto abbastanza della routine.

  • Esegui al cursore (F7 o CTRL+F10): posiziona il cursore in una finestra di origine o disassembly in cui vuoi interrompere l'esecuzione, quindi premi F7; l'esecuzione del codice verrà eseguita a quel punto. Si noti che se il flusso di esecuzione del codice non raggiunge il punto indicato dal cursore (ad esempio, un'istruzione IF non viene eseguita), WinDbg non si interrompe perché l'esecuzione del codice non ha raggiunto il punto indicato.

  • Esecuzione (F5): eseguire fino a quando non viene rilevato un punto di interruzione o si verifica un evento come un controllo di bug.

Opzioni avanzate

  • Impostare l'istruzione sulla riga corrente (CTRL+MAIUSC+I): in una finestra di origine è possibile posizionare il cursore su una riga, immettere questa scelta rapida da tastiera e l'esecuzione del codice inizierà da quel punto non appena la si lascia procedere (ad esempio usando F5 o F10). Questo è utile se si vuole riprovare a una sequenza, ma richiede una certa attenzione. Ad esempio, i registri e le variabili non sono impostati su ciò che sarebbero se l'esecuzione del codice avesse raggiunto naturalmente tale riga.

  • Impostazione diretta del registro eip: è possibile inserire un valore nel registro eip e non appena si preme F5 (o F10, F11 e così via), l'esecuzione inizia da tale indirizzo. Questa operazione è simile all'impostazione dell'istruzione sulla riga corrente designata dal cursore, ad eccezione del fatto che si specifica l'indirizzo di un'istruzione di assembly.

Può essere più semplice scorrere l'interfaccia utente anziché dalla riga di comando in modo che questo metodo sia consigliato. Se necessario, è possibile usare i comandi seguenti per eseguire un file di origine nella riga di comando:

  • .lines: abilitare le informazioni sulla riga di origine.

  • bp main: impostare il punto di interruzione iniziale all'inizio del modulo.

  • l+t- L'istruzione verrà eseguita dalla riga di origine.

  • Selezionare Debug>modalità origine per attivare la modalità di origine. Il L+t comando non è sufficiente.

  • l+s : le righe di origine verranno visualizzate al prompt.

  • g - Eseguire il programma fino a quando non viene immesso "main".

  • p : eseguire una riga di origine.

Per altre informazioni, vedere Debug del codice sorgente in WinDbg (versione classica) nella documentazione di riferimento sul debug.

Impostare punti di interruzione nel codice

È possibile impostare un punto di interruzione nel codice aggiungendo l'istruzione DebugBreak() e ricompilando il progetto e installando nuovamente il driver. Questo punto di interruzione verrà generato ogni volta che il driver è abilitato, quindi sarebbe una tecnica da usare nelle fasi di sviluppo iniziali, non nel codice di produzione. Questa tecnica non è flessibile quanto l'impostazione dinamica dei punti di interruzione tramite i comandi del punto di interruzione.

Suggerimento: è possibile conservare una copia del driver Sysvad con il punto di interruzione aggiunto per ulteriori operazioni del lab.

  1. Impostare un'interruzione in modo che si verifichi ogni volta che viene eseguito il metodo AddDevice aggiungendo l'istruzione DebugBreak() al codice di esempio.

    ...
        // Insert the DebugBreak() statment before the  PcAddAdapterDevice is called.
        //
    
        DebugBreak()
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
    
        return ntStatus;
    } // AddDevice
    
  2. Seguire tutti i passaggi descritti in precedenza per ricompilare il driver in Microsoft Visual Studio e reinstallarlo nel computer di destinazione. Assicurarsi di disinstallare il driver esistente prima di installare il driver aggiornato.

  3. Cancellare eventuali punti di interruzione precedenti e assicurarsi che il debugger sia collegato al PC di destinazione.

  4. Quando il codice viene eseguito e raggiunge l'istruzione, l'esecuzione DebugBreak verrà arrestata e verrà visualizzato un messaggio.

    KERNELBASE!DebugBreak:
    77b3b770 defe     __debugbreak
    

Sezione 8: Visualizzare le variabili

Nella sezione 8 si useranno i comandi del debugger per visualizzare le variabili.

Può essere utile esaminare le variabili durante l'esecuzione del codice per verificare che il codice funzioni come previsto. Questo lab esamina le variabili man mano che il driver audio produce audio.

  1. Usare il comando dv per esaminare le variabili locali associate al tabletaudiosample. CMiniportWaveRT::New*.

    kd> dv tabletaudiosample!CMiniportWaveRT::New*
    
  2. Cancellare i punti di interruzione precedenti

    bc *
    
  3. Impostare un punto di interruzione dei simboli nelle routine CMiniportWaveCyclicStreamMSVAD usando il comando seguente.

    0: kd> bm tabletaudiosample!CMiniportWaveRT::NewStream
      1: fffff801`177dffc0 @!"tabletaudiosample!CMiniportWaveRT::NewStream"
    
  4. Riavviare l'esecuzione del codice nel sistema di destinazione digitando il comando go g.

  5. -> Nel sistema di destinazione

    Individuare un file multimediale di piccole dimensioni, ad esempio un file audio di notifica di Windows con un'estensione di file .wav, e selezionare il file da riprodurre. Ad esempio, è possibile usare Ring05.wav che si trova nella directory Windows\Media.

  6. <- Nel sistema host

    Quando viene riprodotto il file multimediale, il punto di interruzione dovrebbe essere attivato e l'esecuzione del codice del driver nel sistema di destinazione deve interrompersi.

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::NewStream:
    fffff801`177dffc0 44894c2420      mov     dword ptr [rsp+20h],r9d
    

    La finestra del codice sorgente deve evidenziare la parentesi graffa sull'ingresso della funzione NewStream.

    /*++
    
    Routine Description:
    
      The NewStream function creates a new instance of a logical stream 
      associated with a specified physical channel. Callers of NewStream should 
      run at IRQL PASSIVE_LEVEL.
    
    Arguments:
    
      OutStream -
    
      OuterUnknown -
    
      Pin - 
    
      Capture - 
    
      DataFormat -
    
    Return Value:
    
      NT status code.
    
    --*/
    {
    
    ...
    
  7. Variabili locali

    È possibile visualizzare i nomi e i valori di tutte le variabili locali per un determinato frame digitando il comando dv .

    0: kd> dv
                    this = 0xffffe000`4436f8e0
               OutStream = 0xffffe000`49d2f130
            OuterUnknown = 0xffffe000`4436fa30
                     Pin = 0
                 Capture = 0x01 '
              DataFormat = 0xffffe000`44227790
    signalProcessingMode = {487E9220-E000-FFFF-30F1-D24900E0FFFF}
                ntStatus = 0n1055
                  stream = 0x00000000`00000200
    
  8. Usare DML per visualizzare le variabili

    Per usare DML per esplorare le variabili, selezionare gli elementi sottolineati. L'azione select crea un comando dx (Display NatVis Expression) che consente di eseguire il drill-down sulle strutture di dati annidate.

    0: kd> dx -r1 (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380))
    (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) :  [Type: CMiniportWaveRT]
        [+0x020] m_lRefCount      : 0
        [+0x028] m_pUnknownOuter  : 0xffffe001d1477e50 : [Type: IUnknown *]
        [+0x030] m_ulLoopbackAllocated : 0x2050
        [+0x034] m_ulSystemAllocated : 0x180
        [+0x038] m_ulOffloadAllocated : 0x0
        [+0x03c] m_dwCaptureAllocatedModes : 0x0
    
    0: kd> dx -r1 (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : {487E9220-E000-FFFF-30F1-D24900E0FFFF} [Type: _GUID]
        [<Raw View>]    
    
    0: kd> dx -r1 -n (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) :  [Type: _GUID]
        [+0x000] Data1            : 0x487e9220
        [+0x004] Data2            : 0xe000
        [+0x006] Data3            : 0xffff
        [+0x008] Data4            :  [Type: unsigned char [8]]
    
    0: kd> dx -r1 -n (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350))
    (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) :  [Type: unsigned char [8]]
        [0]              : 0x30
        [1]              : 0xf1
        [2]              : 0xd2
        [3]              : 0x49
        [4]              : 0x0
        [5]              : 0xe0
        [6]              : 0xff
        [7]              : 0xff
    
  9. Variabili globali

    È possibile trovare la posizione di memoria di una variabile globale digitando ? <nome> della variabile.

    0: kd> ? signalProcessingMode
    Evaluate expression: -52768896396472 = ffffd001`c8acd348
    
  10. Viene restituita la posizione di memoria della variabile, in questo caso ffffd001'c8acd348. È possibile visualizzare il contenuto della posizione di memoria eseguendo il dump del valore di tale posizione digitando il comando dd usando il percorso di memoria restituito dal comando precedente.

    0: kd> dd ffffd001`c8acd348
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 ffffe000
    
  11. È anche possibile usare nomi di variabile con il comando dd .

    0: kd> dd signalProcessingMode
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 ffffe000
    
  12. Visualizzare le variabili

    Usare la voce di menu Visualizza>variabili locali per visualizzare le variabili locali. Questa interfaccia offre anche questa possibilità di eseguire il drill-down su strutture di dati più complesse.

    Interfaccia WinDbg che visualizza le variabili locali del codice di esempio e le finestre dei comandi.

  13. Usare p o F10 per avanzare circa 10 righe nel codice fino a quando non si evidenzia ntStatus = IsFormatSupported(Pin, Capture, DataFormat); riga di codice.

        PAGED_CODE();
    
        ASSERT(OutStream);
        ASSERT(DataFormat);
    
        DPF_ENTER(("[CMiniportWaveRT::NewStream]"));
    
        NTSTATUS                    ntStatus = STATUS_SUCCESS;
        PCMiniportWaveRTStream      stream = NULL;
        GUID                        signalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
    
        *OutStream = NULL;
    
         //
        // If the data format attributes were specified, extract them.
        //
        if ( DataFormat->Flags & KSDATAFORMAT_ATTRIBUTES )
        {
            // The attributes are aligned (QWORD alignment) after the data format
            PKSMULTIPLE_ITEM attributes = (PKSMULTIPLE_ITEM) (((PBYTE)DataFormat) + ((DataFormat->FormatSize + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
            ntStatus = GetAttributesFromAttributeList(attributes, attributes->Size, &signalProcessingMode);
        }
    
        // Check if we have enough streams.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = ValidateStreamCreate(Pin, Capture, signalProcessingMode);
        }
    
        // Determine if the format is valid.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = IsFormatSupported(Pin, Capture, DataFormat);
        }
    
    ...
    
  14. Usare il comando dv per visualizzare i nomi e i valori di tutte le variabili locali per un determinato frame. Si noti che, come previsto, i valori sono diversi dall'ultima volta che è stato eseguito questo comando, poiché è stato eseguito codice aggiuntivo che modifica le variabili locali e alcune variabili non sono ora nel frame corrente o i relativi valori sono stati modificati.

    2: kd> dv
                    this = 0xffffe001`d1182000
               OutStream = 0xffffe001`d4776d20
            OuterUnknown = 0xffffe001`d4776bc8
                     Pin = 0
                 Capture = 0x00 '
              DataFormat = 0xffffe001`cd7609b0
    signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
                ntStatus = 0n0
                  stream = 0x00000000`00000000
    

Sezione 9: Visualizzare gli stack di chiamate

Nella sezione 9 verranno visualizzati gli stack di chiamate per esaminare il codice chiamante/chiamato.

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 comandi k*:

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.

Se si vuole mantenere disponibile lo stack di chiamate, è possibile selezionare Visualizza>stack di chiamate per visualizzarlo. Selezionare le colonne nella parte superiore della finestra per attivare o disattivare la visualizzazione di informazioni aggiuntive.

Interfaccia WinDbg che visualizza la finestra dello stack di chiamate.

Questo output mostra lo stack di chiamate durante il debug del codice dell'adattatore di esempio in uno stato di interruzione.

0: kd> kb
# RetAddr           : Args to Child                                                           : Call Site
00 fffff800`7a0fa607 : ffffe001`d1182000 ffffe001`d4776d20 ffffe001`d4776bc8 ffffe001`00000000 : tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
01 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d122bb10 ffffe001`ceb81750 ffffe001`d173f058 : portcls!CPortPinWaveRT::Init+0x2e7
02 fffff800`7a0fc7f9 : ffffe001`d4776bc0 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
04 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
05 fffff800`7bd314b1 : ffffe001`d122bb10 ffffd001`c3098590 ffffe001`d122bd90 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
06 fffff803`cda1bfa8 : 00000000`00000024 00000000`00000000 00000000`00000000 ffffe001`d122bb10 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 fffff803`cda7b306 : 00000000`000001f0 ffffe001`d48ce690 ffffe001`d13d6400 ffffe001`d13d64c0 : nt!IopParseDevice+0x7c8
08 fffff803`cda12916 : 00000000`000001f0 ffffd001`c30988d0 ffffe001`d13d6490 fffff803`cda7b250 : nt!IopParseFile+0xb6
09 fffff803`cda1131c : ffffe001`d2ccb001 ffffd001`c30989e0 00ffffe0`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
0a fffff803`cd9fedb8 : ffffe001`00000001 ffffe001`d48ce690 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
0b fffff803`cd9fe919 : 000000ee`6d1fc8d8 000000ee`6d1fc788 000000ee`6d1fc7e0 000000ee`6d1fc7d0 : nt!IopCreateFile+0x3d8
0c fffff803`cd752fa3 : ffffc000`1f296870 fffff803`cd9d9fbd ffffd001`c3098be8 00000000`00000000 : nt!NtCreateFile+0x79
0d 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
0e 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
0f 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
10 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
11 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

È possibile usare DML per esplorare ulteriormente il codice. Quando si seleziona la prima voce 00, il comando .frame (Set Local Context) viene usato per impostare il contesto e quindi il comando dv (Display Local Variables) visualizza le variabili locali.

0: kd> .frame 0n0;dv /t /v
00 ffffd001`c30981d0 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
ffffd001`c30982b0 class CMiniportWaveRT * this = 0xffffe001`d1182000
ffffd001`c30982b8 struct IMiniportWaveRTStream ** OutStream = 0xffffe001`d4776d20
ffffd001`c30982c0 struct IPortWaveRTStream * OuterUnknown = 0xffffe001`d4776bc8
ffffd001`c30982c8 unsigned long Pin = 0
ffffd001`c30982d0 unsigned char Capture = 0x00 '
ffffd001`c30982d8 union KSDATAFORMAT * DataFormat = 0xffffe001`cd7609b0
ffffd001`c3098270 struct _GUID signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
ffffd001`c3098210 long ntStatus = 0n0
ffffd001`c3098218 class CMiniportWaveRTStream * stream = 0x00000000`00000000

Sezione 10: Visualizzare processi e thread

Nella sezione 10 si useranno i comandi del debugger per visualizzare processi e thread.

Processo

Per modificare il contesto del processo corrente, usare il comando .process process<>. Nell'esempio seguente viene illustrato come identificare un processo e passare al contesto.

  • Usare il !process comando per visualizzare il processo corrente coinvolto nella riproduzione del suono.

    Per altre informazioni, vedere !process

L'output mostra che il processo è associato a audiodg.exe. Se si è ancora nel punto di interruzione descritto nella sezione precedente di questo argomento, il processo corrente deve essere associato all'immagine audiodg.exe.

<- Nel sistema host

0: kd> !process
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 70 Clone 0 Private 504. Modified 16. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       <Invalid>
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.000
    QuotaPoolUsage[PagedPool]         81632
    QuotaPoolUsage[NonPagedPool]      9704
    Working Set Sizes (now,min,max)  (2154, 1814, 2109) (8616KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2101
    VirtualSize                       2097192 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2336
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1573

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject

        THREAD ffffe001ceb77080  Cid 10f0.16dc  Teb: 000000ee6cf8d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d112c840  Cid 10f0.0a4c  Teb: 000000ee6cf8f000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d16c7840  Cid 10f0.13c4  Teb: 000000ee6cf91000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001cec67840  Cid 10f0.0dbc  Teb: 000000ee6cf93000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001d1117840  Cid 10f0.1d6c  Teb: 000000ee6cf95000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001cdeae840  Cid 10f0.0298  Teb: 000000ee6cf97000 Win32Thread: 0000000000000000 RUNNING on processor 2

Si noti che uno dei thread associati a questo processo si trova nello stato RUNNING. Questo thread supportava la riproduzione del clip multimediale quando è stato raggiunto il punto di interruzione.

Usare il comando !process 0 0 per visualizzare le informazioni di riepilogo per tutti i processi. Nell'output del comando usare CTRL+F per individuare l'ID processo per il processo associato all'immagine audiodg.exe. Nell'esempio riportato di seguito l'ID processo è ffffe001d147c840.

Registrare l'ID del processo associato a audiodg.exe sul PC per usarlo più avanti in questo lab. ________________________

...

PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
...

Immettere g nel debugger per eseguire il codice in avanti fino a quando non viene eseguita la riproduzione del clip multimediale. Quindi eseguire l'interruzione nel debugger premendo CTRL+ScrLk (CTRL+INTERR) Usare il comando !process per confermare che si sta eseguendo un processo diverso.

!process
PROCESS ffffe001cd0ad040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa000  ObjectTable: ffffc00017214000  HandleCount: <Data Not Accessible>
    Image: System
    VadRoot ffffe001d402b820 Vads 438 Clone 0 Private 13417. Modified 87866. Locked 64.
    DeviceMap ffffc0001721a070
    Token                             ffffc00017216a60
    ElapsedTime                       05:04:54.716
    UserTime                          00:00:00.000
    KernelTime                        00:00:20.531
    QuotaPoolUsage[PagedPool]         0
    QuotaPoolUsage[NonPagedPool]      0
    Working Set Sizes (now,min,max)  (1720, 50, 450) (6880KB, 200KB, 1800KB)
    PeakWorkingSetSize                15853
    VirtualSize                       58 Mb
    PeakVirtualSize                   74 Mb
    PageFaultCount                    46128
   MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      66

        THREAD ffffe001cd0295c0  Cid 0004.000c  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0120  SynchronizationEvent

        THREAD ffffe001cd02a6c0  Cid 0004.0010  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0ba0  Semaphore Limit 0x7fffffff
...

L'output precedente mostra che è in esecuzione un processo di sistema diverso di ffffe001cd0ad040 . Il nome dell'immagine mostra System, non audiodg.exe.

Usare ora il comando !process per passare al processo associato a audiodg.exe. Nell'esempio l'ID processo è ffffe001d147c840. Sostituire l'ID processo nell'esempio con l'ID processo registrato in precedenza.

0: kd> !process  ffffe001d147c840
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 60 Clone 0 Private 299. Modified 152. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       1 Day 01:53:14.490
    UserTime                          00:00:00.031
    KernelTime                        00:00:00.031
    QuotaPoolUsage[PagedPool]         81552
    QuotaPoolUsage[NonPagedPool]      8344
    Working Set Sizes (now,min,max)  (1915, 1814, 2109) (7660KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2116
    VirtualSize                       2097189 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2464
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1418

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      36             IdealProcessor: 0             
        UserTime                  00:00:00.015
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007ff7fb928de0
        Stack Init ffffd001c2ec6dd0 Current ffffd001c2ec60c0
        Base ffffd001c2ec7000 Limit ffffd001c2ec1000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d115c080  Cid 10f0.15b4  Teb: 000000ee6cf9b000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d0bf0640  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      1              IdealProcessor: 0             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c3143dd0 Current ffffd001c3143520
        Base ffffd001c3144000 Limit ffffd001c313e000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      518918         Ticks: 17616 (0:00:04:35.250)
        Context Switch Count      9              IdealProcessor: 1             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
        Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
        Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

Poiché questo codice non è attivo, tutti i thread sono in stato WAIT, come previsto.

Thread

I comandi per visualizzare e impostare i thread sono molto simili a quelli dei processi. Usare il comando !thread per visualizzare i thread. Usare .thread per impostare i thread correnti.

Per esplorare i thread associati al lettore multimediale, riprodurre nuovamente il clip multimediale. Se il punto di interruzione descritto nella sezione precedente è ancora attivo, si arresterà nel contesto di audiodg.exe.

Usare il thread !1 0 per visualizzare brevi informazioni per il thread corrente. Vengono visualizzati l'indirizzo del thread, gli ID del thread e del processo, l'indirizzo del blocco di ambiente thread (TEB), l'indirizzo della funzione Win32 (se presente) che il thread è stato creato per l'esecuzione e lo stato di pianificazione del thread.

0: kd> !thread -1 0
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0

Per visualizzare altre informazioni sul thread in esecuzione, digitare !thread. Verranno visualizzate informazioni simili alle seguenti.

0: kd> !thread
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
IRP List:
    ffffe001d429e580: (0006,02c8) Flags: 000008b4  Mdl: 00000000
Not impersonating
DeviceMap                 ffffc00019113080
Owning Process            ffffe001d147c840       Image:         audiodg.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      537630         Ticks: 0
Context Switch Count      63             IdealProcessor: 1             
UserTime                  00:00:00.000
KernelTime                00:00:00.015
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           : Args to Child                                                           : Call Site
ffffd001`c70c62a8 fffff800`7a0fa607 : ffffe001`d4aec5c0 ffffe001`cdefd3d8 ffffe001`d4aec5c0 ffffe001`cdefd390 : tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
ffffd001`c70c62b0 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d429e580 ffffe001`d4ea47b0 ffffe001`cdefd3d8 : portcls!CPortPinWaveRT::Init+0x2e7
ffffd001`c70c6340 fffff800`7a0fc7f9 : ffffe001`d4aec430 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
ffffd001`c70c63c0 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
ffffd001`c70c6450 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
ffffd001`c70c6510 fffff800`7bd314b1 : ffffe001`d429e580 ffffd001`c70c6590 ffffe001`d429e800 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
ffffd001`c70c6540 fffff803`cda1bfa8 : 00000000`00000025 00000000`00000000 00000000`00000000 ffffe001`d429e580 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
ffffd001`c70c65a0 fffff803`cda7b306 : 00000000`000002fc ffffe001`d5e0d510 00000000`00000000 ffffe001`d3341bd0 : nt!IopParseDevice+0x7c8
ffffd001`c70c6770 fffff803`cda12916 : 00000000`000002fc ffffd001`c70c68d0 ffffe001`d3341ba0 fffff803`cda7b250 : nt!IopParseFile+0xb6
ffffd001`c70c67d0 fffff803`cda1131c : ffffe001`ceb6c601 ffffd001`c70c69e0 00000000`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
ffffd001`c70c6970 fffff803`cd9fedb8 : ffff8ab8`00000001 ffffe001`d5e0d510 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
ffffd001`c70c6a90 fffff803`cd9fe919 : 000000ee`6d37c6e8 00000004`6d37c500 000000ee`6d37c5f0 000000ee`6d37c5e0 : nt!IopCreateFile+0x3d8
ffffd001`c70c6b40 fffff803`cd752fa3 : fffff6fb`7da05360 fffff6fb`40a6c0a8 fffff681`4d815760 ffff8ab8`92895e23 : nt!NtCreateFile+0x79
ffffd001`c70c6bd0 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`c70c6c40)
000000ee`6d37c568 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
000000ee`6d37c570 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
000000ee`6d37c578 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
000000ee`6d37c580 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

Usare il comando k per visualizzare lo stack di chiamate associato al thread.

0: kd> k
# Child-SP          RetAddr           Call Site
00 ffffd001`c70c62a8 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
01 ffffd001`c70c62b0 fffff800`7a0fb2c3 portcls!CPortPinWaveRT::Init+0x2e7
02 ffffd001`c70c6340 fffff800`7a0fc7f9 portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 ffffd001`c70c63c0 fffff800`7a180552 portcls!xDispatchCreate+0xd9
04 ffffd001`c70c6450 fffff800`7a109a9a ks!KsDispatchIrp+0x272
05 ffffd001`c70c6510 fffff800`7bd314b1 portcls!DispatchCreate+0x7a
06 ffffd001`c70c6540 fffff803`cda1bfa8 ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 ffffd001`c70c65a0 fffff803`cda7b306 nt!IopParseDevice+0x7c8
08 ffffd001`c70c6770 fffff803`cda12916 nt!IopParseFile+0xb6
09 ffffd001`c70c67d0 fffff803`cda1131c nt!ObpLookupObjectName+0x776
0a ffffd001`c70c6970 fffff803`cd9fedb8 nt!ObOpenObjectByNameEx+0x1ec
0b ffffd001`c70c6a90 fffff803`cd9fe919 nt!IopCreateFile+0x3d8
0c ffffd001`c70c6b40 fffff803`cd752fa3 nt!NtCreateFile+0x79
0d ffffd001`c70c6bd0 00007fff`69805b74 nt!KiSystemServiceCopyEnd+0x13
0e 000000ee`6d37c568 00007fff`487484e6 0x00007fff`69805b74
0f 000000ee`6d37c570 0000029b`00000003 0x00007fff`487484e6
10 000000ee`6d37c578 00000000`0000012e 0x0000029b`00000003
11 000000ee`6d37c580 00000000`00000000 0x12e

Immettere g nel debugger per eseguire il codice in avanti fino a quando non viene eseguita la riproduzione del clip multimediale. Quindi eseguire l'interruzione nel debugger premendo CTRL - ScrLk (CTRL+INTERR) Usare il comando !thread per confermare che si sta eseguendo un thread diverso.

0: kd> !thread
THREAD ffffe001ce80b840  Cid 17e4.01ec  Teb: 00000071fa9b9000 Win32Thread: ffffe001d41690d0 RUNNING on processor 0
Not impersonating
DeviceMap                 ffffc0001974e2c0
Owning Process            ffffe001d1760840       Image:         rundll32.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      538040         Ticks: 0
Context Switch Count      3181840        IdealProcessor: 0             
UserTime                  00:00:08.250
KernelTime                00:00:10.796
Win32 Start Address 0x00007ff6d2f24270
Stack Init ffffd001cd16afd0 Current ffffd001cd16a730
Base ffffd001cd16b000 Limit ffffd001cd165000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5

Child-SP          RetAddr           : Args to Child                                                           : Call Site
fffff803`cf373d18 fffff800`7a202852 : fffff803`cf373e60 00000000`00000001 ffffe001`cf4ed330 00000000`0000ffff : nt!DbgBreakPointWithStatus
fffff803`cf373d20 fffff803`cd6742c6 : ffffe001`cf4ed2f0 fffff803`cf373e60 00000000`00000001 00000000`0004e4b8 : kdnic!TXSendCompleteDpc+0x142
fffff803`cf373d60 fffff803`cd74d495 : 00000000`00000000 fffff803`cd923180 fffff803`cde1f4b0 fffff901`40669010 : nt!KiRetireDpcList+0x5f6
fffff803`cf373fb0 fffff803`cd74d2a0 : 00000000`00000090 0000000e`0000006a 00000000`00000092 00000000`00000000 : nt!KxRetireDpcList+0x5 (TrapFrame @ fffff803`cf373e70)
ffffd001`cd16a6c0 fffff803`cd74bd75 : 00000000`00000000 fffff803`cd74a031 00000000`00000000 00000000`00000000 : nt!KiDispatchInterruptContinue
ffffd001`cd16a6f0 fffff803`cd74a031 : 00000000`00000000 00000000`00000000 ffffe001`cff4d2a0 fffff803`cd67738e : nt!KiDpcInterruptBypass+0x25
ffffd001`cd16a700 fffff960`50cdb5a4 : fffff901`400006d0 00000000`00000001 fffff901`40000d60 ffffd001`cd16a9f0 : nt!KiInterruptDispatchNoLockNoEtw+0xb1 (TrapFrame @ ffffd001`cd16a700)
ffffd001`cd16a890 fffff960`50c66b2f : 00000000`00000000 fffff901`40669010 fffff901`42358580 fffff901`40000d60 : win32kfull!Win32FreePoolImpl+0x34
ffffd001`cd16a8c0 fffff960`50c68cd6 : 00000000`00000000 ffffd001`cd16a9f0 fffff901`400006d0 fffff901`400c0460 : win32kfull!EXLATEOBJ::vAltUnlock+0x1f
ffffd001`cd16a8f0 fffff803`cd752fa3 : 00000000`00000000 00000000`00000000 ffffe001`ce80b840 00000000`00000000 : win32kfull!NtGdiAlphaBlend+0x1d16
ffffd001`cd16add0 00007fff`674c1494 : 00007fff`674b1e97 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`cd16ae40)
00000071`fa74c9a8 00007fff`674b1e97 : 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 00000000`00ffffff : 0x00007fff`674c1494
00000071`fa74c9b0 0000a7c6`daee0559 : 00000000`00000001 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 : 0x00007fff`674b1e97
00000071`fa74c9b8 00000000`00000001 : 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 00000000`01010bff : 0x0000a7c6`daee0559
00000071`fa74c9c0 0000020b`741f3c50 : 00000000`00ffffff 00000000`00000030 00000000`01010bff 00000000`00000000 : 0x1
00000071`fa74c9c8 00000000`00ffffff : 00000000`00000030 00000000`01010bff 00000000`00000000 00000000`000000c0 : 0x0000020b`741f3c50
00000071`fa74c9d0 00000000`00000030 : 00000000`01010bff 00000000`00000000 00000000`000000c0 00000000`00000030 : 0xffffff
00000071`fa74c9d8 00000000`01010bff : 00000000`00000000 00000000`000000c0 00000000`00000030 00000071`00000030 : 0x30
00000071`fa74c9e0 00000000`00000000 : 00000000`000000c0 00000000`00000030 00000071`00000030 00000071`01ff8000 : 0x1010bff

Il nome dell'immagine è rundll32.exe, che in effetti non è il nome dell'immagine associato alla riproduzione del clip multimediale.

Nota Per impostare il thread corrente, digitare numero di thread.thread<>.

Per altre informazioni su thread e processi, vedere i riferimenti seguenti:

Thread e processi

Modifica dei contesti

Sezione 11: IRQL, registri e disassembly

Visualizzare il runtime di integrazione salvato

Nella sezione 11 verranno visualizzati irQL e il contenuto dei regsister.

<- Nel sistema host

Il livello di richiesta di interrupt (IRQL) 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. L'estensione !irql visualizza il livello di richiesta di interrupt (IRQL) 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 e disassembly

Visualizzare i registri

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.

Screenshot della finestra Registri WinDbg che mostra circa 12 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, vedere r (registri).

Per informazioni sul contenuto del registro, vedere Architettura x86 e architettura x64.

Smontaggio

È possibile disassemblare il codice in esecuzione per visualizzare il codice del linguaggio assembly in esecuzione selezionando Visualizza>disassembly.

Screenshot della finestra disassembly di WinDbg che mostra il codice del linguaggio dell'assembly.

Per altre informazioni sul disassembly del linguaggio di assembly, vedere Annotated x86 Disassembly e Annotated x64 Disassembly.

Sezione 12: Usare la memoria

Nella sezione 12 si useranno i comandi del debugger per visualizzare il contenuto della memoria.

Visualizzare la memoria

Potrebbe essere necessario esaminare la memoria per identificare un problema o per esaminare variabili, puntatori e così via. È possibile visualizzare la memoria digitando uno dei comandi di indirizzo> d* <seguenti.

db

Visualizza i dati in valori di byte e caratteri ASCII.

dd

Visualizza i dati come parole doppie (4 byte).

du

Visualizza i dati come caratteri Unicode.

dw

Visualizza i dati come valori di parola (2 byte) e caratteri ASCII.

Nota Se si tenta di visualizzare un indirizzo non valido, il relativo contenuto viene visualizzato come punti interrogativi (?).

In alternativa, è possibile visualizzare la memoria selezionando Visualizza>memoria. Usare il pulsante a discesa Formato di visualizzazione per modificare la modalità di visualizzazione della memoria.

Screenshot della finestra di memoria della visualizzazione WinDbg con varie opzioni di formato di visualizzazione.

  1. Per visualizzare i dati associati al controllo volume, impostare un punto di interruzione da attivare nella routine PropertyHandlerAudioEngineVolumeLevel usando il comando bm. Prima di impostare il nuovo punto di interruzione, verranno cancellati tutti i punti di interruzione precedenti usando bc *.

    kd> bc *
    
  2. Impostare un punto di interruzione da attivare nella routine PropertyHandlerAudioEngineVolumeLevel usando il comando bm.

    kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  3. Elencare i punti di interruzione per verificare che il punto di interruzione sia impostato correttamente.

    kd> bl
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  4. Usare il comando g per riavviare l'esecuzione del codice.

    Nel sistema di destinazione regolare il volume nell'area di notifica. In questo modo il punto di interruzione verrà attivato.

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume:
    fffff80f`02c3a4b0 44894c2420      mov     dword ptr [rsp+20h],r9d
    
  5. Usare la voce di menu Visualizza>locale per visualizzare le variabili locali. Si noti il valore corrente della variabile IVolume.

  6. È possibile visualizzare il tipo di dati e il valore corrente per la variabile IVolume nel codice di esempio digitando il comando dt e il nome della variabile.

    kd> dt lVolume
    Local var @ 0xa011ea50 Type long
    0n-6291456
    
  7. Il punto di interruzione viene raggiunto immettendo SetDeviceChannelVolume.

    STDMETHODIMP_(NTSTATUS) CMiniportWaveRT::SetDeviceChannelVolume(_In_  ULONG _ulNodeId, _In_ UINT32 _uiChannel, _In_  LONG  _Volume)
    {
        NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    
        PAGED_CODE ();
    
        DPF_ENTER(("[CMiniportWaveRT::SetEndpointChannelVolume]"));
        IF_TRUE_ACTION_JUMP(_ulNodeId != KSNODE_WAVE_AUDIO_ENGINE, ntStatus = STATUS_INVALID_DEVICE_REQUEST, Exit);
    
        // Snap the volume level to our range of steppings.
        LONG lVolume = VOLUME_NORMALIZE_IN_RANGE(_Volume); 
    
        ntStatus = SetChannelVolume(_uiChannel, lVolume);
    Exit:
        return ntStatus;
    }
    
  8. Provare a visualizzare il valore nella posizione di memoria di IVolume usando il comando dt (Tipo di visualizzazione).

    kd> dt dt lVolume
    Local var @ 0xffffb780b7eee664 Type long
    0n0
    

    Poiché la variabile è ancora da definire, non contiene informazioni.

  9. Premere F10 per eseguire l'ultima riga di codice in SetDeviceChannelVolume.

        return ntStatus;
    
  10. Visualizzare il valore nella posizione di memoria di IVolume usando il comando dt (Tipo di visualizzazione).

    kd> dt lVolume
    Local var @ 0xffffb780b7eee664 Type long
    0n-6291456
    

    Ora che la variabile è attiva, in questo esempio viene visualizzato un valore di 6291456.

  11. È anche possibile visualizzare la posizione di memoria di IVolume usando ? (Evaluate Expression) Comando.

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  12. L'indirizzo visualizzato, ffffb780'b7eee664 è l'indirizzo della variabile lVolume. Usare il comando dd per visualizzare il contenuto della memoria in tale posizione.

    kd>  dd ffffb780`b7eee664
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    ffffb780`b7eee674  ffffc98e e0495756 fffff80e c52d7008
    ffffb780`b7eee684  ffffc98e 00000000 fffff80e 00000000
    ffffb780`b7eee694  ffffc98e ffa00000 ffffb780 b7eee710
    ffffb780`b7eee6a4  ffffb780 00000000 00000000 c7477260
    ffffb780`b7eee6b4  ffffc98e b7eee7a0 ffffb780 b7eee6f0
    ffffb780`b7eee6c4  ffffb780 e04959ca fffff80e 00000000
    ffffb780`b7eee6d4  00000000 00000028 00000000 00000002
    
  13. È possibile visualizzare i primi quattro byte di un indirizzo specificando il parametro di intervallo L4.

    kd> dd ffffb780`b7eee664 l4
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    
  14. Per visualizzare i diversi tipi di output della memoria, digitare i comandi du, da e db .

    kd> du ffffb780`b7eee664 
    ffffb780`b7eee664  ""
    
    kd> a ffffb780`b7eee664 
    ffffb780`b7eee664  ""
    
    kd> db 0xffffae015ff97664 
    ffffae01`5ff97664  00 80 bc ff 18 00 00 00-00 00 00 00 08 50 e0 51  .............P.Q
    ffffae01`5ff97674  00 c0 ff ff 56 57 da 56-0e f8 ff ff 08 50 e0 51  ....VW.V.....P.Q
    ffffae01`5ff97684  00 c0 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffae01`5ff97694  00 c0 ff ff aa 80 bc ff-01 ae ff ff 10 77 f9 5f  .............w._
    ffffae01`5ff976a4  01 ae ff ff 40 00 00 00-00 e6 ff ff 10 dc 30 55  ....@.........0U
    ffffae01`5ff976b4  00 c0 ff ff a0 77 f9 5f-01 ae ff ff f0 76 f9 5f  .....w._.....v._
    ffffae01`5ff976c4  01 ae ff ff ca 59 da 56-0e f8 ff ff 00 00 00 00  .....Y.V........
    ffffae01`5ff976d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

    Usare l'opzione df float per visualizzare i dati come numeri a virgola mobile e precisione singola (4 byte).

    df ffffb780`b7eee664 
    ffffb780`b7eee664          -1.#QNAN   3.3631163e-044                0        -2775.002
    ffffb780`b7eee674          -1.#QNAN  -5.8032637e+019         -1.#QNAN        -2775.002
    ffffb780`b7eee684          -1.#QNAN                0         -1.#QNAN                0
    ffffb780`b7eee694          -1.#QNAN         -1.#QNAN         -1.#QNAN  -2.8479408e-005
    

Scrivere in memoria

Analogamente ai comandi usati per la lettura della memoria, è possibile usare i comandi e* per modificare il contenuto della memoria.

Comando Descrizione

Cadauno

Stringa ASCII (non con terminazione NULL)

eu

Stringa Unicode (non con terminazione NULL

Nuovo

Valori di Word (2 byte)

Eza

Stringa ASCII con terminazione NULL

ezu

Stringa Unicode con terminazione NULL

Eb

Valori di byte

ed

Valori di parola doppia (4 byte)

Nell'esempio seguente viene illustrato come sovrascrivere la memoria.

  1. Individuare prima di tutto l'indirizzo dell'oggetto lVolume usato nel codice di esempio.

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  2. Sovrascrivere l'indirizzo di memoria con nuovi caratteri usando il comando eb .

    kd> eb 0xffffb780`b7eee664 11 11 11 11 11
    
  3. Visualizzare il percorso di memoria per verificare che i caratteri siano stati sovrascritti digitando il comando db .

    kd> db 0xffffb780`b7eee664
    ffffb780`b7eee664  11 11 11 11 11 00 00 00-00 00 00 00 08 70 2d c5  .............p-.
    ffffb780`b7eee674  8e c9 ff ff 56 57 49 e0-0e f8 ff ff 08 70 2d c5  ....VWI......p-.
    ffffb780`b7eee684  8e c9 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffb780`b7eee694  8e c9 ff ff 00 00 a0 ff-80 b7 ff ff 10 e7 ee b7  ................
    ffffb780`b7eee6a4  80 b7 ff ff 00 00 00 00-00 00 00 00 60 72 47 c7  ............`rG.
    ffffb780`b7eee6b4  8e c9 ff ff a0 e7 ee b7-80 b7 ff ff f0 e6 ee b7  ................
    ffffb780`b7eee6c4  80 b7 ff ff ca 59 49 e0-0e f8 ff ff 00 00 00 00  .....YI.........
    ffffb780`b7eee6d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

In alternativa, è possibile modificare il contenuto della memoria in una finestra espressioni di controllo o variabili locali. Per la finestra espressioni di controllo, è possibile che vengano visualizzate variabili che non rientrano nel contesto del frame corrente. La modifica non è rilevante se non sono nel contesto.

Sezione 13: Terminare la sessione WinDbg

<-Nel sistema host

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 (versione classica) nella documentazione di riferimento sul debug.

Sezione 14: Risorse di debug di Windows

Altre informazioni sono disponibili nel debug di Windows. Si noti che alcuni di questi libri useranno versioni precedenti di Windows, ad esempio 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

The Defrag Tools Show WinDbg Episodes 13-29: </shows/defrag-tools/>

Fornitori di formazione:

OSR- https://www.osr.com/

Vedi anche

Introduzione al debug di Windows