Можно ли использовать виртуальную память для поддержки функции точки останова в i386?

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


person Travis Su    schedule 15.04.2020    source источник
comment
Непонятно, что именно вы имеете в виду, но вы можете отменить отображение или защитить страницу, содержащую интересующий адрес, так что вы получите ошибку страницы при доступе, которую вы затем сможете обработать в своем отладчике.   -  person Jester    schedule 15.04.2020
comment
Один линейный адрес может иметь несколько разных виртуальных адресов. Любая программа, имеющая достаточные привилегии для доступа к регистрам отладки (DR0-DR5 на '386), должна иметь возможность определять линейный адрес, который соответствует виртуальному адресу, который необходимо отслеживать.   -  person 1201ProgramAlarm    schedule 15.04.2020
comment
@Jester Я просто хочу понять, как работает отладчик с использованием виртуального адреса вместо линейного адреса. И связь между точкой останова по данным и локальными / глобальными переменными. см. pdos.csail.mit.edu/6.828 /2008/readings/i386/s12_02.htm#fig12-1 и pdos.csail.mit.edu/6.828/2008/readings/i386/s12_03.htm. поскольку я слишком зеленый для этого   -  person Travis Su    schedule 15.04.2020
comment
@ 1201ProgramAlarm Я читал отсюда pdos.csail.mit.edu/ 6.828 / 2008 / readings / i386 / s05_02.htm заявляет, что линейный адрес косвенно ссылается на физический адрес путем указания таблицы страниц, так что на самом деле это означает, что когда линейный адрес переводится в физический адрес, фактическое преобразование является соответствующим виртуальный адрес на физический адрес?   -  person Travis Su    schedule 15.04.2020


Ответы (1)


Линейные адреса являются виртуальными в терминологии x86. Адресация памяти x86 идет:

  • режим адресации наподобие [ebp + eax*4] для эффективного адреса (часть смещения сегмента: off). (И каждый режим адресации подразумевает сегмент, если вы не переопределяете вручную, например, [fs: rdi]. Обычно DS, если только базовый регистр не R / E / BP или R / ESP, в этом случае SS. Или для режимов неявной адресации как часть например, push rax или _ 6_, это зависит от инструкции.)
  • seg: off - ›linear путем добавления основания сегмента к смещению.
  • перевод этого линейного адреса на физический. (А в случае виртуализации - от гостевого физического к истинному физическому.)

Все шаги выполняются аппаратным обеспечением ЦП, сначала с использованием базы сегмента, а затем с использованием таблицы страниц, на которую указывает CR3. Или TLB, который кэширует переводы из этой таблицы страниц.

Регистры аппаратной отладки для аппаратных точек останова / наблюдения используют виртуальные адреса. https://en.wikipedia.org/wiki/X86_debug_register объясняет это следующим образом:

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

Это означает, что точка наблюдения может сработать, когда вы обращаетесь к одному и тому же физическому адресу с другого виртуального адреса, чем тот, который вы поместили в регистр отладки. (Если это описание в Википедии является точным; я бы протестировал его и / или проверил руководства Intel или AMD, если это имеет значение.)

На самом деле я не знаю подробностей; знаю, что x86 имеет флаг TF и ​​регистры отладки, а также общее представление о том, что они могут делать, но я никогда не писал код для их использования.


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

аппаратная точка останова означает, что ЦП остановится без необходимости перезаписать программный код исполняемого кода на 0xCC int3. Регистры отладки могут делать это, а также обнаруживать доступ к определенным ячейкам памяти с помощью любой инструкции.

Таким образом, вы можете установить точку наблюдения для прерывания, когда что-либо, что ваша программа читает или записывает в определенную глобальную переменную в памяти, позволяя вам найти код, который изменяет ее с помощью указателя или чего-то еще. А поскольку он поддерживается HW, вы можете работать на полной скорости вместо того, чтобы выполнять пошаговую проверку программного обеспечения при каждом доступе.

Смотрите также

person Peter Cordes    schedule 15.04.2020
comment
Вы, сэр, абсолютно кое-что прояснили для меня. Я также хочу знать, как все работает, когда я устанавливаю точку останова на данные для глобальных переменных по сравнению с локальными переменными. Я читал, что на стороне регистра процесс немного отличался, но ни один из них не объясняет дальше по этому поводу. - person Travis Su; 15.04.2020
comment
@TravisSu: Вы спрашиваете о локальных варах, оптимизированных под регистр? Вы не можете установить точку наблюдения в регистре, только адрес памяти. Вот почему отладочные сборки гарантируют, что переменная всегда имеет адрес, как в абстрактной машине C: Почему clang создает неэффективный asm с -O0 (для этого простая сумма с плавающей запятой)?. Когда вы отлаживаете конкретный экземпляр запущенной программы, отладчик знает адрес этого экземпляра локальной переменной, для которой вы устанавливаете точку останова. - person Peter Cordes; 15.04.2020
comment
Не совсем так. Например, я программирую на языке ассемблера x86, на локальные переменные обычно ссылаются по смещению в регистре EBP, но я не уверен в глобальных переменных. И я хотел знать, как в этих случаях работает точка останова по данным. - person Travis Su; 15.04.2020
comment
при установке точки останова на данные для локальной переменной есть вероятность, что другая функция будет использовать регистр EBP для указания на свой стек кадров, отладчику нужно что-то сделать, чтобы этого избежать? - person Travis Su; 15.04.2020
comment
@TravisSu: Регистрам отладки все равно, какой адрес; они запускаются на основе совпадающего линейного адреса после генерации адреса и перехода от seg: off к linear. См. Начало моего ответа. Чтобы запрограммировать регистры отладки должным образом, отладчику просто нужно вычислить адрес локальной переменной (используя метаданные отладочной информации и текущее значение EBP или ESP, в зависимости от того, была ли оптимизирована функция чтобы не использовать EBP в качестве традиционного указателя кадра.) - person Peter Cordes; 15.04.2020
comment
@TravisSu: как я уже сказал, одна конкретная локальная переменная в кадре стека одной функции будет иметь адрес, который ничто другое не использует в течение всего времени существования этой переменной. Однако, если вы оставите точку наблюдения установленной после возврата из функции, следующая функция, которая повторно использует это пространство стека для чего-либо, может вызвать точку наблюдения. (В дереве вызовов это может быть родственник того, где вы устанавливаете точку наблюдения. Или родительский элемент, если родитель использует alloca или выделяет массив переменной длины после возврата из вызова функции.) - person Peter Cordes; 15.04.2020