Condividi tramite


sintassi Pseudo-Register

Il debugger supporta diversi pseudoregistri che contengono determinati valori.

Il debugger imposta pseudoregistrazioni automatiche su determinati valori utili. I pseudoregistri definiti dall'utente sono variabili integer che è possibile scrivere o leggere.

Tutti i registri pseudo-registrati iniziano con un segno di dollaro ($). Se si usa la sintassi MASM, è possibile aggiungere un segno all'indirizzo ( @ ) prima del segno del dollaro. Questo segno indica al debugger che il token seguente è un registro o uno pseudoregistro, non un simbolo. Se si omette il segno, il debugger risponde più lentamente, perché deve cercare l'intera tabella dei simboli.

Ad esempio, i due comandi seguenti producono lo stesso output, ma il secondo comando è più veloce.

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

Se esiste un simbolo con lo stesso nome dello pseudoregistro, è necessario aggiungere il segno in corrispondenza del segno.

Se si usa la sintassi dell'espressione C++, è sempre necessario l'opzione at sign ( @ ).

Il comando r (Registri) è un'eccezione a questa regola. Il debugger interpreta sempre il primo argomento come registro o pseudoregistro. Non è obbligatorio o consentito un segno. Se è presente un secondo argomento per il comando r , viene interpretato in base alla sintassi dell'espressione predefinita. Se la sintassi dell'espressione predefinita è C++, è necessario usare il comando seguente per copiare il pseudoregistrato $t 2 nel registro pseudo-register $t 1 .

0:000> r $t1 = @$t2

Pseudo-Registers automatico

Il debugger imposta automaticamente gli pseudoregistri seguenti.

Pseudoregistro Descrizione

$ea

Indirizzo effettivo dell'ultima istruzione eseguita. Se questa istruzione non ha un indirizzo efficace, il debugger visualizza "Errore di registrazione non valido". Se questa istruzione ha due indirizzi effettivi, il debugger visualizza il primo indirizzo.

$ea 2

Secondo indirizzo effettivo dell'ultima istruzione eseguita. Se questa istruzione non dispone di due indirizzi effettivi, il debugger visualizza "Errore di registrazione non valido".

$exp

Ultima espressione valutata.

$ra

Indirizzo restituito attualmente nello stack.

Questo indirizzo è particolarmente utile nei comandi di esecuzione. Ad esempio, g @$ra continua fino a quando non viene trovato l'indirizzo restituito (anche se gu (Go Up) è un modo più preciso efficace di "uscire" dalla funzione corrente.

$ip

Registro puntatore delle istruzioni.

Processori basati su x86: Uguale a eip. Processori basati su Itanium: Correlato a iip. Per altre informazioni, vedere la nota seguente. Processori basati su x64: Uguale a rip.

$eventip

Puntatore alle istruzioni al momento dell'evento corrente. Questo puntatore corrisponde in genere $ip, a meno che non si cambiano thread o si modifica manualmente il valore del puntatore all'istruzione.

$previp

