Partilhar via


Debug Drivers - Laboratório Passo a Passo (Modo Kernel Sysvad)

Este laboratório fornece exercícios práticos que demonstram como depurar o driver de dispositivo de modo kernel de áudio Sysvad.

O Microsoft Windows Debugger (WinDbg) é uma poderosa ferramenta de depuração baseada no Windows que você pode usar para executar depuração no modo de usuário e no modo kernel. O WinDbg fornece depuração no nível de origem para o kernel do Windows, drivers de modo kernel e serviços do sistema, bem como aplicativos e drivers de modo de usuário.

O WinDbg pode percorrer o código-fonte, definir pontos de interrupção, exibir variáveis (incluindo objetos C++), rastreamentos de pilha e memória. A janela de comandos do depurador permite ao utilizador emitir uma ampla variedade de comandos.

Configuração do laboratório

Você precisará do seguinte hardware para concluir o laboratório:

  • Um laptop ou computador desktop (host) executando o Windows 10
  • Um laptop ou computador desktop (destino) executando o Windows 10
  • Um hub/router de rede e cabos de rede para ligar os dois PCs
  • Acesso à internet para baixar arquivos de símbolos

Você precisará do seguinte software para poder concluir o laboratório.

  • Microsoft Visual Studio 2017
  • Kit de Desenvolvimento de Software (SDK) do Windows para Windows 10
  • Kit de driver do Windows (WDK) para Windows 10
  • O driver de áudio Sysvad de exemplo para Windows 10

Para obter informações sobre como baixar e instalar o WDK, consulte Baixar o Kit de Driver do Windows (WDK).

Passo a passo de depuração do Sysvad

Este laboratório orienta você através do processo de depuração de um driver de modo kernel. Os exercícios usam o exemplo de driver de áudio virtual Syvad. Como o driver de áudio Syvad não interage com o hardware de áudio real, ele pode ser usado na maioria dos dispositivos. O laboratório abrange as seguintes tarefas:

Laboratório de driver do Echo

O driver Echo é um driver mais simples do que o driver de áudio Sysvad. Se você é novo no WinDbg, você pode querer considerar primeiro completar o Debug Universal Drivers - Step-by-Step Lab (modo kernel Echo). Este laboratório reutiliza as instruções de configuração desse laboratório, portanto, se você tiver concluído esse laboratório, poderá pular as seções 1 e 2 aqui.

Seção 1: Conectar-se a uma sessão WinDbg de modo kernel

Na Seção 1, você configurará a depuração de rede no host e no sistema de destino.

Os PCs neste laboratório precisam ser configurados para usar uma ligação de rede Ethernet para a resolução de problemas do kernel.

Este laboratório utiliza dois computadores. WinDbg é executado no sistema host e o driver Sysvad é executado no sistema de destino .

Use um hub/roteador de rede e cabos de rede para conectar os dois PCs.

Diagrama mostrando dois PCs conectados através de um hub/roteador de rede.

Para trabalhar com aplicativos de modo kernel e usar o WinDbg, recomendamos que você use o transporte KDNET over Ethernet. Para obter informações sobre como usar o protocolo de transporte Ethernet, consulte Introdução ao WinDbg (Kernel-Mode). Para obter mais informações sobre como configurar o computador de destino, consulte Preparando um computador para implantação manual de driver e Configurando a depuração automática do kernel da rede KDNET.

Configurar depuração de modo kernel usando ethernet

Para habilitar a depuração no modo kernel no sistema de destino, execute as etapas a seguir.

<- No sistema host

  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 host: ______________________________________

  2. Registe o nome do host do sistema: ______________________________________

-> Sobre o sistema alvo

  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ê gravou em vez de 169.182.1.1 que é mostrado na saída de exemplo.
C:\> ping 169.182.1.1

Pinging 169.182.1.1 with 32 bytes of data:
Reply from 169.182.1.1: bytes=32 time=1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255

Ping statistics for 169.182.1.1:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 1ms, Average = 0ms

Para usar o utilitário KDNET para habilitar a depuração em modo kernel no sistema de destino, execute as etapas a seguir.

  1. No sistema host, localize o diretório WDK KDNET. Por padrão, ele está localizado aqui.

    C:\Arquivos de programas (x86)\Windows Kits\10\Debuggers\x64

Este laboratório pressupõe que ambos os PCs estão executando uma versão de 64 bits do Windows, tanto no destino quanto no host. Se esse não for o caso, a melhor abordagem é executar no host ferramentas com a mesma arquitetura (número de bits) que está a ser utilizada no destino. Por exemplo, se o destino estiver executando o Windows de 32 bits, execute uma versão 32 do depurador no host. Para obter mais informações, consulte Escolhendo as ferramentas de depuração de 32 bits ou 64 bits.

  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 da Linha de Comandos enquanto Administrador. Insira este comando para validar se a NIC no PC de destino é suportada.

C:\KDNET>kdnet

Network debugging is supported on the following NICs:
busparams=0.25.0, Intel(R) 82579LM Gigabit Network Connection, KDNET is running on this NIC.kdnet.exe
  1. Digite este comando para definir o endereço IP do sistema host. Use o endereço IP real do sistema host que você gravou em vez de 169.182.1.1 que é mostrado na saída de exemplo. Escolha um endereço de porta exclusivo para cada par de destino/host com o qual você trabalha, como 50010.
C:\>kdnet 169.182.1.1 50010

Enabling network debugging on Intel(R) 82577LM Gigabit Network Connection.
Key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

Importante

Antes de usar o BCDEdit para alterar as informações de inicialização, talvez seja necessário suspender temporariamente os recursos de segurança do Windows, como BitLocker e Inicialização Segura, no computador de teste. Reative esses recursos de segurança quando o teste estiver concluído e gerencie adequadamente o computador de teste, quando os recursos de segurança estiverem desativados. A inicialização segura normalmente é desativada na UEFI. Para acessar a configuração UEFI, Use Sistema, Recuperação, Inicialização avançada. Ao reiniciar, selecione Solução de problemas, Opções avançadas, Configurações de firmware UEFI. Tenha cuidado, pois definir incorretamente as opções de UEFI ou desativar o BitLocker pode tornar o sistema inoperante.

  1. Digite este comando para confirmar se o dbgsettings está definido corretamente.
C:\> bcdedit /dbgsettings
busparams               0.25.0
key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
debugtype               NET
hostip                  169.182.1.1
port                    50010
dhcp                    Yes
The operation completed successfully.

Copie a chave exclusiva gerada automaticamente em um arquivo de texto, para evitar ter que digitá-la no PC host. Copie o arquivo de texto com a chave para o sistema host.

NotaFirewalls e debuggers

Se receber uma mensagem pop-up do firewall e desejar usar o depurador, marque todas as três caixas.

Captura de ecrã do Alerta de Segurança do Windows a indicar que a Firewall do Windows bloqueou algumas funcionalidades de uma aplicação.

<- No sistema host

  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 do WinDbg.exe do Kit de Driver do Windows (WDK) que foi instalado como parte da instalação do kit do Windows.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 
  1. Inicie o WinDbg com depuração de usuário remoto usando o seguinte comando. O valor da chave e da porta corresponde ao que você definiu anteriormente usando o BCDEdit no destino.
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

->No sistema alvo

Reinicialize o sistema de destino.

<-No sistema host

Em um ou dois minutos, a saída de depuração deve ser exibida no sistema anfitrião.

Captura de ecrã do Depurador do Windows exibindo a saída da janela de comando de uma conexão em tempo real com o kernel.

A janela Comando do Depurador é a principal janela de informações de depuração no WinDbg. Pode introduzir comandos do depurador e visualizar os resultados dos comandos nesta janela.

A Janela de Comando do Depurador é dividida em dois painéis. Digite comandos no painel menor (o painel de entrada de comando) na parte inferior da janela e visualize a saída do comando no painel maior na parte superior da janela.

No painel de entrada de comandos, use as teclas de seta para cima e seta para baixo para percorrer o histórico de comandos. Quando um comando aparece, você pode editá-lo ou pressionar ENTER para executá-lo.

Seção 2: Comandos e técnicas de depuração do modo kernel

Na Seção 2, você usará comandos de depuração para exibir informações sobre o sistema de destino.

<- No sistema host

Habilite a DML (Debugger Markup Language) com .prefer_dml

Alguns comandos de depuração exibem texto usando a linguagem de marcação do depurador que você pode selecionar para coletar rapidamente mais informações.

  1. Use Ctrl+Break (Scroll Lock) no WinDBg para entrar no código em execução no sistema de destino. Pode levar um pouco de tempo para o sistema de destino responder.
  2. Digite o seguinte comando para habilitar o DML na janela de comando do depurador.
0: kd> .prefer_dml 1
DML versions of commands on by default

Use .hh para obter ajuda

Você pode acessar a ajuda do comando de referência usando o comando .hh .

  1. Digite o seguinte comando para exibir a ajuda de referência de comando para .prefer_dml.
    0: kd> .hh .prefer_dml
    

O arquivo de ajuda do Depurador exibirá a ajuda para o comando .prefer_dml .

