Laboratoire de débogage pas à pas des pilotes Windows (écho en mode noyau)

Ce laboratoire présente le débogueur de noyau WinDbg. Vous utilisez WinDbg pour déboguer le code source du pilote d’écho en mode noyau.

Objectifs du labo

Ce laboratoire comprend des exercices qui présentent les outils de débogage, enseignent les commandes de débogage courantes, illustrent l’utilisation des points d’arrêt et montrent comment utiliser les extensions de débogage.

Dans ce laboratoire, vous utilisez une connexion de débogage de noyau en direct pour explorer les actions suivantes :

  • Utiliser les commandes du débogueur Windows
  • Utiliser des commandes standard (piles d’appels, variables, threads, IRQL)
  • Utiliser des commandes de débogage de pilote avancées (!commands)
  • Utiliser des symboles
  • Définir des points d’arrêt en débogage en direct
  • Afficher les piles d’appels
  • Afficher l’arbre des périphériques Plug and Play
  • Travailler avec le contexte des threads et des processus

Débogage en mode utilisateur et en mode noyau

Lorsque vous travaillez avec le débogueur Windows, vous pouvez effectuer deux types de débogage :

Mode utilisateur : Les applications et sous-systèmes s’exécutent sur l’ordinateur en mode utilisateur. Les processus qui s’exécutent en mode utilisateur le font dans leurs propres espaces d’adresse virtuels. Ils ne peuvent pas accéder directement à de nombreuses parties du système, comme le matériel système, la mémoire qui n’est pas allouée à leur utilisation, et d’autres parties du système qui pourraient compromettre l’intégrité du système. Étant donné que les processus qui s’exécutent en mode utilisateur sont isolés du système et des autres processus en mode utilisateur, ils ne peuvent pas interférer avec ces ressources.

Mode noyau : Le système d’exploitation et les programmes privilégiés s’exécutent en mode noyau. Le code en mode noyau a l’autorisation d’accéder à n’importe quelle partie du système. Il n’est pas restreint comme le code en mode utilisateur. Il peut accéder à n’importe quelle partie de tout autre processus en cours d’exécution en mode utilisateur ou en mode noyau. Une grande partie de la fonctionnalité de base du système d’exploitation et de nombreux pilotes de périphérique s’exécutent en mode noyau.

Cet exercice couvre les commandes de débogage fréquemment utilisées lors du débogage en mode utilisateur et en mode noyau. L’exercice couvre également les extensions de débogage, parfois appelées !commands, qui sont utilisées pour le débogage en mode noyau.

Configuration du laboratoire

Vous avez besoin du matériel suivant pour terminer le laboratoire :

  • Un ordinateur portable ou de bureau (hôte) exécutant Windows 10
  • Un deuxième ordinateur portable ou de bureau (cible) exécutant Windows 10
  • Un hub ou un routeur et des câbles réseau pour connecter les deux ordinateurs
  • Un accès à Internet pour télécharger des fichiers de symboles

Vous avez besoin du logiciel suivant pour terminer le laboratoire :

  • Visual Studio
  • Kit de développement logiciel (SDK) Windows pour Windows 10
  • Kit de développement de pilotes Windows (WDK) pour Windows 10
  • Le pilote d’écho d’exemple pour Windows 10

Le laboratoire comprend les sections suivantes :

Connexion à une session de débogage de noyau WinDbg

Dans cette section, configurez le débogage réseau sur le système hôte et cible.

Les ordinateurs de ce laboratoire doivent être configurés pour utiliser une connexion réseau Ethernet pour le débogage en mode noyau.

Ce laboratoire utilise deux ordinateurs. Le débogueur Windows s’exécute sur le système hôte et le pilote d’écho Framework du mode noyau (KMDF) s’exécute sur le système cible.

Utilisez un concentrateur réseau ou un routeur et des câbles réseau pour connecter les deux ordinateurs.

Diagramme illustrant deux ordinateurs connectés via un concentrateur ou un routeur réseau.

Pour travailler avec des applications en mode noyau et utiliser WinDbg, nous vous recommandons d’utiliser le transport KDNET sur Ethernet. Pour plus d’informations sur l’utilisation du protocole de transport Ethernet, veuillez consulter la rubrique Bien démarrer avec WinDbg (mode noyau). Pour plus d’informations sur la configuration de l’ordinateur cible, veuillez consulter la rubrique Préparer un ordinateur pour le déploiement manuel du pilote et Configurer automatiquement le débogage du noyau réseau KDNET.

Configurez le débogage en mode noyau en utilisant l’Ethernet

Pour activer le débogage en mode noyau sur le système cible :

  1. Sur le système hôte, ouvrez une fenêtre d’invite de commandes et saisissez ipconfig pour déterminer son adresse IP.

    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. Enregistrez l’adresse IP du système hôte : ______________________________________

  3. Sur le système cible, ouvrez une fenêtre d’invite de commandes et utilisez la commande ping pour confirmer la connectivité réseau entre les deux systèmes.

    ping 169.182.1.1
    

    Utilisez l’adresse IP réelle du système hôte que vous avez enregistrée au lieu de 169.182.1.1 qui est affichée dans la sortie d’exemple.

    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
    

Activez le débogage en mode noyau sur le système cible en effectuant les étapes suivantes.

Important

