Usando a extensão !analyze

A primeira etapa na depuração de um computador ou aplicativo de destino com falha é usar o comando !analyze extension. Essa extensão executa uma grande quantidade de análise automatizada. 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 dos dados. Para obter detalhes sobre outras opções, consulte a página de referência !analyze .

Um exemplo de !analyze -v User-Mode

Neste exemplo, o depurador é 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 mantidas pela Microsoft. Nesse caso, uma mensagem de erro foi exibida, indicando que seu computador não pôde 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 erro denomer– o termo bug marcar 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 (Listar Símbolos Mais Próximos) 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 o 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 correspondentes 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 o FOLLOWUP_NAME e os campos Acompanhamento, consulte O Campo de Acompanhamento e o Arquivo de triage.ini.

Há uma variedade de outros campos que podem aparecer:

  • Se o controle tiver sido 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 Kernel-Mode

Neste exemplo, o depurador é 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 exibição mostra o código de marcar de bugs e informações sobre esse tipo de marcar de bugs. Alguns dos textos exibidos podem não se aplicar a essa instância específica. Para obter mais detalhes sobre cada marcar de bugs, consulte a seção Referência de código de verificação de bugs.

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 marcar de bug são exibidos em seguida. Cada um deles é seguido por uma descrição. Por exemplo, o terceiro parâmetro é 1 e o comentário a seguir 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 da falha. Nesse caso, vemos campos WRITE_ADDRESS e CURRENT_IRQL. Eles estão simplesmente informando as informações mostradas nos parâmetros de marcar de bug. Comparando a instrução "Pool nãopagado" com o bug marcar texto 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 nesse 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 marcar de bugs, que já vimos. Em alguns casos, informações adicionais de triagem são acrescentadas.

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 interceptação para esta falha. Essas informações também podem ser exibidas usando o comando .trap (Display Trap Frame).

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 (Listar Símbolos Mais Próximos) 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 esta instrução (se for válido) ou ao chamador desta 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 o FOLLOWUP_NAME e os campos Acompanhamento, consulte O Campo de Acompanhamento e o Arquivo de triage.ini.

Há uma variedade de outros campos que podem aparecer:

  • Se o controle tiver sido 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 ocorrer um bug marcar dentro do código de um driver de dispositivo, seu nome poderá ser exibido no campo BUGCHECKING_DRIVER.

O campo de acompanhamento e o arquivo de triage.ini

No modo de usuário e 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:

  1. 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 for, o próximo quadro será analisado. Esse processo continua até que um quadro que possa estar em falha seja encontrado.

  2. O depurador tenta determinar o proprietário do módulo e da função nesse quadro. Se o proprietário puder ser determinado, esse quadro será considerado com falha.

  3. 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 com falha. Se a pilha estiver esgotada sem que nenhuma informação seja encontrada, nenhum campo Acompanhamento será exibido.

  4. O proprietário do quadro em falha é 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, primeiro você deve 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 falhará, poderá omitir este 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 !analyze

Se nenhuma falha ou exceção tiver ocorrido, !analyze exibirá um texto muito curto dando a status atual do destino. Em determinadas situações, talvez você queira forçar a análise a ocorrer como se uma falha tivesse ocorrido. Use !analyze -f para realizar essa tarefa.

No modo de usuário, se ocorreu uma exceção, mas você acredita 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 um bug marcar ocorreu, mas você acredita que o problema subjacente é um thread suspenso, use !analyze -hang. Essa extensão investigará os bloqueios mantidos pelo sistema e examinará a cadeia de filas DPC e exibirá quaisquer 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 problemas conhecidos. Para fazer isso, primeiro você deve criar um arquivo XML contendo uma lista formatada de problemas conhecidos. Use a extensão !analyze -c -loadKnownIssuesFile 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.

!Analisar

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 de Kernel-Mode com o WinDbg