Использование расширения !analyze

Первым шагом в отладке аварийного целевого компьютера или приложения является использование команды расширения !analyze . Это расширение выполняет большой объем автоматизированного анализа. Результаты этого анализа отображаются в окне Команда отладчика.

Для полного подробного отображения данных следует использовать параметр -v . Дополнительные сведения о других параметрах см. на странице справочника по !analyze .

Пример User-Mode !analyze -v

В этом примере отладчик подключен к приложению пользовательского режима, в которой возникло исключение.

0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

Debugger SolutionDb Connection::Open failed 80004005

Если вы подключены к Интернету, отладчик пытается получить доступ к базе данных аварийного решения, поддерживаемой корпорацией Майкрософт. В этом случае отображается сообщение об ошибке, указывающее, что компьютеру не удалось получить доступ к Интернету или веб-сайт не работает.

FAULTING_IP: 
ntdll!PropertyLengthAsVariant+73
77f97704 cc               int     3

В поле FAULTING_IP отображается указатель инструкции на момент сбоя.

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

В поле EXCEPTION_RECORD отображается запись исключения для этого сбоя. Эти сведения также можно просмотреть с помощью команды .exr (Display Exception Record).

BUGCHECK_STR:  80000003

В поле BUGCHECK_STR показан код исключения. Имя является неправильным — термин ошибка проверка фактически означает сбой в режиме ядра. При отладке в пользовательском режиме будет отображаться код исключения, в данном случае 0x80000003.

DEFAULT_BUCKET_ID:  APPLICATION_FAULT

В поле DEFAULT_BUCKET_ID показана общая категория сбоев, к которым относится этот сбой.

PROCESS_NAME:  MyApp.exe

Поле PROCESS_NAME указывает имя процесса, который вызвал исключение.

LAST_CONTROL_TRANSFER:  from 01050963 to 77f97704

В поле LAST_CONTROL_TRANSFER показан последний вызов в стеке. В этом случае код по адресу 0x01050963 вызывает функцию в 0x77F97704. Эти адреса можно использовать с помощью команды ln (Список ближайших символов), чтобы определить, в каких модулях и функциях находятся эти адреса.

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

В поле STACK_TEXT показана трассировка стека компонента сбоя.

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

Когда !analyze определяет инструкцию, которая, вероятно, вызвала ошибку, она отображается в поле FOLLOWUP_IP. В полях SYMBOL_NAME, MODULE_NAME, IMAGE_NAME и DEBUG_FLR_IMAGE_TIMESTAMP отображаются символ, модуль, имя изображения и метка времени изображения, соответствующая этой инструкции.

STACK_COMMAND:  .ecxr ; kb

В поле STACK_COMMAND показана команда, которая использовалась для получения STACK_TEXT. Эту команду можно использовать для повторения отображения трассировки стека или для получения связанных сведений о стеке.

BUCKET_ID:  80000003_MyApp!FatalErrorBox+55

В поле BUCKET_ID отображается конкретная категория сбоев, к которым относится текущий сбой. Эта категория помогает отладчику определить, какие другие сведения будут отображаться в выходных данных анализа.

Followup: dbg
---------

Сведения о полях FOLLOWUP_NAME и последующего выполнения см. в разделах Поле выполнения и Файл triage.ini.

Есть множество других полей, которые могут появиться:

  • Если элемент управления был передан на недопустимый адрес, то поле FAULTING_IP будет содержать этот недопустимый адрес. Вместо поля FOLLOWUP_IP поле FAILED_INSTRUCTION_ADDRESS будет отображать дизассемблированное код из этого адреса, хотя эта дизассембля, вероятно, будет бессмысленной. В этом случае поля SYMBOL_NAME, MODULE_NAME, IMAGE_NAME и DEBUG_FLR_IMAGE_TIMESTAMP будут ссылаться на вызывающий объект этой инструкции.

  • В случае осечки процессора могут отображаться поля SINGLE_BIT_ERROR, TWO_BIT_ERROR или POSSIBLE_INVALID_CONTROL_TRANSFER.

  • Если кажется, что произошло повреждение памяти, в поле CHKIMG_EXTENSION будет указана команда расширения !chkimg , которую следует использовать для исследования.

Пример Kernel-Mode !analyze -v

В этом примере отладчик подключен к компьютеру, на который только что произошел сбой.

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.

