Раздел: Документация
0 ... 90 91 92 93 94 95 96 ... 102 ПОДКЛЮЧЕНИЕ ДАМПА ПАМЯТИ Для подключения дампа памяти к отладчику Windows Debugger (windbg.exe) в меню File выберите пункт Crash Dump или воспользуйтесь комбинацией клавиш Ctrl+D. В отладчике i386kd.exe для той же пели служит ключ -z командном строки, за которым следует полный путь к файлу дампа, отделенный от ключа одним или несколькими пробелами, при этом переменная окружения NTSYMBOLPATH должна быть определена и должна содержать полный путь к файлам символьных идентификаторов, в противном случае отладчик аварийно завершит свою работу. Как один из вариантов можно указать в командой строке ключ -у, и тогда экран консоли будет выглядеть так: i386kd -z C:\WINNT\ memory.dmp -у C:\WINNT\Symbols, причем отладчик следует вызывать из консоли Checked Build Environment/Free Build Environment, находящейся в папке Windows 2000 DDK, иначе у вас ничего не получится. Хорошая идея — ассоциировать dmp-файлы с отладчиком i386kd, запуская их одним ударом но клавише Enter из FAR. Впрочем, выбор средства анализа — дело вкуса. Кому-то нравится KAnalyze, а кому-то достаточно и простенького DumpChk. Выбор аналитических инструментов чрезвычайно велик (один лишь DDK содержит четыре из них!), и, чтобы хоть как-то определиться с выбором, мы остановимся на i386kd.exe, также называемом Kernel Debugger. Как только консоль отладчика появится на экране (a Kernel Debugger — это консольное приложение, горячо любимое всеми, кто провел свою молодость за текстовыми терминалами), курсор наскоро дизассемблирует текущую машинную инструкцию и своим тревожным мерцанием затягивает нас в пучину машинного кода. 11у что, глазки строить будем или все-таки дисассемблировать? — незлобно ворчим мы, выбивая па клавиатуре команду и, заставляющую отладчик продолжить днзассемблпрование. Судя по символьным идентификаторам PspUnhandledExceptionlnSystemThread и KeBugCheckEx, мы находимся глубоко в ядре, а точнее — в окрестностях того кода, что выводит BSOD на экран (листинг А.20). Листинг А.20. Результат дизассемблирования подключенного дампа памяти с текущего адреса 8045249с 6а01push 0x1 kd>u PsDUnhand!edExceptionInSyste,nIhread(a4: 80452484 8В442404 mov eax. dword ptr [esp+4]
В стеке ничего интересного также не содержится, вот судите сами (просмотр содержимого стека осуществляется командной kb) (листинг А.21). Листинг А.21. Одержимое стека не дает никаких намеков на природу истинного виновника kd> kD ChildEBP RetAddr Args to Child f403f71c 8045251c f403f744 8045CC77 f403f74c ntoskrnl!PspUnhandledExcepti onInSystemThread+0xl8 f403fddc 80465b62 80418ada 00000001 00000000 ntoskrnl!PspSystemThreadStartup0x5e 00000000 00000000 00000000 00000000 00000000 ntoskrnl!KiThreadStartup+0xl6 Такой поворот событий ставит нас в тупик. Сколько бы мы ни дизассембл провали ядро, это ни на йоту не приблизит нас к источнику критической ошибки. Что ж, все вполне логично. Текущий адрес (8045249Ch) лежит далеко за пределами драйвера-убийцы (0BE80A00h). Хороню, давайте развернемся и пойдем другим путем. Помните тот адрес, что высвечивал голубой экран смерти? Не помните — не беда! Если это только не запрещено настройками, копии всех голубых экранов сохраняются в Журнале системы. Откроем его (Панель управления ► Администрирование ► Просмотр событий) (листинг А.22). Листинг А.22. Копия голубого экрана смерти, сохраненная в системном журнале Компьютер был перезагружен после критической ошибки: 0х0000001е (ОхсООООООБ. 0xbe80b000. 0x00000000. 0x00000000)•- . Microsoft Windows 2000 [vls.2195] Копия памяти сохранена: C:\W1NNT\MEM0RY.DMP Отталкиваясь от категории.критической ошибки (OxlE), мы без труда сможем определить адрес инструкции-убийцы — 0хВЕ80В000 (в приведенном выше листинге он выделен полужирным шрифтом). Даем команду u ВЕ80В000 для просмотра его содержимого (листинг А.23). Листинг А.23. Результат дезассемблирования дампа памяти по адресу, сообщенному голубым экраном смерти kd>u 0хВЕ80В000 Ье80Ь000 аЮООООООО том еах. [00000000] Ье80Ь005 C20800ret 0x8 Ье80Ь008 90nop Ье80Ь009 90nop Ье80Ь00а 90nop be80D0Ob 90nop be80b00c 90nop be80b00d 90nop Ага! Вот это уже больше похоже на истину! Инструкция, на которую указыв курсор (в тексте она выделена жирным), обращается к ячейке с нулевым аДР сом, возбуждая тем самым губительное для системы исключение. Теперь • точно знаем, какая ветка программы вызвала сбой. Хорошо, а как быть, если копии экрана смерти и нашем распоряжении нет? На самом деле- синий экран всегда с нами, надо только знать, где искать! Попробуйте открыть файл дампа в любом hex-редакторе, и вы обнаружите следующие строки: 0С000000: 50 41 47 45 44 55 4D 50 ! OF ОС 00 00 93 08 09 ОС JAGEDUMP0 У. C000C01D: 00 00 03 00 00 80 8В 6. СО 46 80 80 А! 46 80 AJlbLflFAAoTA. 00000020: 4С 01 00 СО 01 00 00 ОС ! 1Е ОС 00 00 05 00 ОС СО L0 0 * L 00000030: 00 ВО 80 BE 00 00 00 СО СО СО 00 00 00 41 47 45 -A- AGE С первого же взгляда удается опознать все основные Bug Check-параметры: IE 00 00 00 — это код категории сбоя OxlE (на х86-нроцессорах наименее значимый бант располагается по меньшему адресу, то есть все числа записываются задом наперед); 05 00 00 СО — код исключения ACCESS VIOLATION; а 00 ВО 80 BE — и есть адрес машинной команды, породившей это исключение. В комбинации же 0F 00 00 00 93 OB легко узнается помер билда системы, стоит только записать его в десятичной нотации. Для просмотра Bug Check-параметров и удобочитаемом виде можно воспользоваться командой отладчика dd KiBugCheckData (листинг А.24). Листинг А.24. Bug Check-параметры, отображаемые в удобочитаемом виде kd> dd KiBugCheckCaia dd KiBugCheckData B047e6c0 OOOOOOle C0000005 be80b00000000000 8047e6d0 00000000 00OOOCOO OOOCOG01C0OOO0C0 8047e6e0 00000000 C00COOC0 OOOOOOCO000С0С00 8047e6f0 OOOOOCOC 00000000 ooooococcooococo 8047e700 OOOOOOCO G00OOO00 00000000ooococoo 8047O710 00000000 OOOOOOOC 0000000000000000 B047e720 00000000 C0OO0O00 OOOOOOOC00000000 8047C730 00000000 eOffffff edffffffC0020000 Другие полезные команды: drivers — выводящая список драйверов, загруженных на момент сбоя; arbiter — показывающая всех арбитров вместе с диапазонами арбитража; filecache — отображающая информацию о кэше файловой системы и РТ; vm — отчитывающаяся об использовании виртуальной памяти. т- Д., н т. и. — всех не перечислишь! (Полный перечень команд вы найдете в руководстве по своему любимому отладчику.) Конечно, в реальной жизни определить истинного виновника краха системы "«•много сложнее, поскольку всякий нормальный драйвер состоит из множе-Ства сложно взаимодействующих функций, образующих запутанные иерархи- еские комплексы, местами пересеченные туннелями глобальных переменных, Превращающих драйвер в самый настоящий лабиринт. Приведем только один Пример. Конструкция вида mov еах. [ebx], гдееЬх = 0, работает вполне нормаль-послушно возбуждая исключение, и пытаться поговорить с пен но-мужс- н — бессмысленно! Нужно найти тот код, который записывает в ЕВХ нулевое Зак У76 0 ... 90 91 92 93 94 95 96 ... 102
|