Как отладчики гарантируют правильность при использовании программной точки останова INT 3 (0xCC), даже если инструкция была исправлена? - PullRequest
21 голосов
/ 20 сентября 2010

Я читал, что INT 3 (0xCC) используется для программных точек останова.

Он устанавливается (например) отладчиком, перезаписывая фактический программный код в памяти.

Я также читал, что INT 3 - это исключение «ловушка», а не «ошибка», означающее, что адрес, помещенный в стек, является адресом инструкции, следующей за инструкцией INT3.

Как отладчик гарантирует правильность, если пропатченная инструкция не выполняется повторно?

Ответы [ 3 ]

26 голосов
/ 20 сентября 2010

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

Если предполагалось, что это постоянная точка останова, есть одна дополнительная складка: перед тем, как продолжить выполнение, вы устанавливаете одностадийный бит (aka trap) во флаги стека.Это означает, что будет выполнена только одна инструкция, в которой была установлена ​​точка останова, и вы снова получите прерывание точки останова.Вы отвечаете на это, восстанавливая 3-байтовый int, который вы только что исправили, на первый байт оригинальной инструкции и (снова) продолжаете выполнение.

4 голосов
/ 20 сентября 2010

Прошло много времени с тех пор, как я углубился в подобные вещи, но, если вы правы, что следующий адрес помещен в стек, отладчик может извлечь адрес возврата и использовать его, чтобы выяснить, где была точка останова.(адрес возврата минус один, поскольку инструкция INT 3 имеет длину в один байт) [отредактировано].

Другими словами, отладчику не обязательно возвращаться к адресу в стеке.Он может восстановить исходную инструкцию, а затем выполнить ее в исходном месте.Если точка останова должна оставаться установленной, она может использовать «бит прерывания» в флагах для выполнения только одной инструкции - исходной, которая была перезаписана - до того, как будет сгенерирована другая ловушка (снова INT 3, я думаю);затем инструкция INT 3 может быть восстановлена ​​перед продолжением надлежащего выполнения.

Однако в большинстве случаев отладчики работают в системе, в которой они все равно не обрабатывают ловушку напрямую;им может быть доставлен сигнал, например, сообщающий им, где произошла ловушка.Скорее всего, им все еще нужно выяснить «реальный» адрес (то есть адрес инструкции INT 3) по адресу прерывания, поскольку ОС не может это сделать.

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

2 голосов
/ 20 сентября 2010

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

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