Поделиться через


Синтаксис Pseudo-Register

Отладчик поддерживает несколько псевдорегистров, которые содержат определенные значения.

Отладчик задает автоматические псевдорегистры для определенных полезных значений. Определяемые пользователем псевдорегистры — это целые переменные, в которые можно записывать или читать.

Все псевдорегистры начинаются с знака доллара ($). Если вы используете синтаксис MASM, вы можете добавить знак по знаку ( @ ) перед знаком доллара. Этот символ сообщает отладчику, что следующий токен является регистром или псевдорегистром, а не символом. Если вы опустите значок @, отладчик будет реагировать медленнее, так как ему приходится выполнять поиск по всей таблице символов.

Например, следующие две команды создают одинаковые выходные данные, но вторая команда быстрее.

0:000> ? $exp
Evaluate expression: 143 = 0000008f
0:000> ? @$exp
Evaluate expression: 143 = 0000008f

Если символ существует с тем же именем, что и псевдорегистр, необходимо добавить знак @.

Если используется синтаксис выражения C++, всегда требуется знак ( @ ).

Команда r (Registers) является исключением из этого правила. Отладчик всегда интерпретирует свой первый аргумент как регистр или псевдорегистратор. (Символ "@" не требуется и не разрешён.) Если для команды r есть второй аргумент, он интерпретируется в соответствии с синтаксисом выражения по умолчанию. Если синтаксис выражения по умолчанию — C++, необходимо использовать следующую команду, чтобы скопировать псевдорегистр $t2 в псевдорегистр $t1.

0:000> r $t1 = @$t2

Автоматическая Pseudo-Registers

Отладчик автоматически задает следующие псевдорегистры.

Псевдорегистр Описание

$ea

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

$ea 2

Второй эффективный адрес последней инструкции, которая была выполнена. Если в этой инструкции нет двух эффективных адресов, отладчик отображает сообщение "Ошибка в регистре".

$exp

Последнее выражение, которое было оценено.

$ra

Адрес возврата, который сейчас находится в стеке.

