Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este laboratório fornece exercícios práticos que demonstram como depurar o driver de áudio do Sysvad no modo núcleo.
O Depurador do Microsoft Windows (WinDbg) é uma poderosa ferramenta de depuração baseada no Windows que você pode usar para executar a depuração do modo de usuário e do modo kernel. WinDbg fornece depuração no nível do código-fonte para o kernel do Windows, drivers no modo kernel e serviços do sistema, assim como aplicativos e drivers em modo de usuário.
O WinDbg pode percorrer o código-fonte, definir pontos de interrupção, exibir variáveis (incluindo objetos C++), rastreamentos de pilha e memória. A janela Comando do Depurador permite que o usuário emita uma ampla variedade de comandos.
Configuração do laboratório
Você precisará do seguinte hardware para poder concluir o laboratório:
- Um laptop ou computador desktop (host) executando o Windows 10
- Um laptop ou computador desktop (destino) executando o Windows 10
- Um hub de rede/roteador e cabos de rede para conectar os dois computadores
- Acesso à Internet para baixar arquivos de símbolo
Você precisará do software a seguir para poder concluir o laboratório.
- Microsoft Visual Studio 2017
- SDK (Software Development Kit) do Windows para Windows 10
- Windows Driver Kit (WDK) para Windows 10
- O driver de áudio Sysvad de exemplo para Windows 10
Para obter informações sobre como baixar e instalar o WDK, consulte Baixar o WDK (Windows Driver Kit).
Guia de depuração do Sysvad
Este laboratório orienta você pelo processo de depuração de um driver no modo kernel. Os exercícios usam o exemplo de driver de áudio virtual do Syvad. Como o driver de áudio do Syvad não interage com o hardware de áudio real, ele pode ser usado na maioria dos dispositivos. O laboratório aborda as seguintes tarefas:
- Seção 1: Conectar-se a uma sessão WinDbg no modo kernel
- Seção 2: comandos e técnicas de depuração no modo kernel
- Seção 3: Baixar e criar o driver de áudio do Sysvad
- Seção 4: Instalar o driver de áudio Sysvad no sistema de destino
- Seção 5: Usar o WinDbg para exibir informações sobre o driver
- Seção 6: Exibir informações da árvore de dispositivos Plug and Play
- Seção 7: Trabalhar com pontos de interrupção e código-fonte
- Seção 8: Examinar variáveis
- Seção 9: Exibir pilhas de chamadas
- Seção 10: Exibir processos e tarefas
- Seção 11: IRQL, registradores e desmontagem
- Seção 12: Trabalhar com memória
- Seção 13: Encerrando a sessão do WinDbg
- Seção 14: Recursos de depuração do Windows
Laboratório do driver Echo
O driver Echo é um driver mais simples do que o driver de áudio Sysvad. Se você não estiver familiarizado com o WinDbg, convém primeiro concluir os Drivers Universais de Depuração – Laboratório Passo a Passo (modo kernel Echo). Este laboratório reutiliza as instruções de instalação desse laboratório, portanto, se você concluiu esse laboratório, pode ignorar as seções 1 e 2 aqui.
Seção 1: Conectar-se a uma sessão WinDbg no modo kernel
Na Seção 1, você configurará a depuração de rede no host e no sistema de destino.
Os PCs neste laboratório precisam ser configurados para usar uma conexão de rede Ethernet para a depuração do kernel.
Este laboratório usa dois computadores. O WinDbg é executado no sistema host e o driver Sysvad é executado no sistema de destino .
Use um hub de rede/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 (Kernel-Mode). 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 do Kernel de Rede KDNET Automaticamente.
Configurar a depuração em modo kernel usando Ethernet
Para habilitar a depuração no modo kernel no sistema de destino, execute as etapas a seguir.
<- No sistema hospedeiro
- Abra um prompt de comando no sistema host e digite ipconfig /all para determinar seu endereço IP.
C:\>ipconfig /all
Windows IP Configuration
Host Name . . . . . . . . . . . . : TARGETPC
...
Ethernet adapter Ethernet:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b3
Autoconfiguration IPv4 Address. . : 169.182.1.1
Subnet Mask . . . . . . . . . . . : 255.255.0.0
Default Gateway . . . . . . . . . :
Registre o endereço IP do sistema de host: ______________________________________
Registre o nome do host do sistema: ______________________________________
-> No sistema de destino
- Abra um prompt de comando no sistema de destino e use o comando ping para confirmar a conectividade de rede entre os dois sistemas. Use o endereço IP real do sistema host que você registrou em vez de 169.182.1.1 mostrado na saída de exemplo.
C:\> ping 169.182.1.1
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
Para usar o utilitário KDNET para habilitar a depuração no modo kernel no sistema de destino, execute as etapas a seguir.
No sistema de host, localize o diretório KDNET do WDK. Por padrão, ele está localizado aqui.
C:\Arquivos de Programas (x86)\Kits do Windows\10\Depuradores\x64
Esse laboratório pressupõe que ambos os computadores estejam executando uma versão de 64 bits do Windows, tanto no alvo quanto no host. Se esse não for o caso, a melhor abordagem é executar a mesma arquitetura de ferramentas no host que o sistema-alvo está executando. Por exemplo, se o destino estiver executando o Windows de 32 bits, execute uma versão 32 do depurador no host. Para obter mais informações, consulte Escolhendo as ferramentas de depuração de 32 bits ou 64 bits.
Localize esses dois arquivos e copie-os para um compartilhamento de rede ou pen drive, para que eles estejam disponíveis no computador de destino.
kdnet.exe
VerifiedNICList.xml
No computador de destino, abra uma janela do prompt de comando como Administrador. Insira este comando para validar se há suporte para a NIC no computador de destino.
C:\KDNET>kdnet
Network debugging is supported on the following NICs:
busparams=0.25.0, Intel(R) 82579LM Gigabit Network Connection, KDNET is running on this NIC.kdnet.exe
- Digite este comando para definir o endereço IP do sistema host. Use o endereço IP real do sistema host que você registrou em vez de 169.182.1.1 mostrado na saída de exemplo. Escolha um endereço de porta exclusivo para cada par de destino/host com o qual você trabalha, como 50010.
C:\>kdnet 169.182.1.1 50010
Enabling network debugging on Intel(R) 82577LM Gigabit Network Connection.
Key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
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 e gerencie adequadamente o computador de teste, quando os recursos de segurança estiverem desabilitados. A inicialização segura normalmente está desabilitada na UEFI. Para acessar a configuração UEFI, use Sistema, Recuperação, Inicialização Avançada. Na reinicialização, selecione Solução de problemas, opções avançadas, configurações de firmware UEFI. Tenha cuidado, pois definir incorretamente as opções UEFI ou desabilitar o BitLocker pode tornar o sistema inoperável.
- Digite este comando para confirmar se as dbgsettings estão definidas corretamente.
C:\> bcdedit /dbgsettings
busparams 0.25.0
key 2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
debugtype NET
hostip 169.182.1.1
port 50010
dhcp Yes
The operation completed successfully.
Copie a chave exclusiva gerada automaticamente em um arquivo de texto para evitar ter que digitá-la no computador host. Copie o arquivo de texto com a chave para o sistema host.
Notafirewalls e depuradores
Se você receber uma mensagem pop-up do firewall e quiser usar o depurador, marque todas as três caixas.
<- No sistema hospedeiro
- No computador host, abra uma janela do Prompt de Comando como Administrador. Mude para o diretório WinDbg.exe. Usaremos a versão x64 de WinDbg.exe do Windows Driver Kit (WDK), que foi instalado como parte da instalação do kit do Windows.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
- Inicie o WinDbg com depuração remota de usuário usando o comando a seguir. O valor da chave e da porta corresponde ao que você definiu anteriormente usando BCDEdit no destino.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
-No sistema de destino>
Reinicialize o sistema de destino.
<-No sistema hospedeiro
Dentro de um minuto ou dois, a saída de depuração deverá ser exibida no sistema anfitrião.
A janela Comando do Depurador é a janela de informações de depuração primária no WinDbg. Você pode inserir comandos de depuração e ver a saída do comando nesta janela.
A janela de Comando do Depurador é dividida em dois painéis. Digite comandos no painel menor (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 de 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.
Seção 2: comandos e técnicas de depuração no modo kernel
Na Seção 2, você usará comandos de depuração para exibir informações sobre o sistema de destino.
<- No sistema hospedeiro
Habilitar DML (Linguagem de Marcação do Depurador) com .prefer_dml
Alguns comandos de depuração exibem texto usando a Linguagem de Marcação do Depurador que você pode selecionar para coletar rapidamente mais informações.
- Use Ctrl+Break (Bloqueio de Rolagem) no WinDBg para interromper o código em execução no sistema de destino. Pode levar um pouco de tempo para o sistema de destino responder.
- Digite o comando a seguir para habilitar o DML na janela Comando do Depurador.
0: kd> .prefer_dml 1
DML versions of commands on by default
Use .hh para obter ajuda
Você pode acessar a ajuda de comando de referência usando o comando .hh .
- Digite o comando a seguir para exibir a ajuda de referência de comando para .prefer_dml.
0: kd> .hh .prefer_dml
O arquivo de ajuda do Depurador exibirá a ajuda para o comando .prefer_dml.
Exibir a versão do Windows no sistema de destino
- Exiba informações detalhadas sobre a versão no sistema de destino digitando 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
Listar os módulos carregados
- Você pode verificar se está trabalhando com o processo de modo kernel correto exibindo os módulos carregados digitando o comando lm (List Loaded Modules) na janela WinDbg.
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
...
Nota A saída que foi omitida é indicada com "... " neste laboratório.
Como ainda não definimos o caminho do símbolo e os símbolos carregados, informações limitadas estão disponíveis no depurador.
Seção 3: Baixar e criar o driver de áudio do Sysvad
Na Seção 3, você baixará e criará o driver de áudio Sysvad.
Normalmente, você estaria trabalhando com seu próprio código de driver ao usar o WinDbg. Para se familiarizar com a depuração de drivers de áudio, o driver de exemplo de áudio virtual do Sysvad é usado. Este exemplo é usado para ilustrar como você pode executar o código do modo kernel nativo passo a passo. Essa técnica pode ser muito valiosa para depurar problemas complexos de código no modo kernel.
Para baixar e criar o driver de áudio de exemplo do Sysvad, execute as etapas a seguir.
Baixar e extrair o exemplo de áudio do Sysvad do GitHub
Você pode usar um navegador para exibir o exemplo do Sysvad e Readme.md arquivo aqui:
https://github.com/Microsoft/Windows-driver-samples/tree/main/audio/sysvad
Este laboratório mostra como baixar os exemplos universais de driver em um arquivo zip.
um. Baixe o arquivo de master.zip para o disco rígido local.
https://github.com/Microsoft/Windows-driver-samples/archive/master.zip
b. Selecione e segure (ou clique com o botão direito do mouse) Windows-driver-samples-master.zipe escolha Extrair Tudo. Especifique uma nova pasta ou navegue até uma existente que armazenará os arquivos extraídos. Por exemplo, você pode especificar C:\WDK_Samples\ como a nova pasta na qual os arquivos são extraídos.
c. Depois que os arquivos forem extraídos, navegue até a subpasta a seguir.
C:\WDK_Samples\Sysvad
Abrir a solução de driver no Visual Studio
No Visual Studio, selecione Arquivo>Abrir>Projeto/Solução... e navegue até a pasta que contém os arquivos extraídos (por exemplo, C:\WDK_Samples\Sysvad). Clique duas vezes no arquivo de solução Syvad .
No Visual Studio, localize o Gerenciador de Soluções. (Se isso ainda não estiver aberto, escolha o Gerenciador de Soluções no menu Exibir .) No Gerenciador de Soluções, você pode ver uma solução que tem vários projetos.
Definir a configuração e a plataforma do exemplo
No Gerenciador de Soluções, selecione e segure (ou clique com o botão direito do mouse) solução 'sysvad' (7 de 7 projetos) e escolha o Configuration Manager. Verifique se as configurações e as configurações da plataforma são as mesmas para os quatro projetos. Por padrão, a configuração é definida como "Win10 Debug" e a plataforma é definida como "Win64" para todos os projetos. Se você fizer alterações de configuração e/ou de plataforma para um projeto, deverá fazer as mesmas alterações para os três projetos restantes.
Nota Este laboratório pressupõe que o Windows de 64 bits está sendo usado. Se você estiver usando o Windows de 32 bits, crie o driver para 32 bits.
Verificar a assinatura do driver
Encontre o TabletAudioSample. Abra a página de propriedades do driver Sysvad e verifique se oModo de Assinatura do > está definido como Sinal de Teste.
Os exemplos de driver precisam ser modificados para usar valores que não conflitem com os drivers existentes. Consulte De Código de Exemplo para 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.
Compilar o exemplo usando o Visual Studio
No Visual Studio, selecione Criar>Criar Solução.
As janelas de build devem exibir uma mensagem indicando que o build para todos os seis 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 atenuadas pelo espectro.
Localizar os arquivos de driver compilados
No Explorador de Arquivos, navegue até a pasta que contém os arquivos extraídos para o exemplo. Por exemplo, você navegaria até C:\WDK_Samples\Sysvad, se essa for a pasta especificada anteriormente. Dentro dessa pasta, o local dos arquivos de driver compilados varia dependendo das configurações e das configurações da plataforma selecionadas no Configuration Manager. Por exemplo, se você deixou as configurações padrão inalteradas, os arquivos de driver compilados serão salvos em uma pasta chamada \x64\Depurar para um build de depuração de 64 bits.
Navegue até a pasta que contém os arquivos criados para o driver TabletAudioSample:
C:\WDK_Samples\Sysvad\TabletAudioSample\x64\Debug. A pasta conterá o tabletAudioSample .SYS driver, o arquivo pdp de símbolo e o arquivo inf. Você também precisará localizar os arquivos .dll e de símbolo DelayAPO, KWSApo e KeywordDetectorContosoAdapter.
Para instalar o driver, você precisará dos arquivos a seguir.
Nome do arquivo Descrição TabletAudioSample.sys O arquivo de driver. TabletAudioSample.pdb O arquivo de símbolo do driver. tabletaudiosample.inf Um arquivo INF (informações) que contém informações necessárias para instalar o driver. KeywordDetectorContosoAdapter.dll Um detector de palavras-chave de exemplo. KeywordDetectorContosoAdapter.pdb O arquivo de símbolos de exemplo do detector de palavras-chave. DelayAPO.dll Um exemplo de atraso APO. DelayAPO.pdb O arquivo de símbolo do APO de atraso. KWSApo.dll Um exemplo de detector de palavra-chave APO. KWSApo.pdb O arquivo de símbolo do detector de palavras-chave. TabletAudioSample.cer O arquivo de certificado TabletAudioSample. Localize uma pen drive USB ou configure um compartilhamento de rede para copiar os arquivos de driver compilados do host para o sistema de destino.
Na próxima seção, você copiará o código para o sistema de destino e instalará e testará o driver.
Seção 4: Instalar o exemplo de driver de áudio do Sysvad no sistema de destino
Na Seção 4, você usará o devcon para instalar o driver de áudio Sysvad.
-> No sistema de destino
O computador em que você instala o driver é chamado de computador de destino ou computador de teste. Normalmente, esse é um computador separado do computador no qual você desenvolve e cria o pacote de driver. O computador no qual 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, você deve preparar o computador de destino ativando a assinatura de teste. Depois disso, você estará pronto para executar o exemplo de driver compilado no sistema de destino.
Para instalar o driver no sistema de destino, execute as etapas a seguir.
Habilitar controladores assinados para teste
Para habilitar a capacidade de executar 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 Solucionar problemas.
Em seguida, selecione Opções avançadas, Configurações de Inicialização e, em seguida, selecione Reiniciar.
Selecione Desabilitar a imposição da assinatura do driver pressionando a tecla F7 .
O computador começará com os novos valores em vigor.
-> No sistema de destino
Instalar o driver
As instruções a seguir mostram como instalar e testar o driver de exemplo.
O arquivo INF necessário para instalar esse driver é TabletAudioSample.inf. No computador de destino, abra uma janela do prompt de comando como Administrador. Navegue até a pasta do pacote do driver, clique com o botão direito do mouse no arquivo TabletAudioSample.inf e selecione Instalar.
Uma caixa de diálogo será exibida indicando que o driver de teste é um driver não assinado. Selecione Instalar esse driver de qualquer maneira continuar.
Dica
Se você tiver problemas com a instalação, verifique o arquivo a seguir para obter mais informações.
%windir%\inf\setupapi.dev.logPara obter instruções mais detalhadas, consulte Configurar um computador para implantação, teste e depuração de driver.
O arquivo INF contém a ID de hardware para instalar o tabletaudiosample.sys. Para o exemplo do Syvad, a ID de hardware é:
root\sysvad_TabletAudioSampleExaminar o driver no Gerenciador de Dispositivos
No computador de destino, em uma janela do Prompt de Comando, insira devmgmt para abrir o Gerenciador de Dispositivos. No Gerenciador de Dispositivos, no menu Exibir, selecione Dispositivos por tipo.
Na árvore de dispositivos, localize Dispositivo de Áudio Virtual (WDM) – Exemplo de Tablet no nó de dispositivo de áudio. Isso normalmente está sob o nó Controladores de som, vídeo e jogos. Confirme se ele está instalado e ativo.
Realce o driver para o hardware atual no computador no Gerenciador de Dispositivos. Em seguida, selecione e segure (ou clique com o botão direito do mouse) no driver e selecione desabilitar para desabilitar o driver.
Confirme no Gerenciador de Dispositivos que o driver de hardware de áudio exibe a seta para baixo, indicando que ele está desabilitado.
Depois de instalar com êxito o driver de exemplo, agora você está pronto para testá-lo.
Testar o driver de áudio do Sysvad
No computador de destino, em uma janela do Prompt de Comando, insira devmgmt para abrir o Gerenciador de Dispositivos. No Gerenciador de Dispositivos, no menu Exibir, selecione Dispositivos por tipo. Na árvore do dispositivo, localize Dispositivo de Áudio Virtual (WDM) - Amostra de Tablet.
Abra o Painel de Controle e navegue até Hardware e Som>Gerenciar dispositivos de áudio. Na caixa de diálogo Som, selecione o ícone do alto-falante rotulado como WDM (Dispositivo de Áudio Virtual) – Exemplo de Tablet e selecione Definir Padrão, mas não selecione OK. Isso manterá a caixa de diálogo Som aberta.
Localize um MP3 ou outro arquivo de áudio no computador de destino e clique duas vezes para reproduzi-lo. Em seguida, na caixa de diálogo Som, verifique se há atividade no indicador de nível de volume associado ao Dispositivo de Áudio Virtual (WDM) - Driver de Exemplo de Tablet.
Seção 5: Usar o WinDbg para exibir informações sobre o driver
Na Seção 5, você definirá o caminho do símbolo e usará comandos de depurador de kernel para exibir informações sobre o driver de exemplo do Sysvad.
Os símbolos permitem que o WinDbg exiba informações adicionais, como nomes de variáveis, que podem ser inestimáveis durante a depuração. O WinDbg usa os formatos de símbolo de depuração do Microsoft Visual Studio para depuração no nível do código-fonte. Ele pode acessar qualquer símbolo ou variável de um módulo que tenha arquivos de símbolo PDB.
Para carregar o depurador, execute as etapas a seguir.
<-No sistema hospedeiro
Se você fechou o depurador, abra-o novamente usando o comando a seguir na janela do prompt de comando do administrador. Substitua a chave e a porta pelo que você configurou anteriormente.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874pUse Ctrl+Break (Bloqueio de Rolagem) para interromper o código em execução no sistema de destino.
Definir o caminho do símbolo
Para definir o caminho dos símbolos para o servidor de símbolos da Microsoft no ambiente WinDbg, use o comando .symfix .
0: kd> .symfixPara adicionar o caminho dos símbolos locais para que você possa utilizá-los, adicione o caminho usando .sympath+ e depois .reload /f.
0: kd> .sympath+ C:\WDK_Samples\Sysvad 0: kd> .reload /fNota O comando .reload 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 módulo em si.
Nota Você deve carregar os símbolos adequados para usar a funcionalidade avançada fornecida pelo WinDbg. Se você não tiver símbolos configurados corretamente, receberá mensagens indicando que os símbolos não estão disponíveis quando você tentar usar a funcionalidade que depende de símbolos.
0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.
ObservaçãoServidores de símbolos
Há várias 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 passo a passo pressupõe que essa abordagem será usada. Se os símbolos em seu ambiente estiverem em um local diferente, modifique as etapas para usar esse local. Para obter informações adicionais, consulte o caminho do símbolo para o depurador do Windows.
ObservaçãoEntenda os requisitos de símbolo do código-fonte
Para executar a depuração de origem, você deve criar uma versão checada (debug) de seus binários. O compilador criará arquivos de símbolo (arquivos .pdb). Esses arquivos de símbolo mostrarão ao depurador como as instruções binárias correspondem às linhas de origem. Os próprios arquivos de origem reais 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 exibir variáveis locais ou linhas de origem, defina as opções de build a seguir.
definir COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
Digite o seguinte na área de comando do depurador para exibir informações sobre o driver Sysvad.
0: kd> lm m tabletaudiosample v Browse full module list start end module name fffff801`14b40000 fffff801`14b86000 tabletaudiosample (private pdb symbols) C:\Debuggers\sym\TabletAudioSample.pdb\E992C4803EBE48C7B23DC1596495CE181\TabletAudioSample.pdb Loaded symbol image file: tabletaudiosample.sys Image path: \SystemRoot\system32\drivers\tabletaudiosample.sys Image name: tabletaudiosample.sys Browse all global symbols functions data Timestamp: Thu Dec 10 12:20:26 2015 (5669DE8A) CheckSum: 0004891E ...Para obter mais informações, consulte lm.
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.
Como o DML está habilitado, alguns elementos da saída são links interativos que você pode selecionar. Selecione o link de dados 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 /f tabletaudiosample!a* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z fffff806`9adb1000 tabletaudiosample!AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)Para obter informações, consulte x (Examinar símbolos).
A extensão !lmi exibe informações detalhadas sobre um módulo. Digite !lmi tabletaudiosample. Seu resultado deve ser semelhante ao texto mostrado abaixo.
0: kd> !lmi tabletaudiosample Loaded Module Info: [tabletaudiosample] Module: tabletaudiosample Base Address: fffff8069ad90000 Image Name: tabletaudiosample.sys Machine Type: 34404 (X64) Time Stamp: 58ebe848 Mon Apr 10 13:17:12 2017 Size: 48000 CheckSum: 42df7 Characteristics: 22 Debug Data Dirs: Type Size VA Pointer CODEVIEW a7, e5f4, d1f4 RSDS - GUID: {5395F0C5-AE50-4C56-AD31-DD5473BD318F} Age: 1, Pdb: C:\Windows-driver-samples-master\audio\sysvad\TabletAudioSample\x64\Debug\TabletAudioSample.pdb ?? 250, e69c, d29c [Data not mapped] Image Type: MEMORY - Image read successfully from loaded memory. Symbol Type: PDB - Symbols loaded successfully from image header. C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb Compiler: Resource - front end [0.0 bld 0] - back end [14.0 bld 24210] Load Report: private symbols & lines, not source indexed C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdbUse a extensão !dh para exibir informações de cabeçalho, conforme mostrado abaixo.
0: kd> !dh tabletaudiosample File Type: EXECUTABLE IMAGE FILE HEADER VALUES 8664 machine (X64) 9 number of sections 5669DE8A time date stamp Thu Dec 10 12:20:26 2015 0 file pointer to symbol table 0 number of symbols F0 size of optional header 22 characteristics Executable App can handle >2gb addresses ...
Seção 6: Exibindo informações da árvore de dispositivos Plug and Play
Na Seção 6, você exibirá informações sobre o driver de dispositivo de exemplo do Sysvad e onde ele reside na árvore de dispositivos Plug and Play.
Informações sobre o driver do 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 hospedeiro
Para ver todos os nós do dispositivo na árvore de dispositivos Plug and Play, insira o comando !devnode 0 1. Esse comando pode levar um ou dois minutos para ser executado. Durante esse tempo, "*Ocupado" será exibido na área de status do WinDbg.
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, sysvad.
Haverá uma entrada de nó de dispositivo com um nome
sysvad_TabletAudioSamplepresente na saída !devnode para Syvad.DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0 InstancePath is "ROOT\sysvad_TabletAudioSample\0000" ServiceName is "sysvad_tabletaudiosample" State = DeviceNodeStarted (0x308) ...Observe que o endereço PDO e o endereço DevNode são exibidos.
Use o
!devnode 0 1 sysvad_TabletAudioSamplecomando para exibir informações de Plug and Play associadas ao driver de dispositivo Sysvad.0: kd> !devnode 0 1 sysvad_TabletAudioSample Dumping IopRootDeviceNode (= 0xffffe00082df8d30) DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0 InstancePath is "ROOT\sysvad_TabletAudioSample\0000" ServiceName is "sysvad_tabletaudiosample" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeEnumerateCompletion (0x30d) DevNode 0xffffe000897fb650 for PDO 0xffffe00089927e30 InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{64097438-cdc0-4007-a19e-62e789062e20}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00086d2f5f0 for PDO 0xffffe00089939ae0 InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{78880f4e-9571-44a4-a9df-960bde446487}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00089759bb0 for PDO 0xffffe000875aa060 InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{7cad07f2-d0a0-4b9b-8100-8dc735e9c447}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00087735010 for PDO 0xffffe000872068c0 InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{fc38551b-e69f-4b86-9661-ae6da78bc3c6}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00088457670 for PDO 0xffffe0008562b830 InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{0894b831-c9fe-4c56-86a6-092380fc5628}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe000893dbb70 for PDO 0xffffe00089d68060 InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{15eb6b5c-aa54-47b8-959a-0cff2c1500db}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe00088e6f250 for PDO 0xffffe00089f6e990 InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{778c07f0-af9f-43f2-8b8d-490024f87239}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307) DevNode 0xffffe000862eb4b0 for PDO 0xffffe000884443a0 InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{e4b72c7c-be50-45df-94f5-0f2922b85983}" State = DeviceNodeStarted (0x308) Previous State = DeviceNodeStartPostWork (0x307)A saída exibida no comando anterior inclui o PDO associado à instância em execução do nosso driver, neste exemplo é 0xffffe00089c575a0. Insira o comando !devobj<endereço PDO> para exibir informações de Plug and Play associadas ao driver de dispositivo Sysvad. Use o endereço PDO que o !devnode exibe no computador, não o mostrado aqui.
0: kd> !devobj 0xffffe00089c575a0 Device object (ffffe00089c575a0) is for: 0000004e \Driver\PnpManager DriverObject ffffe00082d47e60 Current Irp 00000000 RefCount 65 Type 0000001d Flags 00001040 SecurityDescriptor ffffc102b0f6d171 DevExt 00000000 DevObjExt ffffe00089c576f0 DevNode ffffe00086e68190 ExtensionFlags (0000000000) Characteristics (0x00000180) FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN AttachedDevice (Upper) ffffe00088386a50 \Driver\sysvad_tabletaudiosample Device queue is not busy.A saída exibida no comando !devobj inclui o nome do dispositivo anexado: \Driver\sysvad_tabletaudiosample. Use o comando !drvobj com uma máscara de bits de 2 para exibir informações associadas ao dispositivo anexado.
0: kd> !drvobj \Driver\sysvad_tabletaudiosample 2 Driver object (ffffe0008834f670) is for: \Driver\sysvad_tabletaudiosample DriverEntry: fffff80114b45310 tabletaudiosample!FxDriverEntry DriverStartIo: 00000000 DriverUnload: fffff80114b5fea0 tabletaudiosample!DriverUnload AddDevice: fffff80114b5f000 tabletaudiosample!AddDevice Dispatch routines: [00] IRP_MJ_CREATE fffff80117b49a20 portcls!DispatchCreate [01] IRP_MJ_CREATE_NAMED_PIPE fffff8015a949a00 nt!IopInvalidDeviceRequest [02] IRP_MJ_CLOSE fffff80115e26f90 ks!DispatchCleanup [03] IRP_MJ_READ fffff80115e32710 ks!DispatchRead [04] IRP_MJ_WRITE fffff80115e327e0 ks!DispatchWrite [05] IRP_MJ_QUERY_INFORMATION fffff8015a949a00 nt!IopInvalidDeviceRequest [06] IRP_MJ_SET_INFORMATION fffff8015a949a00 nt!IopInvalidDeviceRequest [07] IRP_MJ_QUERY_EA fffff8015a949a00 nt!IopInvalidDeviceRequest [08] IRP_MJ_SET_EA fffff8015a949a00 nt!IopInvalidDeviceRequest [09] IRP_MJ_FLUSH_BUFFERS fffff80115e32640 ks!DispatchFlush [0a] IRP_MJ_QUERY_VOLUME_INFORMATION fffff8015a949a00 nt!IopInvalidDeviceRequest [0b] IRP_MJ_SET_VOLUME_INFORMATION fffff8015a949a00 nt!IopInvalidDeviceRequest [0c] IRP_MJ_DIRECTORY_CONTROL fffff8015a949a00 nt!IopInvalidDeviceRequest [0d] IRP_MJ_FILE_SYSTEM_CONTROL fffff8015a949a00 nt!IopInvalidDeviceRequest [0e] IRP_MJ_DEVICE_CONTROL fffff80115e27480 ks!DispatchDeviceIoControl [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL fffff8015a949a00 nt!IopInvalidDeviceRequest [10] IRP_MJ_SHUTDOWN fffff8015a949a00 nt!IopInvalidDeviceRequest [11] IRP_MJ_LOCK_CONTROL fffff8015a949a00 nt!IopInvalidDeviceRequest [12] IRP_MJ_CLEANUP fffff8015a949a00 nt!IopInvalidDeviceRequest [13] IRP_MJ_CREATE_MAILSLOT fffff8015a949a00 nt!IopInvalidDeviceRequest [14] IRP_MJ_QUERY_SECURITY fffff80115e326a0 ks!DispatchQuerySecurity [15] IRP_MJ_SET_SECURITY fffff80115e32770 ks!DispatchSetSecurity [16] IRP_MJ_POWER fffff80117b3dce0 portcls!DispatchPower [17] IRP_MJ_SYSTEM_CONTROL fffff80117b13d30 portcls!PcWmiSystemControl [18] IRP_MJ_DEVICE_CHANGE fffff8015a949a00 nt!IopInvalidDeviceRequest [19] IRP_MJ_QUERY_QUOTA fffff8015a949a00 nt!IopInvalidDeviceRequest [1a] IRP_MJ_SET_QUOTA fffff8015a949a00 nt!IopInvalidDeviceRequest [1b] IRP_MJ_PNP fffff80114b5f7d0 tabletaudiosample!PnpHandlerInsira o comando !devstack<endereço PDO> para exibir informações de Plug and Play associadas ao driver do dispositivo. A saída exibida no comando !devnode 0 1 inclui o endereço PDO associado à instância em execução do nosso driver. Neste exemplo, é 0xffffe00089c575a0. Use o endereço PDO que o !devnode exibe no computador, não o mostrado abaixo.
0: kd> !devstack 0xffffe00089c575a0 !DevObj !DrvObj !DevExt ObjectName ffffe00088d212e0 \Driver\ksthunk ffffe00088d21430 0000007b ffffe00088386a50 \Driver\sysvad_tabletaudiosampleffffe00088386ba0 0000007a > ffffe00089c575a0 \Driver\PnpManager 00000000 0000004e !DevNode ffffe00086e68190 : DeviceInst is "ROOT\sysvad_TabletAudioSample\0000" ServiceName is "sysvad_tabletaudiosample"
A saída mostra que temos uma pilha de drivers de dispositivo relativamente simples. O driver sysvad_TabletAudioSample é um filho do nó PnPManager. O PnPManager é um nó raiz.
Este diagrama mostra uma árvore de nós de dispositivos mais complexa.
Nota Para obter mais informações sobre estruturas de driver mais complexas, consulte Estruturas de driver e Nós de dispositivo e estruturas de dispositivos.
Seção 7: Trabalhando com pontos de interrupção
Na Seção 7, você trabalhará com pontos de interrupção para interromper a execução de código em pontos específicos.
Configurando pontos de interrupção usando comandos
Pontos de interrupção são usados para interromper a execução de código em uma determinada linha de código. Em seguida, você pode avançar no código a partir 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 seguintes comandos b .
Bp |
Define um ponto de interrupção que estará ativo até que o módulo em que ele esteja 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 permitirá escolher bu ou bp apropriadamente e usará curingas * para definir pontos de interrupção em todos os símbolos que correspondem (como todos os métodos em uma classe). |
Use a interface do usuário do WinDbg para confirmar se o Modo de Depuração>Modo de Origem está habilitado na sessão atual do WinDbg.
Adicione a localização do seu código local ao caminho de origem digitando o seguinte comando.
.sympath+ C:\WDK_Samples\SysvadAdicione o local do símbolo local ao caminho do símbolo digitando o comando a seguir.
.sympath+ C:\WDK_Samples\SysvadDefinir a máscara de depuração
Como você está trabalhando com um driver, pode ser útil ver todas as mensagens que ele pode exibir. 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 0xFFFFFFFFDefina o ponto de interrupção com o comando bm usando o nome do driver, seguido pelo nome da função (AddDevice) em que você deseja definir o ponto de interrupção, separado por um ponto de exclamação.
0: kd> bm tabletaudiosample!AddDevice breakpoint 1 redefined 1: fffff801`14b5f000 @!"tabletaudiosample!AddDevice"Você pode usar diferentes sintaxes em conjunto com a configuração de variáveis como <módulo>!<símbolo>, <classe>::<método>,'<arquivo.cpp>:<número da linha>', ou pular algumas vezes <condição><#>. Para obter mais informações, consulte Como usar pontos de interrupção.
Liste os pontos de interrupção atuais para confirmar se o ponto de interrupção foi definido digitando o comando bl .
0: kd> bl 1 e fffff801`14b5f000 0001 (0001) tabletaudiosample!AddDeviceReinicie a execução de código no sistema de destino digitando o comando go g.
-No sistema de destino>
No Windows, abra o Gerenciador de Dispositivos usando o ícone ou inserindo mmc devmgmt.msc. No Gerenciador de Dispositivos, expanda o nó controladores de som, vídeo e jogos. Selecione e segure (ou clique com o botão direito do mouse) na entrada do driver de áudio virtual e selecione Desabilitar no menu.
Selecione e segure (ou clique com o botão direito do mouse) na entrada do driver de áudio virtual novamente e selecione Habilitar no menu.
<- No sistema hospedeiro
Isso deve fazer com que o Windows recarregue o driver, que chama AddDevice. Isso fará com que o ponto de interrupção de depuração do AddDevice seja acionado e a execução do código de driver no sistema de destino deve ser interrompida.
Breakpoint 1 hit tabletaudiosample!AddDevice: fffff801`14baf000 4889542410 mov qword ptr [rsp+10h],rdxSe o caminho de origem estiver definido corretamente, você deverá parar na rotina AddDevice no adapter.cpp
{ PAGED_CODE(); NTSTATUS ntStatus; ULONG maxObjects; DPF(D_TERSE, ("[AddDevice]")); maxObjects = g_MaxMiniports; #ifdef SYSVAD_BTH_BYPASS // // Allow three (3) Bluetooth hands-free profile devices. // maxObjects += g_MaxBthHfpMiniports * 3; #endif // SYSVAD_BTH_BYPASS // Tell the class driver to add the device. // ntStatus = PcAddAdapterDevice ( DriverObject, PhysicalDeviceObject, PCPFNSTARTDEVICE(StartDevice), maxObjects, 0 ); return ntStatus; } // AddDevicePasso linha a linha pelo código digitando o comando p ou pressionando F10. Você pode passar do código sysvad AddDevice para PpvUtilCall, PnpCallAddDevice e, em seguida, para o código do Windows PipCallDriverAddDevice. Você pode fornecer um número para o comando p para avançar várias linhas, por exemplo , p 5.
Quando terminar de percorrer o código, use o comando go g para reiniciar a execução no sistema de destino.
Definindo pontos de interrupção de acesso à memória
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 sintaxe a seguir.
ba <access> <size> <address> {options}
| Opção | Descrição |
|---|---|
e |
execute (quando a CPU busca uma instrução a partir 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) |
Observe que você só pode definir quatro pontos de interrupção de dados a qualquer momento e cabe a você ter certeza de que está alinhando seus dados corretamente ou não disparará o ponto de interrupção (as palavras devem terminar em endereços divisível por 2, as palavras d devem ser divisível por 4 e quadwords 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, use um comando como este.
ba r 4 fffff800`7bc9eff0
Modificando o estado do ponto de interrupção
Você pode modificar pontos de interrupção existentes usando os comandos a seguir.
Bl |
Lista pontos de interrupção. |
a.C |
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. |
ser |
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 selecionando editar>. Observe que a caixa de diálogo de ponto de interrupção funciona apenas com pontos de interrupção já existentes. Novos pontos de interrupção devem ser definidos na linha de comando.
Definir um ponto de interrupção no MixerVolume
Partes diferentes do código do driver de áudio são chamadas para responder a vários eventos, depois que o driver do dispositivo é carregado. Na próxima seção, definimos um ponto de interrupção que será acionado quando o usuário ajustar o controle de volume para o driver de áudio virtual.
Para definir um ponto de interrupção no MixerVolume, execute as etapas a seguir.
<- No sistema hospedeiro
Para localizar o método que altera o volume, use o comando x para listar os símbolos em CAdapterCommon, que contêm o volume da cadeia de caracteres.
kd> x tabletaudiosample!CAdapterCommon::* ... fffff800`7bce26a0 tabletaudiosample!CAdapterCommon::MixerVolumeWrite (unsigned long, unsigned long, long) …Use CTRL+F para pesquisar para cima na saída para volume e localizar o método MixerVolumeWrite.
Desmarque os pontos de interrupção anteriores usando bc *.
Defina um ponto de interrupção de símbolo na rotina CAdapterCommon::MixerVolumeWrite usando o comando a seguir.
kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite 1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"Liste os pontos de interrupção para confirmar se o ponto de interrupção está definido corretamente.
kd> bl 1 e fffff801`177b26a0 [c:\WDK_Samples\audio\sysvad\common.cpp @ 1668] 0001 (0001) tabletaudiosample!CAdapterCommon::MixerVolumeWriteReinicie a execução de código no sistema de destino digitando o comando go g.
No Painel de Controle, selecione as opções Hardware e Som>Som. Selecione e segure (ou clique com o botão direito do mouse) Amostra de Descrição do Coletor e selecione Propriedades. Selecione a guia Níveis . Ajuste o volume do controle deslizante.
Isso deve acionar o ponto de interrupção de depuração SetMixerVolume e interromper a execução do código do driver no sistema de destino.
kd> g Breakpoint 1 hit tabletaudiosample!CAdapterCommon::MixerVolumeWrite: fffff801`177b26a0 44894c2420 mov dword ptr [rsp+20h],r9dVocê deve parar nessa linha em common.cpp
{ if (m_pHW) { m_pHW->SetMixerVolume(Index, Channel, Value); } } // MixerVolumeWriteUse o comando dv para exibir as variáveis atuais e seus valores. Mais informações sobre variáveis são fornecidas na próxima seção deste laboratório.
2: kd> dv this = 0x00000000`00000010 ulNode = 0x344 ulChannel = 0x210a45f8 lVolume = 0n24Pressione a tecla F10 para executar o código passo a passo.
Pressione F5 para concluir a execução do código MixerVolumeWrite.
Resumo – Passo a passo pelo código da janela Comando do Depurador
Veja a seguir os comandos que você pode usar para percorrer seu código (com os atalhos de teclado associados mostrados entre parênteses).
Interrompa (Ctrl+Break) – esse comando interromperá um sistema enquanto o sistema estiver em execução e estiver em comunicação com o WinDbg (a sequência no Depurador kernel é Ctrl+C).
Avançar (F10) – Esse comando faz a execução do código prosseguir uma declaração ou uma instrução por vez. Se uma chamada for encontrada, a execução do código ignorará a chamada sem entrar na rotina a ser 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 Depuração>Modo de origem).
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 continue até sair da rotina atual (posição atual na pilha de chamadas). Isso é útil se você já viu o suficiente da rotina.
Executar para 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 do código será executada até esse ponto. Observe que, se o fluxo de execução de código não atingir o ponto indicado pelo cursor (por exemplo, uma instrução IF não for executada), o WinDbg não será interrompido, pois a execução do código não atingiu o ponto indicado.
Executar (F5) – Executar até que um ponto de interrupção seja encontrado ou um evento como uma verificação de bug ocorra.
Opções avançadas
Defina a instrução para a linha atual (Ctrl+Shift+I) – em uma janela de origem, você pode colocar o cursor em uma linha, inserir esse atalho de teclado e a execução de código começará a partir desse ponto assim que você deixá-lo continuar (por exemplo, usando F5 ou F10). Isso é útil se você quiser repetir uma sequência, mas isso requer algum cuidado. Por exemplo, registros e variáveis não são definidos como seriam se a execução de código tivesse atingido essa linha naturalmente.
Configuração direta do registro de eip – Você pode colocar um valor no registro de eip e assim que pressionar F5 (ou F10, F11 etc.), a execução começa a partir desse endereço. Isso é semelhante a definir uma instrução para a linha atual designada pelo cursor, exceto que você especifica o endereço de uma instrução de assembly.
Pode ser mais fácil percorrer a interface do usuário em vez da linha de comando, portanto, recomenda-se esse método. Se necessário, os seguintes comandos podem ser usados para percorrer um arquivo de origem na linha de comando:
.lines – Habilitar informações das linhas de origem.
bp main - Defina o ponto de interrupção inicial no início do módulo.
l+t – A etapa será feita pela linha de origem.
Selecione Depuração>Modo de Origem para entrar no modo de origem; o
L+tcomando não é suficiente.l+s – As linhas de origem serão exibidas no prompt.
g – Execute o programa até que "main" seja inserido.
p – Executar uma linha de código-fonte.
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.
Definir pontos de interrupção no código
Você pode definir um ponto de interrupção no código adicionando a DebugBreak() instrução e recriando o projeto e reinstalando o driver. Esse ponto de interrupção será acionado sempre que o driver estiver habilitado, portanto, seria uma técnica a ser usada nos estágios iniciais de desenvolvimento, não no código de produção. Essa técnica não é tão flexível quanto definir dinamicamente pontos de interrupção usando os comandos de ponto de interrupção.
Dica: talvez você queira manter uma cópia do driver Sysvad sem o ponto de interrupção adicionado para mais trabalhos de laboratório.
Defina uma interrupção para ocorrer sempre que o método AddDevice for executado adicionando a
DebugBreak()instrução ao código de exemplo.... // Insert the DebugBreak() statment before the PcAddAdapterDevice is called. // DebugBreak() // Tell the class driver to add the device. // ntStatus = PcAddAdapterDevice ( DriverObject, PhysicalDeviceObject, PCPFNSTARTDEVICE(StartDevice), maxObjects, 0 ); return ntStatus; } // AddDeviceSiga todas as etapas descritas anteriormente para recriar o driver no Microsoft Visual Studio e reinstalá-lo no computador de destino. Certifique-se de desinstalar o driver existente antes de instalar o driver atualizado.
Limpe os pontos de interrupção anteriores e confirme se o depurador está anexado ao computador de destino.
Quando o código for executado e atingir a instrução
DebugBreak, a execução será interrompida e uma mensagem será exibida.KERNELBASE!DebugBreak: 77b3b770 defe __debugbreak
Seção 8: Exibir variáveis
Na Seção 8, você usará comandos de depurador para exibir variáveis.
Pode ser útil examinar variáveis conforme o código é executado para confirmar se o código está funcionando conforme o esperado. Esse laboratório examina variáveis à medida que o driver de áudio produz som.
Use o comando dv para examinar as variáveis de local associadas a tabletaudiosample!CMiniportWaveRT::New*.
kd> dv tabletaudiosample!CMiniportWaveRT::New*Limpar os pontos de interrupção anteriores
bc *Defina um ponto de interrupção de símbolo nas rotinas CMiniportWaveCyclicStreamMSVAD usando o comando a seguir.
0: kd> bm tabletaudiosample!CMiniportWaveRT::NewStream 1: fffff801`177dffc0 @!"tabletaudiosample!CMiniportWaveRT::NewStream"Reinicie a execução de código no sistema de destino digitando o comando go g.
-> No sistema de destino
Localize um pequeno arquivo de mídia (como o arquivo de som de notificação do Windows com uma extensão de arquivo .wav) e selecione o arquivo para reproduzi-lo. Por exemplo, você pode usar Ring05.wav localizado no diretório Windows\Media.
<- No sistema hospedeiro
Quando o arquivo de mídia é reproduzido, o ponto de interrupção deve ser acionado e a execução do código de driver no sistema de destino deve ser interrompida.
Breakpoint 1 hit tabletaudiosample!CMiniportWaveRT::NewStream: fffff801`177dffc0 44894c2420 mov dword ptr [rsp+20h],r9dA janela do código-fonte deve realçar a chave na entrada da função NewStream.
/*++ Routine Description: The NewStream function creates a new instance of a logical stream associated with a specified physical channel. Callers of NewStream should run at IRQL PASSIVE_LEVEL. Arguments: OutStream - OuterUnknown - Pin - Capture - DataFormat - Return Value: NT status code. --*/ { ...Variáveis locais
Você pode exibir os nomes e valores de todas as variáveis locais para um determinado quadro digitando o comando dv .
0: kd> dv this = 0xffffe000`4436f8e0 OutStream = 0xffffe000`49d2f130 OuterUnknown = 0xffffe000`4436fa30 Pin = 0 Capture = 0x01 ' DataFormat = 0xffffe000`44227790 signalProcessingMode = {487E9220-E000-FFFF-30F1-D24900E0FFFF} ntStatus = 0n1055 stream = 0x00000000`00000200Usar DML para exibir variáveis
Para usar DML para explorar variáveis, selecione os elementos sublinhados. A ação 'select' cria um comando dx (Exibir Expressão NatVis) que permite fazer drill down (analisar em profundidade) em estruturas de dados aninhadas.
0: kd> dx -r1 (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) : [Type: CMiniportWaveRT] [+0x020] m_lRefCount : 0 [+0x028] m_pUnknownOuter : 0xffffe001d1477e50 : [Type: IUnknown *] [+0x030] m_ulLoopbackAllocated : 0x2050 [+0x034] m_ulSystemAllocated : 0x180 [+0x038] m_ulOffloadAllocated : 0x0 [+0x03c] m_dwCaptureAllocatedModes : 0x0 0: kd> dx -r1 (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : {487E9220-E000-FFFF-30F1-D24900E0FFFF} [Type: _GUID] [<Raw View>] 0: kd> dx -r1 -n (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : [Type: _GUID] [+0x000] Data1 : 0x487e9220 [+0x004] Data2 : 0xe000 [+0x006] Data3 : 0xffff [+0x008] Data4 : [Type: unsigned char [8]] 0: kd> dx -r1 -n (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) : [Type: unsigned char [8]] [0] : 0x30 [1] : 0xf1 [2] : 0xd2 [3] : 0x49 [4] : 0x0 [5] : 0xe0 [6] : 0xff [7] : 0xffVariáveis globais
Você pode encontrar o local de memória de uma variável global digitando? <nome> da variável.
0: kd> ? signalProcessingMode Evaluate expression: -52768896396472 = ffffd001`c8acd348Isso retorna o local de memória da variável, nesse caso ffffd001'c8acd348. Você pode exibir o conteúdo do endereço de memória despejando o valor desse endereço ao digitar o comando dd, usando o endereço de memória retornado pelo comando anterior.
0: kd> dd ffffd001`c8acd348 ffffd001`c8acd348 487e9220 ffffe000 49d2f130 ffffe000 ffffd001`c8acd358 4837c468 ffffe000 18221570 ffffc000 ffffd001`c8acd368 4436f8e0 ffffe000 487e9220 ffffe000 ffffd001`c8acd378 18ab145b fffff801 4837c420 ffffe000 ffffd001`c8acd388 4436f8e0 ffffe000 49d2f130 ffffe000 ffffd001`c8acd398 4436fa30 ffffe000 00000000 00000000 ffffd001`c8acd3a8 00000001 00000000 44227790 ffffe000 ffffd001`c8acd3b8 18adc7f9 fffff801 495972a0 ffffe000Você também pode usar nomes de variáveis com o comando dd .
0: kd> dd signalProcessingMode ffffd001`c8acd348 487e9220 ffffe000 49d2f130 ffffe000 ffffd001`c8acd358 4837c468 ffffe000 18221570 ffffc000 ffffd001`c8acd368 4436f8e0 ffffe000 487e9220 ffffe000 ffffd001`c8acd378 18ab145b fffff801 4837c420 ffffe000 ffffd001`c8acd388 4436f8e0 ffffe000 49d2f130 ffffe000 ffffd001`c8acd398 4436fa30 ffffe000 00000000 00000000 ffffd001`c8acd3a8 00000001 00000000 44227790 ffffe000 ffffd001`c8acd3b8 18adc7f9 fffff801 495972a0 ffffe000Exibir variáveis
Use o item de menu Exibir>Locais para exibir variáveis locais. Essa interface também fornece essa capacidade de detalhar estruturas de dados mais complexas.
Use p ou F10 para avançar aproximadamente 10 linhas no código até destacar a linha de código ntStatus = IsFormatSupported(Pin, Capture, DataFormat);.
PAGED_CODE(); ASSERT(OutStream); ASSERT(DataFormat); DPF_ENTER(("[CMiniportWaveRT::NewStream]")); NTSTATUS ntStatus = STATUS_SUCCESS; PCMiniportWaveRTStream stream = NULL; GUID signalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT; *OutStream = NULL; // // If the data format attributes were specified, extract them. // if ( DataFormat->Flags & KSDATAFORMAT_ATTRIBUTES ) { // The attributes are aligned (QWORD alignment) after the data format PKSMULTIPLE_ITEM attributes = (PKSMULTIPLE_ITEM) (((PBYTE)DataFormat) + ((DataFormat->FormatSize + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT)); ntStatus = GetAttributesFromAttributeList(attributes, attributes->Size, &signalProcessingMode); } // Check if we have enough streams. // if (NT_SUCCESS(ntStatus)) { ntStatus = ValidateStreamCreate(Pin, Capture, signalProcessingMode); } // Determine if the format is valid. // if (NT_SUCCESS(ntStatus)) { ntStatus = IsFormatSupported(Pin, Capture, DataFormat); } ...Use o comando dv para exibir os nomes e valores de todas as variáveis locais para um determinado quadro. Observe que, conforme o esperado, os valores são diferentes da última vez em que executamos esse comando, pois foram executados códigos adicionais que alteram as variáveis locais e algumas variáveis agora não estão no quadro atual ou seus valores foram alterados.
2: kd> dv this = 0xffffe001`d1182000 OutStream = 0xffffe001`d4776d20 OuterUnknown = 0xffffe001`d4776bc8 Pin = 0 Capture = 0x00 ' DataFormat = 0xffffe001`cd7609b0 signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE} ntStatus = 0n0 stream = 0x00000000`00000000
Seção 9: Exibir pilhas de chamadas
Na Seção 9, você exibirá pilhas de chamadas para examinar o código do chamador/receptor.
A pilha de chamadas é a cadeia de chamadas de função que levaram ao local atual do contador de programas. 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*:
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. |
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.
Essa saída exibe a pilha de chamadas ao depurar o código do adaptador de exemplo em um estado de pausa.
0: kd> kb
# RetAddr : Args to Child : Call Site
00 fffff800`7a0fa607 : ffffe001`d1182000 ffffe001`d4776d20 ffffe001`d4776bc8 ffffe001`00000000 : tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
01 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d122bb10 ffffe001`ceb81750 ffffe001`d173f058 : portcls!CPortPinWaveRT::Init+0x2e7
02 fffff800`7a0fc7f9 : ffffe001`d4776bc0 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
04 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
05 fffff800`7bd314b1 : ffffe001`d122bb10 ffffd001`c3098590 ffffe001`d122bd90 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
06 fffff803`cda1bfa8 : 00000000`00000024 00000000`00000000 00000000`00000000 ffffe001`d122bb10 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 fffff803`cda7b306 : 00000000`000001f0 ffffe001`d48ce690 ffffe001`d13d6400 ffffe001`d13d64c0 : nt!IopParseDevice+0x7c8
08 fffff803`cda12916 : 00000000`000001f0 ffffd001`c30988d0 ffffe001`d13d6490 fffff803`cda7b250 : nt!IopParseFile+0xb6
09 fffff803`cda1131c : ffffe001`d2ccb001 ffffd001`c30989e0 00ffffe0`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
0a fffff803`cd9fedb8 : ffffe001`00000001 ffffe001`d48ce690 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
0b fffff803`cd9fe919 : 000000ee`6d1fc8d8 000000ee`6d1fc788 000000ee`6d1fc7e0 000000ee`6d1fc7d0 : nt!IopCreateFile+0x3d8
0c fffff803`cd752fa3 : ffffc000`1f296870 fffff803`cd9d9fbd ffffd001`c3098be8 00000000`00000000 : nt!NtCreateFile+0x79
0d 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
0e 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
0f 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
10 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
11 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e
Você pode usar o DML para explorar ainda mais o código. Quando você seleciona a primeira entrada 00, o comando .frame (Definir Contexto Local) é usado para definir o contexto e, em seguida, o comando dv (Exibir Variáveis Locais) exibe as variáveis locais.
0: kd> .frame 0n0;dv /t /v
00 ffffd001`c30981d0 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
ffffd001`c30982b0 class CMiniportWaveRT * this = 0xffffe001`d1182000
ffffd001`c30982b8 struct IMiniportWaveRTStream ** OutStream = 0xffffe001`d4776d20
ffffd001`c30982c0 struct IPortWaveRTStream * OuterUnknown = 0xffffe001`d4776bc8
ffffd001`c30982c8 unsigned long Pin = 0
ffffd001`c30982d0 unsigned char Capture = 0x00 '
ffffd001`c30982d8 union KSDATAFORMAT * DataFormat = 0xffffe001`cd7609b0
ffffd001`c3098270 struct _GUID signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
ffffd001`c3098210 long ntStatus = 0n0
ffffd001`c3098218 class CMiniportWaveRTStream * stream = 0x00000000`00000000
Seção 10: Exibir processos e threads
Na Seção 10, você usará comandos de depurador para exibir processos e threads.
Processo
Para alterar o contexto do processo atual, use o comando .process <process> . O exemplo a seguir demonstra como identificar um processo e alternar o contexto para ele.
Use o comando
!processpara exibir o processo atual que está envolvido na execução do som.Para obter mais informações, consulte !process
A saída mostra que o processo está associado ao audiodg.exe. Se você ainda estiver no ponto de interrupção descrito na seção anterior deste tópico, o processo atual deverá ser associado à imagem audiodg.exe.
<- No sistema hospedeiro
0: kd> !process
PROCESS ffffe001d147c840
SessionId: 0 Cid: 10f0 Peb: ee6cf8a000 ParentCid: 0434
DirBase: d2122000 ObjectTable: ffffc0001f191ac0 HandleCount: <Data Not Accessible>
Image: audiodg.exe
VadRoot ffffe001d4222f70 Vads 70 Clone 0 Private 504. Modified 16. Locked 0.
DeviceMap ffffc00019113080
Token ffffc0001f1d4060
ElapsedTime <Invalid>
UserTime 00:00:00.000
KernelTime 00:00:00.000
QuotaPoolUsage[PagedPool] 81632
QuotaPoolUsage[NonPagedPool] 9704
Working Set Sizes (now,min,max) (2154, 1814, 2109) (8616KB, 7256KB, 8436KB)
PeakWorkingSetSize 2101
VirtualSize 2097192 Mb
PeakVirtualSize 2097192 Mb
PageFaultCount 2336
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 1573
THREAD ffffe001d173e840 Cid 10f0.1dac Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
ffffe001d16c4dd0 NotificationEvent
ffffe001d08b0840 ProcessObject
THREAD ffffe001ceb77080 Cid 10f0.16dc Teb: 000000ee6cf8d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001cf2d1840 QueueObject
THREAD ffffe001d112c840 Cid 10f0.0a4c Teb: 000000ee6cf8f000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001cf2d1840 QueueObject
THREAD ffffe001d16c7840 Cid 10f0.13c4 Teb: 000000ee6cf91000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001cf2d1840 QueueObject
THREAD ffffe001cec67840 Cid 10f0.0dbc Teb: 000000ee6cf93000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001d173e5c0 QueueObject
THREAD ffffe001d1117840 Cid 10f0.1d6c Teb: 000000ee6cf95000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001d173e5c0 QueueObject
THREAD ffffe001cdeae840 Cid 10f0.0298 Teb: 000000ee6cf97000 Win32Thread: 0000000000000000 RUNNING on processor 2
Observe que um dos threads associados a esse processo está no estado RUNNING. Esse thread estava dando suporte à reprodução do clipe de mídia quando o ponto de interrupção foi atingido.
Use o comando !process 0 0 para exibir informações resumidas para todos os processos. Na saída do comando, use CTRL+F para localizar a ID do processo associado à imagem audiodg.exe. No exemplo mostrado abaixo, a ID do processo é ffffe001d147c840.
Registre a ID do processo associada a audiodg.exe em seu computador para usar posteriormente neste laboratório. ________________________
...
PROCESS ffffe001d147c840
SessionId: 0 Cid: 10f0 Peb: ee6cf8a000 ParentCid: 0434
DirBase: d2122000 ObjectTable: ffffc0001f191ac0 HandleCount: <Data Not Accessible>
Image: audiodg.exe
...
Insira g no depurador para executar o código para frente até que o clipe de mídia termine de ser reproduzido. Em seguida, acesse o depurador pressionando Ctrl+ScrLk (Ctrl+Break). Use o comando !process para verificar se você está executando um processo diferente.
!process
PROCESS ffffe001cd0ad040
SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 001aa000 ObjectTable: ffffc00017214000 HandleCount: <Data Not Accessible>
Image: System
VadRoot ffffe001d402b820 Vads 438 Clone 0 Private 13417. Modified 87866. Locked 64.
DeviceMap ffffc0001721a070
Token ffffc00017216a60
ElapsedTime 05:04:54.716
UserTime 00:00:00.000
KernelTime 00:00:20.531
QuotaPoolUsage[PagedPool] 0
QuotaPoolUsage[NonPagedPool] 0
Working Set Sizes (now,min,max) (1720, 50, 450) (6880KB, 200KB, 1800KB)
PeakWorkingSetSize 15853
VirtualSize 58 Mb
PeakVirtualSize 74 Mb
PageFaultCount 46128
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 66
THREAD ffffe001cd0295c0 Cid 0004.000c Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
fffff803cd8e0120 SynchronizationEvent
THREAD ffffe001cd02a6c0 Cid 0004.0010 Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
fffff803cd8e0ba0 Semaphore Limit 0x7fffffff
...
A saída acima mostra que um processo de sistema diferente de ffffe001cd0ad040 está em execução. O nome da imagem mostra System, não audiodg.exe.
Agora, use o comando !process para alternar para o processo associado ao audiodg.exe. No exemplo, a ID do processo é ffffe001d147c840. Substitua a ID do processo no exemplo pela ID do processo que você registrou anteriormente.
0: kd> !process ffffe001d147c840
PROCESS ffffe001d147c840
SessionId: 0 Cid: 10f0 Peb: ee6cf8a000 ParentCid: 0434
DirBase: d2122000 ObjectTable: ffffc0001f191ac0 HandleCount: <Data Not Accessible>
Image: audiodg.exe
VadRoot ffffe001d4222f70 Vads 60 Clone 0 Private 299. Modified 152. Locked 0.
DeviceMap ffffc00019113080
Token ffffc0001f1d4060
ElapsedTime 1 Day 01:53:14.490
UserTime 00:00:00.031
KernelTime 00:00:00.031
QuotaPoolUsage[PagedPool] 81552
QuotaPoolUsage[NonPagedPool] 8344
Working Set Sizes (now,min,max) (1915, 1814, 2109) (7660KB, 7256KB, 8436KB)
PeakWorkingSetSize 2116
VirtualSize 2097189 Mb
PeakVirtualSize 2097192 Mb
PageFaultCount 2464
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 1418
THREAD ffffe001d173e840 Cid 10f0.1dac Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
ffffe001d16c4dd0 NotificationEvent
ffffe001d08b0840 ProcessObject
Not impersonating
DeviceMap ffffc00019113080
Owning Process ffffe001d147c840 Image: audiodg.exe
Attached Process N/A Image: N/A
Wait Start TickCount 338852 Ticks: 197682 (0:00:51:28.781)
Context Switch Count 36 IdealProcessor: 0
UserTime 00:00:00.015
KernelTime 00:00:00.000
Win32 Start Address 0x00007ff7fb928de0
Stack Init ffffd001c2ec6dd0 Current ffffd001c2ec60c0
Base ffffd001c2ec7000 Limit ffffd001c2ec1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
THREAD ffffe001d115c080 Cid 10f0.15b4 Teb: 000000ee6cf9b000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001d0bf0640 QueueObject
Not impersonating
DeviceMap ffffc00019113080
Owning Process ffffe001d147c840 Image: audiodg.exe
Attached Process N/A Image: N/A
Wait Start TickCount 338852 Ticks: 197682 (0:00:51:28.781)
Context Switch Count 1 IdealProcessor: 0
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c3143dd0 Current ffffd001c3143520
Base ffffd001c3144000 Limit ffffd001c313e000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
THREAD ffffe001d3a27040 Cid 10f0.17f4 Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
ffffe001d173e5c0 QueueObject
Not impersonating
DeviceMap ffffc00019113080
Owning Process ffffe001d147c840 Image: audiodg.exe
Attached Process N/A Image: N/A
Wait Start TickCount 518918 Ticks: 17616 (0:00:04:35.250)
Context Switch Count 9 IdealProcessor: 1
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
Como esse código não está ativo, todos os threads estão no estado WAIT, conforme o esperado.
Tópicos
Os comandos para exibir e definir threads são muito semelhantes aos dos processos. Use o comando !thread para exibir threads. Use .thread para definir os threads atuais.
Para explorar tópicos associados ao player de mídia, reproduza o clipe de mídia novamente. Se o ponto de interrupção descrito na seção anterior ainda estiver em vigor, você interromperá no contexto de audiodg.exe.
Use o !thread -1 0 para exibir informações breves para o thread atual. Isso mostra o endereço do thread, as IDs de thread e de processo, o endereço TEB (bloco de ambiente de thread), o endereço da função Win32 (se houver) que o thread foi criado para execução e o estado de agendamento do thread.
0: kd> !thread -1 0
THREAD ffffe001d3a27040 Cid 10f0.17f4 Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
Para exibir mais informações sobre o thread em execução, digite !thread. Informações semelhantes às seguintes devem ser exibidas.
0: kd> !thread
THREAD ffffe001d3a27040 Cid 10f0.17f4 Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
IRP List:
ffffe001d429e580: (0006,02c8) Flags: 000008b4 Mdl: 00000000
Not impersonating
DeviceMap ffffc00019113080
Owning Process ffffe001d147c840 Image: audiodg.exe
Attached Process N/A Image: N/A
Wait Start TickCount 537630 Ticks: 0
Context Switch Count 63 IdealProcessor: 1
UserTime 00:00:00.000
KernelTime 00:00:00.015
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP RetAddr : Args to Child : Call Site
ffffd001`c70c62a8 fffff800`7a0fa607 : ffffe001`d4aec5c0 ffffe001`cdefd3d8 ffffe001`d4aec5c0 ffffe001`cdefd390 : tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
ffffd001`c70c62b0 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d429e580 ffffe001`d4ea47b0 ffffe001`cdefd3d8 : portcls!CPortPinWaveRT::Init+0x2e7
ffffd001`c70c6340 fffff800`7a0fc7f9 : ffffe001`d4aec430 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
ffffd001`c70c63c0 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
ffffd001`c70c6450 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
ffffd001`c70c6510 fffff800`7bd314b1 : ffffe001`d429e580 ffffd001`c70c6590 ffffe001`d429e800 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
ffffd001`c70c6540 fffff803`cda1bfa8 : 00000000`00000025 00000000`00000000 00000000`00000000 ffffe001`d429e580 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
ffffd001`c70c65a0 fffff803`cda7b306 : 00000000`000002fc ffffe001`d5e0d510 00000000`00000000 ffffe001`d3341bd0 : nt!IopParseDevice+0x7c8
ffffd001`c70c6770 fffff803`cda12916 : 00000000`000002fc ffffd001`c70c68d0 ffffe001`d3341ba0 fffff803`cda7b250 : nt!IopParseFile+0xb6
ffffd001`c70c67d0 fffff803`cda1131c : ffffe001`ceb6c601 ffffd001`c70c69e0 00000000`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
ffffd001`c70c6970 fffff803`cd9fedb8 : ffff8ab8`00000001 ffffe001`d5e0d510 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
ffffd001`c70c6a90 fffff803`cd9fe919 : 000000ee`6d37c6e8 00000004`6d37c500 000000ee`6d37c5f0 000000ee`6d37c5e0 : nt!IopCreateFile+0x3d8
ffffd001`c70c6b40 fffff803`cd752fa3 : fffff6fb`7da05360 fffff6fb`40a6c0a8 fffff681`4d815760 ffff8ab8`92895e23 : nt!NtCreateFile+0x79
ffffd001`c70c6bd0 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`c70c6c40)
000000ee`6d37c568 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
000000ee`6d37c570 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
000000ee`6d37c578 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
000000ee`6d37c580 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e
Use o comando k para exibir a pilha de chamadas associada ao thread.
0: kd> k
# Child-SP RetAddr Call Site
00 ffffd001`c70c62a8 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
01 ffffd001`c70c62b0 fffff800`7a0fb2c3 portcls!CPortPinWaveRT::Init+0x2e7
02 ffffd001`c70c6340 fffff800`7a0fc7f9 portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 ffffd001`c70c63c0 fffff800`7a180552 portcls!xDispatchCreate+0xd9
04 ffffd001`c70c6450 fffff800`7a109a9a ks!KsDispatchIrp+0x272
05 ffffd001`c70c6510 fffff800`7bd314b1 portcls!DispatchCreate+0x7a
06 ffffd001`c70c6540 fffff803`cda1bfa8 ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 ffffd001`c70c65a0 fffff803`cda7b306 nt!IopParseDevice+0x7c8
08 ffffd001`c70c6770 fffff803`cda12916 nt!IopParseFile+0xb6
09 ffffd001`c70c67d0 fffff803`cda1131c nt!ObpLookupObjectName+0x776
0a ffffd001`c70c6970 fffff803`cd9fedb8 nt!ObOpenObjectByNameEx+0x1ec
0b ffffd001`c70c6a90 fffff803`cd9fe919 nt!IopCreateFile+0x3d8
0c ffffd001`c70c6b40 fffff803`cd752fa3 nt!NtCreateFile+0x79
0d ffffd001`c70c6bd0 00007fff`69805b74 nt!KiSystemServiceCopyEnd+0x13
0e 000000ee`6d37c568 00007fff`487484e6 0x00007fff`69805b74
0f 000000ee`6d37c570 0000029b`00000003 0x00007fff`487484e6
10 000000ee`6d37c578 00000000`0000012e 0x0000029b`00000003
11 000000ee`6d37c580 00000000`00000000 0x12e
Insira g no depurador para executar o código para frente até que o clipe de mídia termine de ser reproduzido. Em seguida, interrompa o depurador pressionando Ctrl – ScrLk (Ctrl-Break). Use o comando !thread para confirmar que agora você está executando uma thread diferente.
0: kd> !thread
THREAD ffffe001ce80b840 Cid 17e4.01ec Teb: 00000071fa9b9000 Win32Thread: ffffe001d41690d0 RUNNING on processor 0
Not impersonating
DeviceMap ffffc0001974e2c0
Owning Process ffffe001d1760840 Image: rundll32.exe
Attached Process N/A Image: N/A
Wait Start TickCount 538040 Ticks: 0
Context Switch Count 3181840 IdealProcessor: 0
UserTime 00:00:08.250
KernelTime 00:00:10.796
Win32 Start Address 0x00007ff6d2f24270
Stack Init ffffd001cd16afd0 Current ffffd001cd16a730
Base ffffd001cd16b000 Limit ffffd001cd165000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP RetAddr : Args to Child : Call Site
fffff803`cf373d18 fffff800`7a202852 : fffff803`cf373e60 00000000`00000001 ffffe001`cf4ed330 00000000`0000ffff : nt!DbgBreakPointWithStatus
fffff803`cf373d20 fffff803`cd6742c6 : ffffe001`cf4ed2f0 fffff803`cf373e60 00000000`00000001 00000000`0004e4b8 : kdnic!TXSendCompleteDpc+0x142
fffff803`cf373d60 fffff803`cd74d495 : 00000000`00000000 fffff803`cd923180 fffff803`cde1f4b0 fffff901`40669010 : nt!KiRetireDpcList+0x5f6
fffff803`cf373fb0 fffff803`cd74d2a0 : 00000000`00000090 0000000e`0000006a 00000000`00000092 00000000`00000000 : nt!KxRetireDpcList+0x5 (TrapFrame @ fffff803`cf373e70)
ffffd001`cd16a6c0 fffff803`cd74bd75 : 00000000`00000000 fffff803`cd74a031 00000000`00000000 00000000`00000000 : nt!KiDispatchInterruptContinue
ffffd001`cd16a6f0 fffff803`cd74a031 : 00000000`00000000 00000000`00000000 ffffe001`cff4d2a0 fffff803`cd67738e : nt!KiDpcInterruptBypass+0x25
ffffd001`cd16a700 fffff960`50cdb5a4 : fffff901`400006d0 00000000`00000001 fffff901`40000d60 ffffd001`cd16a9f0 : nt!KiInterruptDispatchNoLockNoEtw+0xb1 (TrapFrame @ ffffd001`cd16a700)
ffffd001`cd16a890 fffff960`50c66b2f : 00000000`00000000 fffff901`40669010 fffff901`42358580 fffff901`40000d60 : win32kfull!Win32FreePoolImpl+0x34
ffffd001`cd16a8c0 fffff960`50c68cd6 : 00000000`00000000 ffffd001`cd16a9f0 fffff901`400006d0 fffff901`400c0460 : win32kfull!EXLATEOBJ::vAltUnlock+0x1f
ffffd001`cd16a8f0 fffff803`cd752fa3 : 00000000`00000000 00000000`00000000 ffffe001`ce80b840 00000000`00000000 : win32kfull!NtGdiAlphaBlend+0x1d16
ffffd001`cd16add0 00007fff`674c1494 : 00007fff`674b1e97 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`cd16ae40)
00000071`fa74c9a8 00007fff`674b1e97 : 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 00000000`00ffffff : 0x00007fff`674c1494
00000071`fa74c9b0 0000a7c6`daee0559 : 00000000`00000001 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 : 0x00007fff`674b1e97
00000071`fa74c9b8 00000000`00000001 : 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 00000000`01010bff : 0x0000a7c6`daee0559
00000071`fa74c9c0 0000020b`741f3c50 : 00000000`00ffffff 00000000`00000030 00000000`01010bff 00000000`00000000 : 0x1
00000071`fa74c9c8 00000000`00ffffff : 00000000`00000030 00000000`01010bff 00000000`00000000 00000000`000000c0 : 0x0000020b`741f3c50
00000071`fa74c9d0 00000000`00000030 : 00000000`01010bff 00000000`00000000 00000000`000000c0 00000000`00000030 : 0xffffff
00000071`fa74c9d8 00000000`01010bff : 00000000`00000000 00000000`000000c0 00000000`00000030 00000071`00000030 : 0x30
00000071`fa74c9e0 00000000`00000000 : 00000000`000000c0 00000000`00000030 00000071`00000030 00000071`01ff8000 : 0x1010bff
O nome da imagem é rundll32.exe, que realmente não corresponde ao nome da imagem associado à reprodução do clipe de mídia.
Nota Para definir o thread atual, digite .thread< número do thread>.
Para obter mais informações sobre threads e processos, consulte as seguintes referências:
Seção 11: IRQL, registros e desmontagem
Exibir o IRQL salvo
Na Seção 11, você exibirá o IRQL e o conteúdo dos regsisters.
<- No sistema hospedeiro
O nível de solicitação de interrupção (IRQL) é usado para gerenciar a prioridade do atendimento de interrupções. Cada processador tem uma configuração de IRQL que threads podem elevar ou reduzir. As interrupções que ocorrem em ou abaixo da configuração IRQL do processador são mascaradas e não interferirão na operação atual. Interrupções que ocorrem acima da configuração IRQL do processador têm precedência sobre a operação atual. A extensão !irql exibe o IRQL (nível de solicitação de interrupção) no processador atual do computador de destino antes da interrupção do depurador. Quando o computador de destino entra no depurador, o IRQL é alterado, mas o IRQL que estava ativo pouco antes da pausa do depurador é salvo e exibido por !irql.
0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)
< Exibir os registros e desmontar
Exibir os registros
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 selecionandoRegistros de Exibição>.
A visualização do conteúdo dos registradores pode ser útil durante a análise da execução de código em linguagem assembly e em outros cenários. Para obter mais informações , consulte r (Registros).
Para obter informações sobre o conteúdo do registro, consulte arquitetura x86 e arquitetura x64.
Desmontagem
Você pode desmontar o código que está em execução para exibir o código de linguagem do assembly que está sendo executado selecionando Exibir>Desmontagem.
Para obter mais informações sobre desmontagens de linguagem assembly, consulte Desmontagem x86 Anotada e Desmontagem x64 Anotada.
Seção 12: Trabalhar com memória
Na Seção 12, você usará comandos de depurador para exibir o conteúdo da memória.
Exibir memória
Talvez seja necessário examinar a memória para identificar um problema ou inspecionar variáveis, ponteiros e assim por diante. Você pode exibir memória digitando um dos seguintes comandos de endereço< d*>.
Db |
Exibe dados em valores de bytes e caracteres ASCII. |
dd |
Exibe dados como palavras de largura dupla (4 bytes). |
Du |
Exibe dados como caracteres Unicode. |
Dw |
Exibe dados como valores de palavra (2 bytes) e caracteres ASCII. |
Nota Se você tentar exibir um endereço inválido, seu conteúdo será mostrado como pontos de interrogação (?).
Como alternativa, você pode exibir a memória selecionando Exibir>Memória. Use o pull para baixo do formato de exibição para alterar a forma como a memória é exibida.
Para exibir dados associados ao controle de volume, defina um ponto de interrupção para ser acionado na rotina PropertyHandlerAudioEngineVolumeLevel usando o comando bm. Antes de definirmos o novo ponto de interrupção, limparemos todos os pontos de interrupção anteriores usando bc *.
kd> bc *Defina um ponto de interrupção para ser acionado na rotina PropertyHandlerAudioEngineVolumeLevel usando o comando bm.
kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume 1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"Liste os pontos de interrupção para confirmar se o ponto de interrupção está definido corretamente.
kd> bl 1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"Use o comando g para reiniciar a execução do código.
No sistema de destino, ajuste o volume na barra de tarefas. Isso fará com que o ponto de interrupção seja acionado.
Breakpoint 1 hit tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume: fffff80f`02c3a4b0 44894c2420 mov dword ptr [rsp+20h],r9dUse o item de menu Exibir>Local para exibir variáveis locais. Observe o valor atual da variável IVolume.
Você pode exibir o tipo de dados e o valor atual da variável IVolume no código de exemplo digitando o comando dt e o nome da variável.
kd> dt lVolume Local var @ 0xa011ea50 Type long 0n-6291456O ponto de interrupção é atingido ao inserir SetDeviceChannelVolume.
STDMETHODIMP_(NTSTATUS) CMiniportWaveRT::SetDeviceChannelVolume(_In_ ULONG _ulNodeId, _In_ UINT32 _uiChannel, _In_ LONG _Volume) { NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; PAGED_CODE (); DPF_ENTER(("[CMiniportWaveRT::SetEndpointChannelVolume]")); IF_TRUE_ACTION_JUMP(_ulNodeId != KSNODE_WAVE_AUDIO_ENGINE, ntStatus = STATUS_INVALID_DEVICE_REQUEST, Exit); // Snap the volume level to our range of steppings. LONG lVolume = VOLUME_NORMALIZE_IN_RANGE(_Volume); ntStatus = SetChannelVolume(_uiChannel, lVolume); Exit: return ntStatus; }Tente exibir o valor no local de memória do IVolume usando o comando dt (Tipo de Exibição ).
kd> dt dt lVolume Local var @ 0xffffb780b7eee664 Type long 0n0Como a variável ainda está para ser definida, ela não contém informações.
Pressione F10 para avançar até a última linha de código em SetDeviceChannelVolume.
return ntStatus;Exiba o valor no local de memória do IVolume usando o comando dt (Tipo de Exibição ).
kd> dt lVolume Local var @ 0xffffb780b7eee664 Type long 0n-6291456Agora que a variável está ativa, um valor de 6291456 é exibido neste exemplo.
Você também pode exibir o local de memória do IVolume usando o ? (Avaliar expressão) comando.
kd> ? lVolume Evaluate expression: -79711507126684 = ffffb780`b7eee664O endereço mostrado, ffffb780'b7eee664 é o endereço da variável lVolume. Use o comando dd para exibir o conteúdo da memória nesse local.
kd> dd ffffb780`b7eee664 ffffb780`b7eee664 ffa00000 00000018 00000000 c52d7008 ffffb780`b7eee674 ffffc98e e0495756 fffff80e c52d7008 ffffb780`b7eee684 ffffc98e 00000000 fffff80e 00000000 ffffb780`b7eee694 ffffc98e ffa00000 ffffb780 b7eee710 ffffb780`b7eee6a4 ffffb780 00000000 00000000 c7477260 ffffb780`b7eee6b4 ffffc98e b7eee7a0 ffffb780 b7eee6f0 ffffb780`b7eee6c4 ffffb780 e04959ca fffff80e 00000000 ffffb780`b7eee6d4 00000000 00000028 00000000 00000002Você pode exibir os quatro primeiros bytes de um endereço especificando o parâmetro de intervalo L4.
kd> dd ffffb780`b7eee664 l4 ffffb780`b7eee664 ffa00000 00000018 00000000 c52d7008Para ver os diferentes tipos de saída de memória exibidos, digite os comandos du, da e db .
kd> du ffffb780`b7eee664 ffffb780`b7eee664 "" kd> a ffffb780`b7eee664 ffffb780`b7eee664 "" kd> db 0xffffae015ff97664 ffffae01`5ff97664 00 80 bc ff 18 00 00 00-00 00 00 00 08 50 e0 51 .............P.Q ffffae01`5ff97674 00 c0 ff ff 56 57 da 56-0e f8 ff ff 08 50 e0 51 ....VW.V.....P.Q ffffae01`5ff97684 00 c0 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00 ................ ffffae01`5ff97694 00 c0 ff ff aa 80 bc ff-01 ae ff ff 10 77 f9 5f .............w._ ffffae01`5ff976a4 01 ae ff ff 40 00 00 00-00 e6 ff ff 10 dc 30 55 ....@.........0U ffffae01`5ff976b4 00 c0 ff ff a0 77 f9 5f-01 ae ff ff f0 76 f9 5f .....w._.....v._ ffffae01`5ff976c4 01 ae ff ff ca 59 da 56-0e f8 ff ff 00 00 00 00 .....Y.V........ ffffae01`5ff976d4 00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00 ....(...........Use a opção df float para exibir dados como números de ponto flutuante de precisão única (4 bytes).
df ffffb780`b7eee664 ffffb780`b7eee664 -1.#QNAN 3.3631163e-044 0 -2775.002 ffffb780`b7eee674 -1.#QNAN -5.8032637e+019 -1.#QNAN -2775.002 ffffb780`b7eee684 -1.#QNAN 0 -1.#QNAN 0 ffffb780`b7eee694 -1.#QNAN -1.#QNAN -1.#QNAN -2.8479408e-005
Gravar na memória
Semelhante aos comandos usados para ler memória, você pode usar os comandos e* para alterar o conteúdo da memória.
| Comando | Descrição |
|---|---|
cada |
Cadeia de caracteres ASCII (não terminada em NULL) |
UE |
Cadeia de caracteres Unicode (não terminada em NULL |
Ew |
Valores de palavras (2 bytes) |
eza |
Cadeia de caracteres ASCII terminada em NULL |
ezu |
Cadeia de caracteres Unicode terminada em NULL |
Eb |
Valores de bytes |
dd |
Valores de palavra dupla (4 bytes) |
O exemplo a seguir mostra como substituir a memória.
Primeiro, localize o endereço do lVolume usado no código de exemplo.
kd> ? lVolume Evaluate expression: -79711507126684 = ffffb780`b7eee664Substitua esse endereço de memória com novos caracteres usando o comando eb .
kd> eb 0xffffb780`b7eee664 11 11 11 11 11Exiba o local da memória para confirmar se os caracteres foram substituídos digitando o comando db .
kd> db 0xffffb780`b7eee664 ffffb780`b7eee664 11 11 11 11 11 00 00 00-00 00 00 00 08 70 2d c5 .............p-. ffffb780`b7eee674 8e c9 ff ff 56 57 49 e0-0e f8 ff ff 08 70 2d c5 ....VWI......p-. ffffb780`b7eee684 8e c9 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00 ................ ffffb780`b7eee694 8e c9 ff ff 00 00 a0 ff-80 b7 ff ff 10 e7 ee b7 ................ ffffb780`b7eee6a4 80 b7 ff ff 00 00 00 00-00 00 00 00 60 72 47 c7 ............`rG. ffffb780`b7eee6b4 8e c9 ff ff a0 e7 ee b7-80 b7 ff ff f0 e6 ee b7 ................ ffffb780`b7eee6c4 80 b7 ff ff ca 59 49 e0-0e f8 ff ff 00 00 00 00 .....YI......... ffffb780`b7eee6d4 00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00 ....(...........
Como alternativa, você pode modificar o conteúdo da memória em um relógio ou janela local. Para a janela de observação, você pode ver variáveis fora do contexto do quadro atual. Modificá-los não será relevante se eles não estiverem no contexto.
Seção 13: Encerrar a sessão do WinDbg
<-No sistema hospedeiro
Se você quiser manter o depurador conectado, mas quiser trabalhar no computador de destino, desmarque todos os pontos de parada 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 use o comando qd (Sair e Desanexar) ou selecione Parar Depuração no menu.
0: kd> qd
Para obter mais informações, consulte Como encerrar uma sessão de depuração no WinDbg (Clássico) na documentação de referência de depuração.
Seção 14: Recursos de depuração do Windows
Informações adicionais sobre o debugging do Windows estão disponíveis. Observe que alguns desses livros usarão versões mais antigas 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 no Windows: um guia prático para estratégias de depuração e monitoramento no Windows® por Tarik Soulami
Windows Internals por Pavel Yosifovich, Alex Ionescu, Mark Russinovich e David Solomon
Vídeo
The Defrag Tools Show WinDbg Episodes 13-29: </shows/defrag-tools/>
Fornecedores de treinamento:
OSR – https://www.osr.com/