Avant d’utiliser BCDEdit pour modifier les informations de démarrage, vous devrez peut-être suspendre temporairement les fonctionnalités de sécurité de Windows telles que BitLocker et Secure Boot sur l’ordinateur de test. Réactivez ces fonctionnalités de sécurité lorsque le test est terminé. Gérez correctement l’ordinateur de test lorsque les fonctionnalités de sécurité sont désactivées. Le démarrage sécurisé est généralement désactivé dans l’UEFI. Pour accéder aux paramètres de l’UEFI, utilisez Système, Récupération, Démarrage avancé. Au redémarrage, sélectionnez Dépannage, Options avancées, Paramètres du microprogramme UEFI. Faites preuve de prudence, car la définition incorrecte des options de l’UEFI ou la désactivation de BitLocker peuvent rendre le système inopérable.

  1. Sur l’ordinateur cible, ouvrez une fenêtre d’invite de commande en tant qu’administrateur. Saisissez cette commande pour activer le débogage :

    bcdedit /set {default} DEBUG YES
    
  2. Saisissez cette commande pour activer la signature de test :

    bcdedit /set TESTSIGNING ON 
    
  3. Saisissez cette commande pour définir l’adresse IP du système hôte. Utilisez l’adresse IP du système hôte que vous avez enregistrée précédemment, pas celle affichée.

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

    Avertissement

    Pour renforcer la sécurité de la connexion et réduire le risque des demandes de connexion au débogueur client aléatoires, utilisez une clé aléatoire générée automatiquement. Pour plus d’informations, consultez la rubrique Configuration automatique du débogage réseau du noyau KDNET.

  4. Saisissez cette commande pour confirmer que les valeurs de dbgsettings sont correctement définies :

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

    Remarque

    Si vous recevez un message du pare-feu et que vous souhaitez utiliser le débogueur, sélectionnez les trois cases.

    Capture d’écran de la boîte de dialogue d’alerte de sécurité de Windows indiquant que le pare-feu Windows a bloqué certaines fonctionnalités d’une application.

  5. Sur l’ordinateur hôte, ouvrez une fenêtre d’invite de commandes en tant qu’administrateur. Ce laboratoire utilise la version x64 de WinDbg.exe du Kit de développement de pilotes Windows (WDK) qui a été installée dans le cadre de l’installation du kit Windows. Rendez-vous dans le répertoire WinDbg par défaut, l’emplacement par défaut est indiqué ci-dessous.

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

    Ce laboratoire suppose que les deux ordinateurs exécutent une version 64 bits de Windows à la fois sur la cible et sur l’hôte. Si ce n’est pas le cas, la meilleure approche est d’exécuter la même architecture d’outils sur l’hôte que sur la cible. Par exemple, si la cible exécute Windows 32 bits, exécutez une version 32 bits du débogueur sur l’hôte. Pour plus d’informations, veuillez consulter la rubrique Choisir les outils de débogage 32 bits ou 64 bits.

  6. Ouvrez WinDbg avec le débogage utilisateur à distance en utilisant la commande suivante. Les valeurs de la clé et du port correspondent aux valeurs que vous avez définies précédemment à l’aide de BCDEdit sur l’ordinateur cible.

    WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  7. Redémarrez le système cible.

  8. En une minute ou deux, les sorties de débogage devraient s’afficher sur le système hôte.

    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
    

La fenêtre de commande du débogueur est la principale fenêtre d’information de débogage dans WinDbg. Vous pouvez saisir des commandes de débogueur et afficher la sortie de commande dans cette fenêtre.

La fenêtre de commande du débogueur est divisée en deux panneaux. Saisissez les commandes dans le petit panneau, qui est le panneau de saisie de commande en bas de la fenêtre, et affichez la sortie de la commande dans le grand panneau en haut de la fenêtre.

Dans le panneau de saisie de commande, utilisez les touches de flèche Haut et Bas pour faire défiler l’historique des commandes. Lorsqu’une commande apparaît, vous pouvez la modifier ou appuyer sur Entrée pour exécuter la commande.

Commandes et techniques de débogage en mode noyau

Dans cette section, utilisez des commandes de débogage pour afficher des informations sur le système cible.

