Introducción a WinDbg (modo kernel)
WinDbg es un depurador en modo kernel y en modo usuario que se incluye en Herramientas de depuración para Windows. En este artículo se proporcionan ejercicios que le ayudarán a empezar a usar WinDbg como depurador en modo kernel.
Para obtener información sobre cómo obtener las Herramientas de depuración para Windows, consulte Descarga e instalación del depurador de Windows de WinDbg. Después de instalar las herramientas de depuración, busque los directorios de instalación de las versiones de 64 bits (x64) y de 32 bits (x86) de las herramientas. Por ejemplo:
- C:\Archivos de programa (x86)\Windows Kits\10\Debuggers\x64
- C:\Archivos de programa (x86)\Windows Kits\10\Debuggers\x86
Configuración de una depuración en modo kernel
Normalmente, un entorno de depuración en modo kernel tiene dos equipos, el equipo host y el equipo de destino. El depurador se ejecuta en el equipo host y el código que se depura se ejecuta en el equipo de destino. El equipo host y de destino están conectados con un cable de depuración.
Los depuradores de Windows admiten los siguientes tipos de cables:
- Ethernet
- puerto USB 3.0 en la parte frontal
- Serie (también denominado módem nulo)
Para mayor velocidad y fiabilidad, debe utilizar un cable Ethernet con un concentrador de red local. En el diagrama siguiente se muestra un equipo host y de destino conectados para la depuración con un cable Ethernet.
Una opción para las versiones anteriores de Windows es usar un cable directo, como un cable serie.
Para obtener más información sobre cómo configurar el equipo host y de destino, consulte Configuración manual de la depuración en modo kernel.
Máquina virtual - VM
Para obtener información sobre cómo conectar un depurador a una máquina virtual de Hyper-V, consulte Configuración de la depuración de red de una máquina virtual - KDNET.
Establecimiento de una sesión de depuración en modo kernel
Después de configurar el equipo host y de destino y conectarlos con un cable de depuración, puede establecer una sesión de depuración en modo kernel. Siga las instrucciones del mismo tema que utilizó para la configuración. Por ejemplo, si decide configurar el equipo host y de destino para la depuración a través de Ethernet, puede encontrar instrucciones para establecer una sesión de depuración en modo kernel en el siguiente artículo:
Introducción al uso de WinDbg
En el equipo host, abra WinDbg y establezca una sesión de depuración en modo kernel con el equipo de destino.
Para abrir el archivo CHM de la documentación del depurador, vaya al menú Ayuda y seleccione Contenido. La documentación del depurador también está disponible en línea en Herramientas de depuración para Windows.
Al establecer una sesión de depuración en modo kernel, WinDbg se podría interrumpir automáticamente en el equipo de destino. Si WinDbg no se interrumpe, vaya al menú Depurar y seleccione Interrumpir.
En la línea de comandos de la parte inferior de la ventana WinDbg, escriba el siguiente comando:
La salida es similar a la del ejemplo siguiente:
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols
La ruta de búsqueda de símbolos indica a WinDbg dónde buscar archivos de símbolos (PDB). El depurador necesita archivos de símbolos para obtener información sobre los módulos de código, como nombres de función y nombres de variable.
Escriba el siguiente comando, que indica a WinDbg que realice su búsqueda inicial y cargue los archivos de símbolos:
Para ver una lista de los módulos cargados, escriba el comando siguiente:
La salida es similar a la del ejemplo siguiente:
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) ...
Para iniciar la ejecución del equipo de destino, escriba el siguiente comando:
Para interrumpir de nuevo, vaya al menú Depurar y seleccione Interrumpir.
Escriba el siguiente comando para examinar el tipo de datos
_FILE_OBJECT
en el módulont
:La salida es similar a la del ejemplo siguiente:
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
Escriba el siguiente comando para examinar algunos de los símbolos del módulo
nt
:La salida es similar a la del ejemplo siguiente:
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> ...
Escriba el siguiente comando para colocar un punto de interrupción en MmCreateProcessAddressSpace:
bu nt!MmCreateProcessAddressSpace
Para comprobar que el punto de interrupción está establecido, escriba el siguiente comando:
La salida es similar a la del ejemplo siguiente:
0:000>0: kd> bu nt!MmCreateProcessAddressSpace 0: kd> bl 0 e fffff800`02e03904 0001 (0001) nt!MmCreateProcessAddressSpace
Escriba g para permitir que se ejecute el equipo de destino.
Si el equipo de destino no interrumpe el depurador inmediatamente, realice algunas acciones en el equipo de destino (por ejemplo, abra el Bloc de notas). El equipo de destino interrumpirá el depurador cuando se llame a MmCreateProcessAddressSpace . Para ver el seguimiento de la pila, escriba los siguientes comandos:
La salida es similar a la del ejemplo siguiente:
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
En el menú Ver, seleccione Desensamblado.
En el menú Depurar, seleccione Paso a paso (o pulse F10). Escriba comandos de paso varias veces más a medida que vea la ventana Desensamblado.
Para borrar el punto de interrupción, escriba el siguiente comando:
Escriba g para permitir que se ejecute el equipo de destino. Para interrumpir de nuevo, vaya al menú Depurar y seleccione Interrumpir o pulse CTRL-Interrumpir.
Para ver una lista de todos los procesos, escriba el siguiente comando:
La salida es similar a la del ejemplo siguiente:
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
Copie la dirección de un proceso y escriba el siguiente comando:
Por ejemplo:
!process ffffe00000d5290 2
La salida muestra los subprocesos en el proceso.
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
Copie la dirección de un subproceso y escriba el siguiente comando:
Por ejemplo:
!thread ffffe00000e6d080
La salida muestra información sobre el subproceso individual.
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 ...
Para ver todos los nodos de dispositivo en el árbol de dispositivos Plug and Play, escriba el siguiente comando:
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) ...
Para ver los nodos de dispositivo y sus recursos de hardware, escriba el siguiente comando:
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 ...
Para ver un nodo de dispositivo que tenga un nombre de servicio de disco, escriba el siguiente comando:
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) ...
La salida de !devnode 0 1 muestra la dirección del objeto de dispositivo físico (PDO) para el nodo. Copie la dirección de un objeto de dispositivo físico (PDO) y escriba el siguiente comando:
Por ejemplo:
<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
Para obtener información sobre el disk.sys del controlador, escriba el siguiente comando:
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 salida de
!drvobj
muestra las direcciones de las rutinas de envío. Por ejemplo,CLASSPNP!ClassGlobalDispatch
. Para establecer y comprobar un punto de interrupción enClassGlobalDispatch
, escriba los siguientes comandos:bu CLASSPNP!ClassGlobalDispatch
Escriba
g
para permitir que se ejecute el equipo de destino.Si el equipo de destino no interrumpe el depurador inmediatamente, realice algunas acciones en el equipo de destino (por ejemplo, abra el Bloc de notas y guarde un archivo). El equipo de destino interrumpirá el depurador cuando se llame a
ClassGlobalDispatch
. Para ver el seguimiento de la pila, escriba los siguientes comandos:La salida es similar a la del ejemplo siguiente:
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 ...
Para finalizar la sesión de depuración, escriba el siguiente comando:
Resumen de comandos
- Comando Contenido en el menú Ayuda
- .sympath (Establecer ruta de acceso de símbolo)
- .reload (Módulo Volver a cargar)
- x (Examinar símbolos)
- g (Ir)
- dt (Tipo de presentación)
- Comando Interrumpir en el menú Depurar
- lm (Lista de módulos cargados)
- k (Mostrar seguimiento de pila)
- bu (Establecer punto de interrupción)
- bl (Lista de puntos de interrupción)
- bc (Borrar punto de interrupción)
- Comando Paso a paso en el menú Depurar (F11)
- !process
- !thread
- !devnode
- !devstack
- !drvobj
- qd (Salir y desasociar)