Depurar drivers do Windows em laboratório passo a passo (modo kernel de eco)
Este laboratório apresenta o depurador do kernel WinDbg. Você usa WinDbg para depurar o código de driver de exemplo de modo kernel echo.
Objetivos do laboratório
Este laboratório inclui exercícios que introduzem as ferramentas de depuração, ensinam comandos de depuração comuns, ilustram o uso de pontos de interrupção e mostram como usar as extensões de depuração.
Neste laboratório, usa-se uma conexão de depuração do kernel ao vivo para explorar as seguintes ações:
- Usar os comandos do depurador do Windows
- Use comandos padrão (pilhas de chamadas, variáveis, threads, IRQL)
- Usar Comandos Avançados de Depuração de Driver (!commands)
- Usar símbolos
- Definir pontos de interrupção na depuração ao vivo
- Ver pilhas de chamadas
- Exibir a árvore de dispositivos Plug and Play
- Trabalhar com thread e contexto de processo
Depuração do modo de usuário e do kernel
Ao trabalhar com o depurador do Windows, você pode fazer dois tipos de depuração:
Modo de usuário - Aplicativos e subsistemas são executados no computador no modo de usuário. Os processos que são executados no modo de usuário o fazem dentro de seus próprios espaços de endereço virtual. Eles são impedidos de obter acesso direto a muitas partes do sistema, incluindo hardware do sistema, memória que não está alocada para seu uso e outras partes do sistema que podem comprometer a integridade do sistema. Como os processos executados no modo de usuário são efetivamente isolados do sistema e de outros processos do modo de usuário, eles não podem interferir nesses recursos.
Modo kernel - O sistema operacional e os programas privilegiados são executados no modo kernel. O código do modo kernel tem permissão para acessar qualquer parte do sistema. Ele não é restrito como o código do modo de usuário. Ele pode obter acesso a qualquer parte de qualquer outro processo em execução no modo de usuário ou no modo kernel. Grande parte da funcionalidade principal do sistema operacional e muitos drivers de dispositivo de hardware são executados no modo kernel.
Este exercício abrange comandos de depuração frequentemente usados durante a depuração em modo de utilizador e em modo kernel. O exercício também abrange extensões de depuração, às vezes chamadas de "bang" !commands, que são usadas para depuração em modo kernel.
Configuração do laboratório
Você precisa do seguinte hardware para concluir o laboratório:
- Um laptop ou computador desktop (host) executando o Windows 10
- Um segundo laptop ou computador desktop (destino) executando o Windows 10
- Um hub de rede ou roteador e cabos de rede para conectar os dois computadores
- Acesso à internet para baixar arquivos de símbolos
Você precisa do seguinte software para concluir o laboratório:
- Estúdio Visual
- Kit de Desenvolvimento de Software (SDK) do Windows para Windows 10
- Kit de driver do Windows (WDK) para Windows 10
- O driver de eco de exemplo para Windows 10
O laboratório tem as seguintes secções:
- Conectar-se a uma sessão WinDbg de modo kernel
- Comandos e técnicas de depuração do modo kernel
- Baixe e construa o driver de eco KMDF
- Instale o exemplo de driver de eco no sistema de destino
- Use o WinDbg para exibir informações sobre o driver
- Exibir informações da árvore de dispositivos Plug and Play
- Trabalhar com pontos de interrupção e código-fonte
- Ver variáveis e pilhas de chamadas
- Mostrar processos e threads
- IRQL, registra e encerra a sessão WinDbg
- recursos de depuração do Windows
Conectar-se a uma sessão WinDbg de modo kernel
Nesta secção, configure a depuração de rede no computador anfitrião e no sistema de destino.
Os computadores neste laboratório precisam ser configurados para usar uma conexão de rede Ethernet para debug do kernel.
Este laboratório utiliza dois computadores. O depurador do Windows é executado no sistema host e o driver KMDF (Kernel Mode Driver Framework) de eco é executado no sistema de destino .
Use um hub ou roteador de rede e cabos de rede para conectar os dois computadores.
Para trabalhar com aplicativos de modo kernel e usar o WinDbg, recomendamos que você use o transporte KDNET over Ethernet. Para obter informações sobre como usar o protocolo de transporte Ethernet, consulte Introdução ao WinDbg (modo kernel). Para obter mais informações sobre como configurar o computador de destino, consulte Preparação de um computador para a implantação manual de drivers e Configuração da depuração do kernel de rede KDNET automaticamente.
Configurar a depuração no modo kernel usando a Ethernet
Para habilitar a depuração em modo kernel no sistema de destino:
No sistema host, abra uma janela de prompt de comando e digite ipconfig para determinar seu endereço IPv4.
Windows IP Configuration Ethernet adapter Ethernet: Connection-specific DNS Suffix . : Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b%3 Autoconfiguration IPv4 Address. . : 169.182.1.1 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . :
Registre o endereço IP do sistema host: ______________________________________
No sistema de destino, abra uma janela do Prompt de Comando e use o comando
ping
para confirmar a conectividade de rede entre os dois sistemas.ping 169.182.1.1
Use o endereço IP real do sistema host que você gravou em vez de 169.182.1.1 que é mostrado na saída de exemplo.
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
Ative a depuração em modo kernel no sistema de destino seguindo os passos a seguir.
Importante
Antes de usar o BCDEdit para alterar as informações de inicialização, talvez seja necessário suspender temporariamente os recursos de segurança do Windows, como BitLocker e Inicialização Segura, no computador de teste. Reative esses recursos de segurança quando o teste estiver concluído. Gerencie adequadamente o computador de teste quando os recursos de segurança estiverem desativados. A inicialização segura normalmente é desativada na UEFI. Para acessar a configuração UEFI, Use Sistema, Recuperação, Inicialização avançada. Ao reiniciar, selecione Solução de problemas, Opções avançadas, Configurações de firmware UEFI. Tenha cuidado, pois definir incorretamente as opções de UEFI ou desativar o BitLocker pode tornar o sistema inoperante.
No computador de destino, abra uma janela da Linha de Comandos enquanto Administrador. Digite este comando para habilitar a depuração:
bcdedit /set {default} DEBUG YES
Digite este comando para habilitar a assinatura de teste:
bcdedit /set TESTSIGNING ON
Digite este comando para definir o endereço IP do sistema host. Use o endereço IP do sistema host que você gravou anteriormente, não o mostrado.
bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Advertência
Para aumentar a segurança da conexão e diminuir o risco de solicitações aleatórias de conexão do depurador do cliente, use uma chave aleatória gerada automaticamente. Para mais informações, consulte Configuração automática da depuração do kernel de rede KDNET.
Digite este comando para confirmar se os valores para
dbgsettings
estão definidos corretamente:bcdedit /dbgsettings
key 2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p debugtype NET hostip 169.168.1.1 port 50000 dhcp Yes The operation completed successfully.
Observação
Se você receber uma mensagem do firewall e quiser usar o depurador, selecione todas as três caixas.
No computador host, abra uma janela do Prompt de Comando como Administrador. Este laboratório usa a versão x64 do WinDbg.exe do Kit de Driver do Windows (WDK) que foi instalado como parte da instalação do kit do Windows. Mude para o diretório WinDbg padrão, o local padrão é mostrado abaixo.
cd C:\Program Files(x86)\Windows Kits\10\Debuggers\x64
Este laboratório pressupõe que ambos os computadores executam uma versão de 64 bits do Windows no destino e no host. Se esse não for o caso, a melhor abordagem é executar a mesma de bits
de ferramentas no host que o destino executa. Por exemplo, se o destino executar o Windows de 32 bits, execute uma versão de 32 bits do depurador no host. Para obter mais informações, consulte Escolhendo as ferramentas de depuração de 32 bits ou 64 bits. Abra o WinDbg com depuração de usuário remoto usando o seguinte comando. Os valores da chave e da porta correspondem aos valores definidos anteriormente usando o BCDEdit no computador de destino.
WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Reinicie o sistema de destino.
Em um ou dois minutos, a saída de depuração deve ser exibida no sistema anfitrião.
Microsoft (R) Windows Debugger Version 10.0.17074.1002 AMD64 Copyright (c) Microsoft Corporation. All rights reserved. Using NET for debugging Opened WinSock 2.0 Waiting to reconnect... Connected to target 169.182.1.1 on port 50005 on local IP 169.182.1.2 You can get the target MAC address by running .kdtargetmac command. Connected to Windows 10 16299 x64 target at (Wed Feb 28 17:16:23.051 2018 (UTC - 8:00)), ptr64 TRUE Kernel Debugger connection established. (Initial Breakpoint requested) Symbol search path is: srv* Executable search path is: Windows 10 Kernel Version 16299 MP (4 procs) Free x64 Product: WinNt, suite: TerminalServer SingleUserTS Built by: 16299.15.amd64fre.rs3_release.170928-1534 Machine Name: Kernel base = 0xfffff800`9540d000 PsLoadedModuleList = 0xfffff800`95774110 Debug session time: Wed Feb 28 17:16:23.816 2018 (UTC - 8:00) System Uptime: 0 days 0:00:20.534
A janela Comando do Depurador é a principal janela de informações de depuração no WinDbg. Pode introduzir comandos do depurador e visualizar os resultados dos comandos nesta janela.
A Janela de Comando do Depurador é dividida em dois painéis. Insira comandos no painel menor, que é o painel de entrada de comando na parte inferior da janela, e exiba a saída do comando no painel maior na parte superior da janela.
No painel de entrada de comandos, use as teclas de seta para cima e seta para baixo para percorrer o histórico de comandos. Quando um comando aparece, você pode editá-lo ou pressionar Enter para executá-lo.
Comandos e técnicas de depuração no modo kernel
Nesta seção, use comandos de depuração para exibir informações sobre o sistema de destino.
Alguns comandos de depuração exibem texto usando DML (Debugger Markup Language) que você pode selecionar para coletar rapidamente mais informações.
No sistema host, use Ctrl+Scroll Lock no WinDBg para interromper o código que está a executar-se no sistema de destino. Pode levar algum tempo para o sistema de destino responder.
Digite o seguinte comando para ativar o DML na janela de comando do depurador:
0: kd> .prefer_dml 1 DML versions of commands on by default
Você pode acessar a ajuda do comando de referência usando o comando
.hh
. Digite o seguinte comando para exibir a ajuda de referência de comando para.prefer_dml
:0: kd> .hh .prefer_dml
O ficheiro de ajuda do Depurador exibe a ajuda para o comando
.prefer_dml
.Para exibir informações detalhadas sobre a versão do sistema de destino, digite o comando vertarget (Show Target Computer Version) na janela 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
Para verificar se você está trabalhando com o processo de modo kernel correto, digite o comando lm (List Loaded Modules)
na janela WinDbg para exibir os módulos carregados: 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 ...
A saída que foi omitida é indicada com "..." neste laboratório.
Para solicitar informações detalhadas sobre um módulo específico, use a opção
v
(verbose):0: Kd> lm v m tcpip Browse full module list start end module name fffff801`09eeb000 fffff801`0a157000 tcpip (no symbols) Loaded symbol image file: tcpip.sys Image path: \SystemRoot\System32\drivers\tcpip.sys Image name: tcpip.sys Browse all global symbols functions data Timestamp: Sun Nov 09 18:59:03 2014 (546029F7) CheckSum: 00263DB1 ImageSize: 0026C000 Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4 Unable to enumerate user-mode unloaded modules, Win32 error 0n30
Não há um caminho de símbolo definido, nem símbolos carregados, por isso, estão disponíveis informações limitadas no depurador.
Baixe e compile o driver de eco KMDF
Nesta seção, baixe e crie o driver de eco KMDF.
Normalmente, você estaria trabalhando com seu próprio código de driver quando você usa WinDbg. Para se familiarizar com o funcionamento do WinDbg, este laboratório utiliza o driver de exemplo "Echo" do Modelo KMDF. O código-fonte está disponível para ajudar a entender as informações exibidas no WinDbg. Este exemplo também é usado para ilustrar como se pode avançar passo a passo através do código nativo em modo kernel. Essa técnica pode ser valiosa para depurar problemas complexos de código de modo kernel.
Para baixar e criar o driver de exemplo Echo:
Primeiro, descarregue e extraia o exemplo KMDF Echo do GitHub.
O exemplo de eco KMDF está localizado na pasta geral.
Baixe as amostras de driver em um arquivo zip: Amostras de driver
Transfira o ficheiro zip para o seu disco rígido local.
Selecione e segure ou clique com o botão direito do mouse no arquivo zip e selecione Extrair tudo. Especifique uma nova pasta ou navegue até uma pasta existente para armazenar os arquivos extraídos. Por exemplo, você pode especificar C:\DriverSamples\ como a nova pasta para a qual extrair os arquivos.
Depois que os arquivos forem extraídos, vá para a seguinte subpasta: C:\DriverSamples\general\echo\kmdf
No Microsoft Visual Studio, selecione Arquivo>Abrir>Projeto/Solução... e vá para a pasta que contém os arquivos extraídos, por exemplo, C:\DriverSamples\general\echo\kmdf. Clique duas vezes no arquivo de solução kmdfecho para abri-lo.
No Visual Studio, localize o Gerenciador de Soluções. Se essa janela ainda não estiver aberta, selecione Gerenciador de Soluções no menu Exibir. No Gerenciador de Soluções, você pode ver uma solução que tem três projetos.
Defina a configuração e a plataforma da amostra. No Gerenciador de Soluções, selecione e segure ou clique com o botão direito do rato Solução 'kmdfecho' (3 projetos)e selecione Gestor de Configuração. Certifique-se de que a configuração e as configurações da plataforma são as mesmas para os três projetos. Por padrão, a configuração é definida como Win10 Debuge a plataforma é definida como Win64 para todos os projetos. Se você fizer alterações de configuração ou plataforma para um projeto, faça as mesmas alterações para os três projetos restantes.
As amostras de driver precisam ser modificadas para usar valores que não se sobreponham com os drivers existentes. Consulte Do Código de Exemplo ao Driver de Produção - O que Alterar nos Exemplos sobre como criar um exemplo exclusivo de driver que coexistirá com os drivers reais já instalados no Windows.
Defina a biblioteca de tempo de execução. Abra a página de propriedades do driver de eco e localize C/C++>Code Generation. Altere a biblioteca de execução para Debug Multithreaded (/MTd). Para obter mais informações sobre as opções de compilação, consulte /MD, /MT, /LD (Use Run-Time Library).
Nas propriedades do driver, verifique se Assinatura de Driver>Modo de Assinatura está definido como Sinal de Teste.
No Visual Studio, selecione Build>Build Solution.
As janelas de compilação devem exibir uma mensagem indicando que a compilação para todos os três projetos foi bem-sucedida.
Dica
Se você encontrar uma mensagem de erro de compilação, use o número de erro de compilação para determinar uma correção. Por exemplo, erro MSBuild MSB8040 descreve como trabalhar com bibliotecas de espectro atenuado.
No Explorador de Ficheiros, vá para a pasta que contém os ficheiros extraídos para o exemplo. Por exemplo, vá para C:\DriverSamples\general\echo\kmdf, se essa for a pasta especificada anteriormente. Dentro dessa pasta, o local dos arquivos de driver compilados varia dependendo da configuração e das definições de plataforma selecionadas no Configuration Manager. Se você deixou as configurações padrão inalteradas, os arquivos de driver compilados serão salvos em uma pasta chamada \x64\Debug para uma compilação de depuração de 64 bits.
Vá para a pasta que contém os arquivos criados para o driver Autosync: C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.
A pasta deve conter estes ficheiros:
Ficheiro Descrição Echo.sys O arquivo do driver. Echo.inf Um arquivo de informações (INF) que contém informações necessárias para instalar o driver. Além disso, o arquivo echoapp.exe foi criado e deve ser localizado aqui: C:\DriverSamples\general\echo\kmdf\exe\x64\Debug.
Ficheiro Descrição EchoApp.exe Um arquivo de teste executável do prompt de comando que se comunica com o driver echo.sys. Localize um pen drive USB ou configure um compartilhamento de rede para copiar os arquivos de driver construídos e o teste EchoApp do host para o sistema de destino.
Na próxima seção, copie o código para o sistema de destino e instale e teste o driver.
Instalar o exemplo de driver de eco KMDF no sistema de destino
Nesta seção, utilize a ferramenta DevCon para instalar o driver de exemplo de eco.
O computador onde você instala o driver é chamado de computador de destino ou o computador de teste . Normalmente, este computador é separado do computador no qual você desenvolve e compila o pacote de driver. O computador onde o utilizador desenvolve e compila o driver é chamado de computador host.
O processo de mover o pacote de driver para o computador de destino e instalar o driver é chamado implantação o driver.
Antes de implantar um driver assinado de teste, prepare o computador de destino ativando a assinatura de teste. Você também precisa localizar a ferramenta DevCon na instalação do WDK e copiá-la para o sistema de destino.
Para instalar o driver no sistema de destino, execute as etapas a seguir.
No sistema de destino, ative controladores assinados de teste:
Abra Configurações do Windows.
No Atualização e Segurança, selecione Recuperação.
Em Inicialização Avançada, selecione Reiniciar agora.
Quando o computador for reiniciado, selecione Opções de inicialização. No Windows 10, selecione Solucionar problemas>opções avançadas>Configurações de inicialização e, em seguida, selecione Reiniciar.
Selecione Desativar imposição de assinatura de driver pressionando a tecla F7.
Reinicie o computador de destino.
No sistema host, vá para a pasta Tools na instalação do WDK e localize a ferramenta DevCon. Por exemplo, procure na seguinte pasta: C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe.
Crie uma pasta no destino para o pacote de driver compilado, por exemplo, C:\EchoDriver. Copie devcon.exe para o sistema de destino. Localize o certificado .cer no sistema host. Está na mesma pasta no computador host, na pasta que contém os arquivos de driver compilados. Copie todos os arquivos do driver construído descrito anteriormente no computador host e salve-os na mesma pasta que você criou no computador de destino.
No computador de destino, selecione e segure ou clique com o botão direito do mouse no arquivo de certificado e selecione Instalare, em seguida, siga as instruções para instalar o certificado de teste.
Se precisar de instruções mais detalhadas para configurar o computador de destino, consulte Preparando um computador para implantação manual de driver.
As instruções a seguir mostram como instalar e testar o driver de exemplo. Aqui está a sintaxe geral para a ferramenta devcon que você usa para instalar o driver:
devcon install <INF file> <hardware ID>
O arquivo INF necessário para instalar este driver é echo.inf. O ficheiro inf contém o ID de hardware para instalar o echo.sys. Para a amostra de eco, o ID de hardware é root\ECHO.
No computador de destino, abra uma janela da Linha de Comandos como Administrador. Vá para a pasta do pacote de driver e digite o seguinte comando:
devcon install echo.inf root\ECHO
Se você receber uma mensagem de erro indicando que o devcon não está a ser reconhecido, tente adicionar o caminho à ferramenta devcon. Por exemplo, se você copiou para uma pasta chamada C:\Tools, tente usar o seguinte comando:
c:\tools\devcon install echo.inf root\ECHO
É exibida uma caixa de diálogo que indica que o driver de teste é um driver não assinado. Selecione Instalar este driver mesmo assim para continuar.
Dica
Se você tiver algum problema com a instalação, verifique o seguinte arquivo para obter mais informações. %windir%\inf\setupapi.dev.log
Depois de instalar com êxito o driver de exemplo, você está pronto para testá-lo.
No computador de destino, em uma janela do Prompt de Comando, digite devmgmt para abrir o Gerenciador de Dispositivos. No Gestor de Dispositivos, no menu Ver, selecione Dispositivos por tipo. Na árvore de dispositivos, localize Sample WDF Echo Driver no nó Sample Device.
Digite echoapp para iniciar o aplicativo de eco de teste para confirmar se o driver está funcional.
C:\Samples\KMDF_Echo_Sample> echoapp
DevicePath: \\?\root#sample#0005#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
512 Pattern Bytes Written successfully
512 Pattern Bytes Read successfully
Pattern Verified successfully
30720 Pattern Bytes Written successfully
30720 Pattern Bytes Read successfully
Pattern Verified successfully
Utilize o WinDbg para exibir informações sobre o driver
Nesta seção, defina o caminho do símbolo e use os comandos do depurador do kernel para exibir informações sobre o driver de exemplo de eco KMDF.
Para visualizar informações sobre o driver:
No sistema host, se você fechou o depurador, abra-o novamente usando o seguinte comando na janela do prompt de comando do administrador.
WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Use Ctrl+Break (Scroll Lock) para quebrar o código em execução no sistema de destino.
Para definir o caminho dos símbolos para o servidor de símbolos da Microsoft no ambiente WinDbg, use o comando
.symfix
.0: kd> .symfix
Para adicionar a localização do símbolo local e utilizar os símbolos locais, adicione o caminho usando
.sympath+
e, em seguida,.reload /f
.0: kd> .sympath+ C:\DriverSamples\general\echo\kmdf 0: kd> .reload /f
O comando
.reload
com a opção/f
force exclui todas as informações de símbolos do módulo especificado e recarrega os símbolos. Em alguns casos, este comando também recarrega ou descarrega o próprio módulo.
Você deve carregar os símbolos adequados para usar a funcionalidade avançada que o WinDbg fornece. Se você não tiver símbolos configurados corretamente, ao tentar usar a funcionalidade que depende de símbolos, receberá mensagens indicando que os símbolos não estão disponíveis.
0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.
Existem muitas abordagens que podem ser usadas para trabalhar com símbolos. Em muitas situações, você pode configurar o computador para acessar símbolos de um servidor de símbolos que a Microsoft fornece quando eles são necessários. Este laboratório usa essa abordagem. Se os símbolos em seu ambiente estiverem em um local diferente, modifique as etapas para usar esse local. Para obter mais informações, consulte caminho dos símbolos para o depurador do Windows.
Para executar a depuração de origem, você deve criar uma versão verificada (depuração) de seus binários. O compilador cria arquivos .pdb de símbolo (). Esses arquivos de símbolo mostram ao depurador como as instruções binárias correspondem às linhas de origem. Os próprios arquivos de origem também devem estar acessíveis ao depurador.
Os arquivos de símbolo não contêm o texto do código-fonte. Para depuração, é melhor se o vinculador não otimizar seu código. A depuração de origem e o acesso a variáveis locais são mais difíceis e, às vezes, quase impossíveis, se o código tiver sido otimizado. Se você estiver tendo problemas para visualizar variáveis locais ou linhas de origem, defina as seguintes opções de compilação:
set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
Digite o seguinte comando na área de comando do depurador para exibir informações sobre o driver de eco:
0: kd> lm m echo* v Browse full module list start end module name fffff801`4ae80000 fffff801`4ae89000 ECHO (private pdb symbols) C:\Samples\KMDF_ECHO_SAMPLE\echo.pdb Loaded symbol image file: ECHO.sys Image path: \SystemRoot\system32\DRIVERS\ECHO.sys Image name: ECHO.sys ...
Para obter mais informações, consulte lm.
Como este conjunto de laboratório
prefer_dml
foi configurado anteriormente, alguns elementos da saída são links ativos que pode selecionar. Selecione o link Procurar todos os símbolos globais na saída de depuração para exibir informações sobre símbolos de itens que começam com a letra "a".0: kd> x /D Echo!a*
A amostra de eco não contém símbolos que comecem com a letra "a", portanto, digite
x ECHO!Echo*
para exibir informações sobre todos os símbolos associados ao driver de eco que começam com "Echo".0: kd> x ECHO!Echo* fffff801`0bf95690 ECHO!EchoEvtIoQueueContextDestroy (void *) fffff801`0bf95000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *) fffff801`0bf95ac0 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *) fffff801`0bf9b120 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *) ...
Para obter mais informações, consulte x (Examinar símbolos).
A extensão
!lmi
exibe informações detalhadas sobre um módulo. Digite!lmi echo
. Sua saída deve ser semelhante ao texto mostrado neste exemplo:0: kd> !lmi echo Loaded Module Info: [echo] Module: ECHO Base Address: fffff8010bf94000 Image Name: ECHO.sys …
Use a extensão
!dh
para exibir informações de cabeçalho, conforme mostrado neste exemplo:0: kd> !dh echo File Type: EXECUTABLE IMAGE FILE HEADER VALUES 14C machine (i386) 6 number of sections 54AD8A42 time date stamp Wed Jan 07 11:34:26 2015 ...
Digite o seguinte para alterar a máscara de bits de depuração padrão para que todas as mensagens de depuração do sistema de destino sejam exibidas no depurador:
0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
Alguns drivers exibem informações adicionais quando a máscara de 0xFFFFFFFF é usada. Defina a máscara como 0x00000000 se quiser reduzir a quantidade de informações exibidas.
0: kd> ed nt!Kd_DEFAULT_MASK 0x00000000
Use o comando
dd
para confirmar se a máscara está definida para exibir todas as mensagens do depurador.0: kd> dd nt!kd_DEFAULT_MASK fffff802`bb4057c0 ffffffff 00000000 00000000 00000000 fffff802`bb4057d0 00000000 00000000 00000000 00000000 fffff802`bb4057e0 00000001 00000000 00000000 00000000 fffff802`bb4057f0 00000000 00000000 00000000 00000000 fffff802`bb405800 00000000 00000000 00000000 00000000 fffff802`bb405810 00000000 00000000 00000000 00000000 fffff802`bb405820 00000000 00000000 00000000 00000000 fffff802`bb405830 00000000 00000000 00000000 00000000
Exibir informações da árvore de dispositivos Plug and Play
Nesta seção, apresente informações sobre o driver de dispositivo de amostra de eco e a sua posição na árvore de dispositivos Plug and Play.
As informações sobre o driver de dispositivo na árvore de dispositivos Plug and Play podem ser úteis para solucionar problemas. Por exemplo, se um driver de dispositivo não for residente na árvore de dispositivos, pode haver um problema com a instalação do driver de dispositivo.
Para obter mais informações sobre a extensão de depuração do nó do dispositivo, consulte !devnode.
No sistema anfitrião, para ver todos os nós de dispositivos na árvore de dispositivos Plug and Play, introduza o comando
!devnode 0 1
.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… …
Use Ctrl+F para pesquisar no resultado gerado para procurar o nome do driver de dispositivo, echo.
O driver do dispositivo de eco deve ser carregado. Use o comando
!devnode 0 1 echo
para exibir informações Plug and Play associadas ao driver do dispositivo echo, conforme mostrado neste exemplo:0: Kd> !devnode 0 1 echo Dumping IopRootDeviceNode (= 0xffffe0007b725d30) DevNode 0xffffe0007b71a630 for PDO 0xffffe0007b71a960 InstancePath is "ROOT\SAMPLE\0000" ServiceName is "ECHO" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) …
A saída exibida no comando anterior inclui o PDO associado à instância em execução do seu driver, neste exemplo, 0xffffe0007b71a960. Digite o comando
!devobj <PDO address>
para exibir informações Plug and Play associadas ao driver de dispositivo echo. Use o endereço DOP que!devnode
exibe no seu computador, não o mostrado aqui.0: kd> !devobj 0xffffe0007b71a960 Device object (ffffe0007b71a960) is for: 0000000e \Driver\PnpManager DriverObject ffffe0007b727e60 Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040 Dacl ffffc102c9b36031 DevExt 00000000 DevObjExt ffffe0007b71aab0 DevNode ffffe0007b71a630 ExtensionFlags (0x00000800) DOE_DEFAULT_SD_PRESENT Characteristics (0x00000180) FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN AttachedDevice (Upper) ffffe000801fee20 \Driver\ECHO Device queue is not busy.
A saída exibida no comando
!devnode 0 1
inclui o endereço PDO associado à instância em execução do seu driver, neste exemplo é 0xffffe0007b71a960. Digite o comando!devstack <PDO address>
para exibir informações Plug and Play associadas ao driver de dispositivo. Use o endereço DOP que!devnode
exibe no seu computador, não o mostrado neste exemplo.0: kd> !devstack 0xffffe0007b71a960 !DevObj !DrvObj !DevExt ObjectName ffffe000801fee20 \Driver\ECHO ffffe0007f72eff0 > ffffe0007b71a960 \Driver\PnpManager 00000000 0000000e !DevNode ffffe0007b71a630 : DeviceInst is "ROOT\SAMPLE\0000" ServiceName is "ECHO"
A saída mostra que você tem uma pilha de drivers de dispositivo bastante simples. O driver de eco é filho do nó PnPManager. PnPManager é um nó raiz.
\Driver\ECHO
\Driver\PnpManager
Este diagrama mostra uma árvore de nós de dispositivo mais complexa.
Para obter mais informações sobre pilhas de drivers mais complexas, consulte Pilhas de drivers e Nós de dispositivo e pilhas de dispositivos.
Trabalhar com pontos de interrupção e código-fonte
Nesta seção, defina pontos de interrupção e execute o código-fonte do modo kernel passo a passo.
Para ser capaz de percorrer o código e verificar os valores das variáveis em tempo real, habilitar pontos de interrupção e definir um caminho para o código-fonte.
Os pontos de interrupção interrompem a execução de código em uma linha de código específica. Avance no código a partir daquele ponto para corrigir essa seção específica do código.
Para definir um ponto de interrupção usando um comando debug, use um dos seguintes comandos b
.
Comando | Descrição |
---|---|
bp |
Define um ponto de interrupção que fica ativo até que o módulo em que ele está seja descarregado. |
bu |
Define um ponto de interrupção que não é resolvido quando o módulo é descarregado e reativa quando o módulo é recarregado. |
bm |
Define um ponto de interrupção para um símbolo. Este comando usa bu ou bp apropriadamente e permite que curingas (* ) sejam usados para definir pontos de interrupção em cada símbolo que corresponde, como todos os métodos em uma classe. |
Para obter mais informações, consulte Depuração de código-fonte no WinDbg.
No sistema host, use a interface de utilizador do WinDbg para confirmar se Depurar >Modo de Origem está ativado na sessão WinDbg atual.
Digite o seguinte comando para adicionar seu local de código local ao caminho de origem:
.srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
Digite o seguinte comando para adicionar o local do símbolo local ao caminho do símbolo:
.sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
Use o comando
x
para examinar os símbolos associados ao driver de eco para determinar o nome da função a ser usada para o ponto de interrupção. Você pode usar um curinga ou Ctrl+F para localizar o nome da funçãoDeviceAdd
.0: kd> x ECHO!EchoEvt* 8b4c7490 ECHO!EchoEvtIoQueueContextDestroy (void *) 8b4c7000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *) 8b4c7820 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *) 8b4cb0e0 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *) 8b4c75d0 ECHO!EchoEvtIoWrite (struct WDFQUEUE__ *, struct WDFREQUEST__ *, unsigned int) 8b4cb170 ECHO!EchoEvtDeviceAdd (struct WDFDRIVER__ *, struct …
A saída mostra que o método
DeviceAdd
do driver de eco éECHO!EchoEvtDeviceAdd
.Como alternativa, revise o código-fonte para encontrar o nome da função para seu ponto de interrupção.
Defina o ponto de interrupção com o comando
bm
usando o nome do driver, seguido pelo nome da função, por exemplo,AddDevice
, onde você deseja definir o ponto de interrupção, separado por um ponto de exclamação. Este laboratório usaAddDevice
para monitorizar o carregamento do controlador.0: kd> bm ECHO!EchoEvtDeviceAdd 1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
Você pode usar sintaxe diferente em conjunto com a configuração de variáveis como
<module>!<symbol>
,<class>::<method>
,'<file.cpp>:<line number>'
ou ignorar várias vezes<condition> <#>
. Para obter mais informações, consulte pontos de interrupção condicionais no WinDbg e outros depuradores do Windows.Liste os pontos de interrupção atuais para confirmar que o ponto de interrupção foi definido inserindo o comando
bl
:0: kd> bl 1 e fffff801`0bf9b1c0 0001 (0001) ECHO!EchoEvtDeviceAdd
O "e" na saída mostrada aqui indica que o ponto de interrupção número 1 está habilitado para disparar.
Reinicie a execução de código no sistema de destino inserindo o comando
g
(go).No sistema de destino, no Windows, abra Gestor de Dispositivos usando o ícone ou inserindo mmc devmgmt.msc. No Gestor de Dispositivos, expanda o nó Amostras.
Selecione e segure ou clique com o botão direito do mouse na entrada do driver de eco KMDF e selecione Desativar no menu.
Selecione e segure ou clique com o botão direito do mouse na entrada do driver de eco KMDF novamente e selecione Ativar no menu.
No sistema host, quando o driver está habilitado, o ponto de interrupção de depuração do AddDevice deve ser acionado. A execução do código do driver no sistema de destino deve parar. Quando o ponto de interrupção é atingido, a execução deve ser interrompida no início da rotina de AddDevice. A saída do comando debug exibe
Breakpoint 1 hit
.Percorra o código linha por linha inserindo o comando
p
ou pressionando F10 até chegar ao final da seguinte rotina AddDevice. O caractere Brace (}
) é destacado como mostrado.
Na próxima seção, examine o estado das variáveis após a execução do código DeviceAdd.
Você pode modificar os pontos de interrupção existentes usando os seguintes comandos:
Comando | Descrição |
---|---|
bl |
Lista os pontos de interrupção. |
bc |
Remove um ponto de interrupção da lista. Use bc * para limpar todos os pontos de interrupção. |
bd |
Desabilita um ponto de interrupção. Use bd * para desativar todos os pontos de interrupção. |
be |
Permite um ponto de interrupção. Use be * para habilitar todos os pontos de interrupção. |
Como alternativa, também pode modificar os pontos de interrupção na UI do WinDbg.
Você também pode definir pontos de interrupção que são acionados quando um local de memória é acessado. Use o comando ba
(break on access), com a seguinte sintaxe:
ba <access> <size> <address> {options}
Opção | Descrição |
---|---|
e |
execute: quando a CPU busca uma instrução do endereço |
r |
leitura/gravação: quando a CPU lê ou grava no endereço |
w |
gravação: quando a CPU grava no endereço |
Você só pode definir quatro pontos de interrupção de dados a qualquer momento. Cabe a você certificar-se de que está alinhando seus dados corretamente para acionar o ponto de interrupção. As palavras devem terminar em endereços divisíveis por 2, as palavras devem ser divisíveis por 4 e as palavras quádruplas por 0 ou 8.
Por exemplo, para definir um ponto de interrupção de leitura/gravação em um endereço de memória específico, você pode usar um comando como este exemplo.
ba r 4 0x0003f7bf0
Você pode usar os comandos a seguir para percorrer seu código com os atalhos de teclado associados mostrados entre parênteses.
- Entrada (Ctrl+Break). Este comando interrompe um sistema enquanto o sistema estiver em execução e estiver em comunicação com o WinDbg. A sequência no Depurador do Kernel é Ctrl+C.
- Corra até ao cursor (F7 ou Ctrl+F10). Coloque o cursor numa janela de origem ou desmontagem onde pretende que a execução seja interrompida e, em seguida, prima F7. A execução do código continua até esse ponto. Se o fluxo de execução de código não atingir o ponto indicado pelo cursor, o WinDbg não quebrará. Essa situação pode acontecer se uma instrução IF não for executada.
- Executar (F5). Execute até que um ponto de interrupção seja encontrado ou um evento como uma verificação de bug ocorra.
- Avançar (F10). Este comando faz com que a execução de código prossiga uma declaração ou uma instrução de cada vez. Se uma chamada for encontrada, a execução de código ignora a chamada sem entrar na rotina chamada. Se a linguagem de programação for C ou C++ e o WinDbg estiver no modo de origem, o modo de origem poderá ser ativado ou desativado usando Debug>Source Mode.
- Entrar (F11). Este comando é como step-over, exceto que a execução de uma chamada entra na rotina chamada.
- Saia (Shift+F11). Este comando faz com que a execução continue até e termine na rotina atual ou no local atual na stack de chamadas. Este comando é útil se você já viu o suficiente da rotina.
Para obter mais informações, consulte Depuração de código-fonte no WinDbg.
Ver variáveis e pilhas de chamadas
Nesta seção, exiba informações sobre variáveis e pilhas de chamadas.
Este laboratório pressupõe que você está parado na rotina de
No sistema host, para exibir variáveis, use a visualização >item de menu local para exibir variáveis locais.
Para encontrar a localização de um endereço variável global, introduza ? <variable name>
.
- Step out (Shift+F11) – Este comando faz com que a execução seja executada e saia da rotina atual (local atual na pilha de chamadas). Isso é útil se você já viu o suficiente da rotina.
Para obter mais informações, consulte Depuração de código-fonte no WinDbg (Clássico) na documentação de referência de depuração.
Seção 8: Exibindo variáveis e pilhas de chamadas
Na Seção 8, você exibirá informações sobre variáveis e pilhas de chamadas.
Este laboratório pressupõe que parou na rotina AddDevice usando o processo descrito anteriormente. Para visualizar o resultado que é apresentado aqui, repita as etapas descritas anteriormente, se necessário.
<- No sistema host
Exibir variáveis
Use o modo de exibição >item de menu local para exibir variáveis locais.
Variáveis globais
Você pode encontrar a localização de um endereço variável global digitando ? <nome da variável>.
Variáveis locais
Você pode exibir os nomes e valores de todas as variáveis locais para um determinado quadro digitando o comando dv.
Para exibir os nomes e valores de todas as variáveis locais de um quadro específico, digite o comando dv
:
0: kd> dv
Driver = 0x00001fff`7ff9c838
DeviceInit = 0xffffd001`51978190
status = 0n0
A pilha de chamadas é a cadeia de chamadas de função que levaram à localização atual do contador do programa. A função superior na pilha de chamadas é a função atual, e a próxima função é a função que chamou a função atual, e assim por diante.
Para exibir a pilha de chamadas, use os comandos k*
.
Comando | Descrição |
---|---|
kb |
Exibe a pilha e os três primeiros parâmetros. |
kp |
Mostra as pilhas e a lista completa de parâmetros. |
kn |
Permite que você veja a pilha com as informações do quadro ao lado dela. |
No sistema host, se quiser manter a pilha de chamadas disponível, seleccione visualizar>pilha de chamadas para visualizá-la. Selecione as colunas na parte superior da janela para alternar a exibição de informações adicionais.
Use o comando
kn
para mostrar a pilha de chamadas durante a depuração do código do adaptador de exemplo num estado de interrupção.3: kd> kn # Child-SP RetAddr Call Site 00 ffffd001`51978110 fffff801`0942f55b ECHO!EchoEvtDeviceAdd+0x66 [c:\Samples\kmdf echo sample\c++\driver\autosync\driver.c @ 138] 01 (Inline Function) --------`-------- Wdf01000!FxDriverDeviceAdd::Invoke+0x30 [d:\wbrtm\minkernel\wdf\framework\shared\inc\private\common\fxdrivercallbacks.hpp @ 61] 02 ffffd001`51978150 fffff801`eed8097d Wdf01000!FxDriver::AddDevice+0xab [d:\wbrtm\minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 72] 03 ffffd001`51978570 fffff801`ef129423 nt!PpvUtilCallAddDevice+0x35 [d:\9142\minkernel\ntos\io\pnpmgr\verifier.c @ 104] 04 ffffd001`519785b0 fffff801`ef0c4112 nt!PnpCallAddDevice+0x63 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 7397] 05 ffffd001`51978630 fffff801`ef0c344f nt!PipCallDriverAddDevice+0x6e2 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 3390] ...
A pilha de chamadas mostra que o kernel (nt) chamou o código Plug and Play (PnP), que chamou o código do quadro de trabalho do driver (WDF), que mais tarde chamou a função DeviceAdd
do driver de eco.
Exibir processos e threads
Nesta seção, exiba informações sobre os processos e threads em execução no modo kernel.
Processos
Você pode exibir ou definir informações de processos usando a extensão do depurador !process. Defina um ponto de interrupção para examinar o processo usado quando um som é reproduzido.
No sistema host, insira o comando
dv
para examinar as variáveis de localidade associadas à rotinaEchoEvtIo
:0: kd> dv ECHO!EchoEvtIo* ECHO!EchoEvtIoQueueContextDestroy ECHO!EchoEvtIoWrite ECHO!EchoEvtIoRead
Limpe os pontos de interrupção anteriores usando
bc *
:0: kd> bc *
Defina um ponto de interrupção de símbolo nas rotinas de
EchoEvtIo
usando o seguinte comando:0: kd> bm ECHO!EchoEvtIo* 2: aade5490 @!”ECHO!EchoEvtIoQueueContextDestroy” 3: aade55d0 @!”ECHO!EchoEvtIoWrite” 4: aade54c0 @!”ECHO!EchoEvtIoRead”
Liste os pontos de interrupção para confirmar se o ponto de interrupção está definido corretamente:
0: kd> bl 1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197] 0001 (0001) ECHO!EchoEvtIoQueueContextDestroy ...
Insira
g
para reiniciar a execução do código:0: kd> g
No sistema de destino, execute o programa de teste de driver
EchoApp.exe
.No sistema host, quando o aplicativo de teste é executado, a rotina de E/S no driver é chamada. Essa chamada faz com que o ponto de interrupção seja acionado e a execução do código do driver no sistema de destino seja interrompida.
Breakpoint 2 hit ECHO!EchoEvtIoWrite: fffff801`0bf95810 4c89442418 mov qword ptr [rsp+18h],r8
Use o comando
!process
para exibir o processo atual envolvido na execução echoapp.exe:0: kd> !process PROCESS ffffe0007e6a7780 SessionId: 1 Cid: 03c4 Peb: 7ff7cfec4000 ParentCid: 0f34 DirBase: 1efd1b000 ObjectTable: ffffc001d77978c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000802c79f0 Vads 30 Clone 0 Private 135. Modified 5. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf270050 ElapsedTime 00:00:00.052 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (682, 50, 345) (2728KB, 200KB, 1380KB) PeakWorkingSetSize 652 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 688 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe00080e32080 Cid 03c4.0ec0 Teb: 00007ff7cfece000 Win32Thread: 0000000000000000 RUNNING on processor 1
A saída mostra que o processo está associado ao thread echoapp.exe, que estava em execução quando o ponto de interrupção no evento de gravação do driver foi atingido. Para obter mais informações, consulte !process.
Use o
!process 0 0
para exibir informações resumidas de todos os processos. Na saída, use Ctrl+F para localizar o mesmo endereço de processo para o processo associado à imagem echoapp.exe. No exemplo, o endereço do processo éffffe0007e6a7780
.... PROCESS ffffe0007e6a7780 SessionId: 1 Cid: 0f68 Peb: 7ff7cfe7a000 ParentCid: 0f34 DirBase: 1f7fb9000 ObjectTable: ffffc001cec82780 HandleCount: 34. Image: echoapp.exe ...
Registre a ID do processo associada ao echoapp.exe para usar posteriormente neste laboratório. Você também pode usar Ctrl+C para copiar o endereço para o buffer de cópia para uso posterior.
_____________________________________________________(echoapp.exe endereço do processo)
Insira
g
conforme necessário no depurador para executar o código até que echoapp.exe termine a execução. Ele atinge frequentemente o ponto de interrupção durante o evento de leitura e escrita. Quando echoapp.exe terminar, entre no depurador, ao pressionar Ctrl+ScrLk, (Ctrl+Break).Use o comando
!process
para confirmar que você está executando um processo diferente. Na saída mostrada aqui, o processo com o valor da Imagem System é diferente do valor da Imagem Echo.1: kd> !process PROCESS ffffe0007b65d900 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000 DirBase: 001ab000 ObjectTable: ffffc001c9a03000 HandleCount: 786. Image: System VadRoot ffffe0007ce45930 Vads 14 Clone 0 Private 22. Modified 131605. Locked 64. DeviceMap ffffc001c9a0c220 Token ffffc001c9a05530 ElapsedTime 21:31:02.516 ...
A saída mostra que um processo do sistema ffffe0007b65d900 estava em execução quando você parou o sistema operacional.
Use o comando
!process
para tentar ver o identificador do processo que foi associado a echoapp.exe que registrou anteriormente. Forneça seu endereço de processo echoapp.exe que você registrou anteriormente, em vez do endereço de processo de exemplo mostrado neste exemplo.0: kd> !process ffffe0007e6a7780 TYPE mismatch for process object at 82a9acc0
O objeto de processo não está mais disponível, porque o processo de echoapp.exe não está mais em execução.
Tópicos
Os comandos para visualizar e definir threads são semelhantes aos comandos para processos. Use o comando !thread para exibir threads. Use .thread para definir os threads atuais.
No sistema host, insira
g
no depurador para reiniciar a execução de código no sistema de destino.No sistema de destino, execute o programa de teste do controlador EchoApp.exe.
No sistema host, o ponto de interrupção é atingido e a execução do código é interrompida.
Breakpoint 4 hit ECHO!EchoEvtIoRead: aade54c0 55 push ebp
Para exibir os threads que estão em execução, digite !thread. Informações semelhantes ao exemplo a seguir devem ser exibidas:
0: kd> !thread THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0008096c900 Image: echoapp.exe ...
Observe o nome da imagem de echoapp.exe. Isso indica que você está olhando para o thread associado ao aplicativo de teste.
Use o comando
!process
para determinar se esse thread é o único thread em execução no processo associado ao echoapp.exe. O número do thread em execução no processo é o mesmo que o comando!thread
exibiu.0: kd> !process PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf5dc050 ElapsedTime 00:00:00.048 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (681, 50, 345) (2724KB, 200KB, 1380KB) PeakWorkingSetSize 651 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 686 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
Use o comando
!process 0 0
para localizar o endereço do processo de dois processos relacionados e registre o endereço do processo aqui.Cmd.exe: ____________________________________________________________
EchoApp.exe: _______________________________________________________
0: kd> !process 0 0 … PROCESS ffffe0007bbde900 SessionId: 1 Cid: 0f34 Peb: 7ff72dfa7000 ParentCid: 0c64 DirBase: 19c5fa000 ObjectTable: ffffc001d8c2f300 HandleCount: 31. Image: cmd.exe … PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe …
Como alternativa, você pode usar
!process 0 17
para exibir informações detalhadas sobre cada processo. A saída deste comando pode ser longa. A saída pode ser pesquisada usando Ctrl+F.Use o comando
!process
para listar informações de processo para ambos os processos que executam o computador. Forneça o endereço do processo a partir da saída!process 0 0
, não o endereço mostrado neste exemplo.Este exemplo de saída é para a ID de processo cmd.exe que foi registrada anteriormente. O nome da imagem para este ID de processo é cmd.exe.
0: kd> !process ffffe0007bbde900 PROCESS ffffe0007bbde900 SessionId: 1 Cid: 0f34 Peb: 7ff72dfa7000 ParentCid: 0c64 DirBase: 19c5fa000 ObjectTable: ffffc001d8c2f300 HandleCount: 31. Image: cmd.exe VadRoot ffffe0007bb8e7b0 Vads 25 Clone 0 Private 117. Modified 20. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001d8c48050 ElapsedTime 21:33:05.840 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 24656 QuotaPoolUsage[NonPagedPool] 3184 Working Set Sizes (now,min,max) (261, 50, 345) (1044KB, 200KB, 1380KB) PeakWorkingSetSize 616 VirtualSize 2097164 Mb PeakVirtualSize 2097165 Mb PageFaultCount 823 MemoryPriority FOREGROUND BasePriority 8 CommitCharge 381 THREAD ffffe0007cf34880 Cid 0f34.0f1c Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable ffffe0008096c900 ProcessObject Not impersonating ...
Este exemplo de saída é para a ID de processo echoapp.exe que foi registrada anteriormente.
0: kd> !process ffffe0008096c900 PROCESS ffffe0008096c900 SessionId: 1 Cid: 0b28 Peb: 7ff7d00df000 ParentCid: 0f34 DirBase: 1fb746000 ObjectTable: ffffc001db6b52c0 HandleCount: 34. Image: echoapp.exe VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0. DeviceMap ffffc001d83c6e80 Token ffffc001cf5dc050 ElapsedTime 00:00:00.048 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 33824 QuotaPoolUsage[NonPagedPool] 4464 Working Set Sizes (now,min,max) (681, 50, 345) (2724KB, 200KB, 1380KB) PeakWorkingSetSize 651 VirtualSize 16 Mb PeakVirtualSize 16 Mb PageFaultCount 686 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 138 THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating ...
Registre o primeiro endereço de thread associado aos dois processos aqui.
Cmd.exe: ____________________________________________________
EchoApp.exe: _________________________________________________
Use o comando
!Thread
para exibir informações sobre o thread atual.0: kd> !Thread THREAD ffffe000809a0880 Cid 0b28.1158 Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0 IRP List: ffffe0007bc5be10: (0006,01f0) Flags: 00060a30 Mdl: 00000000 Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0008096c900 Image: echoapp.exe Attached Process N/A Image: N/A ...
Como esperado, o thread atual é o thread associado ao echoapp.exe e está em um estado de execução.
Use o comando
!Thread
para exibir informações sobre o thread associado a cmd.exe processo. Forneça o endereço do thread que você gravou anteriormente.0: kd> !Thread ffffe0007cf34880 THREAD ffffe0007cf34880 Cid 0f34.0f1c Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable ffffe0008096c900 ProcessObject Not impersonating DeviceMap ffffc001d83c6e80 Owning Process ffffe0007bbde900 Image: cmd.exe Attached Process N/A Image: N/A Wait Start TickCount 4134621 Ticks: 0 Context Switch Count 4056 IdealProcessor: 0 UserTime 00:00:00.000 KernelTime 00:00:01.421 Win32 Start Address 0x00007ff72e9d6e20 Stack Init ffffd0015551dc90 Current ffffd0015551d760 Base ffffd0015551e000 Limit ffffd00155518000 Call 0 Priority 14 BasePriority 8 UnusualBoost 3 ForegroundBoost 2 IoPriority 2 PagePriority 5 Child-SP RetAddr : Args to Child : Call Site ffffd001`5551d7a0 fffff801`eed184fe : fffff801`eef81180 ffffe000`7cf34880 00000000`fffffffe 00000000`fffffffe : nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109] ffffd001`5551d8e0 fffff801`eed17f79 : ffff03a5`ca56a3c8 000000de`b6a6e990 000000de`b6a6e990 00007ff7`d00df000 : nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347] ffffd001`5551d980 fffff801`eecea340 : ffffd001`5551da18 00000000`00000000 00000000`00000000 00000000`00000388 : nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619] ...
Este thread está associado a cmd.exe e está em um estado de espera.
Forneça o endereço do thread do thread de CMD.exe em espera para alterar o contexto para esse thread em espera.
0: kd> .Thread ffffe0007cf34880 Implicit thread is now ffffe000`7cf34880
Use o comando
k
para exibir a pilha de chamadas associada ao thread em espera.0: kd> k *** Stack trace for last set context - .thread/.cxr resets it # Child-SP RetAddr Call Site 00 ffffd001`5551d7a0 fffff801`eed184fe nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109] 01 ffffd001`5551d8e0 fffff801`eed17f79 nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347] 02 ffffd001`5551d980 fffff801`eecea340 nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619] 03 ffffd001`5551da00 fffff801`ef02e642 nt!KeWaitForSingleObject+0x2c0 [d:\9142\minkernel\ntos\ke\wait.c @ 683] ...
Elementos da pilha de chamadas, como
KiCommitThreadWait
indicam que esse thread não está sendo executado como esperado.
Para obter mais informações sobre threads e processos, consulte as seguintes referências:
IRQL, registos e encerramento da sessão do WinDbg
Nesta seção, exiba o nível de solicitação de interrupção (IRQL) e o conteúdo dos registros.
Ver o IRQL guardado
O IRQL é usado para gerenciar a prioridade de interrupção de serviço. Cada processador tem uma configuração IRQL que os threads podem aumentar ou diminuir. As interrupções que ocorrem na configuração IRQL do processador ou abaixo dela são mascaradas e não interferem na operação atual. As interrupções que ocorrem acima da configuração IRQL do processador têm precedência sobre a operação atual.
No sistema anfitrião, a extensão !irql exibe o IRQL no processador em uso do computador de destino antes da interrupção do depurador. Quando o computador de destino entra no depurador, o IRQL muda, mas o IRQL que estava em vigor pouco antes da pausa no depurador é salvo e exibido por !irql
.
0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)
Ver os registos
No sistema host, exiba o conteúdo dos registos para o thread atual no processador atual usando o comando r (Registers).
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
Em alternativa, pode mostrar os conteúdos dos registos selecionando Ver>Registos. Para obter mais informações, consulte r (Registos).
A visualização do conteúdo dos registos pode ser útil ao analisar a execução de código em linguagem assembly e em outros cenários. Para obter mais informações sobre a desmontagem em linguagem de montagem, consulte Desmontagem x86 Anotada e Desmontagem x64 Anotada.
Para obter informações sobre o conteúdo do registro, consulte de arquitetura x86 e de arquitetura x64 .
Encerrar a sessão do WinDbg
Se quiseres deixar o depurador ligado, mas quiseres trabalhar no destino, remove todos os pontos de interrupção usando bc *
, para que o computador de destino não tente se conectar ao depurador do computador anfitrião. Em seguida, use o comando g
para permitir que o computador de destino seja executado novamente.
Para encerrar a sessão de depuração, no sistema host, entre no depurador e digite o comando qd
(Sair e Desanexar) ou selecione Parar Depuração no menu.
0: kd> qd
Para obter mais informações, consulte Encerrar uma sessão de depuração no WinDbg.
Recursos de depuração do Windows
Mais informações estão disponíveis sobre depuração no Windows. Alguns desses livros usam versões anteriores do Windows, como o Windows Vista, em seus exemplos, mas os conceitos discutidos são aplicáveis à maioria das versões do Windows.
Livros
- Depuração avançada do Windows por Mario Hewardt e Daniel Pravat
- Por dentro da depuração do Windows: um guia prático para estratégias de depuração e rastreamento no Windows® por Tarik Soulami
- Windows Internals por Pavel Yosifovich, Alex Ionescu, Mark Russinovich e David Solomon
Vídeo
Fornecedores de formação