Puntatore all'istruzione al momento dell'evento precedente. (L'interruzione nel debugger conta come evento).

$relip

Puntatore alle istruzioni correlato all'evento corrente. Quando si esegue la traccia del ramo, questo puntatore è il puntatore all'origine del ramo.

$scopeip

Puntatore alle istruzioni per il contesto locale corrente (noto anche come ambito).

$exentry

Indirizzo del punto di ingresso del primo eseguibile del processo corrente.

$retreg

Registro del valore restituito primario.

Processori basati su x86: Uguale a eax. Processori basati su Itanium: Uguale a ret0. Processori basati su x64: Uguale a rax.

$retreg 64

Registro del valore restituito primario, in formato a 64 bit.

Processore x86: Uguale alla coppia edx:eax .

$csp

Puntatore dello stack di chiamate corrente. Questo puntatore è il registro che è più rappresentativo della profondità dello stack di chiamate.

Processori basati su x86: Uguale a esp. Processori basati su Itanium: Uguale a bsp. Processori basati su x64: Uguale a rsp.

$p

Valore stampato dall'ultimo comando d* (Visualizzazione memoria).

$proc

Indirizzo del processo corrente, ovvero l'indirizzo del blocco EPROCESS.

$thread

Indirizzo del thread corrente. Nel debug in modalità kernel questo indirizzo è l'indirizzo del blocco ETHREAD. Nel debug in modalità utente, questo indirizzo è l'indirizzo del blocco di ambiente thread (TEB).

$peb

Indirizzo del blocco di ambiente del processo (PEB) del processo corrente.

$teb

Indirizzo del blocco di ambiente thread (TEB) del thread corrente.

$tpid

ID processo (PID) per il processo proprietario del thread corrente.

$tid

ID thread per il thread corrente.

$dtid

$dpid

$dsid

$bpnumero

Indirizzo del punto di interruzione corrispondente. Ad esempio, $bp 3 (o $bp 03) fa riferimento al punto di interruzione il cui ID punto di interruzione è 3. Il numero è sempre un numero decimale. Se nessun punto di interruzione ha un ID numero, $bpNumero restituisce zero. Per altre informazioni sui punti di interruzione, vedere Uso di punti di interruzione.

$frame

Indice frame corrente. Questo indice è lo stesso numero di frame usato dal comando .frame (Set Local Context).

$dbgtime

Ora corrente, in base al computer in cui è in esecuzione il debugger.

$callret

Valore restituito dell'ultima funzione chiamata (funzione di chiamata) o usata in un comando .fnret /s . Il tipo di dati di $callret è il tipo di dati di questo valore restituito.

$extret

$extin

$clrex

$lastclrex

Solo debug gestito: Indirizzo dell'ultimo oggetto eccezione Common Language Runtime (CLR).

$ptrsize

Dimensione di un puntatore. In modalità kernel, queste dimensioni sono le dimensioni del puntatore nel computer di destinazione.

$pagesize

Numero di byte in una pagina di memoria. In modalità kernel, queste dimensioni sono le dimensioni della pagina nel computer di destinazione.

$pcr

$pcrb

$argreg

$exr_chance

Possibilità del record di eccezione corrente.

$exr_code

Codice eccezione per il record di eccezione corrente.

$exr_numparams

Numero di parametri nel record di eccezione corrente.

$exr_param0

Valore di Parametro 0 nel record di eccezione corrente.

$exr_param1

Valore del parametro 1 nel record di eccezione corrente.

$exr_param2

Valore del parametro 2 nel record di eccezione corrente.

$exr_param3

Valore del parametro 3 nel record di eccezione corrente.

$exr_param4

Valore del parametro 4 nel record di eccezione corrente.

$exr_param5

Valore del parametro 5 nel record di eccezione corrente.

$exr_param6

Valore del parametro 6 nel record di eccezione corrente.

$exr_param7

Valore del parametro 7 nel record di eccezione corrente.

$exr_param8

Valore del parametro 8 nel record di eccezione corrente.

$exr_param9

Valore del parametro 9 nel record di eccezione corrente.

$exr_param10

Valore del parametro 10 nel record di eccezione corrente.

$exr_param11

Valore del parametro 11 nel record di eccezione corrente.

$exr_param12

Valore del parametro 12 nel record di eccezione corrente.

$exr_param13

Valore del parametro 13 nel record di eccezione corrente.

$exr_param14

Valore del parametro 14 nel record di eccezione corrente.

$bug_code

Se si è verificato un controllo di bug, si tratta del codice di bug. Si applica al debug in modalità kernel in tempo reale e ai dump di arresto anomalo del kernel.

$bug_param1

Se si è verificato un controllo di bug, si tratta del valore del parametro 1. Si applica al debug in modalità kernel in tempo reale e ai dump di arresto anomalo del kernel.

$bug_param2

Se si è verificato un controllo di bug, si tratta del valore del parametro 2. Si applica al debug in modalità kernel in tempo reale e ai dump di arresto anomalo del kernel.

$bug_param3

Se si è verificato un controllo di bug, si tratta del valore del parametro 3. Si applica al debug in modalità kernel in tempo reale e ai dump di arresto anomalo del kernel.

$bug_param4

Se si è verificato un controllo di bug, si tratta del valore del parametro 4. Si applica al debug in modalità kernel in tempo reale e ai dump di arresto anomalo del kernel.

Alcuni di questi pseudoregistri potrebbero non essere disponibili in determinati scenari di debug. Ad esempio, non è possibile usare $peb, $tid e $tpid quando si esegue il debug di un minidump in modalità utente o di determinati file di dump in modalità kernel. Ci saranno situazioni in cui è possibile apprendere le informazioni sui thread da ~ (Stato thread), ma non da $tid. Non è possibile utilizzare il $previp pseudoregistro nel primo evento del debugger. Non è possibile utilizzare il $relip pseudoregistro a meno che non si stia tracciando rami. Se si utilizza uno pseudoregistro non disponibile, si verifica un errore di sintassi.

Uno pseudoregistro che contiene l'indirizzo di una struttura, ad esempio $thread, $proc, $teb, $peb e $lastclrex , verrà valutato in base al tipo di dati appropriato nell'analizzatore di espressioni C++, ma non nell'analizzatore di espressioni MASM. Ad esempio, il comando ? $teb visualizza l'indirizzo del TEB, mentre il comando ?? @$teb visualizza l'intera struttura TEB. Per altre informazioni, vedere Valutazione delle espressioni.

In un processore basato su Itanium, il registro iip è allineato al bundle, il che significa che punta allo slot 0 nel bundle contenente l'istruzione corrente, anche se viene eseguito uno slot diverso. Quindi iip non è il puntatore completo all'istruzione. Il $ip pseudoregistro è il puntatore di istruzione effettivo, incluso il bundle e lo slot. Gli altri pseudoregistri che contengono puntatori agli indirizzi ($ra, $retreg, $eventip, $previp, $relip e $exentry) hanno la stessa struttura di $ip in tutti i processori.

È possibile usare il comando r per modificare il valore di $ip. Questa modifica modifica anche automaticamente il registro corrispondente. Quando l'esecuzione viene ripresa, riprende in corrispondenza del nuovo indirizzo del puntatore all'istruzione. Questo registro è l'unico pseudoregistro automatico che è possibile modificare manualmente.

Nota Nella sintassi MASM è possibile indicare il $ip pseudoregistro con un punto ( . ). Non aggiungere un simbolo di chioccio (@) prima di questo periodo e non usare il punto come primo parametro del comando r . Questa sintassi non è consentita all'interno di un'espressione C++.

Gli pseudoregistri automatici sono simili agli alias automatici. È tuttavia possibile usare alias automatici insieme ai token correlati agli alias (ad esempio ${ }) e non è possibile usare pseudoregistri con tali token.

Pseudo-Registers definite dall'utente

Esistono 20 pseudoregistri definiti dall'utente ($t 0, $t 1, ..., $t 19). Questi pseudoregistri sono variabili che è possibile leggere e scrivere tramite il debugger. È possibile archiviare qualsiasi valore intero in questi pseudoregistri. Possono essere particolarmente utili come variabili di ciclo.

Per scrivere in uno di questi pseudoregistri, usare il comando r (Registers), come illustrato nell'esempio seguente.

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

Come tutti i pseudoregistri, è possibile usare lo pseudoregistro definito dall'utente in qualsiasi espressione, come illustrato nell'esempio seguente.

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

Un pseudoregistro viene sempre digitato come intero, a meno che non si usi l'opzione ? insieme al comando r . Se si usa questa opzione, il registro pseudo-acquisisce il tipo di qualsiasi oggetto assegnato. Ad esempio, il comando seguente assegna il tipo UNICODE_STRING** e il valore 0x0012FFBC a $t 15.

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

I pseudoregistri definiti dall'utente usano zero come valore predefinito all'avvio del debugger.

Nota Gli alias $u 0, $u 1, ..., $u 9 non sono pseudoregistri, nonostante la loro aspetto simile. Per altre informazioni su questi alias, vedere Uso di alias.

Esempio

Nell'esempio seguente viene impostato un punto di interruzione che viene raggiunto ogni volta che il thread corrente chiama NtOpenFile. Ma questo punto di interruzione non viene raggiunto quando altri thread chiamano NtOpenFile.

kd> bp /t @$thread nt!ntopenfile

Esempio

Nell'esempio seguente viene eseguito un comando finché il registro contiene un valore specificato. Prima di tutto, inserire il codice seguente per l'esecuzione condizionale in un file di script denominato "eaxstep".

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

Eseguire quindi il comando seguente.

t "$<eaxstep"

Il debugger esegue un passaggio e quindi esegue il comando. In questo caso, il debugger esegue lo script, che visualizza 1234 o ripete il processo.