Поделиться через


Включение отладки после сбоя

Обработка исключений в режиме пользователя

Исключения и точки останова

Наиболее распространенные ошибки приложения называются исключениями. К ним относятся нарушения доступа, ошибки деления на нуль, числовые переполнения, исключения CLR и многие другие виды ошибок. Приложения также могут вызывать прерывания, вызванные точкой останова. Они возникают, когда Windows не может запустить приложение (например, если не удается загрузить необходимый модуль) или при обнаружении точки останова. Точки останова можно вставить в код отладчиком или вызвать через функцию, например DebugBreak.

Приоритет обработчиков исключений

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

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

    Если отладчик пользовательского режима подключен, другие методы обработки ошибок не будут использоваться, даже если используется команда gn (Go With Exception Not Handled).

  2. Если отладчик пользовательского режима не подключен, и исполняемый код имеет собственные подпрограммы обработки исключений (например, попробуйте за исключением), эта подпрограмма обработки исключений попытается справиться с ошибкой.

  3. Если отладчик пользовательского режима не подключен, и Windows имеет открытое подключение к отладке ядра, и ошибка является прерыванием точки останова, Windows попытается связаться с отладчиком ядра.

    Подключения отладки ядра должны быть открыты во время загрузки Windows. Если вы хотите запретить прерывание пользовательского режима отладчику ядра, можно использовать служебную программу KDbgCtrl с параметром -du . Дополнительные сведения о настройке подключений к отладке ядра и использовании KDbgCtrl см. в статье "Настройка для отладки".

    В отладчике ядра можно использовать gh (Go With Exception Handled), чтобы игнорировать ошибку и продолжить выполнение целевого объекта. Вы можете использовать gn (Go With Exception Not Handled) для обхода отладчика ядра и перейти к шагу 4.

  4. Если условия, описанные в шагах 1, 2 и 3, не применяются, Windows активирует средство отладки, настроенное в значениях реестра AeDebug. Любую программу можно выбрать заранее в качестве средства, используемого в этой ситуации. Выбранная программа называется postmortem debugger.

  5. Если условия, описанные в шагах 1, 2 и 3, не применяются, и нет зарегистрированного посмертного отладчика, служба отчета об ошибках Windows (WER) отображает сообщение и предоставляет решения, если они доступны. WER также записывает файл дампа памяти, если соответствующие значения заданы в реестре. Дополнительные сведения см. в разделе Использование WER и Сбор дампов User-Mode.

Функция DebugBreak

Если отладчик постмортем установлен, вы можете намеренно вызвать отладчик из приложения пользовательского режима, вызвав функцию DebugBreak.

Указание отладчика Postmortem

В этом разделе описывается, как настраивать такие инструменты, как WinDbg, в качестве отладчика postmortem. После настройки отладчик postmortem будет автоматически запущен при сбое приложения.

Разделы реестра отладчика Post Mortem

Отчеты об ошибках Windows (WER) создают процесс отладки, выполняемый после завершения программы, используя значения, заданные в разделе реестра AeDebug.

HKLM\Программное обеспечение\Корпорация Майкрософт\Windows NT\CurrentVersion\AeDebug

Существует два основных значения реестра, Debugger и Auto. Значение реестра Debugger указывает командную строку для посмертного отладчика. Значение реестра Auto указывает, запускается ли отладчик postmortem автоматически или сначала появляется окно подтверждения.

Отладчик (REG_SZ)

Это значение REG_SZ указывает отладчик, который будет обрабатывать постмортем отладку.

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

Командная строка создается из строки отладчика с помощью вызова стиля printf, включающего 3 параметра. Несмотря на фиксированную последовательность параметров, не требуется использовать любой или все доступные параметры.

DWORD (%ld) — идентификатор целевого процесса.

DWORD (%ld) — дескриптор событий, повторяющийся в процессе отладчика postmortem. Если отладчик postmortem сигнализирует о событии, WER продолжит целевой процесс, не ожидая завершения отладчика postmortem. Событие следует сигнализировать только в том случае, если проблема устранена. Если отладчик postmortem завершается без уведомления о событии, WER продолжает сбор сведений о целевых процессах.