Certaines commandes de débogage affichent du texte en utilisant le langage de balisage de débogueur (DML) que vous pouvez sélectionner pour rassembler rapidement plus d’informations.

  1. Sur le système hôte, utilisez Ctrl+Verrouillage défil pour interrompre le code en cours d’exécution sur le système cible. Il peut falloir un certain temps pour que le système cible réponde.

    Capture d’écran de l’écran principal dans le débogueur montrant la sortie de la fenêtre de commande à partir d’une connexion en direct au noyau.

  2. Entrez la commande suivante pour activer DML dans la fenêtre de commande du débogueur :

    0: kd> .prefer_dml 1
    DML versions of commands on by default
    
  3. Vous pouvez accéder à l’aide des commandes de référence en utilisant la commande .hh. Entrez la commande suivante pour afficher l’aide de référence des commandes .prefer_dml :

    0: kd> .hh .prefer_dml
    

    Le fichier d’aide du débogueur affiche l’aide de la commande .prefer_dml.

    Capture d’écran de l’application d’aide du débogueur affichant l’aide pour la commande .prefer-dml.

  4. Pour afficher des informations détaillées sur la version sur le système cible, entrez la commande vertarget (Afficher la version de l’ordinateur cible) dans la fenêtre WinDbg :

    0: kd> vertarget
    Windows 10 Kernel Version 9926 MP (4 procs) Free x64
    Product: WinNt, suite: TerminalServer SingleUserTS
    Built by: 9926.0.amd64fre.fbl_awesome1501.150119-1648
    Machine Name: ""
    Kernel base = 0xfffff801`8d283000 PsLoadedModuleList = 0xfffff801`8d58aef0
    Debug session time: Fri Feb 20 10:15:17.807 2015 (UTC - 8:00)
    System Uptime: 0 days 01:31:58.931
    
  5. Pour vérifier que vous travaillez avec le processus en mode noyau correct, entrez la commande lm (Liste des modules chargés) dans la fenêtre WinDbg pour afficher les modules chargés :

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

    La sortie qui a été omise est indiquée par « … » dans ce laboratoire.

  6. Pour demander des informations détaillées sur un module spécifique, utilisez l’option v (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
    

    Il n’y a pas de chemin de symbole défini et de symboles chargés, donc des informations limitées sont disponibles dans le débogueur.

Télécharger et compiler le pilote d’écho KMDF

Dans cette section, téléchargez et créez le pilote d’écho KMDF.

Généralement, vous travailleriez avec votre propre code de pilote lorsque vous utilisez WinDbg. Pour vous familiariser avec le fonctionnement de WinDbg, ce laboratoire utilise le modèle KMDF « Echo » de l’échantillon de pilote. Le code source est disponible pour aider à comprendre les informations affichées dans WinDbg. Cet exemple est également utilisé pour illustrer comment vous pouvez procéder étape par étape à travers le code en mode noyau natif. Cette technique peut être précieuse pour le débogage de problèmes de code en mode noyau complexes.

Pour télécharger et créer le pilote d’écho KMDF :

  1. Téléchargez et extrayez l’échantillon Echo KMDF depuis GitHub.

    L’échantillon Echo KMDF est situé dans le dossier general.

    Capture d’écran de la page windows-driver-samples GitHub mettant en évidence le dossier général et le bouton de téléchargement zip.

    1. Téléchargez les échantillons de pilotes dans un fichier zip : Échantillons de pilotes

    2. Téléchargez le fichier zip sur votre disque dur local.

    3. Sélectionnez et maintenez ou cliquez avec le bouton droit sur le fichier zip, puis sélectionnez Extraire tout. Spécifiez un nouveau dossier ou accédez à un dossier existant pour stocker les fichiers extraits. Par exemple, vous pourriez spécifier C:\DriverSamples\ comme nouveau dossier dans lequel extraire les fichiers.

    4. Après l’extraction des fichiers, accédez au sous-dossier suivant : C:\DriverSamples\general\echo\kmdf

  2. Dans Microsoft Visual Studio, sélectionnez Fichier>Ouvrir>Projet/Solution... et rendez-vous dans le dossier contenant les fichiers extraits, par exemple, C:\DriverSamples\general\echo\kmdf. Double-cliquez sur le fichier de solution kmdfecho pour l’ouvrir.

    Dans Visual Studio, localisez l’Explorateur de solutions. Si cette fenêtre n’est pas déjà ouverte, sélectionnez Explorateur de solutions dans le menu Affichage (View). Dans l’Explorateur de solutions, vous pouvez voir une solution qui contient trois projets.

    Capture d’écran de Visual Studio affichant le fichier device.c chargé à partir du projet kmdfecho.

  3. Configurez la configuration et la plate-forme de l’échantillon. Dans l’Explorateur de solutions, sélectionnez et maintenez ou faites un clic droit sur Solution ’kmdfecho’ (3 projets), puis sélectionnez Gestionnaire de configuration. Assurez-vous que les paramètres de configuration et de plate-forme sont les mêmes pour les trois projets. Par défaut, la configuration est définie sur Win10 Debug, et la plate-forme est définie sur Win64 pour tous les projets. Si vous apportez des modifications de configuration ou de plate-forme à un projet, apportez les mêmes modifications aux trois autres projets.

  4. Les échantillons de pilotes doivent être modifiés pour utiliser des valeurs qui ne chevauchent pas les pilotes existants. Consultez De l’exemple de code au pilote de production - Ce qu’il faut changer dans les exemples pour connaître la façon de créer un échantillon de pilote unique qui coexistera avec les pilotes réels existants installés dans Windows.

  5. Configurez la bibliothèque d’exécution. Ouvrez la page des propriétés du pilote d’écho et localisez C/C++>Génération de code. Modifiez la bibliothèque d’exécution en Multithreaded Debug (/MTd). Pour plus d’informations sur les options de génération, consultez /MD, /MT, /LD (Utiliser la bibliothèque d’exécution).

    Capture d’écran de la page de propriétés de l’écho dans Visual Studio mettant en évidence le paramètre de bibliothèque d’exécution.

  6. Dans les propriétés du pilote, assurez-vous que Signature du pilote>Mode de signature est paramétré sur Signature de test.

    Capture d’écran de la page de propriétés de l’écho dans Visual Studio mettant en évidence le paramètre de mode de signature.

  7. Dans Visual Studio, sélectionnez Build>Build Solution.

    La fenêtre de build devrait afficher un message indiquant que la build pour les trois projets a réussi.

Conseil

Si vous rencontrez un message d’erreur de build, utilisez le numéro d’erreur de build pour déterminer une solution. Par exemple, Erreur MSBuild MSB8040 décrit comment travailler avec des bibliothèques atténuées par spectre.

  1. Dans l’Explorateur de fichiers, accédez au dossier contenant les fichiers extraits pour l’échantillon. Par exemple, allez dans C:\DriverSamples\general\echo\kmdf, si c’est le dossier que vous avez spécifié précédemment. Dans ce dossier, l’emplacement des fichiers du pilote compilé varie en fonction des paramètres de configuration et de plate-forme que vous avez sélectionnés dans le Gestionnaire de configuration. Si vous n’avez pas modifié les paramètres par défaut, alors les fichiers du pilote compilé sont enregistrés dans un dossier nommé \x64\Debug pour une build de débogage 64 bits.

    Accédez au dossier contenant les fichiers construits pour le pilote Autosync : C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.

    Le dossier devrait contenir ces fichiers :

    Fichier Description
    Echo.sys Le fichier pilote.
    Echo.inf Un fichier d’informations (INF) qui contient les informations nécessaires pour installer le pilote.

    De plus, le fichier echoapp.exe a été construit et il devrait être situé ici : C:\DriverSamples\general\echo\kmdf\exe\x64\Debug.

    Fichier Description
    EchoApp.exe Un fichier exécutable d’invite de commandes de test qui communique avec le pilote echo.sys.
  2. Localisez une clé USB ou configurez un partage réseau pour copier les fichiers de pilote construits et le test EchoApp de l’hôte vers le système cible.

Dans la section suivante, copiez le code sur le système cible, et installez et testez le pilote.

Installer l’échantillon de pilote d’écho KMDF sur le système cible

Dans cette section, utilisez l’outil DevCon pour installer l’échantillon de pilote d’écho.

L’ordinateur sur lequel vous installez le pilote est appelé l’ordinateur cible ou l’ordinateur de test. Généralement, cet ordinateur est distinct de l’ordinateur sur lequel vous développez et construisez le package de pilotes. L’ordinateur sur lequel vous développez et construisez le pilote est appelé l’ordinateur hôte.

Le processus de déplacement du package de pilotes vers l’ordinateur cible et l’installation du pilote est appelé déploiement du pilote.

Avant de déployer un pilote signé pour les tests, préparez l’ordinateur cible en activant la signature des tests. Vous devez également localiser l’outil DevCon dans votre installation du WDK et le copier sur le système cible.

Pour installer le pilote sur le système cible, suivez les étapes suivantes.

Sur le système cible, activez les pilotes signés pour les tests :

  1. Ouvrez Paramètres Windows.

  2. Dans Mise à jour et sécurité, sélectionnez Récupération.

  3. Sous Démarrage avancé, sélectionnez Redémarrer Maintenant.

  4. Lorsque l’ordinateur redémarre, sélectionnez Options de démarrage. Sous Windows 10, sélectionnez Dépannage>Options avancées>Paramètres de démarrage, puis sélectionnez Redémarrer.

  5. Sélectionnez Désactiver l’application de signature de pilote en appuyant sur la touche F7.

  6. Redémarrer l’ordinateur cible.

Sur le système hôte, accédez au dossier Outils de votre installation du WDK et localisez l’outil DevCon. Par exemple, regardez dans le dossier suivant : C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe.

Créez un dossier sur la cible pour le package de pilote construit, par exemple, C:\PiloteEcho. Copiez devcon.exe vers le système cible. Localisez le certificat .cer sur le système hôte. Il se trouve dans le même dossier sur l’ordinateur hôte dans le dossier contenant les fichiers de pilote construits. Copiez tous les fichiers du pilote construit décrits précédemment sur l’ordinateur hôte et enregistrez-les dans le même dossier que vous avez créé sur l’ordinateur cible.

Sur l’ordinateur cible, sélectionnez et maintenez ou cliquez avec le bouton droit sur le fichier de certificat, puis sélectionnez Installer, puis suivez les invites pour installer le certificat de test.

Si vous avez besoin d’instructions plus détaillées pour configurer l’ordinateur cible, consultez Préparation d’un ordinateur pour le déploiement manuel de pilotes.

Les instructions suivantes vous montrent comment installer et tester le pilote d’échantillon. Voici la syntaxe générale pour l’outil devcon que vous utilisez pour installer le pilote :

devcon install <INF file> <hardware ID>

Le fichier INF requis pour installer ce pilote est echo.inf. Le fichier inf contient l’ID matériel pour installer le echo.sys. Pour l’échantillon d’écho, l’ID matériel est root\ECHO.

Sur l’ordinateur cible, ouvrez une fenêtre d’invite de commande en tant qu’administrateur. Rendez-vous dans votre dossier de package de pilotes, et entrez la commande suivante :

devcon install echo.inf root\ECHO

Si vous obtenez un message d’erreur concernant devcon n’étant pas reconnu, essayez d’ajouter le chemin de l’outil devcon. Par exemple, si vous l’avez copié dans un dossier appelé C:\Outils, essayez d’utiliser la commande suivante :

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

Une boîte de dialogue apparaît indiquant que le pilote de test est un pilote non signé. Sélectionnez Installer ce pilote quand même pour continuer.

Capture d’écran d’avertissement de sécurité de Windows indiquant que Windows ne peut pas vérifier l’éditeur du logiciel de pilote.

Conseil

 Si vous rencontrez des problèmes avec l’installation, vérifiez le fichier suivant pour plus d’informations. %windir%\inf\setupapi.dev.log

Après avoir installé avec succès le pilote d’échantillon, vous êtes prêt à le tester.

Sur l’ordinateur cible, dans une fenêtre d’invite de commandes, saisissez devmgmt pour ouvrir le Gestionnaire de périphériques. Dans Gestionnaire de périphériques, dans le menu Affichage, choisissez Appareils par type. Dans l’arborescence de l’appareil, recherchez Exemple de pilote Echo WDF dans le nœud d’exemple d’appareil.

Capture d’écran de Gestionnaire de périphériques arborescence mettant en évidence l’exemple de pilote d’écho WDF.

Entrez echoapp pour démarrer l’application d’écho de test pour confirmer que le pilote est fonctionnel.

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

Utiliser WinDbg pour afficher des informations sur le pilote

Dans cette section, définissez le chemin du symbole et utilisez les commandes du débogueur du noyau pour afficher des informations sur le pilote d’exemple d’écho KMDF.

Pour afficher des informations sur le pilote :

  1. Sur le système hôte, si vous avez fermé le débogueur, ouvrez-le à nouveau à l’aide de la commande suivante dans la fenêtre d’invite de commandes administrateur.

    WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Utilisez Ctrl+Arrêt (verrouillage de défilement) pour entrer dans le code en cours d’exécution sur le système cible.

  3. Pour définir le chemin des symboles sur le serveur de symboles Microsoft dans l’environnement WinDbg, utilisez la commande .symfix.

    0: kd> .symfix
    
  4. Pour ajouter votre emplacement de symbole local pour utiliser vos symboles locaux, ajoutez le chemin d’accès en utilisant .sympath+ puis .reload /f.

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

    La commande .reload avec l’option /f force supprime toutes les informations de symbole pour le module spécifié et recharge les symboles. Dans certains cas, cette commande recharge ou décharge également le module lui-même.

Vous devez charger les symboles appropriés pour utiliser les fonctionnalités avancées fournies par WinDbg. Si vous n’avez pas configuré correctement les symboles, lorsque vous tentez d’utiliser des fonctionnalités qui dépendent des symboles, vous recevez des messages indiquant que les symboles ne sont pas disponibles.

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

Il existe de nombreuses approches qui peuvent être utilisées pour travailler avec les symboles. Dans de nombreuses situations, vous pouvez configurer l’ordinateur pour accéder aux symboles à partir d’un serveur de symboles que Microsoft fournit lorsque cela est nécessaire. Ce laboratoire utilise cette approche. Si les symboles dans votre environnement sont à un emplacement différent, modifiez les étapes pour utiliser cet emplacement. Pour plus d’informations, veuillez consulter la rubrique Chemin des symboles pour le débogueur Windows.

Pour effectuer un débogage de source, vous devez construire une version vérifiée (débogage) de vos binaires. Le compilateur crée des fichiers de symboles (.pdb). Ces fichiers de symboles montrent au débogueur comment les instructions binaires correspondent aux lignes de code source. Les fichiers source eux-mêmes doivent également être accessibles au débogueur.

Les fichiers de symboles ne contiennent pas le texte du code source. Pour le débogage, il est préférable que le lien n’optimise pas votre code. Le débogage de source et l’accès aux variables locales sont plus difficiles, voire parfois presque impossibles, si le code a été optimisé. Si vous rencontrez des problèmes pour afficher les variables locales ou les lignes de code source, configurez les options de construction suivantes :

set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
  1. Entrez la commande suivante dans la zone de commande du débogueur pour afficher des informations sur le pilote echo :

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

    Pour plus d’informations, voir lm.

  2. Parce que ce laboratoire a défini prefer_dml précédemment, certains éléments de la sortie sont des liens hypertexte que vous pouvez sélectionner. Sélectionnez le lien Parcourir tous les symboles globaux dans la sortie de débogage pour afficher des informations sur les symboles qui commencent par la lettre « a ».

    0: kd> x /D Echo!a*
    
  3. L’échantillon d’écho ne contient aucun symbole qui commence par la lettre « a », donc saisissez x ECHO!Echo* pour afficher des informations sur tous les symboles associés au pilote echo qui commencent par « Echo ».

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

    Pour plus d’informations, veuillez consulter la section x (Examiner les symboles).

  4. L’extension !lmi affiche des informations détaillées sur un module. Saisissez !lmi echo. Votre sortie devrait être similaire au texte montré dans cet exemple :

    0: kd> !lmi echo
    Loaded Module Info: [echo] 
             Module: ECHO
       Base Address: fffff8010bf94000
         Image Name: ECHO.sys
    … 
    
  5. Utilisez l’extension !dh pour afficher les informations d’en-tête comme indiqué dans cet exemple :

    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. Entrez la commande suivante pour modifier le masque de débogage par défaut afin que tous les messages de débogage du système cible soient affichés dans le débogueur :

    0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
    

    Certains pilotes affichent des informations supplémentaires lorsque le masque de 0xFFFFFFFF est utilisé. Définissez le masque sur 0x00000000 si vous souhaitez réduire la quantité d’informations affichées.

    0: kd> ed nt!Kd_DEFAULT_MASK 0x00000000
    

    Utilisez la commande dd pour confirmer que le masque est défini pour afficher tous les messages du débogueur.

    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
    

Afficher des informations sur l’arbre des périphériques Plug and Play

Dans cette section, affichez des informations sur le pilote de périphérique d’échantillon echo et l’endroit où il se trouve dans l’arbre des périphériques Plug and Play.

Les informations sur le pilote de périphérique dans l’arbre des périphériques Plug and Play peuvent être utiles pour le dépannage. Par exemple, si un pilote de périphérique n’est pas résident dans l’arbre des périphériques, il peut y avoir un problème avec l’installation du pilote de périphérique.

Pour plus d’informations sur l’extension de débogage du nœud de périphérique, veuillez consulter la section !devnode.

  1. Sur le système hôte, pour voir tous les nœuds de périphériques dans l’arbre des périphériques Plug and Play, entrez la commande !devnode 0 1.

    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. Utilisez Ctrl+F pour rechercher dans la sortie générée le nom du pilote de périphérique, echo.

    Capture d’écran de la boîte de dialogue Rechercher dans WinDbg recherchant le terme « echo ».

  3. Le pilote de périphérique echo devrait être chargé. Utilisez la commande !devnode 0 1 echo pour afficher les informations Plug and Play associées à votre pilote de périphérique echo comme indiqué dans cet exemple :

    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. La sortie affichée dans la commande précédente comprend le PDO associé à l’instance en cours d’exécution de votre pilote, dans cet exemple, 0xffffe0007b71a960. Entrez la commande !devobj <PDO address> pour afficher les informations Plug and Play associées au pilote de périphérique echo. Utilisez l’adresse PDO que !devnode affiche sur votre ordinateur, pas celle montrée ici.

    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. La sortie affichée dans la commande !devnode 0 1 comprend l’adresse PDO associée à l’instance en cours d’exécution de votre pilote, dans cet exemple c’est 0xffffe0007b71a960. Entrez la commande !devstack <PDO address> pour afficher les informations Plug and Play associées au pilote de périphérique. Utilisez l’adresse PDO que !devnode affiche sur votre ordinateur, pas celle montrée dans cet exemple.

    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"
    

La sortie montre que vous avez un empilement de pilotes de périphériques assez simple. Le pilote echo est un enfant du nœud PnPManager. PnPManager est un nœud racine.

\Driver\ECHO
\Driver\PnpManager

Ce schéma montre un arbre de nœuds de périphériques plus complexe.

Schéma illustrant un arbre de nœuds de périphériques composé d’environ 20 nœuds.

Pour plus d’informations sur les piles de pilotes plus complexes, veuillez consulter la section Empilements de pilotes et Nœuds de périphériques et piles de périphériques.

Travailler avec des points d’arrêt et du code source

Dans cette section, définissez des points d’arrêt et avancez pas à pas dans le code source en mode kernel.

Pour pouvoir avancer dans le code et vérifier les valeurs des variables en temps réel, activez les points d’arrêt et définissez un chemin vers le code source.

Les points d’arrêt arrêtent l’exécution du code à une ligne de code particulière. Avancez dans le code à partir de ce point pour déboguer cette section spécifique du code.

Pour définir un point d’arrêt à l’aide d’une commande de débogage, utilisez l’une des commandes suivantes b.

Commande Description
bp Définit un point d’arrêt actif jusqu’à ce que le module dans lequel il se trouve soit déchargé.
bu Définit un point d’arrêt non résolu lorsque le module est déchargé et le réactive lorsque le module est rechargé.
bm Définit un point d’arrêt pour un symbole. Cette commande utilise bu ou bp de manière appropriée et permet d’utiliser des caractères génériques (*) pour définir des points d’arrêt sur chaque symbole correspondant, comme toutes les méthodes dans une classe.

Pour plus d’informations, veuillez consulter la section Débogage de code source dans WinDbg.

  1. Sur le système hôte, utilisez l’interface utilisateur de WinDbg pour confirmer que Débogage>Mode Source est activé dans la session WinDbg actuelle.

  2. Entrez la commande suivante pour ajouter l’emplacement de votre code local au chemin d’accès source :

    .srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  3. Entrez la commande suivante pour ajouter l’emplacement de vos symboles locaux au chemin des symboles :

    .sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  4. Utilisez la commande x pour examiner les symboles associés au pilote echo afin de déterminer le nom de la fonction à utiliser pour le point d’arrêt. Vous pouvez utiliser un caractère générique ou Ctrl+F pour localiser le nom de fonction DeviceAdd.

    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 
    …
    

    La sortie montre que la DeviceAdd méthode pour votre pilote echo est ECHO!EchoEvtDeviceAdd.

    Alternativement, examinez le code source pour trouver le nom de fonction pour votre point d’arrêt.

  5. Définissez le point d’arrêt avec la commande bm en utilisant le nom du pilote, suivi du nom de la fonction, par exemple, AddDevice, où vous souhaitez définir le point d’arrêt, séparé par un point d’exclamation. Ce laboratoire utilise AddDevice pour surveiller le chargement du pilote.

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

    Vous pouvez utiliser une syntaxe différente en conjonction avec la définition de variables comme <module>!<symbol>, <class>::<method>,'<file.cpp>:<line number>', ou sauter un nombre de fois <condition> <#>. Pour plus d’informations, veuillez consulter la rubrique Points d’arrêt conditionnels dans WinDbg et autres débogueurs Windows.

  6. Listez les points d’arrêt actuels pour confirmer que le point d’arrêt a été défini en entrant la commande bl :

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

    Le « e » dans la sortie indique que le point d’arrêt numéro 1 est activé pour être déclenché.

  7. Redémarrez l’exécution du code sur le système cible en entrant la commande g (go).

  8. Sur le système cible, dans Windows, ouvrez Gestionnaire de périphériques en utilisant l’icône ou en entrant mmc devmgmt.msc. Dans le Gestionnaire de périphériques, développez le nœud Exemples.

  9. Sélectionnez et maintenez ou faites un clic droit sur l’entrée du pilote echo KMDF et sélectionnez Désactiver dans le menu.

  10. Sélectionnez et maintenez ou faites un clic droit sur l’entrée du pilote echo KMDF à nouveau et sélectionnez Activer dans le menu.

  11. Sur le système hôte, lorsque le pilote est activé, le point d’arrêt de débogage AddDevice devrait se déclencher. L’exécution du code du pilote sur le système cible doit s’arrêter. Lorsque le point d’arrêt est atteint, l’exécution doit s’arrêter au début de la routine AddDevice. La sortie de la commande de débogage affiche Breakpoint 1 hit.

    Capture d’écran de WinDbg affichant les variables et fenêtres de commande du code source.

  12. Avancez dans le code ligne par ligne en entrant la commande p ou en appuyant sur F10 jusqu’à atteindre la fin de la routine AddDevice. Le caractère accolade (}) est mis en surbrillance comme illustré.

    Capture d’écran de la fenêtre de code avec le caractère accolade mis en évidence au début de la routine AddDevice.

