Freigeben über


Schritt-für-Schritt-Lab zum Debuggen von Windows-Treibern (Echo-Kernelmodus)

In diesem Lab wird der Kerneldebugger WinDbg vorgestellt. Sie verwenden WinDbg zum Debuggen des Besipielcodes des Echo-Kernelmodus.

Lab-Ziele

Dieses Lab umfasst Übungen, die die Debugging-Tools vorstellen, gängige Debugging-Befehle lehren, die Verwendung von Haltepunkten veranschaulichen und zeigen, wie man die Debugging-Erweiterungen verwendet.

In diesem Labor verwenden Sie eine Live-Kernel-Debugverbindung, um die folgenden Aktivitäten zu untersuchen.

  • Verwenden Sie die Windows-Debuggerbefehle
  • Verwenden Sie Standardbefehle (Aufrufstapel, Variablen, Threads, IRQL)
  • Verwenden Sie erweiterte Treiber-Debugging-Befehle (!commands)
  • Verwenden von Symbolen
  • Setzen von Haltepunkten beim Livedebugging
  • Anzeigen von Aufrufstapeln
  • Anzeigen der Plug-and-Play-Gerätestruktur
  • Arbeiten mit Thread- und Prozesskontext

Debuggen im Benutzer- und Kernelmodus

Beim Arbeiten mit dem Windows-Debugger können Sie zwei Arten von Debugging ausführen:

Benutzermodus - Anwendungen und Subsysteme werden auf dem Computer im Benutzermodus ausgeführt. Prozesse, die im Benutzermodus ausgeführt werden, tun dies innerhalb ihrer eigenen virtuellen Adressräume. Sie sind daran eingeschränkt, direkten Zugriff auf viele Teile des Systems zu erhalten, einschließlich Systemhardware, Arbeitsspeicher, der nicht für die Verwendung zugeordnet ist, und andere Teile des Systems, die die Systemintegrität beeinträchtigen könnten. Da Prozesse, die im Benutzermodus ausgeführt werden, effektiv vom System und anderen Benutzermodusprozessen isoliert sind, können sie diese Ressourcen nicht beeinträchtigen.

Kernelmodus – Das Betriebssystem und privilegierte Programme werden im Kernelmodus ausgeführt. Der Kernelmoduscode verfügt über die Berechtigung, auf jeden beliebigen Systembereich zuzugreifen. Er ist nicht eingeschränkt wie der Code im Benutzermodus. Er kann Zugriff auf einen beliebigen Teil eines anderen Prozesses erhalten, der entweder im Benutzermodus oder im Kernelmodus ausgeführt wird. Ein Großteil der Kernfunktionen des Betriebssystems und viele Hardwaregerätetreiber werden im Kernelmodus ausgeführt.

In dieser Übung werden Debugbefehle behandelt, die häufig sowohl im Benutzermodus als auch beim Kernelmodusdebugging verwendet werden. Die Übung behandelt auch Debug-Erweiterungen, manchmal auch „bang“-!commands genannt, die für das Debugging im Kernel-Modus verwendet werden.

Setup der Übungsumgebung

Sie benötigen die folgende Hardware, um das Labor abzuschließen:

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

Sie benötigen die folgende Software, um das Labor abzuschließen:

  • Visual Studio
  • Windows Software Development Kit (SDK) für Windows 10
  • Windows Driver Kit (WDK) für Windows 10
  • Den Echo-Beispieltreiber für Windows 10

Das Labor hat die folgenden Abschnitte:

Verbindung zu einer WinDbg-Sitzung im Kernelmodus

Konfigurieren Sie in diesem Abschnitt das Netzwerkdebugging auf dem Host- und Zielsystem.

Die Computer in diesem Labor müssen für die Verwendung einer Ethernet-Netzwerkverbindung zum Kernel-Debugging konfiguriert werden.

In diesem Labor werden zwei Computer verwendet. Der Windows-Debugger wird auf dem Hostsystem ausgeführt, und der Echo-Treiber Kernel Mode Driver Framework (KMDF) wird auf dem Zielsystem ausgeführt.

Verwenden Sie einen Netzwerkhub oder Router und Netzwerkkabel, um die beiden Computer zu verbinden.

Diagramm mit zwei Computern, die über einen Netzwerkhub oder 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 (Kernelmodus). Weitere Informationen zum Einrichten des Zielcomputers finden Sie unter Vorbereiten eines Computers für die manuelle Treiberbereitstellung und Automatische Einrichtung des KDNET-Netzwerk-Kernel-Debuggings.

Konfigurieren des Kernelmodusdebuggings mithilfe von Ethernet

So aktivieren Sie das Kernelmodusdebugging auf dem Zielsystem:

  1. Öffnen Sie im Hostsystem ein Eingabeaufforderungsfenster und geben Sie ipconfig ein, um seine IPv4-Adresse zu ermitteln.

    Windows IP Configuration
    Ethernet adapter Ethernet:
       Connection-specific DNS Suffix  . :
       Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b%3
       Autoconfiguration IPv4 Address. . : 169.182.1.1
       Subnet Mask . . . . . . . . . . . : 255.255.0.0
       Default Gateway . . . . . . . . . :
    
  2. Notieren Sie die IP-Adresse des Hostsystems: ______________________________________

  3. Öffnen Sie im Zielsystem ein Eingabeaufforderungsfenster, und verwenden Sie den Befehl ping, um die Netzwerkkonnektivität zwischen den beiden Systemen zu bestätigen.

    ping 169.182.1.1
    

    Verwenden Sie die tatsächliche IP-Adresse des Hostsystems, die Sie aufgezeichnet haben, anstelle von 169.182.1.1, die in der Beispielausgabe angezeigt wird.

    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
    

Aktivieren Sie das Debuggen im Kernelmodus auf dem Zielsystem, indem Sie die folgenden Schritte ausführen.

Wichtig

