Déboguer les pilotes : atelier pas à pas (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.
Microsoft Windows Debugger (WinDbg) est un puissant outil de débogage basé sur Windows que vous pouvez utiliser pour effectuer un débogage en mode utilisateur et en mode noyau. WinDbg fournit un débogage au niveau du code source pour le noyau Windows, les pilotes en mode noyau et les services système, ainsi que pour les applications et les pilotes en mode utilisateur.
WinDbg peut parcourir le code source, définir des points d’arrêt, afficher les variables (y compris les objets C++), les traces de pile et la mémoire. Sa fenêtre de commande de débogueur permet à l’utilisateur d’émettre une grande variété de commandes.
Configuration du laboratoire
Vous aurez besoin du matériel suivant pour pouvoir terminer le laboratoire :
- Un ordinateur portable ou de bureau (hôte) exécutant Windows 10
- Un ordinateur portable ou de bureau (cible) exécutant Windows 10
- Un hub/routeur réseau et des câbles réseau pour connecter les deux PC
- Un accès à Internet pour télécharger des fichiers de symboles
Vous aurez besoin du logiciel suivant pour pouvoir effectuer le laboratoire :
- Microsoft Visual Studio 2017
- Kit de développement logiciel (SDK) Windows pour Windows 10
- Kit de développement de pilotes Windows (WDK) pour Windows 10
- Le pilote audio Sysvad d’exemple pour Windows 10
Pour obtenir des informations sur le téléchargement et l’installation du WDK, veuillez consulter la rubrique Télécharger le Kit de développement de pilotes Windows (WDK).
Guide de débogage Sysvad
Ce laboratoire vous guide à travers le processus de débogage d’un pilote en mode noyau. Les exercices utilisent l’échantillon de pilote audio virtuel Syvad. Étant donné que le pilote audio Syvad n’interagit pas avec du matériel audio réel, il peut être utilisé sur la plupart des appareils. Le laboratoire couvre les tâches suivantes :
- Section 1 : Se connecter à une session WinDbg en mode noyau
- Section 2 : Commandes et techniques de débogage en mode noyau
- Section 3 : Section 3: Télécharger et créer le pilote audio Sysvad
- Section 4 : Installer le pilote audio Sysvad sur le système cible
- Section 5 : Utiliser WinDbg pour afficher des informations sur le pilote
- Section 6 : Afficher les informations de l’arborescence des appareils Plug-and-Play
- Section 7 : Utiliser des points d’arrêt et du code source
- Section 8 : Examiner les variables
- Section 9 : Afficher les piles d’appels
- Section 10 : Afficher les processus et les threads
- Section 11 : IRQL, registres et désassemblement
- Section 12 : Utiliser la mémoire
- Section 13 : Fin de la session WinDbg
- Section 14 : Ressources de débogage Windows
Laboratoire du pilote Echo
Le pilote Echo est un pilote plus simple que le pilote audio Sysvad. Si vous êtes novice dans WinDbg, vous voudrez peut-être envisager de terminer d’abord le Laboratoire pas à pas des pilotes universels - Mode noyau Echo. Ce laboratoire réutilise les instructions de configuration de ce laboratoire, donc si vous l’avez terminé, vous pouvez sauter les sections 1 et 2 ici.
Section 1 : Se connecter à une session WinDbg en mode noyau
Dans la section 1, vous configurerez le débogage réseau sur le système 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 en mode 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/routeur réseau et des câbles réseau pour connecter les deux PC.
Pour travailler avec des applications en mode noyau et utiliser WinDbg, nous vous recommandons d’utiliser le transport KDNET sur Ethernet. Pour obtenir des informations sur l’utilisation du protocole de transport Ethernet, veuillez consulter la rubrique Bien démarrer avec WinDbg (Mode noyau). Pour plus d’informations sur la configuration de l’ordinateur cible, veuillez consulter les rubriques Préparer un ordinateur pour le déploiement manuel du pilote et Configuration du débogage du noyau réseau KDNET automatiquement.
Configurer le débogage en mode noyau en utilisant Ethernet
Pour activer le débogage en mode noyau sur le système cible, effectuez les étapes suivantes.
<- Sur le système hôte
- Ouvrez une invite de commande 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 . . . . . . . . . :
Notez l’adresse IP du système hôte : ______________________________________
Notez le nom d’hôte du système hôte : ______________________________________
-> Sur le système cible
- Ouvrez une invite de commande 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 notée au lieu de 169.182.1.1 qui est affichée dans la sortie d’exemple.
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, effectuez les étapes suivantes.
Sur le système hôte, localisez le répertoire KDNET de WDK. Par défaut, il est situé 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 sur le système cible et hôte. Si ce n’est pas le cas, la meilleure approche est d’exécuter la même « bitness » d’outils sur l’hôte que la cible exécute. Par exemple, si le système cible exécute Windows 32 bits, exécutez une version 32 bits du débogueur sur le système hôte. Pour plus d’informations, consultez Choisir les outils de débogage 32 bits ou 64 bits.
Localisez ces deux fichiers et copiez-les dans un partage réseau ou une clé USB, de sorte qu’ils soient disponibles sur l’ordinateur cible.
kdnet.exe
VerifiedNICList.xml
Sur l’ordinateur cible, ouvrez une fenêtre d’invite de commande en tant qu’administrateur. Entrez cette commande pour valider que la carte NIC 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
- Saisissez 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 notée au lieu de 169.182.1.1 qui est affichée dans la sortie d’exemple. Choisissez un numéro de port unique pour chaque paire cible/hôte avec laquelle vous travaillez, comme 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é de Windows telles que BitLocker et Secure Boot sur le PC de test. Réactivez ces fonctionnalités de sécurité lorsque les tests sont terminés et gérez de manière appropriée le PC de test lorsque ces fonctionnalités de sécurité sont désactivées. Le démarrage sécurisé est généralement désactivé dans l’UEFI. Pour accéder aux paramètres de l’UEFI, utilisez Système, Récupération, Démarrage avancé. Au redémarrage, sélectionnez Dépannage, Options avancées, Paramètres du microprogramme UEFI. Faites preuve de prudence, car la définition incorrecte des options de l’UEFI ou la désactivation de BitLocker peuvent rendre le système inopérable.
- Saisissez 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 à la 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.
<- Sur le système hôte
- Sur l’ordinateur hôte, ouvrez une fenêtre d’invite de commandes en tant qu’administrateur. Changez vers le répertoire WinDbg.exe. Nous utiliserons la version x64 de WinDbg.exe du Kit de développement de pilotes Windows (WDK) qui a été installée dans le cadre de l’installation du kit Windows.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
- Lancez WinDbg avec le débogage utilisateur à distance en utilisant la commande suivante. La valeur de la clé et du port correspond à ce que vous avez défini précédemment en utilisant 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
En une minute ou deux, les sorties de débogage devraient s’afficher sur le système hôte.
La fenêtre de commande du débogueur est la principale fenêtre d’information de débogage dans WinDbg. Vous pouvez saisir des commandes de débogueur et afficher la sortie de commande dans cette fenêtre.
La fenêtre de commande du débogueur est divisée en deux panneaux. Vous saisissez des commandes dans le volet plus petit (le volet de saisie de commande) en bas de la fenêtre et affichez la sortie des commandes dans le volet plus grand en haut de la fenêtre.
Dans le volet de saisie de commande, utilisez les touches fléchées haut et bas pour faire défiler l’historique des commandes. Lorsqu’une commande apparaît, vous pouvez l’éditer 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 utiliserez 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 en utilisant le langage de balisage du débogueur que vous pouvez sélectionner pour obtenir rapidement plus d’informations.
- Utilisez Ctrl+Pause (Verr Num) dans WinDBg pour interrompre le code en cours d’exécution sur le système cible. Il peut falloir un peu de temps pour que le système cible réponde.
- Saisissez la commande suivante pour activer DML dans la fenêtre de commande du débogueur.
0: kd> .prefer_dml 1
DML versions of commands on by default
Utilisez .hh pour obtenir de l’aide
Vous pouvez accéder à l’aide de commande de référence en utilisant la commande .hh.
- Saisissez la commande suivante pour afficher l’aide de référence pour la commande .prefer_dml.
0: kd> .hh .prefer_dml
Le fichier d’aide du débogueur affichera l’aide pour la commande .prefer_dml.
Afficher la version de Windows sur le système cible
- Affichez des informations détaillées sur la version du système cible en entrant 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
Lister les modules chargés
- Vous pouvez vérifier que vous travaillez avec le bon processus en mode noyau en affichant les modules chargés en entrant la commande lm (Lister les modules chargés) 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
...
Remarque : Les sorties omises sont indiquées par « ... » dans ce laboratoire.
Étant donné que nous n’avons pas encore défini le chemin des symboles et chargé les symboles, des informations limitées sont disponibles dans le débogueur.
Section 3: Télécharger et créer le pilote audio Sysvad
Dans la section 3, vous téléchargerez et créerez le pilote audio Sysvad.
Généralement, vous travailleriez avec votre propre code de pilote lorsque vous utilisez WinDbg. Pour vous familiariser avec le débogage des pilotes audio, l’échantillon de pilote audio virtuel Sysvad est utilisé. Cet échantillon est utilisé pour illustrer comment vous pouvez effectuer un pas à pas dans le code natif en mode noyau. Cette technique peut être très utile pour déboguer des problèmes complexes de code en mode noyau.
Pour télécharger et créer l’échantillon de pilote audio Sysvad, effectuez les étapes suivantes.
Télécharger et extraire l’échantillon audio Sysvad depuis GitHub
Vous pouvez utiliser un navigateur pour afficher l’échantillon Sysvad et le fichier Readme.md ici :
https://github.com/Microsoft/Windows-driver-samples/tree/main/audio/sysvad
Ce laboratoire montre comment télécharger les échantillons de pilotes universels dans un seul 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 enfoncé (ou faites un clic droit) Windows-driver-samples-master.zip, et choisissez Extraire tout. Spécifiez un nouveau dossier ou parcourez-en un existant qui stockera les fichiers extraits. Par exemple, vous pourriez spécifier C:\WDK_Samples\ comme nouveau dossier dans lequel les fichiers sont extraits.
c. Après l’extraction des fichiers, accédez au sous-dossier suivant.
C:\WDK_Samples\Sysvad
Ouvrez la solution du pilote dans Visual Studio
Dans Visual Studio, sélectionnez Fichier>Ouvrir>Projet/Solution... et naviguez vers le dossier contenant les fichiers extraits (par exemple, C:\WDK_Samples\Sysvad). Double-cliquez sur le fichier de solution Syvad.
Dans Visual Studio, localisez l’Explorateur de solutions. (Si ce n’est pas déjà ouvert, choisissez Explorateur de solutions dans le menu Affichage.) Dans l’Explorateur de solutions, vous pouvez voir une solution qui comporte plusieurs projets.
Définissez la configuration et la plateforme de l’échantillon
Dans l’Explorateur de solutions, sélectionnez et maintenez enfoncé (ou faites un clic droit) Solution « sysvad » (7 of 7 projects), et choisissez Gestionnaire de configuration. Assurez-vous que les paramètres de configuration et de plateforme sont les mêmes pour les quatre projets. Par défaut, la configuration est définie sur « Win10 Debug » et la plateforme est définie sur « Win64 » pour tous les projets. Si vous apportez des modifications de configuration et/ou de plateforme à un projet, vous devez apporter les mêmes modifications aux trois autres projets.
Remarque : Ce laboratoire suppose que Windows 64 bits est utilisé. Si vous utilisez Windows 32 bits, construisez le pilote pour 32 bits.
Vérifier la signature du pilote
Localisez le TabletAudioSample. Ouvrez la page de propriétés du pilote Sysvad et assurez-vous que le Mode de signature>Signature du pilote est sur Signature test.
Les échantillons de pilotes doivent être modifiés pour utiliser des valeurs qui ne chevauchent pas les pilotes existants. Consultez De l’exemple de code au pilote de production - Ce qu’il faut changer dans les exemples pour connaître la façon de créer un échantillon de pilote unique qui coexistera avec les pilotes réels existants installés dans Windows.
Générez l’exemple à l’aide de Visual Studio
Dans Visual Studio, sélectionnez Build>Build Solution.
La fenêtre de build devrait afficher un message indiquant que la build pour les six projets a réussi.
Conseil
Si vous rencontrez un message d’erreur de build, utilisez le numéro d’erreur de build pour déterminer une solution. Par exemple, Erreur MSBuild MSB8040 décrit comment travailler avec des bibliothèques atténuées par spectre.
Localisez les fichiers de pilotes générés
Dans l’Explorateur de fichiers, accédez au dossier contenant les fichiers extraits pour l’échantillon. Par exemple, accédez à C :\WDK_Samples\Sysvad, s’il s’agit du dossier que vous avez spécifié précédemment. Dans ce dossier, l’emplacement des fichiers du pilote compilé varie en fonction des paramètres de configuration et de plate-forme que vous avez sélectionnés dans le Gestionnaire de configuration. Par exemple, si vous n’avez pas modifié les paramètres par défaut, alors les fichiers du pilote compilé seront 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 contient le pilote TabletAudioSample .SYS, le fichier de symbole pdp et le fichier inf. Vous devrez également localiser les fichiers dll et symboles DelayAPO, KWSApo et KeywordDetectorContosoAdapter.
Pour installer le pilote, vous aurez besoin des fichiers suivants.
Nom de fichier Description TabletAudioSample.sys Le fichier pilote. TabletAudioSample.pdb Le fichier de symbole du pilote. tabletaudiosample.inf Un fichier d’informations (INF) qui contient les informations nécessaires pour installer le pilote. KeywordDetectorContosoAdapter.dll Un exemple de détecteur de mot clé. KeywordDetectorContosoAdapter.pdb L’exemple de fichier de symboles de détecteur de mots clés. DelayAPO.dll Un exemple de délai APO. DelayAPO.pdb Le fichier de symbole de délai APO. KWSApo.dll Un exemple de détecteur de mot clé APO. KWSApo.pdb Le fichier de symbole du détecteur de mots-clés. TabletAudioSample.cer Le fichier de certificat TabletAudioSample. Localisez une clé USB ou configurez un partage réseau pour copier les fichiers du pilote construit de l’hôte vers le système cible.
Dans la section suivante, vous allez copier le code vers le système cible, et installer et tester le pilote.
Section 4 : Installer l’échantillon de pilote audio Sysvad sur le système cible
Dans la section 4, vous utiliserez 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. Généralement, il s’agit d’un ordinateur différent de celui sur lequel vous développez et construisez le package de pilotes. L’ordinateur sur lequel vous développez et construisez le pilote est appelé l’ordinateur hôte.
Le processus de déplacement du package de pilotes vers l’ordinateur cible et l’installation du pilote est appelé déploiement du pilote.
Avant de déployer un pilote, vous devez préparer l’ordinateur cible en activant la signature de test. Après cela, vous êtes prêt à exécuter l’échantillon de pilote construit sur le système cible.
Pour installer le pilote sur le système cible, effectuez les étapes suivantes.
Activer les pilotes signés pour les tests
Pour activer la possibilité d’exécuter des pilotes signés pour les tests :
Ouvrez Paramètres Windows.
Dans Mise à jour et sécurité, sélectionnez Récupération.
Sous Démarrage avancé, sélectionnez Redémarrer Maintenant.
Lorsque l’ordinateur redémarre, sélectionnez Résolution des problèmes.
Puis sélectionnez Options avancées, Paramètres de démarrage et ensuite sélectionnez Redémarrer.
Sélectionnez Désactiver l’application de la signature du pilote en appuyant sur la touche F7.
L’ordinateur démarrera avec les nouvelles valeurs en place.
-> Sur le système cible
Installer le pilote
Les instructions suivantes vous montrent comment installer et tester le pilote d’échantillon.
Le fichier INF requis pour installer ce pilote est TabletAudioSample.inf. Sur l’ordinateur cible, ouvrez une fenêtre d’invite de commande en tant qu’administrateur. Rendez-vous dans le dossier de votre package de pilotes, faites un clic droit sur le fichier TabletAudioSample.inf, puis sélectionnez Installer.
Une boîte de dialogue apparaîtra indiquant que le pilote de test est un pilote non signé. Sélectionnez Installer ce pilote quand même pour continuer.
Conseil
Si vous rencontrez des problèmes avec l’installation, vérifiez le fichier suivant pour plus d’informations.
%windir%\inf\setupapi.dev.log
Pour des instructions plus détaillées, veuillez consulter la section Configuration d’un ordinateur pour le déploiement, les tests et le débogage de pilotes.
Le fichier INF contient l’ID matériel pour installer le tabletaudiosample.sys. Pour l’échantillon Syvad, l’ID matériel est :
root\sysvad_TabletAudioSample
Examiner le pilote dans le Gestionnaire de périphériques
Sur l’ordinateur cible, dans une fenêtre d’invite de commandes, saisissez devmgmt pour ouvrir le Gestionnaire de périphériques. Dans le Gestionnaire de périphériques, dans le menu Affichage, sélectionnez Périphériques par type.
Dans l’arborescence des périphériques, localisez Virtual Audio Device (WDM) - Tablet Sample dans le nœud Périphérique audio. Il s’agit généralement du nœud Contrôleurs audio, vidéo et de jeu. Confirmez qu’il est installé et actif.
Sélectionnez le pilote du matériel audio réel sur l’ordinateur dans le Gestionnaire de périphériques. Puis sélectionnez et maintenez enfoncé (ou faites un clic droit) sur le pilote et sélectionnez désactiver pour désactiver le pilote.
Confirmez dans le Gestionnaire de périphériques que le pilote de matériel audio affiche une flèche vers le bas, indiquant qu’il est désactivé.
Après avoir installé avec succès le pilote d’exemple, vous êtes maintenant prêt à le tester.
Tester le pilote audio Sysvad
Sur l’ordinateur cible, dans une fenêtre d’invite de commandes, saisissez devmgmt pour ouvrir le Gestionnaire de périphériques. Dans le Gestionnaire de périphériques, dans le menu Affichage, sélectionnez Périphériques par type. Dans l’arborescence des périphériques, localisez Virtual Audio Device (WDM) - Tablet Sample.
Ouvrez le Panneau de configuration et rendez-vous dans 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 Virtual Audio Device (WDM) - Tablet Sample, puis sélectionnez Définir par défaut, mais ne sélectionnez pas OK. Cela gardera la boîte de dialogue Son ouverte.
Localisez un fichier audio MP3 ou autre sur l’ordinateur cible et double-cliquez dessus pour le lire. Ensuite, dans la boîte de dialogue Son, vérifiez s’il y a de l’activité dans l’indicateur de niveau de volume associé au pilote Virtual Audio Device (WDM) - Tablet Sample.
Section 5 : Utiliser WinDbg pour afficher des informations sur le pilote
Dans la section 5, vous allez définir le chemin des symboles et utiliser des commandes de débogueur noyau pour afficher des informations sur le pilote d’échantillon Sysvad.
Les symboles permettent à WinDbg d’afficher des informations supplémentaires telles que les noms de variables, qui peuvent être inestimables lors du débogage. WinDbg utilise les formats de symboles de débogage de Microsoft Visual Studio pour le débogage au niveau du code source. Il peut accéder à tout symbole ou variable à partir d’un module qui possède des fichiers de symboles PDB.
Pour charger le débogueur, effectuez les étapes suivantes.
<-Sur le système hôte
Si vous avez fermé le débogueur, ouvrez-le à nouveau en utilisant la commande suivante dans la fenêtre d’invite de commande administrateur. Remplacez la clé et le port par ce que vous avez configuré précédemment.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Utilisez Ctrl+Arrêt (verrouillage de défilement) pour entrer dans le code en cours d’exécution sur le système cible.
Définissez le chemin d’accès aux symboles
Pour définir le chemin des symboles sur le serveur de symboles Microsoft dans l’environnement WinDbg, utilisez la commande .symfix.
0: kd> .symfix
Pour ajouter votre emplacement de symbole local pour utiliser vos symboles locaux, ajoutez le chemin en utilisant .sympath+ et ensuite .reload /f.
0: kd> .sympath+ C:\WDK_Samples\Sysvad 0: kd> .reload /f
Remarque : La commande .reload avec l’option de force /f supprime toutes les informations de symbole pour le module spécifié et recharge les symboles. Dans certains cas, cette commande recharge ou décharge également le module lui-même.
Remarque : Vous devez charger les symboles appropriés pour utiliser les fonctionnalités avancées que fournit WinDbg. Si vous n’avez pas correctement configuré les symboles, vous recevrez des messages indiquant que les symboles ne sont pas disponibles lorsque vous essayez d’utiliser des fonctionnalités qui dépendent des symboles.
0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.
Notezles serveurs de symboles
Il existe plusieurs approches qui peuvent être utilisées pour travailler avec des symboles. Dans de nombreuses situations, vous pouvez configurer l’ordinateur pour accéder aux symboles à partir d’un serveur de symboles que Microsoft fournit quand ils sont nécessaires. Cette présentation suppose que cette approche sera utilisée. Si les symboles dans votre environnement sont à un emplacement différent, modifiez les étapes pour utiliser cet emplacement. Pour plus d’informations, veuillez consulter la rubrique Chemin des symboles pour le débogueur Windows.
RemarqueComprendre les exigences en matière de symboles de code source
Pour effectuer un débogage de source, vous devez construire une version vérifiée (débogage) de vos binaires. Le compilateur créera des fichiers de symboles (.pdb). Ces fichiers de symboles montreront au débogueur comment les instructions binaires correspondent aux lignes de code source. Les fichiers source eux-mêmes doivent également être accessibles au débogueur.
Les fichiers de symboles ne contiennent pas le texte du code source. Pour le débogage, il est préférable que le lien n’optimise pas votre code. Le débogage de source et l’accès aux variables locales sont plus difficiles, voire parfois presque impossibles, si le code a été optimisé. Si vous rencontrez des problèmes pour afficher les variables locales ou les lignes source, définissez les options de construction suivantes.
set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
Saisissez ce qui suit dans la zone de commande du débogueur pour afficher des informations sur 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, voir lm.
Sélectionnez le lien Parcourir tous les symboles globaux dans la sortie de débogage pour afficher des informations sur les symboles qui commencent par la lettre a.
Comme DML est activé, certains éléments de la sortie sont des liens hypertexte que vous pouvez sélectionner. Sélectionnez le lien données dans la sortie de débogage pour afficher des informations sur les symboles 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, voir x (Examiner les symboles).
L’extension !lmi affiche des informations détaillées sur un module. Saisissez !lmi tabletaudiosample. Votre sortie devrait ê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
Utilisez l’extension !dh pour afficher des 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 : Afficher les informations de l’arborescence des appareils Plug-and-Play
Dans la section 6, vous afficherez des informations sur le pilote de l’échantillon Sysvad et où il se trouve dans l’arborescence des périphériques Plug and Play.
Les informations sur le pilote de périphérique dans l’arbre des périphériques Plug and Play peuvent être utiles pour le dépannage. Par exemple, si un pilote de périphérique n’est pas résident dans l’arborescence des périphériques, il peut y avoir un problème avec l’installation du pilote de périphérique.
Pour plus d’informations sur l’extension de débogage de nœud de périphérique, veuillez consulter !devnode.
<-Sur le système hôte
Pour voir tous les nœuds de périphériques dans l’arborescence des périphériques Plug and Play, saisissez la commande !devnode 0 1. Cette commande peut prendre une minute ou deux pour s’exécuter. Pendant ce temps, « *Occupé » sera affiché 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… ...
Utilisez Ctrl+F pour rechercher dans la sortie générée le nom du pilote de périphérique, sysvad.
Une entrée de nœud de périphérique avec un nom de
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.
Utilisez la commande
!devnode 0 1 sysvad_TabletAudioSample
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)
La sortie affichée dans la commande précédente inclut le PDO associé à l’instance en cours d’exécution de notre pilote, dans cet exemple c’est 0xffffe00089c575a0. Saisissez 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, pas 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.
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 bits de 2, pour afficher les informations associées au périphérique 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
Saisissez la commande !devstack<PDO address> pour afficher les informations Plug and Play associées au pilote de 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, pas celle affiché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 montre que nous avons une pile de pilotes de périphériques assez simple. Le pilote sysvad_TabletAudioSample est un enfant du nœud PnPManager. PnPManager est un nœud racine.
Ce schéma montre un arbre de nœuds de périphériques plus complexe.
Remarque : Pour plus d’informations sur les piles de pilotes plus complexes, veuillez consulter les sections Empilements de pilotes et Nœuds de périphériques et piles de périphériques.
Section 7 : Utilisation de points d’arrêt
Dans la section 7, vous travaillerez avec 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 particulière du code. 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 restera actif jusqu’à ce que le module dans lequel il se trouve soit déchargé. |
bu |
Définit un point d’arrêt qui est résolu lorsque le module est déchargé et réactivé lorsque le module se recharge. |
bm |
Définit un point d’arrêt pour un symbole. Cette commande utilisera bu ou bp de manière appropriée et permet l’utilisation de jokers * pour définir des points d’arrêt sur tous les symboles correspondants (comme toutes les méthodes dans une classe). |
Utilisez l’interface utilisateur de WinDbg pour confirmer que le Débogage>Mode SOurce est activé dans la session WinDbg actuelle.
Ajoutez votre emplacement de code local au chemin des sources en tapant la commande suivante.
.sympath+ C:\WDK_Samples\Sysvad
Ajoutez l’emplacement de votre symbole local au chemin des symboles en tapant la commande suivante.
.sympath+ C:\WDK_Samples\Sysvad
Définir le masque de débogage
Comme vous travaillez avec un pilote, il peut être utile de voir tous les messages qu’il peut afficher. Saisissez la commande suivante pour modifier le masque de débogage par défaut afin que tous les messages de débogage du système cible soient affichés dans le débogueur.
0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
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 en conjonction avec la définition de variables comme <module>!<symbol>, <class>::<method>,‘<file.cpp>:<line number>, ou sauter un certain nombre de fois <condition><#>. Pour plus d’informations, consultez Using Breakpoints.
Listez 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
Redémarrez l’exécution du code sur le système cible en tapant la commande g.
->Sur le système cible
En Windows, ouvrez le Gestionnaire de périphériques en utilisant l’icône ou en entrant mmc devmgmt.msc. Dans Gestionnaire de périphériques développez le nœud Contrôleur audio, vidéo et 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.
Sélectionnez et maintenez la touche enfoncée (ou cliquez avec le bouton droit) sur l’entrée du pilote audio virtuel à nouveau, puis sélectionnez Activer dans le menu.
<- Sur le système hôte
Cela devrait amener Windows à recharger le pilote, ce qui appelle AddDevice. Cela provoquera l’activation du point d’arrêt de débogage AddDevice et l’exécution du code du pilote sur le système cible devrait s’arrêter.
Breakpoint 1 hit tabletaudiosample!AddDevice: fffff801`14baf000 4889542410 mov qword ptr [rsp+10h],rdx
Si votre chemin 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
Passez ligne par ligne dans le code en tapant la commande p ou en appuyant sur F10. Vous pouvez avancer hors du code sysvad AddDevice vers PpvUtilCall, PnpCallAddDevice puis vers le code Windows PipCallDriverAddDevice. Vous pouvez fournir un nombre à la commande p pour avancer de plusieurs lignes, par exemple p 5.
Lorsque vous avez terminé de parcourir le code, utilisez la commande g pour redémarrer l’exécution sur le système cible.
Définition de 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’une adresse mémoire est accédée. Utilisez la commande ba (Pause sur Accès), avec la syntaxe suivante :
ba <access> <size> <address> {options}
Option | Description |
---|---|
e |
execute (lorsque le CPU récupère une instruction à partir de l’adresse) |
r |
read/write (lorsque le CPU lit ou écrit à l’adresse) |
w |
write (lorsque le CPU écrit à l’adresse) |
Notez que vous ne pouvez définir que quatre points d’arrêt de données à un moment donné et c’est à vous de vous assurer que vous alignez correctement vos données sinon le point d’arrêt ne se déclenchera pas (les mots doivent se terminer à des adresses divisibles par 2, les dwords doivent être divisibles par 4 et les quadwords par 0 ou 8)
Par exemple, pour définir un point d’arrêt de 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 les points d’arrêt existants en utilisant les commandes suivantes.
bl |
Liste les points d’arrêt. |
bc |
Efface un point d’arrêt de la liste. Utilisez bc * pour effacer tous les points d’arrêt. |
bd |
Désactive un point d’arrêt. Utilisez bd * pour désactiver tous les points d’arrêt. |
be |
Active un point d’arrêt. Utilisez be * pour activer tous les points d’arrêt. |
Alternativement, vous pouvez également modifier les points d’arrêt en sélectionnant Modifier>points d’arrêt. Notez que la boîte de dialogue des points d’arrêt ne fonctionne qu’avec les points d’arrêt existants. Les nouveaux points d’arrêt doivent être définis à partir de la ligne de commande.
Définissez un point d’arrêt sur MixerVolume
Différentes parties du code du pilote audio sont appelées pour répondre à divers événements, après le chargement du pilote de périphérique. Dans la section suivante, nous définissons un point d’arrêt qui se déclenchera lorsque l’utilisateur ajuste le contrôle du volume pour le pilote audio virtuel.
Pour définir un point d’arrêt sur MixerVolume, effectuez les étapes suivantes.
<- Sur le système hôte
Pour localiser la méthode qui modifie le volume, utilisez la commande x pour lister les symboles dans CAdapterCommon, qui contiennent la chaîne de caractères « volume ».
kd> x tabletaudiosample!CAdapterCommon::* ... fffff800`7bce26a0 tabletaudiosample!CAdapterCommon::MixerVolumeWrite (unsigned long, unsigned long, long) …
Utilisez CTRL+F pour rechercher vers le haut dans la sortie pour « volume » et localisez la méthode MixerVolumeWrite.
Effacez les points d’arrêt précédents en utilisant bc *.
Définissez un point d’arrêt symbolique sur la routine CAdapterCommon::MixerVolumeWrite en utilisant la commande suivante.
kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite 1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"
Listez 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
Redémarrez l’exécution du code sur le système cible en tapant la commande g.
Dans le Panneau de configuration, sélectionnez Matériel et audio>Son. Sélectionnez et maintenez enfoncé (ou faites un clic droit) sur Description de l’éviers d’échantillonnage et sélectionnez Propriétés. Sélectionnez l’onglet Niveaux. Ajustez le curseur du volume.
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 devriez vous arrêter à cette ligne dans common.cpp
{ if (m_pHW) { m_pHW->SetMixerVolume(Index, Channel, Value); } } // MixerVolumeWrite
Utilisez la commande dv pour afficher les variables actuelles et leurs valeurs. Plus d’informations sur les variables sont fournies dans la section suivante de ce laboratoire.
2: kd> dv this = 0x00000000`00000010 ulNode = 0x344 ulChannel = 0x210a45f8 lVolume = 0n24
Appuyez sur F10 pour passer en revue le code ligne par ligne.
Appuyez sur F5 pour terminer l’exécution du code MixerVolumeWrite.
Résumé - Parcours du code depuis la fenêtre de commande du débogueur
Voici les commandes que vous pouvez utiliser pour parcourir votre code (avec les raccourcis clavier associés indiqués entre parenthèses).
Interruption (Ctrl+Pause) : Cette commande interrompt un système tant que le système est en cours d’exécution et communique avec WinDbg (la séquence dans le Débogueur noyau est Ctrl+C).
Step over (F10) : Cette commande fait avancer l’exécution du code une instruction ou une instruction à la fois. Si un appel est rencontré, l’exécution du code passe par-dessus l’appel sans entrer dans la routine appelée. (Si le langage de programmation est C ou C++ et WinDbg est en mode source, le mode source peut être activé ou désactivé à l’aide de Debug>Source Mode).
Step in (F11) – Cette commande est similaire à Step over, sauf que l’exécution d’un appel entre dans la routine appelée.
Passer à l’extérieur (Shift+F11) – Cette commande provoque l’exécution pour sortir de la routine actuelle (lieu actuel dans la pile d’appels). C’est utile si vous avez vu assez de la routine.
Run to cursor (F7 ou Ctrl+F10) : placez le curseur dans une fenêtre source ou disassembly dans laquelle vous souhaitez que l’exécution s’interrompe, puis appuyez sur F7 ; l’exécution du code s’exécute à 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’interrompt pas, car l’exécution du code n’a pas atteint le point indiqué.
Run (F5) – Exécute jusqu’à ce qu’un point d’arrêt soit rencontré ou qu’un événement comme un contrôle de bug se produise.
Options avancées
Définir l’instruction sur la ligne actuelle (Ctrl+Shift+I) : Dans une fenêtre source, vous pouvez placer le curseur sur une ligne, entrer ce raccourci clavier, et l’exécution du code commencera à partir de ce point dès que vous le permettrez (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 : Le pas à pas est effectué par ligne source.
Sélectionnez Debug>Source Mode pour entrer en mode source ; la commande
L+t
n’est pas suffisante.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, veuillez consulter la rubrique Débogage de 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 la définition dynamique de points d’arrêt à l’aide des commandes de point d’arrêt.
Conseil : Vous souhaiterez peut-être conserver une copie du pilote Sysvad avec le point d’arrêt ajouté pour un travail de laboratoire supplémentaire.
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
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 à jour.
Effacez les points d’arrêt précédents et assurez-vous que le débogueur est attaché au PC cible.
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.
Utilisez la commande dv pour examiner les variables de paramètres régionaux associées au tabletaudiosample!CMiniportWaveRT::New*.
kd> dv tabletaudiosample!CMiniportWaveRT::New*
Effacer les points d’arrêt précédents
bc *
Définissez un point d’arrêt de symbole sur les routines CMiniportWaveCyclicStreamMSVAD en utilisant la commande suivante.
0: kd> bm tabletaudiosample!CMiniportWaveRT::NewStream 1: fffff801`177dffc0 @!"tabletaudiosample!CMiniportWaveRT::NewStream"
Redémarrez l’exécution du code sur le système cible en tapant la commande g.
-> 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.
<- 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’accolade à 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. --*/ { ...
Variables locales
Vous pouvez afficher les noms et les valeurs de toutes les variables locales pour une trame donnée en tapant la commande dv.
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
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
Variables globales
Vous pouvez trouver l’emplacement d’une mémoire de variable globale en tapant ? <nom de la variable>.
0: kd> ? signalProcessingMode Evaluate expression: -52768896396472 = ffffd001`c8acd348
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
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
Afficher les variables
Utilisez View>Locals pour afficher les variables locales. Cette interface offre également cette possibilité d’explorer les structures de données plus complexes.
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); } ...
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 maintenant pas dans le cadre actuel 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 examinerez les piles d’appels pour examiner le code appelant/appelé.
La pile d’appels est la chaîne d’appels de fonction qui ont conduit à l’emplacement actuel du compteur de programme. La fonction supérieure sur la pile d’appels est la fonction actuelle, et la fonction suivante est la fonction qui a appelé la fonction actuelle, et ainsi de suite.
Pour afficher la pile d’appels, utilisez les commandes k* :
kb |
Affiche la pile et les trois premiers paramètres. |
kp |
Affiche les piles et la liste complète des paramètres. |
kn |
Vous permet de voir la pile avec les informations de trame à côté. |
Si vous souhaitez conserver la pile d’appels disponible, vous pouvez sélectionner View>Call stack pour la visualiser. Sélectionnez les colonnes en haut de la fenêtre pour basculer l’affichage d’informations supplémentaires.
Cette sortie montre la pile d’appels lors du débogage du code d’adaptateur d’échantillon dans un état d’arrêt.
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 davantage 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 utiliserez des commandes de débogage pour afficher les processus et les threads.
Processus
Pour changer le contexte du processus actuel, utilisez la commande <.process>. L’exemple suivant montre comment identifier un processus et basculer son contexte.
Utilisez la commande
!process
pour afficher le processus actuel impliqué dans la lecture du son.Pour plus d’informations, voir !process.
La sortie montre 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 ce sujet, le processus actuel 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 thread prenait en charge la lecture du clip multimédia lorsque le point d’arrêt a été déclenché.
Utilisez la commande !process 0 0 pour afficher des informations récapitulatives pour tous les processus. Dans la sortie de la 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 plus tard dans ce laboratoire. ________________________
...
PROCESS ffffe001d147c840
SessionId: 0 Cid: 10f0 Peb: ee6cf8a000 ParentCid: 0434
DirBase: d2122000 ObjectTable: ffffc0001f191ac0 HandleCount: <Data Not Accessible>
Image: audiodg.exe
...
Saisissez g dans le débogueur pour exécuter le code vers l’avant jusqu’à ce que le clip multimédia soit terminé. Ensuite, interrompez dans le débogueur en appuyant sur Ctrl+ScrLk (Ctrl+Break) Utilisez la commande !process pour confirmer que vous exécutez maintenant un processus différent.
!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 montre System, et non pas audiodg.exe.
Utilisez maintenant la commande !process pour basculer vers le processus qui était 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.
Comme ce code n’est pas actif, tous les threads sont dans l’état WAIT, comme prévu.
Threads
Les commandes pour afficher et définir les 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, jouez à nouveau le clip multimédia. Si le point d’arrêt décrit dans la section précédente est toujours en place, vous vous arrêterez dans le contexte de audiodg.exe.
Utilisez !thread -1 0 pour afficher des informations succinctes sur le thread actuel. Cela montre l’adresse du thread, les IDs de thread et de processus, le bloc d’environnement du thread (TEB) address, l’adresse de la fonction Win32 (le cas échéant) pour laquelle le thread a été créé, 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, saisissez !thread. Des informations similaires à celles ci-dessus devraient ê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 d’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
Saisissez g dans le débogueur pour exécuter le code vers l’avant jusqu’à ce que le clip multimédia soit terminé. Ensuite, interrompez dans le débogueur en appuyant sur Ctrl - ScrLk (Ctrl-Break) Utilisez la commande !thread pour confirmer que vous exécutez maintenant un thread différent.
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.
Remarque Pour définir le thread actuel, saisissez .thread <numéro de thread>.
Pour plus d’informations sur les threads et les processus, consultez les références suivantes :
Section 11 : IRQL, registres et désassemblement
Afficher l’IRQL enregistré
Dans la section 11, vous afficherez le niveau IRQL et le contenu des registres.
<- Sur le système hôte
Le niveau de demande d’interruption (IRQL) est utilisé pour gérer la priorité du service d’interruption. Chaque processeur a un paramètre d’IRQL que les threads peuvent augmenter ou diminuer. Les interruptions qui se produisent au niveau du processeur ou en dessous du paramètre IRQL sont masquées et n’interfèrent pas avec l’opération en cours. Les interruptions qui se produisent au-dessus du paramètre d’IRQL du processeur ont la priorité sur l’opération en cours. L’extension !irql affiche le niveau de demande d’interruption (IRQL) sur le processeur actuel de l’ordinateur cible avant que l’interruption du débogueur ne se produise. Lorsque l’ordinateur cible interrompt dans le débogueur, le niveau IRQL change, mais le niveau IRQL qui était effectif juste avant l’interruption du débogueur est sauvegardé et est affiché par !irql.
0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)
<Afficher les registres et disassembly
Afficher les registres
Affichez le contenu des registres pour le thread actuel sur le processeur actuel en utilisant la commande r (Registres).
0: kd> r
rax=000000000000c301 rbx=ffffe00173eed880 rcx=0000000000000001
rdx=000000d800000000 rsi=ffffe00173eed8e0 rdi=ffffe00173eed8f0
rip=fffff803bb757020 rsp=ffffd001f01f8988 rbp=ffffe00173f0b620
r8=000000000000003e r9=ffffe00167a4a000 r10=000000000000001e
r11=ffffd001f01f88f8 r12=0000000000000000 r13=ffffd001f01efdc0
r14=0000000000000001 r15=0000000000000000
iopl=0 nv up ei pl nz na pe nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000202
nt!DbgBreakPointWithStatus:
fffff803`bb757020 cc int 3
Alternativement, vous pouvez afficher le contenu des registres en sélectionnant Affichage>Registres.
Afficher le contenu des registres peut être utile lors du déroulement de l’exécution du code en langage d’assemblage et dans d’autres scénarios. Pour plus d’informations, voir r (Registres).
Pour des informations sur le contenu du registre, veuillez consulter la section architecture x86 et architecture x64.
Code Machine
Vous pouvez désassembler le code en cours d’exécution pour afficher le code en langage d’assemblage qui est exécuté en sélectionnant View>Disassembly.
Pour plus d’informations sur le désassemblage en langage d’assemblage, veuillez consulter la rubrique Désassemblage x86 annoté et Désassemblage x64 annoté.
Section 12 : Utiliser la mémoire
Dans la section 12, vous utiliserez des commandes de débogage pour afficher le contenu de la mémoire.
Afficher la mémoire
Vous pouvez avoir besoin d’examiner la mémoire pour identifier un problème ou inspecter des variables, des pointeurs, etc. Vous pouvez afficher la mémoire en tapant l’une des commandes suivantes d* <address>.
db |
Affiche les données en valeurs d’octet et en caractères ASCII. |
dd |
Affiche les données sous forme de mots double largeur (4 octets). |
du |
Affiche les données sous forme de caractères Unicode. |
dw |
Affiche les données sous forme de valeurs de mot (2 octets) et de caractères ASCII. |
Remarque Si vous essayez d’afficher une adresse invalide, son contenu est affiché sous forme de points d’interrogation (?).
Alternativement, vous pouvez afficher la mémoire en sélectionnant View>Memory. Utilisez le menu déroulant Display format pour modifier la façon dont la mémoire est affichée.
Pour afficher les données associées au contrôle de volume, définissez un point d’arrêt pour déclencher sur la routine PropertyHandlerAudioEngineVolumeLevel en utilisant la commande bm. Avant de définir le nouveau point d’arrêt, effaçons tous les points d’arrêt précédents en utilisant bc *.
kd> bc *
Définissez un point d’arrêt pour déclencher sur la routine PropertyHandlerAudioEngineVolumeLevel en utilisant la commande bm.
kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume 1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
Listez 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"
Utilisez la commande g pour redémarrer l’exécution du code.
Sur le système cible, ajustez le volume dans la zone de notification du système. Cela déclenchera le point d’arrêt.
Breakpoint 1 hit tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume: fffff80f`02c3a4b0 44894c2420 mov dword ptr [rsp+20h],r9d
Utilisez l’élément de menu View>Local pour afficher les variables locales. Remarquez la valeur actuelle de la variable IVolume.
Vous pouvez afficher le type de données et la valeur actuelle de la variable IVolume dans le code d’exemple en tapant la commande dt et le nom de la variable.
kd> dt lVolume Local var @ 0xa011ea50 Type long 0n-6291456
Le point d’arrêt est atteint en entrant dans 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; }
Tentez d’afficher la valeur à l’emplacement mémoire de IVolume en utilisant la commande dt (Afficher le type).
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.
Appuyez sur F10 pour avancer jusqu’à la dernière ligne de code dans SetDeviceChannelVolume.
return ntStatus;
Affichez la valeur à l’emplacement mémoire de IVolume en utilisant la commande dt (Afficher le type).
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.
Vous pouvez également afficher l’emplacement mémoire de IVolume en utilisant la commande ? (Évaluer l’expression).
kd> ? lVolume Evaluate expression: -79711507126684 = ffffb780`b7eee664
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
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
Pour voir les différents types de sortie 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 float de la commande df pour afficher les données sous forme de nombres en virgule flottante simple (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 dans la mémoire
Tout comme les commandes utilisées pour lire la mémoire, vous pouvez utiliser les commandes e* pour modifier le contenu de la mémoire.
Commande | Description |
---|---|
unité(s) |
Chaîne ASCII (non terminée par NULL) |
eu |
Chaîne Unicode (non terminée par NULL) |
Nouveau |
Valeurs de mots (2 octets) |
eza |
Chaîne ASCII terminée par NULL |
ezu |
Chaîne Unicode terminée par NULL |
eb |
Valeurs d’octets |
ed |
Valeurs de mots double (4 octets) |
L’exemple suivant montre comment écraser la mémoire.
Tout d’abord, localisez l’adresse de la variable lVolume utilisée dans le code d’exemple.
kd> ? lVolume Evaluate expression: -79711507126684 = ffffb780`b7eee664
Écrasez cette adresse mémoire avec de nouveaux caractères en utilisant la commande eb.
kd> eb 0xffffb780`b7eee664 11 11 11 11 11
Affichez l’emplacement mémoire pour confirmer que les caractères ont été écrasés en tapant la commande db.
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 ....(...........
Alternativement, vous pouvez modifier le contenu de la mémoire dans une fenêtre de surveillance ou de variables. Pour la fenêtre de surveillance, vous pouvez voir des variables qui sont hors contexte du cadre actuel. Les modifier n’est pas pertinent s’ils ne sont pas dans le contexte.
Section 13: Terminer la session WinDbg
<-Sur le système hôte
Si vous souhaitez laisser le débogueur attaché, mais que vous voulez travailler sur la cible, effacez tout point d’arrêt en utilisant bc *
, afin que l’ordinateur cible ne tente pas de se connecter au débogueur de l’ordinateur hôte. Ensuite, utilisez la commande g
pour laisser l’ordinateur cible fonctionner à nouveau.
Pour mettre fin à la session de débogage, sur le système hôte, interrompez le débogueur et entrez la commande qd
(Quitter et détacher) ou sélectionnez Arrêter le débogage dans le menu.
0: kd> qd
Pour plus d’informations, veuillez consulter la rubrique Terminer une session de débogage dans WinDbg (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 utiliseront des versions plus anciennes de Windows telles que Windows Vista dans leurs exemples, mais les concepts discutés sont applicables à la plupart des versions de Windows.
Livres
Advanced Windows Debugging par Mario Hewardt et Daniel Pravat
Inside Windows Debugging : A Practical Guide to Debugging and Tracing Strategies in Windows® de Tarik Soulami.
Windows Internals (Au cœur de Windows de Pavel Yosifovich, Alex Ionescu, Mark Russinovich et David Solomon
Vidéo
The Defrag Tools Show WinDbg Episodes 13-29: </shows/defrag-tools/>
Fournisseurs de formation :
OSR - https://www.osr.com/