Usando a extensão !analyze
A primeira etapa na depuração de um computador ou aplicativo de destino com falha é usar o comando de extensão !analyze . Esta extensão executa uma grande quantidade de análises automatizadas. Os resultados dessa análise são exibidos na janela Comando do Depurador.
Você deve usar a opção -v para uma exibição totalmente detalhada de dados. Para obter detalhes sobre outras opções, consulte a página de referência !analyze .
Um exemplo de modo de usuário !analyze -v
Neste exemplo, o depurador está anexado a um aplicativo de modo de usuário que encontrou uma exceção.
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
Debugger SolutionDb Connection::Open failed 80004005
Se você estiver conectado à Internet, o depurador tentará acessar um banco de dados de soluções de falha mantido pela Microsoft. Nesse caso, uma mensagem de erro foi exibida, indicando que sua máquina não conseguiu acessar a Internet ou o site não estava funcionando.
FAULTING_IP:
ntdll!PropertyLengthAsVariant+73
77f97704 cc int 3
O campo FAULTING_IP mostra o ponteiro de instrução no momento da falha.
EXCEPTION_RECORD: ffffffff -- (.exr ffffffffffffffff)
ExceptionAddress: 77f97704 (ntdll!PropertyLengthAsVariant+0x00000073)
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 3
Parameter[0]: 00000000
Parameter[1]: 00010101
Parameter[2]: ffffffff
O campo EXCEPTION_RECORD mostra o registro de exceção para essa falha. Essas informações também podem ser exibidas usando o comando .exr (Exibir Registro de Exceção).
BUGCHECK_STR: 80000003
O campo BUGCHECK_STR mostra o código de exceção. O nome é um nome impróprio — o termo verificação de bug na verdade significa uma falha no modo kernel. Na depuração do modo de usuário, o código de exceção será exibido — nesse caso, 0x80000003.
DEFAULT_BUCKET_ID: APPLICATION_FAULT
O campo DEFAULT_BUCKET_ID mostra a categoria geral de falhas à qual essa falha pertence.
PROCESS_NAME: MyApp.exe
O campo PROCESS_NAME especifica o nome do processo que gerou a exceção.
LAST_CONTROL_TRANSFER: from 01050963 to 77f97704
O campo LAST_CONTROL_TRANSFER mostra a última chamada na pilha. Nesse caso, o código no endereço 0x01050963 chamado de função em 0x77F97704. Você pode usar esses endereços com o comando ln (List Nearest Symbols) para determinar em quais módulos e funções esses endereços residem.
STACK_TEXT:
0006b9dc 01050963 00000000 0006ba04 000603fd ntdll!PropertyLengthAsVariant+0x73
0006b9f0 010509af 00000002 0006ba04 77e1a449 MyApp!FatalErrorBox+0x55 [D:\source_files\MyApp\util.c @ 541]
0006da04 01029f4e 01069850 0000034f 01069828 MyApp!ShowAssert+0x47 [D:\source_files\MyApp\util.c @ 579]
0006db6c 010590c3 000e01ea 0006fee4 0006feec MyApp!SelectColor+0x103 [D:\source_files\MyApp\colors.c @ 849]
0006fe04 77e11d0a 000e01ea 00000111 0000413c MyApp!MainWndProc+0x1322 [D:\source_files\MyApp\MyApp.c @ 1031]
0006fe24 77e11bc8 01057da1 000e01ea 00000111 USER32!UserCallWinProc+0x18
0006feb0 77e172b4 0006fee4 00000001 010518bf USER32!DispatchMessageWorker+0x2d0
0006febc 010518bf 0006fee4 00000000 01057c5d USER32!DispatchMessageA+0xb
0006fec8 01057c5d 0006fee4 77f82b95 77f83920 MyApp!ProcessQCQPMessage+0x3b [D:\source_files\MyApp\util.c @ 2212]
0006ff70 01062cbf 00000001 00683ed8 00682b88 MyApp!main+0x1e6 [D:\source_files\MyApp\MyApp.c @ 263]
0006ffc0 77e9ca90 77f82b95 77f83920 7ffdf000 MyApp!mainCRTStartup+0xff [D:\source_files\MyApp\crtexe.c @ 338]
0006fff0 00000000 01062bc0 00000000 000000c8 KERNEL32!BaseProcessStart+0x3d
O campo STACK_TEXT mostra um rastreamento de pilha do componente com falha.
FOLLOWUP_IP:
MyApp!FatalErrorBox+55
01050963 5e pop esi
FOLLOWUP_NAME: dbg
SYMBOL_NAME: MyApp!FatalErrorBox+55
MODULE_NAME: MyApp
IMAGE_NAME: MyApp.exe
DEBUG_FLR_IMAGE_TIMESTAMP: 383490a9
Quando !analyze determina a instrução que provavelmente causou o erro, ele a exibe no campo FOLLOWUP_IP. Os campos SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DEBUG_FLR_IMAGE_TIMESTAMP mostram o símbolo, o módulo, o nome da imagem e o carimbo de data/hora da imagem correspondente a esta instrução.
STACK_COMMAND: .ecxr ; kb
O campo STACK_COMMAND mostra o comando que foi usado para obter o STACK_TEXT. Você pode usar esse comando para repetir essa exibição de rastreamento de pilha ou alterá-la para obter informações de pilha relacionadas.
BUCKET_ID: 80000003_MyApp!FatalErrorBox+55
O campo BUCKET_ID mostra a categoria específica de falhas à qual a falha atual pertence. Essa categoria ajuda o depurador a determinar quais outras informações exibir na saída da análise.
Followup: dbg
---------
Para obter informações sobre os campos FOLLOWUP_NAME e Acompanhamento, consulte O campo de acompanhamento e o arquivo triage.ini.
Há uma variedade de outros campos que podem aparecer:
Se o controle foi transferido para um endereço inválido, o campo FAULTING_IP conterá esse endereço inválido. Em vez do campo FOLLOWUP_IP, o campo FAILED_INSTRUCTION_ADDRESS mostrará o código desmontado desse endereço, embora essa desmontagem provavelmente não tenha sentido. Nessa situação, os campos SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DEBUG_FLR_IMAGE_TIMESTAMP se referirão ao chamador desta instrução.
Se o processador falhar, você poderá ver os campos SINGLE_BIT_ERROR, TWO_BIT_ERROR ou POSSIBLE_INVALID_CONTROL_TRANSFER.
Se a corrupção de memória parecer ter ocorrido, o campo CHKIMG_EXTENSION especificará o comando de extensão !chkimg que deve ser usado para investigar.
Um exemplo de !analyze -v no modo kernel
Neste exemplo, o depurador está anexado a um computador que acabou de falhar.
kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pagable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
O primeiro elemento da tela mostra o código de verificação de bugs e informações sobre esse tipo de verificação de bugs. Parte do texto exibido pode não se aplicar a esta instância específica. Para obter mais detalhes sobre cada verificação de bug, consulte a seção Referência de código de verificação de bug.
Arguments:
Arg1: 00000004, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: f832035c, address which referenced memory
Os parâmetros de verificação de bugs são exibidos a seguir. Cada um deles é seguido por uma descrição. Por exemplo, o terceiro parâmetro é 1 e o comentário seguinte explica que isso indica que uma operação de gravação falhou.
## Debugging Details:
WRITE_ADDRESS: 00000004 Nonpaged pool
CURRENT_IRQL: 2
Os próximos campos variam dependendo da natureza do acidente. Nesse caso, vemos WRITE_ADDRESS e CURRENT_IRQL campos. Eles estão simplesmente reafirmando as informações mostradas nos parâmetros de verificação de bugs. Comparando a instrução "Pool não paginado" com o texto de verificação de bugs que diz "foi feita uma tentativa de acessar um endereço pagável (ou completamente inválido)", podemos ver que o endereço era inválido. O endereço inválido neste caso foi 0x00000004.
FAULTING_IP:
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204 mov [edx+0x4],eax
O campo FAULTING_IP mostra o ponteiro de instrução no momento da falha.
DEFAULT_BUCKET_ID: DRIVER_FAULT
O campo DEFAULT_BUCKET_ID mostra a categoria geral de falhas à qual essa falha pertence.
BUGCHECK_STR: 0xD1
O campo BUGCHECK_STR mostra o código de verificação de bugs, que já vimos. Em alguns casos, informações adicionais de triagem são anexadas.
TRAP_FRAME: f8950dfc -- (.trap fffffffff8950dfc)
.trap fffffffff8950dfc
ErrCode = 00000002
eax=81cc86dc ebx=81cc80e0 ecx=81e55688 edx=00000000 esi=81cc8028 edi=8052cf3c
eip=f832035c esp=f8950e70 ebp=f8950e90 iopl=0 nv up ei pl nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010216
USBPORT!USBPORT_BadRequestFlush+7c:
f832035c 894204 mov [edx+0x4],eax ds:0023:00000004=????????
.trap
Resetting default context
O campo TRAP_FRAME mostra o quadro de armadilha para essa falha. Essas informações também podem ser visualizadas usando o comando .trap (Exibir quadro de trapping).
LAST_CONTROL_TRANSFER: from f83206e0 to f832035c
O campo LAST_CONTROL_TRANSFER mostra a última chamada na pilha. Nesse caso, o código no endereço 0xF83206E0 chamado de função em 0xF832035C. Você pode usar o comando ln (List Nearest Symbols) para determinar em qual módulo e função esses endereços residem.
STACK_TEXT:
f8950e90 f83206e0 024c7262 00000000 f8950edc USBPORT!USBPORT_BadRequestFlush+0x7c
f8950eb0 804f5561 81cc8644 81cc8028 6d9a2f30 USBPORT!USBPORT_DM_TimerDpc+0x10c
f8950fb4 804f5644 6e4be98e 00000000 ffdff000 nt!KiTimerListExpire+0xf3
f8950fe0 8052c47c 8053cf20 00000000 00002e42 nt!KiTimerExpiration+0xb0
f8950ff4 8052c16a efdefd44 00000000 00000000 nt!KiRetireDpcList+0x31
O campo STACK_TEXT mostra um rastreamento de pilha do componente com falha.
FOLLOWUP_IP:
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204 mov [edx+0x4],eax
O campo FOLLOWUP_IP mostra a desmontagem da instrução que provavelmente causou o erro.
FOLLOWUP_NAME: usbtri
SYMBOL_NAME: USBPORT!USBPORT_BadRequestFlush+7c
MODULE_NAME: USBPORT
IMAGE_NAME: USBPORT.SYS
DEBUG_FLR_IMAGE_TIMESTAMP: 3b7d868b
Os campos SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DBG_FLR_IMAGE_TIMESTAMP mostram o símbolo, o módulo, a imagem e o carimbo de data/hora da imagem correspondentes a essa instrução (se for válido) ou ao chamador dessa instrução (se não for).
STACK_COMMAND: .trap fffffffff8950dfc ; kb
O campo STACK_COMMAND mostra o comando que foi usado para obter o STACK_TEXT. Você pode usar esse comando para repetir essa exibição de rastreamento de pilha ou alterá-la para obter informações de pilha relacionadas.
BUCKET_ID: 0xD1_W_USBPORT!USBPORT_BadRequestFlush+7c
O campo BUCKET_ID mostra a categoria específica de falhas à qual a falha atual pertence. Essa categoria ajuda o depurador a determinar quais outras informações exibir na saída da análise.
Para obter informações sobre os campos FOLLOWUP_NAME e Acompanhamento, consulte O campo de acompanhamento e o arquivo triage.ini.
Há uma variedade de outros campos que podem aparecer:
Se o controle foi transferido para um endereço inválido, o campo FAULTING_IP conterá esse endereço inválido. Em vez do campo FOLLOWUP_IP, o campo FAILED_INSTRUCTION_ADDRESS mostrará o código desmontado desse endereço, embora essa desmontagem provavelmente não tenha sentido. Nessa situação, os campos SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DBG_FLR_IMAGE_TIMESTAMP se referirão ao chamador desta instrução.
Se o processador falhar, você poderá ver os campos SINGLE_BIT_ERROR, TWO_BIT_ERROR ou POSSIBLE_INVALID_CONTROL_TRANSFER.
Se a corrupção de memória parecer ter ocorrido, o campo CHKIMG_EXTENSION especificará o comando de extensão !chkimg que deve ser usado para investigar.
Se ocorreu uma verificação de bug no código de um driver de dispositivo, seu nome pode ser exibido no campo BUGCHECKING_DRIVER.
O campo de acompanhamento e o arquivo triage.ini
Tanto no modo de usuário quanto no modo kernel, o campo Acompanhamento na exibição mostrará informações sobre o proprietário do quadro de pilha atual, se isso puder ser determinado. Essas informações são determinadas da seguinte maneira:
Quando a extensão !analyze é usada, o depurador começa com o quadro superior na pilha e determina se ele é responsável pelo erro. Se não estiver, o próximo quadro será analisado. Esse processo continua até que um quadro que possa estar com defeito seja encontrado.
O depurador tenta determinar o proprietário do módulo e da função nesse quadro. Se o proprietário puder ser determinado, este quadro é considerado culpado.
Se o proprietário não puder ser determinado, o depurador passará para o próximo quadro de pilha e assim por diante, até que o proprietário seja determinado (ou a pilha seja completamente examinada). O primeiro quadro cujo proprietário é encontrado nesta pesquisa é considerado culpado. Se a pilha estiver esgotada sem que nenhuma informação seja encontrada, nenhum campo Acompanhamento será exibido.
O proprietário do quadro em falta é exibido no campo Acompanhamento. Se !analyze -v for usado, os campos FOLLOWUP_IP, SYMBOL_NAME, MODULE_NAME, IMAGE_NAME e DBG_FLR_IMAGE_TIMESTAMP se referirão a esse quadro.
Para que o campo Acompanhamento exiba informações úteis, você deve primeiro criar um arquivo triage.ini contendo os nomes dos proprietários do módulo e da função.
O arquivo triage.ini deve identificar os proprietários de todos os módulos que podem ter erros. Você pode usar uma cadeia de caracteres informativa em vez de um proprietário real, mas essa cadeia de caracteres não pode conter espaços. Se você tiver certeza de que um módulo não apresentará falhas, poderá omitir esse módulo ou indicar que ele deve ser ignorado. Também é possível especificar proprietários de funções individuais, dando ao processo de triagem uma granularidade ainda mais fina.
Para obter detalhes sobre a sintaxe do arquivo triage.ini, consulte Especificando proprietários de módulo e função.
Técnicas adicionais de !analyze
Se nenhuma falha ou exceção tiver ocorrido, !analyze exibirá um texto muito curto fornecendo o status atual do destino. Em determinadas situações, você pode forçar a análise a ocorrer como se tivesse ocorrido uma falha. Use !analyze -f para realizar essa tarefa.
No modo de usuário, se tiver ocorrido uma exceção, mas você acreditar que o problema subjacente é um thread suspenso, defina o thread atual como o thread que você está investigando e use !analyze -hang. Essa extensão executará uma análise de pilha de threads para determinar se algum thread está bloqueando outros threads.
No modo kernel, se uma verificação de bug ocorreu, mas você acredita que o problema subjacente é um thread interrompido, use !analyze -hang. Essa extensão investigará os bloqueios mantidos pelo sistema e examinará a cadeia de filas DPC e exibirá todas as indicações de threads suspensos. Se você acredita que o problema é um deadlock de recursos no modo kernel, use a extensão !deadlock junto com a opção Detecção de Deadlock do Verificador de Driver.
Você também pode ignorar automaticamente os problemas conhecidos. Para fazer isso, você deve primeiro criar um arquivo XML contendo uma lista formatada de problemas conhecidos. Use a extensão !analyze -c -load KnownIssuesFile para carregar esse arquivo. Em seguida, quando ocorrer uma exceção ou interrupção, use a extensão !analyze -c . Se a exceção corresponder a um dos problemas conhecidos, o destino retomará a execução. Se o destino não retomar a execução, você poderá usar !analyze -v para determinar a causa do problema.
Confira também
Consulte estes tópicos para obter informações adicionais.
Referência de código de verificação de bugs
Análise de despejo de memória usando os depuradores do Windows (WinDbg)
Analisando um arquivo de despejo no modo kernel com o WinDbg