void* (%p) — адрес структуры JIT_DEBUG_INFO, выделенной в адресном пространстве целевого процесса. Структура содержит дополнительные сведения об исключении и контексте.

Авто (REG_SZ) Это REG_SZ значение всегда равно 0 или 1.

Если для параметра "Авто " задано значение 0, перед началом процесса посмертной отладки отображается сообщение с подтверждением.

Если для параметра Auto задано значение 1, отладчик postmortem немедленно создается.

При ручном редактировании реестра сделайте это очень тщательно, так как неправильные изменения в реестре могут не позволить Windows загружаться.

Пример использования командной строки

Многие отладчики postmortem используют командную строку, включающую переключатели -p и -e, чтобы указать, что параметры являются идентификатором PID и событием (соответственно). Например, установка WinDbg с помощью windbg.exe -I создает следующие значения:

Debugger = "<Path>\WinDbg -p %ld -e %ld -g"
Auto = 1

Существует гибкость в том, как можно использовать параметры WER %ld %ld %p. Например. Нет необходимости указывать какие-либо переключатели вокруг или между параметрами WER. Например, при установке Windows Sysinternals ProcDump с использованием procdump.exe -i устанавливаются следующие значения без переключения между параметрами WER %ld %ld %p:

Debugger = "<Path>\procdump.exe" -accepteula -j "c:\Dumps" %ld %ld %p
Auto = 1

32 и 64-разрядные отладчики

На 64-разрядной платформе значения реестра отладчика (REG_SZ) и автоматического (REG_SZ) определяются отдельно для 64-разрядных и 32-разрядных приложений. Дополнительный ключ Windows на Windows (WOW) используется для хранения данных отладки 32-разрядного приложения после сбоя.

HKLM\Программное обеспечение\Wow6432Node\Корпорация Майкрософт\Windows NT\CurrentVersion\AeDebug

На 64-разрядной платформе используйте 32-разрядный отладчик post-mortem для 32-разрядных процессов и 64-разрядной отладчик для 64-разрядных процессов. Это позволяет избежать 64-разрядного отладчика, ориентированного на потоки WOW64 вместо 32-разрядных потоков в 32-разрядном процессе.

Для многих postmortem отладчиков, включая средства отладки для Windows, это требует выполнения команды установки дважды: один раз с версией x86 и один раз с версией x64. Например, чтобы использовать WinDbg в качестве интерактивного посмертного отладчика, команду windbg.exe -I нужно выполнить дважды, по одному разу для каждой версии.

64-разрядная установка:

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe –I

Это обновляет ключ реестра с этими данными.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
Debugger = "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe" -p %ld -e %ld –g

32-разрядная установка:

C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe –I

Это обновляет раздел реестра с этими значениями.

HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug
Debugger = "C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe" -p %ld -e %ld –g

Настройка отладчиков Post Mortem

Средства отладки для Windows

Отладочные средства для Windows все поддерживают настройку в качестве отладчика postmortem. Команда установки предназначена для интерактивной отладки процесса.

WinDbg

Чтобы задать отладчик postmortem в WinDbg, выполните команду windbg -I. (Должен I быть заглавным.) Эта команда отобразит сообщение об успешном выполнении или сбое после его использования. Чтобы работать с 32 и 64-разрядными приложениями, выполните команду для отладчиков 64 и 32.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe –I
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe –I

Вот как будет настроен вход реестра AeDebug при запуске windbg -I.

Debugger = "<Path>\WinDbg -p %ld -e %ld -g"
Auto = 1

В примерах Путь — это каталог, <в котором находится отладчик.>

Параметры -p и -e передают идентификатор процесса и событие, как описано ранее.

Команда -g отправляет команду g (Go) в WinDbg и продолжает выполнение с текущей инструкции.

Заметка Существует важная проблема, связанная с передачей команды g (Go). Проблема с этим подходом заключается в том, что исключения не всегда повторяются, как правило, из-за временных условий, которые больше не существуют при перезапуске кода. Дополнительные сведения об этой проблеме см. в разделе .jdinfo (использование JIT_DEBUG_INFO).