В первом элементе отображается код проверка ошибок и сведения об этом типе проверка. Некоторые отображаемые тексты могут не применяться к этому конкретному экземпляру. Дополнительные сведения о каждой проверка ошибок см. в разделе Справочник по коду проверки ошибок.

Arguments:
Arg1: 00000004, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: f832035c, address which referenced memory

Далее отображаются параметры проверка ошибок. За каждым из них следует описание. Например, третий параметр имеет значение 1, а следующий комментарий объясняет, что это указывает на сбой операции записи.

## Debugging Details:


WRITE_ADDRESS:  00000004 Nonpaged pool

CURRENT_IRQL:  2

Следующие несколько полей зависят от характера аварии. В этом случае мы видим поля WRITE_ADDRESS и CURRENT_IRQL. Это просто переоценка сведений, отображаемых в параметрах проверка ошибок. Сравнив оператор "Непагированный пул" с сообщением об ошибке проверка тексте "была предпринята попытка получить доступ к адресу с пажом (или полностью недопустимый), можно увидеть, что адрес был недопустимым. Недопустимый адрес в этом случае был 0x00000004.

FAULTING_IP: 
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204           mov     [edx+0x4],eax

В поле FAULTING_IP отображается указатель инструкции на момент сбоя.

DEFAULT_BUCKET_ID:  DRIVER_FAULT

В поле DEFAULT_BUCKET_ID показана общая категория сбоев, к которым относится этот сбой.

BUGCHECK_STR:  0xD1

В поле BUGCHECK_STR отображается код проверка ошибки, который мы уже видели. В некоторых случаях добавляется дополнительная информация о рассмотрении.

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

В поле TRAP_FRAME показан кадр ловушки для этого сбоя. Эти сведения также можно просмотреть с помощью команды .trap (Display Trap Frame).

LAST_CONTROL_TRANSFER:  from f83206e0 to f832035c

В поле LAST_CONTROL_TRANSFER показан последний вызов в стеке. В этом случае код по адресу 0xF83206E0 вызывать функцию в 0xF832035C. Вы можете использовать команду ln (Перечисление ближайших символов), чтобы определить, в каком модуле и функции находятся эти адреса.

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

В поле STACK_TEXT показана трассировка стека компонента сбоя.

FOLLOWUP_IP: 
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204           mov     [edx+0x4],eax

В поле FOLLOWUP_IP показана дизассембля инструкции, которая, вероятно, вызвала ошибку.

FOLLOWUP_NAME:  usbtri

SYMBOL_NAME:  USBPORT!USBPORT_BadRequestFlush+7c

MODULE_NAME:  USBPORT

IMAGE_NAME:  USBPORT.SYS

DEBUG_FLR_IMAGE_TIMESTAMP:  3b7d868b

В полях SYMBOL_NAME, MODULE_NAME, IMAGE_NAME и DBG_FLR_IMAGE_TIMESTAMP отображаются символ, модуль, изображение и метка времени изображения, соответствующая данной инструкции (если она допустима) или вызывающему объекту этой инструкции (если это не так).

STACK_COMMAND:  .trap fffffffff8950dfc ; kb

В поле STACK_COMMAND показана команда, которая использовалась для получения STACK_TEXT. Эту команду можно использовать для повторения отображения трассировки стека или для получения связанных сведений о стеке.

BUCKET_ID:  0xD1_W_USBPORT!USBPORT_BadRequestFlush+7c

В поле BUCKET_ID отображается конкретная категория сбоев, к которым относится текущий сбой. Эта категория помогает отладчику определить, какие другие сведения будут отображаться в выходных данных анализа.

Сведения о полях FOLLOWUP_NAME и последующего выполнения см. в разделах Поле выполнения и Файл triage.ini.

Есть множество других полей, которые могут появиться:

  • Если элемент управления был передан на недопустимый адрес, то поле FAULTING_IP будет содержать этот недопустимый адрес. Вместо поля FOLLOWUP_IP поле FAILED_INSTRUCTION_ADDRESS будет отображать дизассемблированное код из этого адреса, хотя эта дизассембля, вероятно, будет бессмысленной. В этом случае поля SYMBOL_NAME, MODULE_NAME, IMAGE_NAME и DBG_FLR_IMAGE_TIMESTAMP будут ссылаться на вызывающий объект этой инструкции.

  • В случае осечки процессора могут отображаться поля SINGLE_BIT_ERROR, TWO_BIT_ERROR или POSSIBLE_INVALID_CONTROL_TRANSFER.

  • Если кажется, что произошло повреждение памяти, в поле CHKIMG_EXTENSION будет указана команда расширения !chkimg , которую следует использовать для исследования.

  • Если ошибка проверка произошла в коде драйвера устройства, ее имя может отображаться в поле BUGCHECKING_DRIVER.