Captura de ecrã da aplicação 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 do sistema de destino digitando o comando vertarget (Show Target Computer Version) na janela WinDbg.
0: kd> vertarget
Windows 10 Kernel Version 9926 MP (4 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 9926.0.amd64fre.fbl_awesome1501.150119-1648
Machine Name: ""
Kernel base = 0xfffff801`8d283000 PsLoadedModuleList = 0xfffff801`8d58aef0
Debug session time: Fri Feb 20 10:15:17.807 2015 (UTC - 8:00)
System Uptime: 0 days 01:31:58.931

Listar os módulos carregados

  1. Você pode verificar se está trabalhando com o processo correto do modo kernel exibindo os módulos carregados digitando o comando lm (List Loaded Modules) na janela WinDbg.
0: Kd> lm
start             end                 module name
fffff801`09200000 fffff801`0925f000   volmgrx    (no symbols)           
fffff801`09261000 fffff801`092de000   mcupdate_GenuineIntel   (no symbols)           
fffff801`092de000 fffff801`092ec000   werkernel   (export symbols)       werkernel.sys
fffff801`092ec000 fffff801`0934d000   CLFS       (export symbols)       CLFS.SYS
fffff801`0934d000 fffff801`0936f000   tm         (export symbols)       tm.sys
fffff801`0936f000 fffff801`09384000   PSHED      (export symbols)       PSHED.dll
fffff801`09384000 fffff801`0938e000   BOOTVID    (export symbols)       BOOTVID.dll
fffff801`0938e000 fffff801`093f7000   spaceport   (no symbols)           
fffff801`09400000 fffff801`094cf000   Wdf01000   (no symbols)           
fffff801`094d9000 fffff801`09561000   CI         (export symbols)       CI.dll
...

Observação A saída que foi omitida é indicada com "... " neste laboratório.

Como ainda não definimos o caminho do símbolo e os símbolos carregados, informações limitadas estão disponíveis no depurador.

Seção 3: Baixe e construa o driver de áudio Sysvad

Na Seção 3, você baixará e construirá o driver de áudio Sysvad.

Normalmente, você estaria trabalhando com seu próprio código de driver quando você usa WinDbg. Para se familiarizar com a depuração de drivers de áudio, o driver de amostra de áudio virtual Sysvad é usado. Este exemplo é usado para ilustrar como você pode executar uma única etapa através do código nativo do modo kernel. Essa técnica pode ser muito valiosa para depurar problemas complexos de código no modo kernel.

Para baixar e criar o driver de áudio de exemplo Sysvad, execute as etapas a seguir.

  1. Baixe e extraia o exemplo de áudio do Sysvad do GitHub

    Você pode usar um navegador para visualizar o exemplo Sysvad e Readme.md arquivo aqui:

    https://github.com/Microsoft/Windows-driver-samples/tree/main/audio/sysvad

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

    Este laboratório, mostra como baixar as amostras de driver universal em um arquivo zip.

    a) Transfira o ficheiro master.zip para o seu disco rígido local.

    https://github.com/Microsoft/Windows-driver-samples/archive/master.zip

    b) Selecione e segure (ou clique com o botão direito do mouse) Windows-driver-samples-master.zipe escolha Extrair tudo. Especifique uma nova pasta ou navegue até uma pasta existente que armazenará os arquivos extraídos. Por exemplo, você pode especificar C:\WDK_Samples\ como a nova pasta na qual os arquivos são extraídos.

    c. Depois que os arquivos forem extraídos, navegue até a seguinte subpasta.

    C:\WDK_Samples\Sysvad

  2. Abra a solução de driver no Visual Studio

    No VisualStudio, selecione >/Solução de Arquivo>... e navegue até a pasta que contém os arquivos extraídos (por exemplo, C:\WDK_Samples\Sysvad). Clique duas vezes no arquivo de solução Syvad .

    No Visual Studio, localize o Gerenciador de Soluções. (Se ainda não estiver aberto, escolha Gerenciador de Soluções no menu Exibir .) No Gerenciador de Soluções, você pode ver uma solução que tem vários projetos.

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

  3. Definir a configuração e a plataforma da amostra

    No Gerenciador de Soluções, selecione e segure (ou clique com o botão direito do mouse) Solução 'sysvad' (7 de 7 projetos) e escolha Configuration Manager. Certifique-se de que a configuração e as configurações da plataforma são as mesmas para os quatro projetos. Por padrão, a configuração é definida como "Win10 Debug", e a plataforma é definida como "Win64" para todos os projetos. Se você fizer alterações de configuração e/ou plataforma para um projeto, deverá fazer as mesmas alterações para os três projetos restantes.

    Observação Este laboratório assume que o Windows de 64 bits está a ser utilizado. Se você estiver usando o Windows de 32 bits, crie o driver para 32 bits.

  4. Verificar a assinatura do driver

    Encontre o TabletAudioSample. Abra a página de propriedades do driver Sysvad e verifique se o Modo de Assinatura do Driver está definido como Assinatura de Teste.

  5. As amostras de driver precisam ser modificadas para usar valores que não se sobreponham com os drivers existentes. Consulte Do Código de Exemplo ao Driver de Produção - O que Alterar nos Exemplos sobre como criar um exemplo exclusivo de driver que coexistirá com os drivers reais já instalados no Windows.

  6. Criar o exemplo usando o Visual Studio

    No Visual Studio, seleccione Construir>Construir Solução.

    As janelas de compilação devem exibir uma mensagem indicando que a compilação para todos os seis projetos foi bem-sucedida.

Sugestão

Se você encontrar uma mensagem de erro de compilação, use o número de erro de compilação para determinar uma correção. Por exemplo, erro MSBuild MSB8040 descreve como trabalhar com bibliotecas de espectro atenuado.

  1. Localize os arquivos de driver construídos

    No Explorador de Ficheiros, navegue até à pasta que contém os ficheiros extraídos para o exemplo. Por exemplo, você navegaria até C:\WDK_Samples\Sysvad, se essa for a pasta especificada anteriormente. Dentro dessa pasta, o local dos arquivos de driver compilados varia dependendo da configuração e das definições de plataforma selecionadas no Configuration Manager. Por exemplo, se você deixou as configurações padrão inalteradas, os arquivos de driver compilados serão salvos em uma pasta chamada \x64\Debug para uma compilação de depuração de 64 bits.

    Navegue até a pasta que contém os arquivos criados para o driver TabletAudioSample:

    C:\WDK_Samples\Sysvad\TabletAudioSample\x64\Debug. A pasta conterá o driver TabletAudioSample .SYS, o ficheiro de símbolo pdp e o ficheiro inf. Você também precisará localizar as dlls e os arquivos de símbolo DelayAPO, KWSApo e KeywordDetectorContosoAdapter.

    Para instalar o driver, você precisará dos seguintes arquivos.

    Nome do ficheiro Descrição
    TabletAudioSample.sys O arquivo do driver.
    TabletAudioSample.pdb O ficheiro de símbolo do driver.
    tabletaudiosample.inf Um arquivo de informações (INF) que contém informações necessárias para instalar o driver.
    KeywordDetectorContosoAdapter.dll Um detetor de palavras-chave de exemplo.
    KeywordDetectorContosoAdapter.pdb O arquivo de símbolo do detetor de palavras-chave de exemplo.
    DelayAPO.dll Uma amostra atrasa APO.
    DelayAPO.pdb O arquivo de símbolo de atraso APO.
    KWSApo.dll Um exemplo de detector de palavras-chave APO.
    KWSApo.pdb O ficheiro de símbolos do detetor de palavras-chave.
    TabletAudioSample.cer O arquivo de certificado TabletAudioSample.
  2. Localize um pen drive USB ou configure um compartilhamento de rede para copiar os arquivos de driver construídos do host para o sistema de destino.

Na próxima seção, você copiará o código para o sistema de destino e instalará e testará o driver.

Seção 4: Instalar o exemplo de driver de áudio Sysvad no sistema de destino

Na Seção 4, você usará o devcon para instalar o driver de áudio Sysvad.

-> Sobre o sistema alvo

O computador onde você instala o driver é chamado de computador de destino ou o computador de teste . Normalmente, este é um computador separado do computador no qual você desenvolve e compila o pacote de driver. O computador onde o utilizador desenvolve e compila o driver é chamado de computador host.

O processo de mover o pacote de driver para o computador de destino e instalar o driver é chamado de implantar o driver.

Antes de implantar um driver, você deve preparar o computador de destino ativando a assinatura de teste. Depois disso, você estará pronto para executar o exemplo de driver construído no sistema de destino.

Para instalar o driver no sistema de destino, execute as seguintes etapas.

  1. Ativar drivers assinados de teste

    Para habilitar a capacidade de executar drivers assinados de teste:

    1. Abra as Configurações do Windows.

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

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

    4. Quando o PC reiniciar, selecione Resolução de problemas.

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

    6. Selecione a opção Desativar a imposição de assinatura do driver ao premir a tecla F7.

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

  2. -> Sobre o sistema alvo

    Instale o driver

    As instruções a seguir mostram como instalar e testar o driver de exemplo.

    O arquivo INF necessário para instalar este driver é TabletAudioSample.inf. No computador de destino, abra uma janela da Linha de Comandos enquanto Administrador. Navegue até a pasta do pacote de driver, clique com o botão direito do mouse no arquivo TabletAudioSample.inf e selecione Instalar.

    Uma caixa de diálogo será exibida indicando que o driver de teste é um driver não assinado. Selecione Instalar este driver mesmo assim para continuar.

    Captura de ecrã do Aviso de Segurança do Windows indicando que o Windows não consegue verificar o editor.

    Sugestão

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

    Para obter instruções mais detalhadas, consulte Configuração de um computador para a implantação, teste e depuração de controladores.

    O arquivo INF contém o ID de hardware para instalar o tabletaudiosample.sys. Para o exemplo Syvad, o ID de hardware é: root\sysvad_TabletAudioSample

  3. Examine o driver no Gestor de dispositivos

    No computador de destino, em uma janela do Prompt de Comando, digite devmgmt para abrir o Gerenciador de Dispositivos. No Gerenciador de dispositivos, no menu Exibir, selecione Dispositivos por tipo.

    Na árvore de dispositivos, localize Virtual Audio Device (WDM) - Tablet Sample no nó Dispositivo de áudio. Isso geralmente encontra-se sob o nó Controladores de som, vídeo e jogos. Confirme se ele está instalado e ativo.

    Selecione o driver para o hardware real no PC no Gestor de Dispositivos. Em seguida, selecione e segure (ou clique com o botão direito do mouse) o driver e selecione desativar para desativar o driver.

    Confirme no Gerenciador de dispositivos que o driver de hardware de áudio exibe a seta para baixo, indicando que ele está desativado.

    Captura de ecrã da árvore do Gestor de Dispositivos com o Exemplo de Tablet de Dispositivo de Áudio Virtual realçado.

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