Dans la prochaine section, examinez l’état des variables après que le code de DeviceAdd a été exécuté.

Vous pouvez modifier les points d’arrêt existants en utilisant les commandes suivantes :

Commande Description
bl Liste les points d’arrêt.
bc Efface un point d’arrêt de la liste. Utilisez bc * pour effacer tous les points d’arrêt.
bd Désactive un point d’arrêt. Utilisez bd * pour désactiver tous les points d’arrêt.
be Active un point d’arrêt. Utilisez be * pour activer tous les points d’arrêt.

Alternativement, vous pouvez également modifier les points d’arrêt dans l’interface utilisateur de WinDbg.

Vous pouvez également définir des points d’arrêt qui se déclenchent lorsqu’une adresse mémoire est accédée. Utilisez la commande ba (break on access), avec la syntaxe suivante :

ba <access> <size> <address> {options}
Option Description
e execute : lorsque le processeur récupère une instruction de l’adresse
r read/write : lorsque le processeur lit ou écrit à l’adresse
w write : lorsque le processeur écrit à l’adresse

Vous ne pouvez définir que quatre points d’arrêt de données à un moment donné. C’est à vous de vous assurer que vous alignez correctement vos données pour déclencher le point d’arrêt. Les mots doivent se terminer à des adresses divisibles par 2, les double-mots doivent être divisibles par 4, et les quad-mots par 0 ou 8.

