Проблемы с чтением памяти при анализе аварийных дампов ядра Windows
Анализируя аварийные дампы ядра Windows с помощью WinDBG, я часто сталкивался с проблемой невозможности чтения WinDBG какой-либо области памяти. Недавно, анализируя аварийный дамп ядра (файл мини-дампов), я заметил, что было шесть переменных стека (включая два параметра), из которых WinDBG успешно выгружал значения четырех переменных стека, но возвращал для двух других переменных. Я не мог этого понять, потому что все шесть переменных были частью одного стека.
Кроме того, я заметил, что при попытке вывести глобальную структуру данных WinDBG вернул мне сообщение об ошибке "Невозможно прочитать память по адресу 0xfffff801139c50d0". Я не мог понять, почему WinDBG не может прочитать переменную, которая была определена глобально в моем драйвере.
Я правильно загрузил символы, включая файл PDB моего драйвера. WinDBG не дал мне ошибки, связанной с символами.
Я хочу понять причину такого поведения. Почему WinDBG не может прочитать значения локальных и глобальных переменных? Может кто-нибудь дать мне объяснение этому поведению?
1 ответ
Предполагая, что у вас уже есть доступ к закрытым символам, эта ошибка обычно вызвана оптимизацией кода в драйвере, а PDB не имеют достаточно информации, чтобы всегда определять местоположение исправления переменных.
использование !lmi <module name>
и проверьте, имеет ли поле характеристик "perf" для определения оптимизированного кода.
Как рекомендовано в разделе "Отладка оптимизированного кода производительности". Получающаяся в результате оптимизация уменьшает подкачку (и количество сбоев страниц) и увеличивает пространственную локальность между кодом и данными. Он устраняет ключевые узкие места производительности, которые могут возникнуть из-за неправильного позиционирования исходного кода. Компонент, прошедший эту оптимизацию, может иметь свой код или блок данных в функции, перемещенной в разные места двоичного файла. В модулях, которые были оптимизированы с помощью этих методов, места расположения кода и блоков данных часто находятся по адресам памяти, отличным от мест, где они будут находиться после обычной компиляции и компоновки. Кроме того, функции могут быть разбиты на множество несмежных блоков, чтобы наиболее часто используемые пути кода могли быть расположены близко друг к другу на одних и тех же страницах. Следовательно, функция (или любой символ) плюс смещение не обязательно будут иметь то же значение, что и в неоптимизированном коде. Основное правило при работе с оптимизированными кодами просто заключается в том, что вы не можете выполнять надежную адресную арифметику для оптимизированного кода.
Вам нужно проверить вывод dv /V
определить, где отладчик на самом деле ищет локальных, и подтвердить, что это правильно.