Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Nota As instruções para ativar esse recurso aplicam-se apenas ao WDK para Windows 8. Para o Windows 8.1, esse recurso foi integrado ao Verificador de Driver. Em computadores que executam o Windows 8.1, use a opção Simulação sistemática de baixos recursos.
A opção Stack Based Failure Injection injeta falhas de recursos em drivers de modo kernel. Esta opção usa um driver especial, KmAutoFail.sys, em conjunto com o Verificador de Drivers para investigar os caminhos de tratamento de erros do driver. Testar esses caminhos tem sido historicamente muito difícil. A opção Stack Based Failure Injection injeta falhas de recursos de forma previsível, o que torna os problemas que encontra reproduzíveis. Como os caminhos de erro são fáceis de reproduzir, também facilita a verificação de correções para esses problemas.
Para ajudá-lo a determinar a causa raiz do erro, é fornecida uma extensão do depurador que pode dizer exatamente quais falhas foram injetadas e em que ordem.
Quando a opção Stack Based Failure Injection está ativada num driver específico, interceta chamadas desse driver para o kernel e Ndis.sys. A Injeção de Falha Baseada em Pilha examina a pilha de chamadas — especificamente, a parte da pilha de chamadas que vem do driver em que ela está habilitada. Se for a primeira vez que viu essa pilha, ele falhará na chamada conforme a semântica dessa chamada. Caso contrário, se já viu essa chamada antes, irá passá-la sem alterações. Stack Based Failure Injection contém lógica para lidar com o fato de que um driver pode ser carregado e descarregado várias vezes. Ele reconhecerá que a pilha de chamadas continua a mesma, mesmo se o driver for recarregado em um local de memória diferente.
Ativando esta opção
Você pode ativar o recurso de injeção de falha baseada em pilha para um ou mais drivers quando estiver Implantando um driver em um computador de teste. Você pode selecionar a opção Injeção de Falha Baseada em Pilha ao configurar as Propriedades do Verificador de Controladores para Projetos de Pacote de Controladores . Tem de reiniciar o computador para ativar ou desativar a opção Stack Based Failure Injection. Você também pode executar um utilitário de teste para habilitar o Verificador de Driver e esse recurso no computador de teste.
Importante Ao ativar a injeção de falha baseada em pilha no computador de teste, certifique-se de não selecionar também Simulação de Baixos Recursos.
Página de Propriedades do Verificador de Driver
- Abra as páginas de propriedades do seu pacote de driver. Clique com o botão direito do mouse no projeto do pacote de driver no Gerenciador de Soluções e selecione Propriedades.
- Nas páginas de propriedades do pacote de driver, clique em Propriedades de Configuração, clique em Instalação de Drivere, em seguida, clique em Verificador de Driver.
- Selecione Ativar Verificador de Controladores. Ao habilitar o Verificador de Driver no computador de teste, você pode optar por habilitar o Verificador de Driver para todos os drivers no computador, somente para o projeto de driver ou para uma lista de drivers especificados.
- Em Injetor de Falhas Baseado em Pilha, selecione (assinale) Injeção de Falhas Baseada em Pilha.
- Clique Aplicar ou Confirmar.
- Consulte Implantando um driver em um computador de teste para obter mais informações. O computador de teste deve reiniciar para ativar essa opção.
Usar o teste de Habilitar e Desabilitar Verificador de Driver
Você também pode habilitar o Verificador de Driver executando um teste de utilitário. Siga as instruções descritas em Como testar um driver em tempo de execução usando o Visual Studio. Na categoria de teste Todos os Testes\Verificador de Driver, selecione os testes Ativar Verificador de Driver (possível reinicialização necessária) e Desativar Verificador de Driver (possível reinicialização necessária).
Selecione as opções do Verificador de Driver clicando no nome do teste Ativar Verificador de Driver (possível reinicialização necessária) na janela Grupo de Teste de Driver.
Selecione (verifique) Injeção de falha baseada em pilha.
Depois de adicionar esses testes a um grupo de teste, você pode salvar o grupo de teste. Para habilitar a injeção de falha baseada em pilha, execute o teste Ativar verificador de driver (possível reinicialização necessária) no computador que você configurou para teste.
Para desativar o Verificador de Driver, execute o teste Desativar Verificador de Driver (possível reinicialização necessária).
Usando a opção de injeção de falha baseada em pilha
Uma consideração importante ao testar com o Stack Based Failure Injection é que a maioria dos bugs encontrados resultará em uma análise de erro. Isso pode ser um pouco doloroso se o driver for um driver carregado na inicialização. Devido a isso, desativaremos automaticamente a Stack Based Failure Injection, se o Verificador de Drivers estiver desativado. Isso significa que você pode desativar a injeção de falha baseada em pilha no momento da inicialização a partir do depurador, desativando o Verificador de Driver usando o comando !verifier –disable.
Se for possível, para seus testes iniciais com Stack Based Failure Injection, configure seu driver para que ele não seja carregado no momento da inicialização. Em seguida, você pode executar alguns testes simples de carga e descarga. Muitos dos bugs encontrados pela Stack Based Failure Injection ocorrem durante as fases de inicialização ou limpeza. Carregar e descarregar repetidamente o seu controlador é uma boa maneira de os encontrar.
Depois de fazer todas as correções necessárias para que os testes de descarga de carga sejam bem-sucedidos, você pode passar para testes baseados em IOCTL, testes funcionais completos e, finalmente, testes de estresse. Em geral, se você seguir essa progressão de teste, não descobrirá muitos novos problemas durante o teste de estresse, porque a maioria dos caminhos de código já terá sido executada antes disso.
Usando a extensão do depurador SBFI (Stack Based Failure Injection)
A maioria dos problemas encontrados com a injeção de erros baseada em pilha resulta em análises de bugs. Para ajudar a determinar a causa desses erros de código, o WDK fornece a extensão do depurador Stack Based Failure Injection e os símbolos necessários. O procedimento de instalação instalará ambos no seu sistema depurador. O local padrão é C:\Program Files (x86)\Windows Kits\8.0\Debuggers\<arch>.
Para executar a extensão do depurador
No prompt de comando do depurador, digite o seguinte comando: !<path>\kmautofaildbg.dll.autofail. Por exemplo, supondo que as extensões do depurador estejam instaladas no diretório c:\dbgext e que kmautofail.pdb esteja no caminho de símbolos, deverá digitar o seguinte comando:
!c:\dbgext\kmautofaildbg.dll.autofail
Isso irá descarregar informações para o seu depurador que mostram as pilhas de chamadas das falhas mais recentes injetadas. Cada entrada se parece com a seguinte, tirada de uma execução de teste real. No exemplo a seguir, a Stack Based Failure Injection está habilitada em Mydriver.sys
Sequence: 2, Test Number: 0, Process ID: 0, Thread ID: 0
IRQ Level: 2, HASH: 0xea98a56083aae93c
0xfffff8800129ed83 kmautofail!ShimHookExAllocatePoolWithTag+0x37
0xfffff88003c77566 mydriver!AddDestination+0x66
0xfffff88003c5eeb2 mydriver!ProcessPacketDestination+0x82
0xfffff88003c7db82 mydriver!ProcessPacketSource+0x8b2
0xfffff88003c5d0d8 mydriver!ForwardPackets+0xb8
0xfffff88003c81102 mydriver!RoutePackets+0x142
0xfffff88003c83826 mydriver!RouteNetBufferLists+0x306
0xfffff88003c59a76 mydriver!DeviceSendPackets+0x156
0xfffff88003c59754 mydriver!ProcessingComplete+0x4a4
0xfffff88001b69b81 systemdriver2!ProcessEvent+0x1a1
0xfffff88001b3edc4 systemdriver1!CallChildDriver+0x20
0xfffff88001b3fc0a systemdriver1!ProcessEvent+0x3e
0xfffff800c3ea6eb9 nt!KiRetireDpcList+0x209
0xfffff800c3ea869a nt!KiIdleLoop+0x5a
Na parte superior do resultado, o número de ordem contabiliza as falhas injetadas. Este exemplo mostra a segunda falha injetada durante esta execução de teste. O ID do processo é 0, então este foi o processo do sistema. IRQL é 2, por isso é chamado no nível de execução.
A partir da pilha, KmAutoFail é o driver de injeção de falha baseado em pilha. O nome da função KmAutoFail indica qual chamada de função de Mydriver.sys foi intercetada e teve uma falha injetada. Aqui, a função que falhou foi ExAllocatePoolWithTag. Todas as funções em KmAutoFail que intercetam chamadas para Ntoskrnl.sys ou Ndis.sys usam essa convenção de nomenclatura. Em seguida, vemos a pilha de chamadas com o driver sendo testado (Mydriver.sys). Esta é o segmento da pilha de chamadas que é usado para determinar a unicidade da pilha. Assim, cada entrada despejada pela extensão do depurador será exclusiva nesta parte da pilha de chamadas. O restante da pilha de chamadas indica quem chamou o driver. A principal questão aqui é se o driver é chamado em modo de utilizador (por meio de um IOCTL) ou por um driver em modo kernel.
Note que, se um driver retornou uma falha da sua rotina de DriverEntry , tentativas de recarga normalmente ocorrem em uma localização de memória diferente. Nesse caso, a pilha de chamadas da localização anterior provavelmente conterá "lixo" em vez de informações da pilha do driver. Mas isso não é um problema; isso indica que o driver lidou corretamente com a falha injetada.
Esta entrada seguinte mostra uma chamada para o driver através de um IOCTL em modo utilizador. Observe o identificador do processo e o nível do IRQ. Como Mydriver.sys é um driver de filtro NDIS, o IOCTL passou por Ndis.sys. Note que nt!NtDeviceIoControlFile está na pilha. Qualquer teste que você executar em seu driver que usa IOCTLs passará por essa função.
Sequence: 5, Test Number: 0, Process ID: 2052, Thread ID: 4588
IRQ Level: 0, HASH: 0xecd4650e9c25ee4
0xfffff8800129ed83 kmautofail!ShimHookExAllocatePoolWithTag+0x37
0xfffff88003c6fb39 mydriver!SendMultipleOids+0x41
0xfffff88003c7157b mydriver!PvtDisconnect+0x437
0xfffff88003c71069 mydriver!NicDisconnect+0xd9
0xfffff88003ca3538 mydriver!NicControl+0x10c
0xfffff88003c99625 mydriver!DeviceControl+0x4c5
0xfffff88001559d93 NDIS!ndisDummyIrpHandler+0x73
0xfffff88001559339 NDIS!ndisDeviceControlIrpHandler+0xc9
0xfffff800c445cc96 nt!IovCallDriver+0x3e6
0xfffff800c42735ae nt!IopXxxControlFile+0x7cc
0xfffff800c4274836 nt!NtDeviceIoControlFile+0x56
0xfffff800c3e74753 nt!KiSystemServiceCopyEnd+0x13
Analisando os resultados da Injeção de Falhas Baseada em Stack
Você está a executar os testes no seu driver e, de repente, encontra um problema. Muito provavelmente esta foi uma verificação de bug, mas também pode porque o computador ficou sem resposta. Como encontrar a causa? Supondo que seja uma verificação de erros, primeiro use a extensão acima para encontrar a lista de falhas inseridas e, em seguida, use o comando do depurador: !analyze –v.
A verificação de erros mais comum é causada por não verificar o sucesso de uma alocação. Neste caso, a pilha da análise do bug check é provavelmente quase idêntica à da última falha que foi injetada. Em algum momento após a falha na alocação (muitas vezes já na linha seguinte), o driver acessará o ponteiro nulo. Este tipo de bug é muito fácil de corrigir. Às vezes, a alocação com falha é uma ou duas posições acima na lista, mas esse tipo ainda é muito fácil de encontrar e corrigir.
A segunda verificação de bugs mais comum ocorre durante a limpeza. Neste caso, o condutor provavelmente detectou a falha de alocação e passou para a limpeza; mas durante a limpeza, o condutor não verificou o ponteiro e mais uma vez acedeu a um ponteiro nulo. Um caso intimamente relacionado é aquele em que a limpeza pode ser executada duas vezes. Se, após a libertação de uma estrutura, o ponteiro para essa estrutura não for definido como nulo, a segunda vez que a função de limpeza for chamada, ela tentará libertar a estrutura novamente, resultando num erro de verificação.
Os erros que fazem com que o computador pare de responder são mais difíceis de diagnosticar, mas o procedimento para depurá-los é semelhante. Esses erros geralmente são causados por problemas de contagem de referência ou bloqueio de rotação. Felizmente, o Verificador de Driver detetará muitos problemas de spinlock antes que causem complicações. Nesses casos, acesse o depurador e use a extensão do depurador para obter a lista de falhas que foram injetadas por meio da técnica de injeção de falhas baseada em pilha. Uma rápida olhada no código em torno das falhas mais recentes pode mostrar uma contagem de referência que é feita antes da falha, mas não liberada depois. Se não, procure uma thread no seu driver que está à espera de um spin lock, ou de qualquer contagem de referência que esteja obviamente errada.