Проблемы чтения памяти при анализе аварийных дампов ядра Windows

Анализируя аварийные дампы ядра Windows с помощью WinDBG, я часто сталкивался с проблемой, когда WinDBG не может прочитать некоторую область памяти. Недавно при анализе аварийного дампа ядра (файл минидампа) я заметил, что было шесть переменных стека (включая два параметра), из которых WinDBG успешно сбросил значения четырех переменных стека, но возвращал значения для двух других переменных. Я не мог этого понять, потому что все шесть переменных были частью одного фрейма стека.

В дополнение к этому я заметил, что когда я пытался сделать дамп глобальной структуры данных, WinDBG вернул мне ошибку, указывающую «Невозможно прочитать память по адресу 0xfffff801139c50d0». Я не мог понять, почему WinDBG не может прочитать переменную, которая была определена глобально в моем драйвере.

Я правильно загрузил символы, включая файл PDB моего драйвера. WinDBG не выдавал мне никаких ошибок, связанных с символами.

Я хочу понять причину такого поведения. Почему WinDBG не может прочитать значение локальных и глобальных переменных? Может ли кто-нибудь дать мне объяснение такому поведению?


person Arun Kaushal    schedule 03.08.2017    source источник
comment
Каков размер вашего дампа ядра? Даже если у вас есть полный дамп, на диск может быть выгружена память, которой нет в дампе.   -  person Thomas Weller    schedule 03.08.2017
comment
Размер файла дампа составляет 864 КБ.   -  person Arun Kaushal    schedule 04.08.2017


Ответы (1)


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

Используйте !lmi <module name>и проверьте, есть ли в поле характеристик значение «perf», чтобы определить, оптимизирован ли код.

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

Вам нужно проверить вывод dv /V, чтобы определить, где отладчик на самом деле ищет местных жителей, и подтвердить, что это правильно.

person Malcolm McCaffery    schedule 03.08.2017
comment
Я не вижу производительность в поле характеристик, если запускаю !lmi ‹имя модуля›. Когда я запускаю dv /V, он выводит данные в трех столбцах, первые два столбца содержат имя регистра, а третий столбец имеет ‹переменная› = ‹значение›. Для переменных я не могу видеть значения, он печатает ‹недоступно› в первых двух столбцах и ‹переменная› = ‹ значение недоступно› 2: kd› dv /V ‹недоступно› ‹недоступно› pDevObj = ‹значение недоступно› @rbx @rbx pData = 0xffffc908`c4cced30 - person Arun Kaushal; 03.08.2017
comment
Существуют и другие, более сложные потенциальные причины, но какими бы они ни были, следует начинать с проверки вывода dv /V или !for_each_frame dv /i /t /V. - person Malcolm McCaffery; 03.08.2017
comment
Я попробовал !for_each_frame dv /i /t /V, он не дает мне дампа переменных/параметров стека для кадров стека, отличных от кадра стека моих модулей. Во фрейме стека моего модуля я получаю тот же результат — «значение недоступно» для двух локальных переменных. - person Arun Kaushal; 03.08.2017