Критическая ошибка STOP 000000F4, символическое имя: CRITICAL_OBJECT_TERMINATION. Данная критическая ошибка говорит нам о том, что произошла ситуация, в которой объект (процесс/поток), критичный для функционирования операционной системы, был неожиданно завершен или прерван.
Параметры ошибки:
Нижеследующие параметры можно наблюдать на диагностическом "синем экране смерти" (BSOD), либо в полях дампа памяти.
Параметр | Описание |
---|---|
1 | Тип завершившегося объекта: 0x3: Процесс 0x6: Поток |
2 | Завершившийся объект |
3 | Имя файла образа процесса |
4 | Указатель на ASCII строку, содержащую поясняющее сообщение |
Низкий уровень
В силу особенностей архитектуры x86, а так же специфики критических ошибок операционной системы Windows, рекомендации по устранению причин сбоя, зачастую, не отличаются какой-либо конкретикой и содержат лишь общие предложения, многие из которых не приводят к положительному результату, в следствии чего теряется огромное количество времени. К тому же, в случае общего похода к решению, нет погружения в детали инцидента, из-за этого даже в случае устранения причин сбоя, модуль, виновный в возникновении ошибки, остается не выявленным. Сбой STOP 000000F4, как и многие другие критические сбои, относится к той категории, которая не является легкой в изучении, поскольку отсутствует прямая связь с причиной "падения". Практика показывает, что зачастую даже при наличии полного дампа довольно сложно докопаться до настоящей причины.
Тем не менее, пора уже начинать мыслить реалиями операционной системы и разбираться в низкоуровневых причинах происходящего, поэтому в данном разделе я попытаюсь собрать воедино весь найденный в Сети материал, несколько переработав его и дополнив собственными наблюдениями, преследуя цель выявить хоть какие-то закономерности, описать найденные варианты решений, приблизиться к пониманию происходящего с системой в момент сбоя и хоть немного да упростить жизнь технического специалиста. Поэтому, если Вам стало вдруг интересно, что же происходило с системой в момент падения, хочется добраться до непосредственного источника проблемы, то Вы по адресу! Буду раз любым замечаниям и рекомендациям.
Определение типа объекта
Запускаем отладчик WinDbg из комплекта Debugging Tools for Windows, затем открываем через меню File - Open Crash Dump... имеющийся у нас на руках (желательно полный) дамп памяти.
В интерфейсе отладчика, в командной строке выполняем команду !analyze -v
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* CRITICAL_OBJECT_TERMINATION (f4) A process or thread crucial to system operation has unexpectedly exited or been terminated. Several processes and threads are necessary for the operation of the system; when they are terminated (for any reason), the system can no longer function. Arguments: Arg1: 0000000000000003, Process Arg2: fffffa801723e730, Terminating object Arg3: fffffa801723ea10, Process image file name Arg4: fffff800043849c0, Explanatory message (ascii) Debugging Details: ------------------ ETW minidump data unavailable DUMP_CLASS: 1 DUMP_QUALIFIER: 400 BUILD_VERSION_STRING: 7601.23539.amd64fre.win7sp1_ldr.160902-0600 SYSTEM_MANUFACTURER: MSI SYSTEM_PRODUCT_NAME: MS-7758 SYSTEM_SKU: To be filled by O.E.M. SYSTEM_VERSION: 1.0 BIOS_VENDOR: American Megatrends Inc. BIOS_VERSION: V2.4 BIOS_DATE: 06/19/2012 BASEBOARD_MANUFACTURER: MSI BASEBOARD_PRODUCT: Z77A-G43 (MS-7758) BASEBOARD_VERSION: 1.0 DUMP_TYPE: 2 BUGCHECK_P1: 3 BUGCHECK_P2: fffffa801723e730 BUGCHECK_P3: fffffa801723ea10 BUGCHECK_P4: fffff800043849c0 KERNEL_LOG_FAILING_PROCESS: (null) PROCESS_NAME: csrss.exe CRITICAL_PROCESS: csrss.exe IMAGE_NAME: csrss.exe DEBUG_FLR_IMAGE_TIMESTAMP: 0 MODULE_NAME: csrss FAULTING_MODULE: 0000000000000000 EXCEPTION_CODE: (Win32) 0x2119e060 (555343968) - ERROR_CODE: (NTSTATUS) 0x2119e060 - CPU_COUNT: 8 CPU_MHZ: da4 CPU_VENDOR: GenuineIntel CPU_FAMILY: 6 CPU_MODEL: 3a CPU_STEPPING: 9 CPU_MICROCODE: 6,3a,9,0 (F,M,S,R) SIG: 12'00000000 (cache) 12'00000000 (init) CUSTOMER_CRASH_COUNT: 1 DEFAULT_BUCKET_ID: WIN7_DRIVER_FAULT BUGCHECK_STR: 0xF4 CURRENT_IRQL: 0 ANALYSIS_SESSION_HOST: ANALYSIS_SESSION_TIME: 11-09-2016 10:30:42.0059 ANALYSIS_VERSION: 10.0.14321.1024 amd64fre STACK_TEXT: fffff880`239039d8 fffff800`0440fb22 : 00000000`000000f4 00000000`00000003 fffffa80`1723e730 fffffa80`1723ea10 : nt!KeBugCheckEx fffff880`239039e0 fffff800`043cd12b : 00000000`00000001 fffffa80`2119e060 fffffa80`1723e730 fffffa80`1f54eb01 : nt!PspCatchCriticalBreak+0x92 fffff880`23903a20 fffff800`04334eb4 : 00000000`00000001 00000000`0000239c fffffa80`1723e730 fffffa80`00000008 : nt! ?? ::NNGAKEGL::`string'+0x282c6 fffff880`23903a70 fffff800`0407a413 : 00000000`0000239c fffffa80`2119e060 fffffa80`1723e730 fffffa80`21c24950 : nt!NtTerminateProcess+0x284 fffff880`23903ae0 00000000`7736bdfa : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 00000000`2e94ebf8 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x7736bdfa STACK_COMMAND: kb THREAD_SHA1_HASH_MOD_FUNC: e9460336222f4471d8ae88a3d24ad7df3aff8ef1 THREAD_SHA1_HASH_MOD_FUNC_OFFSET: 9c238bf7ebe2405ac86e2eb68e7c228ca739e29c THREAD_SHA1_HASH_MOD: f08ac56120cad14894587db086f77ce277bfae84 FOLLOWUP_NAME: MachineOwner FAILURE_BUCKET_ID: X64_0xF4_csrss.exe_BUGCHECK_CRITICAL_PROCESS_TERMINATED_BY_ZennoPoster.ex_2119e060 BUCKET_ID: X64_0xF4_csrss.exe_BUGCHECK_CRITICAL_PROCESS_TERMINATED_BY_ZennoPoster.ex_2119e060 PRIMARY_PROBLEM_CLASS: X64_0xF4_csrss.exe_BUGCHECK_CRITICAL_PROCESS_TERMINATED_BY_ZennoPoster.ex_2119e060 TARGET_TIME: 2016-10-29T18:32:47.000Z OSBUILD: 7601 OSSERVICEPACK: 1000 SERVICEPACK_NUMBER: 0 OS_REVISION: 0 SUITE_MASK: 272 PRODUCT_TYPE: 1 OSPLATFORM_TYPE: x64 OSNAME: Windows 7 OSEDITION: Windows 7 WinNt (Service Pack 1) TerminalServer SingleUserTS OS_LOCALE: USER_LCID: 0 OSBUILD_TIMESTAMP: 2016-09-02 17:56:46 BUILDDATESTAMP_STR: 160902-0600 BUILDLAB_STR: win7sp1_ldr BUILDOSVER_STR: 6.1.7601.23539.amd64fre.win7sp1_ldr.160902-0600 ANALYSIS_SESSION_ELAPSED_TIME: aa9 ANALYSIS_SOURCE: KM FAILURE_ID_HASH_STRING: km:x64_0xf4_csrss.exe_bugcheck_critical_process_terminated_by_zennoposter.ex_2119e060 FAILURE_ID_HASH: {84f37c38-3c29-3fb1-11f5-e9b6e5d2d6f8} Followup: MachineOwner |
Вот это всё великое множество полей нам, конечно же, не потребуется. При анализе любого дампа памяти интерес для нас представляет, в первую очередь, описание и аргументы критической ошибки, которые следуют, как правило, непосредственно за "шапкой" Bugcheck Analysis:
1 2 3 4 5 6 7 8 9 10 11 |
CRITICAL_OBJECT_TERMINATION (f4) A process or thread crucial to system operation has unexpectedly exited or been terminated. Several processes and threads are necessary for the operation of the system; when they are terminated (for any reason), the system can no longer function. Arguments: Arg1: 0000000000000003, Process Arg2: fffffa801723e730, Terminating object Arg3: fffffa801723ea10, Process image file name Arg4: fffff800043849c0, Explanatory message (ascii) |
Процесс
Если в Аргументе 1 ошибки содержится указание на процесс (значение 3
, именование Process
), то мы имеем дело с падением процесса. Поскольку упавший объект является процессом, то выполняем следующую команду:
!process <Arg2> 3
Получаем структуру целевого процесса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
2: kd> !process fffffa801723e730 3 GetPointerFromAddress: unable to read from fffff800042b7000 PROCESS fffffa801723e730 SessionId: none Cid: 02b0 Peb: 7fffffdf000 ParentCid: 02a4 DirBase: 59d39d000 ObjectTable: fffff8a001f44a20 HandleCount: Image: csrss.exe VadRoot fffffa80199701a0 Vads 436 Clone 0 Private 3944. Modified 1425461. Locked 0. DeviceMap fffff8a000008c10 Token fffff8a001f445d0 ReadMemory error: Cannot get nt!KeMaximumIncrement value. fffff78000000000: Unable to get shared data ElapsedTime 00:00:00.000 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 1758712 QuotaPoolUsage[NonPagedPool] 57880 Working Set Sizes (now,min,max) (24353, 50, 345) (97412KB, 200KB, 1380KB) PeakWorkingSetSize 146524 VirtualSize 576 Mb PeakVirtualSize 918 Mb PageFaultCount 3554036 MemoryPriority BACKGROUND BasePriority 13 CommitCharge 4378 *** Error in reading nt!_ETHREAD @ fffffa8017abb970 |
информация содержит детализацию по выбранному процессу. Среди прочих параметров мы можем наблюдать в строке 6
и имя образа в виде поля с именем Image, содержащим значение csrss.exe.
Имя исполняемого образа процесса так же содержится в аргументе 3, поэтому мы можем получить его и другим способом, например выведя дамп памяти с адреса, хранящегося в аргументе 3:
dc <Arg3>
1 2 3 4 5 6 7 8 9 |
2: kd> dc fffffa801723ea10 fffffa80`1723ea10 73727363 78652e73 00000065 02000000 csrss.exe....... fffffa80`1723ea20 00000000 00000000 00000000 00000000 ................ fffffa80`1723ea30 00000000 00000000 17abbd98 fffffa80 ................ fffffa80`1723ea40 27ce6f78 fffffa80 00000000 00000000 xo.'............ fffffa80`1723ea50 00000000 00000000 0000000f 00000000 ................ fffffa80`1723ea60 00000000 400003e6 fffdf000 000007ff .......@........ fffffa80`1723ea70 00000000 00000000 00000001 00000000 ................ fffffa80`1723ea80 00000000 00000000 00005e5e 00000000 ........^^...... |
В дополнение к этому, то же имя исполняемого образа можно получить из структуры EPROCESS
:
1 2 3 |
2: kd> dt nt!_EPROCESS fffffa801723e730 imageFileName nt!_EPROCESS +0x2e0 ImageFileName : [15] "csrss.exe" |
Как мы видим, поле под названием ImageFileName
, содержащего имя образа, в структуре EPROCESS
имеет смещение 0x2e0
. Не стоит принимать это значение во внимание и тем более пытаться запомнить, поскольку структура EPROCESS
может, в зависимости от версии операционной системы, меняться. Например когда-то (если я не ошибаюсь) было вроде как значение 0x174 (?), если я не ошибаюсь.
Если нас интересует, то мы можем получить дамп памяти по адресу, где хранится ASCII-строка (аргумент 4 сведений об ошибке):
1 2 3 4 5 6 7 8 9 |
2: kd> dc fffff800043849c0 fffff800`043849c0 6d726554 74616e69 20676e69 74697263 Terminating crit fffff800`043849d0 6c616369 6f727020 73736563 25783020 ical process 0x% fffff800`043849e0 25282070 000a2973 90909090 90909090 p (%s).......... fffff800`043849f0 61657242 6f202c6b 67492072 65726f6e Break, or Ignore fffff800`04384a00 69622820 00203f29 90909090 90909090 (bi)? ......... fffff800`04384a10 74697243 6c616369 72687420 20646165 Critical thread fffff800`04384a20 70257830 6e692820 29732520 69786520 0x%p (in %s) exi fffff800`04384a30 0a646574 90909000 90909090 90909090 ted............. |
Поток
Помимо процесса, упавшим объектом может быть и поток в контексте процесса. Опять же, выяснить это можно по значению первого аргумента (Arg1) критической ошибки, если в нем содержится указание на поток (значение 6
, именование Thread
), то мы имеем дело с потоком внутри некоего процесса. Поскольку упавший объект является потоком, то мы выполняем соответствующую команду:
!thread <Arg2>
Получаем структуру целевого процесса:
1 |
2: kd> !thread fffffa801723e730 |
информация содержит детализацию по выбранному потоку. Однако, нам необходимо получить имя процесса, которому принадлежал поток. Подобную информацию, в данном случае, нам указывает аргумент 3 ошибки, который содержит имя исполняемого образа процесса. Поэтому, нам необходимо вывести дамп памяти с адреса, где хранится имя процесса:
dc <Arg3>
1 2 3 4 5 6 7 8 9 |
2: kd> dc fffffa801723ea10 fffffa80`1723ea10 73727363 78652e73 00000065 02000000 csrss.exe....... fffffa80`1723ea20 00000000 00000000 00000000 00000000 ................ fffffa80`1723ea30 00000000 00000000 17abbd98 fffffa80 ................ fffffa80`1723ea40 27ce6f78 fffffa80 00000000 00000000 xo.'............ fffffa80`1723ea50 00000000 00000000 0000000f 00000000 ................ fffffa80`1723ea60 00000000 400003e6 fffdf000 000007ff .......@........ fffffa80`1723ea70 00000000 00000000 00000001 00000000 ................ fffffa80`1723ea80 00000000 00000000 00005e5e 00000000 ........^^...... |
И аргумент 4 критической ошибки указывает на ASCII-строку с поясняющим сообщением, которое раскрывает характер ошибки. Для того, чтобы его посмотреть это сообщение, мы выводим дамп памяти по указанному в аргументе адресу:
1 2 3 4 5 |
2: kd> dc fffff800043849c0 fffff800`043849c0 6d726554 74616e69 20676e69 74697263 Terminating crit fffff800`043849d0 6c616369 6f727020 73736563 25783020 ical thread 0x% fffff800`043849e0 25282070 000a2973 90909090 90909090 p (in %s)....... . . . |
Поиск ключевых структур
Не важно, виновником останова у нас был процесс или же поток, в любом случае, после определения типа вызвавшего сбой объекта, дальнейшее изучение приводит нас сюда. Само определение типа объекта (процесс/поток) и имени объекта (имя процесса) дают нам лишь минимально-необходимый набор информации для дальнейшего осмысления проблемы. Конечно случаются и исключения, но в большинстве случаев в критической ошибке STOP 000000F4 участвует один из системных процессов, что усложняет дальнейший анализ. К примеру, виновником может запросто оказаться такой системный процесс, как csrss.exe или smss.exe, и что прикажете с этим фактом делать? Обновлять/заменять системные процессы не имеет смысла, поскольку если исключить явную подмену модуля (вследствие вирусной активности), что случается довольно редко, то обычно в системе присутствует самая актуальная версия. В этом случае вопрос ЧТО именно упало заменяется на вопрос ПОЧЕМУ данный процесс/поток упал? Природа критического сбоя такова, что настоящей причиной его может быть вовсе не сам процесс как таковой, а повреждение сторонних системных структур, например ошибка операции ввода-вывода при "подкачке" страницы из файла подкачки в физическую память. Все это подталкивает нас к мысли о необходимости дальнейшего исследования инцидента. В самом начале исследования ошибки STOP 000000F4, мы выполняли в отладчике Windbg команду !analyze -v
, а в выводе этой команды, в большинстве случаев, могут присутствовать дополнительные параметры, такие как код исключения в контексте процесса/потока. Попытайтесь найти в выводе структуру с именем EXCEPTION_RECORD
, она может быть в такой форме:
1 2 3 4 5 6 7 8 9 10 |
. . . EXCEPTION_RECORD: ffffffff -- (.exr ffffffffffffffff) ExceptionAddress: 77b92f4a (msvcrt!_mbsnbcpy+0x0000004f) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 00000001 Parameter[1]: 00000000 Attempt to write to address 00000000 . . . |
а может быть и в такой:
1 2 3 4 |
. . . EXCEPTION_CODE: (NTSTATUS) 0xc0000006 - ERROR_CODE: (NTSTATUS) 0xc0000006 - . . . |
..именно эта структура, в контексте данного сбоя, представляет особый интерес, поскольку имеет ряд значимых для дальнейшего изучения инцидента полей. Если структура присутствует в выводе, то обращаем внимания на поля ExceptionCode
/ EXCEPTION_CODE
и Parameter[x]
/ ERROR_CODE
, поскольку дальнейшее ориентирование будет происходить именно по их комбинациям. Поле ExceptionCode
указывает на код исключения (возможно с кратким описанием), а один из параметров Parameter[x]
может содержать уточняющую информацию о характере возникшего исключения. Итак, значение поля ExceptionCode
анализируется в совокупности с полями Parameter[x]
, обычно содержащими дополнительные коды ошибок, и только после этого выстраивается логическая цепочка дальнейших действий.
ExceptionCode: c0000006
Если поле ExceptionCode
содержит значение c0000006
(In-page I/O error), а второй параметр Parameter[2]: c000009a
(Insufficient system resources exist to complete the API), то полное описание ошибки выглядит следующим образом: "Inpage operation failed at <адрес>, due to I/O error c000009a", что переводится как "Ошибка страничной операции (ошибка подкачки страницы) в следствии ошибки ввода-вывода с кодом c000009a". Так же, статус завершения может содержаться в поле с именем ERROR_CODE
, а полная комбинированный код ошибки в поле EXCEPTION_STR
. Статус c000009a
, в свою очередь, указывает на недостаток системных ресурсов для завершения вызова API, а недостаток ресурсов, чаще всего, является следствием исчерпания памяти. Из всего этого следует, что мы имеем дело с утечкой памяти в одном из сторонних модулей режима ядра, которая привела к исчерпанию системных ресурсов (в данном случае памяти), а это, в свою очередь, вызвало ошибку ввода-вывода при подкачке страницы, поскольку некуда была эту страницу подгрузить.
Память это конечный системный ресурс, и хорошая практика состоит в том, что как только часть памяти (минимальная единица выделения) становится не нужной какому-либо исполняемому коду, она должна быть возвращена в общий пул посредством освобождения (маркировки как свободная). К сожалению, так случается не всегда. А иногда бывает, что ошибка в коде приводит к тому, что память вовремя не освобождается, а только постоянно резервируется. Естественно, что утечка происходит не в самих системных процессах (csrss.exe, smss.exe и прочих), которые могут фигурировать в качестве "упавшего" объекта, а где то еще, в каких-то сторонних модулях, работающих в ядре, скорее всего сторонних драйверах. Исчерпание ресурсов можно диагностировать различными способами, но в данной статье мы будем рассматривать способ с применением техник отладчика WinDbg.
Выполняем команду !vm 2
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
1: kd> !vm 2 *** Virtual Memory Usage *** Physical Memory: 889855 ( 3559420 Kb) Page File: \??\C:\pagefile.sys Current: 3866620 Kb Free Space: 3866616 Kb Minimum: 3866620 Kb Maximum: 10678260 Kb Available Pages: 691829 ( 2767316 Kb) ResAvail Pages: 807967 ( 3231868 Kb) Locked IO Pages: 0 ( 0 Kb) Free System PTEs: 279008 ( 1116032 Kb) Modified Pages: 26283 ( 105132 Kb) Modified PF Pages: 26279 ( 105116 Kb) Modified No Write Pages: 0 ( 0 Kb) NonPagedPool Usage: 6811 ( 27244 Kb) NonPagedPool Max: 522788 ( 2091152 Kb) PagedPool 0 Usage: 22068 ( 88272 Kb) PagedPool 1 Usage: 5782 ( 23128 Kb) PagedPool 2 Usage: 654 ( 2616 Kb) PagedPool 3 Usage: 687 ( 2748 Kb) PagedPool 4 Usage: 750 ( 3000 Kb) PagedPool Usage: 29941 ( 119764 Kb) PagedPool Maximum: 523264 ( 2093056 Kb) Session Commit: 6424 ( 25696 Kb) Shared Commit: 28641 ( 114564 Kb) Special Pool: 0 ( 0 Kb) Shared Process: 2181 ( 8724 Kb) Pages For MDLs: 1344 ( 5376 Kb) Pages For AWE: 0 ( 0 Kb) NonPagedPool Commit: 0 ( 0 Kb) PagedPool Commit: 29945 ( 119780 Kb) Driver Commit: 4252 ( 17008 Kb) Boot Commit: 0 ( 0 Kb) System PageTables: 0 ( 0 Kb) VAD/PageTable Bitmaps: 1073 ( 4292 Kb) ProcessLockedFilePages: 0 ( 0 Kb) Pagefile Hash Pages: 0 ( 0 Kb) Sum System Commit: 73860 ( 295440 Kb) Total Private: 98319 ( 393276 Kb) Misc/Transient Commit: 38686 ( 154744 Kb) Committed pages: 210865 ( 843460 Kb) Commit limit: 1856081 ( 7424324 Kb) |
обратите внимание, что в выводе отладчика я выделил поля с именами NonPagedPool Usage
, NonPagedPool Max
. Они относятся к такому важному системному ресурсу, как невыгружаемый и выгружаемый пулы.
Сразу отмечу, что выгружаемые пулы обычно не являются причиной аварийных ситуаций из-за утечек памяти, поскольку они могут быть выгружены на диск, в файл подкачки. Стоит обращать своё внимание именно на невыгружаемые пулы. В случае, когда значения невыгружаемых пулов NonPagedPool Usage
~= NonPagedPool Max
, можно сделать вывод об наличии факта исчерпания пулов. В дополнение, в выводе могут встретиться такие строки как Excessive NonPaged Pool Usage и ???? pool allocations have failed, которые так же являются характерными признаками исчерпания пулов. Теперь мы можем вывести список всех процессов, использующих невыгружаемые пулы:
!poolused 7
Расширение !poolused
даёт сводку по использованию памяти, на основании тэгов, применяемых для каждого пула, то есть показывает использование памяти для каждого тэга. Сам тэг характеризует конкретный модуль в ядре. Таким образом, !poolused
собирает данные из механизма маркируемых пулов (pool tagging, группируемые по тэгу пулы), которая постоянно включена в ядре только в версиях Windows 2003 и старше. В расширении используются флаги, которые регламентируют количество выводимых данных и метод сортировки:
- Bit 0 (0x1) -- Включает детализированный вывод;
- Bit 1 (0x2) -- Сортирует вывод по количеству невыгружаемой памяти;
- Bit 2 (0x4) -- Сортирует вывод по количеству выгружаемой памяти;
- Bit 3 (0x8) -- Отображает вместо стандартных пулов пулы сессии;
Флаг 2 команды используется для вывода объема использования невыгружаемых пулов, 4 показало бы выгружаемые пулы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
7: kd> !poolused 7 ........ Sorting by NonPaged Pool Consumed NonPaged Paged Tag Allocs Frees Diff Used Allocs Frees Diff Used @GMM 86 63 23 2291256 1 0 1 2097152 (Intel video driver) Memory manager Cont 267 8 259 2154640 0 0 0 0 Contiguous physical memory allocations for device drivers EtwB 179 109 70 1779736 2 0 2 131072 Etw Buffer , Binary: nt!etw VHAL 15 0 15 1578176 0 0 0 0 UNKNOWN pooltag 'VHAL', please update pooltag.txt Ntfx 9682 1852 7830 1469264 0 0 0 0 General Allocation , Binary: ntfs.sys File 82334 74244 8090 1446864 0 0 0 0 File objects VoSm 62 41 21 1240192 0 0 0 0 Bitmap allocations , Binary: volsnap.sys Pool 13 8 5 1156680 0 0 0 0 Pool tables, etc. MmCa 6578 564 6014 904208 0 0 0 0 Mm control areas for mapped files , Binary: nt!mm FMsl 9240 1461 7779 809016 0 0 0 0 STREAM_LIST_CTRL structure , Binary: fltmgr.sys Thre 2216 1456 760 563216 0 0 0 0 Thread objects , Binary: nt!ps IU3C 23 22 1 483328 73 71 2 48 IIS Utility Driver Mm 443 434 9 456448 65 62 3 88 general Mm Allocations , Binary: nt!mm MmCi 1592 0 1592 423008 0 0 0 0 Mm control areas for images , Binary: nt!mm 0AEC 189 2 187 414896 0 0 0 0 UNKNOWN pooltag '0AEC', please update pooltag.txt AmlH 6 0 6 393216 0 0 0 0 ACPI AMLI Pooltags Devi 383 42 341 344960 0 0 0 0 Device objects . . . |
список обычно выдается просто огромный и приводить его тут целиком не имеет особого смысла, поэтому я показал лишь небольшую его часть, верхнюю. Конкретно в этом дампе у меня нет необходимой информации, однако обычно из подробного вывода видно, что у какой-то метки пула может присутствовать очень большое значение (обычно сотни тысяч) в столбце Diff у группировки NonPaged, которое говорит о том, что память, маркированная данным тэгом постоянно резервируется, но при этом мало освобождается. Если в столбце Tag
присутствует значение Irp, то имеются в виду IRP-пакеты (I/O request packet, пакеты запроса ввода-вывода), которые используются для обмена данными с драйверами. Поэтому, мы можем обратить своё внимание на пакеты драйверов (IRP), поскольку они могут дать нам подсказку по функциям, интенсивно использующим память. Для этого используем команду !irpfind
отладчика:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
7: kd> !irpfind Scanning large pool allocation table for tag 0x3f707249 (Irp?) (86bfb000 : 86cfb000) Irp [ Thread ] irpStack: (Mj,Mn) DevObj [Driver] MDL Process 8612d828 [8760e030] irpStack: ( e,20) 868b4198 [ \Driver\AFD] 0x8759d6f8 87625530 [875e4398] irpStack: ( d, 0) 86110de8 [ \FileSystem\Npfs] 8619ec08 [8788c030] irpStack: ( e, 3) 868b4198 [ \Driver\AFD] 86eb8ad0 [876b30e0] irpStack: ( e,20) 868b4198 [ \Driver\AFD] 0x876a5980 87d31d20 [857a3c20] irpStack: ( e,2d) 868b4198 [ \Driver\AFD] 861a5c08 [00000000] Irp is complete (CurrentLocation 3 > StackCount 2) 86ac28e0 [00000000] Irp is complete (CurrentLocation 2 > StackCount 1) 0x00000000 86e911d0 [00000000] Irp is complete (CurrentLocation 7 > StackCount 6) Searching nonpaged pool (80000000 : ffc00000) for tag 0x3f707249 (Irp?) 8563fe90 [00000000] irpStack: ( f, 0) 00000000 [00000000: Could not read device object or _DEVICE_OBJECT not found ] 856a2210 [00000000] irpStack: ( f, 0) 861d1b90 [ \Driver\ACPI] 856a2600 [00000000] irpStack: (16, 0) 8563f328 [ \Driver\ACPI] 856bb008 [00000000] Irp is complete (CurrentLocation 31 > StackCount 30) 856bb6a8 [00000000] Irp is complete (CurrentLocation 31 > StackCount 30) 856bbb58 [00000000] Irp is complete (CurrentLocation 31 > StackCount 30) 856bf368 [87611030] irpStack: ( d, 0) 86110de8 [ \FileSystem\Npfs] 856bf420 [00000000] Irp is complete (CurrentLocation 31 > StackCount 30) 856bf8d0 [00000000] Irp is complete (CurrentLocation 31 > StackCount 30) 856e30d8 [00000000] Irp is complete (CurrentLocation 2 > StackCount 1) 85713ae0 [876f7d48] irpStack: ( e,2d) 868b4198 [ \Driver\AFD] 85718300 [00000000] Irp is complete (CurrentLocation 2 > StackCount 1) 857190a0 [87b7ad48] irpStack: ( d, 0) 86110de8 [ \FileSystem\Npfs] 85719aa0 [87837420] irpStack: ( e, 0) 8782bd10 [ \Driver\mpsdrv] 8571a008 [87ace828] irpStack: ( c, 2) 86734020 [ \FileSystem\Ntfs] 857676a8 [87b25d48] irpStack: ( e, 0) 86f0e030 [*** ERROR: Module load completed but symbols could not be loaded for iusb3hub.sys \Driver\iusb3hub] 85768d48 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 85775840 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 85776408 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 85776cc8 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 85777338 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 85777ce0 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 857861d8 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 857b2928 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 857b3090 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) 857b5028 [00000000] Irp is complete (CurrentLocation 4 > StackCount 3) . . . |
!irpfind
может быть ЧУДОВИЩНО БОЛЬШИМ! У меня последний раз при дампе размером в 4 гигабайта, операция выполнялась в течении нескольких часов.Список, традиционно, не маленький, и я привел лишь небольшую его часть. По команде !pool
1 2 3 4 5 6 7 8 9 |
7: kd> !pool 8612d828 Pool page 8612d828 region is Nonpaged pool 8612d808 size: 8 previous size: 0 (Allocated) Frag 8612d810 size: 10 previous size: 8 (Allocated) ViMm *8612d820 size: 108 previous size: 10 (Allocated) *Irp Pooltag Irp : Io, IRP packets 8612d928 size: 2f8 previous size: 108 (Allocated) IdeP 8612dc20 size: 2f0 previous size: 2f8 (Allocated) Ioin 8612df10 size: f0 previous size: 2f0 (Allocated) PlWl |
По команде !irp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
7: kd> !irp 8612d828 Irp is active with 4 stacks 4 is current (= 0x8612d904) Mdl=879e43f0: No System Buffer: Thread 8760e030: Irp stack trace. cmd flg cl Device File Completion-Context [N/A(0), N/A(0)] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 [N/A(0), N/A(0)] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 [N/A(0), N/A(0)] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 >[IRP_MJ_DEVICE_CONTROL(e), N/A(20)] 5 1 868b4198 87a11420 00000000-00000000 pending \Driver\AFD Args: 00000000 00000090 00000090 87a1d818 |
Как мы можем видеть, в последних строках есть ссылка на драйвер устройства, которому предназначался IRP пакет: \Driver\AFD
. У нас имя драйвера устройства было сразу видно в выводе команды !irpfind
, приведенном выше, однако если Вам по каким-либо причинам необходимо узнать имя драйвера, то можно выполнить команду !devstack <Device>
(адрес из колонки Device), которая получает информацию об устройстве, получившем IRP пакет:
1 2 3 |
7: kd> !devstack 868b4198 !DevObj !DrvObj !DevExt ObjectName > 868b4198 \Driver\AFD 00000000 Afd |
При обнаружении стороннего драйвера, информацию по нему можно посмотреть командной
lmvm <имя_драйвера>
1 2 3 4 5 6 7 8 9 10 11 12 |
7: kd> lmvm iusb3xhc Browse full module list start end module name 91d11000 91dd7000 iusb3xhc (no symbols) Loaded symbol image file: iusb3xhc.sys Image path: \SystemRoot\system32\DRIVERS\iusb3xhc.sys Image name: iusb3xhc.sys Browse all global symbols functions data Timestamp: Tue Oct 16 18:48:18 2012 (507D81C2) CheckSum: 000C5843 ImageSize: 000C6000 Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4 |
Стоит обращать внимание на время создания стороннего драйвера, поскольку некоторые проблемы могут вызывать драйвера, выпущенные довольно давно и плохо работающие в среде актуальной операционной системы.
ExceptionCode: c0000005
Если поле ExceptionCode
содержит значение c0000005 (Access Violation), то мы, скорее всего, имеем дело с нарушением доступа, возможно возникшим по причине отсутствия необходимой страницы в физической (оперативной) памяти. Вероятно, проблема кроется в контроллере/жестком диске.
EXCEPTION_RECORD отсутствует
Встречаются ситуации, когда структуры EXCEPTION_RECORD
просто нет! Если автоматизированный анализ Windbg не смог получить структуру EXCEPTION_RECORD
из дампа, и нет никакого упоминания о возникшем в процессе/потоке исключении, то у нас есть несколько вариантов.
Анализ стека вызовов
Первое, что можно сделать, это попытаться разобраться в стеке вызовов. Вот характерный пример из дикой природы. Имелся дамп памяти с такими вот аргументами ошибки:
1 2 3 4 5 |
Arguments: Arg1: 00000003, Process Arg2: 86933020, Terminating object Arg3: 8693318c, Process image file name Arg4: 82e279d0, Explanatory message (ascii) |
Затем, из того же вывода команды !analyze -v
получаем стек момента падения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
. . . STACK_TEXT: 90437a04 82eee983 000000f4 00000003 86933020 nt!KeBugCheckEx+0x1e 90437a28 82e6b0cb 82e279d0 8693318c 86933020 nt!PspCatchCriticalBreak+0x71 90437a58 82ea119e 86933020 87aad430 c0000354 nt!PspTerminateAllThreads+0x2d 90437a84 82ebd35c c0000354 85627a58 87cfee68 nt!PsTerminateProcess+0xb0 90437aa8 82e32ced 86933020 87cfee80 00000000 nt!DbgkpCloseObject+0x19f 90437af4 82e54549 857fd6c0 ad67f488 87aad430 nt!ObpDecrementHandleCount+0x139 90437b38 82e83265 9677e958 ad67f488 857fd6c0 nt!ObpCloseHandleTableEntry+0x203 90437b68 82e6b433 9677e958 90437b7c 9105c030 nt!ExSweepHandleTable+0x5f 90437b88 82e78235 ba04a89c 857fd6c0 87aad430 nt!ObKillProcess+0x54 90437bfc 82e6af16 7ffd8000 ffffffff 0442fe44 nt!PspExitThread+0x5e4 90437c24 82c47db6 ffffffff 00000000 0442fe50 nt!NtTerminateProcess+0x12e 90437c24 76fc6c74 ffffffff 00000000 0442fe50 nt!KiSystemServicePostCall 0442fe30 76fc649c 76fde01d ffffffff 00000000 ntdll!KiFastSystemCallRet 0442fe34 76fde01d ffffffff 00000000 00000000 ntdll!ZwTerminateProcess+0xc 0442fe50 7592bdf6 00000000 77e8f3b0 ffffffff ntdll!RtlExitUserProcess+0x85 0442fe64 00c81451 00000000 00000000 62d01940 kernel32!ExitProcessStub+0x12 0442fe84 00c675b0 a9f094ce 00000000 00000000 windbg!ExitDebugger+0x8b 0442fec0 7591ef1c 00000000 0442ff0c 76fe367a windbg!EngineLoop+0x850 0442fecc 76fe367a 00000000 73440776 00000000 kernel32!BaseThreadInitThunk+0xe 0442ff0c 76fe364d 00c66d60 00000000 00000000 ntdll!__RtlUserThreadStart+0x70 0442ff24 00000000 00c66d60 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b . . . |
Обратите внимание на выделенные строки 5
и 7
. Поскольку разбор стека идет снизу вверх, то вызов функции в строке 7
произошел ранее, и здесь мы видим функцию nt!DbgkpCloseObject
, а что у неё в одном из аргументов? Значение 86933020
, которое является идентификатором прерванного процесса smss.exe (обратите внимание на параметр 2 (Arg2) сбоя). Далее, по цепочке вызовов движемся вверх и доходим до строки 5
, видим там вызов функции nt!PspTerminateAllThreads
, среди агрументов которой опять обнаруживаем знакомый идентификатор процесса 86933020
, а заодно и параметр c0000354
. Этот параметр есть ни что иное, как код NTSTATUS, то есть статус завершения операции. Вероятно, функция nt!PspTerminateAllThreads
принудительно завершает все потоки процесса с идентификатором 86933020
и со статусом c0000354
, который по описанию интерпретируется как STATUS_DEBUGGER_INACTIVE
, а расшифровывается как Попытка произвести действие с отладочным портом не удалась, порт находится в процессе удаления. Кто-то просто-напросто закрыл отладчик, который был подключен в разрушающем (агрессивном, invasive) режиме к системному процессу smss.exe. История кажется фантастической? Отнюдь, поскольку именно этот STOP я специально сэмулировал на тестовой машине, произведя как раз описанные выше действия :) Конечно, вероятность возникновения подобного сферического BSOD в вакууме в дикой природе довольно мала, однако пример показывает нам, что процесс анализа дампа - это как правило творческое занятие.
Анализ поля ExitStatus
Ну если уж при анализе дампа другими методами вообще никакой полезной информации получить не удалось, то можно попытаться получить хоть какую-то информацию по коду завершения из структуры EPROCESS
, воспользовавшись следующей командой:
dt nt!_EPROCESS <Arg2> ExitStatus
в случае отсутствия иной информации о проблеме, статус завершения может дать нам хотя бы мизерный шанс к дальнейшему продвижению.
1 2 3 |
2: kd> dt nt!_EPROCESS fffffa801723e730 ExitStatus nt!_EPROCESS +0x444 ExitStatus : 0n259 |
ExitStatus
представлен в десятичном формате, поэтому для вычисления выражения (перевод в 16-ричную систему), можно использовать следующую команду:
1 2 |
2: kd> ? 0n259 Evaluate expression: 259 = 00000103 |
А затем уже, имея шестнадцатеричное представление, можно найти общую информацию по коду ошибки посредством команды:
!error <NTSTATUS>
если информацию по ошибке встроенными средствами получить не удалось, её всегда можно найти на странице NTSTATUS.
Замечания
Однако в некоторых случаях, из дампа мы не можем получить ни кода исключения, ни кода ошибки, а видим примерно такой вот результат:
1 2 3 4 |
. . . EXCEPTION_CODE: (Win32) 0x2119e060 (555343968) - ERROR_CODE: (NTSTATUS) 0x2119e060 - . . . |
то есть автоматика Windbg данных кодов из дампа получить не смогла, быть может это связано с тем, что во время сбоя логика формирования дампа, по какой-то причине, не смогла заполнить структуру, либо заполнила её на основании каких-либо некорректных данных, попавших туда ошибочно. Выполнение команды по запросу статуса выхода
1 2 3 |
2: kd> dt _EPROCESS fffffa801723e730 ExitStatus nt!_EPROCESS +0x444 ExitStatus : 0n-1 |
выдает вообще какой-то фантастический код 0n-1
(0xFFFFFFFF
)!! Могу ошибаться, но может быть это вызвано тем, что при конкретный дамп представляет собой минидамп и не содержит в себе необходимых структур?
STOP 0x000000F4 - CRITICAL_OBJECT_TERMINATION
Image: csrss.exe
ExceptionCode: c0000006 (In-page I/O error)
Parameter[2]: 00000000c000000e
Inpage operation failed at 000007fefd3fe8c0, due to I/O error 00000000c000000e
Подскажите, пожалуйста, на что указывает в данном случае 2-ой параметр ?
судя по всему значение второго параметра = C000000E, что есть STATUS_NO_SUCH_DEVICE.
через analyze -v в подробностях нет подробного описания EXCEPTION_CODE (NTSTATUS) с расшифровкой?
Судя по всему ошибка ввода-вывода при подкачке страницы случилась потому, что что-то произошло с устройством, с которого критический для системы файл "подкачивался". Устройство = какой-то из дисков (HDD/SSD) в системе.. Проверяйте контроллер, диск, кабель.. ну это так, по NTSTATUS, поскольку Вы вряд ли сможете предоставить полный дамп?
EXCEPTION_CODE: (NTSTATUS) 0xc0000006 - The instruction at 0x%p referenced memory at 0x%p. The required data was not placed into memory because of an I/O error status of 0x%x.
В системе 1 hdd seagate 1ТБ (новая прошивка для него не выходила).
Полного дампа нет (в списке нет данного типа в системе windows 7 pro x64), есть дамп ядра и мини дамп.
HDD проверял различными программами: SeaTools, MHDD, Victoria, тест поверхности в норме, смарт атрибуты тоже в порядке.
Также проверил RAM и сделал антивирусную проверку, также всё в порядке.
BIOS последней версии, но от 2012 года.
Тоже подумал, что какая-то проблема с hdd из-за таких упоминаний:
IO_ERROR: (NTSTATUS) 0xc000000e - A device which does not exist was specified.
MODULE_NAME: hardware_disk
IMAGE_NAME: hardware_disk
FAILURE_BUCKET_ID: X64_0xF4_csrss.exe_BUGCHECK_CRITICAL_PROCESS_3bab980_IMAGE_hardware_disk
В стеке не смог разобраться, не знаю что это за функции.
STACK_TEXT:
fffff880`02e9b108 fffff800`02e0e292 : 00000000`000000f4 00000000`00000003 fffffa80`03b01060 fffffa80`03b01340 : nt!KeBugCheckEx
fffff880`02e9b110 fffff800`02dcc68b : 00000000`00000001 fffffa80`03bab980 fffffa80`03b01060 00000000`001b1200 : nt!PspCatchCriticalBreak+0x92
fffff880`02e9b150 fffff800`02d35684 : 00000000`00000001 ffffffff`ffffffff fffffa80`03b01060 00000000`00000008 : nt! ?? ::NNGAKEGL::`string'+0x26ea6
fffff880`02e9b1a0 fffff800`02a7a093 : ffffffff`ffffffff fffffa80`03bab980 fffffa80`03b01060 00000000`001b0cb0 : nt!NtTerminateProcess+0x284
fffff880`02e9b210 fffff800`02a76650 : fffff800`02ab7475 fffff880`02e9bb78 fffff880`02e9b8e0 fffff880`02e9b3e0 : nt!KiSystemServiceCopyEnd+0x13
fffff880`02e9b3a8 fffff800`02ab7475 : fffff880`02e9bb78 fffff880`02e9b8e0 fffff880`02e9b3e0 fffff880`02e9bb78 : nt!KiServiceLinkage
fffff880`02e9b3b0 fffff800`02a7a48e : fffff880`02e9bb78 00000000`c0000006 fffff880`02e9bc20 00000000`001b1328 : nt!KiDispatchException+0x534
fffff880`02e9ba40 fffff800`02a78ffa : 00000000`00000000 000007fe`fd3fe8c0 00000000`00000001 00000000`00011c50 : nt!KiExceptionDispatch+0xce
fffff880`02e9bc20 00000000`77798042 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiPageFault+0x23a
00000000`001b1270 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x77798042
BSOD происходит редко примерно 1,2 раза в неделю.
Спасибо за помощь.
IO_ERROR: (NTSTATUS) 0xc000000e - A device which does not exist was specified.
кстати, почитайте о дампе: http://datadump.ru/windows-crash-dump/
на замену есть hdd/мать/кабель попробовать?
Спасибо, в статье нашел, что можно изменить на полный дамп памяти, изменив значение в реестре.
Есть шлейф, но смарт атрибут UltraDMA CRC Error Count в норме.
К подозреваемым можно ещё БП добавить, но всё это проверить заменой пока нет возможности.
дело в том, что причину многих аппаратных сбоев невозможно точно определить по анализу дампа. такова специфика архитектуры, к сожалению. быть может, на каком-то очень высоком уровне знания возможно выявить однозначные закономерности различных структур ядра, но я на этом уровне пока не нахожусь :) дамп сделаете?
Да, поменял в настройках с дампа ядра на полный дамп.
делайте, а там поглядим. если конечно получится.
Есть полный дамп
выкладывайте, давайте ссылку
https://yadi.sk/d/ZqutVoEm3Pua5b
Ничего интересного я лично не обнаружил. Попробуйте обновить сторонние программы/драйвера:
SystemRoot\system32\DRIVERS\Rt64win7.sys
SystemRoot\system32\DRIVERS\dtlitescsibus.sys
SystemRoot\system32\DRIVERS\dtliteusbbus.sys
SystemRoot\system32\DRIVERS\igdkmd64.sys
SystemRoot\system32\drivers\RTKVHD64.sys
Windows\system32\Drivers\SSPORT.sys
SystemRoot\system32\drivers\intelide.sys
SystemRoot\system32\DRIVERS\intelppm.sys
ну а далее пробуйте со шлейфом/диском, как и было предложено ранее..
Хорошо, спасибо
Помогла замена HDD. BSOD-а нет уже около месяца.
спасибо Вам за отзыв, подобная статистика будет полезна читателям.
Статья хорошая, спасибо. Но зачастую всё бывает гораздо проще - проблемы с физ. планками памяти, например. Их по дампу не найдёшь.
Да, вероятно Вы правы. У меня наработок по анализу дампов немного, поэтому не могу делать никаких глобальных выводов. Из личной практики: один раз сбойная видеокарта генерировала 5 (!) разнообразных STOP-кодов. Подобное сразу навело на мысль о сбойном железе, поскольку не часто увидишь такую рандомизацию :) Возможно сбои оперативной памяти ведут себя подобным образом: генерируя STOP в абсолютно разных подсистемах ОС, что исключает какую-либо логику. Но, опять же, более информативным было бы мнение специалистов, которые занимаются анализом сбоев в промышленных масштабах.