Compartilhar via


Depuração de Drivers – Guia Passo a Passo (Modo Kernel do Sysvad)

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:

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.

Diagrama mostrando dois computadores conectados por meio de um hub/roteador de rede.

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

  1. 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 . . . . . . . . . :
  1. Registre o endereço IP do sistema de host: ______________________________________

  2. Registre o nome do host do sistema: ______________________________________

-> No sistema de destino

  1. 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.

  1. 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.

  1. 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

  2. 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
  1. 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.

  1. 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.

Captura de tela do Alerta de Segurança do Windows indicando que o Firewall do Windows bloqueou alguns recursos de um aplicativo.

<- No sistema hospedeiro

  1. 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 
  1. 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.

Captura de tela do Depurador do Windows exibindo a saída da janela de comando de uma conexão de kernel dinâmica.

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.

  1. 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.
  2. 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 .

  1. 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.

Captura de tela do aplicativo de Ajuda do Depurador exibindo ajuda para o comando .prefer-dml.

Exibir a versão do Windows no sistema de destino

  1. 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

  1. 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.

  1. 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

    Captura de tela do repositório GitHub exibindo a pasta geral e o botão Baixar ZIP.

    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

  2. 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.

    Captura de tela do Visual Studio com o arquivo adapter.cpp carregado do projeto Sysvad.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  1. 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.
  2. 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.

  1. Habilitar controladores assinados para teste

    Para habilitar a capacidade de executar drivers assinados de teste:

    1. Abra as Configurações do Windows.

    2. Em Atualização e Segurança, selecione Recuperação.

    3. Em Inicialização Avançada, selecione Reiniciar Agora.

    4. Quando o computador for reiniciado, selecione Solucionar problemas.

    5. Em seguida, selecione Opções avançadas, Configurações de Inicialização e, em seguida, selecione Reiniciar.

    6. Selecione Desabilitar a imposição da assinatura do driver pressionando a tecla F7 .

    7. O computador começará com os novos valores em vigor.

  2. -> 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.

    Captura de tela do Aviso de Segurança do Windows informando que o Windows não pode verificar o publicador.

    Dica

     Se você tiver problemas com a instalação, verifique o arquivo a seguir para obter mais informações. %windir%\inf\setupapi.dev.log

    Para 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_TabletAudioSample

  3. Examinar 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.

    Captura de tela da árvore do Gerenciador de Dispositivos com a Amostra de Dispositivo de Áudio Virtual para Tablet realçada.

    Depois de instalar com êxito o driver de exemplo, agora você está pronto para testá-lo.

Testar o driver de áudio do Sysvad

  1. 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.

  2. 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.

  3. 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

  1. 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.1sp3yo9yz874p
    
  2. Use Ctrl+Break (Bloqueio de Rolagem) para interromper o código em execução no sistema de destino.

Definir o caminho do símbolo

  1. Para definir o caminho dos símbolos para o servidor de símbolos da Microsoft no ambiente WinDbg, use o comando .symfix .

    0: kd> .symfix
    
  2. Para 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 /f
    

    Nota 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

  1. 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.

  2. 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.

  3. 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).

  4. 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.pdb
    
  5. Use 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

  1. 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…
    ...
    
  2. Use Ctrl+F para pesquisar na saída gerada para procurar o nome do driver do dispositivo, sysvad.

    Encontre a caixa de diálogo com o termo 'sysvad' inserido no campo de pesquisa.

    Haverá uma entrada de nó de dispositivo com um nome sysvad_TabletAudioSample presente 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.

  3. Use o !devnode 0 1 sysvad_TabletAudioSample comando 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)
    
  4. 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.
    
  5. 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!PnpHandler
    
  6. Insira 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.

Diagrama de uma árvore de nós do dispositivo que consiste em aproximadamente 20 nós.

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).

  1. 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.

  2. Adicione a localização do seu código local ao caminho de origem digitando o seguinte comando.

    .sympath+ C:\WDK_Samples\Sysvad
    
  3. Adicione o local do símbolo local ao caminho do símbolo digitando o comando a seguir.

    .sympath+ C:\WDK_Samples\Sysvad
    
  4. Definir 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 0xFFFFFFFF
    
  5. Defina 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.

  6. 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!AddDevice
    
  7. Reinicie a execução de código no sistema de destino digitando o comando go g.

  8. -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.

  9. 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.

  10. <- 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],rdx
    

    Se 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;
    } // AddDevice
    
  11. Passo 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.

  12. 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.

  1. <- 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.

  2. Desmarque os pontos de interrupção anteriores usando bc *.

  3. 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"
    
  4. 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::MixerVolumeWrite
    
  5. Reinicie a execução de código no sistema de destino digitando o comando go g.

  6. 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.

  7. 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],r9d
    

    Você deve parar nessa linha em common.cpp

    {
        if (m_pHW)
        {
            m_pHW->SetMixerVolume(Index, Channel, Value);
        }
    } // MixerVolumeWrite
    
  8. Use 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 = 0n24
    
  9. Pressione a tecla F10 para executar o código passo a passo.

  10. 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+t comando 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.

  1. 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;
    } // AddDevice
    
  2. Siga 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.

  3. Limpe os pontos de interrupção anteriores e confirme se o depurador está anexado ao computador de destino.

  4. 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.

  1. Use o comando dv para examinar as variáveis de local associadas a tabletaudiosample!CMiniportWaveRT::New*.

    kd> dv tabletaudiosample!CMiniportWaveRT::New*
    
  2. Limpar os pontos de interrupção anteriores

    bc *
    
  3. 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"
    
  4. Reinicie a execução de código no sistema de destino digitando o comando go g.

  5. -> 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.

  6. <- 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],r9d
    

    A 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.
    
    --*/
    {
    
    ...
    
  7. 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`00000200
    
  8. Usar 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]              : 0xff
    
  9. Variá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`c8acd348
    
  10. Isso 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 ffffe000
    
  11. Você 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 ffffe000
    
  12. Exibir 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.

    Interface do WinDbg exibindo variáveis locais do código de exemplo e janelas de comandos.

  13. 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);
        }
    
    ...
    
  14. 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.

Interface WinDbg exibindo a janela de pilha de chamadas.

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 !process para 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:

threads e processos

Alterando contextos

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>.

Captura de tela da janela de registros do WinDbg exibindo aproximadamente 12 registros.

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.

Captura de tela da janela de desmontagem do WinDbg mostrando código de linguagem de assembly.

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.

Captura de tela da janela de memória de exibição do WinDbg com várias opções de formato de exibição.

  1. 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 *
    
  2. 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"
    
  3. 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"
    
  4. 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],r9d
    
  5. Use o item de menu Exibir>Local para exibir variáveis locais. Observe o valor atual da variável IVolume.

  6. 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-6291456
    
  7. O 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;
    }
    
  8. 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
    0n0
    

    Como a variável ainda está para ser definida, ela não contém informações.

  9. Pressione F10 para avançar até a última linha de código em SetDeviceChannelVolume.

        return ntStatus;
    
  10. 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-6291456
    

    Agora que a variável está ativa, um valor de 6291456 é exibido neste exemplo.

  11. Você também pode exibir o local de memória do IVolume usando o ? (Avaliar expressão) comando.

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  12. O 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 00000002
    
  13. Você 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 c52d7008
    
  14. Para 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.

  1. Primeiro, localize o endereço do lVolume usado no código de exemplo.

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  2. Substitua esse endereço de memória com novos caracteres usando o comando eb .

    kd> eb 0xffffb780`b7eee664 11 11 11 11 11
    
  3. Exiba 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/

Consulte Também

Introdução à Depuração do Windows