Partager via


Déboguer les pilotes - Laboratoire Étape par Étape (Mode noyau Sysvad)

Ce laboratoire fournit des exercices pratiques qui montrent comment déboguer le pilote de périphérique en mode noyau audio Sysvad.

Le débogueur Microsoft Windows (WinDbg) est un outil de débogage windows puissant que vous pouvez utiliser pour effectuer le débogage en mode utilisateur et en mode noyau. WinDbg fournit un débogage au niveau source pour le noyau Windows, les pilotes en mode noyau et les services système, ainsi que les applications et pilotes en mode utilisateur.

WinDbg peut parcourir le code source, définir des points d’arrêt, afficher des variables (y compris des objets C++), des traces de pile et de la mémoire. Sa fenêtre commande de débogueur permet à l’utilisateur d’émettre un large éventail de commandes.

Configuration du laboratoire

Vous aurez besoin du matériel suivant pour pouvoir terminer le labo :

  • Ordinateur portable ou ordinateur de bureau exécutant Windows 10
  • Ordinateur portable ou ordinateur de bureau (cible) exécutant Windows 10
  • Un hub réseau/routeur et des câbles réseau pour connecter les deux PC
  • Accès à Internet pour télécharger des fichiers de symboles

Vous aurez besoin du logiciel suivant pour pouvoir terminer le labo.

  • Microsoft Visual Studio 2017
  • Kit de développement logiciel Windows (SDK) pour Windows 10
  • Kit de pilotes Windows (WDK) pour Windows 10
  • Exemple de pilote audio Sysvad pour Windows 10

Pour plus d’informations sur le téléchargement et l’installation de WDK, consultez Télécharger le Kit de pilotes Windows (WDK).

Procédure pas à pas du débogage Sysvad

Ce labo vous guide tout au long du processus de débogage d’un pilote en mode noyau. Les exercices utilisent l’exemple de pilote audio virtuel Syvad. Étant donné que le pilote audio Syvad n’interagit pas avec le matériel audio réel, il peut être utilisé sur la plupart des appareils. Le labo couvre les tâches suivantes :

Laboratoire de pilotes Echo

Le pilote Echo est un pilote plus simple que le pilote audio Sysvad. Si vous débutez avec WinDbg, vous souhaiterez peut-être commencer par terminer le laboratoire étape par étape de débogage des pilotes universels (mode noyau Echo). Ce labo réutilise les instructions de configuration de ce laboratoire. Par conséquent, si vous avez terminé ce labo, vous pouvez ignorer les sections 1 et 2 ici.

Section 1 : Se connecter à une session WinDbg en mode noyau

Dans la section 1, vous allez configurer le débogage réseau sur l’hôte et le système cible.

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

Ce laboratoire utilise deux ordinateurs. WinDbg s’exécute sur le système hôte et le pilote Sysvad s’exécute sur le système cible .

Utilisez un hub réseau/routeur et des câbles réseau pour connecter les deux PC.

Diagramme montrant deux PC connectés via un hub réseau/routeur.

Pour utiliser des applications en mode noyau et utiliser WinDbg, nous vous recommandons d’utiliser le réseau KDNET sur le transport Ethernet. Pour plus d’informations sur l’utilisation du protocole de transport Ethernet, consultez Prise en main de WinDbg (Kernel-Mode). Pour plus d’informations sur la configuration de l’ordinateur cible, consultez Préparation d’un ordinateur pour le déploiement manuel de pilotes et configuration du débogage automatique du noyau réseau KDNET.

Configurer le débogage en mode noyau à l’aide d’Ethernet

Pour activer le débogage en mode noyau sur le système cible, procédez comme suit.

<- Sur le système hôte

  1. Ouvrez une invite de commandes sur le système hôte et tapez ipconfig /all pour déterminer son adresse IP.
C:\>ipconfig /all
Windows IP Configuration

 Host Name . . . . . . . . . . . . : TARGETPC
...

Ethernet adapter Ethernet:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b3
   Autoconfiguration IPv4 Address. . : 169.182.1.1
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . :
  1. Enregistrez l’adresse IP du système hôte : ______________________________________

  2. Enregistrez le nom d’hôte du système hôte : ______________________________________

-> Sur le système cible

  1. Ouvrez une invite de commandes sur le système cible et utilisez la commande ping pour confirmer la connectivité réseau entre les deux systèmes. 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 l’exemple de sortie.
C:\> ping 169.182.1.1

Pinging 169.182.1.1 with 32 bytes of data:
Reply from 169.182.1.1: bytes=32 time=1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255

Ping statistics for 169.182.1.1:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 1ms, Average = 0ms

Pour utiliser l’utilitaire KDNET pour activer le débogage en mode noyau sur le système cible, procédez comme suit.

  1. Sur le système hôte, recherchez le répertoire KDNET WDK. Par défaut, il se trouve ici.

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

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

  1. Recherchez ces deux fichiers et copiez-les sur un partage réseau ou un lecteur pouce, afin qu’ils soient disponibles sur l’ordinateur cible.

    kdnet.exe

    VerifiedNICList.xml

  2. Sur l’ordinateur cible, ouvrez une fenêtre d’invite de commandes en tant qu’administrateur. Entrez cette commande pour vérifier que la carte réseau sur le PC cible est prise en charge.

C:\KDNET>kdnet

Network debugging is supported on the following NICs:
busparams=0.25.0, Intel(R) 82579LM Gigabit Network Connection, KDNET is running on this NIC.kdnet.exe
  1. Tapez cette commande pour définir l’adresse IP du système hôte. 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 l’exemple de sortie. Choisissez une adresse de port unique pour chaque paire cible/hôte avec laquelle vous travaillez, par exemple 50010.
C:\>kdnet 169.182.1.1 50010

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

Important

Avant d’utiliser BCDEdit pour modifier les informations de démarrage, vous devrez peut-être suspendre temporairement les fonctionnalités de sécurité Windows telles que BitLocker et Le démarrage sécurisé sur le PC de test. Réactivez ces fonctionnalités de sécurité lorsque le test est terminé et gérez correctement le PC 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 UEFI. Pour accéder au paramètre UEFI, utilisez le système, la récupération, le démarrage avancé. Lors du redémarrage, sélectionnez Résoudre les problèmes, Options avancées, paramètres du microprogramme UEFI. Utilisez une précaution, car la définition incorrecte des options UEFI ou la désactivation de BitLocker peut rendre le système inopérable.

  1. Tapez cette commande pour confirmer que les dbgsettings sont correctement définis.
C:\> bcdedit /dbgsettings
busparams               0.25.0
key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
debugtype               NET
hostip                  169.182.1.1
port                    50010
dhcp                    Yes
The operation completed successfully.

Copiez la clé unique générée automatiquement dans un fichier texte pour éviter d’avoir à le taper sur le PC hôte. Copiez le fichier texte avec la clé sur le système hôte.

Remarque :Pare-feu et débogueurs

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

Capture d’écran de l’alerte de sécurité Windows indiquant que le Pare-feu Windows a bloqué certaines fonctionnalités d’une application.

<- Sur le système hôte

  1. Sur l’ordinateur hôte, ouvrez une fenêtre d’invite de commandes en tant qu’administrateur. Accédez au répertoire WinDbg.exe. Nous allons utiliser la version x64 de WinDbg.exe à partir du Kit de pilotes Windows (WDK) qui a été installé dans le cadre de l’installation du kit Windows.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 
  1. Lancez WinDbg avec le débogage utilisateur distant à l’aide de la commande suivante. La valeur de la clé et du port correspond à ce que vous avez défini précédemment à l’aide de BCDEdit sur la cible.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

->Sur le système cible

Redémarrez le système cible.

<-Sur le système hôte

D'ici une minute ou deux, la sortie de débogage doit être affichée sur le système hôte.

Capture d’écran du débogueur Windows affichant la sortie de la fenêtre de commande à partir d’une connexion de noyau actif.

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

La fenêtre Commande du débogueur est divisée en deux volets. Vous tapez des commandes dans le volet plus petit (le volet d’entrée de commande) en bas de la fenêtre et affichez la sortie de commande dans le volet plus grand en haut de la fenêtre.

Dans le volet d’entrée de commande, utilisez la flèche vers le haut et les touches de direction vers le bas pour parcourir l’historique des commandes. Lorsqu’une commande s’affiche, vous pouvez la modifier ou appuyer sur Entrée pour exécuter la commande.

Section 2 : commandes et techniques de débogage en mode noyau

Dans la section 2, vous allez utiliser des commandes de débogage pour afficher des informations sur le système cible.

<- Sur le système hôte

Activer le langage de balisage du débogueur (DML) avec .prefer_dml

Certaines commandes de débogage affichent du texte à l’aide du langage de balisage du débogueur que vous pouvez sélectionner pour collecter rapidement plus d’informations.

  1. Utilisez Ctrl+Arrêt (verrouillage de défilement) dans WinDBg pour basculer dans le code en cours d’exécution sur le système cible. La réponse du système cible peut prendre un peu de temps.
  2. Tapez la commande suivante pour activer DML dans la fenêtre Commande du débogueur.
0: kd> .prefer_dml 1
DML versions of commands on by default

Utiliser .hh pour obtenir de l’aide

Vous pouvez accéder à l'aide de la commande de référence à l'aide de .hh.

  1. Tapez la commande suivante pour afficher l’aide de référence de commande pour .prefer_dml.
    0: kd> .hh .prefer_dml
    

Le fichier d’aide du débogueur affichera l’aide pour la commande .prefer_dml.

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

Afficher la version de Windows sur le système cible

  1. Affichez des informations détaillées sur la version du système cible en tapant 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

Répertorier les modules chargés

  1. Vous pouvez vérifier que vous travaillez avec le processus en mode noyau approprié en affichant les modules chargés en tapant la commande lm (List Loaded Modules) dans la fenêtre WinDbg.
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
...

Note La sortie qui a été omise est indiquée avec « ... » " dans ce labo.

Étant donné que nous n’avons pas encore défini le chemin d’accès des symboles et les symboles chargés, des informations limitées sont disponibles dans le débogueur.

Section 3 : Télécharger et générer le pilote audio Sysvad

Dans la section 3, vous allez télécharger et générer le pilote audio Sysvad.

En règle générale, vous travaillez avec votre propre code de pilote lorsque vous utilisez WinDbg. Pour vous familiariser avec le débogage des pilotes audio, l’exemple de pilote audio virtuel Sysvad est utilisé. Cet exemple est utilisé pour illustrer la façon dont vous pouvez parcourir un seul pas à pas dans le code en mode noyau natif. Cette technique peut être très utile pour le débogage de problèmes complexes de code en mode noyau.

