Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este laboratório fornece exercícios práticos que demonstram como depurar o driver de dispositivo de modo kernel de áudio Sysvad.
O Microsoft Windows Debugger (WinDbg) é uma poderosa ferramenta de depuração baseada no Windows que você pode usar para executar depuração no modo de usuário e no modo kernel. O WinDbg fornece depuração no nível de origem para o kernel do Windows, drivers de modo kernel e serviços do sistema, bem como aplicativos e drivers de 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 de comandos do depurador permite ao utilizador emitir uma ampla variedade de comandos.
Configuração do laboratório
Você precisará do seguinte hardware para 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/router de rede e cabos de rede para ligar os dois PCs
- Acesso à internet para baixar arquivos de símbolos
Você precisará do seguinte software para poder concluir o laboratório.
- Microsoft Visual Studio 2017
- Kit de Desenvolvimento de Software (SDK) do Windows para Windows 10
- Kit de driver do Windows (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 Kit de Driver do Windows (WDK).
Passo a passo de depuração do Sysvad
Este laboratório orienta você através do processo de depuração de um driver de modo kernel. Os exercícios usam o exemplo de driver de áudio virtual Syvad. Como o driver de áudio Syvad não interage com o hardware de áudio real, ele pode ser usado na maioria dos dispositivos. O laboratório abrange as seguintes tarefas:
- Seção 1: Conectar-se a uma sessão WinDbg de modo kernel
- Seção 2: Comandos e técnicas de depuração do modo kernel
- Seção 3: Baixe e construa o driver de áudio Sysvad
- Seção 4: Instale o driver de áudio Sysvad no sistema de destino
- Seção 5: Usar 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
- Secção 8: Analise as variáveis
- Seção 9: Exibir pilhas de chamadas
- Seção 10: Mostrar processos e threads
- Secção 11: IRQL, registos e desmontagem
- Seção 12: Trabalhar com memória
- Seção 13: Encerrando a sessão do WinDbg
- Seção 14: Ferramentas de depuração do Windows
Laboratório de driver do Echo
O driver Echo é um driver mais simples do que o driver de áudio Sysvad. Se você é novo no WinDbg, você pode querer considerar primeiro completar o Debug Universal Drivers - Step-by-Step Lab (modo kernel Echo). Este laboratório reutiliza as instruções de configuração desse laboratório, portanto, se você tiver concluído esse laboratório, poderá pular as seções 1 e 2 aqui.
Seção 1: Conectar-se a uma sessão WinDbg de 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 ligação de rede Ethernet para a resolução de problemas do kernel.
Este laboratório utiliza dois computadores. WinDbg é executado no sistema host e o driver Sysvad é executado no sistema de destino .
Use um hub/roteador de rede e cabos de rede para conectar os dois PCs.
Para trabalhar com aplicativos de modo kernel e usar o WinDbg, recomendamos que você use o transporte KDNET over Ethernet. Para obter informações sobre como usar o protocolo de transporte Ethernet, consulte Introdução ao WinDbg (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 automática do kernel da rede KDNET.
Configurar depuração de modo kernel usando ethernet
Para habilitar a depuração no modo kernel no sistema de destino, execute as etapas a seguir.
<- No sistema host
- 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 host: ______________________________________
Registe o nome do host do sistema: ______________________________________
-> Sobre o sistema alvo
- 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ê gravou em vez de 169.182.1.1 que é 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 em modo kernel no sistema de destino, execute as etapas a seguir.
No sistema host, localize o diretório WDK KDNET. Por padrão, ele está localizado aqui.
C:\Arquivos de programas (x86)\Windows Kits\10\Debuggers\x64
Este laboratório pressupõe que ambos os PCs estão executando uma versão de 64 bits do Windows, tanto no destino quanto no host. Se esse não for o caso, a melhor abordagem é executar no host ferramentas com a mesma arquitetura (número de bits) que está a ser utilizada no destino. 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 da Linha de Comandos enquanto Administrador. Insira este comando para validar se a NIC no PC de destino é suportada.
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ê gravou em vez de 169.182.1.1 que é 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 o BCDEdit para alterar as informações de inicialização, talvez seja necessário suspender temporariamente os recursos de segurança do Windows, como BitLocker e Inicialização Segura, no computador de teste. Reative esses recursos de segurança quando o teste estiver concluído e gerencie adequadamente o computador de teste, quando os recursos de segurança estiverem desativados. A inicialização segura normalmente é desativada na UEFI. Para acessar a configuração UEFI, Use Sistema, Recuperação, Inicialização avançada. Ao reiniciar, selecione Solução de problemas, Opções avançadas, Configurações de firmware UEFI. Tenha cuidado, pois definir incorretamente as opções de UEFI ou desativar o BitLocker pode tornar o sistema inoperante.
- Digite este comando para confirmar se o dbgsettings está definido 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 PC host. Copie o arquivo de texto com a chave para o sistema host.
NotaFirewalls e debuggers
Se receber uma mensagem pop-up do firewall e desejar usar o depurador, marque todas as três caixas.
<- No sistema host
- No computador host, abra uma janela do Prompt de Comando como Administrador. Mude para o diretório WinDbg.exe. Usaremos a versão x64 do WinDbg.exe do Kit de Driver do Windows (WDK) que foi instalado como parte da instalação do kit do Windows.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
- Inicie o WinDbg com depuração de usuário remoto usando o seguinte comando. O valor da chave e da porta corresponde ao que você definiu anteriormente usando o BCDEdit no destino.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
->No sistema alvo
Reinicialize o sistema de destino.
<-No sistema host
Em um ou dois minutos, a saída de depuração deve ser exibida no sistema anfitrião.
A janela Comando do Depurador é a principal janela de informações de depuração no WinDbg. Pode introduzir comandos do depurador e visualizar os resultados dos comandos nesta janela.
A Janela de Comando do Depurador é dividida em dois painéis. Digite comandos no painel menor (o painel de entrada de comando) na parte inferior da janela e visualize a saída do comando no painel maior na parte superior da janela.
No painel de entrada de comandos, use as teclas de seta para cima e seta para baixo para percorrer o histórico de comandos. Quando um comando aparece, você pode editá-lo ou pressionar ENTER para executá-lo.
Seção 2: Comandos e técnicas de depuração do modo kernel
Na Seção 2, você usará comandos de depuração para exibir informações sobre o sistema de destino.
<- No sistema host
Habilite a DML (Debugger Markup Language) 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 (Scroll Lock) no WinDBg para entrar no código em execução no sistema de destino. Pode levar um pouco de tempo para o sistema de destino responder.
- Digite o seguinte comando para habilitar o DML na janela de 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 do comando de referência usando o comando .hh .
- Digite o seguinte comando para exibir a ajuda de referência de comando para .prefer_dml.
0: kd> .hh .prefer_dml
O 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 do sistema de destino digitando o comando vertarget (Show Target Computer Version) na janela WinDbg.
0: kd> vertarget
Windows 10 Kernel Version 9926 MP (4 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 9926.0.amd64fre.fbl_awesome1501.150119-1648
Machine Name: ""
Kernel base = 0xfffff801`8d283000 PsLoadedModuleList = 0xfffff801`8d58aef0
Debug session time: Fri Feb 20 10:15:17.807 2015 (UTC - 8:00)
System Uptime: 0 days 01:31:58.931
Listar os módulos carregados
- Você pode verificar se está trabalhando com o processo correto do modo kernel 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
...
Observação 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: Baixe e construa o driver de áudio Sysvad
Na Seção 3, você baixará e construirá o driver de áudio Sysvad.
Normalmente, você estaria trabalhando com seu próprio código de driver quando você usa WinDbg. Para se familiarizar com a depuração de drivers de áudio, o driver de amostra de áudio virtual Sysvad é usado. Este exemplo é usado para ilustrar como você pode executar uma única etapa através do código nativo do modo kernel. 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 Sysvad, execute as etapas a seguir.
Baixe e extraia o exemplo de áudio do Sysvad do GitHub
Você pode usar um navegador para visualizar o exemplo Sysvad e Readme.md arquivo aqui:
https://github.com/Microsoft/Windows-driver-samples/tree/main/audio/sysvad
Este laboratório, mostra como baixar as amostras de driver universal em um arquivo zip.
a) Transfira o ficheiro master.zip para o seu 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 pasta 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 seguinte subpasta.
C:\WDK_Samples\Sysvad
Abra a solução de driver no Visual Studio
No VisualStudio, selecione >/Solução de Arquivo>... 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 ainda não estiver aberto, escolha 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 da amostra
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 Configuration Manager. Certifique-se de que a configuração 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 plataforma para um projeto, deverá fazer as mesmas alterações para os três projetos restantes.
Observação Este laboratório assume que o Windows de 64 bits está a ser utilizado. 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 o Modo de Assinatura do Driver está definido como Assinatura de Teste.
As amostras de driver precisam ser modificadas para usar valores que não se sobreponham com os drivers existentes. Consulte Do Código de Exemplo ao Driver de Produção - O que Alterar nos Exemplos sobre como criar um exemplo exclusivo de driver que coexistirá com os drivers reais já instalados no Windows.
Criar o exemplo usando o Visual Studio
No Visual Studio, seleccione Construir>Construir Solução.
As janelas de compilação devem exibir uma mensagem indicando que a compilação para todos os seis projetos foi bem-sucedida.
Sugestão
Se você encontrar uma mensagem de erro de compilação, use o número de erro de compilação para determinar uma correção. Por exemplo, erro MSBuild MSB8040 descreve como trabalhar com bibliotecas de espectro atenuado.
Localize os arquivos de driver construídos
No Explorador de Ficheiros, navegue até à pasta que contém os ficheiros 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 da configuração e das definições de 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\Debug para uma compilação 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 driver TabletAudioSample .SYS, o ficheiro de símbolo pdp e o ficheiro inf. Você também precisará localizar as dlls e os arquivos de símbolo DelayAPO, KWSApo e KeywordDetectorContosoAdapter.
Para instalar o driver, você precisará dos seguintes arquivos.
Nome do ficheiro Descrição TabletAudioSample.sys O arquivo do driver. TabletAudioSample.pdb O ficheiro de símbolo do driver. tabletaudiosample.inf Um arquivo de informações (INF) que contém informações necessárias para instalar o driver. KeywordDetectorContosoAdapter.dll Um detetor de palavras-chave de exemplo. KeywordDetectorContosoAdapter.pdb O arquivo de símbolo do detetor de palavras-chave de exemplo. DelayAPO.dll Uma amostra atrasa APO. DelayAPO.pdb O arquivo de símbolo de atraso APO. KWSApo.dll Um exemplo de detector de palavras-chave APO. KWSApo.pdb O ficheiro de símbolos do detetor de palavras-chave. TabletAudioSample.cer O arquivo de certificado TabletAudioSample. Localize um pen drive USB ou configure um compartilhamento de rede para copiar os arquivos de driver construídos 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 Sysvad no sistema de destino
Na Seção 4, você usará o devcon para instalar o driver de áudio Sysvad.
-> Sobre o sistema alvo
O computador onde você instala o driver é chamado de computador de destino ou o computador de teste . Normalmente, este é um computador separado do computador no qual você desenvolve e compila o pacote de driver. O computador onde o utilizador desenvolve e compila o driver é chamado de computador host.
O processo de mover o pacote de driver para o computador de destino e instalar o driver é chamado de implantar o 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 construído no sistema de destino.
Para instalar o driver no sistema de destino, execute as seguintes etapas.
Ativar drivers assinados de teste
Para habilitar a capacidade de executar drivers assinados de teste:
Abra as Configurações do Windows.
No Atualização e Segurança, selecione Recuperação.
Em Inicialização Avançada, selecione Reiniciar agora.
Quando o PC reiniciar, selecione Resolução de problemas.
Em seguida, selecione Opções avançadas, Configurações de inicialização e, em seguida, selecione Reiniciar.
Selecione a opção Desativar a imposição de assinatura do driver ao premir a tecla F7.
O PC começará com os novos valores em vigor.
-> Sobre o sistema alvo
Instale o driver
As instruções a seguir mostram como instalar e testar o driver de exemplo.
O arquivo INF necessário para instalar este driver é TabletAudioSample.inf. No computador de destino, abra uma janela da Linha de Comandos enquanto Administrador. Navegue até a pasta do pacote de 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 este driver mesmo assim para continuar.
Sugestão
Se você tiver algum problema com a instalação, verifique o seguinte arquivo para obter mais informações.
%windir%\inf\setupapi.dev.logPara obter instruções mais detalhadas, consulte Configuração de um computador para a implantação, teste e depuração de controladores.
O arquivo INF contém o ID de hardware para instalar o tabletaudiosample.sys. Para o exemplo Syvad, o ID de hardware é:
root\sysvad_TabletAudioSampleExamine o driver no Gestor de dispositivos
No computador de destino, em uma janela do Prompt de Comando, digite devmgmt para abrir o Gerenciador de Dispositivos. No Gerenciador de dispositivos, no menu Exibir, selecione Dispositivos por tipo.
Na árvore de dispositivos, localize Virtual Audio Device (WDM) - Tablet Sample no nó Dispositivo de áudio. Isso geralmente encontra-se sob o nó Controladores de som, vídeo e jogos. Confirme se ele está instalado e ativo.
Selecione o driver para o hardware real no PC no Gestor de Dispositivos. Em seguida, selecione e segure (ou clique com o botão direito do mouse) o driver e selecione desativar para desativar o driver.
Confirme no Gerenciador de dispositivos que o driver de hardware de áudio exibe a seta para baixo, indicando que ele está desativado.
Depois de instalar com êxito o driver de exemplo, você está pronto para testá-lo.
Teste o driver de áudio Sysvad
No computador de destino, em uma janela do Prompt de Comando, digite devmgmt para abrir o Gerenciador de Dispositivos. No Gestor de Dispositivos, no menu Visualizar, selecione Dispositivos por tipo. Na árvore de dispositivos, localize Virtual Audio Device (WDM) - Tablet Sample.
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 Dispositivo de áudio virtual (WDM) - Amostra de tablet e, em seguida, 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 driver de Virtual Audio Device (WDM) - Tablet Sample.
Seção 5: Usar WinDbg para exibir informações sobre o driver
Na Seção 5, você definirá o caminho do símbolo e usará os comandos do depurador do kernel para exibir informações sobre o driver de exemplo 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. WinDbg usa os formatos de símbolo de depuração do Microsoft Visual Studio para depuração a nível de código-fonte. Ele pode acessar qualquer símbolo ou variável de um módulo que tenha arquivos de símbolos PDB.
Para carregar o depurador, execute as seguintes etapas.
<-No sistema host
Se você fechou o depurador, abra-o novamente usando o seguinte comando 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 (Scroll Lock) para quebrar o código em execução no sistema de destino.
Definir o caminho do símbolo
Para definir o caminho de símbolos para o servidor de símbolos da Microsoft no ambiente WinDbg, use o comando .symfix .
0: kd> .symfixPara adicionar a localização dos símbolos locais para usar os seus símbolos locais, adicione o caminho usando .sympath+ e, em seguida, .reload /f.
0: kd> .sympath+ C:\WDK_Samples\Sysvad 0: kd> .reload /fObservação O comando .reload com a opção /f force exclui todas as informações de símbolos do módulo especificado e recarrega os símbolos. Em alguns casos, este comando também recarrega ou descarrega o próprio módulo.
Observação 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, 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á uma série de abordagens que podem ser usadas para trabalhar com símbolos. Em muitas situações, pode configurar o PC para aceder a símbolos a partir de um servidor de símbolos que a Microsoft fornece quando 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 Caminho de símbolos para o depurador do Windows.
ObservaçãoCompreender os requisitos do símbolo do código-fonte
Para executar a depuração de origem, você deve criar uma versão verificada (depuração) de seus binários. O compilador criará arquivos de símbolos (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 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 linker não otimize o seu código. A depuração de origem e o acesso a variáveis locais são mais difíceis e, às vezes, quase impossíveis, se o código tiver sido otimizado. Se você estiver tendo problemas para visualizar variáveis locais ou linhas de origem, defina as seguintes opções de compilação.
definir COMPILE_DEBUG=1
Definir 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 os símbolos de itens que começam com a letra a.
Como o DML está habilitado, alguns elementos da saída são hot links 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. O 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 como 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 Sysvad e onde ele reside na árvore de dispositivos Plug and Play.
As informações sobre o driver de dispositivo na árvore de dispositivos Plug and Play podem ser úteis para solucionar problemas. Por exemplo, se um driver de dispositivo não for residente na árvore de dispositivos, pode haver um problema com a instalação do driver de dispositivo.
Para obter mais informações sobre a extensão de depuração do nó do dispositivo, consulte !devnode.
<-No sistema host
Para ver todos os nós do dispositivo na árvore de dispositivos Plug and Play, digite o comando !devnode 0 1 . Este comando pode levar um ou dois minutos para ser executado. Durante esse tempo, "*Busy" 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 procurar na saída gerada o nome do driver de dispositivo, sysvad.
Uma entrada de nó de dispositivo com um nome de
sysvad_TabletAudioSampleserá apresentada 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 Plug and Play associadas ao nosso 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. Digite o comando !devobj<PDO address> para exibir as informações Plug and Play associadas ao driver de dispositivo Sysvad. Use o endereço DOP que !devnode exibe no seu PC, 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 conectado: \Driver\sysvad_tabletaudiosample. Use o comando !drvobj com uma máscara de bits de 2 para exibir informações associadas ao dispositivo conectado.
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!PnpHandlerDigite o comando !devstack<PDO address> para exibir as informações Plug and Play associadas ao driver de dispositivo. A saída exibida no comando !devnode 0 1 inclui o endereço DOP associado à instância em execução do nosso driver. Neste exemplo, é 0xffffe00089c575a0. Use o endereço DOP que !devnode exibe no seu PC, 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 driver de dispositivo muito simples. O driver sysvad_TabletAudioSample é um componente do nó PnPManager. O PnPManager é um nó raiz.
Este diagrama mostra uma árvore de nós de dispositivo mais complexa.
Observação Para obter mais informações sobre pilhas de drivers mais complexas, consulte Pilhas de driver e Nós de dispositivo e pilhas de dispositivos.
Secção 7: Trabalhar 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.
Definindo pontos de interrupção usando comandos
Os pontos de interrupção são usados para interromper a execução de código em uma linha de código específica. 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 debug, use um dos seguintes comandos b .
BP |
Define um ponto de interrupção que ficará ativo até que o módulo em que ele está seja descarregado. |
bu |
Define um ponto de interrupção que não é resolvido quando o módulo é descarregado e reativa quando o módulo é recarregado. |
BM |
Define um ponto de interrupção para um símbolo. Este comando utilizará bu ou bp de forma adequada e permite que caracteres universais * sejam usados 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 oModo de Origem de> está habilitado na sessão WinDbg atual.
Adicione o seu código local ao caminho de origem inserindo o seguinte comando.
.sympath+ C:\WDK_Samples\SysvadAdicione a localização do símbolo local ao caminho do símbolo digitando o seguinte comando.
.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) onde 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 sintaxe diferente em conjunto com variáveis de configuração como <módulo>!<symbol>, <class>::<method>,'<file.cpp>:<line number>', ou ignore um número de vezes <condição><#>. Para obter mais informações, consulte Usando pontos de interrupção.
Liste os pontos de interrupção atuais para confirmar que 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 alvo
No Windows, abra o Gerenciador de Dispositivos usando o ícone ou digitando mmc devmgmt.msc. No Gestor de dispositivos, expanda o nó Controladores de som, vídeo e jogos. Selecione e segure (ou clique com o botão direito do mouse) a entrada do driver de áudio virtual e selecione Desativar no menu.
Selecione e segure (ou clique com o botão direito do mouse) a entrada do driver de áudio virtual novamente e selecione Ativar no menu.
<- No sistema host
Isso deve fazer com que o Windows recarregue o driver, que chama AddDevice. Isso fará com que o ponto de interrupção do debugger AddDevice seja acionado e a execução do código do driver no sistema de destino seja suspensa.
Breakpoint 1 hit tabletaudiosample!AddDevice: fffff801`14baf000 4889542410 mov qword ptr [rsp+10h],rdxSe o caminho de origem estiver configurado corretamente, deves parar na rotina AddDevice em 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; } // AddDevicePercorra o código linha a linha digitando o comando p ou pressionando F10. Você pode avançar 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 |
executar (quando a CPU executa uma instrução a partir do endereço) |
r |
leitura/gravação (quando a CPU lê ou grava para o endereço) |
w |
escrever (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ê certificar-se de que está alinhando seus dados corretamente ou não acionará o ponto de interrupção (as palavras devem terminar em endereços divisíveis por 2, dwords devem ser divisíveis 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 os pontos de interrupção existentes usando os seguintes comandos.
BL |
Lista os pontos de interrupção. |
BC |
Remove um ponto de interrupção da lista. Use bc * para limpar todos os pontos de interrupção. |
BD |
Desabilita um ponto de interrupção. Use bd * para desativar todos os pontos de interrupção. |
ser |
Permite um ponto de interrupção. Use be * para ativar todos os pontos de interrupção. |
Como alternativa, você também pode modificar os pontos de interrupção selecionando editar>pontos de interrupção. Observe que a caixa de diálogo ponto de interrupção só funciona com pontos de interrupção existentes. Novos pontos de interrupção devem ser definidos a partir da linha de comando.
Definir um ponto de interrupção no MixerVolume
Diferentes partes do código do driver de áudio são chamadas para responder aos vários eventos, após o driver de dispositivo ser 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 seguintes etapas.
<- No sistema host
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 procurar por volume para cima na saída e localizar o método MixerVolumeWrite.
Limpe os pontos de interrupção anteriores utilizando o comando 'bc *'.
Defina um ponto de interrupção de símbolo na rotina CAdapterCommon::MixerVolumeWrite usando o seguinte comando.
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 Controlo, selecione Hardware e Som>. Selecione e segure (ou clique com o botão direito do mouse) Exemplo de Descrição do coletor e selecione Propriedades. Selecione a guia Níveis . Ajuste o volume do controle deslizante.
Isso deve fazer com que o ponto de interrupção de depuração SetMixerVolume seja acionado e a execução do código do driver no sistema de destino seja interrompida.
kd> g Breakpoint 1 hit tabletaudiosample!CAdapterCommon::MixerVolumeWrite: fffff801`177b26a0 44894c2420 mov dword ptr [rsp+20h],r9dVocê deve parar nesta 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 F10 para percorrer o código em uma única etapa.
Pressione F5 para concluir a execução do código MixerVolumeWrite.
Resumo - Percorrer o código a partir da janela de comando do depurador
A seguir estão os comandos que você pode usar para percorrer seu código (com os atalhos de teclado associados mostrados entre parênteses).
Break in (Ctrl+Break) - Este comando interromperá 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).
Step over (F10) – Este comando faz com que a execução de código prossiga uma instrução ou uma declaração de cada vez. Se uma chamada for encontrada, a execução de código ignora a chamada sem entrar na rotina chamada. (Se a linguagem de programação for C ou C++ e o WinDbg estiver no modo de origem, o modo de origem poderá ser ativado ou desativado usando Debug>Modo de origem).
Step in (F11) – Este comando é como step-over, exceto que a execução de uma chamada entra na rotina chamada.
Step out (Shift+F11) – Este comando faz com que a execução seja executada e saia da rotina atual (local atual na pilha de chamadas). Isso é útil se você já viu o suficiente da rotina.
Executar para o cursor (F7 ou Ctrl+F10) – Coloque o cursor numa janela de origem ou desmontagem onde pretende que a execução seja interrompida e, em seguida, prima F7; A execução do código 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á quebrado, porque 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
Definir instruções 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 do código começará a partir desse ponto assim que você permitir que ele prossiga (por exemplo, usando F5 ou F10). Isso é útil se você quiser repetir uma sequência, mas requer alguns cuidados. Por exemplo, registros e variáveis não são definidos para o que seriam se a execução de código tivesse atingido essa linha naturalmente.
Configuração direta do registro eip -- Você pode colocar um valor no registro eip e, assim que pressionar F5 (ou F10, F11, etc.), a execução começa a partir desse endereço. Isto é semelhante a definir a instrução para a linha atual designada pelo cursor, com a diferença de que se especifica o endereço de uma instrução de assembly.
É mais fácil percorrer a interface de utilizador em vez da linha de comando, portanto, este método é recomendado. Se necessário, os seguintes comandos podem ser usados para percorrer um arquivo de origem na linha de comando:
.lines - Habilitar informações da linha de origem.
bp main - Defina o ponto de interrupção inicial no início do módulo.
l+t - O passo será feito por linha de origem.
Selecione Debug>Source Mode para entrar no modo source, 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 - Execute 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 reconstruindo o projeto e reinstalando o driver. Esse ponto de interrupção será acionado cada vez 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: Você pode querer manter uma cópia do driver Sysvad sem o ponto de interrupção adicionado para trabalho de laboratório adicional.
Defina uma quebra 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 reconstruir o driver no Microsoft Visual Studio e reinstalá-lo na máquina de destino. Certifique-se de desinstalar o driver existente antes de instalar o driver atualizado.
Limpe todos os pontos de interrupção anteriores e certifique-se de que o depurador está ligado ao PC de destino.
Quando o código é executado e atinge a instrução, a
DebugBreakexecuçã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 do depurador para exibir variáveis.
Pode ser útil examinar variáveis à medida que o código é executado para confirmar se o código está funcionando conforme o esperado. Este laboratório examina variáveis à medida que o controlador de áudio gera som.
Use o comando dv para examinar as variáveis de ambiente associadas ao 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.
-> Sobre o sistema alvo
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 host
Quando o arquivo de mídia é reproduzido, o ponto de interrupção deve ser acionado e a execução do código do driver no sistema de destino deve parar.
Breakpoint 1 hit tabletaudiosample!CMiniportWaveRT::NewStream: fffff801`177dffc0 44894c2420 mov dword ptr [rsp+20h],r9dA janela do código-fonte deve destacar a chaveta 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 (Display NatVis Expression) que permite detalhar 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 da memória de uma variável global digitando ? <nome> da variável.
0: kd> ? signalProcessingMode Evaluate expression: -52768896396472 = ffffd001`c8acd348Isso retorna o local da memória da variável, neste caso ffffd001'c8acd348. Você pode exibir o conteúdo do local da memória despejando o valor desse local digitando o comando dd usando o local da 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
Utilize o item do menu Ver>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 cerca de 10 linhas no código até realçar 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, como esperado, os valores são diferentes da última vez que executamos esse comando, pois foi executado um código adicional que altera 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ê visualizará pilhas de chamadas para examinar o código do chamador/destinatário.
A pilha de chamadas é a cadeia de chamadas de função que levaram à localização atual do contador do programa. A função superior na pilha de chamadas é a função atual, e a próxima função é a função que chamou a função atual, e assim por diante.
Para exibir a pilha de chamadas, use os comandos k*:
KB |
Exibe a pilha e os três primeiros parâmetros. |
kp |
Mostra as pilhas e a lista completa de parâmetros. |
KN |
Permite que você veja a pilha com as informações do quadro ao lado dela. |
Se quiser manter a pilha de chamadas disponível, selecione Exibir>pilha de chamadas para visualizá-la. Selecione as colunas na parte superior da janela para alternar a exibição de informações adicionais.
Esta saída mostra a pilha de chamadas ao depurar o código do adaptador de exemplo em um estado de interrupção.
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 do 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 envolvido na reprodução de som.Para mais informações, consulte !process
A saída mostra que o processo está associado a 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 host
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. Este tópico estava suportando a 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 de 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, o ID do processo é ffffe001d147c840.
Registe o ID do processo associado ao audiodg.exe no seu PC para utilizar mais tarde neste laboratório. ________________________
...
PROCESS ffffe001d147c840
SessionId: 0 Cid: 10f0 Peb: ee6cf8a000 ParentCid: 0434
DirBase: d2122000 ObjectTable: ffffc0001f191ac0 HandleCount: <Data Not Accessible>
Image: audiodg.exe
...
Digite g no depurador para executar o código até que o clipe de mídia termine de ser reproduzido. Em seguida, entre no depurador, pressionando Ctrl+ScrLk (Ctrl+Break) Use o comando !process para confirmar que agora 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 que foi associado a audiodg.exe. No exemplo, o ID do processo é ffffe001d147c840. Substitua o ID do processo no exemplo pelo ID do processo que registou 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 visualizar 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 threads associados ao media player, reproduza o clipe de mídia novamente. Se o ponto de interrupção descrito na seção anterior ainda estiver em vigor, você parará no contexto de audiodg.exe.
Use o !thread -1 0 para exibir informações breves para o thread atual. Isso mostra o endereço da thread, as IDs da thread e do processo, o endereço do TEB (bloco de ambiente de thread), o endereço da função Win32 (se houver) para o qual a thread foi criada para executar, e o estado de agendamento da 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. Devem ser apresentadas informações semelhantes às seguintes.
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
Digite g no depurador para executar o código até que o clipe de mídia termine de ser reproduzido. Em seguida, entre no depurador, pressionando Ctrl - ScrLk (Ctrl-Break) Use o comando !thread para confirmar que agora você está executando um 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 efetivamente não corresponde ao nome da imagem associado à reprodução do clipe de mídia.
Observação Para definir o thread atual, digite .thread <thread number>.
Para obter mais informações sobre threads e processos, consulte as seguintes referências:
Seção 11: IRQL, registros e desmontagem
Ver o IRQL guardado
Na Seção 11, você exibirá o IRQL e o conteúdo das regsisters.
<- No sistema host
O nível de solicitação de interrupção (IRQL) é usado para gerenciar a prioridade do serviço de interrupção. Cada processador tem uma configuração IRQL que os threads podem aumentar ou diminuir. As interrupções que ocorrem na configuração IRQL do processador ou abaixo dela são mascaradas e não interferirão na operação atual. As interrupções que ocorrem acima da configuração IRQL do processador têm precedência sobre a operação atual. A extensão !irql exibe o nível de solicitação de interrupção (IRQL) no processador atual do computador de destino antes da interrupção do depurador. Quando o computador de destino ativa o depurador, o IRQL muda, mas o IRQL que estava ativo pouco antes da interrupção do depurador é salvo e exibido pelo !irql.
0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)
< Ver os registos e desmontagem
Ver os registos
Exiba o conteúdo dos registradores para o thread atual no processador atual usando o comando r (Registers ).
0: kd> r
rax=000000000000c301 rbx=ffffe00173eed880 rcx=0000000000000001
rdx=000000d800000000 rsi=ffffe00173eed8e0 rdi=ffffe00173eed8f0
rip=fffff803bb757020 rsp=ffffd001f01f8988 rbp=ffffe00173f0b620
r8=000000000000003e r9=ffffe00167a4a000 r10=000000000000001e
r11=ffffd001f01f88f8 r12=0000000000000000 r13=ffffd001f01efdc0
r14=0000000000000001 r15=0000000000000000
iopl=0 nv up ei pl nz na pe nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000202
nt!DbgBreakPointWithStatus:
fffff803`bb757020 cc int 3
Em alternativa, pode mostrar os conteúdos dos registos selecionando Ver>Registos.
A visualização do conteúdo dos registos pode ser útil ao analisar a execução de código em linguagem assembly e em outros cenários. Para mais informações, ver r (Registos).
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 visualizar o código em linguagem assembly que está a ser executado, selecionando Exibir>Desmontagem.
Para obter mais informações sobre desmontagem de linguagem de montagem, consulte Desmontagem x86 anotada e Desmontagem x64 anotada.
Seção 12: Trabalhar com memória
Na Seção 12, você usará comandos do depurador para exibir o conteúdo da memória.
Ver 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 a memória digitando um dos seguintes comandos de endereço< d*>.
dB |
Exibe dados em valores de byte 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 palavras (2 bytes) e caracteres ASCII. |
Observação Se você tentar exibir um endereço inválido, seu conteúdo será mostrado como pontos de interrogação (?).
Como alternativa, você pode visualizar a memória selecionando Exibir>memória. Use o menu suspenso 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 disparar 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 disparar 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 área de notificações. 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 Ver>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 para a 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 mostrar o valor no endereço de memória de IVolume usando o comando dt (Display Type).
kd> dt dt lVolume Local var @ 0xffffb780b7eee664 Type long 0n0Como a variável ainda não foi definida, ela não contém informações.
Pressione F10 para avançar para a última linha de código em SetDeviceChannelVolume.
return ntStatus;Exiba o valor no local da memória de IVolume usando o comando dt (Display Type).
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 da 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 primeiros quatro 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 a memória, você pode usar os comandos e* para alterar o conteúdo da memória.
| Comando | Descrição |
|---|---|
EA |
String ASCII (não terminada por NULL) |
UE |
Cadeia de caracteres Unicode (não terminada por NULL |
Ew |
Valores do Word (2 bytes) |
Eza |
Cadeia de caracteres ASCII terminada por NULL |
Ezu |
Cadeia de caracteres Unicode terminada por NULL |
EB |
Valores de byte |
Ed |
Valores de palavras duplas (4 bytes) |
O exemplo a seguir mostra como substituir a memória.
Primeiro, localize o endereço do lVolume que é usado no código de exemplo.
kd> ? lVolume Evaluate expression: -79711507126684 = ffffb780`b7eee664Substitua esse endereço de memória por novos caracteres usando o comando eb .
kd> eb 0xffffb780`b7eee664 11 11 11 11 11Exiba o local da memória para confirmar que 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 uma janela de observação ou locais. Para a janela de observação, você pode ver variáveis que estão fora de contexto do quadro atual. Modificá-los não é relevante se não estiverem no contexto.
Seção 13: Encerrar a sessão do WinDbg
<-No sistema host
Se quiseres deixar o depurador ligado, mas quiseres trabalhar no destino, remove todos os pontos de interrupção usando bc *, para que o computador de destino não tente se conectar ao depurador do computador anfitrião. Em seguida, use o comando g para permitir que o computador de destino seja executado novamente.
Para encerrar a sessão de depuração, no sistema host, entre no depurador e digite o comando qd (Sair e Desanexar) ou selecione Parar Depuração no menu.
0: kd> qd
Para obter mais informações, consulte Encerrando 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 estão disponíveis sobre a depuração do Windows. 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
Advanced Windows Debugging por Mario Hewardt e Daniel Pravat
Dentro do Windows Debugging: Um guia prático de estratégias de depuração e rastreamento no Windows® por Tarik Soulami
Windows Internals por Pavel Yosifovich, Alex Ionescu, Mark Russinovich e David Solomon
Vídeo
As ferramentas de desfragmentação mostram os episódios 13-29 do WinDbg: </shows/defrag-tools/>
Fornecedores de Treinamento:
OSR - https://www.osr.com/