Bevor Sie BCDEdit verwenden, um Startinformationen zu ändern, müssen Sie möglicherweise vorübergehend Windows-Sicherheitsfeatures wie BitLocker und sicherer Start auf dem Testcomputer anhalten. Aktivieren Sie diese Sicherheitsfeatures nach Abschluss des Tests erneut. Verwalten Sie den Testcomputer entsprechend, wenn die Sicherheitsfeatures deaktiviert sind. Der sichere Start ist in der Regel in UEFI deaktiviert. Um auf die UEFI-Einstellungen zuzugreifen, gehen Sie zu System, Wiederherstellung, Erweiterte Startoptionen. Wählen Sie beim Neustart die Option "Problembehandlung", "Erweiterte Optionen", "UEFI-Firmwareeinstellungen" aus. Seien Sie vorsichtig, da falsches Einstellen von UEFI-Optionen oder das Deaktivieren von BitLocker das System unbrauchbar machen kann.

  1. Öffnen Sie auf dem Zielcomputer ein Eingabeaufforderungsfenster als Administrator. Geben Sie diesen Befehl ein, um das Debuggen zu aktivieren:

    bcdedit /set {default} DEBUG YES
    
  2. Geben Sie diesen Befehl ein, um die Testsignierung zu aktivieren:

    bcdedit /set TESTSIGNING ON 
    
  3. Geben Sie diesen Befehl ein, um die IP-Adresse des Hostsystems festzulegen. Verwenden Sie die IP-Adresse des Zuvor aufgezeichneten Hostsystems, nicht die angezeigte.

    bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    

    Warnung

    Um die Sicherheit der Verbindung zu erhöhen und das Risiko der zufälligen Clientdebuggerverbindungsanforderungen zu verringern, verwenden Sie einen automatisch generierten Zufallsschlüssel. Weitere Informationen finden Sie unter Automatisches Einrichten des KDNET-Netzwerkkernen-Debuggings.

  4. Geben Sie diesen Befehl ein, um zu bestätigen, dass die Werte für dbgsettings ordnungsgemäß festgelegt sind:

    bcdedit /dbgsettings
    
    key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    debugtype               NET
    hostip                  169.168.1.1
    port                    50000
    dhcp                    Yes
    The operation completed successfully.
    

    Anmerkung

    Wenn Sie eine Nachricht von der Firewall erhalten und den Debugger verwenden möchten, wählen Sie alle drei Felder aus.

    Screenshot des Dialogfelds

  5. Öffnen Sie auf dem Host-Computer ein Eingabeaufforderungsfenster als Administrator. In diesem Lab wird die x64-Version von WinDbg.exe aus dem Windows Driver Kit (WDK) verwendet, das als Teil der Windows-Kit-Installation installiert wurde. Wechseln Sie in das WinDbg-Standardverzeichnis, das unten abgebildet ist.

    cd C:\Program Files(x86)\Windows Kits\10\Debuggers\x64 
    

    In diesen Labs wird davon ausgegangen, dass beide Computer eine 64-Bit-Version von Windows sowohl auf dem Ziel als auch auf dem Host ausführen. Wenn das nicht der Fall ist, ist es am besten, die gleiche Bitanzahl von Tools auf dem Host auszuführen, die auch auf dem Zielsystem auszugeführt werden. Führen Sie beispielsweise bei einem Ziel, das 32-Bit-Windows ausführt, eine 32-Bit-Version des Debuggers auf dem Host aus. Weitere Informationen finden Sie unter Auswählen der 32-Bit- oder 64-Bit-Debugging-Tools.

  6. Öffnen Sie WinDbg mit Remotebenutzerdebug, indem Sie den folgenden Befehl verwenden. Die Werte für den Schlüssel und Port entsprechen den Werten, die Sie zuvor mithilfe von BCDEdit auf dem Zielcomputer festgelegt haben.

    WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  7. Starten Sie das Zielsystem neu.

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

    Microsoft (R) Windows Debugger Version 10.0.17074.1002 AMD64
    Copyright (c) Microsoft Corporation. All rights reserved.
    
    Using NET for debugging
    Opened WinSock 2.0
    Waiting to reconnect...
    Connected to target 169.182.1.1 on port 50005 on local IP 169.182.1.2
    You can get the target MAC address by running .kdtargetmac command.
    Connected to Windows 10 16299 x64 target at (Wed Feb 28 17:16:23.051 2018 (UTC - 8:00)), ptr64 TRUE
    Kernel Debugger connection established.  (Initial Breakpoint requested)
    Symbol search path is: srv*
    Executable search path is: 
    Windows 10 Kernel Version 16299 MP (4 procs) Free x64
    Product: WinNt, suite: TerminalServer SingleUserTS
    Built by: 16299.15.amd64fre.rs3_release.170928-1534
    Machine Name:
    Kernel base = 0xfffff800`9540d000 PsLoadedModuleList = 0xfffff800`95774110
    Debug session time: Wed Feb 28 17:16:23.816 2018 (UTC - 8:00)
    System Uptime: 0 days 0:00:20.534
    

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

Das Debugger-Befehlsfenster ist in zwei Bereiche unterteilt. Geben Sie Befehle im kleineren Bereich ein, bei dem es sich um den Befehlseingabebereich am unteren Rand des Fensters handelt, und zeigen Sie die Befehlsausgabe im größeren Bereich am oberen Rand des Fensters an.

Verwenden Sie im Befehlseingabebereich die Pfeil-nach-oben- und Pfeil-nach-unten-Tasten, um durch den Befehlsverlauf zu blättern. Wenn ein Befehl angezeigt wird, können Sie ihn bearbeiten oder die EINGABETASTE drücken, um den Befehl auszuführen.

Debuggingbefehle und -techniken für den Kernelmodus

Verwenden Sie in diesem Abschnitt Debugbefehle, um Informationen zum Zielsystem anzuzeigen.

Einige Debugbefehle zeigen Text mit Debugger Markup Language (DML) an, den Sie auswählen können, um schnell weitere Informationen zu sammeln.

  1. Verwenden Sie auf dem Hostsystem die Tastenkombination Strg+Rollen-Taste in WinDBg, um in den auf dem Zielsystem ausgeführten Code einzudringen. Es kann einige Zeit dauern, bis das Zielsystem reagiert.

    Der Hauptbildschirm des Debuggers zeigt die Ausgabe des Befehlsfensters bei einer Livekernelverbindung.

  2. Geben Sie den folgenden Befehl ein, um DML im Fenster "Debuggerbefehle" zu aktivieren:

    0: kd> .prefer_dml 1
    DML versions of commands on by default
    
  3. Sie können die Hilfe zu den Referenzbefehlen mit dem Befehl .hh aufrufen. Geben Sie den folgenden Befehl ein, um die Befehlsreferenzhilfe für .prefer_dmlanzuzeigen:

    0: kd> .hh .prefer_dml
    

    Die Hilfedatei des Debuggers zeigt die Hilfe für den Befehl .prefer_dml an.

    Screenshot der Debugger-Hilfeanwendung, die die Hilfe für den Befehl „.prefer-dml“ anzeigt.

  4. Um detaillierte Versionsinformationen auf dem Zielsystem anzuzeigen, geben Sie im WinDbg-Fenster den Befehl vertarget (Show Target Computer Version) ein:

    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
    
  5. Um zu überprüfen, ob Sie mit dem richtigen Kernelmodusprozess arbeiten, geben Sie das lm (Geladene Module auflisten) Befehl im WinDbg-Fenster ein, um die geladenen Module anzuzeigen:

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

    Ausgelassene Ausgaben sind in diesem Lab mit „...“ gekennzeichnet.

  6. Um detaillierte Informationen über ein bestimmtes Modul anzufordern, verwenden Sie die Option v (ausführlich (verbose)):

    0: Kd> lm v m tcpip
    Browse full module list
    start             end                 module name
    fffff801`09eeb000 fffff801`0a157000   tcpip      (no symbols)           
        Loaded symbol image file: tcpip.sys
        Image path: \SystemRoot\System32\drivers\tcpip.sys
        Image name: tcpip.sys
        Browse all global symbols  functions  data
        Timestamp:        Sun Nov 09 18:59:03 2014 (546029F7)
        CheckSum:         00263DB1
        ImageSize:        0026C000
        Translations:     0000.04b0 0000.04e4 0409.04b0 0409.04e4
    
    Unable to enumerate user-mode unloaded modules, Win32 error 0n30
    

    Es gibt keinen festgelegten Symbolpfad und geladene Symbole, sodass eingeschränkte Informationen im Debugger verfügbar sind.

Herunterladen und Erstellen des KMDF-Echo-Treibers

Laden Sie in diesem Abschnitt den KMDF-Echotreiber herunter, und erstellen Sie diesen.

Normalerweise arbeiten Sie mit Ihrem eigenen Treibercode, wenn Sie WinDbg verwenden. Um sich mit der Funktionsweise von WinDbg vertraut zu machen, wird in diesem Lab der Beispieltreiber „KMDF Template "Echo"“ verwendet. Der Quellcode ist verfügbar, um die Informationen zu verstehen, die in WinDbg angezeigt werden. Dieses Beispiel wird auch verwendet, um zu veranschaulichen, wie Sie in einem einzigen Schritt durch nativen Kernelmoduscode gehen können. Diese Technik kann für das Debuggen komplexer Kernelmodus-Codeprobleme hilfreich sein.