Pour télécharger et générer l’exemple de pilote audio Sysvad, procédez comme suit.

  1. Télécharger et extraire l’exemple audio Sysvad à partir de GitHub

    Vous pouvez utiliser un navigateur pour afficher l’exemple Sysvad et le fichier Readme.md ici :

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

    Capture d’écran du dépôt GitHub affichant le dossier général et le bouton Télécharger zip.

    Ce labo montre comment télécharger les exemples de pilotes universels dans un fichier zip.

    a) Téléchargez le fichier master.zip sur votre disque dur local.

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

    b. Sélectionnez et maintenez la touche enfoncée (ou cliquez avec le bouton droit) Windows-driver-samples-master.zip, puis choisissez Extraire tout. Spécifiez un nouveau dossier ou accédez à un dossier existant qui stockera les fichiers extraits. Par exemple, vous pouvez spécifier C :\WDK_Samples\ comme nouveau dossier dans lequel les fichiers sont extraits.

    v. Une fois les fichiers extraits, accédez au sous-dossier suivant.

    C :\WDK_Samples\Sysvad

  2. Ouvrir la solution de pilote dans Visual Studio

    Dans Visual Studio, sélectionnez Fichier>ouvrir>un projet/solution... et accédez au dossier qui contient les fichiers extraits (par exemple, C :\WDK_Samples\Sysvad). Double-cliquez sur le fichier de solution Syvad .

    Dans Visual Studio, recherchez l’Explorateur de solutions. (Si ce n’est pas déjà fait, choisissez l’Explorateur de solutions dans le menu Affichage .) Dans l’Explorateur de solutions, vous pouvez voir une solution comportant un certain nombre de projets.

    Capture d’écran de Visual Studio avec le fichier adapter.cpp chargé à partir du projet Sysvad.

  3. Définir la configuration et la plateforme de l’exemple

    Dans l’Explorateur de solutions, sélectionnez et maintenez la solution (ou cliquez avec le bouton droit) « sysvad » (7 sur 7 projets) et choisissez Configuration Manager. Assurez-vous que les paramètres de configuration et de plateforme sont identiques pour les quatre projets. Par défaut, la configuration est définie sur « Débogage Win10 », et la plateforme est définie sur « Win64 » pour tous les projets. Si vous apportez des modifications de configuration et/ou de plateforme pour un projet, vous devez apporter les mêmes modifications pour les trois projets restants.

    Note Ce laboratoire suppose que Windows 64 bits est utilisé. Si vous utilisez Windows 32 bits, générez le pilote pour 32 bits.

  4. Vérifier la signature du pilote

    Trouvez le TabletAudioSample. Ouvrez la page de propriétés du pilote Sysvad et vérifiez que lemode> du pilote est défini sur Test Sign.

  5. Les exemples de pilotes doivent être modifiés pour utiliser des valeurs qui n'entrent pas en conflit avec les pilotes existants. Reportez-vous à Partir d’un exemple de code à un pilote de production - Qu’est-ce à changer dans les exemples pour créer un exemple de pilote unique qui coexistera avec les pilotes réels existants installés dans Windows.

  6. Générer l’exemple à l’aide de Visual Studio

    Dans Visual Studio, sélectionnez Générer>Générer la solution.

    Les fenêtres de build doivent afficher un message indiquant que la build pour les six projets a réussi.

Conseil / Astuce

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

  1. Localiser les fichiers de pilote compilés

    Dans l’Explorateur de fichiers, accédez au dossier qui contient les fichiers extraits pour l’exemple. Par exemple, vous accédez à C :\WDK_Samples\Sysvad, si c’est le dossier que vous avez spécifié précédemment. Dans ce dossier, l’emplacement des fichiers de pilotes compilés varie en fonction des paramètres de configuration et de plateforme que vous avez sélectionnés dans Configuration Manager. Par exemple, si vous avez laissé les paramètres par défaut inchangés, les fichiers de pilotes compilés sont enregistrés dans un dossier nommé \x64\Debug pour une build de débogage 64 bits.

    Accédez au dossier qui contient les fichiers générés pour le pilote TabletAudioSample :

    C :\WDK_Samples\Sysvad\TabletAudioSample\x64\Debug. Le dossier contiendra le pilote TabletAudioSample .SYS, le fichier symbole pdp et le fichier inf. Vous devez également localiser les fichiers dll et symboles DelayAPO, KWSApo et KeywordDetectorContosoAdapter.

    Pour installer le pilote, vous aurez besoin des fichiers suivants.

    Nom de fichier Descriptif
    TabletAudioSample.sys Fichier du pilote.
    TabletAudioSample.pdb Fichier de symboles du pilote.
    tabletaudiosample.inf Fichier d’informations (INF) qui contient les informations nécessaires pour installer le pilote.
    KeywordDetectorContosoAdapter.dll Exemple de détecteur de mots clés.
    KeywordDetectorContosoAdapter.pdb Exemple de fichier de symboles de détecteur de mots clés.
    DelayAPO.dll Un exemple de délai APO.
    DelayAPO.pdb Fichier de symbole APO retardé.
    KWSApo.dll Exemple d’APO de détecteur de mots-clés.
    KWSApo.pdb Fichier de symboles du détecteur de mots clés.
    TabletAudioSample.cer Fichier de certificat TabletAudioSample.
  2. Localisez un lecteur USB ou configurez un partage réseau pour copier les fichiers de pilotes générés de l’hôte vers le système cible.

Dans la section suivante, vous allez copier le code dans le système cible, installer et tester le pilote.

Section 4 : Installer l’exemple de pilote audio Sysvad sur le système cible

Dans la section 4, vous allez utiliser devcon pour installer le pilote audio Sysvad.

-> Sur le système cible

L’ordinateur sur lequel vous installez le pilote est appelé l’ordinateur cible ou l’ordinateur de test. En règle générale, il s’agit d’un ordinateur distinct de l’ordinateur sur lequel vous développez et générez le package de pilotes. L’ordinateur sur lequel vous développez et générez 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, vous devez préparer l’ordinateur cible en activant la signature de test. Après cela, vous êtes prêt à exécuter l’exemple de pilote généré sur le système cible.

Pour installer le pilote sur le système cible, procédez comme suit.

  1. Activer les pilotes signés de test

    Pour permettre l'utilisation de pilotes de test signés :

    1. Ouvrez les paramètres Windows.

    2. Dans Update and Security, sélectionnez Récupération.

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

    4. Lorsque le PC redémarre, sélectionnez Résoudre les problèmes.

    5. Sélectionnez Ensuite Options avancées, Paramètres de démarrage , puis Redémarrez.

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

    7. Le PC commence par les nouvelles valeurs en place.

  2. -> Sur le système cible

    Installer le pilote

    Les instructions suivantes vous montrent comment installer et tester l’exemple de pilote.

    Le fichier INF requis pour l’installation de ce pilote est TabletAudioSample.inf. Sur l’ordinateur cible, ouvrez une fenêtre d’invite de commandes en tant qu’administrateur. Accédez au dossier de votre package de pilotes, cliquez avec le bouton droit sur le fichier TabletAudioSample.inf, puis sélectionnez Installer.

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

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

    Conseil / Astuce

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

    Pour obtenir des instructions plus détaillées, consultez Configuration d’un ordinateur pour le déploiement, le test et le débogage de pilotes.

    Le fichier INF contient l’ID matériel pour l’installation du tabletaudiosample.sys. Pour l’exemple Syvad, l’ID matériel est : root\sysvad_TabletAudioSample

  3. Examiner le pilote dans Device Manager

    Sur l’ordinateur cible, dans une fenêtre d’invite de commandes, entrez devmgmt pour ouvrir Device Manager. Dans le Gestionnaire de périphériques, dans le menu Affichage, sélectionnez Appareils par type.

    Dans l’arborescence de l’appareil, recherchez l’appareil audio virtuel (WDM) - Exemple de tablette dans le nœud Appareil audio. Cela se trouve généralement sous le nœud Son, vidéo et contrôleurs de jeu. Vérifiez qu’elle est installée et active.

    Mettez en surbrillance le pilote du matériel actuel sur le PC dans le Gestionnaire de périphériques. Sélectionnez et maintenez la touche enfoncée (ou cliquez avec le bouton droit) sur le pilote, puis sélectionnez Désactiver pour désactiver le pilote.

    Confirmez dans Device Manager que le pilote matériel audio affiche la flèche vers le bas, indiquant qu’il est désactivé.

    Capture d’écran de l’arborescence Device Manager avec l’exemple de tablette d’appareil audio virtuel mis en surbrillance.

    Après avoir installé l’exemple de pilote, vous êtes maintenant prêt à le tester.

Tester le pilote audio Sysvad

  1. Sur l’ordinateur cible, dans une fenêtre d’invite de commandes, entrez devmgmt pour ouvrir Device Manager. Dans le Gestionnaire de périphériques, dans le menu Affichage , sélectionnez Appareils par type. Dans l’arborescence de l’appareil, recherchez l’appareil audio virtuel (WDM) - Exemple de tablette.

  2. Ouvrez le Panneau de configuration et accédez à Matériel et audio>Gérer les périphériques audio. Dans la boîte de dialogue Son, sélectionnez l’icône du haut-parleur étiquetée en tant que périphérique audio virtuel (WDM) - Exemple de tablette, puis sélectionnez Définir la valeur par défaut, mais ne sélectionnez pas OK. La boîte de dialogue Son est alors ouverte.

  3. Recherchez un fichier MP3 ou un autre fichier audio sur l’ordinateur cible, puis double-cliquez dessus pour le lire. Ensuite, dans la boîte de dialogue Son, vérifiez qu’il existe une activité dans l’indicateur de niveau volume associé au périphérique audio virtuel (WDM) - Exemple de pilote tablet.

Section 5 : Utiliser WinDbg pour afficher des informations sur le pilote

Dans la section 5, vous allez définir le chemin du symbole et utiliser les commandes du débogueur du noyau pour afficher des informations sur l’exemple de pilote Sysvad.

Les symboles permettent à WinDbg d’afficher des informations supplémentaires telles que des noms de variables, qui peuvent être inestimables lors du débogage. WinDbg utilise les formats de symboles de débogage Microsoft Visual Studio pour le débogage au niveau source. Il peut accéder à n’importe quel symbole ou variable à partir d’un module qui a des fichiers de symboleS PDB.

Pour charger le débogueur, procédez comme suit.

<-Sur le système hôte

  1. Si vous avez fermé le débogueur, ouvrez-le à nouveau à l’aide de la commande suivante dans la fenêtre de commande d'administrateur. Remplacez la clé et le port par ce que vous avez précédemment configuré.

    C:\> WinDbg –k net:port=50010,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.

Définir le chemin d’accès aux symboles

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

    0: kd> .symfix
    
  2. Pour ajouter votre emplacement de symbole local pour utiliser vos symboles locaux, ajoutez le chemin à l’aide de .sympath+ puis .reload /f.

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

    Note 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 également ou décharge le module lui-même.

Note Vous devez charger les symboles appropriés pour utiliser des fonctionnalités avancées que WinDbg fournit. Si vous n’avez pas correctement configuré de symboles, vous recevrez des messages indiquant que les symboles ne sont pas disponibles lorsque vous tentez d’utiliser des fonctionnalités dépendantes des symboles.

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

