Depurar o laboratório passo a passo dos drivers do Windows (modo de kernel de eco)
Este laboratório apresenta o depurador de kernel do WinDbg. Você usa o WinDbg para depurar o código de driver de exemplo do modo kernel de eco.
Objetivos de laboratório
Este laboratório inclui exercícios que introduzem as ferramentas de depuração, ensinam comandos comuns de depuração, ilustram o uso de pontos de interrupção e mostram como usar as extensões de depuração.
Neste laboratório, você usa uma conexão de depuração de kernel dinâmico para explorar as seguintes ações:
- Usar os comandos do depurador do Windows
- Usar comandos padrão (pilhas de chamadas, variáveis, threads, IRQL)
- Usar comandos avançados de depuração de driver (!comandos)
- Usar símbolos
- Definir pontos de interrupção na depuração dinâmica
- Exibir pilhas de chamadas
- Exibir a árvore de dispositivos Plug and Play
- Trabalhar com o thread e o contexto do processo
Depuração do modo de usuário e 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 executados no modo de usuário fazem isso em 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 é alocada para 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 de 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 aborda comandos de depuração que são frequentemente usados durante o modo de usuário e a depuração do modo kernel. O exercício também aborda extensões de depuração, às vezes chamadas de comandos !, que são usadas para depuração no modo kernel.
Configuração do laboratório
Você precisa do hardware a seguir para concluir o laboratório:
- Um laptop ou computador desktop (host) executando Windows 10
- Um segundo laptop ou computador desktop (destino) executando Windows 10
- Um hub de rede ou roteador e cabos de rede para conectar os dois computadores
- Acesso à Internet para baixar arquivos de símbolo
Você precisa do seguinte software para concluir o laboratório:
- Visual Studio
- Software Development Kit do Windows (SDK do Windows) para Windows 10
- WDK (Windows Driver Kit) para Windows 10
- O driver de eco de exemplo para Windows 10
O laboratório tem as seguintes seções:
- Conectar-se a uma sessão WinDbg no modo kernel
- Comandos e técnicas de depuração no modo kernel
- Baixar e compilar o driver de eco KMDF
- Instalar o exemplo do driver de eco no sistema de destino
- Usar o WinDbg para exibir informações sobre o driver
- Exibir informações de árvore de dispositivo Plug and Play
- Trabalhar com pontos de interrupção e código-fonte
- Exibir variáveis e pilhas de chamadas
- Exibir processos e threads
- IRQL, registra e encerra a sessão do WinDbg
- Recursos de depuração do Windows
Conectar-se a uma sessão WinDbg no modo kernel
Nesta seção, configure a depuração de rede no host e no sistema de destino.
Os computadores neste laboratório precisam ser configurados para usar uma conexão de rede Ethernet para depuração de kernel.
Este laboratório usa dois computadores. O depurador do Windows é executado no sistema host e o driver de eco KMDF (Kernel Mode Driver Framework) é executado no sistema de destino .
Use um hub de rede ou roteador e cabos de rede para conectar os dois computadores.
Para trabalhar com aplicativos no modo kernel e usar o WinDbg, recomendamos que você use a KDNET por meio do transporte 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 Preparando um computador para implantação manual de driver e Configurando a depuração de kernel de rede KDNET automaticamente.
Configurar a depuração do modo kernel usando a Ethernet
Para habilitar a depuração no modo kernel no sistema de destino:
No sistema host, abra uma janela do Prompt de Comando e insira ipconfig para determinar seu endereço IP.
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
ping
comando 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ê registrou 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
Habilite a depuração no modo kernel no sistema de destino concluindo as etapas a seguir.
Importante
Antes de usar 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. Habilite novamente esses recursos de segurança quando o teste for concluído. Gerencie adequadamente o computador de teste quando os recursos de segurança estiverem desabilitados.
No computador de destino, abra uma janela do Prompt de Comando como Administrador. Insira este comando para habilitar a depuração:
bcdedit /set {default} DEBUG YES
Insira este comando para habilitar a assinatura de teste:
bcdedit /set TESTSIGNING ON
Insira este comando para definir o endereço IP do sistema host. Use o endereço IP do sistema host que você registrou anteriormente, não o mostrado.
bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Aviso
Para aumentar a segurança da conexão e diminuir o risco das solicitações de conexão aleatórias do depurador de cliente, use uma chave aleatória gerada automaticamente. Para obter mais informações, consulte Configurando a depuração de kernel de rede KDNET automaticamente.
Insira este comando para confirmar se os valores de
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 WDK (Kit de Driver do Windows) que foi instalado como parte da instalação do kit do Windows. Altere para o diretório WinDbg padrão, o local padrão é mostrado abaixo.
cd C:\Program Files(x86)\Windows Kits\10\Debuggers\x64
Esse laboratório pressupõe que ambos os computadores executem uma versão de 64 bits do Windows no destino e no host. Se esse não for o caso, a melhor abordagem será executar a mesma bitness de ferramentas no host executado pelo destino. 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 comando a seguir. Os valores da chave e da porta correspondem aos valores definidos anteriormente usando BCDEdit no computador de destino.
WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Reinicie o sistema de destino.
Em um minuto ou dois, a saída de depuração deve ser exibida no sistema host.
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 janela principal de informações de depuração no WinDbg. Você pode inserir comandos do depurador e exibir a saída do comando nesta janela.
A janela 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 comando, use as teclas Seta para cima e Seta para baixo para rolar pelo histórico de comandos. Quando um comando é exibido, você pode editá-lo ou pressionar Enter para executar o comando.
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 (Linguagem de Marcação do Depurador) que você pode selecionar para coletar mais informações rapidamente.
No sistema host, use Ctrl+Scroll Lock no WinDBg para invadir o código em execução no sistema de destino. Pode levar algum tempo para o sistema de destino responder.
Insira o seguinte comando para habilitar o DML na janela 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
.hh
comando . Insira o seguinte comando para exibir a ajuda de referência de comando para.prefer_dml
:0: kd> .hh .prefer_dml
O arquivo de ajuda do depurador exibe a ajuda para o
.prefer_dml
comando .Para exibir informações detalhadas sobre a versão no sistema de destino, insira o comando vertarget (Mostrar Versão do Computador de Destino) 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, insira o comando lm (Listar Módulos Carregados) 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
(detalhada):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á nenhum caminho de símbolo definido e símbolos carregados, portanto, informações limitadas estão disponíveis no depurador.
Baixar e compilar o driver de eco KMDF
Nesta seção, baixe e compile o driver de eco KMDF.
Normalmente, você estaria trabalhando com seu próprio código de driver ao usar o WinDbg. Para se familiarizar com a operação WinDbg, este laboratório usa 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 você pode executar uma única etapa por meio do código nativo do modo kernel. Essa técnica pode ser valiosa para depurar problemas complexos de código no modo kernel.
Para baixar e criar o driver de áudio de exemplo echo:
Baixe e extraia o exemplo kmdf echo do GitHub.
Exiba o exemplo de eco no GitHub.
Leia sobre o exemplo.
Navegue por todos os exemplos de driver do Windows.
O exemplo de Eco KMDF está localizado na pasta geral .
Baixe os exemplos de driver em um arquivo zip: Exemplos de driver
Baixe o arquivo zip no 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 existente para armazenar os arquivos extraídos. Por exemplo, você pode especificar C:\DriverSamples\ como a nova pasta na 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. Em Gerenciador de Soluções, você pode ver uma solução que tem três projetos.
Defina a configuração e a plataforma do exemplo. Em Gerenciador de Soluções, selecione e segure ou clique com o botão direito do mouse em Solução 'kmdfecho' (3 projetos)e selecione Configuration Manager. Verifique se as definições de configuração e plataforma são as mesmas para os três projetos. Por padrão, a configuração é definida como Depuração do Win10 e 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.
Os exemplos de driver precisam ser modificados para usar valores que não se sobrepõem aos drivers existentes. Consulte Do Código de Exemplo ao Driver de Produção – O que alterar nos exemplos sobre como criar um exemplo de driver exclusivo que coexistirá com drivers reais existentes instalados no Windows.
Defina a biblioteca de runtime. Abra a página de propriedades do driver de eco e localize Geração de CódigoC/C++>. Altere a Biblioteca de Runtime para Depuração multi-threaded (/MTd). Para obter mais informações sobre as opções de build, consulte /MD, /MT, /LD (Use Run-Time Library).
Nas propriedades do driver, verifique se oModo de Assinatura de Driver> está definido como Sinal de Teste.
No Visual Studio, selecione Compilar>solução de build.
As janelas de build devem exibir uma mensagem indicando que o build para todos os três projetos foi bem-sucedido.
Dica
Se você encontrar uma mensagem de erro de build, use o número de erro de build para determinar uma correção. Por exemplo, o erro do MSBuild MSB8040 descreve como trabalhar com bibliotecas mitigadas pelo spectre.
Em Explorador de Arquivos, vá para a pasta que contém os arquivos extraídos para o exemplo. Por exemplo, vá para C:\DriverSamples\general\echo\kmdf, se essa for a pasta especificada anteriormente. Nessa pasta, o local dos arquivos de driver compilados varia dependendo das configurações e das configurações da 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 um build de depuração de 64 bits.
Vá para a pasta que contém os arquivos criados para o driver autossíncrono: C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.
A pasta deve conter estes arquivos:
Arquivo Descrição Echo.sys O arquivo de 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 estar localizado aqui: C:\DriverSamples\general\echo\kmdf\exe\x64\Debug.
Arquivo 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 compilados e o EchoApp de teste 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, use a ferramenta DevCon para instalar o driver de exemplo de eco.
O computador em que você instala o driver é chamado de computador de destino ou computador de teste. Normalmente, esse computador é separado do computador no qual você desenvolve e cria o pacote de driver. O computador em que você desenvolve e cria o driver é chamado de computador host.
O processo de mover o pacote de driver para o computador de destino e instalar o driver é chamado de implantação do driver.
Antes de implantar um driver assinado de teste, prepare o computador de destino habilitando 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, habilite os drivers assinados de teste:
Abra as Configurações do Windows.
Em 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. Em Windows 10, selecione Solucionar> problemas deconfigurações de inicialização deopções> avançadas e, em seguida, selecione Reiniciar.
Selecione Desabilitar imposição de assinatura do driver pressionando a tecla F7.
Reinicie o computador de destino.
No sistema host, vá para a pasta Ferramentas na instalação do WDK e localize a ferramenta DevCon. Por exemplo, examine a seguinte pasta: C:\Arquivos de Programas (x86)\Windows Kits\10\Tools\x64\devcon.exe.
Crie uma pasta no destino para o pacote de driver criado, por exemplo, C:\EchoDriver. Copie devcon.exe para o sistema de destino. Localize o certificado .cer no sistema host. Ele está na mesma pasta no computador host na pasta que contém os arquivos de driver criados. Copie todos os arquivos do driver criado descritos 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 Instalar e siga os prompts para instalar o certificado de teste.
Se você precisar de instruções mais detalhadas para configurar o computador de destino, consulte Preparando um computador para implantação manual do driver.
As instruções a seguir mostram como instalar e testar o driver de exemplo. Aqui está a sintaxe geral da ferramenta devcon que você usa para instalar o driver:
devcon install <INF file> <hardware ID>
O arquivo INF necessário para instalar esse driver é echo.inf. O arquivo inf contém a ID de hardware para instalar o echo.sys. Para o exemplo de eco, a ID de hardware é root\ECHO.
No computador de destino, abra uma janela do Prompt de Comando como Administrador. Vá para a pasta do pacote de driver e insira o seguinte comando:
devcon install echo.inf root\ECHO
Se você receber uma mensagem de erro sobre o desenvolvimento não ser reconhecido, tente adicionar o caminho à ferramenta de desenvolvimento . Por exemplo, se você copiou para uma pasta chamada C:\Tools, tente usar o seguinte comando:
c:\tools\devcon install echo.inf root\ECHO
Uma caixa de diálogo é exibida que indica que o driver de teste é um driver sem sinal. Selecione Instalar este driver de qualquer maneira para continuar.
Dica
Se você tiver problemas com a instalação, marcar o arquivo a seguir para obter mais informações. %windir%\inf\setupapi.dev.log
Depois de instalar o driver de exemplo com êxito, você estará pronto para testá-lo.
No computador de destino, em uma janela do Prompt de Comando, insira devmgmt para abrir Gerenciador de Dispositivos. Em Gerenciador de Dispositivos, no menu Exibir, escolha Dispositivos por tipo. Na árvore de dispositivos, localize o Driver de Eco WDF de exemplo no nó Dispositivo de Exemplo.
Insira 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
Usar o WinDbg para exibir informações sobre o driver
Nesta seção, defina o caminho do símbolo e use comandos de depurador de kernel para exibir informações sobre o driver de exemplo de eco KMDF.
Para exibir informações sobre o driver:
No sistema host, se você fechou o depurador, abra-o novamente usando o comando a seguir na janela do Prompt de Comando do administrador.
WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
Use Ctrl+Break (Bloqueio de Rolagem) para invadir 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
.symfix
comando .0: kd> .symfix
Para adicionar o local do símbolo local para usar 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
.reload
comando com a opção/f
force exclui todas as informações de símbolo do módulo especificado e recarrega os símbolos. Em alguns casos, esse 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 dependente 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.
Há 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 necessário. 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 do símbolo 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 de símbolo (arquivos.pdb ). 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 reais também devem ser acessíveis para o 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 exibir variáveis locais ou linhas de origem, defina as seguintes opções de build:
set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
Insira 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 esse laboratório foi definido
prefer_dml
anteriormente, alguns elementos da saída são links quentes que você 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*
O exemplo de eco não contém nenhum símbolo que comece 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
!lmi
extensão 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
!dh
extensão 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 ...
Insira 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
dd
comando 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 de árvore de dispositivo Plug and Play
Nesta seção, exiba informações sobre o driver de dispositivo de exemplo de eco e onde ele reside na árvore de dispositivos Plug and Play.
Informações sobre o driver de dispositivo na árvore de dispositivos Plug and Play podem ser úteis para solução de problemas. Por exemplo, se um driver de dispositivo não estiver residente na árvore do dispositivo, poderá haver um problema com a instalação do driver do dispositivo.
Para obter mais informações sobre a extensão de depuração do nó do dispositivo, consulte !devnode.
No sistema host, para ver todos os nós do dispositivo na árvore do dispositivo Plug and Play, insira o
!devnode 0 1
comando .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 na saída gerada para procurar o nome do driver do dispositivo, eco.
O driver do dispositivo de eco deve ser carregado. Use o
!devnode 0 1 echo
comando para exibir Plug and Play informações associadas ao driver do dispositivo de eco, 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 driver, neste exemplo, 0xffffe0007b71a960. Insira o
!devobj <PDO address>
comando para exibir Plug and Play informações associadas ao driver do dispositivo de eco. Use o endereço PDO exibido!devnode
no 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
!devnode 0 1
comando inclui o endereço PDO associado à instância em execução do driver, neste exemplo é 0xffffe0007b71a960. Insira o!devstack <PDO address>
comando para exibir Plug and Play informações associadas ao driver do dispositivo. Use o endereço PDO exibido!devnode
no 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 driver de dispositivo bastante simples. O driver de eco é um filho do nó PnPManager . PnPManager é um nó raiz.
\Driver\ECHO
\Driver\PnpManager
Este diagrama mostra uma árvore de nó de dispositivo mais complexa.
Para obter mais informações sobre pilhas de driver mais complexas, consulte Pilhas de driver 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 etapa única por meio do código-fonte do modo kernel.
Para poder percorrer o código e marcar os valores das variáveis em tempo real, habilite os pontos de interrupção e defina 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 desse ponto para depurar essa seção específica do código.
Para definir um ponto de interrupção usando um comando de depuração, use um dos comandos a seguir b
.
Comando | Descrição |
---|---|
bp |
Define um ponto de interrupção que está 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 habilita novamente quando o módulo é recarregado. |
bm |
Define um ponto de interrupção para um símbolo. Esse comando usa bu ou bp adequadamente e permite que curingas (* ) sejam usados para definir pontos de interrupção em todos os símbolos correspondentes, 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 do usuário do WinDbg para confirmar se oModo de Origem de Depuração> está habilitado na sessão atual do WinDbg.
Insira o seguinte comando para adicionar o local do código local ao caminho de origem:
.srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
Insira 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
x
comando para examinar os símbolos associados ao driver de eco para determinar o nome da função a ser usado para o ponto de interrupção. Você pode usar um curinga ou Ctrl+F para localizar o nome daDeviceAdd
função.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
DeviceAdd
método para o driver de eco éECHO!EchoEvtDeviceAdd
.Como alternativa, examine o código-fonte para localizar o nome da função para o ponto de interrupção.
Defina o ponto de interrupção com o
bm
comando usando o nome do driver, seguido pelo nome da função, por exemplo,AddDevice
, em que você deseja definir o ponto de interrupção, separado por um ponto de exclamação. Este laboratório usaAddDevice
para watch o driver que está sendo carregado.0: kd> bm ECHO!EchoEvtDeviceAdd 1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
Você pode usar uma 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 se o ponto de interrupção foi definido inserindo o
bl
comando :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 ser acionado.
Reinicie a execução de código no sistema de destino inserindo o
g
comando (go).No sistema de destino, no Windows, abra Gerenciador de Dispositivos usando o ícone ou inserindo mmc devmgmt.msc. Em Gerenciador de Dispositivos, expanda o nó Exemplos.
Selecione e segure ou clique com o botão direito do mouse na entrada do driver de eco KMDF e selecione Desabilitar no menu.
Selecione e segure ou clique com o botão direito do mouse na entrada do driver de eco KMDF novamente e selecione Habilitar no menu.
No sistema host, quando o driver está habilitado, o ponto de interrupção de depuração AddDevice deve ser acionado. A execução do código do driver no sistema de destino deve ser interrompida. Quando o ponto de interrupção é atingido, a execução deve ser interrompida no início da rotina AddDevice . A saída do comando de depuração exibe
Breakpoint 1 hit
.Percorra o código linha por linha inserindo o
p
comando ou pressionando F10 até chegar ao final a seguir da rotina AddDevice . O caractere Brace (}
) é realçado conforme 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 |
Listas pontos de interrupção. |
bc |
Limpa 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 desabilitar todos os pontos de interrupção. |
be |
Habilita um ponto de interrupção. Use be * para habilitar todos os pontos de interrupção. |
Como alternativa, você também pode modificar pontos de interrupção na interface do usuário do WinDbg.
Você também pode definir pontos de interrupção que são acionados quando um local de memória é acessado. Use o ba
comando (interromper no acesso), 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 |
write: quando a CPU grava no endereço |
Você só pode definir quatro pontos de interrupção de dados em um determinado momento. Cabe a você verificar se está alinhando seus dados corretamente para disparar o ponto de interrupção. As palavras devem terminar em endereços divisível por 2, dwords devem ser divisível por 4 e quad words 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.
- Interrompa (Ctrl+Break). Esse 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.
- Execute até o cursor (F7 ou Ctrl+F10). Coloque o cursor em uma janela de origem ou desmontagem em que você deseja que a execução seja interrompida e pressione F7. A execução de código é executada até esse ponto. Se o fluxo de execução de código não atingir o ponto indicado pelo cursor, o WinDbg não será interrompido. Essa situação poderá ocorrer 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 um bug marcar ocorrer.
- Passo a passo (F10). Esse comando faz com que a execução do código prossiga com uma instrução ou uma instrução por vez. Se uma chamada for encontrada, a execução do código passará pela chamada sem entrar na rotina chamada. Se a linguagem de programação for C ou C++ e WinDbg estiver no modo de origem, o modo de origem poderá ser ativado ou desativado usando oModo de Origemde Depuração>.
- Intervir (F11). Esse comando é como um passo a passo, exceto que a execução de uma chamada entra na rotina chamada.
- Sair (Shift+F11). Esse comando faz com que a execução seja executada e saia da rotina atual ou do local atual na pilha de chamadas. Esse comando é útil se você já viu o suficiente da rotina.
Para obter mais informações, consulte Depuração de código-fonte no WinDbg.
Exibir 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ê esteja parado na rotina AddDevice usando o processo descrito anteriormente. Para exibir a saída mostrada aqui, repita as etapas descritas anteriormente, se necessário.
No sistema host, para exibir variáveis, use o item de menulocalde> exibição para exibir variáveis locais.
Para localizar o local de um endereço de variável global, insira ? <variable name>
.
- Sair (Shift+F11) – esse 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 você esteja parado na rotina AddDevice usando o processo descrito anteriormente. Para exibir a saída mostrada aqui, repita as etapas descritas anteriormente, se necessário.
<- No sistema host
Exibir variáveis
Use o item de menulocalde exibição> para exibir variáveis locais.
Variáveis globais
Você pode encontrar o local de um endereço de 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 para um quadro específico, insira o dv
comando :
0: kd> dv
Driver = 0x00001fff`7ff9c838
DeviceInit = 0xffffd001`51978190
status = 0n0
A pilha de chamadas é a cadeia de chamadas de função que levaram ao local 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 k*
comandos .
Comando | Descrição |
---|---|
kb |
Exibe a pilha e os três primeiros parâmetros. |
kp |
Exibe as pilhas e a lista completa de parâmetros. |
kn |
Permite que você veja a pilha com as informações de quadro ao lado dela. |
No sistema host, se você quiser manter a pilha de chamadas disponível, selecione exibir>pilha de chamadas para exibi-la. Selecione as colunas na parte superior da janela para alternar a exibição de informações adicionais.
Use o
kn
comando para mostrar a pilha de chamadas ao depurar o código do adaptador de exemplo em um 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 Plug and Play código (PnP) que chamou o código da estrutura de driver (WDF) que mais tarde chamou a função de driver DeviceAdd
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 processo 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
dv
comando para examinar as variáveis de localidade associadas àEchoEvtIo
rotina: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
EchoEvtIo
rotinas 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
EchoApp.exe
driver no sistema de destino.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 é interrompida.
Breakpoint 2 hit ECHO!EchoEvtIoWrite: fffff801`0bf95810 4c89442418 mov qword ptr [rsp+18h],r8
Use o
!process
comando 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 threadechoapp.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 para 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 a echoapp.exe a ser usada 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.
_____________________________________________________(endereço do processo echoapp.exe)
Insira
g
conforme necessário no depurador para executar o código até queechoapp.exe termine de ser executado. Ele atinge o ponto de interrupção no evento de leitura e gravação muitas vezes. Quando echoapp.exe terminar, entre no depurador pressionando Ctrl+ScrLk (Ctrl+Break).Use o
!process
comando para confirmar que você está executando um processo diferente. Na saída mostrada aqui, o processo com o valor Imagem do Sistema é diferente do valor de Imagem de Eco .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
!process
comando para tentar examinar a ID do processo que havia sido associada a echoapp.exe que você registrou anteriormente. Forneça seu echoapp.exe endereço de processo 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, pois o processo deechoapp.exe não está mais em execução.
Threads
Os comandos para exibir 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 de driver 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 em execução, insira !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á examinando o thread associado ao aplicativo de teste.
Use o
!process
comando para determinar se esse thread é o único thread em execução no processo associado ao echoapp.exe. O número de thread do thread em execução no processo é o mesmo thread em execução que o!thread
comando 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
!process 0 0
comando para localizar o endereço do processo de dois processos relacionados e registrar 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 desse comando pode ser longa. A saída pode ser pesquisada usando Ctrl+F.Use o
!process
comando para listar informações de processo para ambos os processos que executam seu computador. Forneça o endereço do processo de sua!process 0 0
saída, não o endereço mostrado neste exemplo.Este exemplo de saída é para a ID do processocmd.exeque foi registrada anteriormente. O nome da imagem para essa 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 do processoechoapp.exeque 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
!Thread
comando 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 ...
Conforme esperado, o thread atual é o thread associado a echoapp.exe e está em um estado em execução.
Use o
!Thread
comando para exibir informações sobre o thread associado a cmd.exe processo. Forneça o endereço de 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] ...
Esse thread está associado a cmd.exe e está em estado de espera.
Forneça o endereço do thread de esperaCMD.exe para alterar o contexto para esse thread de espera.
0: kd> .Thread ffffe0007cf34880 Implicit thread is now ffffe000`7cf34880
Use o
k
comando para exibir a pilha de chamadas associada ao thread de 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 de pilha de chamadas, como, indicam
KiCommitThreadWait
que esse thread não está em execução conforme o esperado.
Para obter mais informações sobre threads e processos, consulte as seguintes referências:
IRQL, registra e encerra a sessão do WinDbg
Nesta seção, exiba o IRQL (nível de solicitação de interrupção) e o conteúdo dos registros.
Exibir o IRQL salvo
O IRQL é usado para gerenciar a prioridade de manutenção de interrupção. Cada processador tem uma configuração IRQL que os threads podem gerar ou reduzir. As interrupções que ocorrem em ou abaixo da configuração IRQL do processador são mascaradas e não interferem na operação atual. Interrupções que ocorrem acima da configuração IRQL do processador têm precedência sobre a operação atual.
No sistema host, a extensão !irql exibe o IRQL no processador atual do computador de destino antes da interrupção do depurador ocorrer. Quando o computador de destino entra no depurador, o IRQL é alterado, mas o IRQL que foi eficaz pouco antes da quebra do depurador ser salvo e exibido por !irql
.
0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)
Exibir os registros
No sistema host, exiba o conteúdo dos registros do thread atual no processador atual usando o comando r (Registros ).
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
Como alternativa, você pode exibir o conteúdo dos registros selecionando Exibir>Registros. Para obter mais informações, consulte r (Registros).
A exibição do conteúdo dos registros pode ser útil ao percorrer a execução do código do idioma do assembly e em outros cenários. Para obter mais informações sobre a desmontagem da linguagem do assembly, consulte Desmontagem anotada x86 e Desmontagem x64 anotada.
Para obter informações sobre o conteúdo do registro, consulte arquitetura x86 e arquitetura x64.
Encerrar a sessão do WinDbg
Se você quiser deixar o depurador anexado, mas quiser trabalhar no destino, desmarque todos os pontos de interrupção usando bc *
, para que o computador de destino não tente se conectar ao depurador do computador host. Em seguida, use o g
comando para permitir que o computador de destino seja executado novamente.
Para encerrar a sessão de depuração, no sistema host, interrompa o depurador e insira o qd
comando (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 na depuração do 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.
Manuais
- Depuração avançada do Windows por Mario Hewardt e Daniel Pravat
- 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 de Pavel Yosifovich, Alex Ionescu, Mark Russinovich e David Solomon
Vídeo
Fornecedores de treinamento
Confira também
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de