So laden Sie den Echo-Beispieltreiber herunter und erstellen ihn:

  1. Zunächst laden Sie das KMDF Echo Sample von GitHub herunter und extrahieren es.

    Das KMDF-Echo-Beispiel befindet sich im Ordner general.

    Screenshot der GitHub-Seite „Windows-driver-samples“ mit Hervorhebung des Ordners „general“ und der Schaltfläche „Download ZIP“.

    1. Laden Sie die Treiberbeispiele in einer ZIP-Datei herunter: Treiberbeispiele

    2. Laden Sie die ZIP-Datei auf Ihre lokale Festplatte herunter.

    3. Halten Sie die ZIP-Datei ausgewählt, oder klicken Sie mit der rechten Maustaste darauf und wählen Sie Alle extrahieren. Geben Sie einen neuen Ordner an, oder navigieren Sie zu einem vorhandenen Ordner, um die extrahierten Dateien zu speichern. Sie können z. B. C:\DriverSamples\ als neuen Ordner angeben, in den die Dateien extrahiert werden sollen.

    4. Wechseln Sie nach dem Extrahieren der Dateien zum folgenden Unterordner: C:\DriverSamples\general\echo\kmdf

  2. Wählen Sie in Microsoft Visual Studio Datei>Öffnen>Projekt/Projektmappe... aus, und wechseln Sie zu dem Ordner, der die extrahierten Dateien enthält, zum Beispiel C:\DriverSamples\general\echo\kmdf. Doppelklicken Sie auf die Lösungsdatei kmdfecho , um sie zu öffnen.

    Suchen Sie in Visual Studio den Projektmappen-Explorer. Falls dieses Fenster noch nicht geöffnet ist, wählen Sie Projektmappen-Explorer im Menü Ansicht aus. Im Projektmappen-Explorer sehen Sie eine Lösung, die drei Projekte umfasst.

    Screenshot von Visual Studio, das die aus dem kmdfecho-Projekt geladene Datei

  3. Legen Sie die Konfiguration und Plattform des Beispiels fest. Wählen Sie im Projektmappen-Explorer mit der rechten Maustaste oder durch Halten Solution 'kmdfecho' (3 projects) und wählen Sie Konfigurations-Manager aus. Stellen Sie sicher, dass die Konfigurations- und Plattformeinstellungen für die drei 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- oder Plattformänderungen für ein Projekt vornehmen, nehmen Sie die gleichen Änderungen für die verbleibenden drei Projekte vor.

  4. Treiberbeispiele müssen geändert werden, um Werte zu verwenden, die sich nicht mit vorhandenen Treibern überlappen. Unter Vom Beispielcode zum Produktionstreiber – Was in den Beispielen geändert werden soll erfahren Sie, wie Sie ein einzigartiges Treiberbeispiel erstellen, das mit den in Windows installierten echten Treibern koexistiert.

  5. Legen Sie die Laufzeitbibliothek fest. Öffnen Sie die Eigenschaftsseite des Echo-Treibers, und suchen Sie C/C++>Codegenerierung. Ändern Sie die Laufzeitbibliothek in Multi-Threaded Debug (/MTd). Weitere Informationen zu den Buildoptionen finden Sie unter /MD, /MT, /LD (Laufzeitbibliothek verwenden).

    Screenshot der Echo-Eigenschaftsseite in Visual Studio mit Hervorhebung der Einstellung für die Laufzeitbibliothek.

  6. Stellen Sie in den Treibereigenschaften sicher, dass Signieren von Treibern>Signaturmodus auf Testsignatur eingestellt ist.

    Screenshot der Echo-Eigenschaftsseite in Visual Studio mit Hervorhebung der Einstellung für den Signaturmodus.

  7. Wählen Sie in Visual Studio Erstellen>Projektmappe erstellen.

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

Tipp

Wenn eine Buildfehlermeldung auftritt, verwenden Sie die Buildfehlernummer, um einen Fix zu ermitteln. Zum Beispiel beschreibt MSBuild-Fehler MSB8040, wie man mit Bibliotheken arbeitet, die durch Spectre abgeschwächt wurden.

  1. Wechseln Sie im Datei-Explorer zu dem Ordner, der die extrahierten Dateien für das Beispiel enthält. Wechseln Sie beispielsweise zu C:\DriverSamples\general\echo\kmdf, 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 die Standardeinstellungen unverändert gelassen haben, werden die kompilierten Treiberdateien in einem Ordner namens \x64\Debug für einen 64-Bit-Debugbuild gespeichert.

    Wechseln Sie zu dem Ordner, der die erstellten Dateien für den Autosync-Treiber enthält: C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.

    Der Ordner sollte diese Dateien enthalten:

    Datei Beschreibung
    Echo.sys Die Treiberdatei.
    Echo.inf Eine Informationsdatei (INF), die Informationen enthält, die zum Installieren des Treibers erforderlich sind.

    Außerdem wurde die echoapp.exe Datei erstellt und sollte sich hier befinden: C:\DriverSamples\general\echo\kmdf\exe\x64\Debug.

    Datei Beschreibung
    EchoApp.exe Eine ausführbare Testdatei der Eingabeaufforderung, die mit dem Treiber „echo.sys“ kommuniziert.
  2. Suchen Sie einen USB-Stick oder richten Sie eine Netzwerkfreigabe ein, um die erstellten Treiberdateien und den Test EchoApp vom Host auf das Zielsystem zu kopieren.

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

Installieren des KMDF-Echo-Treiberbeispiels auf dem Zielsystem

Verwenden Sie in diesem Abschnitt das DevCon-Tool, um den Echo-Beispieltreiber zu installieren.

Der Computer, auf dem Sie den Treiber installieren, wird als Zielcomputer oder dem Testcomputerbezeichnet. Normalerweise ist dieser Computer von dem Computer getrennt, auf dem Sie das Treiberpaket entwickeln und erstellen. Der Computer, auf dem Sie den Treiber entwickeln und erstellen, wird als Hostcomputerbezeichnet.

Der Prozess des Verschiebens des Treiberpakets auf den Zielcomputer und der Installation des Treibers wird als Bereitstellen des Treibers bezeichnet.

Bereiten Sie vor der Bereitstellung eines signierten Testtreibers den Zielcomputer vor, indem Sie die Testsignierung aktivieren. Sie müssen auch das DevCon-Tool in Ihrer WDK-Installation finden und es auf das Zielsystem kopieren.

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

Aktivieren Sie auf dem Zielsystem die testsignierten Treiber:

  1. Öffnen Sie Windows-Einstellungen.

  2. Unter Update und Sicherheit, wählen Sie Wiederherstellung.

  3. Wählen Sie unter Erweiterter Start, Jetzt neu starten.

  4. Wenn der Computer neu startet, wählen Sie Startoptionen. Wählen Sie unter Windows 10 Problembehandlung>Erweiterte Optionen>Starteinstellungen und dann Neustart aus.

  5. Wählen Sie Durchsetzung der Treibersignatur deaktivieren aus, indem Sie die Taste F7 drücken.

  6. Starten Sie den Zielcomputer neu.

Rufen Sie auf dem Hostsystem den Ordner Tools in Ihrer WDK-Installation auf und suchen Sie das Tool DevCon. Suchen Sie beispielsweise im folgenden Ordner: C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe.

Erstellen Sie einen Ordner im Zielverzeichnis für das erstellte Treiberpaket, beispielsweise C:\EchoDriver. Kopieren Sie devcon.exe in das Zielsystem. Suchen Sie das .cer Zertifikat auf dem Hostsystem. Er befindet sich im gleichen Ordner auf dem Hostcomputer im Ordner, der die integrierten Treiberdateien enthält. Kopieren Sie alle Dateien aus dem zuvor auf dem Hostcomputer beschriebenen integrierten Treiber, und speichern Sie sie in dem Ordner, den Sie auf dem Zielcomputer erstellt haben.

Wählen Sie auf dem Zielcomputer die Zertifikatsdatei aus und halten Sie sie gedrückt, oder klicken Sie mit der rechten Maustaste darauf, und wählen Sie Installieren aus. Folgen Sie dann den Anweisungen, um das Testzertifikat zu installieren.

Ausführlichere Anweisungen zum Einrichten des Zielcomputers finden Sie unter Vorbereiten eines Computers für die manuelle Treiberbereitstellung.

Die folgenden Anweisungen zeigen, wie Sie den Beispieltreiber installieren und testen. Dies ist die allgemeine Syntax für das Devcon-Tool, das Sie zum Installieren des Treibers verwenden:

devcon install <INF file> <hardware ID>

Die FÜR die Installation dieses Treibers erforderliche INF-Datei ist echo.inf. Die INF-Datei enthält die Hardware-ID für die Installation von echo.sys. Für das Echo-Beispiel lautet die Hardware-ID root\ECHO.

Öffnen Sie auf dem Zielcomputer ein Eingabeaufforderungsfenster als Administrator. Wechseln Sie zu Ihrem Treiberpaketordner, und geben Sie den folgenden Befehl ein:

devcon install echo.inf root\ECHO

