[Previous] [Next]

Чтение crash-экранов

Несмотря на ужасающее название "system crash", системный сбой является вполне заурядным событием. Операционная система всего лишь сообщает, что она перешла в такое внутреннее состояние, которое несовместимо с возможностью продолжения работы. Следовательно, полагает операционная система, лучше прекратить работу сейчас, нежели функционировать с этим ошибочным состоянием. И это решение во многих случаях предпочтительнее.

Кто инициирует объявление системного сбоя?

Во-первых, некоторые компоненты уровня ядра, которые "по долгу службы" обнаружили некорректное состояния, могут решить, что пришла пора "сказать стоп". Например, если Диспетчер ввода/вывода обнаруживает, что драйвер передал в вызов IoCompleteRequest завершенный ранее пакет IRP, то Диспетчер ввода/вывода непременно вызовет этот самый сигнал фатального системного сбоя.

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

Независимо от того, какие подсистемы ядра выступают инициатором системного останова, реально выполняется вызов одной из двух функций:

VOID KeBugCheck( BugChCode );
VOID KeBugCheckEx( BugChCode, Arg1, Arg2, Arg3, Arg4 ); 

Любая из этих функций вызывает останов системы и (необязательно) сохраняет файл со снимком памяти (crash dump file) на жестком диске. В зависимости от выбора системного администратора, операционная система после этого прекращает работу, перезапускается или запускает отладку ядра (kernel's debug client).

Аргумент BugChCode в вызове KeBugCheck указывает причину сбоя в виде значения типа DWORD. Этот аргумент известен также под именем "bugcheck code". Дополнительные 4 аргумента в функции KeBugCheckEx дают возможность видеть в диагностическом сообщении дополнительную информацию (что, возможно, позволит удачнее локализовать источник сбоя).

Коды "bugcheck codes" могут быть использованы из числа определенных Microsoft (см. файл BUGCODES.h), либо можно определить в драйвере дополнительно.

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

Голубой экран смерти (BSOD)

Системное сообщение об останове системы — это появляющееся на голубом фоне сообщение, которое носит закрепившееся за ним название "Blue Screen Of Death" (BSOD). В разных версиях NT вид BSOD сообщений сильно менялся. В русифицированных версиях зачастую на экране видна абракадабра вместо текста (из-за неверной кодировки), что, однако, не должно сильно обременять разработчика. Главной информацией являются две строки, содержащие код ошибки и некоторые параметры сбоя (шестнадцатеричные числа), например:

DRIVER_IRQL_NOT_LESS_OR_EQUAL
*** STOP: 000000Dl (00000000 00000002 00000000 F8B57624)
*** Example.sys - address F8B57624 base at F8B57000 Datestamp 3e6da099  

Сообщение код "bugcheck code", указанный в текстовой форме (DRIVER_IRQL_NOT_LESS_OR_EQUAL), его шестнадцатеричное значение (здесь 000000D1, после слова STOP) и четыре аргумента, переданные в вызове KeBugCheckEx. B зависимости от кода интерпретируется значение остальных 4-х аргументов (см. Приложение А).

Коду 0xD1 соответствует DRIVER_IRQL_NOT_LESS_OR_EQUAL. Приложение А указывает, что код 0xD1 означает ошибку, связанную с обращением к отсутствующей в физической памяти странице (page fault) на уровне IRQL равном DISPATCH_LEVEL или выше. Кроме того, при этом коде ошибки можно сказать, что четыре аргумента KeBugCheckEx означают следующее:

Arg1: Ссылочный адрес (обращение к которому вызвало сбой) 00000000
Arg2: Текущий IRQL уровень 2
Arg3: Тип доступа 0 (что означает "чтение")
Arg4: Адрес инструкции, которая вызвала сбой 0xF8B57624 

Анализ информации Crash Dump файлов

Когда происходит фатальный сбой системы, операционная система может (при определенных настройках системы) сохранить состояние системы в момент сбоя в файле на жестком диске. Чтобы это выполнялось, в апплете Пуск - Настройка - Панель Управления - Система - Дополнительно - Загрузка и восстановление - Параметры (рисунок 13.3) необходимо ввести приемлемые данные. Фиксирование состояние системы в момент сбоя позволит затем вернуться к анализу причин сбоя.

Рис. 13.3
Окно системного апплета для установки параметров crash dump файла

При помощи отладчика WinDbg можно проанализировать состояние системы в момент сбоя по содержимому crash dump файла. Там можно обнаружить всю информацию, которая была бы доступна отладчику, если бы он оказался включенным в момент сбоя. Это тип экспертизы позволяет добывать убедительные доказательства причин, приведших к фатальному сбою. Во время анализа необходимо установить:

После запуска WinDbg необходимо открыть crash dump файл (полученный с целевого компьютера) для анализа, выбрав пункт меню File и затем Open Crash Dump. После выбора и загрузки необходимого файла, на экране появится информация следующего (например) типа:

Windows XP Kernel Version 2600 UP Free x86 compatible
Kernel base = 0x804d4000 PsLoadedModuleList = 0x8054be30
Bufcheck 000000Dl : 00000000 00000002 00000000 F8B57624
. . .

Как видим, начальная информация показывает те же данные, что и сообщение экрана BSOD. Не должно вводить в заблуждение сообщение о не перехваченном исключении с кодом 0x80000003. Это точка прерывания, используемая собственно KeBugCheck для останова системы, поэтому не следует придавать ей значения.

Следует отметить, что в отсутствие отладочных символов операционной системы картина получается безрадостной. Распечатка сообщений WinDbg для этого случая приводится ниже.

Loading Dump File [E:\SystemCrashDump\MEMORY.DMP]
Kernel Dump File: Full address space is available

Microsoft (R) Windows Kernel Debugger Version 3.0.0020.0
Copyright (c) Microsoft Corporation. All rights reserved.

Loaded dbghelp extension DLL
Loaded ext extension DLL
Loaded exts extension DLL
Loaded kext extension DLL
Loaded kdexts extension DLL
Symbol search path is: *** Invalid *** : Verify _NT_SYMBOL_PATH setting
Executable search path is:
*********************************************************************
* Symbols can not be loaded because symbol path is not initialized. *
*                                                                   *
* The Symbol Path can be set by:                                    *
*   using the _NT_SYMBOL_PATH environment variable.                 *
*   using the -y <symbol_path> argument when starting the debugger. *
*   using .sympath and .sympath+                                    *
*********************************************************************
*** ERROR: Symbol file could not be found. Defaulted to export symbols for
ntoskrnl.exe -
Windows XP Kernel Version 2600 (Service Pack 1) UP Free x86 compatible
Built by: 2600.xpspl.020828-1920
Kernel base = 0x804d4000 PsLoadedModuleList = 0x8054be30
Debug session time: Fri Jun 13 02:20:17 2003
System Uptime: 0 days 3:15:59
*********************************************************************
* Symbols can not be loaded because symbol path is not initialized. *
*                                                                   *
* The Symbol Path can be set by:                                    *
*   using the _NT_SYMBOL_PATH environment variable.                 *
*   using the -y <symbol_path> argument when starting the debugger. *
*   using .sympath and .sympath+                                    *
*********************************************************************

WaitForEvent failed
WARNING: Stack unwind information not available. Following frames may be wrong.
WARNING: Stack unwind information not available. Following frames may be wrong.
*******************************************************************************
*                                                                             *
*                         Bugcheck Analysis                                   *
*                                                                             *
*******************************************************************************

***** Kernel symbols are WRONG. Please fix symbols to do bugcheck analysis.
*******************************************************************************
*                                                                             *
*                         Bugcheck Analysis                                   *
*                                                                             *
*******************************************************************************
Bugcheck code 000000D1
Arguments 00000000 00000002 00000000 f8b57624

ChildEBP RetAddr  Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
f2270b54 804dce53 0000000a 00000000 00000002 ntoskrnl!KeBugCheckEx+0xl9
f2270b70 00000000 00000000 00000000 00000000 ntoskrnl!Kei386EoiHelper+0x251c

eax=ffdff13c ebx=0000000a ecx=00000000 edx=40000000 esi=f8b57624 edi=00000000
eip=805266db esp=f2270b3c ebp=f2270b54 iopl=0         nv up ei ng nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000286
ntoskrnl!KeBugCheckEx+19:
805266db 5d               pop     ebp 

Самой важной информацией, которую можно извлечь из приведенного выше набора строк — это код ошибочной ситуации (bugcheck code), равный 0x00D1. Остальные сведения, связанные с раскруткой стека вызовов в данной ситуации недоступны. Хотя именно данная информация особенно ценна в crash dump файлах.