Teste o driver de áudio Sysvad

  1. No computador de destino, em uma janela do Prompt de Comando, digite devmgmt para abrir o Gerenciador de Dispositivos. No Gestor de Dispositivos, no menu Visualizar, selecione Dispositivos por tipo. Na árvore de dispositivos, localize Virtual Audio Device (WDM) - Tablet Sample.

  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 Dispositivo de áudio virtual (WDM) - Amostra de tablet e, em seguida, selecione Definir padrão, mas não selecione OK. Isso manterá a caixa de diálogo Som aberta.

  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 driver de Virtual Audio Device (WDM) - Tablet Sample.

Seção 5: Usar WinDbg para exibir informações sobre o driver

Na Seção 5, você definirá o caminho do símbolo e usará os comandos do depurador do kernel para exibir informações sobre o driver de exemplo Sysvad.

Os símbolos permitem que o WinDbg exiba informações adicionais, como nomes de variáveis, que podem ser inestimáveis durante a depuração. WinDbg usa os formatos de símbolo de depuração do Microsoft Visual Studio para depuração a nível de código-fonte. Ele pode acessar qualquer símbolo ou variável de um módulo que tenha arquivos de símbolos PDB.

Para carregar o depurador, execute as seguintes etapas.

<-No sistema host

  1. Se você fechou o depurador, abra-o novamente usando o seguinte comando na janela do prompt de comando do administrador. Substitua a chave e a porta pelo que você configurou anteriormente.

    C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Use Ctrl+Break (Scroll Lock) para quebrar o código em execução no sistema de destino.

Definir o caminho do símbolo

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

    0: kd> .symfix
    
  2. Para adicionar a localização dos símbolos locais para usar os seus símbolos locais, adicione o caminho usando .sympath+ e, em seguida, .reload /f.

    0: kd> .sympath+ C:\WDK_Samples\Sysvad
    0: kd> .reload /f
    

    Observação O comando .reload com a opção /f force exclui todas as informações de símbolos do módulo especificado e recarrega os símbolos. Em alguns casos, este comando também recarrega ou descarrega o próprio módulo.

Observação Você deve carregar os símbolos adequados para usar a funcionalidade avançada que o WinDbg fornece. Se você não tiver símbolos configurados corretamente, receberá mensagens indicando que os símbolos não estão disponíveis quando você tentar usar a funcionalidade que depende de símbolos.

0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.

ObservaçãoServidores de símbolos

Há uma série de abordagens que podem ser usadas para trabalhar com símbolos. Em muitas situações, pode configurar o PC para aceder a símbolos a partir de um servidor de símbolos que a Microsoft fornece quando são necessários. Este passo a passo pressupõe que essa abordagem será usada. Se os símbolos em seu ambiente estiverem em um local diferente, modifique as etapas para usar esse local. Para obter informações adicionais, consulte Caminho de símbolos para o depurador do Windows.

ObservaçãoCompreender os requisitos do símbolo do código-fonte

Para executar a depuração de origem, você deve criar uma versão verificada (depuração) de seus binários. O compilador criará arquivos de símbolos (arquivos .pdb). Esses arquivos de símbolo mostrarão ao depurador como as instruções binárias correspondem às linhas de origem. Os próprios arquivos de origem também devem estar acessíveis ao depurador.

Os arquivos de símbolo não contêm o texto do código-fonte. Para depuração, é melhor se o linker não otimize o seu código. A depuração de origem e o acesso a variáveis locais são mais difíceis e, às vezes, quase impossíveis, se o código tiver sido otimizado. Se você estiver tendo problemas para visualizar variáveis locais ou linhas de origem, defina as seguintes opções de compilação.

definir COMPILE_DEBUG=1