Wenn Sie die Fehlermeldung erhalten, dass devcon nicht erkannt wird, versuchen Sie, den Pfad zum devcon-Tool hinzuzufügen. Wenn Sie ihn beispielsweise in einen Ordner namens C:\Toolskopiert haben, versuchen Sie es mit dem folgenden Befehl:

c:\tools\devcon install echo.inf root\ECHO

Ein Dialogfeld mit der Information, dass der Testtreiber ein unsignierter Treiber ist, wird angezeigt. Wählen Sie Diesen Treiber trotzdem installieren, um fortzufahren.

Screenshot der Windows-Sicherheitswarnung, die besagt, dass Windows den Herausgeber der Treibersoftware 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

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

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 im Knoten Sample Device nach Sample WDF Echo Driver.

Screenshot der Struktur des Geräte-Managers mit Hervorhebung des WDF-Echo-Treibers.

Geben Sie echoapp ein, um die Echo-Test-App zu starten, um zu bestätigen, dass der Treiber funktionsfähig ist.

C:\Samples\KMDF_Echo_Sample> echoapp
DevicePath: \\?\root#sample#0005#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
512 Pattern Bytes Written successfully
512 Pattern Bytes Read successfully
Pattern Verified successfully
30720 Pattern Bytes Written successfully
30720 Pattern Bytes Read successfully
Pattern Verified successfully

Verwenden Sie WinDbg, um Informationen zum Treiber anzuzeigen.

Legen Sie in diesem Abschnitt den Symbolpfad fest, und verwenden Sie Kerneldebuggerbefehle, um Informationen zum KMDF-Echobeispieltreiber anzuzeigen.

Anzeigen von Informationen über den Treiber:

  1. Wenn Sie den Debugger geschlossen haben, öffnen Sie ihn auf dem Hostsystem erneut, indem Sie den folgenden Befehl im Fenster der Administrator-Eingabeaufforderung verwenden.

    WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Verwenden Sie die Tastenkombination Strg+Rollen-Taste in WinDBg, um in den auf dem Zielsystem ausgeführten Code einzudringen.

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

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

    0: kd> .sympath+ C:\DriverSamples\general\echo\kmdf
    0: kd> .reload /f
    

    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.

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.

Es gibt viele Ansätze, die zum Arbeiten mit Symbolen verwendet werden können. In vielen Situationen können Sie den Computer für den Zugriff auf Symbole von einem Symbolserver konfigurieren, den Microsoft bei Bedarf bereitstellt. Dieses Labor verwendet diesen Ansatz. 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.

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, wie die binären Anweisungen den Quellzeilen entsprechen. Die eigentlichen Quelldateien selbst müssen auch für den Debugger zugänglich sein.

Die Symboldateien enthalten nicht den Text des Quellcodes. Für das Debugging 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:

set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
  1. Geben Sie den folgenden Befehl im Befehlsbereich des Debuggers ein, um Informationen zum Echotreiber anzuzeigen:

    0: kd> lm m echo* v
    Browse full module list
    start             end                 module name
    fffff801`4ae80000 fffff801`4ae89000   ECHO       (private pdb symbols)  C:\Samples\KMDF_ECHO_SAMPLE\echo.pdb
        Loaded symbol image file: ECHO.sys
        Image path: \SystemRoot\system32\DRIVERS\ECHO.sys
        Image name: ECHO.sys
    ...  
    

    Weitere Informationen finden Sie unter lm.

  2. Da in diesem Labset zuvor prefer_dml festgelegt wurde, sind einige Elemente der Ausgabe Hotlinks, die Sie auswählen können. Wählen Sie den Link Browse all global symbols in der Debugausgabe, um Informationen über Elemente anzuzeigen, die mit dem Buchstaben „a“ beginnen.

    0: kd> x /D Echo!a*
    
  3. Das Echomuster enthält keine Symbole, die mit dem Buchstaben "a" beginnen. Geben Sie daher x ECHO!Echo* ein, um Informationen zu allen Symbolen anzuzeigen, die dem Echo-Treiber zugeordnet sind und mit "Echo" beginnen.

    0: kd> x ECHO!Echo*
    fffff801`0bf95690 ECHO!EchoEvtIoQueueContextDestroy (void *)
    fffff801`0bf95000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *)
    fffff801`0bf95ac0 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *)
    fffff801`0bf9b120 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *)
    ...
    

    Weitere Informationen finden Sie unter x (Symbole untersuchen).

  4. Die !lmi Erweiterung zeigt detaillierte Informationen zu einem Modul an. Geben Sie !lmi echoein. Ihre Ausgabe sollte dem in diesem Beispiel gezeigten Text ähnlich sein:

    0: kd> !lmi echo
    Loaded Module Info: [echo] 
             Module: ECHO
       Base Address: fffff8010bf94000
         Image Name: ECHO.sys
    … 
    
  5. Verwenden Sie die !dh-Erweiterung, um Kopfzeileninformationen anzuzeigen, wie in diesem Beispiel gezeigt:

    0: kd> !dh echo
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
         14C machine (i386)
           6 number of sections
    54AD8A42 time date stamp Wed Jan 07 11:34:26 2015
    ...
    
  6. Geben Sie Folgendes ein, um die standardmäßige Debugbitmaske so zu ändern, dass alle Debugmeldungen aus dem Zielsystem im Debugger angezeigt werden:

    0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
    

    Einige Treiber zeigen zusätzliche Informationen an, wenn die Maske von 0xFFFFFFFF verwendet wird. Setzen Sie die Maske auf 0x00000000, wenn Sie die Menge der angezeigten Informationen reduzieren möchten.

    0: kd> ed nt!Kd_DEFAULT_MASK 0x00000000
    

    Verwenden Sie den Befehl dd, um zu bestätigen, dass die Maske so eingestellt ist, dass alle Debuggermeldungen angezeigt werden.

    0: kd> dd nt!kd_DEFAULT_MASK 
    fffff802`bb4057c0  ffffffff 00000000 00000000 00000000
    fffff802`bb4057d0  00000000 00000000 00000000 00000000
    fffff802`bb4057e0  00000001 00000000 00000000 00000000
    fffff802`bb4057f0  00000000 00000000 00000000 00000000
    fffff802`bb405800  00000000 00000000 00000000 00000000
    fffff802`bb405810  00000000 00000000 00000000 00000000
    fffff802`bb405820  00000000 00000000 00000000 00000000
    fffff802`bb405830  00000000 00000000 00000000 00000000
    

Anzeigen von Plug-and-Play-Gerätestrukturinformationen

In diesem Abschnitt zeigen Sie Informationen über den Echo-Beispielgerätetreiber an und wo er sich in der Plug-and-Play-Gerätestruktur befindet.

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