Par exemple, pour définir un point d’arrêt de lecture/d’écriture sur une adresse mémoire spécifique, vous pouvez utiliser une commande comme cet exemple.

ba r 4 0x0003f7bf0

Vous pouvez utiliser les commandes suivantes pour avancer dans votre code avec les raccourcis clavier associés indiqués entre parenthèses.

  • Interruption (Ctrl+Pause). Cette commande interrompt un système tant que le système est en cours d’exécution et est en communication avec WinDbg. La séquence dans le débogueur noyau est Ctrl+C.
  • Exécuter jusqu’au curseur (F7 ou Ctrl+F10). Placez le curseur dans une fenêtre de code source ou de désassemblage où vous souhaitez que l’exécution se bloque, puis appuyez sur F7. L’exécution du code se déroule jusqu’à ce point. Si le flux d’exécution du code n’atteint pas le point indiqué par le curseur, WinDbg ne s’arrêtera pas. Cette situation peut se produire si une instruction IF n’est pas exécutée.
  • Exécuter (F5). Exécute jusqu’à ce qu’un point d’arrêt soit rencontré ou qu’un événement comme un contrôle de bug se produise.
  • Pas à pas principal (F10). Cette commande permet à l’exécution du code de procéder une instruction ou une instruction à la fois. Si un appel est rencontré, l’exécution du code passe par-dessus l’appel sans entrer dans la routine appelée. Si le langage de programmation est C ou C++ et que WinDbg est en mode source, le mode source peut être activé ou désactivé à l’aide de Debug>Mode Source.
  • Passer dans (F11). Cette commande est similaire au passage à la ligne suivante, sauf que l’exécution d’un appel entre dans la routine appelée.
  • Passer à l’extérieur (Shift+F11). Cette commande entraîne l’exécution pour sortir de la routine actuelle ou du lieu actuel dans la pile d’appels. Cette commande est utile si vous avez vu assez de la routine.