Definir ENABLE_OPTIMIZER=0

  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 os símbolos de itens que começam com a letra a.

  3. Como o DML está habilitado, alguns elementos da saída são hot links que você pode selecionar. Selecione o link de dados na saída de depuração para exibir informações sobre símbolos de itens que começam com a letra a.

    0: kd> x /D /f tabletaudiosample!a*
     A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    
    fffff806`9adb1000 tabletaudiosample!AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)
    

    Para obter informações, consulte x (Examinar símbolos).

  4. A extensão !lmi exibe informações detalhadas sobre um módulo. Digite !lmi tabletaudiosample. O seu resultado deve ser semelhante ao texto mostrado abaixo.

    0: kd> !lmi tabletaudiosample
    Loaded Module Info: [tabletaudiosample] 
             Module: tabletaudiosample
       Base Address: fffff8069ad90000
         Image Name: tabletaudiosample.sys
       Machine Type: 34404 (X64)
         Time Stamp: 58ebe848 Mon Apr 10 13:17:12 2017
               Size: 48000
           CheckSum: 42df7
    Characteristics: 22  
    Debug Data Dirs: Type  Size     VA  Pointer
                 CODEVIEW    a7,  e5f4,    d1f4 RSDS - GUID: {5395F0C5-AE50-4C56-AD31-DD5473BD318F}
                   Age: 1, Pdb: C:\Windows-driver-samples-master\audio\sysvad\TabletAudioSample\x64\Debug\TabletAudioSample.pdb
                       ??   250,  e69c,    d29c [Data not mapped]
         Image Type: MEMORY   - Image read successfully from loaded memory.
        Symbol Type: PDB      - Symbols loaded successfully from image header.
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
           Compiler: Resource - front end [0.0 bld 0] - back end [14.0 bld 24210]
        Load Report: private symbols & lines, not source indexed 
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
    
  5. Use a extensão !dh para exibir informações de cabeçalho como mostrado abaixo.

    0: kd> !dh tabletaudiosample 
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
        8664 machine (X64)
           9 number of sections
    5669DE8A time date stamp Thu Dec 10 12:20:26 2015
    
           0 file pointer to symbol table
           0 number of symbols
          F0 size of optional header
          22 characteristics
                Executable
                App can handle >2gb addresses
    ...
    

Seção 6: Exibindo informações da árvore de dispositivos Plug and Play

Na Seção 6, você exibirá informações sobre o driver de dispositivo de exemplo Sysvad e onde ele reside na árvore de dispositivos Plug and Play.

As informações sobre o driver de dispositivo na árvore de dispositivos Plug and Play podem ser úteis para solucionar problemas. Por exemplo, se um driver de dispositivo não for residente na árvore de dispositivos, pode haver um problema com a instalação do driver de dispositivo.

Para obter mais informações sobre a extensão de depuração do nó do dispositivo, consulte !devnode.

<-No sistema host

  1. Para ver todos os nós do dispositivo na árvore de dispositivos Plug and Play, digite o comando !devnode 0 1 . Este comando pode levar um ou dois minutos para ser executado. Durante esse tempo, "*Busy" será exibido na área de status do WinDbg.

    0: kd> !devnode 0 1
    Dumping IopRootDeviceNode (= 0xffffe0005a3a8d30)
    DevNode 0xffffe0005a3a8d30 for PDO 0xffffe0005a3a9e50
      InstancePath is "HTREE\ROOT\0"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe0005a3a3d30 for PDO 0xffffe0005a3a4e50
        InstancePath is "ROOT\volmgr\0000"
        ServiceName is "volmgr"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeEnumerateCompletion (0x30d)
        DevNode 0xffffe0005a324560 for PDO 0xffffe0005bd95ca0…
    ...
    
  2. Use Ctrl+F para procurar na saída gerada o nome do driver de dispositivo, sysvad.

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

    Uma entrada de nó de dispositivo com um nome de sysvad_TabletAudioSample será apresentada na saída !devnode para Syvad.

      DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
        InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
        ServiceName is "sysvad_tabletaudiosample"
        State = DeviceNodeStarted (0x308)
    ...
    

    Observe que o endereço PDO e o endereço DevNode são exibidos.

  3. Use o !devnode 0 1 sysvad_TabletAudioSample comando para exibir informações Plug and Play associadas ao nosso driver de dispositivo Sysvad.

    0: kd> !devnode 0 1 sysvad_TabletAudioSample
    Dumping IopRootDeviceNode (= 0xffffe00082df8d30)
    DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
      InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe000897fb650 for PDO 0xffffe00089927e30
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{64097438-cdc0-4007-a19e-62e789062e20}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00086d2f5f0 for PDO 0xffffe00089939ae0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{78880f4e-9571-44a4-a9df-960bde446487}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00089759bb0 for PDO 0xffffe000875aa060
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{7cad07f2-d0a0-4b9b-8100-8dc735e9c447}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00087735010 for PDO 0xffffe000872068c0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{fc38551b-e69f-4b86-9661-ae6da78bc3c6}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088457670 for PDO 0xffffe0008562b830
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{0894b831-c9fe-4c56-86a6-092380fc5628}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000893dbb70 for PDO 0xffffe00089d68060
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{15eb6b5c-aa54-47b8-959a-0cff2c1500db}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088e6f250 for PDO 0xffffe00089f6e990
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{778c07f0-af9f-43f2-8b8d-490024f87239}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000862eb4b0 for PDO 0xffffe000884443a0
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{e4b72c7c-be50-45df-94f5-0f2922b85983}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
    
  4. A saída exibida no comando anterior inclui o PDO associado à instância em execução do nosso driver, neste exemplo é 0xffffe00089c575a0. Digite o comando !devobj<PDO address> para exibir as informações Plug and Play associadas ao driver de dispositivo Sysvad. Use o endereço DOP que !devnode exibe no seu PC, não o mostrado aqui.

    0: kd> !devobj 0xffffe00089c575a0
    Device object (ffffe00089c575a0) is for:
    0000004e \Driver\PnpManager DriverObject ffffe00082d47e60
    Current Irp 00000000 RefCount 65 Type 0000001d Flags 00001040
    SecurityDescriptor ffffc102b0f6d171 DevExt 00000000 DevObjExt ffffe00089c576f0 DevNode ffffe00086e68190 
    ExtensionFlags (0000000000)  
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe00088386a50 \Driver\sysvad_tabletaudiosample
    Device queue is not busy.
    
  5. A saída exibida no comando !devobj inclui o nome do dispositivo conectado: \Driver\sysvad_tabletaudiosample. Use o comando !drvobj com uma máscara de bits de 2 para exibir informações associadas ao dispositivo conectado.

    0: kd> !drvobj \Driver\sysvad_tabletaudiosample 2
    Driver object (ffffe0008834f670) is for:
    \Driver\sysvad_tabletaudiosample
    DriverEntry:   fffff80114b45310  tabletaudiosample!FxDriverEntry
    DriverStartIo: 00000000 
    DriverUnload:  fffff80114b5fea0                tabletaudiosample!DriverUnload
    AddDevice:     fffff80114b5f000  tabletaudiosample!AddDevice
    
    Dispatch routines:
    [00] IRP_MJ_CREATE                      fffff80117b49a20             portcls!DispatchCreate
    [01] IRP_MJ_CREATE_NAMED_PIPE           fffff8015a949a00          nt!IopInvalidDeviceRequest
    [02] IRP_MJ_CLOSE                       fffff80115e26f90                ks!DispatchCleanup
    [03] IRP_MJ_READ                        fffff80115e32710                ks!DispatchRead
    [04] IRP_MJ_WRITE                       fffff80115e327e0              ks!DispatchWrite
    [05] IRP_MJ_QUERY_INFORMATION           fffff8015a949a00         nt!IopInvalidDeviceRequest
    [06] IRP_MJ_SET_INFORMATION             fffff8015a949a00              nt!IopInvalidDeviceRequest
    [07] IRP_MJ_QUERY_EA                    fffff8015a949a00         nt!IopInvalidDeviceRequest
    [08] IRP_MJ_SET_EA                      fffff8015a949a00              nt!IopInvalidDeviceRequest
    [09] IRP_MJ_FLUSH_BUFFERS               fffff80115e32640  ks!DispatchFlush
    [0a] IRP_MJ_QUERY_VOLUME_INFORMATION    fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0b] IRP_MJ_SET_VOLUME_INFORMATION      fffff8015a949a00               nt!IopInvalidDeviceRequest
    [0c] IRP_MJ_DIRECTORY_CONTROL           fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0d] IRP_MJ_FILE_SYSTEM_CONTROL         fffff8015a949a00         nt!IopInvalidDeviceRequest
    [0e] IRP_MJ_DEVICE_CONTROL              fffff80115e27480               ks!DispatchDeviceIoControl
    [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     fffff8015a949a00   nt!IopInvalidDeviceRequest
    [10] IRP_MJ_SHUTDOWN                    fffff8015a949a00      nt!IopInvalidDeviceRequest
    [11] IRP_MJ_LOCK_CONTROL                fffff8015a949a00  nt!IopInvalidDeviceRequest
    [12] IRP_MJ_CLEANUP                     fffff8015a949a00           nt!IopInvalidDeviceRequest
    [13] IRP_MJ_CREATE_MAILSLOT             fffff8015a949a00               nt!IopInvalidDeviceRequest
    [14] IRP_MJ_QUERY_SECURITY              fffff80115e326a0 ks!DispatchQuerySecurity
    [15] IRP_MJ_SET_SECURITY                fffff80115e32770      ks!DispatchSetSecurity
    [16] IRP_MJ_POWER                       fffff80117b3dce0            portcls!DispatchPower
    [17] IRP_MJ_SYSTEM_CONTROL              fffff80117b13d30              portcls!PcWmiSystemControl
    [18] IRP_MJ_DEVICE_CHANGE               fffff8015a949a00 nt!IopInvalidDeviceRequest
    [19] IRP_MJ_QUERY_QUOTA                 fffff8015a949a00  nt!IopInvalidDeviceRequest
    [1a] IRP_MJ_SET_QUOTA                   fffff8015a949a00       nt!IopInvalidDeviceRequest
    [1b] IRP_MJ_PNP                         fffff80114b5f7d0 tabletaudiosample!PnpHandler
    
  6. Digite o comando !devstack<PDO address> para exibir as informações Plug and Play associadas ao driver de dispositivo. A saída exibida no comando !devnode 0 1 inclui o endereço DOP associado à instância em execução do nosso driver. Neste exemplo, é 0xffffe00089c575a0. Use o endereço DOP que !devnode exibe no seu PC, não o mostrado abaixo.

    0: kd> !devstack 0xffffe00089c575a0
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe00088d212e0  \Driver\ksthunk    ffffe00088d21430  0000007b
      ffffe00088386a50  \Driver\sysvad_tabletaudiosampleffffe00088386ba0  0000007a
    > ffffe00089c575a0  \Driver\PnpManager 00000000  0000004e
    !DevNode ffffe00086e68190 :
      DeviceInst is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
    

A saída mostra que temos uma pilha de driver de dispositivo muito simples. O driver sysvad_TabletAudioSample é um componente do nó PnPManager. O PnPManager é um nó raiz.

Este diagrama mostra uma árvore de nós de dispositivo mais complexa.

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

Observação Para obter mais informações sobre pilhas de drivers mais complexas, consulte Pilhas de driver e Nós de dispositivo e pilhas de dispositivos.

Secção 7: Trabalhar com pontos de interrupção

Na Seção 7, você trabalhará com pontos de interrupção para interromper a execução de código em pontos específicos.

Definindo pontos de interrupção usando comandos

Os pontos de interrupção são usados para interromper a execução de código em uma linha de código específica. Em seguida, você pode avançar no código a partir desse ponto, para depurar essa seção específica do código.

Para definir um ponto de interrupção usando um comando debug, use um dos seguintes comandos b .

BP

Define um ponto de interrupção que ficará ativo até que o módulo em que ele está seja descarregado.

bu

Define um ponto de interrupção que não é resolvido quando o módulo é descarregado e reativa quando o módulo é recarregado.

BM

Define um ponto de interrupção para um símbolo. Este comando utilizará bu ou bp de forma adequada e permite que caracteres universais * sejam usados para definir pontos de interrupção em todos os símbolos que correspondem (como todos os métodos em uma classe).

  1. Use a interface do usuário do WinDbg para confirmar se oModo de Origem de> está habilitado na sessão WinDbg atual.

  2. Adicione o seu código local ao caminho de origem inserindo o seguinte comando.

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

    .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) onde você deseja definir o ponto de interrupção, separado por um ponto de exclamação.

    0: kd> bm tabletaudiosample!AddDevice
    breakpoint 1 redefined
      1: fffff801`14b5f000 @!"tabletaudiosample!AddDevice"
    

    Você pode usar sintaxe diferente em conjunto com variáveis de configuração como <módulo>!<symbol>, <class>::<method>,'<file.cpp>:<line number>', ou ignore um número de vezes <condição><#>. Para obter mais informações, consulte Usando pontos de interrupção.

  6. Liste os pontos de interrupção atuais para confirmar que o ponto de interrupção foi definido digitando o comando bl .

    0: kd> bl
    1 e fffff801`14b5f000     0001 (0001) tabletaudiosample!AddDevice
    
  7. Reinicie a execução de código no sistema de destino digitando o comando go g.

  8. ->No sistema alvo

    No Windows, abra o Gerenciador de Dispositivos usando o ícone ou digitando mmc devmgmt.msc. No Gestor de dispositivos, expanda o nó Controladores de som, vídeo e jogos. Selecione e segure (ou clique com o botão direito do mouse) a entrada do driver de áudio virtual e selecione Desativar no menu.

  9. Selecione e segure (ou clique com o botão direito do mouse) a entrada do driver de áudio virtual novamente e selecione Ativar no menu.

  10. <- No sistema host

    Isso deve fazer com que o Windows recarregue o driver, que chama AddDevice. Isso fará com que o ponto de interrupção do debugger AddDevice seja acionado e a execução do código do driver no sistema de destino seja suspensa.

    Breakpoint 1 hit
    tabletaudiosample!AddDevice:
    fffff801`14baf000 4889542410      mov     qword ptr [rsp+10h],rdx
    

    Se o caminho de origem estiver configurado corretamente, deves parar na rotina AddDevice em adapter.cpp

    {
        PAGED_CODE();
    
        NTSTATUS        ntStatus;
        ULONG           maxObjects;
    
        DPF(D_TERSE, ("[AddDevice]"));
    
        maxObjects = g_MaxMiniports;
    
        #ifdef SYSVAD_BTH_BYPASS
        // 
        // Allow three (3) Bluetooth hands-free profile devices.
        //
        maxObjects += g_MaxBthHfpMiniports * 3; 
        #endif // SYSVAD_BTH_BYPASS
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
        return ntStatus;
    } // AddDevice
    
  11. Percorra o código linha a linha digitando o comando p ou pressionando F10. Você pode avançar do código sysvad AddDevice para PpvUtilCall, PnpCallAddDevice e, em seguida, para o código do Windows PipCallDriverAddDevice. Você pode fornecer um número para o comando p para avançar várias linhas, por exemplo p 5.

  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

executar (quando a CPU executa uma instrução a partir do endereço)

r

leitura/gravação (quando a CPU lê ou grava para o endereço)

w

escrever (quando a CPU grava no endereço)

Observe que você só pode definir quatro pontos de interrupção de dados a qualquer momento e cabe a você certificar-se de que está alinhando seus dados corretamente ou não acionará o ponto de interrupção (as palavras devem terminar em endereços divisíveis por 2, dwords devem ser divisíveis por 4 e quadwords por 0 ou 8)

Por exemplo, para definir um ponto de interrupção de leitura/gravação em um endereço de memória específico, use um comando como este.