Weitere Informationen über die Debugerweiterung für Geräteknoten finden Sie unter !devnode.

  1. Geben Sie im Hostsystem den Befehl !devnode 0 1 ein, um alle Geräteknoten im Plug-and-Play-Gerätebaum anzuzeigen.

    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 generierten Ausgabe nach dem Namen des Gerätetreibers zu suchen, echo.

    Screenshot des Dialogfelds „Suchen“ in WinDbg bei der Suche nach dem Begriff „echo“.

  3. Der Echo-Gerätetreiber sollte geladen sein. Verwenden Sie den Befehl !devnode 0 1 echo, um Plug-and-Play-Informationen anzuzeigen, die Ihrem Echo-Gerätetreiber zugeordnet sind, wie in diesem Beispiel gezeigt:

    0: Kd> !devnode 0 1 echo
    Dumping IopRootDeviceNode (= 0xffffe0007b725d30)
    DevNode 0xffffe0007b71a630 for PDO 0xffffe0007b71a960
      InstancePath is "ROOT\SAMPLE\0000"
      ServiceName is "ECHO"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
    …
    
  4. Die im vorherigen Befehl angezeigte Ausgabe enthält das PDO, das mit der laufenden Instanz Ihres Treibers verbunden ist, in diesem Beispiel 0xffffe0007b71a960. Geben Sie den Befehl !devobj <PDO address> ein, um Plug-and-Play-Informationen anzuzeigen, die dem Echo-Gerätetreiber zugeordnet sind. Verwenden Sie die PDO-Adresse, die !devnode auf Ihrem Computer anzeigt, nicht die hier angegebene.

    0: kd> !devobj 0xffffe0007b71a960
    Device object (ffffe0007b71a960) is for:
     0000000e \Driver\PnpManager DriverObject ffffe0007b727e60
    Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040
    Dacl ffffc102c9b36031 DevExt 00000000 DevObjExt ffffe0007b71aab0 DevNode ffffe0007b71a630 
    ExtensionFlags (0x00000800)  DOE_DEFAULT_SD_PRESENT
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe000801fee20 \Driver\ECHO
    Device queue is not busy.
    
  5. Die mit dem Befehl !devnode 0 1 angezeigte Ausgabe enthält die PDO-Adresse, die mit der laufenden Instanz Ihres Treibers verknüpft ist, in diesem Beispiel ist es 0xffffe0007b71a960. Geben Sie den Befehl !devstack <PDO address> ein, um Plug- und Play-Informationen anzuzeigen, die dem Gerätetreiber zugeordnet sind. Verwenden Sie die PDO-Adresse, die von !devnode auf Ihrem Computer angezeigt wird, nicht die in diesem Beispiel gezeigte.

    0: kd> !devstack 0xffffe0007b71a960
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe000801fee20  \Driver\ECHO       ffffe0007f72eff0  
    > ffffe0007b71a960  \Driver\PnpManager 00000000  0000000e
    !DevNode ffffe0007b71a630 :
      DeviceInst is "ROOT\SAMPLE\0000"
      ServiceName is "ECHO"
    

Die Ausgabe zeigt, dass Sie über einen relativ einfachen Gerätetreiberstapel verfügen. Der Echo-Treiber ist ein untergeordnetes Element des Knotens PnPManager. PnPManager ist ein Root-Knoten.

\Driver\ECHO
\Driver\PnpManager

Dieses Diagramm zeigt einen komplexeren Geräteknotenbaum.

Diagramm, das eine Geräteknotenstruktur veranschaulicht, die aus ca. 20 Knoten besteht.

Weitere Informationen über komplexere Treiberstapel finden Sie unter Treiberstapel und Geräteknoten und Gerätestapel.

Arbeiten mit Haltepunkten und Quellcode

In diesem Abschnitt setzen Sie Haltepunkte und gehen in Einzelschritten durch den Kernelmodus-Quellcode.

Damit Sie Code schrittweise durchlaufen und die Werte von Variablen in Echtzeit überprüfen können, aktivieren Sie Haltepunkte, und legen Sie einen Pfad zum Quellcode fest.

Haltepunkte beenden die Codeausführung in einer bestimmten Codezeile. Gehen Sie im Code von diesem Punkt aus weiter, um den spezifischen Abschnitt des Codes zu debuggen.

Um einen Haltepunkt mit einem Debugbefehl festzulegen, verwenden Sie einen der folgenden b-Befehle.

Befehl Beschreibung
bp Setzt einen Haltepunkt, der aktiv ist, bis das Modul, in dem er sich befindet, entladen wird.
bu Legt einen Haltepunkt fest, der beim Entladen des Moduls nicht aufgelöst wird, und aktiviert es erneut, wenn das Modul neu geladen wird.
bm Setzt einen Haltepunkt für ein Symbol. Dieser Befehl verwendet bu oder bp entsprechend und lässt die Verwendung von Platzhaltern (*) zu, um Haltepunkte für jedes übereinstimmende Symbol zu setzen, wie z. B. alle Methoden in einer Klasse.

