Inserimento di errori basati su stack
Nota Le istruzioni per abilitare questa funzionalità si applicano solo a WDK per Windows 8. Per Windows 8.1, questa funzionalità è stata integrata in Verifica driver. Nei computer che eseguono Windows 8.1, usare l'opzione Simulazione di risorse a basso livello sistematico.
L'opzione Stack Based Failure Injection inserisce errori di risorsa nei driver in modalità kernel. Questa opzione usa un driver speciale, KmAutoFail.sys, insieme a Driver Verifier per penetrare i percorsi di gestione degli errori del driver. Il test di questi percorsi è stato storicamente molto difficile. L'opzione Stack Based Failure Injection inserisce gli errori delle risorse in modo prevedibile, che rende i problemi che trova riproducibili. Poiché i percorsi di errore sono facili da riprodurre, semplifica anche la verifica delle correzioni a questi problemi.
Per determinare la causa radice dell'errore, viene fornita un'estensione del debugger che può indicare esattamente quali errori sono stati inseriti e nell'ordine in cui sono stati inseriti.
Quando l'opzione Stack Based Failure Injection è abilitata in un driver specifico, intercetta alcune chiamate dal driver al kernel e Ndis.sys. Stack Based Failure Injection esamina lo stack di chiamate, in particolare nella parte dello stack di chiamate che proviene dal driver abilitato. Se si tratta della prima volta che ha mai visto lo stack, avrà esito negativo la chiamata in base alla semantica di tale chiamata. In caso contrario, se ha visto che la chiamata prima, la passerà attraverso non toccato. Stack Based Failure Injection contiene la logica per gestire il fatto che un driver può essere caricato e scaricato più volte. Riconoscerà che uno stack di chiamate è lo stesso anche se il driver viene ricaricato in una posizione di memoria diversa.
Attivazione di questa opzione
È possibile attivare la funzionalità Stack Based Failure Injection per uno o più driver quando si distribuisce un driver in un computer di test. È possibile selezionare l'opzione Stack Based Failure Injection quando si configurano le proprietà del verificatore driver per i progetti del pacchetto driver. È necessario riavviare il computer per attivare o disattivare l'opzione Stack Based Failure Injection. È anche possibile eseguire un'utilità di test per abilitare Il verifica driver e questa funzionalità nel computer di test.
Importante Quando si attiva Stack Based Failure Injection nel computer di test, assicurarsi di non selezionare Anche Simulazione risorse basse.
Pagina Utilizzo della proprietà Del verificatore driver
- Aprire le pagine delle proprietà per il pacchetto driver. Fare clic con il pulsante destro del mouse sul progetto del pacchetto driver in Solution Explorer e selezionare Proprietà.
- Nelle pagine delle proprietà per il pacchetto driver fare clic su Proprietà di configurazione, fare clic su Installazione driver e quindi su Verifica driver.
- Selezionare Abilita verifica driver. Quando si abilita Il verificatore driver nel computer di test, è possibile scegliere di abilitare Driver Verifier per tutti i driver nel computer, solo per il progetto driver o per un elenco di driver specificati.
- In Stack Based Failure Injector selezionare (check) Stack Based Failure Injection( Inserimento errori basati su stack).
- Fare clic su Applica o OK.
- Per altre informazioni, vedere Distribuzione di un driver in un computer di test . Il computer di test deve riavviare per attivare questa opzione.
Uso del test Abilita e Disabilita test del driver
È anche possibile abilitare Il verificatore driver eseguendo un test di utilità. Seguire le istruzioni descritte in Come testare un driver in fase di esecuzione usando Visual Studio. Nella categoria Di test All Test\Driver Verifier selezionare il test Abilita verifica driver (possibile riavvio richiesto) e Disabilitare il verifica driver (possibile riavvio richiesto).
Selezionare le opzioni del verificatore driver facendo clic sul nome del test Abilita verifica driver (possibile riavvio richiesto) nella finestra Gruppo di test driver .
Selezionare (check) Inserimento errori basati su stack.
Dopo aver aggiunto questi test a un gruppo di test, è possibile salvare il gruppo di test. Per abilitare l'inserimento di errori basati su stack, eseguire il test Enable Driver Verifier (possibile riavvio obbligatorio) nel computer configurato per i test.
Per disattivare il verificatore driver, eseguire il test Disable Driver Verifier (possibile riavvio richiesto).
Uso dell'opzione Stack Based Failure Injection
Una considerazione importante quando si esegue il test con Stack Based Failure Injection è che la maggior parte dei bug rilevati genererà un controllo di bug. Questo potrebbe rivelarsi un po 'doloroso se il driver è un driver caricato di avvio. A causa di questo, si disabilita automaticamente Stack Based Failure Injection se il verificatore driver è disabilitato. Ciò significa che è possibile disabilitare Stack Based Failure Injection al momento dell'avvio dal debugger disabilitando Driver Verifier usando il comando !verifier –disable.
Se è possibile, per i test iniziali con Stack Based Failure Injection, configurare il driver in modo che non venga caricato al momento dell'avvio. È quindi possibile eseguire alcuni test di caricamento e scaricamento semplici. Molti dei bug trovati da Stack Based Failure Injection si verificano durante l'inizializzazione o la pulizia. Il caricamento e lo scaricamento ripetuto del driver è un buon modo per trovare questi.
Dopo aver apportato eventuali correzioni necessarie per ottenere i test di caricamento che hanno esito positivo, è possibile passare a test basati su IOCTL, test funzionali completi e infine test di stress. In generale, se si segue questa progressione di test, non verranno rilevati molti nuovi problemi durante i test di stress perché la maggior parte dei percorsi di codice sarà già stata eseguita prima di questo.
Uso dell'estensione del debugger SBFI (Stack Based Failure Injection)
La maggior parte dei problemi riscontrati con l'inserimento degli errori basati su stack causa i controlli dei bug. Per determinare la causa di questi bug di codice, WDK fornisce l'estensione del debugger Di inserimento errori basati su stack e i simboli necessari. La procedura di installazione installerà entrambi nel sistema del debugger. Il percorso predefinito è C:\Programmi (x86)\Windows Kits\8.0\Debuggers\<arch>.
Per eseguire l'estensione del debugger
Dal prompt dei comandi del debugger digitare il comando seguente: !<path>\kmautofaildbg.dll.autofail. Si supponga, ad esempio, che le estensioni del debugger siano installate in c:\dbgext e che kmautofail.pdb si trovi nel percorso del simbolo, immettere il comando seguente:
!c:\dbgext\kmautofaildbg.dll.autofail
In questo modo verranno dumpte le informazioni sul debugger che mostrano gli stack di chiamate dagli errori più recenti inseriti. Ogni voce ha un aspetto simile al seguente, tratto da un'esecuzione di test reale. Nell'esempio seguente l'inserimento degli errori basati su stack è abilitato in Mydriver.sys
Sequence: 2, Test Number: 0, Process ID: 0, Thread ID: 0
IRQ Level: 2, HASH: 0xea98a56083aae93c
0xfffff8800129ed83 kmautofail!ShimHookExAllocatePoolWithTag+0x37
0xfffff88003c77566 mydriver!AddDestination+0x66
0xfffff88003c5eeb2 mydriver!ProcessPacketDestination+0x82
0xfffff88003c7db82 mydriver!ProcessPacketSource+0x8b2
0xfffff88003c5d0d8 mydriver!ForwardPackets+0xb8
0xfffff88003c81102 mydriver!RoutePackets+0x142
0xfffff88003c83826 mydriver!RouteNetBufferLists+0x306
0xfffff88003c59a76 mydriver!DeviceSendPackets+0x156
0xfffff88003c59754 mydriver!ProcessingComplete+0x4a4
0xfffff88001b69b81 systemdriver2!ProcessEvent+0x1a1
0xfffff88001b3edc4 systemdriver1!CallChildDriver+0x20
0xfffff88001b3fc0a systemdriver1!ProcessEvent+0x3e
0xfffff800c3ea6eb9 nt!KiRetireDpcList+0x209
0xfffff800c3ea869a nt!KiIdleLoop+0x5a
Nella parte superiore dell'output il numero di sequenza conta il numero di errori inseriti. Questo esempio mostra il secondo errore inserito durante questa esecuzione di test. L'ID processo è 0, quindi questo è stato il processo di sistema. IRQL è 2, quindi viene chiamato a livello di invio.
Dallo stack, KmAutoFail è il driver Stack Based Failure Injection. Il nome della funzione KmAutoFail indica la chiamata di funzione da Mydriver.sys è stata intercettata e inserita un errore. In questo caso, la funzione non riuscita era ExAllocatePoolWithTag. Tutte le funzioni in KmAutoFail che intercettano le chiamate a Ntoskrnl.sys o Ndis.sys usano questa convenzione di denominazione. Verrà quindi visualizzato lo stack di chiamate con il driver sottoposto a test (Mydriver.sys). Si tratta della parte dello stack di chiamate utilizzato per determinare l'univocità dello stack. Pertanto ogni voce dumpata dall'estensione del debugger sarà univoca in questa parte dello stack di chiamate. Il resto dello stack di chiamate indica chi ha chiamato il driver. L'importanza principale di questo è se il driver viene chiamato dalla modalità utente (tramite un IOCTL) o da un driver in modalità kernel.
Si noti che se un driver ha restituito un errore dalla routine DriverEntry , un tentativo di ricaricamento verrà normalmente eseguito in una posizione di memoria diversa. In tal caso, lo stack di chiamate dalla posizione precedente conterrà probabilmente "Garbage" anziché le informazioni sullo stack dal driver. Ma questo non è un problema; indica che il driver ha gestito correttamente l'errore inserito.
Questa voce successiva mostra una chiamata al driver tramite un IOCTL dalla modalità utente. Prendere nota dell'ID processo e del livello IRQ. Poiché Mydriver.sys è un driver di filtro NDIS, L'IOCTL ha superato Ndis.sys. Si noti che nt! NtDeviceIoControlFile è nello stack. Tutti i test eseguiti sul driver che usano IOCTLs verranno eseguiti tramite questa funzione.
Sequence: 5, Test Number: 0, Process ID: 2052, Thread ID: 4588
IRQ Level: 0, HASH: 0xecd4650e9c25ee4
0xfffff8800129ed83 kmautofail!ShimHookExAllocatePoolWithTag+0x37
0xfffff88003c6fb39 mydriver!SendMultipleOids+0x41
0xfffff88003c7157b mydriver!PvtDisconnect+0x437
0xfffff88003c71069 mydriver!NicDisconnect+0xd9
0xfffff88003ca3538 mydriver!NicControl+0x10c
0xfffff88003c99625 mydriver!DeviceControl+0x4c5
0xfffff88001559d93 NDIS!ndisDummyIrpHandler+0x73
0xfffff88001559339 NDIS!ndisDeviceControlIrpHandler+0xc9
0xfffff800c445cc96 nt!IovCallDriver+0x3e6
0xfffff800c42735ae nt!IopXxxControlFile+0x7cc
0xfffff800c4274836 nt!NtDeviceIoControlFile+0x56
0xfffff800c3e74753 nt!KiSystemServiceCopyEnd+0x13
Analisi dei risultati dell'inserimento di errori basati su stack
Si stanno eseguendo i test sul driver e improvvisamente si è verificato un problema. Probabilmente questo è stato un controllo di bug, ma potrebbe anche perché il computer è diventato non rispondente. Come si trova la causa? Supponendo che si tratti di un controllo di bug, usare prima l'estensione precedente per trovare l'elenco di errori inseriti, quindi usare il comando debugger: !analizza -v.
Il controllo dei bug più comune è causato dal mancato controllo dell'esito positivo di un'allocazione. In questo caso, lo stack dall'analisi del controllo dei bug è probabilmente quasi identico a quello dell'ultimo errore inserito. A un certo punto dopo l'allocazione non riuscita (spesso la riga successiva), il driver accederà al puntatore Null. Questo tipo di bug è molto facile da correggere. A volte l'allocazione non riuscita è una o due fino all'elenco, ma questo tipo è ancora molto facile da trovare e correggere.
Il secondo controllo dei bug più comune si verifica durante la pulizia. In questo caso, il driver ha probabilmente rilevato l'errore di allocazione e ha saltato alla pulizia; ma durante la pulizia, il driver non ha controllato il puntatore e ancora una volta ha eseguito l'accesso a un puntatore Null. Un caso strettamente correlato è dove la pulizia può essere chiamata due volte. Se la pulizia non imposta il puntatore su una struttura su Null dopo che lo libera, la seconda volta che la funzione di pulizia viene chiamata tenterà di liberare la struttura una seconda volta, causando un controllo di bug.
Gli errori che causano la mancata risposta del computer sono più difficili da diagnosticare, ma la procedura per eseguirne il debug è simile. Questi errori sono spesso causati da problemi di conteggio dei riferimenti o blocco di selezione. Fortunatamente, Driver Verifier intercetta molti problemi di blocco spin prima di causare problemi. In questi casi, eseguire l'interruzione nel debugger e usare l'estensione del debugger per eseguire il dump dell'elenco di errori inseriti dall'inserimento di errori basati su stack. Un rapido sguardo al codice relativo agli errori più recenti potrebbe mostrare un conteggio dei riferimenti eseguito prima dell'errore ma non rilasciato dopo. In caso contrario, cercare un thread nel driver in attesa di un blocco di rotazione o per qualsiasi conteggio dei riferimenti ovviamente errato.