ba r 4 fffff800`7bc9eff0

Modificando o estado do ponto de interrupção

Você pode modificar os pontos de interrupção existentes usando os seguintes comandos.

BL

Lista os pontos de interrupção.

BC

Remove um ponto de interrupção da lista. Use bc * para limpar todos os pontos de interrupção.

BD

Desabilita um ponto de interrupção. Use bd * para desativar todos os pontos de interrupção.

ser

Permite um ponto de interrupção. Use be * para ativar todos os pontos de interrupção.

Como alternativa, você também pode modificar os pontos de interrupção selecionando editar>pontos de interrupção. Observe que a caixa de diálogo ponto de interrupção só funciona com pontos de interrupção existentes. Novos pontos de interrupção devem ser definidos a partir da linha de comando.

Definir um ponto de interrupção no MixerVolume

Diferentes partes do código do driver de áudio são chamadas para responder aos vários eventos, após o driver de dispositivo ser carregado. Na próxima seção, definimos um ponto de interrupção que será acionado quando o usuário ajustar o controle de volume para o driver de áudio virtual.

Para definir um ponto de interrupção no MixerVolume, execute as seguintes etapas.

  1. <- No sistema host

    Para localizar o método que altera o volume, use o comando x para listar os símbolos em CAdapterCommon, que contêm o volume da cadeia de caracteres.

    kd> x tabletaudiosample!CAdapterCommon::*
    ...
    fffff800`7bce26a0 tabletaudiosample!CAdapterCommon::MixerVolumeWrite (unsigned long, unsigned long, long)
    …
    

    Use CTRL+F para procurar por volume para cima na saída e localizar o método MixerVolumeWrite.

  2. Limpe os pontos de interrupção anteriores utilizando o comando 'bc *'.

  3. Defina um ponto de interrupção de símbolo na rotina CAdapterCommon::MixerVolumeWrite usando o seguinte comando.

    kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite
      1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"
    
  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 Controlo, selecione Hardware e Som>. Selecione e segure (ou clique com o botão direito do mouse) Exemplo de Descrição do coletor e selecione Propriedades. Selecione a guia Níveis . Ajuste o volume do controle deslizante.

  7. Isso deve fazer com que o ponto de interrupção de depuração SetMixerVolume seja acionado e a execução do código do driver no sistema de destino seja interrompida.

    kd> g
    Breakpoint 1 hit
    tabletaudiosample!CAdapterCommon::MixerVolumeWrite:
    fffff801`177b26a0 44894c2420      mov     dword ptr [rsp+20h],r9d
    

    Você deve parar nesta 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 F10 para percorrer o código em uma única etapa.

  10. Pressione F5 para concluir a execução do código MixerVolumeWrite.

Resumo - Percorrer o código a partir da janela de comando do depurador

A seguir estão os comandos que você pode usar para percorrer seu código (com os atalhos de teclado associados mostrados entre parênteses).

  • Break in (Ctrl+Break) - Este comando interromperá um sistema enquanto o sistema estiver em execução e estiver em comunicação com o WinDbg (a sequência no Depurador do Kernel é Ctrl+C).

  • Step over (F10) – Este comando faz com que a execução de código prossiga uma instrução ou uma declaração de cada vez. Se uma chamada for encontrada, a execução de código ignora a chamada sem entrar na rotina chamada. (Se a linguagem de programação for C ou C++ e o WinDbg estiver no modo de origem, o modo de origem poderá ser ativado ou desativado usando Debug>Modo de origem).

  • Step in (F11) – Este comando é como step-over, exceto que a execução de uma chamada entra na rotina chamada.

  • Step out (Shift+F11) – Este comando faz com que a execução seja executada e saia da rotina atual (local atual na pilha de chamadas). Isso é útil se você já viu o suficiente da rotina.

  • Executar para o cursor (F7 ou Ctrl+F10) – Coloque o cursor numa janela de origem ou desmontagem onde pretende que a execução seja interrompida e, em seguida, prima F7; A execução do código será executada até esse ponto. Observe que, se o fluxo de execução de código não atingir o ponto indicado pelo cursor (por exemplo, uma instrução IF não for executada), o WinDbg não será quebrado, porque a execução do código não atingiu o ponto indicado.

  • Executar (F5) – Executar até que um ponto de interrupção seja encontrado ou um evento como uma verificação de bug ocorra.

Opções avançadas

  • Definir instruções para a linha atual (Ctrl+Shift+I) – Em uma janela de origem, você pode colocar o cursor em uma linha, inserir esse atalho de teclado e a execução do código começará a partir desse ponto assim que você permitir que ele prossiga (por exemplo, usando F5 ou F10). Isso é útil se você quiser repetir uma sequência, mas requer alguns cuidados. Por exemplo, registros e variáveis não são definidos para o que seriam se a execução de código tivesse atingido essa linha naturalmente.

  • Configuração direta do registro eip -- Você pode colocar um valor no registro eip e, assim que pressionar F5 (ou F10, F11, etc.), a execução começa a partir desse endereço. Isto é semelhante a definir a instrução para a linha atual designada pelo cursor, com a diferença de que se especifica o endereço de uma instrução de assembly.

É mais fácil percorrer a interface de utilizador em vez da linha de comando, portanto, este método é recomendado. Se necessário, os seguintes comandos podem ser usados para percorrer um arquivo de origem na linha de comando:

  • .lines - Habilitar informações da linha de origem.

  • bp main - Defina o ponto de interrupção inicial no início do módulo.

  • l+t - O passo será feito por linha de origem.

  • Selecione Debug>Source Mode para entrar no modo source, o L+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 - Execute uma linha de código fonte.

Para obter mais informações, consulte Depuração de código-fonte no WinDbg (Clássico) na documentação de referência de depuração.

Definir pontos de interrupção no código

Você pode definir um ponto de interrupção no código adicionando a DebugBreak() instrução e reconstruindo o projeto e reinstalando o driver. Esse ponto de interrupção será acionado cada vez que o driver estiver habilitado, portanto, seria uma técnica a ser usada nos estágios iniciais de desenvolvimento, não no código de produção. Essa técnica não é tão flexível quanto definir dinamicamente pontos de interrupção usando os comandos de ponto de interrupção.

Dica: Você pode querer manter uma cópia do driver Sysvad sem o ponto de interrupção adicionado para trabalho de laboratório adicional.

  1. Defina uma quebra para ocorrer sempre que o método AddDevice for executado, adicionando a DebugBreak() instrução ao código de exemplo.

    ...
        // Insert the DebugBreak() statment before the  PcAddAdapterDevice is called.
        //
    
        DebugBreak()
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
    
        return ntStatus;
    } // AddDevice
    
  2. Siga todas as etapas descritas anteriormente para reconstruir o driver no Microsoft Visual Studio e reinstalá-lo na máquina de destino. Certifique-se de desinstalar o driver existente antes de instalar o driver atualizado.

  3. Limpe todos os pontos de interrupção anteriores e certifique-se de que o depurador está ligado ao PC de destino.

  4. Quando o código é executado e atinge a instrução, a DebugBreak 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 do depurador para exibir variáveis.

Pode ser útil examinar variáveis à medida que o código é executado para confirmar se o código está funcionando conforme o esperado. Este laboratório examina variáveis à medida que o controlador de áudio gera som.

  1. Use o comando dv para examinar as variáveis de ambiente associadas ao 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. -> Sobre o sistema alvo

    Localize um pequeno arquivo de mídia (como o arquivo de som de notificação do Windows com uma extensão de arquivo .wav) e selecione o arquivo para reproduzi-lo. Por exemplo, você pode usar Ring05.wav localizado no diretório Windows\Media.

  6. <- No sistema host

    Quando o arquivo de mídia é reproduzido, o ponto de interrupção deve ser acionado e a execução do código do driver no sistema de destino deve parar.

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::NewStream:
    fffff801`177dffc0 44894c2420      mov     dword ptr [rsp+20h],r9d
    

    A janela do código-fonte deve destacar a chaveta na entrada da função NewStream.

    /*++
    
    Routine Description:
    
      The NewStream function creates a new instance of a logical stream 
      associated with a specified physical channel. Callers of NewStream should 
      run at IRQL PASSIVE_LEVEL.
    
    Arguments:
    
      OutStream -
    
      OuterUnknown -
    
      Pin - 
    
      Capture - 
    
      DataFormat -
    
    Return Value:
    
      NT status code.
    
    --*/
    {
    
    ...
    
  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 (Display NatVis Expression) que permite detalhar estruturas de dados aninhadas.

    0: kd> dx -r1 (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380))
    (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) :  [Type: CMiniportWaveRT]
        [+0x020] m_lRefCount      : 0
        [+0x028] m_pUnknownOuter  : 0xffffe001d1477e50 : [Type: IUnknown *]
        [+0x030] m_ulLoopbackAllocated : 0x2050
        [+0x034] m_ulSystemAllocated : 0x180
        [+0x038] m_ulOffloadAllocated : 0x0
        [+0x03c] m_dwCaptureAllocatedModes : 0x0
    
    0: kd> dx -r1 (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : {487E9220-E000-FFFF-30F1-D24900E0FFFF} [Type: _GUID]
        [<Raw View>]    
    
    0: kd> dx -r1 -n (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) :  [Type: _GUID]
        [+0x000] Data1            : 0x487e9220
        [+0x004] Data2            : 0xe000
        [+0x006] Data3            : 0xffff
        [+0x008] Data4            :  [Type: unsigned char [8]]
    
    0: kd> dx -r1 -n (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350))
    (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) :  [Type: unsigned char [8]]
        [0]              : 0x30
        [1]              : 0xf1
        [2]              : 0xd2
        [3]              : 0x49
        [4]              : 0x0
        [5]              : 0xe0
        [6]              : 0xff
        [7]              : 0xff
    
  9. Variáveis globais

    Você pode encontrar o local da memória de uma variável global digitando ? <nome> da variável.

    0: kd> ? signalProcessingMode
    Evaluate expression: -52768896396472 = ffffd001`c8acd348
    
  10. Isso retorna o local da memória da variável, neste caso ffffd001'c8acd348. Você pode exibir o conteúdo do local da memória despejando o valor desse local digitando o comando dd usando o local da memória retornado pelo comando anterior.

    0: kd> dd ffffd001`c8acd348
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 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

    Utilize o item do menu Ver>Locais para exibir variáveis locais. Essa interface também fornece essa capacidade de detalhar estruturas de dados mais complexas.

    Interface WinDbg exibindo locais de código de exemplo e janelas de comando.

  13. Use p ou F10 para avançar cerca de 10 linhas no código até realçar a linha de código ntStatus = IsFormatSupported(Pin, Capture, DataFormat);.

        PAGED_CODE();
    
        ASSERT(OutStream);
        ASSERT(DataFormat);
    
        DPF_ENTER(("[CMiniportWaveRT::NewStream]"));
    
        NTSTATUS                    ntStatus = STATUS_SUCCESS;
        PCMiniportWaveRTStream      stream = NULL;
        GUID                        signalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
    
        *OutStream = NULL;
    
         //
        // If the data format attributes were specified, extract them.
        //
        if ( DataFormat->Flags & KSDATAFORMAT_ATTRIBUTES )
        {
            // The attributes are aligned (QWORD alignment) after the data format
            PKSMULTIPLE_ITEM attributes = (PKSMULTIPLE_ITEM) (((PBYTE)DataFormat) + ((DataFormat->FormatSize + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
            ntStatus = GetAttributesFromAttributeList(attributes, attributes->Size, &signalProcessingMode);
        }
    
        // Check if we have enough streams.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = ValidateStreamCreate(Pin, Capture, signalProcessingMode);
        }
    
        // Determine if the format is valid.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = IsFormatSupported(Pin, Capture, DataFormat);
        }
    
    ...
    
  14. Use o comando dv para exibir os nomes e valores de todas as variáveis locais para um determinado quadro. Observe que, como esperado, os valores são diferentes da última vez que executamos esse comando, pois foi executado um código adicional que altera as variáveis locais e algumas variáveis agora não estão no quadro atual ou seus valores foram alterados.

    2: kd> dv
                    this = 0xffffe001`d1182000
               OutStream = 0xffffe001`d4776d20
            OuterUnknown = 0xffffe001`d4776bc8
                     Pin = 0
                 Capture = 0x00 '
              DataFormat = 0xffffe001`cd7609b0
    signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
                ntStatus = 0n0
                  stream = 0x00000000`00000000
    

Seção 9: Exibir pilhas de chamadas

Na Seção 9, você visualizará pilhas de chamadas para examinar o código do chamador/destinatário.

A pilha de chamadas é a cadeia de chamadas de função que levaram à localização atual do contador do programa. A função superior na pilha de chamadas é a função atual, e a próxima função é a função que chamou a função atual, e assim por diante.

Para exibir a pilha de chamadas, use os comandos k*:

KB

Exibe a pilha e os três primeiros parâmetros.

kp

Mostra as pilhas e a lista completa de parâmetros.

KN

Permite que você veja a pilha com as informações do quadro ao lado dela.

Se quiser manter a pilha de chamadas disponível, selecione Exibir>pilha de chamadas para visualizá-la. Selecione as colunas na parte superior da janela para alternar a exibição de informações adicionais.

Interface WinDbg exibindo a janela da pilha de chamadas.

Esta saída mostra a pilha de chamadas ao depurar o código do adaptador de exemplo em um estado de interrupção.

0: kd> kb
# RetAddr           : Args to Child                                                           : Call Site
00 fffff800`7a0fa607 : ffffe001`d1182000 ffffe001`d4776d20 ffffe001`d4776bc8 ffffe001`00000000 : tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
01 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d122bb10 ffffe001`ceb81750 ffffe001`d173f058 : portcls!CPortPinWaveRT::Init+0x2e7
02 fffff800`7a0fc7f9 : ffffe001`d4776bc0 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
04 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
05 fffff800`7bd314b1 : ffffe001`d122bb10 ffffd001`c3098590 ffffe001`d122bd90 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
06 fffff803`cda1bfa8 : 00000000`00000024 00000000`00000000 00000000`00000000 ffffe001`d122bb10 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 fffff803`cda7b306 : 00000000`000001f0 ffffe001`d48ce690 ffffe001`d13d6400 ffffe001`d13d64c0 : nt!IopParseDevice+0x7c8
08 fffff803`cda12916 : 00000000`000001f0 ffffd001`c30988d0 ffffe001`d13d6490 fffff803`cda7b250 : nt!IopParseFile+0xb6
09 fffff803`cda1131c : ffffe001`d2ccb001 ffffd001`c30989e0 00ffffe0`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
0a fffff803`cd9fedb8 : ffffe001`00000001 ffffe001`d48ce690 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
0b fffff803`cd9fe919 : 000000ee`6d1fc8d8 000000ee`6d1fc788 000000ee`6d1fc7e0 000000ee`6d1fc7d0 : nt!IopCreateFile+0x3d8
0c fffff803`cd752fa3 : ffffc000`1f296870 fffff803`cd9d9fbd ffffd001`c3098be8 00000000`00000000 : nt!NtCreateFile+0x79
0d 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
0e 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
0f 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
10 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
11 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

Você pode usar o DML para explorar ainda mais o código. Quando você seleciona a primeira entrada 00, o comando .frame (Definir Contexto Local) é usado para definir o contexto e, em seguida, o comando dv (Exibir Variáveis Locais) exibe as variáveis locais.

0: kd> .frame 0n0;dv /t /v
00 ffffd001`c30981d0 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
ffffd001`c30982b0 class CMiniportWaveRT * this = 0xffffe001`d1182000
ffffd001`c30982b8 struct IMiniportWaveRTStream ** OutStream = 0xffffe001`d4776d20
ffffd001`c30982c0 struct IPortWaveRTStream * OuterUnknown = 0xffffe001`d4776bc8
ffffd001`c30982c8 unsigned long Pin = 0
ffffd001`c30982d0 unsigned char Capture = 0x00 '
ffffd001`c30982d8 union KSDATAFORMAT * DataFormat = 0xffffe001`cd7609b0
ffffd001`c3098270 struct _GUID signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
ffffd001`c3098210 long ntStatus = 0n0
ffffd001`c3098218 class CMiniportWaveRTStream * stream = 0x00000000`00000000

Seção 10: Exibir processos e threads

Na Seção 10, você usará comandos do depurador para exibir processos e threads.

Processo

Para alterar o contexto do processo atual, use o comando .process <process> . O exemplo a seguir demonstra como identificar um processo e alternar o contexto para ele.

  • Use o comando !process para exibir o processo atual envolvido na reprodução de som.

    Para mais informações, consulte !process

A saída mostra que o processo está associado a audiodg.exe. Se você ainda estiver no ponto de interrupção descrito na seção anterior deste tópico, o processo atual deverá ser associado à imagem audiodg.exe.

<- No sistema host

0: kd> !process
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 70 Clone 0 Private 504. Modified 16. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       <Invalid>
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.000
    QuotaPoolUsage[PagedPool]         81632
    QuotaPoolUsage[NonPagedPool]      9704
    Working Set Sizes (now,min,max)  (2154, 1814, 2109) (8616KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2101
    VirtualSize                       2097192 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2336
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1573

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject

        THREAD ffffe001ceb77080  Cid 10f0.16dc  Teb: 000000ee6cf8d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d112c840  Cid 10f0.0a4c  Teb: 000000ee6cf8f000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d16c7840  Cid 10f0.13c4  Teb: 000000ee6cf91000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001cec67840  Cid 10f0.0dbc  Teb: 000000ee6cf93000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001d1117840  Cid 10f0.1d6c  Teb: 000000ee6cf95000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001cdeae840  Cid 10f0.0298  Teb: 000000ee6cf97000 Win32Thread: 0000000000000000 RUNNING on processor 2

Observe que um dos threads associados a esse processo está no estado RUNNING. Este tópico estava suportando a reprodução do clipe de mídia quando o ponto de interrupção foi atingido.

Use o comando !process 0 0 para exibir informações resumidas de todos os processos. Na saída do comando, use CTRL+F para localizar a ID do processo associado à imagem audiodg.exe. No exemplo mostrado abaixo, o ID do processo é ffffe001d147c840.

Registe o ID do processo associado ao audiodg.exe no seu PC para utilizar mais tarde neste laboratório. ________________________

...

PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
...

Digite g no depurador para executar o código até que o clipe de mídia termine de ser reproduzido. Em seguida, entre no depurador, pressionando Ctrl+ScrLk (Ctrl+Break) Use o comando !process para confirmar que agora está executando um processo diferente.

!process
PROCESS ffffe001cd0ad040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa000  ObjectTable: ffffc00017214000  HandleCount: <Data Not Accessible>
    Image: System
    VadRoot ffffe001d402b820 Vads 438 Clone 0 Private 13417. Modified 87866. Locked 64.
    DeviceMap ffffc0001721a070
    Token                             ffffc00017216a60
    ElapsedTime                       05:04:54.716
    UserTime                          00:00:00.000
    KernelTime                        00:00:20.531
    QuotaPoolUsage[PagedPool]         0
    QuotaPoolUsage[NonPagedPool]      0
    Working Set Sizes (now,min,max)  (1720, 50, 450) (6880KB, 200KB, 1800KB)
    PeakWorkingSetSize                15853
    VirtualSize                       58 Mb
    PeakVirtualSize                   74 Mb
    PageFaultCount                    46128
   MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      66

        THREAD ffffe001cd0295c0  Cid 0004.000c  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0120  SynchronizationEvent

        THREAD ffffe001cd02a6c0  Cid 0004.0010  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0ba0  Semaphore Limit 0x7fffffff
...

A saída acima mostra que um processo de sistema diferente de ffffe001cd0ad040 está em execução. O nome da imagem mostra System, não audiodg.exe.

Agora use o comando !process para alternar para o processo que foi associado a audiodg.exe. No exemplo, o ID do processo é ffffe001d147c840. Substitua o ID do processo no exemplo pelo ID do processo que registou anteriormente.

0: kd> !process  ffffe001d147c840
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 60 Clone 0 Private 299. Modified 152. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       1 Day 01:53:14.490
    UserTime                          00:00:00.031
    KernelTime                        00:00:00.031
    QuotaPoolUsage[PagedPool]         81552
    QuotaPoolUsage[NonPagedPool]      8344
    Working Set Sizes (now,min,max)  (1915, 1814, 2109) (7660KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2116
    VirtualSize                       2097189 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2464
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1418

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      36             IdealProcessor: 0             
        UserTime                  00:00:00.015
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007ff7fb928de0
        Stack Init ffffd001c2ec6dd0 Current ffffd001c2ec60c0
        Base ffffd001c2ec7000 Limit ffffd001c2ec1000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d115c080  Cid 10f0.15b4  Teb: 000000ee6cf9b000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d0bf0640  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      1              IdealProcessor: 0             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c3143dd0 Current ffffd001c3143520
        Base ffffd001c3144000 Limit ffffd001c313e000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      518918         Ticks: 17616 (0:00:04:35.250)
        Context Switch Count      9              IdealProcessor: 1             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
        Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
        Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

Como esse código não está ativo, todos os threads estão no estado WAIT, conforme o esperado.

Tópicos

Os comandos para visualizar e definir threads são muito semelhantes aos dos processos. Use o comando !thread para exibir threads. Use .thread para definir os threads atuais.

Para explorar threads associados ao media player, reproduza o clipe de mídia novamente. Se o ponto de interrupção descrito na seção anterior ainda estiver em vigor, você parará no contexto de audiodg.exe.

Use o !thread -1 0 para exibir informações breves para o thread atual. Isso mostra o endereço da thread, as IDs da thread e do processo, o endereço do TEB (bloco de ambiente de thread), o endereço da função Win32 (se houver) para o qual a thread foi criada para executar, e o estado de agendamento da thread.

0: kd> !thread -1 0
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0

Para exibir mais informações sobre o thread em execução, digite !thread. Devem ser apresentadas informações semelhantes às seguintes.

0: kd> !thread
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
IRP List:
    ffffe001d429e580: (0006,02c8) Flags: 000008b4  Mdl: 00000000
Not impersonating
DeviceMap                 ffffc00019113080
Owning Process            ffffe001d147c840       Image:         audiodg.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      537630         Ticks: 0
Context Switch Count      63             IdealProcessor: 1             
UserTime                  00:00:00.000
KernelTime                00:00:00.015
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           : Args to Child                                                           : Call Site
ffffd001`c70c62a8 fffff800`7a0fa607 : ffffe001`d4aec5c0 ffffe001`cdefd3d8 ffffe001`d4aec5c0 ffffe001`cdefd390 : tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
ffffd001`c70c62b0 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d429e580 ffffe001`d4ea47b0 ffffe001`cdefd3d8 : portcls!CPortPinWaveRT::Init+0x2e7
ffffd001`c70c6340 fffff800`7a0fc7f9 : ffffe001`d4aec430 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
ffffd001`c70c63c0 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
ffffd001`c70c6450 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
ffffd001`c70c6510 fffff800`7bd314b1 : ffffe001`d429e580 ffffd001`c70c6590 ffffe001`d429e800 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
ffffd001`c70c6540 fffff803`cda1bfa8 : 00000000`00000025 00000000`00000000 00000000`00000000 ffffe001`d429e580 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
ffffd001`c70c65a0 fffff803`cda7b306 : 00000000`000002fc ffffe001`d5e0d510 00000000`00000000 ffffe001`d3341bd0 : nt!IopParseDevice+0x7c8
ffffd001`c70c6770 fffff803`cda12916 : 00000000`000002fc ffffd001`c70c68d0 ffffe001`d3341ba0 fffff803`cda7b250 : nt!IopParseFile+0xb6
ffffd001`c70c67d0 fffff803`cda1131c : ffffe001`ceb6c601 ffffd001`c70c69e0 00000000`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
ffffd001`c70c6970 fffff803`cd9fedb8 : ffff8ab8`00000001 ffffe001`d5e0d510 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
ffffd001`c70c6a90 fffff803`cd9fe919 : 000000ee`6d37c6e8 00000004`6d37c500 000000ee`6d37c5f0 000000ee`6d37c5e0 : nt!IopCreateFile+0x3d8
ffffd001`c70c6b40 fffff803`cd752fa3 : fffff6fb`7da05360 fffff6fb`40a6c0a8 fffff681`4d815760 ffff8ab8`92895e23 : nt!NtCreateFile+0x79
ffffd001`c70c6bd0 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`c70c6c40)
000000ee`6d37c568 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
000000ee`6d37c570 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
000000ee`6d37c578 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
000000ee`6d37c580 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

Use o comando k para exibir a pilha de chamadas associada ao thread.

0: kd> k
# Child-SP          RetAddr           Call Site
00 ffffd001`c70c62a8 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
01 ffffd001`c70c62b0 fffff800`7a0fb2c3 portcls!CPortPinWaveRT::Init+0x2e7
02 ffffd001`c70c6340 fffff800`7a0fc7f9 portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 ffffd001`c70c63c0 fffff800`7a180552 portcls!xDispatchCreate+0xd9
04 ffffd001`c70c6450 fffff800`7a109a9a ks!KsDispatchIrp+0x272
05 ffffd001`c70c6510 fffff800`7bd314b1 portcls!DispatchCreate+0x7a
06 ffffd001`c70c6540 fffff803`cda1bfa8 ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 ffffd001`c70c65a0 fffff803`cda7b306 nt!IopParseDevice+0x7c8
08 ffffd001`c70c6770 fffff803`cda12916 nt!IopParseFile+0xb6
09 ffffd001`c70c67d0 fffff803`cda1131c nt!ObpLookupObjectName+0x776
0a ffffd001`c70c6970 fffff803`cd9fedb8 nt!ObOpenObjectByNameEx+0x1ec
0b ffffd001`c70c6a90 fffff803`cd9fe919 nt!IopCreateFile+0x3d8
0c ffffd001`c70c6b40 fffff803`cd752fa3 nt!NtCreateFile+0x79
0d ffffd001`c70c6bd0 00007fff`69805b74 nt!KiSystemServiceCopyEnd+0x13
0e 000000ee`6d37c568 00007fff`487484e6 0x00007fff`69805b74
0f 000000ee`6d37c570 0000029b`00000003 0x00007fff`487484e6
10 000000ee`6d37c578 00000000`0000012e 0x0000029b`00000003
11 000000ee`6d37c580 00000000`00000000 0x12e

Digite g no depurador para executar o código até que o clipe de mídia termine de ser reproduzido. Em seguida, entre no depurador, pressionando Ctrl - ScrLk (Ctrl-Break) Use o comando !thread para confirmar que agora você está executando um thread diferente.

0: kd> !thread
THREAD ffffe001ce80b840  Cid 17e4.01ec  Teb: 00000071fa9b9000 Win32Thread: ffffe001d41690d0 RUNNING on processor 0
Not impersonating
DeviceMap                 ffffc0001974e2c0
Owning Process            ffffe001d1760840       Image:         rundll32.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      538040         Ticks: 0
Context Switch Count      3181840        IdealProcessor: 0             
UserTime                  00:00:08.250
KernelTime                00:00:10.796
Win32 Start Address 0x00007ff6d2f24270
Stack Init ffffd001cd16afd0 Current ffffd001cd16a730
Base ffffd001cd16b000 Limit ffffd001cd165000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5

Child-SP          RetAddr           : Args to Child                                                           : Call Site
fffff803`cf373d18 fffff800`7a202852 : fffff803`cf373e60 00000000`00000001 ffffe001`cf4ed330 00000000`0000ffff : nt!DbgBreakPointWithStatus
fffff803`cf373d20 fffff803`cd6742c6 : ffffe001`cf4ed2f0 fffff803`cf373e60 00000000`00000001 00000000`0004e4b8 : kdnic!TXSendCompleteDpc+0x142
fffff803`cf373d60 fffff803`cd74d495 : 00000000`00000000 fffff803`cd923180 fffff803`cde1f4b0 fffff901`40669010 : nt!KiRetireDpcList+0x5f6
fffff803`cf373fb0 fffff803`cd74d2a0 : 00000000`00000090 0000000e`0000006a 00000000`00000092 00000000`00000000 : nt!KxRetireDpcList+0x5 (TrapFrame @ fffff803`cf373e70)
ffffd001`cd16a6c0 fffff803`cd74bd75 : 00000000`00000000 fffff803`cd74a031 00000000`00000000 00000000`00000000 : nt!KiDispatchInterruptContinue
ffffd001`cd16a6f0 fffff803`cd74a031 : 00000000`00000000 00000000`00000000 ffffe001`cff4d2a0 fffff803`cd67738e : nt!KiDpcInterruptBypass+0x25
ffffd001`cd16a700 fffff960`50cdb5a4 : fffff901`400006d0 00000000`00000001 fffff901`40000d60 ffffd001`cd16a9f0 : nt!KiInterruptDispatchNoLockNoEtw+0xb1 (TrapFrame @ ffffd001`cd16a700)
ffffd001`cd16a890 fffff960`50c66b2f : 00000000`00000000 fffff901`40669010 fffff901`42358580 fffff901`40000d60 : win32kfull!Win32FreePoolImpl+0x34
ffffd001`cd16a8c0 fffff960`50c68cd6 : 00000000`00000000 ffffd001`cd16a9f0 fffff901`400006d0 fffff901`400c0460 : win32kfull!EXLATEOBJ::vAltUnlock+0x1f
ffffd001`cd16a8f0 fffff803`cd752fa3 : 00000000`00000000 00000000`00000000 ffffe001`ce80b840 00000000`00000000 : win32kfull!NtGdiAlphaBlend+0x1d16
ffffd001`cd16add0 00007fff`674c1494 : 00007fff`674b1e97 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`cd16ae40)
00000071`fa74c9a8 00007fff`674b1e97 : 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 00000000`00ffffff : 0x00007fff`674c1494
00000071`fa74c9b0 0000a7c6`daee0559 : 00000000`00000001 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 : 0x00007fff`674b1e97
00000071`fa74c9b8 00000000`00000001 : 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 00000000`01010bff : 0x0000a7c6`daee0559
00000071`fa74c9c0 0000020b`741f3c50 : 00000000`00ffffff 00000000`00000030 00000000`01010bff 00000000`00000000 : 0x1
00000071`fa74c9c8 00000000`00ffffff : 00000000`00000030 00000000`01010bff 00000000`00000000 00000000`000000c0 : 0x0000020b`741f3c50
00000071`fa74c9d0 00000000`00000030 : 00000000`01010bff 00000000`00000000 00000000`000000c0 00000000`00000030 : 0xffffff
00000071`fa74c9d8 00000000`01010bff : 00000000`00000000 00000000`000000c0 00000000`00000030 00000071`00000030 : 0x30
00000071`fa74c9e0 00000000`00000000 : 00000000`000000c0 00000000`00000030 00000071`00000030 00000071`01ff8000 : 0x1010bff

O nome da imagem é rundll32.exe, que efetivamente não corresponde ao nome da imagem associado à reprodução do clipe de mídia.

Observação Para definir o thread atual, digite .thread <thread number>.

Para obter mais informações sobre threads e processos, consulte as seguintes referências:

Threads e Processos

Contextos em mudança

Seção 11: IRQL, registros e desmontagem

Ver o IRQL guardado

Na Seção 11, você exibirá o IRQL e o conteúdo das regsisters.

<- No sistema host

O nível de solicitação de interrupção (IRQL) é usado para gerenciar a prioridade do serviço de interrupção. Cada processador tem uma configuração IRQL que os threads podem aumentar ou diminuir. As interrupções que ocorrem na configuração IRQL do processador ou abaixo dela são mascaradas e não interferirão na operação atual. As interrupções que ocorrem acima da configuração IRQL do processador têm precedência sobre a operação atual. A extensão !irql exibe o nível de solicitação de interrupção (IRQL) no processador atual do computador de destino antes da interrupção do depurador. Quando o computador de destino ativa o depurador, o IRQL muda, mas o IRQL que estava ativo pouco antes da interrupção do depurador é salvo e exibido pelo !irql.

0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)

