[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 8, Nov 1998 file 00A
Встроенные средства отладки процессора 80386
by Тед Мирецки
Важнейшей особенностью процессора 80386 является наличие восьми
отладочных регистров, обозначаемых DR0-DR7. Два из этих регистров,
DR4 и DR5, зарезервированы для внутренних нужд микропроцессора и яв-
ляются недоступными для программ. К остальным доступ может осуществ-
ляться с помощью команд пересылки следующего вида:
MOV DRx, zzz
MOV zzz, DRx
где х может принимать значения 0, 1, 2, 3, 6 или 7, а zzz явля-
ется одним из 32-разрядных регистров EAX, EBX, ECX, EDX, EDI или ESI.
Эти команды выполнимы как в REAL-, так и в защищенном режиме, причем
в последнем случае они должны выполняться только на высшем (нулевом)
уровне приоритета.
Каждый из четырех регистров DR0-DR3 может содержать адрес точки
останова. Этот адрес должен быть представлен в 32-разрядной линейной
форме, возникающей уже после осуществления сегментных адресных преоб-
разований, но до использующего страничный механизм перехода с вирту-
ального адреса на физический. Если страничный механизм не использует-
ся, то линейный адрес совпадает с физическим; в REAL-режиме он вычис-
ляется путем сдвига адреса сегмента на четыре бита влево с последую-
щим добавлением величины смещения.
Отладочный управляющий регистр DR7 (см. рис.1 ) служит для опи-
сания характера точек останова, а также для выборочного разрешения
и/или запрещения этих остановов. Hа каждый из четырех отладочных ад-
ресных регистров DR7 содержит по два бита разрешения: локальный бит
разрешения и глобальный бит разрешения. Если какой-либо из этих битов
установлен, то соответствующий адрес останова считается активным, и
обращение к участку памяти по этому адресу будет инициировать преры-
вание INT 1. Биты чтения/записи указывают способ обращения к памяти,
вызывающий прерывание: выполнение машинной инструкции, только запись
данных, запись или чтение данных. Для обращения, связанного с данны-
ми, используются биты длины, указывающие длины областей памяти, начи-
нающиеся с адреса останова (максимум 4 байта), при обращении к кото-
рым происходит останов. Для остановов, связанных с выполнением инст-
рукций, биты длины должны содержать 0; если инструкция имеет префик-
сы, то специфицированный адрес должен быть адресом первого префикса.
Рис.1. Управляющий регистр и регистр состояния
Отладочный управляющий регистр (DR7)
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│LEN│R/W│LEN│R/W│LEN│R/W│LEN│R/W│ 0 │G│ 0 │G│L│G│L│G│L│G│L│G│L│
│ 3 │ 3 │ 2 │ 2 │ 1 │ 1 │ 0 │ 0 │ │D│ │E│E│3│3│2│2│1│1│0│0│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
31 23 15 7 0
LENn - длина останова n: 00 = 1 байт
01 = 2 байта
10 = неопределена
11 = 4 байта
R/Wn - тип останова: 00 = выполнение инструкции
01 = запись данных
10 = неопределен
11 = чтение и/или запись данных
GD - генерировать INT 1 при обращении к отладочным регистрам
GE - глобальный бит "точного соответствия"
LE - локальный бит "точного соответствия"
Gn - глобальный бит разрешения останова с номером n
Ln - локальный бит разрешения останова с номером n
Отладочный регистр состояния (DR6)
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│ 0 │В│В│В│ 0 │В│В│В│В│
│ │T│S│D│ │3│2│1│0│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
31 23 15 7 0
BT - переключение контекстов (установлен бит Т в сегменте
состояния задачи)
BS - пошаговое выполнение (установлен бит Т в регистре флагов)
BD - обращение к отладочным регистрам (установлен GD в DR7)
Bn - точка останова с номером n
Двухуровневая система разрешения/запрещения остановов предпола-
гает, что отладка происходит в многозадачной среде с виртуальной па-
мятью. В момент переключения контекста с одной задачи на другую про-
цессор автоматически очищает четыре локальных бита разрешения преры-
вания; при этом нежелательные для новой задачи неглобальные отладоч-
ные прерывания происходить не будут. В случае, когда некоторый оста-
нов остается активным, могут возникать нежелательные отладочные пре-
рывания, поскольку линейный адрес, содержащийся в отладочном регист-
ре, не является по отношению к задаче уникальным. При использовании
страничного механизма различные задачи могут обращаться к различным
физическим адресам памяти, используя один и тот же линейный адрес
(для этого достаточно изменить информацию в таблицах постраничного
соответствия). Глобальные биты разрешения останова обычно устанавли-
ваются в случае отладки общедоступных программ, например драйверов
устройств.
Заметим, однако, что переключение контекстов автоматически обну-
ляет локальные биты разрешения останова регистра DR7, при этом не
сохраняя их содержимого; эти биты остаются очищенными и в тот момент,
когда управление получает задача-отладчик. Для устранения этого неу-
добства программа отладчика должна устанавливать бит отладочной ло-
вушки в своем сегменте переключения контекстов (TSS), что вызовет вы-
полнение прерывания INT 1 всякий раз, когда эта программа будет во-
зобновлять работу. Когда обработчик прерывания определит, что INT 1
вызвано преключением контекстов, он может установить по своему усмот-
рению локальные биты разрешения, после чего передать управление в ту
точку, где отладчик был в последний раз приостановлен.
Hазначение битов GE и LE регистра DR7 состоит в установлении
точного соответствия между моментом выполнения инструкции, вызвавшей
прерывание, и моментом возникновения прерывания. Дело в том, что
обычно 386-й процессор осуществляет физическую запись данных в память
уже после того, как была выполнена инициировавшая эту запись машинная
инструкция, причем эта задержка может оказаться довольно большой. В
связи с этим прерывание, вызванное записью данных по одному из актив-
ных адресов останова, может произойти в тот момент, когда регистр IP
указывает совсем не на ту инструкцию, которая осуществляла запись.
Однако, если по крайней мере один из битов GE или LE установлен, про-
цессор приостановит свою работу с тем, чтобы дождаться фактического
завершения операции записи. Руководство программиста по процессору
Intel 386 рекомендует устанавливать какой-либо из этих битов в слу-
чае, если используется останов по обращению к данным. Отметим, что
переключение контекстов обнуляет бит LE, но не влияет на бит GE.
Установка битов "точного соответствия" несколько увеличивает
время выполнения отлаживаемой программы по сравнению с реальным вре-
менем, однако возникающее замедление несравнимо с замедлением, проис-
ходящим из-за пошагового выполнения или вызова отладочных подпрограмм
сравнения для отслеживания записи в память. Это замедление составляет
всего 25 процентов, в то время как пошаговое выполнение ухудшает вре-
мя в несколько раз.
Последний используемый регистром управления флаг - бит GD - слу-
жит для защиты отладочных регистров от какого бы то ни было доступа в
любом режиме работы процессора и на любых уровнях приоритетов. В слу-
чае, если этот бит установлен, любая попытка чтения или записи в лю-
бой из отладочных регистров вызовет прерывание INT 1. Отладчик может
устанавливать бит GD с тем, чтобы зарезервировать отладочные регистры
для своих целей и защитить их от воздействия прочих программ. INT 1
очищает бит GD, поэтому обработчик прерывания, находящийся в отладчи-
ке, всегда будет иметь доступ к отладочным регистрам.
Бит GD описан в дополнительных руководствах фирмы Intel по 386
процессору; в общедоступном Руководстве программиста описания этого
бита нет. Версии микросхемы 80386, ориентированные на частоты 16 МГц
и 20 МГц, поддерживают работу с битом GD, однако использовать эту
особенность, как и любое другое недокументированное средство, следует
с осторожностью, т.к. в последующих версиях микропроцессора она может
не поддерживаться.
Все аппаратно реализуемые отладочные средства микропроцессора
386 используют для входа в среду отладчика прерывание INT 1. Кроме
того, это прерывание, как и в предшествующих микропроцессорах фирмы
Intel, может вызываться выполнением инструкций в пошаговом режиме
(для этого должен быть установлен бит пошагового выполнения в регист-
ре флагов). Таким образом, имеем семь возможных причин возникновения
прерывания INT 1: останов по одному из четырех адресов в регистрах
DR0-DR3; переключение контекстов при установленном бите отладочной
ловушки в TSS; попытка доступа к отладочным регистрам при установлен-
ном бите GD в DR7; останов, связанный с пошаговым выполнением (уста-
новлен бит останова в регистре флагов).
Для того, чтобы обработчик прерывания мог определить, по какой
из этих семи причин произошло прерывание, аппаратура устанавливает
соответствующие биты в отладочном регистре состояния DR6. Эти биты не
очищаются процессором автоматически, поэтому обработчик прерывания
должен обнулить их перед завершением своей работы, для того, чтобы не
возникало недоразумений при последующих прерываниях.
В момент достижения точки останова по выполнению машинной инст-
рукции процессор инициирует соответствующее прерывание непосредствен-
но перед выполнением инструкции по адресу останова. В момент входа в
обработчик прерывания адрес возврата из прерывания, записанный в сте-
ке, указывает на инструкцию по адресу останова. Когда обработчик воз-
вратит управление, процессор снова попытается выполнить ту же самую
инструкцию; если к этому моменту останов все еще активен, то произой-
дет повторное прерывание. Обработчик прерывания INT 1 может запретить
останов, однако это может сказаться на работе отладчика, которому
последовательно возникающие в одной точке остановы могут требоваться
для отслеживания последовательных циклов в отлаживаемых программах.
Аппаратура процессора 386 предлагает следующий реальный выход из это-
го тупика.
В защищенном режиме при возникновении прерывания в стек перед
адресом возврата помещается 32-разрядный регистр флагов. В случае
возникновения INT 1 процессор устанавливает бит, соответствующий фла-
гу возобновления, в образе регистра флагов, находящегося в стеке. В
момент выхода из прерывания с помощью инструкции IRET для защищенного
режима флаги восстанавливаются из стека, таким образом флаг возобнов-
ления окажется установленным. Hазначение этого флага состоит в запре-
щении прерываний до момента выполнения следующей инструкции; процес-
сор автоматически обнуляет флаг возобновления в тот момент, когда лю-
бая из инструкций, за исключением инструкций установки флагов (SETF,
POPF или переходов и вызовов, связанных с переключением контекстов),
будет выполнена.
В REAL-режиме при возникновении прерывания в стек помещается
только 16-битовый регистр флагов; исходя из этого в REAL-режиме инст-
рукция IRET не может воздействовать на флаг возобновления, находящий-
ся в 16-м бите 32-разрядного регистра EFLAGS. Однако, обработчик пре-
рывания INT 1 может установить этот флаг путем изменения содержимого
стека таким образом, чтобы он содержал полные 32-разрядные варианты
регистра флагов и адреса возврата, после чего можно осуществить выход
из прерывания инструкцией IRETD вместо IRET.
В случае, когда останов возникает вследствие доступа к данным,
прерывание происходит после выполнения инструкции, осуществляющей
этот доступ. Если установлены биты GE или LE, в стек прерывания будет
помещен адрес инструкции, непосредственно следующей вслед за инструк-
цией, вызвавшей прерывание. Следует иметь в виду, что в момент воз-
никновения останова по записи ячейка памяти, вызвавшая останов, будет
содержать обновленное значение; если желательно сохранить старое зна-
чение этой ячейки, то отладчик должен это сделать (тем же способом,
которым DEBUG сохраняет содержимое ячейки, когда записывает на ее
место инструкцию INT 3) еще до момента передачи управления в отлажи-
ваемую программу.