Чтобы избежать этой проблемы, используйте jdinfo или .dump /j. Такой подход позволяет отладчику находиться в контексте интересующего вас сбоя кода. Дополнительные сведения см. в разделе JIT-отладка далее в этом разделе.

CDB

Чтобы установить отладчик postmortem на CDB, запустите cdb -iae (Install AeDebug) или cdb -iaecKeyString (Install AeDebug with Command).

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe -iae
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe -iae

Если используется параметр -iaec , KeyString указывает строку, которая будет добавлена в конец командной строки, используемой для запуска отладчика postmortem. Если KeyString содержит пробелы, он должен быть заключен в кавычки.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe -iaec [KeyString]
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe -iaec [KeyString]

Эта команда не отображает ничего, если она выполнена успешно, и сообщение об ошибке при сбое.

NTSD

Чтобы задать отладчик postmortem на NTSD, запустите ntsd -iae (Install AeDebug) или ntsd -iaecKeyString (Install AeDebug with Command).

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe -iae
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\ntsd.exe -iae

Если используется параметр -iaec , KeyString указывает строку, которая будет добавлена в конец командной строки, используемой для запуска отладчика postmortem. Если KeyString содержит пробелы, он должен быть заключен в кавычки.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe -iaec [KeyString]
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\ntsd.exe -iaec [KeyString]

Эта команда ничего не отображает, если выполнена успешно, и в случае сбоя показывает ошибку в новом окне консоли.

Заметка Так как параметры -p %ld -e %ld -g всегда отображаются в командной строке отладчика postmortem, не следует использовать параметр -iaec для указания параметра -server, так как -server не будет работать, если только не появится в командной строке. Чтобы установить отладчик postmortem, включающий этот параметр, необходимо вручную изменить реестр.

Отладчик JIT Visual Studio

Если Visual Studio установлен, vsjitdebugger.exe будет зарегистрирован в качестве post-mortem отладчика. Отладчик JIT Visual Studio намерен выполнить интерактивную отладку процесса.

Debugger = "C:\WINDOWS\system32\vsjitdebugger.exe" -p %ld -e %ld

Если Visual Studio обновлена или повторно установлена, эта запись будет перезаписана, заменив любые альтернативные значения.

Окно Sysinternals ProcDump

Служебная программа ProcDump для Windows Sysinternals также может использоваться для отслеживания дампа postmortem. Дополнительные сведения об использовании и скачивании ProcDump см. в разделе ProcDump.

Как и команда .dump WinDbg, ProcDump может снять дамп аварийного сбоя без участия пользователя. Запись может происходить в любом системном сеансе Windows.

ProcDump завершает работу после завершения записи файла дампа, WER затем сообщает об ошибке и завершается процесс сбоя.

Используйте procdump -i для установки ProcDump и -u для удаления ProcDump для 32-разрядной и 64-разрядной посмертной отладки.

<Path>\procdump.exe -i

Команды установки и удаления выводить значения реестра, измененные при успешном выполнении, и ошибки при сбое.

Параметры командной строки ProcDump в реестре задаются следующим образом:

Debugger = <Path>\ProcDump.exe -accepteula -j "<DumpFolder>" %ld %ld %p

ProcDump использует все 3 параметра — PID, Event и JIT_DEBUG_INFO. Дополнительные сведения о параметре JIT_DEBUG_INFO см. в разделе JIT-отладка ниже.

Размер дампа, захваченного по умолчанию, — это Мини (процесс/потоки/дескрипторы/модули/адресное пространство) без указания опции размера, МиниПлюс (Мини плюс страницы MEM_PRIVATE) с установленной опцией -mp или Полный (вся память — эквивалентно ".dump /mA") с установленной опцией -ma.

Для систем с достаточным объемом дискового пространства рекомендуется выполнить полный (-ma) захват.

Используйте -ma с параметром -i, чтобы указать полный захват памяти. При необходимости укажите путь к файлам дампа.

<Path>\procdump.exe -ma -i c:\Dumps

