Freigeben über


Debugtreiber – Step by Step Lab (Sysvad Kernel Mode)

Dieses Labor bietet praktische Übungen, die veranschaulichen, wie der Sysvad-Audio-Kernelmodusgerätetreiber gedebuggt wird.

Microsoft Windows Debugger (WinDbg) ist ein leistungsfähiges Windows-basiertes Debuggingtool, mit dem Sie das Debuggen im Benutzermodus und im Kernelmodus ausführen können. WinDbg bietet Debuggen auf Quellebene für Windows-Kernel-, Kernelmodustreiber und Systemdienste sowie Benutzermodusanwendungen und -treiber.

WinDbg kann Quellcode durchlaufen, Haltepunkte festlegen, Variablen anzeigen (einschließlich C++-Objekte), Stapelspuren und Arbeitsspeicher anzeigen. Das Fenster "Debuggerbefehl" ermöglicht es dem Benutzer, eine Vielzahl von Befehlen ausstellen zu können.

Laboreinrichtung

Sie benötigen die folgende Hardware, um das Lab abschließen zu können:

  • Ein Laptop oder Desktopcomputer (Host) unter Windows 10
  • Laptop oder Desktopcomputer (Ziel) unter Windows 10
  • Netzwerkhub/Router und Netzwerkkabel zum Verbinden der beiden PCs
  • Zugriff auf das Internet zum Herunterladen von Symboldateien

Sie benötigen die folgende Software, um das Lab abschließen zu können.

  • Microsoft Visual Studio 2017
  • Windows Software Development Kit (SDK) für Windows 10
  • Windows Driver Kit (WDK) für Windows 10
  • Der Sysvad-Beispielaudiotreiber für Windows 10

Informationen zum Herunterladen und Installieren des WDK finden Sie unter "Herunterladen des Windows Driver Kit (WDK)".

Exemplarische Vorgehensweise zum Sysvad-Debuggen

In dieser Übung werden Sie durch den Prozess des Debuggens eines Kernelmodustreibers geführt. Die Übungen verwenden das Beispiel für einen virtuellen Syvad-Audiotreiber. Da der Syvad-Audiotreiber nicht mit der tatsächlichen Audiohardware interagiert, kann er auf den meisten Geräten verwendet werden. Das Labor befasst sich mit den folgenden Aufgaben:

Echo-Treiberlabor

Der Echo-Treiber ist ein einfacherer Treiber als der Sysvad-Audiotreiber. Wenn Sie neu bei WinDbg sind, sollten Sie zuerst das Debuggen von universellen Treibern – Step-by-Step Lab (Echo-Kernelmodus) abschließen. In diesem Lab werden die Einrichtungsanweisungen aus diesem Labor wiederverwendet. Wenn Sie also die Übung abgeschlossen haben, können Sie die Abschnitte 1 und 2 hier überspringen.

Abschnitt 1: Herstellen einer Verbindung mit einer WinDbg-Sitzung im Kernelmodus

In Abschnitt 1 konfigurieren Sie das Netzwerkdebugging auf dem Host- und Zielsystem.

Die PCs in dieser Übung müssen für die Verwendung einer Ethernet-Netzwerkverbindung für das Kerneldebugging konfiguriert werden.

In dieser Übung werden zwei Computer verwendet. WinDbg wird auf dem Hostsystem ausgeführt, und der Sysvad-Treiber wird auf dem Zielsystem ausgeführt.

Verwenden Sie einen Netzwerkhub/Router und Netzwerkkabel, um die beiden PCs zu verbinden.

Diagramm mit zwei PCs, die über einen Netzwerkhub/Router verbunden sind.

Um mit Kernelmodusanwendungen zu arbeiten und WinDbg zu verwenden, empfehlen wir, den KDNET over Ethernet-Transport zu verwenden. Informationen zur Verwendung des Ethernet-Transportprotokolls finden Sie unter "Erste Schritte mit WinDbg (Kernel-Mode)". Weitere Informationen zum Einrichten des Zielcomputers finden Sie unter Vorbereiten eines Computers für die manuelle Treiberbereitstellung und das automatische Einrichten des KDNET-Netzwerkkernkerndebuggings.

Konfigurieren des Kernelmodusdebuggings mit Ethernet

Führen Sie die folgenden Schritte aus, um das Debuggen im Kernelmodus im Zielsystem zu aktivieren.

<- Auf dem Hostsystem

  1. Öffnen Sie eine Eingabeaufforderung im Hostsystem, und geben Sie "ipconfig /all " ein, um die IP-Adresse zu ermitteln.
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. Notieren Sie die IP-Adresse des Hostsystems: ______________________________________

  2. Aufzeichnen des Hostnamens des Hostsystems: ______________________________________

-> Auf dem Zielsystem

  1. Öffnen Sie eine Eingabeaufforderung im Zielsystem, und verwenden Sie den Pingbefehl , um die Netzwerkkonnektivität zwischen den beiden Systemen zu bestätigen. Verwenden Sie die tatsächliche IP-Adresse des Hostsystems, das Sie anstelle von 169.182.1.1 aufgezeichnet haben, das in der Beispielausgabe angezeigt wird.
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

Führen Sie die folgenden Schritte aus, um das Kernelmodusdebugging auf dem Zielsystem mithilfe des KDNET-Hilfsprogramms zu aktivieren.

  1. Suchen Sie im Hostsystem das WDK-KDNET-Verzeichnis. Standardmäßig befindet es sich hier.

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

In diesen Labs wird davon ausgegangen, dass auf beiden PCs sowohl das Ziel als auch der Host eine 64-Bit-Version von Windows ausgeführt wird. Wenn dies nicht der Fall ist, besteht der beste Ansatz darin, die gleiche "Bitanzahl" von Tools auf dem Host auszuführen, auf dem das Ziel läuft. Wenn das Ziel beispielsweise 32-Bit-Windows ausführt, führen Sie eine 32-Version des Debuggers auf dem Host aus. Weitere Informationen finden Sie unter Auswählen der 32-Bit- oder 64-Bit-Debuggingtools.

  1. Suchen Sie diese beiden Dateien und kopieren Sie sie auf eine Netzwerkfreigabe oder einen USB-Stick, damit sie auf dem Zielcomputer verfügbar sind.

    kdnet.exe

    VerifiedNICList.xml

  2. Öffnen Sie auf dem Zielcomputer ein Eingabeaufforderungsfenster als Administrator. Geben Sie diesen Befehl ein, um zu überprüfen, ob die NIC auf dem Ziel-PC unterstützt wird.

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. Geben Sie diesen Befehl ein, um die IP-Adresse des Hostsystems festzulegen. Verwenden Sie die tatsächliche IP-Adresse des Hostsystems, das Sie anstelle von 169.182.1.1 aufgezeichnet haben, das in der Beispielausgabe angezeigt wird. Wählen Sie eine eindeutige Portadresse für jedes Ziel-/Hostpaar aus, mit dem Sie arbeiten, z. B. 50010.
C:\>kdnet 169.182.1.1 50010

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

Von Bedeutung

Bevor Sie BCDEdit verwenden, um Startinformationen zu ändern, müssen Sie Möglicherweise Windows-Sicherheitsfeatures wie BitLocker und sicherer Start auf dem Test-PC vorübergehend anhalten. Aktivieren Sie diese Sicherheitsfeatures erneut, wenn tests abgeschlossen sind, und verwalten Sie den Test-PC entsprechend, wenn die Sicherheitsfeatures deaktiviert sind. Der sichere Start ist in der Regel in UEFI deaktiviert. Um auf die UEFI-Einstellung zuzugreifen, verwenden Sie System, Wiederherstellung, erweitertes Start-Up. Wählen Sie beim Neustart die Option "Problembehandlung", "Erweiterte Optionen", "UEFI-Firmwareeinstellungen" aus. Seien Sie vorsichtig, da das falsche Festlegen von UEFI-Optionen oder das Deaktivieren von BitLocker das System möglicherweise unbrauchbar machen kann.

  1. Geben Sie diesen Befehl ein, um zu bestätigen, dass die dbgsettings ordnungsgemäß festgelegt sind.
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.

Kopieren Sie den automatisch generierten eindeutigen Schlüssel in eine Textdatei, um die Eingabe auf dem Host-PC zu vermeiden. Kopieren Sie die Textdatei mit dem Schlüssel auf das Hostsystem.

Hinweis: Firewalls und Debugger

Wenn Sie eine Popupnachricht von der Firewall erhalten und den Debugger verwenden möchten, aktivieren Sie alle drei Kontrollkästchen.

Screenshot der Windows-Sicherheitswarnung, die angibt, dass die Windows-Firewall einige Features einer App blockiert hat.