Remarqueles serveurs de symboles

Il existe un certain nombre d’approches qui peuvent être utilisées pour utiliser des symboles. Dans de nombreuses situations, vous pouvez configurer le PC pour accéder aux symboles à partir d’un serveur de symboles fourni par Microsoft lorsqu’il est nécessaire. Cette procédure pas à pas suppose que cette approche sera utilisée. Si les symboles de votre environnement se trouvent dans un autre emplacement, modifiez les étapes à suivre pour utiliser cet emplacement. Pour plus d’informations, consultez Le chemin d’accès des symboles pour le débogueur Windows.

RemarqueComprendre les exigences en matière de symboles de code source

Pour effectuer le débogage source, vous devez générer une version vérifiée (debug) de vos fichiers binaires. Le compilateur crée des fichiers de symboles (fichiers.pdb). Ces fichiers de symboles affichent le débogueur comment les instructions binaires correspondent aux lignes sources. Les fichiers sources réels 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 l’éditeur de liens n’optimise pas votre code. Le débogage source et l’accès aux variables locales sont plus difficiles, et parfois presque impossibles, si le code a été optimisé. Si vous rencontrez des problèmes lors de l’affichage des variables locales ou des lignes sources, définissez les options de génération suivantes.

set COMPILE_DEBUG=1

set ENABLE_OPTIMIZER=0

  1. Tapez ce qui suit dans le champ de commande du débogueur pour afficher les informations concernant le pilote Sysvad.

    0: kd> lm m tabletaudiosample v
    Browse full module list
    start             end                 module name
    fffff801`14b40000 fffff801`14b86000   tabletaudiosample   (private pdb symbols)  C:\Debuggers\sym\TabletAudioSample.pdb\E992C4803EBE48C7B23DC1596495CE181\TabletAudioSample.pdb
        Loaded symbol image file: tabletaudiosample.sys
        Image path: \SystemRoot\system32\drivers\tabletaudiosample.sys
        Image name: tabletaudiosample.sys
        Browse all global symbols  functions  data
        Timestamp:        Thu Dec 10 12:20:26 2015 (5669DE8A)
        CheckSum:         0004891E
    ...  
    

    Pour plus d’informations, consultez lm.

  2. Sélectionnez le lien Parcourir tous les symboles globaux dans la sortie de débogage pour afficher des informations sur les symboles d’éléments qui commencent par la lettre a.

  3. Étant donné que DML est activé, certains éléments de la sortie sont des liens chauds que vous pouvez sélectionner. Sélectionnez le lien de données dans la sortie de débogage pour afficher des informations sur les symboles d’éléments qui commencent par la lettre a.

    0: kd> x /D /f tabletaudiosample!a*
     A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    
    fffff806`9adb1000 tabletaudiosample!AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)
    

    Pour plus d’informations, consultez x (Examiner les symboles).

  4. L’extension !lmi affiche des informations détaillées sur un module. Tapez !lmi tabletaudiosample. Votre sortie doit être similaire au texte indiqué ci-dessous.

    0: kd> !lmi tabletaudiosample
    Loaded Module Info: [tabletaudiosample] 
             Module: tabletaudiosample
       Base Address: fffff8069ad90000
         Image Name: tabletaudiosample.sys
       Machine Type: 34404 (X64)
         Time Stamp: 58ebe848 Mon Apr 10 13:17:12 2017
               Size: 48000
           CheckSum: 42df7
    Characteristics: 22  
    Debug Data Dirs: Type  Size     VA  Pointer
                 CODEVIEW    a7,  e5f4,    d1f4 RSDS - GUID: {5395F0C5-AE50-4C56-AD31-DD5473BD318F}
                   Age: 1, Pdb: C:\Windows-driver-samples-master\audio\sysvad\TabletAudioSample\x64\Debug\TabletAudioSample.pdb
                       ??   250,  e69c,    d29c [Data not mapped]
         Image Type: MEMORY   - Image read successfully from loaded memory.
        Symbol Type: PDB      - Symbols loaded successfully from image header.
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
           Compiler: Resource - front end [0.0 bld 0] - back end [14.0 bld 24210]
        Load Report: private symbols & lines, not source indexed 
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
    
  5. Utilisez l’extension !dh pour afficher les informations d’en-tête comme indiqué ci-dessous.

    0: kd> !dh tabletaudiosample 
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
        8664 machine (X64)
           9 number of sections
    5669DE8A time date stamp Thu Dec 10 12:20:26 2015
    
           0 file pointer to symbol table
           0 number of symbols
          F0 size of optional header
          22 characteristics
                Executable
                App can handle >2gb addresses
    ...
    

Section 6 : Affichage des informations sur l’arborescence des appareils Plug-and-Play

Dans la section 6, vous allez afficher des informations sur l’exemple de pilote de périphérique Sysvad et son emplacement dans l’arborescence des appareils Plug-and-Play.

Les informations sur le pilote de périphérique dans l’arborescence d’appareils Plug-and-Play peuvent être utiles pour résoudre les problèmes. Par exemple, si un pilote de périphérique ne réside pas dans l’arborescence de l’appareil, 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 périphérique, consultez !devnode.

<-Sur le système hôte

  1. Pour afficher tous les nœuds d’appareil dans l’arborescence des appareils Plug-and-Play, entrez la commande !devnode 0 1 . Cette commande peut prendre une minute ou deux pour s’exécuter. Pendant cette période, « *Occupé » s’affiche dans la zone d’état de WinDbg.

    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 effectuer une recherche dans la sortie générée pour rechercher le nom du pilote de périphérique , sysvad.

    Boîte de dialogue avec le terme « sysvad » saisi dans le champ de recherche.

    Une entrée de nœud d’appareil portant le nom sysvad_TabletAudioSample sera présente dans la sortie !devnode pour Syvad.

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

    Notez que l’adresse PDO et l’adresse DevNode sont affichées.

  3. Utilisez la !devnode 0 1 sysvad_TabletAudioSample commande pour afficher les informations Plug-and-Play associées à notre pilote de périphérique Sysvad.

    0: kd> !devnode 0 1 sysvad_TabletAudioSample
    Dumping IopRootDeviceNode (= 0xffffe00082df8d30)
    DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
      InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe000897fb650 for PDO 0xffffe00089927e30
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{64097438-cdc0-4007-a19e-62e789062e20}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00086d2f5f0 for PDO 0xffffe00089939ae0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{78880f4e-9571-44a4-a9df-960bde446487}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00089759bb0 for PDO 0xffffe000875aa060
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{7cad07f2-d0a0-4b9b-8100-8dc735e9c447}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00087735010 for PDO 0xffffe000872068c0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{fc38551b-e69f-4b86-9661-ae6da78bc3c6}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088457670 for PDO 0xffffe0008562b830
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{0894b831-c9fe-4c56-86a6-092380fc5628}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000893dbb70 for PDO 0xffffe00089d68060
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{15eb6b5c-aa54-47b8-959a-0cff2c1500db}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088e6f250 for PDO 0xffffe00089f6e990
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{778c07f0-af9f-43f2-8b8d-490024f87239}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000862eb4b0 for PDO 0xffffe000884443a0
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{e4b72c7c-be50-45df-94f5-0f2922b85983}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
    
  4. La sortie affichée dans la commande précédente inclut l’objet PDO associé à l’instance en cours d’exécution de notre pilote, dans cet exemple, il est 0xffffe00089c575a0. Entrez la commande !devobj<adresse PDO> pour afficher les informations Plug-and-Play associées au pilote de périphérique Sysvad. Utilisez l’adresse PDO que !devnode affiche sur votre PC, et non celle affichée ici.

    0: kd> !devobj 0xffffe00089c575a0
    Device object (ffffe00089c575a0) is for:
    0000004e \Driver\PnpManager DriverObject ffffe00082d47e60
    Current Irp 00000000 RefCount 65 Type 0000001d Flags 00001040
    SecurityDescriptor ffffc102b0f6d171 DevExt 00000000 DevObjExt ffffe00089c576f0 DevNode ffffe00086e68190 
    ExtensionFlags (0000000000)  
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe00088386a50 \Driver\sysvad_tabletaudiosample
    Device queue is not busy.
    
  5. La sortie affichée dans la commande !devobj inclut le nom du périphérique attaché : \Driver\sysvad_tabletaudiosample. Utilisez la commande !drvobj avec un masque de 2 bits pour afficher les informations associées à l’appareil attaché.

    0: kd> !drvobj \Driver\sysvad_tabletaudiosample 2
    Driver object (ffffe0008834f670) is for:
    \Driver\sysvad_tabletaudiosample
    DriverEntry:   fffff80114b45310  tabletaudiosample!FxDriverEntry
    DriverStartIo: 00000000 
    DriverUnload:  fffff80114b5fea0                tabletaudiosample!DriverUnload
    AddDevice:     fffff80114b5f000  tabletaudiosample!AddDevice
    
    Dispatch routines:
    [00] IRP_MJ_CREATE                      fffff80117b49a20             portcls!DispatchCreate
    [01] IRP_MJ_CREATE_NAMED_PIPE           fffff8015a949a00          nt!IopInvalidDeviceRequest
    [02] IRP_MJ_CLOSE                       fffff80115e26f90                ks!DispatchCleanup
    [03] IRP_MJ_READ                        fffff80115e32710                ks!DispatchRead
    [04] IRP_MJ_WRITE                       fffff80115e327e0              ks!DispatchWrite
    [05] IRP_MJ_QUERY_INFORMATION           fffff8015a949a00         nt!IopInvalidDeviceRequest
    [06] IRP_MJ_SET_INFORMATION             fffff8015a949a00              nt!IopInvalidDeviceRequest
    [07] IRP_MJ_QUERY_EA                    fffff8015a949a00         nt!IopInvalidDeviceRequest
    [08] IRP_MJ_SET_EA                      fffff8015a949a00              nt!IopInvalidDeviceRequest
    [09] IRP_MJ_FLUSH_BUFFERS               fffff80115e32640  ks!DispatchFlush
    [0a] IRP_MJ_QUERY_VOLUME_INFORMATION    fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0b] IRP_MJ_SET_VOLUME_INFORMATION      fffff8015a949a00               nt!IopInvalidDeviceRequest
    [0c] IRP_MJ_DIRECTORY_CONTROL           fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0d] IRP_MJ_FILE_SYSTEM_CONTROL         fffff8015a949a00         nt!IopInvalidDeviceRequest
    [0e] IRP_MJ_DEVICE_CONTROL              fffff80115e27480               ks!DispatchDeviceIoControl
    [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     fffff8015a949a00   nt!IopInvalidDeviceRequest
    [10] IRP_MJ_SHUTDOWN                    fffff8015a949a00      nt!IopInvalidDeviceRequest
    [11] IRP_MJ_LOCK_CONTROL                fffff8015a949a00  nt!IopInvalidDeviceRequest
    [12] IRP_MJ_CLEANUP                     fffff8015a949a00           nt!IopInvalidDeviceRequest
    [13] IRP_MJ_CREATE_MAILSLOT             fffff8015a949a00               nt!IopInvalidDeviceRequest
    [14] IRP_MJ_QUERY_SECURITY              fffff80115e326a0 ks!DispatchQuerySecurity
    [15] IRP_MJ_SET_SECURITY                fffff80115e32770      ks!DispatchSetSecurity
    [16] IRP_MJ_POWER                       fffff80117b3dce0            portcls!DispatchPower
    [17] IRP_MJ_SYSTEM_CONTROL              fffff80117b13d30              portcls!PcWmiSystemControl
    [18] IRP_MJ_DEVICE_CHANGE               fffff8015a949a00 nt!IopInvalidDeviceRequest
    [19] IRP_MJ_QUERY_QUOTA                 fffff8015a949a00  nt!IopInvalidDeviceRequest
    [1a] IRP_MJ_SET_QUOTA                   fffff8015a949a00       nt!IopInvalidDeviceRequest
    [1b] IRP_MJ_PNP                         fffff80114b5f7d0 tabletaudiosample!PnpHandler
    
  6. Entrez la commande !devstack<adresse PDO> pour afficher les informations Plug-and-Play associées au pilote du périphérique. La sortie affichée dans la commande !devnode 0 1 inclut l’adresse PDO associée à l’instance en cours d’exécution de notre pilote. Dans cet exemple, il s’agit de 0xffffe00089c575a0. Utilisez l’adresse PDO que !devnode affiche sur votre PC, et non celle indiquée ci-dessous.

    0: kd> !devstack 0xffffe00089c575a0
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe00088d212e0  \Driver\ksthunk    ffffe00088d21430  0000007b
      ffffe00088386a50  \Driver\sysvad_tabletaudiosampleffffe00088386ba0  0000007a
    > ffffe00089c575a0  \Driver\PnpManager 00000000  0000004e
    !DevNode ffffe00086e68190 :
      DeviceInst is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
    

La sortie indique que nous avons une pile de pilotes de périphérique relativement simple. Le pilote sysvad_TabletAudioSample est un sous-composant du nœud PnPManager. PnPManager est un nœud racine.

Ce diagramme montre une arborescence de nœuds d’appareil plus complexe.

Diagramme d’une arborescence de nœuds d’appareil composée d’environ 20 nœuds.

Note Pour plus d’informations sur les piles de pilotes plus complexes , consultez piles de pilotes et nœuds d’appareil et piles d’appareils.

Section 7 : Utilisation de points d’arrêt

Dans la section 7, vous allez utiliser des points d’arrêt pour arrêter l’exécution du code à des points spécifiques.

Définition de points d’arrêt à l’aide de commandes

Les points d’arrêt sont utilisés pour arrêter l’exécution du code à une ligne de code particulière. Vous pouvez ensuite avancer 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 b suivantes.

Bp

Définit un point d’arrêt qui sera 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 réactivé lors du rechargement du module.

Bm

Définit un point d’arrêt pour un symbole. Cette commande utilise bu ou bp de manière appropriée et permet aux caractères génériques * d’être utilisés pour définir des points d’arrêt sur tous les symboles qui correspondent (comme toutes les méthodes d’une classe).

  1. Utilisez l’interface utilisateur WinDbg pour vérifier que lemode source> est activé dans la session WinDbg actuelle.

  2. Ajoutez votre emplacement de code local au chemin source en tapant la commande suivante.

    .sympath+ C:\WDK_Samples\Sysvad
    
  3. Ajoutez votre emplacement de symbole local au chemin d’accès du symbole en tapant la commande suivante.

    .sympath+ C:\WDK_Samples\Sysvad
    
  4. Définir le masque de débogage

    Lorsque vous travaillez avec un pilote, il peut être pratique de voir tous les messages qu’il peut afficher. Tapez ce qui suit pour modifier le masque de bits 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
    
  5. Définissez le point d’arrêt avec la commande bm en utilisant le nom du pilote, suivi du nom de la fonction (AddDevice) où vous souhaitez définir le point d’arrêt, séparé par un point d’exclamation.

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

    Vous pouvez utiliser une syntaxe différente conjointement avec la définition de variables telles que <le module> !<symbol>, <classe>::<méthode>, '<file.cpp> :<numéro de ligne>', ou ignorer un certain nombre de fois <condition><#>. Pour plus d’informations, consultez Utilisation de points d’arrêt.

  6. Répertoriez les points d’arrêt actuels pour confirmer que le point d’arrêt a été défini en tapant la commande bl .

    0: kd> bl
    1 e fffff801`14b5f000     0001 (0001) tabletaudiosample!AddDevice
    
  7. Redémarrez l’exécution du code sur le système cible en tapant la commande go g.

  8. ->Sur le système cible

    Dans Windows, ouvrez Device Manager à l’aide de l’icône ou en entrant mmc devmgmt.msc. Dans Device Manager , développez le nœud Son, vidéo et contrôleurs de jeu . Sélectionnez et maintenez la touche enfoncée (ou cliquez avec le bouton droit) sur l’entrée du pilote audio virtuel, puis sélectionnez Désactiver dans le menu.

  9. Sélectionnez et maintenez la touche enfoncée (ou cliquez avec le bouton droit) à nouveau sur l’entrée du pilote audio virtuel, puis sélectionnez Activer dans le menu.

  10. <- Sur le système hôte

    Cela doit entraîner le rechargement du pilote par Windows, qui appelle AddDevice. Cela déclenchera le point d’arrêt Debug AddDevice, et l’exécution du code du pilote sur le système cible devrait s’interrompre.

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

    Si votre chemin d'accès source est correctement défini, vous devriez vous arrêter à la routine AddDevice dans "adapter.cpp".

    {
        PAGED_CODE();
    
        NTSTATUS        ntStatus;
        ULONG           maxObjects;
    
        DPF(D_TERSE, ("[AddDevice]"));
    
        maxObjects = g_MaxMiniports;
    
        #ifdef SYSVAD_BTH_BYPASS
        // 
        // Allow three (3) Bluetooth hands-free profile devices.
        //
        maxObjects += g_MaxBthHfpMiniports * 3; 
        #endif // SYSVAD_BTH_BYPASS
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
        return ntStatus;
    } // AddDevice
    
  11. Effectuez une étape ligne par ligne dans le code en tapant la commande p ou en appuyant sur F10. Vous pouvez passer du code sysvad AddDevice à PpvUtilCall, PnpCallAddDevice, puis au code Windows PipCallDriverAddDevice. Vous pouvez fournir un nombre à la commande p pour avancer plusieurs lignes, par exemple p 5.

  12. Lorsque vous avez terminé de parcourir le code, utilisez la commande go g pour redémarrer l’exécution sur le système cible.