< Ver os registos e desmontagem

Ver os registos

Exiba o conteúdo dos registradores para o thread atual no processador atual usando o comando r (Registers ).

0: kd> r
rax=000000000000c301 rbx=ffffe00173eed880 rcx=0000000000000001
rdx=000000d800000000 rsi=ffffe00173eed8e0 rdi=ffffe00173eed8f0
rip=fffff803bb757020 rsp=ffffd001f01f8988 rbp=ffffe00173f0b620
 r8=000000000000003e  r9=ffffe00167a4a000 r10=000000000000001e
r11=ffffd001f01f88f8 r12=0000000000000000 r13=ffffd001f01efdc0
r14=0000000000000001 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
nt!DbgBreakPointWithStatus:
fffff803`bb757020 cc              int     3

Em alternativa, pode mostrar os conteúdos dos registos selecionando Ver>Registos.

Captura de ecrã da janela de registos do WinDbg exibindo aproximadamente 12 registos.

A visualização do conteúdo dos registos pode ser útil ao analisar a execução de código em linguagem assembly e em outros cenários. Para mais informações, ver r (Registos).

Para obter informações sobre o conteúdo do registro, consulte Arquitetura x86 e Arquitetura x64.

Desmontagem

Você pode desmontar o código que está em execução para visualizar o código em linguagem assembly que está a ser executado, selecionando Exibir>Desmontagem.

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

Para obter mais informações sobre desmontagem de linguagem de montagem, consulte Desmontagem x86 anotada e Desmontagem x64 anotada.

Seção 12: Trabalhar com memória

Na Seção 12, você usará comandos do depurador para exibir o conteúdo da memória.

Ver memória

Talvez seja necessário examinar a memória para identificar um problema ou inspecionar variáveis, ponteiros e assim por diante. Você pode exibir a memória digitando um dos seguintes comandos de endereço< d*>.

dB

Exibe dados em valores de byte e caracteres ASCII.

DD

Exibe dados como palavras de largura dupla (4 bytes).

Du

Exibe dados como caracteres Unicode.

DW

Exibe dados como valores de palavras (2 bytes) e caracteres ASCII.

Observação Se você tentar exibir um endereço inválido, seu conteúdo será mostrado como pontos de interrogação (?).

Como alternativa, você pode visualizar a memória selecionando Exibir>memória. Use o menu suspenso Formato de exibição para alterar a forma como a memória é exibida.

Captura de tela da janela de memória de exibição 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 disparar na rotina PropertyHandlerAudioEngineVolumeLevel usando o comando bm. Antes de definirmos o novo ponto de interrupção, limparemos todos os pontos de interrupção anteriores usando bc *.

    kd> bc *
    
  2. Defina um ponto de interrupção para disparar na rotina PropertyHandlerAudioEngineVolumeLevel usando o comando bm.

    kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  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 área de notificações. Isso fará com que o ponto de interrupção seja acionado.

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume:
    fffff80f`02c3a4b0 44894c2420      mov     dword ptr [rsp+20h],r9d
    
  5. Use o item de menu Ver>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 para a variável IVolume no código de exemplo digitando o comando dt e o nome da variável.

    kd> dt lVolume
    Local var @ 0xa011ea50 Type long
    0n-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 mostrar o valor no endereço de memória de IVolume usando o comando dt (Display Type).

    kd> dt dt lVolume
    Local var @ 0xffffb780b7eee664 Type long
    0n0
    

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

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

        return ntStatus;
    
  10. Exiba o valor no local da memória de IVolume usando o comando dt (Display Type).

    kd> dt lVolume
    Local var @ 0xffffb780b7eee664 Type long
    0n-6291456
    

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

  11. Você também pode exibir o local da 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 primeiros quatro 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 a memória, você pode usar os comandos e* para alterar o conteúdo da memória.