Weitere Informationen finden Sie unter Quellcode-Debugging in WinDbg.

  1. Verwenden Sie auf dem Hostsystem die WinDbg-Benutzeroberfläche, um zu bestätigen, dass Debuggen>Quellmodus in der aktuellen WinDbg-Sitzung aktiviert ist.

  2. Geben Sie den folgenden Befehl ein, um den lokalen Code-Ort zum Quellpfad hinzuzufügen:

    .srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  3. Geben Sie den folgenden Befehl ein, um den lokalen Symbolstandort dem Symbolpfad hinzuzufügen:

    .sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  4. Verwenden Sie den Befehl x, um die mit dem Echo-Treiber verbundenen Symbole zu untersuchen und den Funktionsnamen für den Haltepunkt zu bestimmen. Sie können einen Platzhalter oder die Tastenkombination Strg+F verwenden, um den Funktionsnamen DeviceAdd zu finden.

    0: kd> x ECHO!EchoEvt*
    8b4c7490          ECHO!EchoEvtIoQueueContextDestroy (void *)
    8b4c7000          ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *)
    8b4c7820          ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *)
    8b4cb0e0          ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *)
    8b4c75d0          ECHO!EchoEvtIoWrite (struct WDFQUEUE__ *, struct WDFREQUEST__ *, unsigned int)
    8b4cb170          ECHO!EchoEvtDeviceAdd (struct WDFDRIVER__ *, struct 
    …
    

    Die Ausgabe zeigt, dass die DeviceAdd-Methode für Ihren Echo-Treiber ECHO!EchoEvtDeviceAdd ist.

    Alternativ können Sie auch den Quellcode überprüfen, um den Funktionsnamen für Ihren Haltepunkt zu finden.

  5. Setzen Sie den Haltepunkt mit dem Befehl bm . Geben Sie dabei den Namen des Treibers ein, gefolgt von dem Funktionsnamen, z. B. AddDevice, an dem Sie den Haltepunkt setzen wollen, getrennt durch ein Ausrufezeichen. In diesem Lab wird AddDevice verwendet, um das Laden des Treibers zu beobachten.

    0: kd> bm ECHO!EchoEvtDeviceAdd
      1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
    

    Sie können eine andere Syntax in Verbindung mit dem Setzen von Variablen wie <module>!<symbol>, <class>::<method>,'<file.cpp>:<line number>' verwenden oder <condition> <#> mehrmals überspringen. Weitere Informationen finden Sie unter Bedingte Haltepunkte in WinDbg und anderen Windows-Debuggern.

  6. Listen Sie die aktuellen Haltepunkte auf, um zu bestätigen, dass der Haltepunkt durch Eingabe des Befehls bl gesetzt wurde:

    0: kd> bl
    1 e fffff801`0bf9b1c0     0001 (0001) ECHO!EchoEvtDeviceAdd
    

    Das „e“ in der hier gezeigten Ausgabe zeigt an, dass der Haltepunkt Nummer 1 aktiviert ist und ausgelöst wird.

  7. Starten Sie die Codeausführung im Zielsystem neu, indem Sie den Befehl g (go) eingeben.

  8. Öffnen Sie auf dem Zielsystem unter Windows den Geräte-Manager über das Symbol oder durch Eingabe von mmc devmgmt.msc. Erweitern Sie im Geräte-Manager den Knoten Samples.

  9. Halten Sie den Eintrag für den KMDF-Echotreiber gedrückt, oder klicken Sie mit der rechten Maustaste darauf, und wählen Sie im Menü die Option Deaktivieren.

  10. Halten Sie den KMDF-Echo-Treibereintrag gedrückt, oder klicken Sie erneut mit der rechten Maustaste darauf, und wählen Sie im Menü die Option Aktivieren aus.

  11. Wenn der Treiber auf dem Hostsystem aktiviert ist, sollte der Debughaltepunkt AddDevice ausgelöst werden. Die Ausführung des Treibercodes im Zielsystem sollte angehalten werden. Wenn der Haltepunkt erreicht ist, sollte die Ausführung am Anfang der Routine AddDevice angehalten werden. Die Ausgabe des Debugbefehls zeigt Breakpoint 1 hit an.

    Screenshot von WinDbg mit Anzeige von lokalen Variablen und Befehlsfenstern des Beispielcodes.

  12. Gehen Sie den Code Zeile für Zeile durch, indem Sie den Befehl p eingeben oder F10 drücken, bis Sie das folgende Ende der Routine AddDevice erreichen. Das Klammerzeichen (}) ist wie abgebildet hervorgehoben.

    Screenshot des Codefensters mit hervorgehobenem Klammerzeichen am Anfang der AddDevice-Routine.

Überprüfen Sie im nächsten Abschnitt den Status der Variablen, nachdem der DeviceAdd-Code ausgeführt wurde.

Sie können vorhandene Haltepunkte mit den folgenden Befehlen ändern:

Befehl Beschreibung
bl Listet Haltepunkte auf.
bc Löscht einen Haltepunkt aus der Liste. Verwenden Sie bc *, um alle Haltepunkte zu löschen.
bd Deaktiviert einen Haltepunkt. Verwenden Sie bd *, um alle Haltepunkte zu deaktivieren.
be Aktiviert einen Haltepunkt. Verwenden Sie be *, um alle Haltepunkte zu aktivieren.

Alternativ dazu können Sie Haltepunkte auch auf der WinDbg-Benutzeroberfläche ändern.

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

ba <access> <size> <address> {options}
Option Beschreibung
e Ausführen: wenn die CPU einen Befehl von der Adresse abruft
r Lesen/Schreiben: wenn die CPU die Adresse liest oder schreibt
w Schreiben: wenn die CPU an die Adresse schreibt

Sie können immer nur vier Datenhaltepunkte gleichzeitig setzen. Es liegt an Ihnen, sicherzustellen, dass Sie Ihre Daten richtig ausrichten, um den Haltepunkt auszulösen. Wörter müssen auf Adressen enden, die durch 2 teilbar sind, Doppelwörter müssen durch 4 teilbar sein, und Vierfachwörter durch 0 oder 8.

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

ba r 4 0x0003f7bf0

Sie können die folgenden Befehle verwenden, um durch Ihren Code zu gehen, wobei die zugehörigen Tastaturkürzel in Klammern angegeben sind.

  • Break in (Strg+Break). Dieser Befehl unterbricht ein System, sofern es ausgeführt wird und mit WinDbg kommuniziert. Die Reihenfolge im Kerneldebugger ist Strg+C.
  • Ausführen bis Cursor (F7 oder Strg+F10). Platzieren Sie den Cursor in einem Quell- oder Disassemblierungsfenster an der Stelle, an der die Ausführung unterbrochen werden soll, und drücken Sie dann F7. Der Code wird bis zu diesem Punkt ausgeführt. Wenn der Ablauf der Codeausführung nicht den vom Cursor angezeigten Punkt erreicht, wird WinDbg nicht unterbrochen. Diese Situation kann auftreten, wenn eine IF-Anweisung nicht ausgeführt wird.
  • Ausführen (F5). Ausführen, bis ein Haltepunkt erreicht wird oder ein Ereignis wie eine Fehlerprüfung eintritt.
  • Schritt über (F10). Dieser Befehl veranlasst die Ausführung des Codes um jeweils eine Anweisung oder einen Befehl. Trifft man auf einen Aufruf, wird der Code über den Aufruf hinweg ausgeführt, ohne in die aufgerufene Routine einzutreten. Wenn die Programmiersprache C oder C++ ist und WinDbg sich im Quellmodus befindet, kann der Quellmodus mit Debug->Quellmodusaktiviert oder deaktiviert werden.
  • Einzelschritt (F11). Dieser Befehl entspricht dem „Schritt über“-Befehl, mit dem Unterschied, dass die Ausführung eines Aufrufs in die aufgerufene Routine geht.
  • Schritt bis zur nächsten Anweisung in der aufrufenden Funktion (Umschalt+F11). Dieser Befehl bewirkt, dass die Ausführung bis zur aktuellen Routine oder der aktuellen Stelle im Aufrufstapel läuft und dort beendet wird. Dieser Befehl ist nützlich, wenn Sie genug von der Routine gesehen haben.

Weitere Informationen finden Sie unter Quellcode-Debugging in WinDbg.

Anzeigen von Variablen und Call-Stacks

In diesem Abschnitt zeigen Sie Informationen zu Variablen und Aufrufstapeln an.

In diesem Lab wird davon ausgegangen, dass Sie bei der Routine AddDevice mit dem zuvor beschriebenen Verfahren angehalten haben. Um die hier gezeigte Ausgabe zu sehen, wiederholen Sie die zuvor beschriebenen Schritte, falls erforderlich.

Auf dem Hostsystem können Sie mit dem Menüpunkt anzeigen>lokal lokale Variablen anzeigen.

Screenshot von WinDbg mit dem Fenster mit den lokalen Variablen.

Um den Speicherort einer globalen Variablenadresse zu finden, geben Sie ? <variable name>ein.

  • Step out (Shift+F11): Dieser Befehl bewirkt, dass die Ausführung bis zur aktuellen Routine oder der aktuellen Stelle im Aufrufstapel läuft und dort beendet wird. Dies ist nützlich, wenn Sie genug von der Routine gesehen haben.

Weitere Informationen finden Sie unter Quellcodedebuggen in WinDbg (klassisch) in der Debugging-Referenzdokumentation.

Abschnitt 8: Anzeigen von Variablen und Aufrufstapeln

In Abschnitt 8 werden Sie Informationen über Variablen und Call-Stacks anzeigen.

In diesem Lab wird davon ausgegangen, dass Sie bei der Routine AddDevice mit dem zuvor beschriebenen Verfahren angehalten haben. Um die hier gezeigte Ausgabe zu sehen, wiederholen Sie die zuvor beschriebenen Schritte, falls erforderlich.

<- Auf dem Host-System

Variablen anzeigen

Verwenden Sie den Menüpunkt anzeigen>lokal, um lokale Variablen anzuzeigen.

Screenshot von WinDbg mit dem Fenster mit den lokalen Variablen.

Globale Variablen

Sie können den Speicherort der Adresse einer globalen Variable finden, indem Sie ? <Name der Variablen> eingeben.

Lokale Variablen

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

0: kd> dv
         Driver = 0x00001fff`7ff9c838
     DeviceInit = 0xffffd001`51978190
         status = 0n0

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 den Befehl „k*“.

Befehl Beschreibung
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 die Anzeige des Stapels mit den Frameinformationen daneben.
  1. Wenn Sie den Aufrufstapel auf dem Hostsystem verfügbar halten möchten, wählen Sie anzeigen>Aufrufstapel aus, um ihn anzuzeigen. Wählen Sie die Spalten am oberen Rand des Fensters aus, um die Anzeige zusätzlicher Informationen umzuschalten.

    Screenshot von WinDbg mit dem Fenster mit den Aufrufstapeln.

  2. Verwenden Sie den Befehl kn, um den Aufrufstapel beim Debuggen des Beispieladaptercodes in einem Unterbrechungszustand anzuzeigen.

    3: kd> kn
    # Child-SP          RetAddr           Call Site
    00 ffffd001`51978110 fffff801`0942f55b ECHO!EchoEvtDeviceAdd+0x66 [c:\Samples\kmdf echo sample\c++\driver\autosync\driver.c @ 138]
    01 (Inline Function) --------`-------- Wdf01000!FxDriverDeviceAdd::Invoke+0x30 [d:\wbrtm\minkernel\wdf\framework\shared\inc\private\common\fxdrivercallbacks.hpp @ 61]
    02 ffffd001`51978150 fffff801`eed8097d Wdf01000!FxDriver::AddDevice+0xab [d:\wbrtm\minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 72]
    03 ffffd001`51978570 fffff801`ef129423 nt!PpvUtilCallAddDevice+0x35 [d:\9142\minkernel\ntos\io\pnpmgr\verifier.c @ 104]
    04 ffffd001`519785b0 fffff801`ef0c4112 nt!PnpCallAddDevice+0x63 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 7397]
    05 ffffd001`51978630 fffff801`ef0c344f nt!PipCallDriverAddDevice+0x6e2 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 3390]
    ...
    

Der Aufrufstapel zeigt, dass der Kernel (nt) den Plug-and-Play-Code (PnP) aufruft, der den Treiberframework-Code (WDF) aufruft, der wiederum die Funktion des Echo-Treibers DeviceAdd aufruft.

Anzeigen von Prozessen und Threads

Zeigen Sie in diesem Abschnitt Informationen zu den Prozessen und Threads an, die im Kernelmodus ausgeführt werden.

