Introdução ao WinDbg (modo kernel)
O WinDbg é um depurador do modo kernel e do modo de usuário incluído nas Ferramentas de Depuração para Windows. Este artigo fornece exercícios para ajudá-lo a começar a usar o WinDbg como um depurador no modo kernel.
Para obter informações sobre como obter ferramentas de depuração para Windows, consulte Ferramentas de depuração para Windows (WinDbg, KD, CDB, NTSD). Depois de instalar as ferramentas de depuração, localize os diretórios de instalação para versões de 64 bits (x64) e 32 bits (x86) das ferramentas. Por exemplo:
- C:\Arquivos de Programas (x86)\Kits do Windows\10\Depuradores\x64
- C:\Arquivos de Programas (x86)\Windows Kits\10\Depuradores\x86
Configurar uma depuração no modo kernel
Um ambiente de depuração no modo kernel normalmente tem dois computadores, o computador host e o computador de destino. O depurador é executado no computador host e o código que está sendo depurado é executado no computador de destino. O host e o destino são conectados por um cabo de depuração.
Os depuradores do Windows dão suporte aos seguintes tipos de cabos:
- Ethernet
- USB 2.0 / USB 3.0
- Serial (também chamado de modem nulo)
Para velocidade e confiabilidade, você deve usar um cabo Ethernet com um hub de rede local. O diagrama a seguir ilustra um host e um computador de destino conectados para depuração com um cabo Ethernet.
Uma opção para versões mais antigas do Windows é usar um cabo direto, como um cabo USB ou serial.
Para obter detalhes sobre como configurar o host e os computadores de destino, consulte Configurando a depuração do modo kernel manualmente.
Máquina virtual – VM
Para obter informações sobre como conectar um depurador a uma máquina virtual Hyper-V, consulte Configurando a depuração de rede de uma máquina virtual – KDNET.
Estabelecer uma sessão de depuração no modo kernel
Depois de configurar o host e o computador de destino e conectá-los com um cabo de depuração, você poderá estabelecer uma sessão de depuração no modo kernel. Siga as instruções no mesmo tópico que você usou para ser configurado. Por exemplo, se você decidir configurar o host e os computadores de destino para depuração por Ethernet, poderá encontrar instruções para estabelecer uma sessão de depuração no modo kernel no seguinte artigo:
Introdução ao uso do WinDbg
No computador host, abra o WinDbg e estabeleça uma sessão de depuração no modo kernel com o computador de destino.
Para abrir o arquivo CHM da documentação do depurador, acesse o menu Ajuda e selecione Conteúdo. A documentação do depurador também está disponível online nas Ferramentas de Depuração para Windows.
Quando você estabelece uma sessão de depuração no modo kernel, o WinDbg pode entrar automaticamente no computador de destino. Se o WinDbg não for interrompido, vá para o menu Depurar e selecione Interromper.
Na linha de comando na parte inferior da janela do WinDbg, insira o seguinte comando:
A saída deverá ser semelhante ao seguinte exemplo:
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols
O caminho de pesquisa de símbolo informa ao WinDbg onde procurar arquivos de símbolo (PDB). O depurador precisa de arquivos de símbolo para obter informações sobre módulos de código, como nomes de função e nomes de variáveis.
Insira o seguinte comando, que informa ao WinDbg para fazer a localização inicial e o carregamento de arquivos de símbolo:
Para ver uma lista de módulos carregados, insira o seguinte comando:
A saída deverá ser semelhante ao seguinte exemplo:
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 a execução do computador de destino, insira o seguinte comando:
Para interromper novamente, vá para o menu Depurar e selecione Interromper.
Insira o seguinte comando para examinar o
_FILE_OBJECT
tipo de dados nont
módulo:A saída deverá ser semelhante ao seguinte exemplo:
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
Insira o seguinte comando para examinar alguns dos símbolos no
nt
módulo:A saída deverá ser semelhante ao seguinte exemplo:
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> ...
Insira o seguinte comando para colocar um ponto de interrupção em MmCreateProcessAddressSpace:
bu nt! MmCreateProcessAddressSpace
Para verificar se o ponto de interrupção está definido, insira o seguinte comando:
A saída deverá ser semelhante ao seguinte exemplo:
0:000>0: kd> bu nt!MmCreateProcessAddressSpace 0: kd> bl 0 e fffff800`02e03904 0001 (0001) nt!MmCreateProcessAddressSpace
Insira g para permitir que o computador de destino seja executado.
Se o computador de destino não entrar no depurador imediatamente, execute algumas ações no computador de destino (por exemplo, abra o Bloco de Notas). O computador de destino será interrompido no depurador quando MmCreateProcessAddressSpace for chamado. Para ver o rastreamento de pilha, insira os seguintes comandos:
A saída deverá ser semelhante ao seguinte exemplo:
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
No menu Exibir , selecione Desmontagem.
No menu Depurar , selecione Passar por Cima (ou pressione F10). Insira comandos de etapa mais algumas vezes enquanto observa a janela Desmontagem.
Limpe o ponto de interrupção inserindo o seguinte comando:
Insira g para permitir que o computador de destino seja executado. Para interromper novamente, vá para o menu Depurar e selecione Interromper ou pressione CTRL-Break.
Para ver uma lista de todos os processos, insira o seguinte comando:
A saída deverá ser semelhante ao seguinte exemplo:
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 o endereço de um processo e insira o seguinte comando:
Por exemplo:
!process ffffe00000d5290 2
A saída mostra os threads no processo.
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 o endereço de um thread e insira o seguinte comando:
Por exemplo:
!thread ffffe00000e6d080
A saída mostra informações sobre o thread 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 os nós de dispositivo na árvore de dispositivos Plug and Play, insira o seguinte 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 os nós do dispositivo e seus recursos de hardware, insira o seguinte 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 um nó de dispositivo que tem um nome de serviço de disco, insira o seguinte 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) ...
A saída de !devnode 0 1 mostra o endereço do PDO (objeto de dispositivo físico) para o nó. Copie o endereço de um objeto de dispositivo físico (PDO) e insira o seguinte comando:
Por exemplo:
<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 obter informações sobre o driver disk.sys, insira o seguinte 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
A saída de
!drvobj
mostra endereços de rotinas de expedição. Por exemplo,CLASSPNP!ClassGlobalDispatch
. Para definir e verificar um ponto de interrupção emClassGlobalDispatch
, insira os seguintes comandos:bu CLASSPNP! ClassGlobalDispatch
Insira
g
para permitir que o computador de destino seja executado.Se o computador de destino não entrar no depurador imediatamente, execute algumas ações no computador de destino (por exemplo, abra o Bloco de Notas e salve um arquivo). O computador de destino será interrompido no depurador quando
ClassGlobalDispatch
for chamado. Para ver o rastreamento de pilha, insira os seguintes comandos:A saída deverá ser semelhante ao seguinte exemplo:
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 encerrar a sessão de depuração, insira o seguinte comando:
Resumo dos comandos
- Comando Conteúdo no menu Ajuda
- .sympath (definir caminho do símbolo)
- .reload (recarregar módulo)
- x (examinar símbolos)
- g (Go)
- dt (Tipo de exibição)
- Comando Interromper no menu Depurar
- lm (Listar módulos carregados)
- k (Exibir backtrace de pilha)
- bu (Definir ponto de interrupção)
- bl (lista de pontos de interrupção)
- bc (ponto de interrupção claro)
- Comando Intervir no menu Depurar (F11)
- !Processo
- !Thread
- !devnode
- !devstack
- !drvobj
- qd (sair e desanexar)