<- Auf dem Hostsystem

  1. Öffnen Sie auf dem Hostcomputer ein Eingabeaufforderungsfenster als Administrator. Wechseln Sie in das Verzeichnis WinDbg.exe. Wir verwenden die x64version von WinDbg.exe aus dem Windows Driver Kit (WDK), das als Teil der Windows Kit-Installation installiert wurde.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 
  1. Starten Sie WinDbg mit Remotebenutzerdebugging mit dem folgenden Befehl. Der Wert für den Schlüssel und port entspricht dem, was Sie zuvor mithilfe von BCDEdit für das Ziel festgelegt haben.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

->Auf dem Zielsystem

Starten Sie das Zielsystem neu.

<-Auf dem Hostsystem

In einer oder zwei Minuten sollte die Debugausgabe auf dem Hostsystem angezeigt werden.

Screenshot des Windows-Debuggers, der die Ausgabe des Befehlsfensters aus einer Live-Kernelverbindung anzeigt.

Das Fenster "Debuggerbefehl" ist das primäre Debuginformationsfenster in WinDbg. Sie können Debuggerbefehle eingeben und die Befehlsausgabe in diesem Fenster anzeigen.

Das Fenster "Debuggerbefehl" ist in zwei Bereiche unterteilt. Sie geben Befehle im kleineren Bereich (dem Befehlseingabebereich) am unteren Rand des Fensters ein, und zeigen Sie die Befehlsausgabe im größeren Bereich oben im Fenster an.

Verwenden Sie im Befehlseingabebereich die NACH-OBEN- und NACH-UNTEN-TASTE, um durch den Befehlsverlauf zu scrollen. Wenn ein Befehl angezeigt wird, können Sie ihn bearbeiten oder die EINGABETASTE drücken, um den Befehl auszuführen.

Abschnitt 2: Kernelmodus-Debuggingbefehle und -techniken

In Abschnitt 2 verwenden Sie Debugbefehle, um Informationen zum Zielsystem anzuzeigen.

<- Auf dem Hostsystem

Debugger-Markupsprache (Debugger Markup Language, DML) mit .prefer_dml aktivieren

Einige Debugbefehle zeigen Text mithilfe der Debuggermarkupsprache an, die Sie auswählen können, um schnell weitere Informationen zu sammeln.

  1. Verwenden Sie STRG+BREAK (Bildlaufsperre) in WinDBg, um in den Code einzubrechen, der auf dem Zielsystem ausgeführt wird. Es kann einige Zeit dauern, bis das Zielsystem reagiert.
  2. Geben Sie den folgenden Befehl ein, um DML im Fenster "Debuggerbefehl" zu aktivieren.
0: kd> .prefer_dml 1
DML versions of commands on by default

Verwenden Sie .hh, um Hilfe zu erhalten

Sie können mit dem .hh-Befehl auf die Hilfe zu Referenzbefehlen zugreifen.

  1. Geben Sie den folgenden Befehl ein, um die Befehlsreferenzhilfe für .prefer_dml anzuzeigen.
    0: kd> .hh .prefer_dml
    

Die Debugger-Hilfedatei zeigt Hilfe für den Befehl .prefer_dml an.

Screenshot der Debuggerhilfeanwendung mit Hilfe für den Befehl

Anzeigen der Windows-Version auf dem Zielsystem

  1. Zeigen Sie detaillierte Versionsinformationen auf dem Zielsystem an, indem Sie den Befehl "Vertarget" (Zielcomputerversion anzeigen) im WinDbg-Fenster eingeben.
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

Auflisten der geladenen Module

  1. Sie können überprüfen, ob Sie mit dem richtigen Kernelmodusprozess arbeiten, indem Sie die geladenen Module anzeigen, indem Sie den Lm-Befehl (Geladene Module auflisten) im WinDbg-Fenster eingeben.
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
...

Anmerkung Ausgelassene Ausgaben werden mit "… in diesem Labor.

Da wir den Symbolpfad und geladene Symbole noch festlegen müssen, sind im Debugger begrenzte Informationen verfügbar.

Abschnitt 3: Herunterladen und Erstellen des Sysvad-Audiotreibers

In Abschnitt 3 laden Sie den Sysvad-Audiotreiber herunter und erstellen diesen.

Normalerweise arbeiten Sie mit Ihrem eigenen Treibercode, wenn Sie WinDbg verwenden. Um sich mit dem Debuggen von Audiotreibern vertraut zu machen, wird der virtuelle Sysvad-Audiobeispieltreiber verwendet. Dieses Beispiel wird verwendet, um zu veranschaulichen, wie Sie systemeigenen Kernelmoduscode schrittweise durchlaufen können. Diese Technik kann für das Debuggen komplexer Kernelmodus-Codeprobleme sehr nützlich sein.

