Verwenden von Kerneldebugging zum Debuggen von Fehlern beim Testen der Zuverlässigkeit von Gerätegrundlagen
In diesem Artikel wird beschrieben, wie Sie allgemeine Kerneldebuggingbefehle verwenden können, um Fehler beim Testen der Zuverlässigkeit von Gerätegrundlagen zu debuggen.
Festlegen von Symbolen
Sie finden die Inhaltssymbole für Windows Hardware Kit Lab auf der Website des Microsoft-Servers für öffentliche Symbole. Unter Verwenden des Microsoft-Symbolservers zum Abrufen von Debugsymboldateien finden Sie weitere Informationen zum Microsoft-Server für öffentliche Symbole. Sie können Symbole im Kerneldebugger festlegen, indem Sie den Befehl .sympath (Set Symbol Path) ausführen.
Beispiel:
In diesem Beispiel legt der Befehl „.sympath“ den Serverpfad für öffentliche Symbole im Debugger fest.
.sympath SRV*c:\localsymbols*https://msdl.microsoft.com/download/symbols
!analyze -v
Wenn Sie Testfehler untersuchen, die durch Systemfehlerüberprüfungen des Kerneldebuggers verursacht werden, sollten Sie zunächst den Befehl !analyze verwenden, nachdem Sie Symbole festgelegt haben. Dieser Befehl identifiziert den Fehlerprüfungscode, den Grund für die Fehlerprüfung und die Stapelüberwachung, in der die fehlerhafte Komponente angezeigt wird. Unter Verwenden der Erweiterung „!analyze“ finden Sie weitere Informationen zu diesem Befehl.
Untersuchen von Stapelüberwachungen des Testvorgangs
Tests der Zuverlässigkeit von Gerätegrundlagen werden oft als Te.ProcessHost.exe oder Te.exe auf dem Testcomputer ausgeführt. Es ist nützlich, Stapelüberwachungen aus diesen Testprozessen zu überprüfen, wenn Sie Systemfehlerüberprüfungen oder Testunterbrechungen untersuchen. Bei Fehlerüberprüfungen kann mithilfe von Stapelüberwachungen der Testfall identifiziert werden, der zum Zeitpunkt des Absturzes getestet wurde. Bei Testunterbrechungen können anhand von Stapelüberwachungen alle Testthreads identifiziert werden, die den Fortschritt des Tests verhindern.
Sie können die Erweiterung !process 0 0 verwenden, um alle auf dem Testcomputer ausgeführten Prozesse aufzuführen und die EPROCESS-Blockadresse des Testprozesses zu ermitteln.
Sie können die Erweiterung !process /p /r verwenden, um die vollständigen Stapelüberwachungen aus den Testprozessen abzurufen.
Weitere Informationen zur Erweiterung !process finden Sie unter !process und .process (Set Process Context).
Beachten Sie, dass die Ausgabe von !process die Taktanzahl jedes Threads enthält, der im Prozess ausgeführt wird. Wenn Sie Testunterbrechungen untersuchen, sollten Threads mit einer hohen Taktanzahl, die WDTF-Komponenten im Stapel enthalten (also Modulnamen, die im Stapel mit „WDTF“ beginnen), sorgfältig überprüft werden, da diese Threads die Tests dauerhaft behindern und diese schließlich aufgrund eines Timeouts fehlschlagen können.
Beispiel:
In diesem Beispiel identifizieren die Erweiterungen !process 0 0, !process /p /r und !process einen Testthread, der eine sehr hohe Taktanzahl aufweist, die verhindert, dass der Test fortgeführt wird:
!process 0 0 Te.ProcessHost.exe
PROCESS fffffa80093c6340
SessionId: 1 Cid: 1320 Peb: 7f6595b3000 ParentCid: 12a0
DirBase: 21eee000 ObjectTable: fffff8a0035b0a00 HandleCount: 327.
Image: TE. ProcessHost.exe
.process /p /r fffffa80093c6340
!process fffffa80093c6340
THREAD fffffa800b2be8c0 Cid 0964.0eac Teb: 000007f601ba6000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
fffffa800b2a11d0 SynchronizationEvent
fffffa800b300640 SynchronizationEvent
Not impersonating
DeviceMap fffff8a0014b9c80
Owning Process fffffa800b302940 Image: TE.exe
Attached Process N/A Image: N/A
Wait Start TickCount 210995 Ticks: 405945 (0:01:45:32.782)
Context Switch Count 51 IdealProcessor: 2
UserTime 00:00:00.015
KernelTime 00:00:00.015
Win32 Start Address WDTFInterfaces!TsSingleWorkerThread (0x000007fe3a567f28)
Stack Init fffff8800eb5edd0 Current fffff8800eb5dee0
Base fffff8800eb5f000 Limit fffff8800eb59000 Call 0
Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
Child-SP RetAddr Call Site
fffff880`0eb5df20 fffff803`78b27f7c nt!KiSwapContext+0x76
(Inline Function) --------`-------- nt!KiSwapThread+0xf4 (Inline Function @ fffff803`78b27f7c)
fffff880`0eb5e060 fffff803`78aaf4ab nt!KiCommitThreadWait+0x23c
fffff880`0eb5e120 fffff803`78b257a0 nt!KiWaitForAllObjects+0x3bb
fffff880`0eb5e3c0 fffff803`78ecb3dc nt!KeWaitForMultipleObjects+0x4ae
fffff880`0eb5e470 fffff803`78ecb853 nt!ObWaitForMultipleObjects+0x29c
fffff880`0eb5e980 fffff803`78aff053 nt!NtWaitForMultipleObjects+0xe3
fffff880`0eb5ebd0 000007fe`45d2315b nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffff880`0eb5ec40)
00000083`7cdef148 000007fe`430912c6 ntdll!ZwWaitForMultipleObjects+0xa
00000083`7cdef150 000007fe`368641b5 KERNELBASE!WaitForMultipleObjectsEx+0xe5
00000083`7cdef430 000007fe`3a566793 WDTFAudioSimpleIoAction!CAudioImpl::RunIO+0x3d1
00000083`7cdef520 000007fe`3a566ea0 WDTFInterfaces!CSimpleIOEx::PerformIO+0x10f
00000083`7cdef5b0 000007fe`3a56706b WDTFInterfaces!CSimpleIOExWrap::PerformIO+0x28
00000083`7cdef5e0 000007fe`3a553fe5 WDTFInterfaces!CMTest_Receiver::Run+0x77
00000083`7cdefe20 000007fe`3a5578ac WDTFInterfaces!CSimpleIO_MTestEx::ActionThread+0x105
00000083`7cdefeb0 000007fe`3a567f3e WDTFInterfaces!CMTEXThread::ThreadWorker+0xc
00000083`7cdefee0 000007fe`4319167e WDTFInterfaces!TsSingleWorkerThread+0x16
00000083`7cdeff20 000007fe`45d3c3f1 KERNEL32!BaseThreadInitThunk+0x1a
00000083`7cdeff50 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
Wechseln des Kontexts zu Threads und Frames zum Anzeigen von lokalen Variablen
Wenn Sie lokale Variablen aus einem Stapelrahmen anzeigen möchten, müssen Sie Folgendes durchführen:
Wechseln Sie den Kontext zum Thread, indem Sie den Befehl .thread (Set Register Context) ausführen.
Sichern Sie den Stapel mithilfe des Befehls kn zusammen mit den Framenummern (weitere Informationen finden Sie unter Stapel- und Sicherungsprotokollierung).
Wechseln Sie mithilfe des Befehls .frame (Set Local Context) zum Framekontext.
Zeigen Sie mithilfe des Befehl dv (Display Local Variables) lokale Variablen an.
Hinweis
Sie müssen private Symbole verwenden, um lokale Variablen zu sichern.
Beispiel:
In diesem Beispiel werden die Befehle .thread, kn, .frame und dv verwendet, um lokale Variablen aus einem Stapelrahmen zu sichern:
3: kd> .thread fffffa8009da7b00
Implicit thread is now fffffa80`09da7b00
3: kd> kn
*** Stack trace for last set context - .thread/.cxr resets it
# Child-SP RetAddr Call Site
00 fffff880`054a03a0 fffff801`05caaf7c nt!KiSwapContext+0x76
01 fffff880`054a04e0 fffff801`05ca8d9f nt!KiCommitThreadWait+0x23c
02 fffff880`054a05a0 fffff801`05f98841 nt!KeWaitForSingleObject+0x1cf
03 fffff880`054a0630 fffff801`061f253d nt!IopCancelAlertedRequest+0x71
04 fffff880`054a0670 fffff801`0604fc5d nt! ?? ::NNGAKEGL::`string'+0x1caaf
05 fffff880`054a0860 fffff801`060552b8 nt!ObpLookupObjectName+0x7a1
06 fffff880`054a0990 fffff801`06066ebe nt!ObOpenObjectByName+0x258
07 fffff880`054a0a60 fffff801`06067609 nt!IopCreateFile+0x37c
08 fffff880`054a0b00 fffff801`05c82053 nt!NtCreateFile+0x79
09 fffff880`054a0b90 000007fa`1a4930fa nt!KiSystemServiceCopyEnd+0x13
0a 00000038`d21bb478 000007fa`0677feef ntdll!NtCreateFile+0xa
0b 00000038`d21bb480 000007fa`0678e9a2 WDTFFuzzTestAction!DPETryOpenDevice+0x2b3
0c 00000038`d21bcde0 000007fa`0678e892 WDTFFuzzTestAction!CWDTFFuzz_MTestImpl::AttemptToOpenSurface+0x66
0d 00000038`d21bce50 000007fa`0678b84c WDTFFuzzTestAction!CWDTFFuzz_MTestImpl::FindAttackSurfaces+0x16e
0e 00000038`d21bf6c0 000007fa`0678a4d9 WDTFFuzzTestAction!CWDTFFuzz_MTestImpl::ActionThread+0x200
0f 00000038`d21bf760 000007fa`1a17167e WDTFFuzzTestAction!ActionThreadStart+0x9
10 00000038`d21bf790 000007fa`1a4ac3f1 KERNEL32!BaseThreadInitThunk+0x1a
11 00000038`d21bf7c0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
3: kd> .frame b
0b 00000038`d21bb480 000007fa`0678e9a2 WDTFFuzzTestAction!DPETryOpenDevice+0x2b3
3: kd> dv
szName = 0x00000038`d21bce90
bSync = 0n0
ppdevice = 0x00000038`d21bce10
messageBuffer = wchar_t [2048] "Attempting to open device : \DosDevices\root#multiportserial#0000#{05caff94-7b1e-420c-8c70-d8361bc4ee0a}"
oa = struct _OBJECT_ATTRIBUTES
!pnptriage
Wenn Sie Fehler beim Testen der Zuverlässigkeit von Gerätegrundlagen debuggen, können Sie mit dem Befehl !pnptriage aktive PNP-Threads auflisten. Beachten Sie, dass die Ausgabe von !pnptriage die Taktanzahl für jeden PNP-Thread enthält, der im System ausgeführt wird. Wenn Sie Testunterbrechungen untersuchen, sollten Threads mit einer hohen Taktanzahl sorgfältig überprüft werden, da diese Threads die Tests dauerhaft behindern und diese schließlich aufgrund eines Timeouts fehlschlagen können.
Debugerweiterungen für Treiber
Die folgenden Erweiterungen für Kerneldebugger können Treiberprobleme debuggen, die beim Testen der Zuverlässigkeit von Gerätegrundlagen auftreten können: !drvobj, !devnode, !devobj, !devstack und !irp. Weitere Informationen zu diesen Erweiterungen finden Sie unter Kernelmoduserweiterungen.
Debuggererweiterungen
Debuggingtools für Windows enthält zusätzliche Debuggererweiterungen, mit denen Sie Fehler behandeln können, die beim Ausführen von Tests für die folgenden Treibertypen auftreten: USB-, Speicher-, NDIS-, Grafik-, KMDF- (Kernel-Mode Driver Framework) und UMDF-Treiber (User-Mode Driver Framework). Weitere Informationen zu diesen Erweiterungen finden Sie unter Spezialisierte Erweiterungen. Weitere Informationen zu den Debugtools für Windows finden Sie unter Herunterladen und Installieren von Debugtools für Windows.