Comando Descrição

EA

String ASCII (não terminada por NULL)

UE

Cadeia de caracteres Unicode (não terminada por NULL

Ew

Valores do Word (2 bytes)

Eza

Cadeia de caracteres ASCII terminada por NULL

Ezu

Cadeia de caracteres Unicode terminada por NULL

EB

Valores de byte

Ed

Valores de palavras duplas (4 bytes)

O exemplo a seguir mostra como substituir a memória.

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

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

    kd> eb 0xffffb780`b7eee664 11 11 11 11 11
    
  3. Exiba o local da memória para confirmar que os caracteres foram substituídos digitando o comando db .

    kd> db 0xffffb780`b7eee664
    ffffb780`b7eee664  11 11 11 11 11 00 00 00-00 00 00 00 08 70 2d c5  .............p-.
    ffffb780`b7eee674  8e c9 ff ff 56 57 49 e0-0e f8 ff ff 08 70 2d c5  ....VWI......p-.
    ffffb780`b7eee684  8e c9 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffb780`b7eee694  8e c9 ff ff 00 00 a0 ff-80 b7 ff ff 10 e7 ee b7  ................
    ffffb780`b7eee6a4  80 b7 ff ff 00 00 00 00-00 00 00 00 60 72 47 c7  ............`rG.
    ffffb780`b7eee6b4  8e c9 ff ff a0 e7 ee b7-80 b7 ff ff f0 e6 ee b7  ................
    ffffb780`b7eee6c4  80 b7 ff ff ca 59 49 e0-0e f8 ff ff 00 00 00 00  .....YI.........
    ffffb780`b7eee6d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

Como alternativa, você pode modificar o conteúdo da memória em uma janela de observação ou locais. Para a janela de observação, você pode ver variáveis que estão fora de contexto do quadro atual. Modificá-los não é relevante se não estiverem no contexto.

Seção 13: Encerrar a sessão do WinDbg

<-No sistema host

Se quiseres deixar o depurador ligado, mas quiseres trabalhar no destino, remove todos os pontos de interrupção usando bc *, para que o computador de destino não tente se conectar ao depurador do computador anfitrião. Em seguida, use o comando g para permitir que o computador de destino seja executado novamente.

Para encerrar a sessão de depuração, no sistema host, entre no depurador e digite o comando qd (Sair e Desanexar) ou selecione Parar Depuração no menu.

0: kd> qd

Para obter mais informações, consulte Encerrando uma sessão de depuração no WinDbg (Clássico) na documentação de referência de depuração.

Seção 14: Recursos de depuração do Windows

Informações adicionais estão disponíveis sobre a depuração do Windows. Observe que alguns desses livros usarão versões mais antigas do Windows, como o Windows Vista, em seus exemplos, mas os conceitos discutidos são aplicáveis à maioria das versões do Windows.

Livros

  • Advanced Windows Debugging por Mario Hewardt e Daniel Pravat

  • Dentro do Windows Debugging: Um guia prático de estratégias de depuração e rastreamento no Windows® por Tarik Soulami

  • Windows Internals por Pavel Yosifovich, Alex Ionescu, Mark Russinovich e David Solomon

Vídeo

As ferramentas de desfragmentação mostram os episódios 13-29 do WinDbg: </shows/defrag-tools/>

Fornecedores de Treinamento:

OSR - https://www.osr.com/

Ver também

Introdução à Depuração do Windows