Pour plus d’informations, veuillez consulter la section Débogage de code source dans WinDbg.

Afficher des variables et des piles d’appels

Dans cette section, affichez des informations sur les variables et les piles d’appels.

Ce laboratoire suppose que vous êtes arrêté à la routine AddDevice en utilisant le processus décrit précédemment. Pour afficher la sortie indiquée ici, répétez les étapes décrites précédemment, si nécessaire.

Sur le système hôte, pour afficher les variables, utilisez l’élément de menu view>local pour afficher les variables locales.

Capture d’écran de WinDbg affichant la fenêtre Variables Locales

Pour rechercher l’emplacement d’une adresse de variable globale, saisissez ? <variable name>.

  • Passer à l’extérieur (Shift+F11) – Cette commande provoque l’exécution pour sortir de la routine actuelle (lieu actuel dans la pile d’appels). C’est utile si vous avez vu assez de la routine.

Pour plus d’informations, veuillez consulter la rubrique Débogage de code source dans WinDbg (Classique) dans la documentation de référence sur le débogage.

Section 8 : affichage des variables et des piles d’appels

Dans la section 8, vous allez afficher des informations sur les variables et les piles d’appels.

Ce laboratoire suppose que vous êtes arrêté à la routine AddDevice en utilisant le processus décrit précédemment. Pour afficher la sortie indiquée ici, répétez les étapes décrites précédemment, si nécessaire.

