Sintaxe Pseudo-Register
O depurador dá suporte a vários pseudo-registros que contêm determinados valores.
O depurador define pseudo-registros automáticos para determinados valores úteis. Pseudo-registros definidos pelo usuário são variáveis de inteiro que você pode gravar ou ler.
Todos os pseudo-registros começam com um cifrão ($). Se você estiver usando a sintaxe MASM, poderá adicionar um sinal de at ( @ ) antes do cifrão. Isso no sinal informa ao depurador que o token a seguir é um registro ou pseudo-registro, não um símbolo. Se você omitir o sinal em , o depurador responderá mais lentamente, pois ele precisará pesquisar a tabela de símbolos inteira.
Por exemplo, os dois comandos a seguir produzem a mesma saída, mas o segundo comando é mais rápido.
0:000> ? $exp
Evaluate expression: 143 = 0000008f
0:000> ? @$exp
Evaluate expression: 143 = 0000008f
Se existir um símbolo com o mesmo nome que o pseudo-registro, você deverá adicionar o sinal de at.
Se você estiver usando a sintaxe de expressão C++, o sinal de at ( @ ) sempre será necessário.
O comando r (Registers) é uma exceção a essa regra. O depurador sempre interpreta seu primeiro argumento como um registro ou pseudo-registro. (Um sinal de não é necessário ou permitido.) Se houver um segundo argumento para o comando r , ele será interpretado de acordo com a sintaxe de expressão padrão. Se a sintaxe de expressão padrão for C++, você deverá usar o comando a seguir para copiar o pseudo-registro $t 2 para o pseudo-registro $t 1 .
0:000> r $t1 = @$t2
Pseudo-Registers automática
O depurador define automaticamente os pseudo-registros a seguir.
Pseudo-registro | Descrição |
---|---|
$ea |
O endereço efetivo da última instrução que foi executada. Se esta instrução não tiver um endereço efetivo, o depurador exibirá "Erro de registro inválido". Se essa instrução tiver dois endereços efetivos, o depurador exibirá o primeiro endereço. |
$ea 2 |
O segundo endereço efetivo da última instrução que foi executada. Se essa instrução não tiver dois endereços efetivos, o depurador exibirá "Erro de registro incorreto". |
$exp |
A última expressão que foi avaliada. |
$ra |
O endereço de retorno que está atualmente na pilha. Esse endereço é especialmente útil em comandos de execução. Por exemplo, g @$ra continua até que o endereço de retorno seja encontrado (embora gu (Go Up) seja uma maneira mais precisa e eficaz de "sair" da função atual). |
$ip |
O registro do ponteiro de instrução. Processadores baseados em x86: O mesmo que eip. Processadores baseados em Itanium: Relacionado ao iip. (Para obter mais informações, consulte a observação a seguir nesta tabela.) Processadores baseados em x64: O mesmo que rasgar. |
$eventip |
O ponteiro de instrução no momento do evento atual. Esse ponteiro normalmente corresponde a $ip, a menos que você tenha alternado threads ou alterado manualmente o valor do ponteiro de instrução. |
$previp |
O ponteiro de instrução no momento do evento anterior. (Invadir o depurador conta como um evento.) |
$relip |
Um ponteiro de instrução relacionado ao evento atual. Quando você está rastreando branch, esse ponteiro é o ponteiro para a origem do branch. |
$scopeip |
O ponteiro de instrução para o contexto local atual (também conhecido como escopo). |
$exentry |
O endereço do ponto de entrada do primeiro executável do processo atual. |
$retreg |
O registro de valor retornado primário. Processadores baseados em x86: O mesmo que eax. Processadores baseados em Itanium: O mesmo que ret0. Processadores baseados em x64: O mesmo que rax. |
$retreg 64 |
O registro de valor retornado primário, no formato de 64 bits. Processador x86: O mesmo que o par edx:eax . |
$csp |
O ponteiro da pilha de chamadas atual. Esse ponteiro é o registro mais representativo da profundidade da pilha de chamadas. Processadores baseados em x86: O mesmo que esp. Processadores baseados em Itanium: O mesmo que bsp. Processadores baseados em x64: O mesmo que rsp. |
$p |
O valor que o último comando d* (Memória de Exibição) imprimiu. |
$proc |
O endereço do processo atual (ou seja, o endereço do bloco EPROCESS). |
$thread |
O endereço do thread atual. Na depuração do modo kernel, esse endereço é o endereço do bloco ETHREAD. Na depuração no modo de usuário, esse endereço é o endereço do TEB (bloco de ambiente de thread). |
$peb |
O endereço do PEB (bloco de ambiente de processo) do processo atual. |
$teb |
O endereço do TEB (bloco de ambiente de thread) do thread atual. |
$tpid |
A ID do processo (PID) para o processo que possui o thread atual. |
$tid |
A ID do thread atual. |
$dtid |
|
$dpid |
|
$dsid |
|
Número do $bp |
O endereço do ponto de interrupção correspondente. Por exemplo, $bp 3 (ou $bp 03) refere-se ao ponto de interrupção cuja ID do ponto de interrupção é 3. O número é sempre um número decimal. Se nenhum ponto de interrupção tiver uma ID de Número, $bpNúmero será avaliado como zero. Para obter mais informações sobre pontos de interrupção, consulte Usando pontos de interrupção. |
$frame |
O índice de quadro atual. Esse índice é o mesmo número de quadro que o comando .frame (Definir Contexto Local) usa. |
$dbgtime |
A hora atual, de acordo com o computador em que o depurador está sendo executado. |
$callret |
O valor retornado da última função que .call (Função de Chamada) chamou ou que é usada em um comando .fnret /s . O tipo de dados de $callret é o tipo de dados desse valor retornado. |
$extret |
|
$extin |
|
$clrex |
|
$lastclrex |
Somente depuração gerenciada: O endereço do objeto de exceção CLR (Common Language Runtime) encontrado pela última vez. |
$ptrsize |
O tamanho de um ponteiro. No modo kernel, esse tamanho é o tamanho do ponteiro no computador de destino. |
$pagesize |
O número de bytes em uma página de memória. No modo kernel, esse tamanho é o tamanho da página no computador de destino. |
$pcr |
|
$pcrb |
|
$argreg |
|
$exr_chance |
A chance do registro de exceção atual. |
$exr_code |
O código de exceção para o registro de exceção atual. |
$exr_numparams |
O número de parâmetros no registro de exceção atual. |
$exr_param0 |
O valor do Parâmetro 0 no registro de exceção atual. |
$exr_param1 |
O valor do Parâmetro 1 no registro de exceção atual. |
$exr_param2 |
O valor do Parâmetro 2 no registro de exceção atual. |
$exr_param3 |
O valor do Parâmetro 3 no registro de exceção atual. |
$exr_param4 |
O valor do Parâmetro 4 no registro de exceção atual. |
$exr_param5 |
O valor do Parâmetro 5 no registro de exceção atual. |
$exr_param6 |
O valor do Parâmetro 6 no registro de exceção atual. |
$exr_param7 |
O valor do Parâmetro 7 no registro de exceção atual. |
$exr_param8 |
O valor do Parâmetro 8 no registro de exceção atual. |
$exr_param9 |
O valor do Parâmetro 9 no registro de exceção atual. |
$exr_param10 |
O valor do Parâmetro 10 no registro de exceção atual. |
$exr_param11 |
O valor do Parâmetro 11 no registro de exceção atual. |
$exr_param12 |
O valor do Parâmetro 12 no registro de exceção atual. |
$exr_param13 |
O valor do Parâmetro 13 no registro de exceção atual. |
$exr_param14 |
O valor do Parâmetro 14 no registro de exceção atual. |
$bug_code |
Se ocorreu um bug marcar, esse é o código de bug. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel. |
$bug_param1 |
Se ocorreu um bug marcar, esse é o valor do Parâmetro 1. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel. |
$bug_param2 |
Se ocorreu um bug marcar, esse é o valor do Parâmetro 2. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel. |
$bug_param3 |
Se ocorreu um bug marcar, esse é o valor do Parâmetro 3. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel. |
$bug_param4 |
Se ocorreu um bug marcar, esse é o valor do Parâmetro 4. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel. |
Alguns desses pseudo-registros podem não estar disponíveis em determinados cenários de depuração. Por exemplo, você não pode usar $peb, $tid e $tpid ao depurar um minidump no modo de usuário ou determinados arquivos de despejo no modo kernel. Haverá situações em que você poderá aprender informações de thread de ~ (Status do Thread), mas não de $tid. Não é possível usar o pseudo-registro $previp no primeiro evento de depurador. Você não pode usar o pseudo-registro $relip , a menos que esteja rastreando branch. Se você usar um pseudo-registro indisponível, ocorrerá um erro de sintaxe.
Um pseudo-registro que contém o endereço de uma estrutura , como $thread, $proc, $teb, $peb e $lastclrex -- será avaliado de acordo com o tipo de dados adequado no avaliador de expressão C++, mas não no avaliador de expressão MASM. Por exemplo, o comando ? $teb exibe o endereço do TEB, enquanto o comando ?? @$teb exibe toda a estrutura TEB. Para obter mais informações, consulte Avaliando expressões.
Em um processador baseado em Itanium, o registro iip é alinhado a pacotes, o que significa que ele aponta para o slot 0 no pacote que contém a instrução atual, mesmo que um slot diferente esteja sendo executado. Portanto , iip não é o ponteiro de instrução completo. O pseudo-registro $ip é o ponteiro de instrução real, incluindo o pacote e o slot. Os outros pseudo-registros que contêm ponteiros de endereço ($ra, $retreg, $eventip, $previp, $relip e $exentry) têm a mesma estrutura que $ip em todos os processadores.
Você pode usar o comando r para alterar o valor de $ip. Essa alteração também altera automaticamente o registro correspondente. Quando a execução é retomada, ela é retomada no novo endereço do ponteiro de instrução. Esse registro é o único pseudo-registro automático que você pode alterar manualmente.
Nota Na sintaxe MASM, você pode indicar a $ip pseudo-registro com um período ( . ). Você não adiciona um sinal de at (@) antes desse período e não usa o período como o primeiro parâmetro do comando r . Essa sintaxe não é permitida em uma expressão C++.
Os pseudo-registros automáticos são semelhantes aos aliases automáticos. Mas você pode usar aliases automáticos junto com tokens relacionados a alias (como ${ }) e não pode usar pseudo-registros com esses tokens.
Pseudo-Registers definida pelo usuário
Há 20 pseudo-registros definidos pelo usuário ($t 0, $t 1, ..., $t 19). Esses pseudo-registro são variáveis que você pode ler e gravar por meio do depurador. Você pode armazenar qualquer valor inteiro nesses pseudo-registros. Elas podem ser especialmente úteis como variáveis de loop.
Para gravar em um desses pseudo-registros, use o comando r (Registros), como mostra o exemplo a seguir.
0:000> r $t0 = 7
0:000> r $t1 = 128*poi(MyVar)
Como todos os pseudo-registros, você pode usar o pseudo-registro definido pelo usuário em qualquer expressão, como mostra o exemplo a seguir.
0:000> bp $t3
0:000> bp @$t4
0:000> ?? @$t1 + 4*@$t2
Um pseudo-registro sempre é digitado como um inteiro, a menos que você use a opção ? junto com o comando r . Se você usar essa opção, o pseudo-registro adquirirá o tipo do que for atribuído a ele. Por exemplo, o comando a seguir atribui o tipo UNICODE_STRING** e o valor 0x0012FFBC a $t 15.
0:000> r? $t15 = * (UNICODE_STRING*) 0x12ffbc
Os pseudo-registros definidos pelo usuário usam zero como o valor padrão quando o depurador é iniciado.
Nota Os aliases $u 0, $u 1, ..., $u 9 não são pseudo-registros, apesar de sua aparência semelhante. Para obter mais informações sobre esses aliases, consulte Usando aliases.
Exemplo
O exemplo a seguir define um ponto de interrupção que é atingido sempre que o thread atual chama NtOpenFile. Mas esse ponto de interrupção não é atingido quando outros threads chamam NtOpenFile.
kd> bp /t @$thread nt!ntopenfile
Exemplo
O exemplo a seguir executa um comando até que o registro mantenha um valor especificado. Primeiro, coloque o código a seguir para a etapa condicional em um arquivo de script chamado "eaxstep".
.if (@eax == 1234) { .echo 1234 } .else { t "$<eaxstep" }
Em seguida, emita o comando a seguir.
t "$<eaxstep"
O depurador executa uma etapa e executa o comando. Nesse caso, o depurador executa o script, que exibe 1234 ou repete o processo.