Для систем с ограниченным пространством на диске рекомендуется запись MiniPlus (-mp).

<Path>\procdump.exe -mp -i c:\Dumps

Папка для сохранения файла дампа необязательна. По умолчанию используется текущая папка. Папка должна защититься с помощью ACL, равной или лучше используемой для C:\Windows\Temp. Дополнительные сведения об управлении безопасностью, связанной с папками, см. в разделе "Безопасность во время отладки postmortem".

Чтобы удалить ProcDump в качестве отладчика postmortem и восстановить предыдущие параметры, используйте параметр -u (Удаление).

<Path>\procdump.exe -u

Для получения дополнительной информации о ProcDump см. ProcDump и руководство администратора Windows SysInternals Марка Руссиновича и Аарона Маргозиса, опубликованное Microsoft Press.

JIT-отладка

Настройка контекста для неисправного приложения

Как упоминалось ранее, очень желательно задать контекст исключения, вызвавшего сбой с помощью параметра JIT_DEBUG_INFO. Дополнительные сведения об этом см. в разделе .jdinfo (использование JIT_DEBUG_INFO).

Инструменты отладки для Windows

В этом примере показано, как изменить реестр для выполнения начальной команды (-c), которая использует команду .jdinfo <address> для отображения дополнительных сведений об исключении и изменения контекста на место расположения исключения (аналогично тому, как .ecxr используется для установки контекста на запись об исключении).

Debugger = "<Path>\windbg.exe -p %ld -e %ld -c ".jdinfo 0x%p"
Auto = 1

Параметр %p — это адрес структуры JIT_DEBUG_INFO в адресном пространстве целевого процесса. Параметр %p предварительно добавляется с 0x, чтобы он интерпретировался как шестнадцатеричное значение. Дополнительные сведения см. в разделе .jdinfo (использование JIT_DEBUG_INFO).

Чтобы выполнить отладку 32-разрядных и 64-разрядных приложений, настройте разделы реестра как для 32-разрядных, так и для 64-разрядных приложений (описанные выше), задав правильный путь к расположению 64-разрядной и 32-разрядной WinDbg.exe.

Создание файла дампа с помощью .dump

Чтобы записать файл дампа всякий раз, когда происходит сбой, содержащий данные JIT_DEBUG_INFO, используйте .дамп /j <address>.

<Path>\windbg.exe -p %ld -e %ld -c ".dump /j %p /u <DumpPath>\AeDebug.dmp; qd"

Используйте параметр /u для создания уникального имени файла, чтобы разрешить автоматическое создание нескольких файлов дампа. Дополнительные сведения о параметрах см. в разделе .dump (Create Dump File).

Созданный дамп будет содержать данные JITDEBUG_INFO, хранящиеся в качестве контекста исключения по умолчанию. Вместо использования Jdinfo для просмотра сведений об исключении и задания контекста используйте exr -1 для отображения записи исключений и ECXR для задания контекста. Подробнее см. в .exr (Display Exception Record) и .ecxr (Display Exception Context Record).

Отчеты об ошибках Windows — q /qd

Способ завершения сеанса отладки определяет, будет ли отчет об ошибках Windows сообщать о сбое.

Если сеанс отладки отсоединен с помощью qd до закрытия отладчика, WER сообщит об ошибке.

Если сеанс отладки завершён с использованием q (или если отладчик закрыт без предварительного отключения), WER не сообщит об ошибке.

Добавление ; q или ; qd до конца командной строки для вызова требуемого поведения.

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

<Path>\cdb.exe -p %ld -e %ld -c ".dump /j 0x%p /u c:\Dumps\AeDebug.dmp; qd"

Этот пример позволит WER сообщить о сбое после записи дампа WinDbg.

<Path>\windbg.exe -p %ld -e %ld -c ".dump /j %p /u <DumpPath>\AeDebug.dmp; qd""

Уязвимости системы безопасности

Если вы рассматриваете возможность включения отладки postmortem на компьютере, к которому вы предоставляете общий доступ другим пользователям, см. статью "Безопасность во время отладки postmortem".