<- Sur le système hôte

Afficher les variables

Utilisez l’élément de menu view>local pour afficher les variables locales.

Capture d’écran de WinDbg affichant la fenêtre Variables Locales

Variables globales

Vous pouvez trouver l’emplacement d’une adresse de variable globale en tapant ? <nom de la variable>.

Variables locales

Vous pouvez afficher les noms et les valeurs de toutes les variables locales pour une trame donnée en tapant la commande dv. Pour afficher les noms et les valeurs de toutes les variables locales pour une trame spécifique, entrez la commande dv :

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

La pile d’appels est la chaîne d’appels de fonction qui ont conduit à l’emplacement actuel du compteur de programme. La fonction supérieure sur la pile d’appels est la fonction actuelle, et la fonction suivante est la fonction qui a appelé la fonction actuelle, et ainsi de suite.

Pour afficher la pile d’appels, utilisez les commandes k*.

Commande Description
kb Affiche la pile et les trois premiers paramètres.
kp Affiche les piles et la liste complète des paramètres.
kn Vous permet de voir la pile avec les informations de trame à côté.
  1. Sur le système hôte, si vous souhaitez conserver la pile d’appels disponible, sélectionnez view>call stack pour l’afficher. Sélectionnez les colonnes en haut de la fenêtre pour basculer l’affichage d’informations supplémentaires.

    Capture d’écran de WinDbg affichant la fenêtre de la pile d’appels.

  2. Utilisez la commande kn pour afficher la pile d’appels tout en déboguant le code de l’adaptateur d’échantillon dans un état d’arrêt.

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

La pile d’appels montre que le noyau (nt) a appelé le code Plug and Play (PnP) qui a appelé le code du framework du pilote (WDF) qui a ensuite appelé la fonction du pilote echo DeviceAdd.

Afficher des processus et des threads

Dans cette section, affichez des informations sur les processus et les threads s’exécutant en mode kernel.

Processus

Vous pouvez afficher ou définir des informations sur le processus en utilisant l’extension de débogueur !process. Définissez un point d’arrêt pour examiner le processus utilisé lorsqu’un son est joué.

  1. Sur le système hôte, entrez la commande dv pour examiner les variables locales associées à la routine EchoEvtIo :

    0: kd> dv ECHO!EchoEvtIo*
    ECHO!EchoEvtIoQueueContextDestroy
    ECHO!EchoEvtIoWrite
    ECHO!EchoEvtIoRead         
    
  2. Effacez les points d’arrêt précédents en utilisant bc * :

    0: kd> bc *  
    
  3. Définissez un point d’arrêt de symbole sur les routines EchoEvtIo en utilisant la commande suivante :

    0: kd> bm ECHO!EchoEvtIo*
      2: aade5490          @!”ECHO!EchoEvtIoQueueContextDestroy”
      3: aade55d0          @!”ECHO!EchoEvtIoWrite”
      4: aade54c0          @!”ECHO!EchoEvtIoRead”
    
  4. Listez les points d’arrêt pour confirmer que le point d’arrêt est correctement défini :

    0: kd> bl
    1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197]    0001 (0001) ECHO!EchoEvtIoQueueContextDestroy
    ...
    
  5. Entrez g pour redémarrer l’exécution du code :

    0: kd> g
    
  6. Sur le système cible, exécutez le programme de test du pilote EchoApp.exe sur le système cible.

  7. Sur le système hôte, lorsque l’application de test s’exécute, la routine d’E/S dans le pilote est appelée. Cet appel déclenche le point d’arrêt, et l’exécution du code du pilote sur le système cible s’arrête.

    Breakpoint 2 hit
    ECHO!EchoEvtIoWrite:
    fffff801`0bf95810 4c89442418      mov     qword ptr [rsp+18h],r8
    
  8. Utilisez la commande !process pour afficher le processus actuel impliqué dans l’exécution de echoapp.exe :

    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
    

    La sortie montre que le processus est associé au thread echoapp.exe, qui s’exécutait lorsque votre point d’arrêt sur l’événement d’écriture du pilote a été atteint. Pour plus d’informations, veuillez consulter la section !process.

  9. Utilisez !process 0 0 pour afficher les informations de synthèse pour tous les processus. Dans la sortie, utilisez Ctrl+F pour localiser la même adresse de processus pour le processus associé à l’image echoapp.exe. Dans l’exemple, l’adresse du processus est ffffe0007e6a7780.

    ...
    
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 0f68    Peb: 7ff7cfe7a000  ParentCid: 0f34
        DirBase: 1f7fb9000  ObjectTable: ffffc001cec82780  HandleCount:  34.
        Image: echoapp.exe
    
    ...
    
  10. Enregistrez l’ID de processus associé à echoapp.exe pour l’utiliser plus tard dans ce laboratoire. Vous pouvez également utiliser Ctrl+C pour copier l’adresse dans le presse-papiers pour une utilisation ultérieure.

    _____________________________________________________(adresse du processus echoapp.exe)

  11. Saisissez g au besoin dans le débogueur pour faire avancer le code jusqu’à ce que echoapp.exe finisse de s’exécuter. Il atteint le point d’arrêt dans l’événement de lecture et d’écriture de nombreuses fois. Lorsque echoapp.exe se termine, interrompez le débogueur en appuyant sur Ctrl+ScrLk (Ctrl+Break).

  12. Utilisez la commande !process pour confirmer que vous exécutez un processus différent. Dans la sortie montrée ici, le processus avec la valeur Image de Système est différent de la valeur Image de 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
    ...
    

    La sortie montre qu’un processus système ffffe0007b65d900 s’exécutait lorsque vous avez arrêté le système d’exploitation.

  13. Utilisez la commande !process pour essayer de regarder l’ID de processus qui avait été associé à echoapp.exe que vous avez enregistré précédemment. Fournissez votre adresse de processus echoapp.exe que vous avez enregistrée précédemment, au lieu de l’exemple d’adresse de processus indiquée dans cet exemple.

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

    L’objet de processus n’est plus disponible, car le processus echoapp.exe n’est plus en cours d’exécution.

Threads

Les commandes pour afficher et définir les threads sont similaires aux commandes pour les processus. Utilisez la commande !thread pour afficher les threads. Utilisez .thread pour définir les threads actuels.

  1. Sur le système hôte, entrez g dans le débogueur pour redémarrer l’exécution du code sur le système cible.

  2. Sur le système cible, exécutez le programme de test EchoApp.exe.

  3. Sur le système hôte, le point d’arrêt est atteint et l’exécution du code s’arrête.

    Breakpoint 4 hit
    ECHO!EchoEvtIoRead:
    aade54c0 55              push    ebp
    
  4. Pour afficher les threads en cours d’exécution, entrez !thread. Des informations similaires à l’exemple suivant doivent être affichées :

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

    Notez le nom de l’image d’echoapp.exe. Cela indique que vous examinez le thread associé à l’application de test.

  5. Utilisez la commande !process pour déterminer si ce thread est le seul en cours d’exécution dans le processus associé à echoapp.exe. Le numéro du thread en cours d’exécution dans le processus est le même que celui affiché par la commande !thread.

    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. Utilisez la commande !process 0 0 pour localiser l’adresse de processus de deux processus liés et enregistrez ces adresses de processus ici.

    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
    …
    

    Vous pouvez également utiliser !process 0 17 pour afficher des informations détaillées sur chaque processus. La sortie de cette commande peut être longue. La sortie peut être recherchée en utilisant Ctrl+F.

  7. Utilisez la commande !process pour répertorier les informations de processus pour les deux processus en cours d’exécution sur votre ordinateur. Fournissez l’adresse du processus de votre sortie !process 0 0, pas l’adresse indiquée dans cet exemple.

    Cette sortie d’exemple est pour l’ID de processus cmd.exe qui a été enregistré précédemment. Le nom de l’image pour cet ID de processus est 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
    ...
    

    Cette sortie d’exemple est pour l’ID de processus echoapp.exe qui a été enregistré précédemment.

    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. Enregistrez la première adresse de thread associée aux deux processus ici.

    Cmd.exe: ____________________________________________________

    EchoApp.exe: _________________________________________________

  9. Utilisez la commande !Thread pour afficher des informations sur le thread actuel.

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

    Comme prévu, le thread actuel est le thread associé à echoapp.exe et il est dans un état d’exécution.

  10. Utilisez la commande !Thread pour afficher des informations sur le thread associé au processus cmd.exe. Fournissez l’adresse du thread que vous avez enregistrée précédemment.

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

    Ce thread est associé au processus cmd.exe et se trouve dans un état d’attente.

  11. Indiquez l’adresse du thread du processus CMD.exe en attente pour changer le contexte de ce thread en attente.

    0: kd> .Thread ffffe0007cf34880
    Implicit thread is now ffffe000`7cf34880
    
  12. Utilisez la commande k pour afficher la pile d’appels associée au thread en attente.

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

    Des éléments de la pile d’appels tels que KiCommitThreadWait indiquent que ce thread ne s’exécute pas comme prévu.