Führen Sie die folgenden Schritte aus, um den Sysvad-Beispielaudiotreiber herunterzuladen und zu erstellen.

  1. Herunterladen und Extrahieren des Sysvad-Audiobeispiels von GitHub

    Sie können einen Browser verwenden, um das Sysvad-Beispiel und Readme.md Datei hier anzuzeigen:

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

    Screenshot des GitHub-Repositorys, das den Allgemeinen Ordner und die Schaltfläche

    In diesem Labor wird gezeigt, wie Sie Beispiele für universelle Treiber in einer ZIP-Datei herunterladen.

    a) Laden Sie die master.zip Datei auf Ihre lokale Festplatte herunter.

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

    b. Wählen Sie Windows-driver-samples-master.zipaus und halten Sie sie gedrückt (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie " Alle extrahieren" aus. Geben Sie einen neuen Ordner an, oder navigieren Sie zu einem vorhandenen Ordner, der die extrahierten Dateien speichert. Sie können z. B. C:\WDK_Samples\ als neuen Ordner angeben, in den die Dateien extrahiert werden.

    Abschnitt c. Navigieren Sie nach dem Extrahieren der Dateien zum folgenden Unterordner.

    C:\WDK_Samples\Sysvad

  2. Öffnen der Treiberlösung in Visual Studio

    Wählen Sie in Visual Studio "Datei>Öffnen>Projekt/Projektmappe..." aus, und navigieren Sie zu dem Ordner, der die extrahierten Dateien enthält (z. B. C:\WDK_Samples\Sysvad). Doppelklicken Sie auf die Lösungsdatei "Syvad ".

    Suchen Sie in Visual Studio den Projektmappen-Explorer. (Wenn dies noch nicht geöffnet ist, wählen Sie "Projektmappen-Explorer" aus dem Menü "Ansicht".) Im Projektmappen-Explorer sehen Sie eine Projektmappe mit einer Reihe von Projekten.

    Screenshot von Visual Studio mit der aus dem Sysvad-Projekt geladenen adapter.cpp Datei.

  3. Festlegen der Konfiguration und Plattform des Beispiels

    Wählen Sie im Projektmappen-Explorer die Projektmappe "sysvad" (7 von 7 Projekten) aus, und halten Sie sie gedrückt (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie "Configuration Manager" aus. Stellen Sie sicher, dass die Konfigurations- und Plattformeinstellungen für die vier Projekte identisch sind. Standardmäßig ist die Konfiguration auf "Win10 Debug" festgelegt, und die Plattform wird für alle Projekte auf "Win64" festgelegt. Wenn Sie Konfigurations- und/oder Plattformänderungen für ein Projekt vornehmen, müssen Sie dieselben Änderungen für die verbleibenden drei Projekte vornehmen.

    Anmerkung In dieser Übung wird davon ausgegangen, dass 64-Bit-Windows verwendet wird. Wenn Sie 32-Bit-Windows verwenden, erstellen Sie den Treiber für 32 Bit.

  4. Überprüfen der Treibersignatur

    Suchen Sie das TabletAudioSample. Öffnen Sie die Eigenschaftenseite des Sysvad-Treibers, und stellen Sie sicher, dass der Signaturmodus für Treiber> auf "Testzeichen" festgelegt ist.

  5. Treiberbeispiele müssen geändert werden, um Werte zu verwenden, die sich nicht mit vorhandenen Treibern überlappen. Informationen dazu, wie Sie ein eindeutiges Treiberbeispiel erstellen, das mit vorhandenen realen Treibern in Windows koexistiert, finden Sie unter "Vom Beispielcode zum Produktionstreiber - Was in den Beispielen geändert werden muss".

  6. Erstellen des Beispiels mit Visual Studio

    Wählen Sie in Visual Studio Build>Build Solutionaus.

    In den Buildfenstern sollte eine Meldung angezeigt werden, die angibt, dass der Build für alle sechs Projekte erfolgreich war.

Tipp

Wenn eine Buildfehlermeldung auftritt, verwenden Sie die Buildfehlernummer, um einen Fix zu ermitteln. Beispielsweise beschreibt MSBuild-Fehler MSB8040, wie mit spektrengeminderten Bibliotheken gearbeitet wird.

  1. Suchen der integrierten Treiberdateien

    Navigieren Sie im Datei-Explorer zu dem Ordner, der die extrahierten Dateien für das Beispiel enthält. Beispielsweise würden Sie zu C:\WDK_Samples\Sysvad navigieren, wenn dies der Ordner ist, den Sie zuvor angegeben haben. Innerhalb dieses Ordners variiert der Speicherort der kompilierten Treiberdateien je nach den Konfigurations- und Plattformeinstellungen, die Sie im Configuration Manager ausgewählt haben. Wenn Sie beispielsweise die Standardeinstellungen unverändert gelassen haben, werden die kompilierten Treiberdateien in einem Ordner mit dem Namen \x64\Debug für einen 64-Bit-Debugbuild gespeichert.

    Navigieren Sie zu dem Ordner, der die integrierten Dateien für den TabletAudioSample-Treiber enthält:

    C:\WDK_Samples\Sysvad\TabletAudioSample\x64\Debug. Der Ordner enthält den TabletAudioSample-.SYS Treiber, die Symbol-PDP-Datei und die Inf-Datei. Außerdem müssen Sie die DLL-Dateien und Symboldateien für DelayAPO, KWSApo und KeywordDetectorContosoAdapter lokalisieren.

    Um den Treiber zu installieren, benötigen Sie die folgenden Dateien.

    Dateiname BESCHREIBUNG
    TabletAudioSample.sys Die Treiberdatei.
    TabletAudioSample.pdb Die Treibersymboldatei.
    tabletaudiosample.inf Eine Informationsdatei (INF), die Informationen enthält, die zum Installieren des Treibers erforderlich sind.
    KeywordDetectorContosoAdapter.dll Beispielschlüsselwortdetektor.
    KeywordDetectorContosoAdapter.pdb Die Beispieldatei des Schlüsselwortdetektorsymbols.
    DelayAPO.dll Eine Verzögerungs-APO-Beispiel.
    DelayAPO.pdb Die Verzögerungssymboldatei für APO.
    KWSApo.dll Ein Muster-Keyword-Spotter APO.
    KWSApo.pdb Die Schlüsselwort-Spotter-Symboldatei.
    TabletAudioSample.cer Die TabletAudioSample-Zertifikatdatei.
  2. Suchen Sie einen USB-Stick, oder richten Sie eine Netzwerkfreigabe ein, um die erstellten Treiberdateien vom Host auf das Zielsystem zu kopieren.

Im nächsten Abschnitt kopieren Sie den Code in das Zielsystem, installieren und testen den Treiber.

Abschnitt 4: Installieren des Sysvad-Audiotreiberbeispiels auf dem Zielsystem

In Abschnitt 4 verwenden Sie devcon, um den Sysvad-Audiotreiber zu installieren.

-> Auf dem Zielsystem

Der Computer, auf dem Sie den Treiber installieren, wird als Zielcomputer oder Testcomputer bezeichnet. Dies ist in der Regel ein separater Computer vom Computer, auf dem Sie das Treiberpaket entwickeln und erstellen. Der Computer, auf dem Sie den Treiber entwickeln und erstellen, wird als Hostcomputer bezeichnet.

Der Vorgang zum Verschieben des Treiberpakets auf den Zielcomputer und die Installation des Treibers wird als Bereitstellen des Treibers bezeichnet.

Bevor Sie einen Treiber bereitstellen, müssen Sie den Zielcomputer vorbereiten, indem Sie die Testsignierung aktivieren. Danach können Sie das integrierte Treiberbeispiel auf dem Zielsystem ausführen.

Führen Sie die folgenden Schritte aus, um den Treiber auf dem Zielsystem zu installieren.

  1. Aktivieren von signierten Testtreibern

    So aktivieren Sie die Möglichkeit, signierte Testtreiber auszuführen:

    1. Öffnen Sie die Windows-Einstellungen.

    2. Wählen Sie in Update und Sicherheit die Option "Wiederherstellung" aus.

    3. Wählen Sie unter "Erweiterter Start" die Option "Jetzt neu starten" aus.

    4. Wenn der PC neu gestartet wird, wählen Sie "Problembehandlung" aus.

    5. Wählen Sie dann "Erweiterte Optionen", "Starteinstellungen" und dann " Neu starten" aus.

    6. Deaktivieren Sie die Erzwingung der Treibersignatur, indem Sie die Taste F7 drücken.

    7. Der PC wird mit den neuen Werten gestartet.

  2. -> Auf dem Zielsystem

    Installieren des Treibers

    Die folgenden Anweisungen zeigen, wie Sie den Beispieltreiber installieren und testen.

    Die FÜR die Installation dieses Treibers erforderliche INF-Datei ist TabletAudioSample.inf. Öffnen Sie auf dem Zielcomputer ein Eingabeaufforderungsfenster als Administrator. Navigieren Sie zu Ihrem Treiberpaketordner, klicken Sie mit der rechten Maustaste auf die Datei "TabletAudioSample.inf", und wählen Sie dann "Installieren" aus.

    Ein Dialogfeld wird angezeigt, das angibt, dass der Testtreiber ein nicht signierter Treiber ist. Wählen Sie Diesen Treiber trotzdem installieren, um fortzufahren.

    Screenshot der Windows-Sicherheitswarnung, die besagt, dass Windows den Herausgeber nicht überprüfen kann.

    Tipp

     Wenn Probleme mit der Installation auftreten, überprüfen Sie die folgende Datei, um weitere Informationen zu erhalten. %windir%\inf\setupapi.dev.log

    Ausführlichere Anweisungen finden Sie unter Konfigurieren eines Computers für die Treiberbereitstellung, Tests und Debugging.

    Die INF-Datei enthält die Hardware-ID zum Installieren des tabletaudiosample.sys. Für das Syvad-Beispiel lautet die Hardware-ID: root\sysvad_TabletAudioSample

  3. Untersuchen des Treibers im Geräte-Manager

    Geben Sie auf dem Zielcomputer in einem Eingabeaufforderungsfenster devmgmt ein, um den Geräte-Manager zu öffnen. Wählen Sie im Geräte-Manager im Menü "Ansicht" die Option "Geräte nach Typ" aus.

    Suchen Sie in der Gerätestruktur nach virtuellem Audiogerät (WDM) – Tablet-Beispiel im Knoten "Audiogerät". Dies befindet sich in der Regel unter dem Knoten "Sound", "Video" und "Gamecontroller" . Vergewissern Sie sich, dass sie installiert und aktiv ist.

    Markieren Sie den Treiber für die tatsächliche Hardware auf dem PC im Geräte-Manager. Wählen Sie dann den Treiber aus, halten Sie ihn gedrückt (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie "Deaktivieren", um den Treiber zu deaktivieren.

    Vergewissern Sie sich im Geräte-Manager, dass der Audiohardwaretreiber den Abwärtspfeil anzeigt, der angibt, dass er deaktiviert ist.

    Screenshot der Geräte-Manager-Baumstruktur mit hervorgehobenen 'Virtual Audio Device Tablet Sample'.

    Nachdem Sie den Beispieltreiber erfolgreich installiert haben, können Sie ihn jetzt testen.

Testen des Sysvad-Audiotreibers

  1. Geben Sie auf dem Zielcomputer in einem Eingabeaufforderungsfenster devmgmt ein, um den Geräte-Manager zu öffnen. Wählen Sie im Geräte-Manager im Menü "Ansicht " die Option "Geräte nach Typ" aus. Suchen Sie in der Geräteliste nach Virtual Audio Device (WDM) - Tablet Sample.

  2. Öffnen Sie die Systemsteuerung, und navigieren Sie zu "Hardware und Sound>Verwalten von Audiogeräten". Wählen Sie im Dialogfeld "Sound" das Lautsprechersymbol mit der Bezeichnung "Virtuelles Audiogerät (WDM) – Tablet Sample" aus, und wählen Sie dann " Standard festlegen", aber nicht " OK" aus. Dadurch bleibt das Dialogfeld "Sound" offen.

  3. Suchen Sie eine MP3- oder andere Audiodatei auf dem Zielcomputer, und doppelklicken Sie, um sie wiederzugeben. Vergewissern Sie sich dann im Dialogfeld "Ton", dass in der Lautstärkeanzeige Aktivität vorhanden ist, die dem Virtuellen Audiogerät (WDM) - Tablet Sample-Treiber zugeordnet ist.

Abschnitt 5: Verwenden von WinDbg zum Anzeigen von Informationen zum Treiber

In Abschnitt 5 legen Sie den Symbolpfad fest und verwenden Kerneldebuggerbefehle, um Informationen zum Sysvad-Beispieltreiber anzuzeigen.

Symbole ermöglichen es WinDbg, zusätzliche Informationen wie Variablennamen anzuzeigen, die beim Debuggen von unschätzbarem Wert sein können. WinDbg verwendet die Debugsymbolformate von Microsoft Visual Studio für das Debuggen auf Quellebene. Sie kann auf ein beliebiges Symbol oder jede Variable in einem Modul zugreifen, das PDB-Symboldateien enthält.

Führen Sie die folgenden Schritte aus, um den Debugger zu laden.

<-Auf dem Hostsystem

  1. Wenn Sie den Debugger geschlossen haben, öffnen Sie ihn erneut mithilfe des folgenden Befehls im Eingabeaufforderungsfenster des Administrators. Ersetzen Sie den Schlüssel und den Port durch das, was Sie zuvor konfiguriert haben.

    C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Verwenden Sie Strg+Pause (Bildlaufsperre), um den Code zu unterbrechen, der auf dem Zielsystem ausgeführt wird.

Festlegen des Symbolpfads

  1. Verwenden Sie den Befehl ".symfix ", um den Symbolpfad zum Microsoft-Symbolserver in der WinDbg-Umgebung festzulegen.

    0: kd> .symfix
    
  2. Um Ihren lokalen Symbolspeicherort hinzuzufügen und Ihre lokalen Symbole verwenden zu können, fügen Sie den Pfad mit .sympath+ hinzu und laden Sie dann .reload /f.

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

    Anmerkung Der Befehl ".reload " mit der Option "/f force" löscht alle Symbolinformationen für das angegebene Modul und lädt die Symbole neu. In einigen Fällen lädt dieser Befehl auch das Modul selbst neu oder entlädt es.

Anmerkung Sie müssen die richtigen Symbole laden, um erweiterte Funktionen zu verwenden, die WinDbg bereitstellt. Wenn Sie keine Symbole ordnungsgemäß konfiguriert haben, erhalten Sie Nachrichten, die angeben, dass Symbole nicht verfügbar sind, wenn Sie versuchen, Funktionen zu verwenden, die von Symbolen abhängig sind.

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

HinweisSymbolserver

Es gibt eine Reihe von Ansätzen, die zum Arbeiten mit Symbolen verwendet werden können. In vielen Situationen können Sie den PC so konfigurieren, dass er auf Symbole von einem Symbolserver zugreift, den Microsoft bei Bedarf bereitstellt. In dieser Schritt-für-Schritt-Anleitung wird davon ausgegangen, dass dieser Ansatz verwendet wird. Wenn sich die Symbole in Ihrer Umgebung an einem anderen Speicherort befinden, ändern Sie die Schritte, um diesen Speicherort zu verwenden. Weitere Informationen finden Sie unter Symbolpfad für Windows-Debugger.

Hinweis: Verstehen Sie die Anforderungen für Quellcodesymbole

Zum Ausführen des Quelldebuggings müssen Sie eine überprüfte (Debug)-Version Ihrer Binärdateien erstellen. Der Compiler erstellt Symboldateien (PDB-Dateien). Diese Symboldateien zeigen den Debugger an, wie die binären Anweisungen den Quellzeilen entsprechen. Die tatsächlichen Quelldateien selbst müssen auch für den Debugger zugänglich sein.

Die Symboldateien enthalten nicht den Text des Quellcodes. Für das Debuggen ist es am besten, wenn der Linker Ihren Code nicht optimiert. Das Quelldebugging und der Zugriff auf lokale Variablen sind schwieriger und manchmal fast unmöglich, wenn der Code optimiert wurde. Wenn Sie Probleme beim Anzeigen lokaler Variablen oder Quellzeilen haben, legen Sie die folgenden Buildoptionen fest.

setze COMPILE_DEBUG=1

Setze ENABLE_OPTIMIZER=0

  1. Geben Sie Folgendes im Befehlsbereich des Debuggers ein, um Informationen zum Sysvad-Treiber anzuzeigen.

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

    Weitere Informationen finden Sie unter lm.

  2. Wählen Sie den Link "Alle globalen Symbole durchsuchen " in der Debugausgabe aus, um Informationen zu Elementen anzuzeigen, die mit dem Buchstaben a beginnen.

  3. Da DML aktiviert ist, sind einige Elemente der Ausgabe hot links, die Sie auswählen können. Wählen Sie den Datenlink in der Debugausgabe aus, um Informationen zu Elementsymbolen anzuzeigen, die mit dem Buchstaben a beginnen.

    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 *)
    

    Weitere Informationen finden Sie unter x (Untersuchen von Symbolen).For information, see x (Examine Symbols).

  4. Die !lmi-Erweiterung zeigt detaillierte Informationen zu einem Modul an. Geben Sie !lmi tabletaudiosample ein. Die Ausgabe sollte dem unten angezeigten Text ähneln.

    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. Verwenden Sie die Erweiterung !dh , um Kopfzeileninformationen wie unten dargestellt anzuzeigen.

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

Abschnitt 6: Anzeige von Informationen zur Plug-and-Play-Gerätehierarchie

In Abschnitt 6 werden Informationen über den Sysvad-Beispielgerätetreiber und seinen Speicherort im Plug-and-Play-Gerätebaum angezeigt.

Informationen zum Gerätetreiber im Plug-and-Play-Gerätebaum können bei der Problembehandlung hilfreich sein. Wenn sich beispielsweise ein Gerätetreiber nicht im Gerätebaum befindet, könnte ein Problem mit der Installation des Gerätetreibers vorliegen.

Weitere Informationen zur Debugerweiterung des Geräteknotens finden Sie unter !devnode.

<-Auf dem Hostsystem

  1. Um alle Geräteknoten in der Plug and Play-Gerätestruktur anzuzeigen, geben Sie den Befehl "!devnode 0 1 " ein. Dieser Befehl kann eine oder zwei Minuten dauern, bis er ausgeführt wird. Während dieser Zeit wird "*Beschäftigt" im Statusbereich von WinDbg angezeigt.

    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. Verwenden Sie STRG+F, um in der Ausgabe zu suchen, die generiert wird, um nach dem Namen des Gerätetreibers sysvad zu suchen.

    Finde das Dialogfeld mit dem im Suchfeld eingegebenen Begriff

    Ein Geräteknoteneintrag mit einem Namen sysvad_TabletAudioSample ist in der !devnode-Ausgabe für Syvad vorhanden.

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

    Beachten Sie, dass die PDO-Adresse und die DevNode-Adresse angezeigt werden.

  3. Verwenden Sie den !devnode 0 1 sysvad_TabletAudioSample Befehl, um Plug- und Play-Informationen anzuzeigen, die unserem Sysvad-Gerätetreiber zugeordnet sind.

    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. Die im vorherigen Befehl angezeigte Ausgabe enthält die PDO, die der ausgeführten Instanz unseres Treibers zugeordnet ist, in diesem Beispiel ist sie 0xffffe00089c575a0. Geben Sie den Befehl !devobj<PDO-Adresse> ein, um Plug-and-Play-Informationen anzuzeigen, die dem Sysvad-Gerätetreiber zugeordnet sind. Verwenden Sie die PDO-Adresse, die !devnode auf Ihrem PC anzeigt, nicht die hier gezeigte.

    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. Die im Befehl "!devobj " angezeigte Ausgabe enthält den Namen des angefügten Geräts: \Driver\sysvad_tabletaudiosample. Verwenden Sie den Befehl !drvobj mit einer Bitmaske von 2, um Informationen anzuzeigen, die dem angeschlossenen Gerät zugeordnet sind.

    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. Geben Sie den !devstack<PDO-Adressbefehl> ein, um Plug-and-Play-Informationen anzuzeigen, die dem Gerätetreiber zugeordnet sind. Die im Befehl "!devnode 0 1 " angezeigte Ausgabe enthält die PDO-Adresse, die der ausgeführten Instanz unseres Treibers zugeordnet ist. In diesem Beispiel ist es 0xffffe00089c575a0. Verwenden Sie die PDO-Adresse, die !devnode auf Ihrem PC anzeigt, nicht die unten gezeigte.

    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"
    

Die Ausgabe zeigt, dass wir einen ziemlich einfachen Treiber-Stack haben. Der sysvad_TabletAudioSample Treiber ist ein untergeordnetes Element des PnPManager-Knotens. Der PnPManager ist ein Stammknoten.

Dieses Diagramm zeigt eine komplexere Geräteknotenstruktur.

Diagramm einer Geräteknotenstruktur, die aus ca. 20 Knoten besteht.

Anmerkung Weitere Informationen zu komplexeren Treiberstapeln finden Sie unter Treiberstapel und Geräteknoten und Gerätestapel.

Abschnitt 7: Arbeiten mit Haltepunkten

In Abschnitt 7 arbeiten Sie mit Haltepunkten zusammen, um die Codeausführung an bestimmten Punkten zu beenden.

Festlegen von Haltepunkten mithilfe von Befehlen

Haltepunkte werden verwendet, um die Codeausführung in einer bestimmten Codezeile zu beenden. Anschließend können Sie den Code von diesem Punkt aus vorwärts ausführen, um diesen spezifischen Codeabschnitt zu debuggen.

Verwenden Sie einen der folgenden b-Befehle , um einen Haltepunkt mithilfe eines Debugbefehls festzulegen.

Bp

Legt einen Haltepunkt fest, der aktiv ist, bis das Modul, in dem es sich befindet, entladen wird.

Bu

Legt einen Haltepunkt fest, der beim Entladen des Moduls nicht aufgelöst wird, und aktiviert erneut, wenn das Modul neu geladen wird.

Bm

Legt einen Haltepunkt für ein Symbol fest. Dieser Befehl verwendet bu oder bp entsprechend und ermöglicht die Verwendung von Wildcards * zum Festlegen von Haltepunkten für alle Symbole, die übereinstimmen (z. B. alle Methoden in einer Klasse).

  1. Verwenden Sie die WinDbg-Benutzeroberfläche, um zu bestätigen, dass derDebugquellmodus> in der aktuellen WinDbg-Sitzung aktiviert ist.

  2. Fügen Sie den Standort des lokalen Codes zum Pfad der Quelle hinzu, indem Sie den folgenden Befehl eingeben.

    .sympath+ C:\WDK_Samples\Sysvad
    
  3. Fügen Sie Ihren lokalen Symbolspeicherort zum Symbolverzeichnis hinzu, indem Sie den folgenden Befehl eingeben.

    .sympath+ C:\WDK_Samples\Sysvad
    
  4. Festlegen der Debugmaske

    Während Sie mit einem Treiber arbeiten, kann es praktisch sein, alle Nachrichten zu sehen, die angezeigt werden. Geben Sie Folgendes ein, um die standardmäßige Debugbitmaske zu ändern, damit alle Debugmeldungen aus dem Zielsystem im Debugger angezeigt werden.

    0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
    
  5. Legen Sie den Haltepunkt mit dem BM-Befehl unter Verwendung des Namens des Treibers fest, gefolgt vom Funktionsnamen (AddDevice), an dem Sie den Haltepunkt festlegen möchten, getrennt durch ein Ausrufezeichen.

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

    Sie können eine verschiedene Syntax in Verbindung mit Variablen setzen wie <Modul> verwenden!<symbol>, <Klasse>::<Methode>, '<Datei.cpp>:<Zeilennummer>', oder eine Anzahl von Malen überspringen <Bedinung><#>. Weitere Informationen finden Sie unter Verwenden von Haltepunkten.

  6. Auflisten der aktuellen Haltepunkte, um zu bestätigen, dass der Haltepunkt durch Eingeben des Befehls "bl " festgelegt wurde.

    0: kd> bl
    1 e fffff801`14b5f000     0001 (0001) tabletaudiosample!AddDevice
    
  7. Starten Sie die Codeausführung im Zielsystem neu, indem Sie den Befehl g eingeben.

  8. ->Auf dem Zielsystem

    Öffnen Sie in Windows den Geräte-Manager, indem Sie das Symbol verwenden oder mmc devmgmt.msc eingeben. Erweitern Sie im Geräte-Manager den Knoten "Sound", "Video" und "Gamecontroller" . Wählen Sie den Eintrag des virtuellen Audiotreibers aus und halten Sie sie gedrückt (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie im Menü "Deaktivieren" aus.

  9. Wählen Sie den Eintrag des virtuellen Audiotreibers erneut aus und halten Sie den Eintrag (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie im Menü "Aktivieren" aus.

  10. <- Auf dem Hostsystem

    Dies sollte dazu führen, dass Windows den Treiber neu lädt, der AddDevice aufruft. Dadurch wird der AddDevice-Debug-Haltepunkt ausgelöst, und die Ausführung des Treibercodes im Zielsystem sollte angehalten werden.

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

    Wenn der Quellpfad ordnungsgemäß festgelegt ist, sollten Sie bei der AddDevice-Routine in adapter.cpp stoppen.

    {
        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. Durchlaufen Sie den Code durch eine Zeile, indem Sie den Befehl "p " eingeben oder F10 drücken. Sie können den sysvad-AddDevice-Code schrittweise ausführen: zu PpvUtilCall, PnpCallAddDevice und dann zum PipCallDriverAddDevice-Windows-Code. Sie können dem Befehl "p " eine Zahl angeben, um mehrere Zeilen vorwärts zu leiten, z. B. P 5.

  12. Wenn Sie mit dem Schrittweisen Durchlaufen des Codes fertig sind, verwenden Sie den Go-Befehl g , um die Ausführung im Zielsystem neu zu starten.

Festlegen von Speicherzugriffs-Haltepunkten

Sie können auch Haltepunkte setzen, die ausgelöst werden, wenn auf einen Speicherort zugegriffen wird. Verwenden Sie den Befehl ba (Unterbrechung beim Zugriff) mit der folgenden Syntax.

ba <access> <size> <address> {options}
Auswahlmöglichkeit BESCHREIBUNG

e

ausführen (wenn die CPU eine Anweisung von der Adresse abruft)

r

Lese-/Schreibzugriff (wenn die CPU auf die Adresse zugreift, indem sie liest oder schreibt)

w

schreiben (wenn die CPU an die Adresse schreibt)

Beachten Sie, dass Sie zu einem bestimmten Zeitpunkt nur vier Datenhaltepunkte festlegen können, und es liegt an Ihnen, sicherzustellen, dass Sie Ihre Daten richtig ausrichten oder den Haltepunkt nicht auslösen (Wörter müssen in Adressen enden, die durch 2 divisierbar sind, dwords müssen durch 4 divisierbar sein, und Quadwords von 0 oder 8)

Wenn Sie z. B. einen Lese-/Schreibhaltepunkt für eine bestimmte Speicheradresse festlegen möchten, verwenden Sie einen Befehl wie folgt.

ba r 4 fffff800`7bc9eff0

Ändern des Haltepunktzustands

Sie können vorhandene Haltepunkte mithilfe der folgenden Befehle verändern.

Bl

Listet Haltepunkte auf.

v. Chr

Löscht einen Haltepunkt aus der Liste. Verwenden Sie bc *, um alle Haltepunkte zu entfernen.

Bd

Deaktiviert ein Breakpoint. Verwenden Sie bd * zum Deaktivieren aller Haltepunkte.

sein

Aktiviert einen Haltepunkt. Verwenden Sie "be *", um alle Haltepunkte zu aktivieren.

Alternativ können Sie die Haltepunkte auch ändern, indem Sie Bearbeiten>Haltepunkte auswählen. Beachten Sie, dass das Haltepunktdialogfeld nur mit vorhandenen Haltepunkten funktioniert. Neue Haltepunkte müssen über die Befehlszeile festgelegt werden.

Festlegen eines Haltepunkts auf MixerVolume

Verschiedene Teile des Audiotreibercodes werden aufgerufen, um auf verschiedene Ereignisse zu reagieren, nachdem der Gerätetreiber geladen wurde. Im nächsten Abschnitt legen wir einen Haltepunkt fest, der ausgelöst wird, wenn der Benutzer die Lautstärkeregelung für den virtuellen Audiotreiber anpasst.

Um einen Haltepunkt bei MixerVolume festzulegen, führen Sie die folgenden Schritte aus.

  1. <- Auf dem Hostsystem

    Um die Methode zu suchen, die das Volume ändert, verwenden Sie den x-Befehl, um die Symbole in CAdapterCommon auflisten, die das Zeichenfolgenvolume enthalten.

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

    Verwenden Sie STRG+F, um in der Ausgabe nach oben nach Volume zu suchen und die MixerVolumeWrite-Methode zu finden.

  2. Löschen Sie die vorherigen Haltepunkte mit dem Befehl „bc *“.

  3. Legen Sie einen Symbolhaltepunkt für die CAdapterCommon::MixerVolumeWrite-Routine mithilfe des folgenden Befehls fest.

    kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite
      1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"
    
  4. Listen Sie die Haltepunkte auf, um zu bestätigen, dass der Haltepunkt ordnungsgemäß festgelegt ist.

    kd> bl
    1 e fffff801`177b26a0 [c:\WDK_Samples\audio\sysvad\common.cpp @ 1668]    0001 (0001) tabletaudiosample!CAdapterCommon::MixerVolumeWrite
    
  5. Starten Sie die Codeausführung im Zielsystem neu, indem Sie den Befehl g eingeben.

  6. Wählen Sie in der Systemsteuerung Hardware und Sound>aus. Wählen Sie Sink Description Sample aus und halten Sie sie gedrückt (oder klicken Sie mit der rechten Maustaste darauf), und wählen Sie Eigenschaften. Wählen Sie die Registerkarte "Ebenen " aus. Passen Sie die Schiebereglerlautstärke an.

  7. Dies sollte dazu führen, dass der SetMixerVolume-Debug-Haltepunkt ausgelöst wird und die Ausführung des Treibercodes auf dem Zielsystem angehalten wird.

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

    Sie sollten an dieser Zeile in common.cpp anhalten.

    {
        if (m_pHW)
        {
            m_pHW->SetMixerVolume(Index, Channel, Value);
        }
    } // MixerVolumeWrite
    
  8. Verwenden Sie den Befehl dv, um die aktuellen Variablen und deren Werte anzuzeigen. Weitere Informationen zu Variablen werden im nächsten Abschnitt dieses Labors bereitgestellt.

    2: kd> dv
               this = 0x00000000`00000010
             ulNode = 0x344
          ulChannel = 0x210a45f8
            lVolume = 0n24
    
  9. Drücken Sie F10 , um den Code einzeln durchzugehen.

  10. Drücken Sie F5 , um die Ausführung des MixerVolumeWrite-Codes abzuschließen.

Zusammenfassung – Schrittweises Durchlaufen von Code aus dem Fenster "Debuggerbefehl"

Im Folgenden sind die Befehle aufgeführt, die Sie zum Durchlaufen des Codes verwenden können (mit den zugehörigen Tastaturkürzungen, die in Klammern angezeigt werden).

  • Break in (STRG+Break) – Mit diesem Befehl wird ein System unterbrochen, während das System läuft und mit WinDbg kommuniziert (die Sequenz im Kernel-Debugger ist STRG+C).

  • Step over (F10) – Dieser Befehl führt dazu, dass die Codeausführung jeweils eine Anweisung oder ein Befehl ausgeführt wird. Wenn ein Aufruf auftritt, übergibt die Codeausführung den Aufruf, ohne die aufgerufene Routine einzugeben. (Wenn die Programmiersprache C oder C++ ist und WinDbg sich im Quellmodus befindet, kann der Quellmodus mithilfe von Debug> aktiviert oder deaktiviert werden.Quellmodus).

  • Schritt In (F11) – Dieser Befehl ist wie Überschreiten, mit der Ausnahme, dass die Ausführung eines Aufrufs in die aufgerufene Routine wechselt.

  • Heraustreten (UMSCHALT+F11) – Mit diesem Befehl wird die Ausführung zur aktuellen Routine fortgesetzt und dann beendet (aktuelle Stelle im Aufrufstapel). Dies ist nützlich, wenn Sie genug von der Routine gesehen haben.

  • Zum Cursor ausführen (F7 oder STRG+F10) – Platzieren Sie den Cursor in einem Quell- oder Disassemblierungsfenster, an dem die Ausführung anhalten soll, und drücken Sie dann F7; Der Code wird bis zu diesem Punkt ausgeführt. Beachten Sie, dass winDbg nicht unterbrochen würde, wenn der Fluss der Codeausführung nicht den durch den Cursor angegebenen Punkt erreicht (z. B. eine IF-Anweisung nicht ausgeführt wird), da die Codeausführung den angegebenen Punkt nicht erreicht hat.

  • Ausführen (F5) – Ausführen, bis ein Haltepunkt erreicht wird oder ein Ereignis wie eine Fehlerprüfung auftritt.

Erweiterte Optionen

  • Festlegen der Anweisung auf die aktuelle Zeile (STRG+UMSCHALT+I) – In einem Quellfenster können Sie den Cursor auf eine Zeile setzen, diese Tastenkombination eingeben, und die Codeausführung beginnt ab diesem Punkt, sobald Sie den Vorgang fortsetzen lassen (z. B. F5 oder F10). Dies ist praktisch, wenn Sie eine Sequenz wiederholen möchten, aber es erfordert eine gewisse Sorgfalt. Beispielsweise werden Register und Variablen nicht auf das festgelegt, was sie sein würden, wenn die Codeausführung diese Zeile natürlich erreicht hätte.

  • Direkte Einstellung des Eip-Registers - Sie können einen Wert in das Eip-Register setzen, und sobald Sie F5 (oder F10, F11 usw.) drücken, beginnt die Ausführung von dieser Adresse. Dies ähnelt dem Festlegen einer Anweisung auf die durch den Cursor festgelegte aktuelle Zeile, mit der Ausnahme, dass Sie die Adresse einer Assemblyanweisung angeben.

Es kann einfacher sein, die Benutzeroberfläche zu durchlaufen, anstatt über die Befehlszeile, sodass diese Methode empfohlen wird. Bei Bedarf können die folgenden Befehle verwendet werden, um eine Quelldatei in der Befehlszeile zu durchlaufen:

  • .lines - Quellzeileninformationen aktivieren.

  • bp main - Legen Sie den anfänglichen Haltepunkt am Anfang des Moduls fest.

  • l+t - Schritt erfolgt über die Quellzeile.

  • Wählen Sie Debug>Quellmodus aus, um in den Quellmodus zu gelangen. Der L+t-Befehl reicht nicht aus.

  • l+s - Quellzeilen werden an der Eingabeaufforderung angezeigt.

  • g - Programm ausführen, bis "main" eingegeben wird.

  • p – Führen Sie eine Quellzeile aus.

Weitere Informationen finden Sie unter Quellcodedebugging in WinDbg (Klassisch) in der Debugreferenzdokumentation.

Festlegen von Haltepunkten im Code

Sie können einen Haltepunkt im Code festlegen, indem Sie die DebugBreak() Anweisung hinzufügen und das Projekt neu erstellen und den Treiber erneut installieren. Dieser Haltepunkt wird jedes Mal ausgelöst, wenn der Treiber aktiviert ist, weshalb es sich um eine Technik handelt, die nur in den frühen Entwicklungsphasen eingesetzt werden sollte und nicht im Produktionscode. Diese Technik ist nicht so flexibel wie das dynamische Festlegen von Haltepunkten mithilfe der Haltepunktbefehle.

Es könnte sinnvoll sein, eine Kopie des Sysvad-Treibers ohne den hinzugefügten Haltepunkt für weitere Laborarbeit aufzubewahren.

  1. Setzen Sie bei jeder Ausführung der AddDevice-Methode einen Haltepunkt, indem Sie die DebugBreak() Anweisung dem Beispielcode hinzufügen.

    ...
        // 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. Führen Sie alle zuvor beschriebenen Schritte aus, um den Treiber in Microsoft Visual Studio neu zu erstellen und erneut auf dem Zielcomputer zu installieren. Stellen Sie sicher, dass Sie den vorhandenen Treiber deinstallieren, bevor Sie den aktualisierten Treiber installieren.

  3. Löschen Sie alle vorherigen Haltepunkte, und stellen Sie sicher, dass der Debugger an den Ziel-PC angeschlossen ist.

  4. Wenn der Code ausgeführt wird und die DebugBreak-Anweisung erreicht ist, wird die Ausführung gestoppt, und eine Meldung wird angezeigt.

    KERNELBASE!DebugBreak:
    77b3b770 defe     __debugbreak
    

Abschnitt 8: Anzeigen von Variablen

In Abschnitt 8 verwenden Sie Debuggerbefehle zum Anzeigen von Variablen.

Es kann hilfreich sein, Variablen zu untersuchen, während der Code ausgeführt wird, um zu bestätigen, dass der Code wie erwartet funktioniert. In diesen Laboren werden Variablen untersucht, da der Audiotreiber Sound erzeugt.

  1. Verwenden Sie den dv-Befehl, um die Locale-Variablen zu untersuchen, die mit tabletaudiosample! CMiniportWaveRT::New* verknüpft sind.

    kd> dv tabletaudiosample!CMiniportWaveRT::New*
    
  2. Löschen Sie die vorherigen Haltepunkte

    bc *
    
  3. Legen Sie einen Symbolhaltepunkt für die CMiniportWaveCyclicStreamMSVAD-Routinen mithilfe des folgenden Befehls fest.

    0: kd> bm tabletaudiosample!CMiniportWaveRT::NewStream
      1: fffff801`177dffc0 @!"tabletaudiosample!CMiniportWaveRT::NewStream"
    
  4. Starten Sie die Codeausführung im Zielsystem neu, indem Sie den Befehl g eingeben.

  5. -> Auf dem Zielsystem

    Suchen Sie eine kleine Mediendatei (z. B. windows-Benachrichtigungssounddatei mit einer .wav Dateierweiterung), und wählen Sie die Datei aus, um sie wiederzugeben. Sie können z. B. Ring05.wav im Windows\Media-Verzeichnis verwenden.

  6. <- Auf dem Hostsystem

    Wenn die Mediendatei abgespielt wird, sollte der Breakpoint aktiviert werden und die Ausführung des Treibercodes im Zielsystem angehalten werden.

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

    Das Quellcodefenster sollte die geschweifte Klammer auf dem Eingang zur NewStream-Funktion hervorheben.

    /*++
    
    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. Lokale Variablen

    Sie können die Namen und Werte aller lokalen Variablen für einen bestimmten Frame anzeigen, indem Sie den Befehl dv eingeben.

    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. Verwenden von DML zum Anzeigen von Variablen

    Um DML zum Untersuchen von Variablen zu verwenden, wählen Sie die unterstrichenen Elemente aus. Die Auswahlaktion erstellt einen Dx-Befehl (NatVis-Ausdruck anzeigen), mit dem Sie einen Drilldown für geschachtelte Datenstrukturen ausführen können.

    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. Globale Variablen

    Sie können den Speicherort einer globalen Variablen durch Eingabe finden ? <Variablenname>.

    0: kd> ? signalProcessingMode
    Evaluate expression: -52768896396472 = ffffd001`c8acd348
    
  10. Dadurch wird der Speicherort der Variablen zurückgegeben, in diesem Fall ffffd001'c8acd348. Sie können den Inhalt des Speicherorts anzeigen, indem Sie den dd-Befehl verwenden und den Wert dieses Speicherorts dumpen, der vom vorherigen Befehl zurückgegeben wurde.

    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. Sie können auch Variablennamen mit dem Befehl "dd " verwenden.

    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. Anzeigen von Variablen

    Verwenden Sie das Menüelement "Lokalanzeigen>", um lokale Variablen anzuzeigen. Diese Schnittstelle bietet auch diese Möglichkeit, einen Drilldown zu komplexeren Datenstrukturen zu erstellen.

    WinDbg-Schnittstelle mit Beispielcode, lokalen Variablen und Befehlsfenstern.

  13. Verwenden Sie p oder F10, um im Code etwa 10 Zeilen vorwärts zu schalten, bis Sie die Codezeile ntStatus = IsFormatSupported(Pin, Capture, DataFormat) hervorheben.

        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. Verwenden Sie den Dv-Befehl , um die Namen und Werte aller lokalen Variablen für einen bestimmten Frame anzuzeigen. Beachten Sie, dass sich die Werte wie erwartet von der letzten Ausführung dieses Befehls unterscheiden, da zusätzlicher Code ausgeführt wurde, der die lokalen Variablen ändert und einige Variablen sich jetzt nicht im aktuellen Frame befinden oder ihre Werte geändert wurden.

    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
    

Abschnitt 9: Anzeigen von Anrufstapeln

In Abschnitt 9 werden Aufrufstapel angezeigt, um den Anrufer-/Calle-Code zu untersuchen.

Der Aufrufstapel ist die Kette von Funktionsaufrufen, die zur aktuellen Position des Programmzählers geführt haben. Die oberste Funktion im Aufrufstapel ist die aktuelle Funktion, und die nächste Funktion ist die Funktion, die die aktuelle Funktion aufgerufen hat usw.

Verwenden Sie zum Anzeigen des Aufrufstapels die k*-Befehle:

KB

Zeigt den Stapel und die ersten drei Parameter an.

Kp

Zeigt die Stapel und die vollständige Liste der Parameter an.

Kn

Ermöglicht es Ihnen, den Stapel mit den Frameinformationen daneben anzuzeigen.

Wenn Sie den Anrufstapel verfügbar halten möchten, können Sie "Anruflisteanzeigen"> auswählen, um ihn anzuzeigen. Wählen Sie die Spalten am oberen Rand des Fensters aus, um die Anzeige zusätzlicher Informationen umzuschalten.

WinDbg-Schnittstelle, die das Aufrufstapelfenster anzeigt.

Diese Ausgabe zeigt den Aufrufstapel beim Debuggen des Beispieladaptercodes in einem Unterbrechungszustand an.

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

Sie können DML verwenden, um den Code weiter zu untersuchen. Wenn Sie den ersten 00-Eintrag auswählen, wird der Befehl ".frame" (Set Local Context) verwendet, um den Kontext festzulegen, und dann zeigt der Befehl dv (Lokale Variablen anzeigen) die lokalen Variablen an.

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

Abschnitt 10: Anzeigen von Prozessen und Threads

In Abschnitt 10 verwenden Sie Debuggerbefehle zum Anzeigen von Prozessen und Threads.

Prozess

Verwenden Sie den <Prozess>befehl, um den aktuellen Prozesskontext zu ändern. Im folgenden Beispiel wird veranschaulicht, wie Sie einen Prozess identifizieren und den Kontext zu diesem wechseln.

  • Verwenden Sie den !process Befehl, um den aktuellen Prozess anzuzeigen, der an der Wiedergabe des Sounds beteiligt ist.

    Weitere Informationen finden Sie unter !process

Die Ausgabe zeigt, dass der Prozess audiodg.exezugeordnet ist. Wenn Sie sich noch an dem im vorherigen Abschnitt beschriebenen Haltepunkt befinden, sollte der aktuelle Prozess dem audiodg.exe Image zugeordnet sein.

<- Auf dem Hostsystem

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

Beachten Sie, dass sich einer der Threads, die diesem Prozess zugeordnet sind, im Zustand "RUNNING" befindet. Dieser Thread unterstützte die Wiedergabe des Medienclips, als der Haltepunkt erreicht wurde.

Verwenden Sie den Befehl "!process 0 0" , um Zusammenfassungsinformationen für alle Prozesse anzuzeigen. Verwenden Sie in der Befehlsausgabe STRG+F, um die Prozess-ID für den Prozess zu suchen, der dem audiodg.exe Bild zugeordnet ist. Im folgenden Beispiel ist die Prozess-ID ffffe001d147c840.

Notieren Sie die Prozess-ID, die audiodg.exe auf Ihrem PC zugeordnet ist, für die spätere Verwendung in dieser Übung. ________________________

...

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

Geben Sie g in den Debugger ein, um den Code vorwärts auszuführen, bis die Wiedergabe des Medienclips abgeschlossen ist. Steppen Sie dann in den Debugger ein, indem Sie "Ctrl+ScrLk" (Strg+Umbruch) drücken. Benutzen Sie den Befehl "!process", um zu bestätigen, dass Sie jetzt einen anderen Prozess ausführen.

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

Die obige Ausgabe zeigt, dass ein anderer Systemprozess von ffffe001cd0ad040 ausgeführt wird. Der Bildname zeigt 'System', nicht 'audiodg.exe'.

Verwenden Sie nun den Befehl "!process", um zu dem Prozess zu wechseln, der audiodg.exezugeordnet war. Im Beispiel ist die Prozess-ID ffffe001d147c840. Ersetzen Sie die Prozess-ID im Beispiel durch Ihre Prozess-ID, die Sie zuvor aufgezeichnet haben.

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.

Da dieser Code nicht aktiv ist, befinden sich alle Threads erwartungsgemäß im WAIT-Zustand.

Threads

Die Befehle zum Anzeigen und Festlegen von Threads sind denen von Prozessen sehr ähnlich. Verwenden Sie den Befehl "!thread ", um Threads anzuzeigen. Verwenden Sie THREAD , um die aktuellen Threads festzulegen.

Um die mit dem Medienplayer verbundenen Threads zu erkunden, spielen Sie den Medienclip erneut ab. Wenn der im vorherigen Abschnitt beschriebene Haltepunkt noch vorhanden ist, halten Sie im Kontext von audiodg.exean.

Verwenden Sie den !thread--1 0, um kurze Informationen für den aktuellen Thread anzuzeigen. Dies zeigt die Threadadresse, die Thread- und Prozess-IDs, die TEB-Adresse (Threadumgebungsblock), die Adresse der Win32-Funktion (falls vorhanden) des Threads, der ausgeführt werden soll, und den Planungszustand des Threads.

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

Wenn Sie weitere Informationen zum ausgeführten Thread anzeigen möchten, geben Sie !thread ein. Informationen, die den folgenden Angaben ähneln, sollten angezeigt werden.

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

Verwenden Sie den Befehl k, um den dem Thread zugeordneten Aufrufstapel anzuzeigen.

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

Geben Sie g in den Debugger ein, um den Code vorwärts auszuführen, bis die Wiedergabe des Medienclips abgeschlossen ist. Unterbrechen Sie dann den Debugger, indem Sie STRG - ScrLk (Ctrl-Break) Drücken Sie den Befehl "!thread", um zu bestätigen, dass Sie jetzt einen anderen Thread ausführen.

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

Der Bildname ist rundll32.exe, was tatsächlich nicht der Bildname ist, der mit der Wiedergabe des Medienclips verknüpft ist.

Anmerkung Geben Sie zum Festlegen des aktuellen Threads die THREAD-Nummer <>ein.

Weitere Informationen zu Threads und Prozessen finden Sie in den folgenden Verweisen:

Threads und Prozesse

Ändern von Kontexten

Abschnitt 11: IRQL, Register und Demontage

Anzeigen des gespeicherten IRQL

In Abschnitt 11 zeigen Sie die IRQL und den Inhalt der Regsisters an.

<- Auf dem Hostsystem

Die Interruptanforderungsebene (IRQL) wird verwendet, um die Priorität des Unterbrechungsdienstes zu verwalten. Jeder Prozessor verfügt über eine IRQL-Einstellung, die Threads erhöhen oder senken können. Unterbrechungen, die bei oder unter der IRQL-Einstellung des Prozessors auftreten, sind maskiert und beeinträchtigen den aktuellen Vorgang nicht. Unterbrechungen, die oberhalb der IRQL-Einstellung des Prozessors auftreten, haben Vorrang vor dem aktuellen Vorgang. Die Erweiterung !irql zeigt die Interruptanforderungsebene (IRQL) auf dem aktuellen Prozessor des Zielcomputers an, bevor der Debuggerbruch aufgetreten ist. Wenn der Zielcomputer in den Debugger wechselt, ändert sich die IRQL, aber die IRQL, die unmittelbar vor dem Debuggerumbruch wirksam war, wird gespeichert und von !irql angezeigt.

0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)

< Anzeigen der Register und Demontage

Anzeigen der Register

Zeigen Sie den Inhalt der Register für den aktuellen Thread auf dem aktuellen Prozessor mithilfe des Befehls r (Registers) an.

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

Alternativ können Sie den Inhalt der Register anzeigen, indem Sie "Registeranzeigen"> auswählen.

Screenshot des WinDbg-Register-Fensters mit ungefähr 12 Registern.

Das Anzeigen der Inhalte der Register kann hilfreich sein, wenn Sie die Ausführung von Assemblysprachencode und in anderen Szenarien durchlaufen. Weitere Informationen finden Sie unter r (Register).

Informationen zum Inhalt des Registers finden Sie unter x86 Architecture and x64 Architecture.

Demontage

Sie können den Code, der ausgeführt wird, zerlegen, um den Assemblysprachencode anzuzeigen, der ausgeführt wird, indem Sie "Zerlegen anzeigen"> auswählen.

Screenshot des WinDbg-Demontagefensters mit Assemblysprachencode.

Weitere Informationen über das Disassemblieren von Assemblysprachen finden Sie in "Annotated x86 Disassembly" und "Annotated x64 Disassembly".

Abschnitt 12: Arbeiten mit Arbeitsspeicher

In Abschnitt 12 verwenden Sie Debuggerbefehle, um den Inhalt des Arbeitsspeichers anzuzeigen.

Speicher anzeigen

Möglicherweise müssen Sie den Speicher untersuchen, um ein Problem zu identifizieren oder Variablen, Zeiger usw. zu überprüfen. Sie können Arbeitsspeicher anzeigen, indem Sie einen der folgenden d* <-Adressbefehle> eingeben.

Datenbank

Zeigt Daten in Bytewerten und ASCII-Zeichen an.

Dd

Zeigt Daten als doppelte breite Wörter an (4 Byte).

du

Zeigt Daten als Unicode-Zeichen an.

DW

Zeigt Daten als Wortwerte (2 Bytes) und ASCII-Zeichen an.

Anmerkung Wenn Sie versuchen, eine ungültige Adresse anzuzeigen, werden deren Inhalte als Fragezeichen (?) angezeigt.

Alternativ können Sie den Speicher anzeigen, indem Sie "Speicheranzeigen"> auswählen. Verwenden Sie das Dropdown-Menü für das Anzeigeformat, um die Darstellung des Arbeitsspeichers anzupassen.

Screenshot des WinDbg-Ansichtsspeicherfensters mit verschiedenen Anzeigeformatoptionen.

  1. Um Daten anzuzeigen, die dem Volumesteuerelement zugeordnet sind, legen Sie einen Haltepunkt fest, der mithilfe des bm-Befehls in der PropertyHandlerAudioEngineVolumeLevel-Routine ausgelöst wird. Bevor wir den neuen Haltepunkt festlegen, werden alle vorherigen Haltepunkte mithilfe von bc *gelöscht.

    kd> bc *
    
  2. Legen Sie einen Haltepunkt fest, der mithilfe des BM-Befehls in der PropertyHandlerAudioEngineVolumeLevel-Routine ausgelöst wird.

    kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  3. Listen Sie die Haltepunkte auf, um zu bestätigen, dass der Haltepunkt ordnungsgemäß festgelegt ist.

    kd> bl
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  4. Verwenden Sie den Befehl g , um die Codeausführung neu zu starten.

    Passen Sie auf dem Zielsystem die Lautstärke in der Taskleiste an. Dadurch wird der Haltepunkt ausgelöst.

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume:
    fffff80f`02c3a4b0 44894c2420      mov     dword ptr [rsp+20h],r9d
    
  5. Verwenden Sie das Menüelement "Lokalanzeigen>", um lokale Variablen anzuzeigen. Notieren Sie sich den aktuellen Wert der IVolume-Variablen.

  6. Sie können den Datentyp und den aktuellen Wert für die IVolume-Variable im Beispielcode anzeigen, indem Sie den Befehl dt und den Namen der Variablen eingeben.

    kd> dt lVolume
    Local var @ 0xa011ea50 Type long
    0n-6291456
    
  7. Der Haltepunkt wird beim Eingeben von SetDeviceChannelVolume erreicht.

    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. Versuchen Sie, den Wert an der Speicherposition von IVolume mithilfe des Befehls dt (Anzeigetyp) anzuzeigen.

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

    Da die Variable noch definiert werden muss, enthält sie keine Informationen.

  9. Drücken Sie F10, um zur letzten Codezeile in SetDeviceChannelVolume weiterzuleiten.

        return ntStatus;
    
  10. Zeigen Sie den Wert an der Speicherposition von IVolume mithilfe des Befehls dt (Anzeigetyp) an.

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

    Nachdem die Variable aktiv ist, wird in diesem Beispiel ein Wert von 6291456 angezeigt.

  11. Sie können auch den Speicherort von IVolume mithilfe des ? (Ausdruck auswerten) Befehls anzeigen lassen.

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  12. Die angezeigte Adresse ffffb780'b7ee664 ist die Adresse der Variablen "lVolume". Verwenden Sie den dd-Befehl, um den Inhalt des Arbeitsspeichers an diesem Speicherort anzuzeigen.

    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. Sie können die ersten vier Bytes einer Adresse anzeigen, indem Sie den Bereichsparameter L4 angeben.

    kd> dd ffffb780`b7eee664 l4
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    
  14. Um die verschiedenen Arten der angezeigten Speicherausgabe anzuzeigen, geben Sie die Befehle "du", "da " und "db " ein.

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

    Verwenden Sie die df-Float-Option, um Daten als Gleitkommazahlen mit einfacher Genauigkeit (4-Byte) darzustellen.

    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
    

Schreiben in den Arbeitsspeicher

Ähnlich wie bei den Befehlen, die zum Lesen des Arbeitsspeichers verwendet werden, können Sie die e*-Befehle verwenden, um den Speicherinhalt zu ändern.

Befehl BESCHREIBUNG

Stck

ASCII-Zeichenfolge (nicht NULL-terminiert)

EU

Unicode-Zeichenfolge (nicht NULL-beendet)

Ew

Word-Werte (2 Bytes)

eza

NULL-beendete ASCII-Zeichenfolge

ezu

UNICODE-Zeichenfolge mit NULL-Beendigung

eb

Bytewerte

ed

Double-Word-Werte (4 Bytes)

Das folgende Beispiel zeigt, wie Speicher überschrieben wird.

  1. Suchen Sie zunächst die Adresse des lVolume, das im Beispielcode verwendet wird.

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  2. Überschreiben Sie diese Speicheradresse mit neuen Zeichen mithilfe des Eb-Befehls .

    kd> eb 0xffffb780`b7eee664 11 11 11 11 11
    
  3. Zeigen Sie den Speicherspeicherort an, um zu bestätigen, dass die Zeichen durch Eingabe des Db-Befehls überschrieben wurden.

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

Alternativ können Sie den Inhalt des Speichers in einem Überwachungs- oder Lokalfenster ändern. Für das Überwachungsfenster werden möglicherweise Variablen angezeigt, die nicht im aktuellen Framekontext liegen. Das Ändern dieser Elemente ist nicht relevant, wenn sie nicht im Kontext enthalten sind.

Abschnitt 13: Beenden der WinDbg-Sitzung

<-Auf dem Hostsystem

Wenn Sie den Debugger angefügt lassen möchten, aber am Ziel arbeiten möchten, löschen Sie alle Haltepunkte mit bc *, damit der Zielcomputer nicht versucht, eine Verbindung mit dem Hostcomputer-Debugger herzustellen. Verwenden Sie dann den g Befehl, damit der Zielcomputer erneut ausgeführt werden kann.

Um die Debugsitzung zu beenden, brechen Sie im Hostsystem in den Debugger auf, und geben Sie den qd Befehl (Beenden und Trennen) ein, oder wählen Sie " Debuggen beenden" aus dem Menü aus.

0: kd> qd

Weitere Informationen finden Sie unter Beenden einer Debugsitzung in WinDbg (Klassisch) in der Debugreferenzdokumentation.

Abschnitt 14: Windows-Debuggingressourcen

Weitere Informationen finden Sie im Windows-Debugging. Beachten Sie, dass einige dieser Bücher ältere Versionen von Windows wie Windows Vista in ihren Beispielen verwenden, aber die behandelten Konzepte gelten für die meisten Versionen von Windows.

Bücher

  • Erweitertes Windows Debugging von Mario Hewardt und Daniel Pravat

  • Inside Windows Debugging: Eine praktische Anleitung zum Debuggen und Tracing von Strategien in Windows® von Tarik Soulami

  • Windows Internals von Pavel Yosifovich, Alex Ionescu, Mark Russinovich und David Salomon

Video

Die Defrag-Tools Zeigen WinDbg Episoden 13-29: </shows/defrag-tools/>

Schulungsanbieter:

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

Siehe auch

Erste Schritte mit Dem Windows-Debugging