Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este guia mostra como usar o WinDbg para depurar aplicativos no modo de usuário. Você pratica habilidades essenciais de depuração anexando-se a um processo em execução, definindo pontos de interrupção e diagnosticando falhas de aplicativo.
Neste artigo:
- Anexar o WinDbg ao Bloco de Notas e explorar a depuração básica
- Depurar seu próprio aplicativo e analisar uma falha
- Domine os comandos essenciais de depuração
O que você aprenderá
- Anexar o WinDbg a um processo em execução
- Configurar arquivos de símbolo para saída de depuração legível
- Definir pontos de interrupção e controlar a execução do programa
- Analisar falhas de aplicativo
- Navegar por threads e pilhas de chamadas
Pré-requisitos
- WinDbg instalado em seu computador. Para obter instruções de instalação, consulte Baixar e instalar o depurador do Windows WinDbg.
- Familiaridade básica com interfaces de linha de comando
- (Opcional) Um aplicativo compilado com símbolos de depuração para o segundo exercício
Tempo estimado para conclusão: 30 minutos
Abrir o Bloco de Notas e anexar o WinDbg
Vá para o diretório de instalação e abra WinDbg.exe.
No menu Arquivo, selecione Iniciar Executável. Na caixa de diálogo Inicializar Executável , vá para a pasta que contém notepad.exe. (O arquivo notepad.exe geralmente está em
C:\Windows\System32.) Para o nome do arquivo, insiranotepad.exe. Selecione Abrir.
Configure arquivos de símbolo para que o WinDbg possa exibir nomes de função e variável legíveis.
Na linha de comando próxima à parte inferior da janela do WinDbg, insira este comando:
A saída deverá ser semelhante ao seguinte exemplo:
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRVO que são símbolos? Os arquivos de símbolo (PDB) contêm informações sobre módulos de código, como nomes de função e nomes de variáveis. Sem símbolos, você vê apenas endereços de memória.
Em seguida, insira este comando:
O comando
.reloadinstrui o WinDbg a realizar sua pesquisa inicial para localizar e carregar arquivos de símbolo.Para ver os símbolos do módulo notepad.exe , insira este comando:
Nota
Se nenhuma saída for exibida, digite
.reload /fpara tentar forçar a carregamento do símbolo. Use !sym noisy para exibir informações adicionais de carregamento de símbolos.Para ver símbolos no módulo notepad.exe que contém
main, use o comando examinar símbolos para listar módulos que correspondem à máscara:x notepad!wWin*A saída deverá ser semelhante ao seguinte exemplo:
00007ff6`6e76b0a0 notepad!wWinMain (wWinMain) 00007ff6`6e783db0 notepad!wWinMainCRTStartup (wWinMainCRTStartup)Para colocar um ponto de interrupção em
notepad!wWinMain, insira este comando:Para verificar se você definiu o ponto de interrupção, insira este comando:
A saída deverá ser semelhante ao seguinte exemplo:
0 e Disable Clear 00007ff6`6e76b0a0 0001 (0001) 0:**** notepad!wWinMainPara iniciar o processo do Bloco de Notas, insira este comando:
O Bloco de Notas é executado até chegar à função
WinMaine, então, interrompe o depurador.Breakpoint 0 hit notepad!wWinMain: 00007ff6`6e76b0a0 488bc4 mov rax,rspPara ver uma lista de módulos de código que estão atualmente carregados no processo do Bloco de Notas, insira este comando:
A saída deverá ser semelhante ao seguinte exemplo:
0:000> lm start end module name 00007ff6`6e760000 00007ff6`6e798000 notepad (pdb symbols) C:\ProgramData\Dbg\sym\notepad.pdb\BC04D9A431EDE299D4625AD6201C8A4A1\notepad.pdb 00007ff8`066a0000 00007ff8`067ab000 gdi32full (deferred) 00007ff8`067b0000 00007ff8`068b0000 ucrtbase (deferred) 00007ff8`06a10000 00007ff8`06aad000 msvcp_win (deferred) 00007ff8`06ab0000 00007ff8`06ad2000 win32u (deferred) 00007ff8`06b40000 00007ff8`06e08000 KERNELBASE (deferred) 00007ff8`07220000 00007ff8`072dd000 KERNEL32 (deferred) 00007ff8`07420000 00007ff8`07775000 combase (deferred) 00007ff8`07820000 00007ff8`079c0000 USER32 (deferred) 00007ff8`079c0000 00007ff8`079f0000 IMM32 (deferred) 00007ff8`07c00000 00007ff8`07c2a000 GDI32 (deferred) 00007ff8`08480000 00007ff8`085ab000 RPCRT4 (deferred) 00007ff8`085b0000 00007ff8`0864e000 msvcrt (deferred) 00007ff8`08c40000 00007ff8`08cee000 shcore (deferred) 00007ff8`08db0000 00007ff8`08fa5000 ntdll (pdb symbols) C:\ProgramData\Dbg\sym\ntdll.pdb\53F12BFE149A2F50205C8D5D66290B481\ntdll.pdb 00007fff`f8580000 00007fff`f881a000 COMCTL32 (deferred)Para ver um rastreamento de pilha, digite este comando:
A saída deverá ser semelhante ao seguinte exemplo:
0:000> k 00 000000c8`2647f708 00007ff6`6e783d36 notepad!wWinMain 01 000000c8`2647f710 00007ff8`07237034 notepad!__scrt_common_main_seh+0x106 02 000000c8`2647f750 00007ff8`08e02651 KERNEL32!BaseThreadInitThunk+0x14 03 000000c8`2647f780 00000000`00000000 ntdll!RtlUserThreadStart+0x21Para iniciar o Bloco de Notas novamente, insira este comando:
Próximo: Você interromperá a execução e explorará os módulos carregados.
Para entrar no Bloco de Notas, no menu Arquivo, selecione Interromper.
Para definir e verificar um ponto de interrupção em
ZwWriteFile, insira estes comandos:Para iniciar o Bloco de Notas novamente, insira g. Na janela bloco de notas, insira algum texto. No menu Arquivo, selecione Salvar. O código em execução falha quando chega a
ZwCreateFile. Digite o comando k para ver o rastreamento da pilha.
Na janela WinDbg, à esquerda da linha de comando, os números de processador e thread são mostrados. Neste exemplo, o número atual do processador é 0 e o número do thread atual é 11 (
0:011>). A janela exibe o rastreamento de pilha para o thread 11 em execução no processador 0.Para ver uma lista de todos os threads no processo do Bloco de Notas, digite este comando (o til):
A saída deverá ser semelhante ao seguinte exemplo:
0:011> ~ 0 Id: 5500.34d8 Suspend: 1 Teb: 000000c8`262c4000 Unfrozen 1 Id: 5500.3960 Suspend: 1 Teb: 000000c8`262c6000 Unfrozen 2 Id: 5500.5d68 Suspend: 1 Teb: 000000c8`262c8000 Unfrozen 3 Id: 5500.4c90 Suspend: 1 Teb: 000000c8`262ca000 Unfrozen 4 Id: 5500.4ac4 Suspend: 1 Teb: 000000c8`262cc000 Unfrozen 5 Id: 5500.293c Suspend: 1 Teb: 000000c8`262ce000 Unfrozen 6 Id: 5500.53a0 Suspend: 1 Teb: 000000c8`262d0000 Unfrozen 7 Id: 5500.3ca4 Suspend: 1 Teb: 000000c8`262d4000 Unfrozen 8 Id: 5500.808 Suspend: 1 Teb: 000000c8`262da000 Unfrozen 10 Id: 5500.3940 Suspend: 1 Teb: 000000c8`262dc000 Unfrozen . 11 Id: 5500.28b0 Suspend: 1 Teb: 000000c8`262de000 Unfrozen 12 Id: 5500.12bc Suspend: 1 Teb: 000000c8`262e0000 Unfrozen 13 Id: 5500.4c34 Suspend: 1 Teb: 000000c8`262e2000 UnfrozenNeste exemplo, 14 threads têm índices de 0 a 13.
Para examinar o rastreamento de pilha para o thread 0, digite estes comandos:
A saída deverá ser semelhante ao seguinte exemplo:
0:011> ~0s 0:011> ~0s win32u!NtUserGetProp+0x14: 00007ff8`06ab1204 c3 ret 0:000> k # Child-SP RetAddr Call Site 00 000000c8`2647bd08 00007ff8`07829fe1 win32u!NtUserGetProp+0x14 01 000000c8`2647bd10 00007fff`f86099be USER32!GetPropW+0xd1 02 000000c8`2647bd40 00007ff8`07d12f4d COMCTL32!DefSubclassProc+0x4e 03 000000c8`2647bd90 00007fff`f8609aba SHELL32!CAutoComplete::_EditWndProc+0xb1 04 000000c8`2647bde0 00007fff`f86098b7 COMCTL32!CallNextSubclassProc+0x9a 05 000000c8`2647be60 00007ff8`0782e858 COMCTL32!MasterSubclassProc+0xa7 06 000000c8`2647bf00 00007ff8`0782de1b USER32!UserCallWinProcCheckWow+0x2f8 07 000000c8`2647c090 00007ff8`0782d68a USER32!SendMessageWorker+0x70b 08 000000c8`2647c130 00007ff8`07afa4db USER32!SendMessageW+0xdaPara sair da depuração e desanexar-se do processo do Bloco de Notas, digite este comando:
Abra seu próprio aplicativo e anexe o WinDbg
Por exemplo, suponha que você escreveu e criou este pequeno aplicativo de console:
...
void MyFunction(long p1, long p2, long p3)
{
long x = p1 + p2 + p3;
long y = 0;
y = x / p2;
}
void main ()
{
long a = 2;
long b = 0;
MyFunction(a, b, 5);
}
Para este exercício, suponha que o aplicativo interno (MyApp.exe) e o arquivo de símbolo (MyApp.pdb) estejam em C:\MyApp\x64\Debug. Suponha também que o código-fonte do aplicativo esteja em C:\MyApp\MyApp and that the target machine compiled MyApp.exe.
Abra o WinDbg.
No menu Arquivo, selecione Iniciar Executável. Na caixa de diálogo Executar Arquivo Executável, vá para C:\MyApp\x64\Debug. Em Nome do arquivo, insira MyApp.exe. Selecione Abrir.
Insira estes comandos:
.sympath+ C:\MyApp\x64\Debug
Esses comandos informam ao WinDbg onde encontrar símbolos e código-fonte para seu aplicativo. Nesse caso, você não precisa definir o local do código-fonte usando .srcpath porque os símbolos têm caminhos totalmente qualificados para os arquivos de origem.
Insira estes comandos:
Seu aplicativo entra automaticamente no depurador quando atinge sua
mainfunção.O WinDbg exibe o código-fonte e a janela Comando.
No menu Depurar, selecione Intervir (ou selecione F11). Continue a intervenção até entrar no
MyFunction. Quando você entra na linhay = x / p2, seu aplicativo falha e interrompe o depurador.A saída deverá ser semelhante ao seguinte exemplo:
(1450.1424): Integer divide-by-zero - code c0000094 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. MyApp!MyFunction+0x44: 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] ss:00000063`2036f808=00000000Insira este comando:
O WinDbg exibe uma análise do problema (nesse caso, divisão por 0).
FAULTING_IP: MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7] 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 00007ff63be11064 (MyApp!MyFunction+0x0000000000000044) ExceptionCode: c0000094 (Integer divide-by-zero) ExceptionFlags: 00000000 NumberParameters: 0 ... STACK_TEXT: 00000063`2036f7e0 00007ff6`3be110b8 : ... : MyApp!MyFunction+0x44 00000063`2036f800 00007ff6`3be1141d : ... : MyApp!main+0x38 00000063`2036f840 00007ff6`3be1154e : ... : MyApp!__tmainCRTStartup+0x19d 00000063`2036f8b0 00007ffc`b1cf16ad : ... : MyApp!mainCRTStartup+0xe 00000063`2036f8e0 00007ffc`b1fc4629 : ... : KERNEL32!BaseThreadInitThunk+0xd 00000063`2036f910 00000000`00000000 : ... : ntdll!RtlUserThreadStart+0x1d STACK_COMMAND: dt ntdll!LdrpLastDllInitializer BaseDllName ;dt ntdll!LdrpFailureData ;.cxr 0x0 ;kb FOLLOWUP_IP: MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7] 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] FAULTING_SOURCE_LINE: c:\myapp\myapp\myapp.cpp FAULTING_SOURCE_FILE: c:\myapp\myapp\myapp.cpp FAULTING_SOURCE_LINE_NUMBER: 7 FAULTING_SOURCE_CODE: 3: void MyFunction(long p1, long p2, long p3) 4: { 5: long x = p1 + p2 + p3; 6: long y = 0; > 7: y = x / p2; 8: } 9: 10: void main () 11: { 12: long a = 2; ...
Próximas etapas
Depois de depurar um aplicativo do sistema e seu próprio código, você estará pronto para explorar cenários de depuração mais avançados:
- Introdução ao WinDbg (modo kernel) – Depurar o kernel e os drivers do Windows
- Operação do depurador – Saiba mais sobre os conceitos de operação do depurador
- Técnicas de depuração – Explorar métodos avançados de depuração
Resumo dos comandos
Aqui estão os comandos essenciais que você usa neste tutorial:
Configuração e símbolos:
- .sympath (Definir Caminho do Símbolo) – Configurar onde o WinDbg encontra arquivos de símbolo
- .reload (Módulo de Recarregamento) – Carregar arquivos de símbolo
Controlando a execução:
- g (Go) – Continuar a execução do programa
- bu (Definir Ponto de Interrupção) – Pausar a execução em uma função específica
-
Step Into(F11) – Executar uma instrução e entrar em funções
Inspecionando seu programa:
- x (Examinar Símbolos) – Listar funções e variáveis
- lm (Listar Módulos Carregados) – Mostrar todas as DLLs carregadas e executáveis
- k (Exibir Retrocesso da Pilha) – Ver a pilha de chamadas
- ~ (Status do Thread) – Listar todos os threads
- !analyze -v - Analisar automaticamente falhas
Referência:
- bl (Lista de Pontos de Interrupção)
- ~s (Definir Thread Atual)
- .sympath+
- .srcpath (Definir caminho de origem)
- qd (Sair e Desanexar)
Consulte também
Introdução ao WinDbg (modo kernel)