Pour plus d’informations sur les threads et les processus, consultez les références suivantes :

IRQL, registres et fin de la session WinDbg

Dans cette section, affichez le niveau de requête d’interruption (IRQL) et le contenu des registres.

Afficher l’IRQL enregistré

L’IRQL est utilisé pour gérer la priorité du traitement des interruptions. Chaque processeur a un paramètre d’IRQL que les threads peuvent augmenter ou diminuer. Les interruptions qui se produisent au niveau ou en dessous du paramètre d’IRQL du processeur sont masquées et n’interfèrent pas avec l’opération en cours. Les interruptions qui se produisent au-dessus du paramètre d’IRQL du processeur ont la priorité sur l’opération en cours.

Sur le système hôte, l’extension !irql affiche l’IRQL sur le processeur actuel de l’ordinateur cible avant que l’arrêt du débogueur ne se produise. Lorsque l’ordinateur cible se met en pause dans le débogueur, l’IRQL change, mais l’IRQL qui était efficace juste avant l’arrêt du débogueur est enregistré et est affiché par !irql.

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

Afficher les registres

Sur le système hôte, affichez le contenu des registres pour le thread actuel sur le processeur actuel à l’aide de la commande r (Registres).

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

Alternativement, vous pouvez afficher le contenu des registres en sélectionnant Affichage>Registres. Pour plus d’informations, voir r (Registres).

Afficher le contenu des registres peut être utile lors du déroulement de l’exécution du code en langage d’assemblage et dans d’autres scénarios. Pour plus d’informations sur le désassemblage en langage d’assemblage, veuillez consulter la rubrique Désassemblage x86 annoté et Désassemblage x64 annoté.

Pour des informations sur le contenu du registre, veuillez consulter la section architecture x86 et architecture x64.

Fin de la session WinDbg

Si vous souhaitez laisser le débogueur attaché, mais que vous voulez travailler sur la cible, effacez tout point d’arrêt en utilisant bc *, afin que l’ordinateur cible ne tente pas de se connecter au débogueur de l’ordinateur hôte. Ensuite, utilisez la commande g pour laisser l’ordinateur cible fonctionner à nouveau.

Pour mettre fin à la session de débogage, sur le système hôte, interrompez le débogueur et entrez la commande qd (Quitter et détacher) ou sélectionnez Arrêter le débogage dans le menu.

0: kd> qd

Pour plus d’informations, veuillez consulter la rubrique Terminer une session de débogage dans WinDbg.

Ressources de débogage Windows

Plus d’informations sont disponibles sur le débogage Windows. Certains de ces livres utilisent des versions antérieures de Windows comme Windows Vista dans leurs exemples, mais les concepts discutés sont applicables à la plupart des versions de Windows.

Voir aussi