Prozesse

Sie können Prozessinformationen mithilfe der !process Debuggererweiterung anzeigen oder festlegen. Setzen Sie einen Haltepunkt, um den Prozess zu untersuchen, der verwendet wird, wenn ein Ton abgespielt wird.

  1. Geben Sie auf dem Hostsystem den Befehl dv ein, um die mit der Routine EchoEvtIo verbundenen Gebietsschemavariablen zu prüfen:

    0: kd> dv ECHO!EchoEvtIo*
    ECHO!EchoEvtIoQueueContextDestroy
    ECHO!EchoEvtIoWrite
    ECHO!EchoEvtIoRead         
    
  2. Löschen Sie die vorherigen Haltepunkte mit bc *:

    0: kd> bc *  
    
  3. Legen Sie einen Symboltrennpunkt für die EchoEvtIo Routinen mithilfe des folgenden Befehls fest:

    0: kd> bm ECHO!EchoEvtIo*
      2: aade5490          @!”ECHO!EchoEvtIoQueueContextDestroy”
      3: aade55d0          @!”ECHO!EchoEvtIoWrite”
      4: aade54c0          @!”ECHO!EchoEvtIoRead”
    
  4. Listen Sie die Haltepunkte auf, um zu bestätigen, dass der Haltepunkt richtig gesetzt ist:

    0: kd> bl
    1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197]    0001 (0001) ECHO!EchoEvtIoQueueContextDestroy
    ...
    
  5. Geben Sie g ein, um die Codeausführung neu zu starten:

    0: kd> g
    
  6. Führen Sie auf dem Zielsystem das EchoApp.exe Treibertestprogramm aus.

  7. Wenn die Test-App ausgeführt wird, wird im Hostsystem die E/A-Routine des Treibers aufgerufen. Durch diesen Aufruf wird der Haltepunkt ausgelöst, und die Ausführung des Treibercodes auf dem Zielsystem wird angehalten.

    Breakpoint 2 hit
    ECHO!EchoEvtIoWrite:
    fffff801`0bf95810 4c89442418      mov     qword ptr [rsp+18h],r8
    
  8. Verwenden Sie den Befehl !process, um den aktuellen Prozess anzuzeigen, der an der Ausführung von echoapp.exebeteiligt ist:

    0: kd> !process
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 03c4    Peb: 7ff7cfec4000  ParentCid: 0f34
        DirBase: 1efd1b000  ObjectTable: ffffc001d77978c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000802c79f0 Vads 30 Clone 0 Private 135. Modified 5. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf270050
        ElapsedTime                       00:00:00.052
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (682, 50, 345) (2728KB, 200KB, 1380KB)
        PeakWorkingSetSize                652
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    688
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe00080e32080  Cid 03c4.0ec0  Teb: 00007ff7cfece000 Win32Thread: 0000000000000000 RUNNING on processor 1
    

    Die Ausgabe zeigt, dass der Prozess mit dem Thread echoapp.exe verbunden ist, der ausgeführt wurde, als Ihr Haltepunkt für das Treiberschreibereignis erreicht wurde. Weitere Informationen finden Sie unter !process.

  9. Verwenden Sie die !process 0 0, um Zusammenfassungsinformationen für alle Prozesse anzuzeigen. Verwenden Sie in der Ausgabe Strg+F, um die gleiche Prozessadresse für den Prozess zu finden, der dem echoapp.exe Bild zugeordnet ist. Im Beispiel ist die Prozessadresse ffffe0007e6a7780.

    ...
    
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 0f68    Peb: 7ff7cfe7a000  ParentCid: 0f34
        DirBase: 1f7fb9000  ObjectTable: ffffc001cec82780  HandleCount:  34.
        Image: echoapp.exe
    
    ...
    
  10. Notieren Sie die Prozess-ID, die mit echoapp.exe verknüpft ist, um sie später in diesem Labor zu verwenden. Sie können auch STRG+C verwenden, um die Adresse für die spätere Verwendung in den Kopierpuffer zu kopieren.

    _____________________________________________________(echoapp.exe Prozessadresse)

  11. Geben Sie g nach Bedarf in den Debugger ein, um den Code vorwärts auszuführen, bis echoapp.exe die Ausführung beendet hat. Es trifft den Haltepunkt im Lese- und Schreibereignis viele Male. Wenn echoapp.exe beendet ist, wechseln Sie in den Debugger, indem Sie Strg+Rollen (Strg+Unterbr) drücken.

  12. Verwenden Sie den Befehl !process, um zu bestätigen, dass Sie einen anderen Prozess ausführen. In der hier gezeigten Ausgabe unterscheidet sich der Prozess mit dem Imagewert von System vom Imagewert von Echo.

    1: kd> !process
    PROCESS ffffe0007b65d900
        SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
        DirBase: 001ab000  ObjectTable: ffffc001c9a03000  HandleCount: 786.
        Image: System
        VadRoot ffffe0007ce45930 Vads 14 Clone 0 Private 22. Modified 131605. Locked 64.
        DeviceMap ffffc001c9a0c220
        Token                             ffffc001c9a05530
        ElapsedTime                       21:31:02.516
    ...
    

    Die Ausgabe zeigt, dass ein Systemprozess ffffe0007b65d900 ausgeführt wurde, als Sie das Betriebssystem beendet haben.

  13. Verwenden Sie den Befehl !process, um die Prozess-ID zu ermitteln, die mit dem zuvor aufgezeichneten echoapp.exe-Prozess verbunden war. Geben Sie Ihre echoapp.exe Prozessadresse an, die Sie zuvor aufgezeichnet haben, anstelle der angegebenen Beispielprozessadresse in diesem Beispiel.

    0: kd> !process ffffe0007e6a7780
    TYPE mismatch for process object at 82a9acc0
    

    Das Prozessobjekt ist nicht mehr verfügbar, da der echoapp.exe Prozess nicht mehr ausgeführt wird.

Threads

Die Befehle zum Anzeigen und Festlegen von Threads ähneln den Befehlen für Prozesse. Verwenden Sie den Befehl !thread, um Threads anzuzeigen. Verwenden Sie .thread, um die aktuellen Threads festzulegen.

  1. Geben Sie im Hostsystem g in den Debugger ein, um die Codeausführung im Zielsystem neu zu starten.

  2. Führen Sie auf dem Zielsystem das Treibertestprogramm „EchoApp.exe“ aus.

  3. Auf dem Hostsystem wird der Haltepunkt erreicht und die Codeausführung angehalten.

    Breakpoint 4 hit
    ECHO!EchoEvtIoRead:
    aade54c0 55              push    ebp
    
  4. Um die laufenden Threads anzuzeigen, geben Sie !threadein. Informationen, die dem folgenden Beispiel ähneln, sollten angezeigt werden:

    0: kd>  !thread
    THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    IRP List:
        ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0008096c900       Image:         echoapp.exe
    ...
    

    Notieren Sie sich den Imagenamen von echoapp.exe. Das bedeutet, dass Sie den Thread betrachten, der der Test-App zugeordnet ist.

  5. Verwenden Sie den Befehl !process, um zu ermitteln, ob dieser Thread der einzige Thread ist, der im Prozess ausgeführt wird, der echoapp.exezugeordnet ist. Die Threadnummer des ausgeführten Threads im Prozess ist derselbe ausgeführte Thread, den der Befehl !thread anzeigt.

    0: kd> !process
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf5dc050
        ElapsedTime                       00:00:00.048
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (681, 50, 345) (2724KB, 200KB, 1380KB)
        PeakWorkingSetSize                651
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    686
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    
  6. Verwenden Sie den Befehl !process 0 0, um die Prozessadresse von zwei verwandten Prozessen zu finden und diese Prozessadresse hier aufzuzeichnen.

    Cmd.exe: ____________________________________________________________

    EchoApp.exe: _______________________________________________________

    0: kd> !process 0 0 
    
    …
    
    PROCESS ffffe0007bbde900
        SessionId: 1  Cid: 0f34    Peb: 7ff72dfa7000  ParentCid: 0c64
        DirBase: 19c5fa000  ObjectTable: ffffc001d8c2f300  HandleCount:  31.
        Image: cmd.exe
    …
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
    …
    

    Alternativ können Sie !process 0 17 verwenden, um detaillierte Informationen zu jedem Prozess anzuzeigen. Die Ausgabe dieses Befehls kann sehr umfangreich sein. Die Ausgabe kann mit der Tastenkombination Strg+F durchsucht werden.

  7. Verwenden Sie den Befehl !process, um Prozessinformationen für beide Prozesse auf dem Computer auflisten. Geben Sie die Prozessadresse aus Ihrer !process 0 0-Ausgabe an, nicht die in diesem Beispiel gezeigte Adresse.

    Diese Beispielausgabe bezieht sich auf die Prozess-ID cmd.exe, die zuvor aufgezeichnet wurde. Der Bildname für diese Prozess-ID ist cmd.exe.

    0: kd>  !process ffffe0007bbde900
    PROCESS ffffe0007bbde900
        SessionId: 1  Cid: 0f34    Peb: 7ff72dfa7000  ParentCid: 0c64
        DirBase: 19c5fa000  ObjectTable: ffffc001d8c2f300  HandleCount:  31.
        Image: cmd.exe
        VadRoot ffffe0007bb8e7b0 Vads 25 Clone 0 Private 117. Modified 20. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001d8c48050
        ElapsedTime                       21:33:05.840
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         24656
        QuotaPoolUsage[NonPagedPool]      3184
        Working Set Sizes (now,min,max)  (261, 50, 345) (1044KB, 200KB, 1380KB)
        PeakWorkingSetSize                616
        VirtualSize                       2097164 Mb
        PeakVirtualSize                   2097165 Mb
        PageFaultCount                    823
        MemoryPriority                    FOREGROUND
        BasePriority                      8
        CommitCharge                      381
    
            THREAD ffffe0007cf34880  Cid 0f34.0f1c  Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
                ffffe0008096c900  ProcessObject
            Not impersonating
    ...
    

    Diese Beispielausgabe bezieht sich auf die echoapp.exe-Prozess-ID, die zuvor aufgezeichnet wurde.

    0: kd>  !process ffffe0008096c900
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf5dc050
        ElapsedTime                       00:00:00.048
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (681, 50, 345) (2724KB, 200KB, 1380KB)
        PeakWorkingSetSize                651
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    686
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
            IRP List:
                ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
            Not impersonating
    ...
    
  8. Notieren Sie hier die erste Threadadresse, die mit den beiden Prozessen verbunden ist.

    Cmd.exe: ____________________________________________________

    EchoApp.exe: _________________________________________________

  9. Verwenden Sie den Befehl !Thread, um Informationen zum aktuellen Thread anzuzeigen.

    0: kd>  !Thread
    THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    IRP List:
        ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0008096c900       Image:         echoapp.exe
    Attached Process          N/A            Image:         N/A
    ...
    

    Wie erwartet, ist der aktuelle Thread der Thread, der mit echoapp.exe verbunden ist, und er wird ausgeführt.

  10. Verwenden Sie den Befehl !Thread, um Informationen zum Thread anzuzeigen, der cmd.exe Prozess zugeordnet ist. Geben Sie die Threadadresse an, die Sie zuvor aufgezeichnet haben.

    0: kd> !Thread ffffe0007cf34880
    THREAD ffffe0007cf34880  Cid 0f34.0f1c  Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
        ffffe0008096c900  ProcessObject
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0007bbde900       Image:         cmd.exe
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      4134621        Ticks: 0
    Context Switch Count      4056           IdealProcessor: 0             
    UserTime                  00:00:00.000
    KernelTime                00:00:01.421
    Win32 Start Address 0x00007ff72e9d6e20
    Stack Init ffffd0015551dc90 Current ffffd0015551d760
    Base ffffd0015551e000 Limit ffffd00155518000 Call 0
    Priority 14 BasePriority 8 UnusualBoost 3 ForegroundBoost 2 IoPriority 2 PagePriority 5
    Child-SP          RetAddr           : Args to Child                                                           : Call Site
    ffffd001`5551d7a0 fffff801`eed184fe : fffff801`eef81180 ffffe000`7cf34880 00000000`fffffffe 00000000`fffffffe : nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109]
    ffffd001`5551d8e0 fffff801`eed17f79 : ffff03a5`ca56a3c8 000000de`b6a6e990 000000de`b6a6e990 00007ff7`d00df000 : nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347]
    ffffd001`5551d980 fffff801`eecea340 : ffffd001`5551da18 00000000`00000000 00000000`00000000 00000000`00000388 : nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619]
    ...
    

    Dieser Thread ist cmd.exe zugeordnet und befindet sich im Wartezustand.

  11. Geben Sie die Threadadresse des wartenden CMD.exe-Threads an, um den Kontext zu diesem wartenden Thread zu ändern.

    0: kd> .Thread ffffe0007cf34880
    Implicit thread is now ffffe000`7cf34880
    
  12. Verwenden Sie den Befehl k, um den Aufrufstapel anzuzeigen, der dem Wartethread zugeordnet ist.

    0: kd> k
      *** Stack trace for last set context - .thread/.cxr resets it
    # Child-SP          RetAddr           Call Site
    00 ffffd001`5551d7a0 fffff801`eed184fe nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109]
    01 ffffd001`5551d8e0 fffff801`eed17f79 nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347]
    02 ffffd001`5551d980 fffff801`eecea340 nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619]
    03 ffffd001`5551da00 fffff801`ef02e642 nt!KeWaitForSingleObject+0x2c0 [d:\9142\minkernel\ntos\ke\wait.c @ 683]
    ...
    

    Aufrufstapelelemente wie KiCommitThreadWait deuten darauf hin, dass dieser Thread nicht wie erwartet ausgeführt wird.

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

