Странное отображение содержимого памяти в режиме отладки Visual Studio - PullRequest
2 голосов
/ 12 октября 2019

Я пишу какую-то многопоточную программу на Си. Я попытался изменить несколько инструкций в начале тела функции, чтобы перенаправить выполнение куда-то еще.

Но я заметил, что при отладке в Visual Studio 2015 некоторая область памяти кажется неизменной, как показано вMemory окно.

Например:

На рисунке ниже функция ApSignalMceToOs() начинается с 0x7FFBBEE51360. Я удалил диапазон памяти от 0x7FFBBEE51360 до 0x7FFBBEE5136E, чтобы изменить его.

Строки с 305 до 312 изменили диапазон адресов 0x7FFBBEE51360 ~ 0x7FFBBEE5136E.

Все хорошо, пока 0x7FFBBEE51369. В строке 311 (uint32_t(((uintptr_t)dst) >> 32 составляет 0x00007ffb. После выполнения строки 311 я ожидал, что диапазон памяти в 0x7FFBBEE51369 ~ 0x7FFBBEE5136C будет заполнен как fb 7f 00 00. Но, как показано ниже, Visual Studio говорит, что это 48 7f 00 00, где 48 - старое значение.

enter image description here

Затем я пошел проверитькод разборки функции ApSignalMceToOs(). И неудивительно, что инструкция на 00007FFBBF171365 равна mov dword ptr [rsp+4], 7F48h, которая должна быть 7FFB. Как показано ниже в красном поле ниже.

enter image description here

Так что до этого момента Visual Studio 2015 сообщала мне, что моя модификация произойдет сбой .

Но, как показывает желтая стрелка на над изображением, после выполнения mov dword ptr [rsp+4], 7F48h я проверил содержимое в области стека. Удивительно это действительно 7f fb перенесено в стек (показано в поле зеленый на над изображением).

И послеret инструкция выполнена, регистр RIP изменится на 00007FFBBEEAD940, что неудивительно. См. Ниже:

enter image description here

И в другой функции читается то же место. Ниже показано:

enter image description here code[len] или byte ptr [rax] - это ячейка памяти, содержащая 48 или fb. Но он читает 0xcc, что не является ни 0x48, ни 0xfb.

Код дизассемблирования Visual Studio декодируется из содержимого памяти. Таким образом, содержимое памяти или , как VS2015 считывает / обновляет ее , является ключевым моментом.

Исходя из вышесказанного, я пришел к двум выводам в режиме отладки VS 2015:

  • Некоторое содержимое памяти отображается неправильно (или обновляется в графическом интерфейсе).
  • Некоторые операции чтения из памяти не работают правильно.

Но программа работает без сбоев.

Кто-нибудь знает, почему это происходит?

ADD 1 - 17:08 PM 10/14/2019

Благодаря @MichaelBurr. Думаю, теперь я могу это объяснить.

Основная причина в том, что я добавил точку останова на 0x00007FFB...369 на уровне кода разборки, а не на уровне исходного кода C.

enter image description here

Когда я сделал это, отладчик VS сделал и добавил 0xCC инструкцию в расположении 0x00007FFB...369. Но, похоже, Visual Studio 2015 делает все возможное, чтобы скрыть этот факт . Ниже показано отображение содержимого памяти с точкой останова на 0x00007FFB...369, мы видим, что 0x00007FFB...369 все еще содержит старое значение 0x48.

enter image description here

Но после того, как я вручную скопировал память из 0x00007FFB...360 в 0x00007FFB...36e куда-то еще. Инструкция 0xCC со смещением 0x9 является раскрытой . См. Ниже:

enter image description here

Когда я изменял содержимое в 0x00007FFB...369, Visual Studio, казалось, был предупрежден, и он просто восстановил содержимое в сохраненном старомодин, то есть 0x48. Не мой недавно написанный.

Но я думаю, что само это восстановление не имеет никакого смысла. Восстановление сохраненного байтового содержимого ни в коем случае не должно запускаться в данный момент. Более разумное действие - немного обновить местоположение точки останова и вставить инструкцию 0xCC в новое место. Потому что недавно измененный код может изменить «границы команд». Таким образом, опыт отладки самоизменяющегося кода может быть лучше сохранен. Но для этого потребуется Visual Studio, чтобы разобрать новый код в соседнем. И новый контент инструкции может быть недействительным, если программист допустил ошибку.

1 Ответ

3 голосов
/ 12 октября 2019

Я думаю, что вы, по сути, боретесь с точкой останова / обработкой одного шага отладчика. Точки останова часто реализуются с помощью инструкции int 3, которая имеет кодировку 0xCC. Когда отладчик устанавливает 0xCC для точки останова, он должен сохранить исходное значение, а затем заменить его, когда отладчик остановил выполнение программы.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...