Этот адрес особенно полезен в командах выполнения. Например, g @$ra продолжается до тех пор, пока возвращаемый адрес не найден (хотя gu (Go Up) является более точным эффективным способом "выхода" текущей функции.

$ip

Регистр указателя инструкций.

Процессоры на основе x86: То же самое, что и eip. Процессоры на основе Itanium: Связана с iip. (Дополнительные сведения см. в записке ниже этой таблицы.) Процессоры на основе x64: Такой же, как rip.

$eventip

Инструкционный указатель в момент текущего события. Этот указатель обычно соответствует $ip, если вы не переключили потоки или вручную не изменили значение указателя инструкции.

$previp

Указатель инструкций на момент предыдущего события. (Вторжение в отладчик считается событием.)

$relip

Указатель инструкции, связанный с текущим событием. При трассировке ветви этот указатель является указателем на источник ветви.

$scopeip

Указатель инструкции для текущего локального контекста (также называется областью видимости).

$exentry

Адрес точки входа первого исполняемого файла текущего процесса.

$retreg

Основной регистр возвращаемого значения.

Процессоры на основе x86: То же самое, что и eax. Процессоры на основе Itanium: То же самое, что и ret0. Процессоры на основе x64: То же самое, что и rax.

$retreg 64

Основной регистр возвращаемого значения в 64-разрядном формате.

Процессор x86: То же, что и пара edx:eax .

$csp

Текущий указатель стека вызовов. Этот указатель является регистром, который наиболее точно отражает глубину стека вызовов.

Процессоры на основе x86: То же самое, что и esp. Процессоры на основе Itanium: То же самое, что и bsp. Процессоры на основе x64: То же самое, что и rsp.

$p

Значение, которое была напечатана последней командой d* (отображаемая память).

$proc

Адрес текущего процесса (то есть адрес блока EPROCESS).

$thread

Адрес текущего потока. В отладке в режиме ядра этот адрес является адресом блока ETHREAD. В отладке в пользовательском режиме этот адрес — это адрес блока среды потока (TEB).

$peb

Адрес блока среды процесса (PEB) текущего процесса.

$teb

Адрес блока среды потока (TEB) текущего потока.

$tpid

Идентификатор процесса (PID) для процесса, которому принадлежит текущий поток.

$tid

Идентификатор потока для текущего потока.

$dtid

$dpid

$dsid

номер $bp

Адрес соответствующей точки останова. Например, $bp 3 (или $bp 03) ссылается на точку останова, идентификатор точки останова которой равен 3. Число всегда является десятичным числом. Если ни одна точка останова не имеет ID равного Number, $bpNumber оценивается как ноль. Дополнительные сведения об точках останова см. в разделе "Использование точек останова".

$frame

Текущий индекс кадров. Этот индекс совпадает с номером кадра, который использует команда .frame (Set Local Context).

$dbgtime

Текущее время, в соответствии с компьютером, на котором работает отладчик.

$callret

Возвращаемое значение последней функции, которая вызывается (функция вызова) или используется в команде Fnret /s . Тип данных $callret — это тип данных этого возвращаемого значения.

$extret

$extin

$clrex

$lastclrex

Только управляемая отладка: Адрес последнего обнаруженного объекта исключения среды CLR.

$ptrsize

Размер указателя. В режиме ядра этот размер — это размер указателя на целевом компьютере.

$pagesize

Количество байтов в одной странице памяти. В режиме ядра этот размер — это размер страницы на целевом компьютере.

$pcr

$pcrb

$argreg

$exr_шанс

Вероятность текущей записи исключений.

$exr_code

Код исключения для текущей записи исключений.

$exr_numparams

Количество параметров в текущей записи исключений.

$exr_param0

Значение параметра 0 в текущей записи исключений.

$exr_param1

Значение параметра 1 в текущей записи исключений.

$exr_param2

Значение параметра 2 в текущей записи исключений.

$exr_param3

Значение параметра 3 в текущей записи исключений.

$exr_param4

Значение параметра 4 в текущей записи исключений.

$exr_param5

Значение параметра 5 в текущей записи исключений.

$exr_param6

Значение параметра 6 в текущей записи исключений.

$exr_param7

Значение параметра 7 в текущей записи исключений.

$exr_param8

Значение параметра 8 в текущей записи исключений.

$exr_param9

Значение параметра 9 в текущей записи исключений.

$exr_param10

Значение параметра 10 в текущей записи исключений.

$exr_param11

Значение параметра 11 в текущей записи исключений.

$exr_param12

Значение параметра 12 в текущей записи исключений.

$exr_param13

Значение параметра 13 в текущей записи исключений.

$exr_param14

Значение параметра 14 в текущей записи исключений.

$bug_code

Если произошла проверка ошибок, это код ошибки. Применяется к отладке в динамическом режиме ядра и аварийным дампам ядра.

$bug_param1

Если произошла проверка ошибок, это значение параметра 1. Применяется к отладке ядра в режиме реального времени и аварийным дампам ядра.

$bug_param2

Если произошла проверка на наличие ошибки, это значение параметра 2. Применяется к отладке ядра в режиме реального времени и аварийным дампам ядра.

$bug_param3

Если произошла системная ошибка, это значение параметра 3. Применяется к отладке в динамическом режиме ядра и аварийным дампам ядра.

$bug_param4

Если произошла проверка на ошибки, это значение параметра 4. Применяется к отладке в динамическом режиме ядра и аварийным дампам ядра.

Некоторые из этих псевдорегистрации могут быть недоступны в определенных сценариях отладки. Например, нельзя использовать $peb, $tid и $tpid при отладке мини-dump в пользовательском режиме или определенных файлов дампа в режиме ядра. В таких ситуациях вы можете узнать сведения о потоке из ~ (состояние потока), но не из $tid. Вы не можете использовать псевдорегистратор $previp в первом событии отладчика. Вы не можете использовать псевдорегистр $relip, если только вы не трассируете ветви. При использовании недоступного псевдорегистрирующего регистра возникает синтаксическая ошибка.

Псевдорегистратор, содержащий адрес структуры, например $thread, $proc, $teb, $peb и $lastclrex, будет оцениваться в соответствии с соответствующим типом данных в средстве оценки выражений C++, но не в средстве оценки выражений MASM. Например, команда ? $teb отображает адрес TEB, а команда ?? @$teb отображает всю структуру TEB. Дополнительные сведения см. в разделе "Оценка выражений".

На процессоре на основе Itanium регистр iipвыравнен по пакетам, что означает, что он указывает на слот 0 в пакете, содержащем текущую инструкцию, даже если выполняется другой слот. Итак, iip не является полным указателем инструкции. $ip псевдорегистр является фактическим указателем команд, включая бандл и слот. Другие псевдорегистры, которые содержат указатели адресов ($ra, $retreg, $eventip, $previp, $relip и $exentry) имеют одинаковую структуру, что и $ip на всех процессорах.

Команду r можно использовать для изменения значения $ip. Это изменение также автоматически изменяет соответствующий регистр. При возобновлении выполнения, выполнение продолжается по новому адресу указателя инструкции. Этот регистр является единственным автоматическим псевдорегистром, который можно изменить вручную.

Заметка В синтаксисе MASM вы можете указать псевдорегистр $ip через точку (.). Вы не добавляете знак по адресу (@) до этого периода и не используете период в качестве первого параметра команды r . Этот синтаксис не допускается в выражении C++.

Автоматические псевдорегистры похожи на автоматические псевдонимы. Но вы можете использовать автоматические псевдонимы вместе с маркерами, связанными с псевдонимом (например, ${ }), и вы не можете использовать псевдорегистры с такими токенами.

User-Defined Pseudo-Registers

Существует 20 пользовательских псевдорегистров ($t 0, $t 1, ..., $t 19). Эти псевдорегистраторы — это переменные, которые можно читать и записывать с помощью отладчика. Вы можете сохранить любое целочисленное значение в этих псевдорегистрации. Они могут быть особенно полезны в качестве переменных цикла.

Чтобы записать в один из этих псевдорегистров, используйте команду r (Registers), как показано в следующем примере.

0:000> r $t0 = 7
0:000> r $t1 = 128*poi(MyVar)

Как и все псевдорегистры, вы можете использовать определяемый пользователем псевдорегистр в любом выражении, как показано в следующем примере.

0:000> bp $t3 
0:000> bp @$t4 
0:000> ?? @$t1 + 4*@$t2 

Псевдорегистр всегда является целым числом, если вы не используете параметр ? вместе с командой r. Если вы используете этот параметр, псевдорегистр приобретает тип, который ему назначается. Например, следующая команда назначает тип UNICODE_STRING** и значение 0x0012FFBC $t 15.

0:000> r? $t15 = * (UNICODE_STRING*) 0x12ffbc

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

Заметка Псевдонимы $u 0, $u 1, ..., $u 9 не являются псевдорегистрацией, несмотря на их аналогичный внешний вид. Дополнительные сведения об этих псевдонимах см. в разделе "Использование псевдонимов".

Пример

В следующем примере устанавливается точка останова, которая достигается каждый раз, когда текущий поток вызывает NtOpenFile. Но эта точка останова не достигается, когда другие потоки вызывают NtOpenFile.

kd> bp /t @$thread nt!ntopenfile

Пример

В следующем примере выполняется команда, пока регистр не содержит указанное значение. Сначала поместите следующий код для условного шага в файл скрипта с именем eaxstep.

.if (@eax == 1234) { .echo 1234 } .else { t "$<eaxstep" }

Затем выполните следующую команду.

t "$<eaxstep"

Отладчик выполняет шаг, а затем выполняет команду. В этом случае отладчик запускает скрипт, который отображает 1234 или повторяет процесс.