Поле для последующего выполнения и файл triage.ini

Как в пользовательском режиме, так и в режиме ядра в поле "Отслеживание" на экране будут отображаться сведения о владельце текущего кадра стека, если это можно определить. Эти сведения определяются следующим образом:

  1. При использовании расширения !analyze отладчик начинает с верхнего кадра в стеке и определяет, является ли он ответственным за ошибку. Если это не так, анализируется следующий кадр. Этот процесс продолжается до тех пор, пока не будет найден фрейм, который может быть неисправен.

  2. Отладчик пытается определить владельца модуля и функции в этом кадре. Если владелец может быть определен, этот кадр считается неисправным.

  3. Если не удается определить владельца, отладчик переходит к следующему кадру стека и т. д., пока владелец не будет определен (или стек не будет полностью проверен). Первый кадр, владелец которого найден в этом поиске, считается неисправным. Если стек исчерпан без поиска каких-либо сведений, поле "Отслеживание" не отображается.

  4. Владелец неисправного кадра отображается в поле Отслеживание. Если используется !analyze -v , поля FOLLOWUP_IP, SYMBOL_NAME, MODULE_NAME, IMAGE_NAME и DBG_FLR_IMAGE_TIMESTAMP будут ссылаться на этот кадр.

Чтобы в поле Дальнейшие действия отображались полезные сведения, необходимо сначала создать файл triage.ini, содержащий имена владельцев модулей и функций.

В файле triage.ini должны быть определены владельцы всех модулей, в которых могут возникнуть ошибки. Вы можете использовать информационную строку вместо фактического владельца, но эта строка не может содержать пробелы. Если вы уверены, что модуль не завершится ошибкой, можно опустить этот модуль или указать, что его следует пропустить. Можно также указать владельцев отдельных функций, что дает процессу рассмотрения еще более детальную детализацию.

Дополнительные сведения о синтаксисе файла triage.ini см. в разделе Указание владельцев модулей и функций.

Дополнительные методы анализа

Если сбой или исключение не произошло, !analyze отобразит очень короткий текст, предоставляющий текущее состояние целевого объекта. В некоторых ситуациях может потребоваться принудительно выполнить анализ, как если бы произошел сбой. Для выполнения этой задачи используйте !analyze -f .

В пользовательском режиме, если возникло исключение, но вы считаете, что основная проблема связана с зависанием, задайте текущий поток в качестве потока, который вы изучаете, а затем используйте !analyze -hang. Это расширение выполняет анализ стека потоков, чтобы определить, блокируют ли какие-либо потоки другие потоки.

Если в режиме ядра произошла ошибка проверка, но вы считаете, что основная проблема связана с зависанием потока, используйте !analyze -hang. Это расширение будет исследовать блокировки, удерживаемые системой, и сканировать цепочку очередей DPC, а также отображать все признаки зависаемых потоков. Если вы считаете, что проблема связана с взаимоблокировкой ресурсов в режиме ядра, используйте расширение !взаимоблокировки вместе с параметром Обнаружение взаимоблокировок в средстве проверки драйверов.

Вы также можете автоматически игнорировать известные проблемы. Для этого необходимо сначала создать XML-файл, содержащий отформатированный список известных проблем. Используйте расширение !analyze -c -loadKnownIssuesFile для загрузки этого файла. Затем при возникновении исключения или разрыва используйте расширение !analyze -c . Если исключение соответствует одной из известных проблем, целевой объект возобновит выполнение. Если целевой объект не возобновляет выполнение, можно использовать !analyze -v , чтобы определить причину проблемы.

См. также раздел

Дополнительные сведения см. в этих разделах.

!Анализировать

Bug Check Code Reference (Справочник с кодами критических ошибок)

Анализ аварийного дампа с помощью отладчиков Windows (WinDbg)

Анализ файла дампа Kernel-Mode с помощью WinDbg