IRQL, Register und Beenden der WinDbg-Sitzung

In diesem Abschnitt werden die Unterbrechungsanforderungsebene (IRQL) und der Inhalt der Register angezeigt.

Anzeigen der gespeicherten IRQL

IRQL wird verwendet, um die Priorität der Unterbrechungsabarbeitung zu verwalten. Jeder Prozessor hat 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.

Auf dem Hostsystem zeigt die Erweiterung !irql die IRQL auf dem aktuellen Prozessor des Zielcomputers an, bevor die Debuggerunterbrechung auftrat. Wenn der Zielcomputer in den Debugger wechselt, ändert sich die IRQL, aber die IRQL, der kurz vor der Debuggerunterbrechung wirksam war, wird gespeichert und von !irql angezeigt.

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

Anzeigen der Register

Zeigen Sie auf dem Hostsystem 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 Anzeigen>Register auswählen. Weitere Informationen finden Sie unter r (Registers).

Die Anzeige der Registerinhalte kann beim schrittweisen Ausführen von Assemblysprachcode und in anderen Szenarien hilfreich sein. Weitere Informationen zur Disassemblierung der Assemblysprache finden Sie unter X86-Disassemblierung mit Anmerkungen und X64-Disassemblierung mit Anmerkungen.

Informationen zum Inhalt des Registers finden Sie unter x86-Architektur und x64-Architektur.

Beenden der WinDbg-Sitzung

Wenn Sie den Debugger angeschlossen lassen, aber am Ziel arbeiten wollen, löschen Sie alle Haltepunkte mit bc *, damit der Zielcomputer nicht versucht, eine Verbindung zum Debugger des Hostcomputers herzustellen. Verwenden Sie dann den Befehl g, damit der Zielcomputer erneut ausgeführt werden kann.

Um die Debuggingsitzung zu beenden, rufen Sie auf dem Hostsystem den Debugger auf und geben den Befehl qd (Quit and Detach) ein, oder wählen Sie im Menü die Option Debuggen beenden aus.

0: kd> qd

Weitere Informationen finden Sie unter Beenden einer Debugsitzung in WinDbg.

Windows-Debuggingressourcen

Weitere Informationen finden Sie unter Windows-Debugging. Einige dieser Bücher verwenden frühere Versionen von Windows wie Windows Vista in ihren Beispielen, aber die behandelten Konzepte gelten für die meisten Versionen von Windows.

Siehe auch