Définition des points d’arrêt d’accès à la mémoire

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

ba <access> <size> <address> {options}
Choix Descriptif

e

exécuter (lorsque le processeur récupère une instruction depuis l’adresse)

r

lecture/écriture (lorsque le processeur lit ou écrit à l'adresse)

w

écrire (lorsque le processeur écrit à l’adresse)

Notez que vous ne pouvez définir que quatre points d’arrêt de données à un moment donné et qu’il vous incombe de vous assurer que vous alignez correctement vos données, sans quoi vous ne déclencherez pas le point d’arrêt (les mots doivent se terminer à des adresses divisibles par 2, les dwords doivent être divisibles par 4, et les quadwords par 4 ou 8).

Par exemple, pour définir un point d’arrêt en lecture/écriture sur une adresse mémoire spécifique, utilisez une commande comme celle-ci.

ba r 4 fffff800`7bc9eff0

Modification de l’état du point d’arrêt

Vous pouvez modifier des points d’arrêt existants à l’aide des commandes suivantes.

bl

Répertorie les points d’arrêt.

av. J.-C

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

être

Permet d'activer un point d'arrêt. Utilisez * pour activer tous les points d’arrêt.

Vous pouvez également modifier des points d’arrêt en sélectionnant modifier>les points d’arrêt. Notez que la boîte de dialogue point d’arrêt fonctionne uniquement avec les points d’arrêt existants. Les nouveaux points d’arrêt doivent être définis à partir de la ligne de commande.

Définir un point d’arrêt sur MixerVolume

Différentes parties du code du pilote audio sont appelées pour répondre à différents événements, une fois le pilote de périphérique chargé. Dans la section suivante, nous définissons un point d’arrêt qui se déclenche lorsque l’utilisateur ajuste le contrôle de volume pour le pilote audio virtuel.

Pour définir un point d’arrêt sur MixerVolume, procédez comme suit.

  1. <- Sur le système hôte

    Pour localiser la méthode qui modifie le volume, utilisez la commande x pour répertorier les symboles dans CAdapterCommon, qui contiennent le volume de chaîne.

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

    Utilisez Ctrl+F pour rechercher en remontant dans la sortie pour le volume et localiser la méthode "MixerVolumeWrite".

  2. Effacez les points de rupture précédents avec bc *.

  3. Définissez un point d’arrêt de symbole sur la routine CAdapterCommon ::MixerVolumeWrite à l’aide de la commande suivante.

    kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite
      1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"
    
  4. Répertoriez les points d’arrêt pour confirmer que le point d’arrêt est correctement défini.

    kd> bl
    1 e fffff801`177b26a0 [c:\WDK_Samples\audio\sysvad\common.cpp @ 1668]    0001 (0001) tabletaudiosample!CAdapterCommon::MixerVolumeWrite
    
  5. Redémarrez l’exécution du code sur le système cible en tapant la commande go g.

  6. Dans le Panneau de configuration, sélectionnez Matériel et son>son. Sélectionnez et maintenez enfoncé (ou cliquez avec le bouton droit) Exemple de description du récepteur, puis sélectionnez Propriétés. Sélectionnez l’onglet Niveaux . Ajustez le volume du curseur.

  7. Cela devrait déclencher le point d'arrêt de débogage SetMixerVolume, et l'exécution du code du pilote sur le système cible devrait s'arrêter.

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

    Vous devez vous arrêter à cette ligne dans le fichier common.cpp

    {
        if (m_pHW)
        {
            m_pHW->SetMixerVolume(Index, Channel, Value);
        }
    } // MixerVolumeWrite
    
  8. Utilisez la commande dv pour afficher les variables actuelles et leurs valeurs. Vous trouverez plus d’informations sur les variables dans la section suivante de ce labo.

    2: kd> dv
               this = 0x00000000`00000010
             ulNode = 0x344
          ulChannel = 0x210a45f8
            lVolume = 0n24
    
  9. Appuyez sur F10 pour parcourir le code en une seule étape.

  10. Appuyez sur F5 pour terminer l’exécution du code MixerVolumeWrite.

Résumé - Exécution pas à pas du code à partir de la fenêtre Commande du débogueur

Voici les commandes que vous pouvez utiliser pour parcourir votre code (avec les raccourcis clavier associés affichés entre parenthèses).

  • Arrêt (Ctrl+Arrêt) : 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 du noyau est Ctrl+C).

  • Pas à pas (F10) : cette commande entraîne l’exécution du code d’une instruction ou d’une instruction à la fois. Si un appel est rencontré, l’exécution du code ignore l'appel sans entrer dans la routine appelée. (Si le langage de programmation est C ou C++ et WinDbg est en mode source, le mode source peut être activé ou désactivé à l’aide de Debug>Mode source).

  • Pas à pas (F11) : cette commande est semblable au pas à pas, sauf que l’exécution d’un appel passe à la routine appelée.

  • Pas à pas (Maj+F11) : cette commande entraîne l’exécution et la sortie de la routine actuelle (emplacement actuel dans la pile des appels). Cela est utile si vous avez vu assez de routine.

  • Exécution 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 s’interrompe, puis appuyez sur F7 ; l’exécution du code se poursuivra jusqu’à ce point. Notez que si le flux d’exécution du code n’atteint pas le point indiqué par le curseur (par exemple, une instruction IF n’est pas exécutée), WinDbg ne s’arrête pas, car l’exécution du code n’a pas atteint le point indiqué.

  • Exécuter (F5) : exécuter jusqu’à ce qu’un point d’arrêt soit rencontré ou qu’un événement comme une analyse de bogue se produise.

Options avancées

  • Définissez l’instruction sur la ligne active (Ctrl+Maj+I) : dans une fenêtre source, vous pouvez placer votre curseur sur une ligne, entrer ce raccourci clavier et l’exécution du code commence à partir de ce point dès que vous l’avez laissé continuer (par exemple en utilisant F5 ou F10). Cela est pratique si vous souhaitez réessayer une séquence, mais cela nécessite des soins. Par exemple, les registres et les variables ne sont pas définis sur ce qu’ils seraient si l’exécution du code avait atteint cette ligne naturellement.

  • Paramètre direct du registre eip : vous pouvez placer une valeur dans le registre eip et dès que vous appuyez sur F5 (ou F10, F11, etc.), l’exécution commence à partir de cette adresse. Cela est similaire à la définition d’instructions sur la ligne actuelle désignée par le curseur, sauf que vous spécifiez l’adresse d’une instruction d’assembly.

Il peut être plus facile de parcourir l’interface utilisateur plutôt que de partir de la ligne de commande afin que cette méthode soit recommandée. Si nécessaire, les commandes suivantes peuvent être utilisées pour parcourir un fichier source à la ligne de commande :

  • .lines - Activer les informations de ligne source.

  • bp main : définissez le point d’arrêt initial au début de votre module.

  • l+t - L'exécution pas à pas se fait par ligne de code source.

  • Sélectionnez Debug>le mode source pour passer en mode source ; le L+t commande n’est pas suffisant.

  • l+s - Les lignes sources s’affichent à l’invite.

  • g - Exécuter le programme jusqu’à ce que « main » soit entré.

  • p - Exécuter une ligne source.

Pour plus d’informations, consultez Le débogage du code source dans WinDbg (classique) dans la documentation de référence sur le débogage.

Définir des points d’arrêt dans le code

Vous pouvez définir un point d’arrêt dans le code en ajoutant l’instruction DebugBreak() et en recréant le projet et en réinstallant le pilote. Ce point d’arrêt se déclenche chaque fois que le pilote est activé. Il s’agit donc d’une technique à utiliser dans les premières phases de développement, et non dans le code de production. Cette technique n’est pas aussi flexible que de définir dynamiquement des points d’arrêt à l’aide des commandes de point d’arrêt.

Conseil : Vous pourriez vouloir conserver une copie du pilote Sysvad sans le point d'arrêt ajouté pour un travail de laboratoire supplémentaire.

  1. Définissez un saut à chaque exécution de la méthode AddDevice en ajoutant l’instruction DebugBreak() à l’exemple de code.

    ...
        // Insert the DebugBreak() statment before the  PcAddAdapterDevice is called.
        //
    
        DebugBreak()
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
    
        return ntStatus;
    } // AddDevice
    
  2. Suivez toutes les étapes décrites précédemment pour reconstruire le pilote dans Microsoft Visual Studio et la réinstaller sur l’ordinateur cible. Veillez à désinstaller le pilote existant avant d’installer le pilote mis à jour.

  3. Effacez les points d’arrêt précédents et assurez-vous que le débogueur est attaché au PC cible.

  4. Lorsque le code s’exécute et atteint l’instruction DebugBreak , l’exécution s’arrête et un message s’affiche.

    KERNELBASE!DebugBreak:
    77b3b770 defe     __debugbreak
    

Section 8 : Afficher les variables

Dans la section 8, vous allez utiliser des commandes de débogueur pour afficher des variables.

Il peut être utile d’examiner les variables à mesure que le code s’exécute pour confirmer que le code fonctionne comme prévu. Ces laboratoires examinent les variables à mesure que le pilote audio produit du son.

  1. Utilisez la commande dv pour examiner les variables de paramètres locaux associées au tabletaudiosample: !CMiniportWaveRT::New*.

    kd> dv tabletaudiosample!CMiniportWaveRT::New*
    
  2. Effacer les points d’arrêt précédents

    bc *
    
  3. Définissez un point d'arrêt sur les routines CMiniportWaveCyclicStreamMSVAD en utilisant la commande suivante.

    0: kd> bm tabletaudiosample!CMiniportWaveRT::NewStream
      1: fffff801`177dffc0 @!"tabletaudiosample!CMiniportWaveRT::NewStream"
    
  4. Redémarrez l’exécution du code sur le système cible en tapant la commande go g.

  5. -> Sur le système cible

    Recherchez un petit fichier multimédia (tel que le fichier audio de notification Windows avec une extension de fichier .wav) et sélectionnez le fichier à lire. Par exemple, vous pouvez utiliser Ring05.wav situé dans le répertoire Windows\Media.

  6. <- Sur le système hôte

    Lorsque le fichier multimédia est lu, le point d’arrêt doit se déclencher et l’exécution du code du pilote sur le système cible doit s’arrêter.

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

    La fenêtre de code source doit mettre en surbrillance l’accolades à l’entrée de la fonction NewStream.

    /*++
    
    Routine Description:
    
      The NewStream function creates a new instance of a logical stream 
      associated with a specified physical channel. Callers of NewStream should 
      run at IRQL PASSIVE_LEVEL.
    
    Arguments:
    
      OutStream -
    
      OuterUnknown -
    
      Pin - 
    
      Capture - 
    
      DataFormat -
    
    Return Value:
    
      NT status code.
    
    --*/
    {
    
    ...
    
  7. Variables locales

    Vous pouvez afficher les noms et valeurs de toutes les variables locales d’une trame donnée en tapant la commande dv .

    0: kd> dv
                    this = 0xffffe000`4436f8e0
               OutStream = 0xffffe000`49d2f130
            OuterUnknown = 0xffffe000`4436fa30
                     Pin = 0
                 Capture = 0x01 '
              DataFormat = 0xffffe000`44227790
    signalProcessingMode = {487E9220-E000-FFFF-30F1-D24900E0FFFF}
                ntStatus = 0n1055
                  stream = 0x00000000`00000200
    
  8. Utiliser DML pour afficher des variables

    Pour utiliser DML pour explorer les variables, sélectionnez les éléments soulignés. L’action select génère une commande dx (Display NatVis Expression) qui vous permet d’explorer les structures de données imbriquées.

    0: kd> dx -r1 (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380))
    (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) :  [Type: CMiniportWaveRT]
        [+0x020] m_lRefCount      : 0
        [+0x028] m_pUnknownOuter  : 0xffffe001d1477e50 : [Type: IUnknown *]
        [+0x030] m_ulLoopbackAllocated : 0x2050
        [+0x034] m_ulSystemAllocated : 0x180
        [+0x038] m_ulOffloadAllocated : 0x0
        [+0x03c] m_dwCaptureAllocatedModes : 0x0
    
    0: kd> dx -r1 (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : {487E9220-E000-FFFF-30F1-D24900E0FFFF} [Type: _GUID]
        [<Raw View>]    
    
    0: kd> dx -r1 -n (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) :  [Type: _GUID]
        [+0x000] Data1            : 0x487e9220
        [+0x004] Data2            : 0xe000
        [+0x006] Data3            : 0xffff
        [+0x008] Data4            :  [Type: unsigned char [8]]
    
    0: kd> dx -r1 -n (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350))
    (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) :  [Type: unsigned char [8]]
        [0]              : 0x30
        [1]              : 0xf1
        [2]              : 0xd2
        [3]              : 0x49
        [4]              : 0x0
        [5]              : 0xe0
        [6]              : 0xff
        [7]              : 0xff
    
  9. Variables globales

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

    0: kd> ? signalProcessingMode
    Evaluate expression: -52768896396472 = ffffd001`c8acd348
    
  10. Cela retourne l’emplacement de mémoire de la variable, dans ce cas ffffd001'c8acd348. Vous pouvez afficher le contenu de l’emplacement de mémoire en vidant la valeur de cet emplacement en tapant la commande dd à l’aide de l’emplacement de mémoire retourné par la commande précédente.

    0: kd> dd ffffd001`c8acd348
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 ffffe000
    
  11. Vous pouvez également utiliser des noms de variables avec la commande dd .

    0: kd> dd signalProcessingMode
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 ffffe000
    
  12. Afficher les variables

    Utilisez l’élément de menu Afficher>les variables locales pour afficher les variables locales. Cette interface offre également cette possibilité d’explorer les structures de données plus complexes.

    Interface WinDbg affichant des exemples de codes locaux et des fenêtres de commande.

  13. Utilisez p ou F10 pour avancer environ 10 lignes dans le code jusqu’à ce que vous mettez en surbrillance le ntStatus = IsFormatSupported(Pin, Capture, DataFormat) ; ligne de code.

        PAGED_CODE();
    
        ASSERT(OutStream);
        ASSERT(DataFormat);
    
        DPF_ENTER(("[CMiniportWaveRT::NewStream]"));
    
        NTSTATUS                    ntStatus = STATUS_SUCCESS;
        PCMiniportWaveRTStream      stream = NULL;
        GUID                        signalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
    
        *OutStream = NULL;
    
         //
        // If the data format attributes were specified, extract them.
        //
        if ( DataFormat->Flags & KSDATAFORMAT_ATTRIBUTES )
        {
            // The attributes are aligned (QWORD alignment) after the data format
            PKSMULTIPLE_ITEM attributes = (PKSMULTIPLE_ITEM) (((PBYTE)DataFormat) + ((DataFormat->FormatSize + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
            ntStatus = GetAttributesFromAttributeList(attributes, attributes->Size, &signalProcessingMode);
        }
    
        // Check if we have enough streams.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = ValidateStreamCreate(Pin, Capture, signalProcessingMode);
        }
    
        // Determine if the format is valid.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = IsFormatSupported(Pin, Capture, DataFormat);
        }
    
    ...
    
  14. Utilisez la commande dv pour afficher les noms et les valeurs de toutes les variables locales pour une trame donnée. Notez que, comme prévu, les valeurs sont différentes de la dernière fois que nous avons exécuté cette commande, car du code supplémentaire a été exécuté qui modifie les variables locales et certaines variables ne sont désormais pas dans l’image actuelle ou leurs valeurs ont changé.

    2: kd> dv
                    this = 0xffffe001`d1182000
               OutStream = 0xffffe001`d4776d20
            OuterUnknown = 0xffffe001`d4776bc8
                     Pin = 0
                 Capture = 0x00 '
              DataFormat = 0xffffe001`cd7609b0
    signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
                ntStatus = 0n0
                  stream = 0x00000000`00000000
    

Section 9 : Afficher les piles d’appels

Dans la section 9, vous allez afficher les piles d’appels pour examiner le code appelant/appelé.

La pile d'appels est la suite d’appels de fonction qui ont conduit à l’emplacement actuel du compteur de programme. La fonction supérieure de la pile des 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 des appels, utilisez les commandes k* :

Ko

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 cadre à côté.

Si vous souhaitez conserver la pile des appels disponible, vous pouvez sélectionner Afficher> lapile des appels pour l’afficher. Sélectionnez les colonnes en haut de la fenêtre pour activer/désactiver l’affichage d’informations supplémentaires.

Interface WinDbg affichant la fenêtre de la pile d'appels.

Ce résultat montre la pile des appels pendant le débogage du code d'exemple de l'adaptateur en pause.

0: kd> kb
# RetAddr           : Args to Child                                                           : Call Site
00 fffff800`7a0fa607 : ffffe001`d1182000 ffffe001`d4776d20 ffffe001`d4776bc8 ffffe001`00000000 : tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
01 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d122bb10 ffffe001`ceb81750 ffffe001`d173f058 : portcls!CPortPinWaveRT::Init+0x2e7
02 fffff800`7a0fc7f9 : ffffe001`d4776bc0 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
04 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
05 fffff800`7bd314b1 : ffffe001`d122bb10 ffffd001`c3098590 ffffe001`d122bd90 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
06 fffff803`cda1bfa8 : 00000000`00000024 00000000`00000000 00000000`00000000 ffffe001`d122bb10 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 fffff803`cda7b306 : 00000000`000001f0 ffffe001`d48ce690 ffffe001`d13d6400 ffffe001`d13d64c0 : nt!IopParseDevice+0x7c8
08 fffff803`cda12916 : 00000000`000001f0 ffffd001`c30988d0 ffffe001`d13d6490 fffff803`cda7b250 : nt!IopParseFile+0xb6
09 fffff803`cda1131c : ffffe001`d2ccb001 ffffd001`c30989e0 00ffffe0`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
0a fffff803`cd9fedb8 : ffffe001`00000001 ffffe001`d48ce690 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
0b fffff803`cd9fe919 : 000000ee`6d1fc8d8 000000ee`6d1fc788 000000ee`6d1fc7e0 000000ee`6d1fc7d0 : nt!IopCreateFile+0x3d8
0c fffff803`cd752fa3 : ffffc000`1f296870 fffff803`cd9d9fbd ffffd001`c3098be8 00000000`00000000 : nt!NtCreateFile+0x79
0d 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
0e 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
0f 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
10 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
11 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

Vous pouvez utiliser DML pour explorer le code. Lorsque vous sélectionnez la première entrée 00, la commande .frame (Définir le contexte local) est utilisée pour définir le contexte, puis la commande dv (Afficher les variables locales) affiche les variables locales.

0: kd> .frame 0n0;dv /t /v
00 ffffd001`c30981d0 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
ffffd001`c30982b0 class CMiniportWaveRT * this = 0xffffe001`d1182000
ffffd001`c30982b8 struct IMiniportWaveRTStream ** OutStream = 0xffffe001`d4776d20
ffffd001`c30982c0 struct IPortWaveRTStream * OuterUnknown = 0xffffe001`d4776bc8
ffffd001`c30982c8 unsigned long Pin = 0
ffffd001`c30982d0 unsigned char Capture = 0x00 '
ffffd001`c30982d8 union KSDATAFORMAT * DataFormat = 0xffffe001`cd7609b0
ffffd001`c3098270 struct _GUID signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
ffffd001`c3098210 long ntStatus = 0n0
ffffd001`c3098218 class CMiniportWaveRTStream * stream = 0x00000000`00000000

Section 10 : Afficher les processus et les threads

Dans la section 10, vous allez utiliser des commandes de débogueur pour afficher les processus et les threads.

Processus

Pour modifier le contexte de processus actuel, utilisez la commande .process process<>. L’exemple suivant montre comment identifier un processus et changer le contexte pour celui-ci.

  • Utilisez la !process commande pour afficher le processus actuel impliqué dans la lecture du son.

    Pour plus d’informations, consultez !process

La sortie indique que le processus est associé à audiodg.exe. Si vous êtes toujours au point d’arrêt décrit dans la section précédente de cette rubrique, le processus en cours devrait être associé à l'image audiodg.exe.

<- Sur le système hôte

0: kd> !process
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 70 Clone 0 Private 504. Modified 16. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       <Invalid>
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.000
    QuotaPoolUsage[PagedPool]         81632
    QuotaPoolUsage[NonPagedPool]      9704
    Working Set Sizes (now,min,max)  (2154, 1814, 2109) (8616KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2101
    VirtualSize                       2097192 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2336
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1573

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject

        THREAD ffffe001ceb77080  Cid 10f0.16dc  Teb: 000000ee6cf8d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d112c840  Cid 10f0.0a4c  Teb: 000000ee6cf8f000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d16c7840  Cid 10f0.13c4  Teb: 000000ee6cf91000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001cec67840  Cid 10f0.0dbc  Teb: 000000ee6cf93000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001d1117840  Cid 10f0.1d6c  Teb: 000000ee6cf95000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001cdeae840  Cid 10f0.0298  Teb: 000000ee6cf97000 Win32Thread: 0000000000000000 RUNNING on processor 2

Notez qu’un des threads associés à ce processus est dans l’état RUNNING. Ce fil soutenait la lecture du clip multimédia quand le point d’arrêt a été atteint.

Utilisez la commande !process 0 0 pour afficher des informations récapitulatives pour tous les processus. Dans la sortie de commande, utilisez Ctrl+F pour localiser l’ID de processus du processus associé à l’image audiodg.exe. Dans l’exemple ci-dessous, l’ID de processus est ffffe001d147c840.

Enregistrez l’ID de processus associé à audiodg.exe sur votre PC pour l’utiliser ultérieurement dans ce labo. ________________________

...

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

Entrez g dans le débogueur pour exécuter le code jusqu'à ce que le clip multimédia ait terminé de jouer. Ensuite, connectez-vous au débogueur en appuyant sur Ctrl+ScrLk (Ctrl+Arrêt) Utilisez la commande !process pour confirmer que vous exécutez maintenant un autre processus.

!process
PROCESS ffffe001cd0ad040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa000  ObjectTable: ffffc00017214000  HandleCount: <Data Not Accessible>
    Image: System
    VadRoot ffffe001d402b820 Vads 438 Clone 0 Private 13417. Modified 87866. Locked 64.
    DeviceMap ffffc0001721a070
    Token                             ffffc00017216a60
    ElapsedTime                       05:04:54.716
    UserTime                          00:00:00.000
    KernelTime                        00:00:20.531
    QuotaPoolUsage[PagedPool]         0
    QuotaPoolUsage[NonPagedPool]      0
    Working Set Sizes (now,min,max)  (1720, 50, 450) (6880KB, 200KB, 1800KB)
    PeakWorkingSetSize                15853
    VirtualSize                       58 Mb
    PeakVirtualSize                   74 Mb
    PageFaultCount                    46128
   MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      66

        THREAD ffffe001cd0295c0  Cid 0004.000c  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0120  SynchronizationEvent

        THREAD ffffe001cd02a6c0  Cid 0004.0010  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0ba0  Semaphore Limit 0x7fffffff
...

La sortie ci-dessus montre qu’un autre processus système de ffffe001cd0ad040 est en cours d’exécution. Le nom de l’image affiche System, pas audiodg.exe.

Utilisez maintenant la commande !process pour basculer vers le processus associé à audiodg.exe. Dans l’exemple, l’ID de processus est ffffe001d147c840. Remplacez l’ID de processus dans l’exemple par votre ID de processus, que vous avez enregistré précédemment.

0: kd> !process  ffffe001d147c840
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 60 Clone 0 Private 299. Modified 152. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       1 Day 01:53:14.490
    UserTime                          00:00:00.031
    KernelTime                        00:00:00.031
    QuotaPoolUsage[PagedPool]         81552
    QuotaPoolUsage[NonPagedPool]      8344
    Working Set Sizes (now,min,max)  (1915, 1814, 2109) (7660KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2116
    VirtualSize                       2097189 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2464
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1418

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      36             IdealProcessor: 0             
        UserTime                  00:00:00.015
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007ff7fb928de0
        Stack Init ffffd001c2ec6dd0 Current ffffd001c2ec60c0
        Base ffffd001c2ec7000 Limit ffffd001c2ec1000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d115c080  Cid 10f0.15b4  Teb: 000000ee6cf9b000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d0bf0640  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      1              IdealProcessor: 0             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c3143dd0 Current ffffd001c3143520
        Base ffffd001c3144000 Limit ffffd001c313e000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      518918         Ticks: 17616 (0:00:04:35.250)
        Context Switch Count      9              IdealProcessor: 1             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
        Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
        Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

Étant donné que ce code n’est pas actif, tous les threads sont dans l’état WAIT, comme prévu.

Sujets

Les commandes permettant d’afficher et de définir des threads sont très similaires à celles des processus. Utilisez la commande !thread pour afficher les threads. Utilisez .thread pour définir les threads actuels.

Pour explorer les threads associés au lecteur multimédia, lisez à nouveau le clip multimédia. Si le point d’arrêt décrit dans la section précédente est toujours en place, vous arrêterez dans le contexte de audiodg.exe.

Utilisez !thread -1 0 pour afficher de brèves informations pour le thread actuel. Cela montre l’adresse du thread, le thread et les ID de processus, l’adresse TEB (Thread Environment Block), l’adresse de la fonction Win32 (le cas échéant) que le thread a été créé pour s’exécuter et l’état de planification du thread.

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

Pour afficher plus d’informations sur le thread en cours d’exécution, tapez !thread. Les informations similaires à ce qui suit doivent être affichées.

0: kd> !thread
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
IRP List:
    ffffe001d429e580: (0006,02c8) Flags: 000008b4  Mdl: 00000000
Not impersonating
DeviceMap                 ffffc00019113080
Owning Process            ffffe001d147c840       Image:         audiodg.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      537630         Ticks: 0
Context Switch Count      63             IdealProcessor: 1             
UserTime                  00:00:00.000
KernelTime                00:00:00.015
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           : Args to Child                                                           : Call Site
ffffd001`c70c62a8 fffff800`7a0fa607 : ffffe001`d4aec5c0 ffffe001`cdefd3d8 ffffe001`d4aec5c0 ffffe001`cdefd390 : tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
ffffd001`c70c62b0 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d429e580 ffffe001`d4ea47b0 ffffe001`cdefd3d8 : portcls!CPortPinWaveRT::Init+0x2e7
ffffd001`c70c6340 fffff800`7a0fc7f9 : ffffe001`d4aec430 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
ffffd001`c70c63c0 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
ffffd001`c70c6450 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
ffffd001`c70c6510 fffff800`7bd314b1 : ffffe001`d429e580 ffffd001`c70c6590 ffffe001`d429e800 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
ffffd001`c70c6540 fffff803`cda1bfa8 : 00000000`00000025 00000000`00000000 00000000`00000000 ffffe001`d429e580 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
ffffd001`c70c65a0 fffff803`cda7b306 : 00000000`000002fc ffffe001`d5e0d510 00000000`00000000 ffffe001`d3341bd0 : nt!IopParseDevice+0x7c8
ffffd001`c70c6770 fffff803`cda12916 : 00000000`000002fc ffffd001`c70c68d0 ffffe001`d3341ba0 fffff803`cda7b250 : nt!IopParseFile+0xb6
ffffd001`c70c67d0 fffff803`cda1131c : ffffe001`ceb6c601 ffffd001`c70c69e0 00000000`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
ffffd001`c70c6970 fffff803`cd9fedb8 : ffff8ab8`00000001 ffffe001`d5e0d510 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
ffffd001`c70c6a90 fffff803`cd9fe919 : 000000ee`6d37c6e8 00000004`6d37c500 000000ee`6d37c5f0 000000ee`6d37c5e0 : nt!IopCreateFile+0x3d8
ffffd001`c70c6b40 fffff803`cd752fa3 : fffff6fb`7da05360 fffff6fb`40a6c0a8 fffff681`4d815760 ffff8ab8`92895e23 : nt!NtCreateFile+0x79
ffffd001`c70c6bd0 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`c70c6c40)
000000ee`6d37c568 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
000000ee`6d37c570 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
000000ee`6d37c578 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
000000ee`6d37c580 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

Utilisez la commande k pour afficher la pile des appels associée au thread.

0: kd> k
# Child-SP          RetAddr           Call Site
00 ffffd001`c70c62a8 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
01 ffffd001`c70c62b0 fffff800`7a0fb2c3 portcls!CPortPinWaveRT::Init+0x2e7
02 ffffd001`c70c6340 fffff800`7a0fc7f9 portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 ffffd001`c70c63c0 fffff800`7a180552 portcls!xDispatchCreate+0xd9
04 ffffd001`c70c6450 fffff800`7a109a9a ks!KsDispatchIrp+0x272
05 ffffd001`c70c6510 fffff800`7bd314b1 portcls!DispatchCreate+0x7a
06 ffffd001`c70c6540 fffff803`cda1bfa8 ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 ffffd001`c70c65a0 fffff803`cda7b306 nt!IopParseDevice+0x7c8
08 ffffd001`c70c6770 fffff803`cda12916 nt!IopParseFile+0xb6
09 ffffd001`c70c67d0 fffff803`cda1131c nt!ObpLookupObjectName+0x776
0a ffffd001`c70c6970 fffff803`cd9fedb8 nt!ObOpenObjectByNameEx+0x1ec
0b ffffd001`c70c6a90 fffff803`cd9fe919 nt!IopCreateFile+0x3d8
0c ffffd001`c70c6b40 fffff803`cd752fa3 nt!NtCreateFile+0x79
0d ffffd001`c70c6bd0 00007fff`69805b74 nt!KiSystemServiceCopyEnd+0x13
0e 000000ee`6d37c568 00007fff`487484e6 0x00007fff`69805b74
0f 000000ee`6d37c570 0000029b`00000003 0x00007fff`487484e6
10 000000ee`6d37c578 00000000`0000012e 0x0000029b`00000003
11 000000ee`6d37c580 00000000`00000000 0x12e

Entrez g dans le débogueur pour exécuter le code jusqu'à ce que le clip multimédia ait terminé de jouer. Ensuite, connectez-vous au débogueur en appuyant sur Ctrl - ScrLk (Ctrl-Break) Utilisez la commande !thread pour confirmer que vous exécutez maintenant un autre thread.

0: kd> !thread
THREAD ffffe001ce80b840  Cid 17e4.01ec  Teb: 00000071fa9b9000 Win32Thread: ffffe001d41690d0 RUNNING on processor 0
Not impersonating
DeviceMap                 ffffc0001974e2c0
Owning Process            ffffe001d1760840       Image:         rundll32.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      538040         Ticks: 0
Context Switch Count      3181840        IdealProcessor: 0             
UserTime                  00:00:08.250
KernelTime                00:00:10.796
Win32 Start Address 0x00007ff6d2f24270
Stack Init ffffd001cd16afd0 Current ffffd001cd16a730
Base ffffd001cd16b000 Limit ffffd001cd165000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5

Child-SP          RetAddr           : Args to Child                                                           : Call Site
fffff803`cf373d18 fffff800`7a202852 : fffff803`cf373e60 00000000`00000001 ffffe001`cf4ed330 00000000`0000ffff : nt!DbgBreakPointWithStatus
fffff803`cf373d20 fffff803`cd6742c6 : ffffe001`cf4ed2f0 fffff803`cf373e60 00000000`00000001 00000000`0004e4b8 : kdnic!TXSendCompleteDpc+0x142
fffff803`cf373d60 fffff803`cd74d495 : 00000000`00000000 fffff803`cd923180 fffff803`cde1f4b0 fffff901`40669010 : nt!KiRetireDpcList+0x5f6
fffff803`cf373fb0 fffff803`cd74d2a0 : 00000000`00000090 0000000e`0000006a 00000000`00000092 00000000`00000000 : nt!KxRetireDpcList+0x5 (TrapFrame @ fffff803`cf373e70)
ffffd001`cd16a6c0 fffff803`cd74bd75 : 00000000`00000000 fffff803`cd74a031 00000000`00000000 00000000`00000000 : nt!KiDispatchInterruptContinue
ffffd001`cd16a6f0 fffff803`cd74a031 : 00000000`00000000 00000000`00000000 ffffe001`cff4d2a0 fffff803`cd67738e : nt!KiDpcInterruptBypass+0x25
ffffd001`cd16a700 fffff960`50cdb5a4 : fffff901`400006d0 00000000`00000001 fffff901`40000d60 ffffd001`cd16a9f0 : nt!KiInterruptDispatchNoLockNoEtw+0xb1 (TrapFrame @ ffffd001`cd16a700)
ffffd001`cd16a890 fffff960`50c66b2f : 00000000`00000000 fffff901`40669010 fffff901`42358580 fffff901`40000d60 : win32kfull!Win32FreePoolImpl+0x34
ffffd001`cd16a8c0 fffff960`50c68cd6 : 00000000`00000000 ffffd001`cd16a9f0 fffff901`400006d0 fffff901`400c0460 : win32kfull!EXLATEOBJ::vAltUnlock+0x1f
ffffd001`cd16a8f0 fffff803`cd752fa3 : 00000000`00000000 00000000`00000000 ffffe001`ce80b840 00000000`00000000 : win32kfull!NtGdiAlphaBlend+0x1d16
ffffd001`cd16add0 00007fff`674c1494 : 00007fff`674b1e97 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`cd16ae40)
00000071`fa74c9a8 00007fff`674b1e97 : 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 00000000`00ffffff : 0x00007fff`674c1494
00000071`fa74c9b0 0000a7c6`daee0559 : 00000000`00000001 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 : 0x00007fff`674b1e97
00000071`fa74c9b8 00000000`00000001 : 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 00000000`01010bff : 0x0000a7c6`daee0559
00000071`fa74c9c0 0000020b`741f3c50 : 00000000`00ffffff 00000000`00000030 00000000`01010bff 00000000`00000000 : 0x1
00000071`fa74c9c8 00000000`00ffffff : 00000000`00000030 00000000`01010bff 00000000`00000000 00000000`000000c0 : 0x0000020b`741f3c50
00000071`fa74c9d0 00000000`00000030 : 00000000`01010bff 00000000`00000000 00000000`000000c0 00000000`00000030 : 0xffffff
00000071`fa74c9d8 00000000`01010bff : 00000000`00000000 00000000`000000c0 00000000`00000030 00000071`00000030 : 0x30
00000071`fa74c9e0 00000000`00000000 : 00000000`000000c0 00000000`00000030 00000071`00000030 00000071`01ff8000 : 0x1010bff

Le nom de l’image est rundll32.exe, ce qui n’est en effet pas le nom de l’image associé à la lecture du clip multimédia.

Note Pour définir le thread actuel, tapez .thread < numéro de thread >.

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

threads et processus

Modification des contextes

Section 11 : IRQL, registres et désassemblement

Afficher le runtime d’intégration enregistré

Dans la section 11, vous allez afficher l’IRQL, ainsi que le contenu des registres.

<- Sur le système hôte

Le niveau de demande d’interruption (IRQL) est utilisé pour gérer la priorité de la maintenance des interruptions. Chaque processeur a un paramètre IRQL que les threads peuvent augmenter ou réduire. Les interruptions qui se produisent au niveau ou en dessous du paramètre IRQL du processeur sont masquées et n’interfèrent pas avec l’opération actuelle. Les interruptions qui se produisent au-dessus du paramètre IRQL du processeur sont prioritaires sur l’opération actuelle. L’extension !irql affiche le niveau de demande d’interruption (IRQL) sur le processeur actuel de l’ordinateur cible avant l’arrêt du débogueur. Lorsque l’ordinateur cible passe en mode débogueur, l'IRQL change, mais l'IRQL qui était en vigueur juste avant la pause du débogueur est enregistré et s’affiche par !irql.

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

< Afficher les registres et désassembler

Afficher les registres

Affichez le contenu des registres pour le thread actif sur le processeur actuel à l’aide de la commande r (Registers).

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

Vous pouvez également afficher le contenu des registres en sélectionnant Afficher>les registres.

Capture d’écran de la fenêtre WinDbg affichant environ 12 registres.

L’affichage du contenu des registres peut être utile lors de l’exécution de code du langage d’assembly et dans d’autres scénarios. Pour plus d’informations, consultez r (Registres).

Pour plus d’informations sur le contenu du registre, consultez architecture x86 et architecture x64.

Démontage

Vous pouvez désassembler le code sous exécution pour afficher le code du langage d’assembly en cours d’exécution en sélectionnant Afficher> ledésassemblement.

Capture d’écran de la fenêtre désassembleur WinDbg montrant le code du langage d’assembly.

Pour plus d’informations sur le désassemblage du langage assembleur, voir Désassemblage x86 annoté et Désassemblage x64 annoté.

Section 12 : Utiliser la mémoire

Dans la section 12, vous allez utiliser des commandes de débogueur pour afficher le contenu de la mémoire.

Afficher la mémoire

Vous devrez peut-être examiner la mémoire pour identifier un problème ou inspecter des variables, des pointeurs, et ainsi de suite. Vous pouvez afficher la mémoire en tapant l’une des commandes d* <adresse> suivantes.

Db

Affiche les données dans les valeurs d’octet et les caractères ASCII.

Dd

Affiche les données sous forme de deux mots larges (4 octets).

du

Affiche les données sous forme de caractères Unicode.

"dw"

Affiche les données sous forme de valeurs word (2 octets) et de caractères ASCII.

Note Si vous tentez d’afficher une adresse non valide, son contenu s’affiche sous forme de points d’interrogation ( ?).

Vous pouvez également afficher la mémoire en sélectionnant Afficher> lamémoire. Utilisez le menu déroulant format d’affichage pour modifier l'affichage de la mémoire.

Capture d’écran de la fenêtre de visualisation de la mémoire de WinDbg avec différentes options de formats d’affichage.

  1. Pour afficher les données associées au contrôle de volume, définissez un point d’arrêt à déclencher sur la routine PropertyHandlerAudioEngineVolumeLevel à l’aide de la commande bm. Avant de définir le nouveau point d’arrêt, nous effacerons tous les points d’arrêt précédents à l’aide de bc *.

    kd> bc *
    
  2. Définissez un point d’arrêt à déclencher sur la routine PropertyHandlerAudioEngineVolumeLevel à l’aide de la commande bm.

    kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  3. Répertoriez les points d’arrêt pour confirmer que le point d’arrêt est correctement défini.

    kd> bl
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  4. Utilisez la commande g pour redémarrer l’exécution du code.

    Sur le système cible, ajustez le volume dans la barre d’état système. Cela provoquera le déclenchement du point d’arrêt.

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume:
    fffff80f`02c3a4b0 44894c2420      mov     dword ptr [rsp+20h],r9d
    
  5. Utilisez l’élément de menu Affichage>local pour afficher les variables locales. Notez la valeur actuelle de la variable IVolume.

  6. Vous pouvez afficher le type de données et la valeur actuelle de la variable IVolume dans l’exemple de code en tapant la commande dt et le nom de la variable.

    kd> dt lVolume
    Local var @ 0xa011ea50 Type long
    0n-6291456
    
  7. Le point d’arrêt est atteint à l'entrée de SetDeviceChannelVolume.

    STDMETHODIMP_(NTSTATUS) CMiniportWaveRT::SetDeviceChannelVolume(_In_  ULONG _ulNodeId, _In_ UINT32 _uiChannel, _In_  LONG  _Volume)
    {
        NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    
        PAGED_CODE ();
    
        DPF_ENTER(("[CMiniportWaveRT::SetEndpointChannelVolume]"));
        IF_TRUE_ACTION_JUMP(_ulNodeId != KSNODE_WAVE_AUDIO_ENGINE, ntStatus = STATUS_INVALID_DEVICE_REQUEST, Exit);
    
        // Snap the volume level to our range of steppings.
        LONG lVolume = VOLUME_NORMALIZE_IN_RANGE(_Volume); 
    
        ntStatus = SetChannelVolume(_uiChannel, lVolume);
    Exit:
        return ntStatus;
    }
    
  8. Essayez d’afficher la valeur à l’emplacement de mémoire d’IVolume à l’aide de la commande dt (Type d’affichage).

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

    Étant donné que la variable n’est pas encore définie, elle ne contient pas d’informations.

  9. Appuyez sur F10 pour exécuter la dernière ligne de code dans SetDeviceChannelVolume.

        return ntStatus;
    
  10. Affichez la valeur à l’emplacement de mémoire de IVolume à l’aide de la commande dt (Type d’affichage).

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

    Maintenant que la variable est active, une valeur de 6291456 est affichée dans cet exemple.

  11. Vous pouvez également afficher l'adresse mémoire de IVolume à l’aide de la commande ? (Évaluer l’expression).

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  12. L’adresse indiquée, ffffb780'b7eee664 est l’adresse de la variable lVolume. Utilisez la commande dd pour afficher le contenu de la mémoire à cet emplacement.

    kd>  dd ffffb780`b7eee664
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    ffffb780`b7eee674  ffffc98e e0495756 fffff80e c52d7008
    ffffb780`b7eee684  ffffc98e 00000000 fffff80e 00000000
    ffffb780`b7eee694  ffffc98e ffa00000 ffffb780 b7eee710
    ffffb780`b7eee6a4  ffffb780 00000000 00000000 c7477260
    ffffb780`b7eee6b4  ffffc98e b7eee7a0 ffffb780 b7eee6f0
    ffffb780`b7eee6c4  ffffb780 e04959ca fffff80e 00000000
    ffffb780`b7eee6d4  00000000 00000028 00000000 00000002
    
  13. Vous pouvez afficher les quatre premiers octets d’une adresse en spécifiant le paramètre de plage L4.

    kd> dd ffffb780`b7eee664 l4
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    
  14. Pour afficher les différents types de sortie de mémoire affichés, tapez les commandes du, da et db .

    kd> du ffffb780`b7eee664 
    ffffb780`b7eee664  ""
    
    kd> a ffffb780`b7eee664 
    ffffb780`b7eee664  ""
    
    kd> db 0xffffae015ff97664 
    ffffae01`5ff97664  00 80 bc ff 18 00 00 00-00 00 00 00 08 50 e0 51  .............P.Q
    ffffae01`5ff97674  00 c0 ff ff 56 57 da 56-0e f8 ff ff 08 50 e0 51  ....VW.V.....P.Q
    ffffae01`5ff97684  00 c0 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffae01`5ff97694  00 c0 ff ff aa 80 bc ff-01 ae ff ff 10 77 f9 5f  .............w._
    ffffae01`5ff976a4  01 ae ff ff 40 00 00 00-00 e6 ff ff 10 dc 30 55  ....@.........0U
    ffffae01`5ff976b4  00 c0 ff ff a0 77 f9 5f-01 ae ff ff f0 76 f9 5f  .....w._.....v._
    ffffae01`5ff976c4  01 ae ff ff ca 59 da 56-0e f8 ff ff 00 00 00 00  .....Y.V........
    ffffae01`5ff976d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

    Utilisez l’option df float pour afficher les données sous forme de nombres à virgule flottante simple précision (4 octets).

    df ffffb780`b7eee664 
    ffffb780`b7eee664          -1.#QNAN   3.3631163e-044                0        -2775.002
    ffffb780`b7eee674          -1.#QNAN  -5.8032637e+019         -1.#QNAN        -2775.002
    ffffb780`b7eee684          -1.#QNAN                0         -1.#QNAN                0
    ffffb780`b7eee694          -1.#QNAN         -1.#QNAN         -1.#QNAN  -2.8479408e-005
    

Écrire en mémoire

Comme pour les commandes utilisées pour lire la mémoire, vous pouvez utiliser les commandes e* pour modifier le contenu de la mémoire.

Commande Descriptif

unité(s)

Chaîne ASCII (non terminée par NULL)

UE

Chaîne Unicode (non terminée par NULL)

Ew

Valeurs de mot (2 octets)

eza

Chaîne ASCII terminée par NULL

ezu

Chaîne Unicode terminée par NULL

eb

Valeurs d’octets

non

Valeurs de mot double (4 octets)

L’exemple suivant montre comment remplacer la mémoire.

  1. Tout d’abord, recherchez l’adresse du lVolume utilisé dans l’exemple de code.

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  2. Remplacez cette adresse mémoire par de nouveaux caractères à l’aide de la commande eb .

    kd> eb 0xffffb780`b7eee664 11 11 11 11 11
    
  3. Affichez l’emplacement de mémoire pour vérifier que les caractères ont été remplacés en tapant la commande de base de données .

    kd> db 0xffffb780`b7eee664
    ffffb780`b7eee664  11 11 11 11 11 00 00 00-00 00 00 00 08 70 2d c5  .............p-.
    ffffb780`b7eee674  8e c9 ff ff 56 57 49 e0-0e f8 ff ff 08 70 2d c5  ....VWI......p-.
    ffffb780`b7eee684  8e c9 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffb780`b7eee694  8e c9 ff ff 00 00 a0 ff-80 b7 ff ff 10 e7 ee b7  ................
    ffffb780`b7eee6a4  80 b7 ff ff 00 00 00 00-00 00 00 00 60 72 47 c7  ............`rG.
    ffffb780`b7eee6b4  8e c9 ff ff a0 e7 ee b7-80 b7 ff ff f0 e6 ee b7  ................
    ffffb780`b7eee6c4  80 b7 ff ff ca 59 49 e0-0e f8 ff ff 00 00 00 00  .....YI.........
    ffffb780`b7eee6d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

Vous pouvez également modifier le contenu de la mémoire dans une fenêtre de surveillance ou des variables locales. Pour la fenêtre d'observation, il est possible de voir des variables en dehors du contexte de la trame actuelle. La modification de ces éléments n’est pas pertinente si elles ne sont pas dans le contexte.

Section 13 : Mettre fin à la session WinDbg

<-Sur le système hôte

Si vous souhaitez laisser le débogueur attaché, mais que vous souhaitez travailler sur la cible, supprimez les points d’arrêt à l’aide de bc *, afin que l’ordinateur cible n’essaie pas de se connecter au débogueur de l’ordinateur hôte. Utilisez ensuite la g commande pour autoriser l’ordinateur cible à réexécuter.

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

0: kd> qd

Pour plus d’informations, consultez Fin d’une session de débogage dans WinDbg (classique) dans la documentation de référence sur le débogage.

Section 14 : Ressources de débogage Windows

Des informations supplémentaires sont disponibles sur le débogage Windows. Notez que certains de ces livres utilisent des versions antérieures de Windows telles que Windows Vista dans leurs exemples, mais les concepts abordés s’appliquent à la plupart des versions de Windows.

Livres

  • Débogage Windows avancé par Mario Hewardt et Daniel Pravat

  • Débogage Windows en profondeur : Guide pratique de débogage et de traçabilité des stratégies dans Windows® par Tarik Soulami

  • Windows Internals by Pavel Yosifovich, Alex Ionescu, Mark Russinovich et David Salomon

Vidéo

L'émission Defrag Tools présente les épisodes WinDbg 13-29 : </shows/defrag-tools/>

Fournisseurs de formation :

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

Voir aussi

Commencer avec le débogage Windows