Prise en main de WinDbg (mode noyau)
WinDbg est un débogueur en mode noyau et en mode utilisateur inclus dans les Outils de débogage pour Windows. Cet article propose des exercices pour vous aider dans l’utilisation de WinDbg comme un débogueur en mode noyau.
Pour des informations sur la manière d’obtenir les Outils de débogage pour Windows, veuillez consulter la section Télécharger et installer le débogueur Windows WinDbg. Après avoir installé les outils de débogage, localisez les répertoires d’installation pour les versions 64 bits (x64) et 32 bits (x86) des outils. Par exemple :
- C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
- C:\Program Files (x86)\Windows Kits\10\Debuggers\x86
Configurer un débogage en mode noyau
Un environnement de débogage en mode noyau a typiquement deux ordinateurs, l’ordinateur hôte et l’ordinateur cible. Le débogueur s’exécute sur l’ordinateur hôte, et le code en cours de débogage s’exécute sur l’ordinateur cible. L’hôte et la cible sont connectés par un câble de débogage.
Les débogueurs Windows supportent les types de câbles suivants :
- Ethernet
- USB 3.0
- Série (aussi appelé null modem)
Pour la vitesse et la fiabilité, vous devriez utiliser un câble Ethernet avec un hub réseau local. Le diagramme suivant illustre un ordinateur hôte et un ordinateur cible connectés pour le débogage avec un câble Ethernet.
Une option pour les versions antérieures de Windows consiste à utiliser un câble direct, tel qu’un câble série.
Pour obtenir des détails sur la manière de configurer les ordinateurs hôte et cible, veuillez consulter la section Configurer manuellement le débogage en mode noyau.
Machine virtuelle - VM
Pour obtenir des informations concernant la connexion d’un débogueur à une machine virtuelle Hyper-V, veuillez consulter la section Configurer le débogage réseau d’une machine virtuelle - KDNET.
Établir une session de débogage en mode noyau
Après avoir configuré votre ordinateur hôte et cible et les avoir connectés avec un câble de débogage, vous pouvez établir une session de débogage en mode noyau. Veuillez suivre les instructions dans la même rubrique que vous avez utilisé pour la configuration. Par exemple, si vous décidez de configurer vos ordinateurs hôte et cible pour le débogage via Ethernet, vous pouvez trouver des instructions pour établir une session de débogage en mode noyau dans l’article suivant :
Prise en main avec WinDbg
Sur l’ordinateur hôte, ouvrez WinDbg et établissez une session de débogage en mode noyau avec l’ordinateur cible.
Pour ouvrir le fichier de documentation CHM du débogueur, rendez-vous dans le menu Aide et sélectionnez Contenus. La documentation du débogueur est aussi disponible en ligne dans Outils de débogage pour Windows.
Lorsque vous établissez une session de débogage en mode noyau, WinDbg peut interrompre automatiquement l’ordinateur cible. Si WinDbg n’interrompt pas, rendez-vous dans le menu Déboguer et sélectionnez Interrompre.
Dans la ligne de commande en bas de la fenêtre WinDbg, saisissez la commande suivante :
Le résultat ressemble à l’exemple suivant :
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols
Le chemin de recherche des symboles indique à WinDbg où chercher les fichiers de symboles (PDB). Le débogueur a besoin de fichiers de symboles pour obtenir des informations sur les modules de code, comme les noms de fonctions et les noms de variables.
Veuillez saisir la commande suivante, qui indique à WinDbg de faire sa recherche initiale pour trouver et charger les fichiers de symboles :
Pour voir une liste des modules chargés, saisissez la commande suivante :
Le résultat ressemble à l’exemple suivant :
0:000>3: kd> lm start end module name fffff800`00000000 fffff800`00088000 CI (deferred) ... fffff800`01143000 fffff800`01151000 BasicRender (deferred) fffff800`01151000 fffff800`01163000 BasicDisplay (deferred) ... fffff800`02a0e000 fffff800`03191000 nt (pdb symbols) C:\...\ntkrnlmp.pdb fffff800`03191000 fffff800`03200000 hal (deferred) ...
Pour démarrer l’ordinateur cible en cours d’exécution, veuillez saisir la commande suivante :
Pour interrompre à nouveau, rendez-vous dans le menu Déboguer et sélectionnez Interrompre.
Saisissez la commande suivante pour examiner le type de données
_FILE_OBJECT
dans le modulent
:Le résultat ressemble à l’exemple suivant :
0:000>0: kd> dt nt!_FILE_OBJECT +0x000 Type : Int2B +0x002 Size : Int2B +0x008 DeviceObject : Ptr64 _DEVICE_OBJECT +0x010 Vpb : Ptr64 _VPB ... +0x0c0 IrpList : _LIST_ENTRY +0x0d0 FileObjectExtension : Ptr64 Void
Saisissez la commande suivante pour examiner certains des symboles dans le module
nt
:Le résultat ressemble à l’exemple suivant :
0:000>0: kd> x nt!*CreateProcess* fffff800`030821cc nt!ViCreateProcessCallbackInternal (<no parameter info>) ... fffff800`02e03904 nt!MmCreateProcessAddressSpace (<no parameter info>) fffff800`02cece00 nt!PspCreateProcessNotifyRoutine = <no type information> ...
Saisissez la commande suivante pour mettre un point d’arrêt à MmCreateProcessAddressSpace :
bu nt!MmCreateProcessAddressSpace
Pour vérifier que le point d’arrêt est défini, saisissez la commande suivante :
Le résultat ressemble à l’exemple suivant :
0:000>0: kd> bu nt!MmCreateProcessAddressSpace 0: kd> bl 0 e fffff800`02e03904 0001 (0001) nt!MmCreateProcessAddressSpace
Saisissez g pour laisser l’ordinateur cible fonctionner.
Si l’ordinateur cible n’interrompt pas immédiatement dans le débogueur, effectuez quelques actions sur l’ordinateur cible (par exemple, ouvrez le Bloc-notes). L’ordinateur cible interrompra le débogueur lorsque MmCreateProcessAddressSpace est appelé. Pour voir l’arborescence des appels de procédure , saisissez les commandes suivantes:
Le résultat ressemble à l’exemple suivant :
0:000>2: kd> k Child-SP RetAddr Call Site ffffd000`224b4c88 fffff800`02d96834 nt!MmCreateProcessAddressSpace ffffd000`224b4c90 fffff800`02dfef17 nt!PspAllocateProcess+0x5d4 ffffd000`224b5060 fffff800`02b698b3 nt!NtCreateUserProcess+0x55b ... 000000d7`4167fbb0 00007ffd`14b064ad KERNEL32!BaseThreadInitThunk+0xd 000000d7`4167fbe0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
Dans le menu Affichage, sélectionnez Désassemblage.
Dans le menu Déboguer, sélectionnez Pas à Pas (ou appuyez sur F10). Saisissez les commandes encore quelques fois tout en regardant la fenêtre de désassemblage.
Effacez votre point d’arrêt en saisissant la commande suivante:
Saisissez g pour laisser l’ordinateur cible fonctionner. Pour interrompre à nouveau, rendez-vous dans le menu Déboguer et sélectionnez Interrompre, ou appuyez sur CTRL-Break.
Pour voir une liste de tous les processus, saisissez la commande suivante:
Le résultat ressemble à l’exemple suivant :
0:000>0: kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** PROCESS ffffe000002287c0 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000 DirBase: 001aa000 ObjectTable: ffffc00000003000 HandleCount: <Data Not Accessible> Image: System PROCESS ffffe00001e5a900 SessionId: none Cid: 0124 Peb: 7ff7809df000 ParentCid: 0004 DirBase: 100595000 ObjectTable: ffffc000002c5680 HandleCount: <Data Not Accessible> Image: smss.exe ... PROCESS ffffe00000d52900 SessionId: 1 Cid: 0910 Peb: 7ff669b8e000 ParentCid: 0a98 DirBase: 3fdba000 ObjectTable: ffffc00007bfd540 HandleCount: <Data Not Accessible> Image: explorer.exe
Copiez l’adresse d’un processus, et saisissez la commande suivante:
Par exemple :
!process ffffe00000d5290 2
Cela montre les threads dans le processus.
0:000>0:000>0: kd> !process ffffe00000d52900 2 PROCESS ffffe00000d52900 SessionId: 1 Cid: 0910 Peb: 7ff669b8e000 ParentCid: 0a98 DirBase: 3fdba000 ObjectTable: ffffc00007bfd540 HandleCount: Image: explorer.exe THREAD ffffe00000a0d880 Cid 0910.090c Teb: 00007ff669b8c000 ffffe00000d57700 SynchronizationEvent THREAD ffffe00000e48880 Cid 0910.0ad8 Teb: 00007ff669b8a000 ffffe00000d8e230 NotificationEvent ffffe00000cf6870 Semaphore Limit 0xffff ffffe000039c48c0 SynchronizationEvent ... THREAD ffffe00000e6d080 Cid 0910.0cc0 Teb: 00007ff669a10000 ffffe0000089a300 QueueObject
Copiez l’adresse d’un thread, et saisissez la commande suivante:
Par exemple :
!thread ffffe00000e6d080
Cela affiche des informations sur le thread individuel.
0: kd> !thread ffffe00000e6d080 THREAD ffffe00000e6d080 Cid 0910.0cc0 Teb: 00007ff669a10000 Win32Thread: 0000000000000000 WAIT: ... ffffe0000089a300 QueueObject Not impersonating DeviceMap ffffc000034e7840 Owning Process ffffe00000d52900 Image: explorer.exe Attached Process N/A Image: N/A Wait Start TickCount 13777 Ticks: 2 (0:00:00:00.031) Context Switch Count 2 IdealProcessor: 1 UserTime 00:00:00.000 KernelTime 00:00:00.000 Win32 Start Address ntdll!TppWorkerThread (0x00007ffd14ab2850) Stack Init ffffd00021bf1dd0 Current ffffd00021bf1580 Base ffffd00021bf2000 Limit ffffd00021bec000 Call 0 Priority 13 BasePriority 13 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5 ...
Pour voir tous les nœuds de périphérique dans l’arborescence de périphériques Plug and Play, saisissez la commande suivante:
0:000>0: kd> !devnode 0 1 Dumping IopRootDeviceNode (= 0xffffe000002dbd30) DevNode 0xffffe000002dbd30 for PDO 0xffffe000002dc9e0 InstancePath is "HTREE\ROOT\0" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) DevNode 0xffffe000002d9d30 for PDO 0xffffe000002daa40 InstancePath is "ROOT\volmgr\0000" ServiceName is "volmgr" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) DevNode 0xffffe00001d49290 for PDO 0xffffe000002a9a90 InstancePath is "STORAGE\Volume\{3007dfd3-df8d-11e3-824c-806e6f6e6963}#0000000000100000" ServiceName is "volsnap" TargetDeviceNotify List - f 0xffffc0000031b520 b 0xffffc0000008d0f0 State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) ...
Pour voir les nœuds de périphérique et leurs ressources matérielles, saisissez la commande suivante :
0:000>... DevNode 0xffffe000010fa770 for PDO 0xffffe000010c2060 InstancePath is "PCI\VEN_8086&DEV_2937&SUBSYS_2819103C&REV_02\3&33fd14ca&0&D0" ServiceName is "usbuhci" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) TranslatedResourceList at 0xffffc00003c78b00 Version 1.1 Interface 0x5 Bus #0 Entry 0 - Port (0x1) Device Exclusive (0x1) Flags (0x131) - PORT_MEMORY PORT_IO 16_BIT_DECODE POSITIVE_DECODE Range starts at 0x3120 for 0x20 bytes Entry 1 - DevicePrivate (0x81) Device Exclusive (0x1) Flags (0000) - Data - {0x00000001, 0x00000004, 0000000000} Entry 2 - Interrupt (0x2) Shared (0x3) Flags (0000) - LEVEL_SENSITIVE Level 0x8, Vector 0x81, Group 0, Affinity 0xf ...
Pour voir un nœud de périphérique qui a un nom de service disk, saisissez la commande suivante :
0: kd> !devnode 0 1 disk Dumping IopRootDeviceNode (= 0xffffe000002dbd30) DevNode 0xffffe0000114fd30 for PDO 0xffffe00001159610 InstancePath is "IDE\DiskST3250820AS_____________________________3.CHL___\5&14544e82&0&0.0.0" ServiceName is "disk" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) ...
!devnode 0 1 montre l’adresse de l’objet de périphérique physique (PDO) pour le nœud. Copiez l’adresse d’un objet de périphérique physique (PDO), et saisissez la commande suivante :
Par exemple :
<PdoAddress>!devstack 0xffffe00001159610
0:000>0: kd> !devstack 0xffffe00001159610 !DevObj !DrvObj !DevExt ObjectName ffffe00001d50040 \Driver\partmgr ffffe00001d50190 ffffe00001d51450 \Driver\disk ffffe00001d515a0 DR0 ffffe00001156e50 \Driver\ACPI ffffe000010d8bf0
Pour obtenir des informations sur le pilote disk.sys, saisissez la commande suivante :
0:000>0: kd> !drvobj disk 2 Driver object (ffffe00001d52680) is for: \Driver\disk DriverEntry: fffff800006b1270 disk!GsDriverEntry DriverStartIo: 00000000 DriverUnload: fffff800010b0b5c CLASSPNP!ClassUnload AddDevice: fffff800010aa110 CLASSPNP!ClassAddDevice Dispatch routines: [00] IRP_MJ_CREATE fffff8000106d160 CLASSPNP!ClassGlobalDispatch [01] IRP_MJ_CREATE_NAMED_PIPE fffff80002b0ab24 nt!IopInvalidDeviceRequest [02] IRP_MJ_CLOSE fffff8000106d160 CLASSPNP!ClassGlobalDispatch [03] IRP_MJ_READ fffff8000106d160 CLASSPNP!ClassGlobalDispatch ... [1b] IRP_MJ_PNP fffff8000106d160 CLASSPNP!ClassGlobalDispatch
La commande
!drvobj
affiche les adresses des routines de distribution. Par exemple :CLASSPNP!ClassGlobalDispatch
. Pour définir et vérifier un point d’arrêt àClassGlobalDispatch
, saisissez les commandes suivantes :bu CLASSPNP!ClassGlobalDispatch
Saisissez
g
pour laisser l’ordinateur cible s’exécuter.Si l’ordinateur cible n’interrompt pas immédiatement dans le débogueur, effectuez quelques actions sur l’ordinateur cible (par exemple, ouvrez le Bloc-notes et enregistrez un fichier). L’ordinateur cible interrompra le débogueur lorsque
ClassGlobalDispatch
est appelé. Pour voir l’arborescence des appels de procédure , saisissez les commandes suivantes:Le résultat ressemble à l’exemple suivant :
2: kd> k Child-SP RetAddr Call Site ffffd000`21d06cf8 fffff800`0056c14e CLASSPNP!ClassGlobalDispatch ffffd000`21d06d00 fffff800`00f2c31d volmgr!VmReadWrite+0x13e ffffd000`21d06d40 fffff800`0064515d fvevol!FveFilterRundownReadWrite+0x28d ffffd000`21d06e20 fffff800`0064578b rdyboost!SmdProcessReadWrite+0x14d ffffd000`21d06ef0 fffff800`00fb06ad rdyboost!SmdDispatchReadWrite+0x8b ffffd000`21d06f20 fffff800`0085cef5 volsnap!VolSnapReadFilter+0x5d ffffd000`21d06f50 fffff800`02b619f7 Ntfs!NtfsStorageDriverCallout+0x16 ...
Pour mettre fin à votre session de débogage, saisissez la commande suivante :
Résumé des commandes
- Commande Contenu dans le menu Aide
- .sympath (Définir le chemin du symbole)
- .reload (Recharger le module)
- x (Examiner les symboles)
- g (Go)
- dt (Type d’affichage)
- Commande Arrêt dans le menu Débogage
- lm (Lister les modules chargés)
- k (Afficher l’arborescence des appels de procédure)
- bu (Définir un point d’arrêt)
- bl (Liste des points d’arrêt)
- bc (effacer le point d’arrêt)
- Commande Pas à pas dans le menu Déboguer (F11)
- !process
- !thread
- !devnode
- !devstack
- !drvobj
- qd (Quitter et détacher)