Conversione di indirizzi virtuali in indirizzi fisici
La maggior parte dei comandi del debugger usa indirizzi virtuali, non indirizzi fisici, come input e output. Tuttavia, ci sono momenti in cui l'indirizzo fisico può essere utile.
Esistono due modi per convertire un indirizzo virtuale in un indirizzo fisico: usando l'estensione !vtop e usando l'estensione !pte .
Per una panoramica dell'indirizzo virtuale in Windows, vedere Spazi indirizzi virtuali.
Conversione degli indirizzi con !vtop
Si supponga di eseguire il debug di un computer di destinazione in cui è in esecuzione il processo di MyApp.exe e di voler analizzare l'indirizzo virtuale 0x0012F980. Ecco la procedura usata con l'estensione !vtop per determinare l'indirizzo fisico corrispondente.
Conversione di un indirizzo virtuale in un indirizzo fisico con !vtop
Assicurarsi di lavorare in formato esadecimale. Se necessario, impostare la base corrente con il comando N 16 .
Determinare l'indice di byte dell'indirizzo. Questo numero è uguale ai 12 bit più bassi dell'indirizzo virtuale. Pertanto, l'indirizzo virtuale 0x0012F980 ha un indice di byte di 0x980.
Determinare la base di directory dell'indirizzo usando l'estensione !process :
kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** .... PROCESS ff779190 SessionId: 0 Cid: 04fc Peb: 7ffdf000 ParentCid: 0394 DirBase: 098fd000 ObjectTable: e1646b30 TableSize: 8. Image: MyApp.exe
Determinare il numero di frame di pagina della directory di base. Si tratta semplicemente della base di directory senza i tre zeri esadecimali finali. In questo esempio, la base di directory è 0x098FD000, quindi il numero di frame di pagina è 0x098FD.
Usare l'estensione !vtop . Il primo parametro di questa estensione deve essere il numero di frame di pagina. Il secondo parametro di !vtop deve essere l'indirizzo virtuale in questione:
kd> !vtop 98fd 12f980 Pdi 0 Pti 12f 0012f980 09de9000 pfn(09de9)
Il secondo numero visualizzato nella riga finale è l'indirizzo fisico dell'inizio della pagina fisica.
Aggiungere l'indice di byte all'indirizzo dell'inizio della pagina: 0x09DE9000 + 0x980 = 0x09DE9980. Questo è l'indirizzo fisico desiderato.
È possibile verificare che il calcolo sia stato eseguito correttamente visualizzando la memoria in ogni indirizzo. L'estensione !d\* visualizza la memoria in corrispondenza di un indirizzo fisico specificato:
kd> !dc 9de9980
# 9de9980 6d206e49 726f6d65 00120079 0012f9f4 In memory.......
# 9de9990 0012f9f8 77e57119 77e8e618 ffffffff .....q.w...w....
# 9de99a0 77e727e0 77f6f13e 77f747e0 ffffffff .'.w>..w.G.w....
# 9de99b0 .....
Il comando d* (Display Memory) usa un indirizzo virtuale come argomento:
kd> dc 12f980
0012f980 6d206e49 726f6d65 00120079 0012f9f4 In memory.......
0012f990 0012f9f8 77e57119 77e8e618 ffffffff .....q.w...w....
0012f9a0 77e727e0 77f6f13e 77f747e0 ffffffff .'.w>..w.G.w....
0012f9b0 .....
Poiché i risultati sono gli stessi, ciò indica che l'indirizzo fisico 0x09DE9980 corrisponde effettivamente all'indirizzo virtuale 0x0012F980.
Conversione degli indirizzi con !pte
Anche in questo caso, si supponga di analizzare l'indirizzo virtuale 0x0012F980 appartenente al processo di MyApp.exe. Ecco la procedura usata con l'estensione !pte per determinare l'indirizzo fisico corrispondente:
Conversione di un indirizzo virtuale in un indirizzo fisico tramite !pte
Assicurarsi di lavorare in formato esadecimale. Se necessario, impostare la base corrente con il comando N 16 .
Determinare l'indice di byte dell'indirizzo. Questo numero è uguale ai 12 bit più bassi dell'indirizzo virtuale. Pertanto, l'indirizzo virtuale 0x0012F980 ha un indice di byte di 0x980.
Impostare il contesto del processo sul processo desiderato:
kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** .... PROCESS ff779190 SessionId: 0 Cid: 04fc Peb: 7ffdf000 ParentCid: 0394 DirBase: 098fd000 ObjectTable: e1646b30 TableSize: 8. Image: MyApp.exe kd> .process /p ff779190 Implicit process is now ff779190 .cache forcedecodeuser done
Usare l'estensione !pte con l'indirizzo virtuale come argomento. Vengono visualizzate informazioni in due colonne. La colonna sinistra descrive la voce di directory della pagina (PDE) per questo indirizzo; la colonna destra descrive la voce della tabella di pagina (PTE):
kd> !pte 12f980 VA 0012f980 PDE at C0300000 PTE at C00004BC contains 0BA58067 contains 09DE9067 pfn ba58 ---DA--UWV pfn 9de9 ---DA--UWV
Cercare nell'ultima riga della colonna destra. Viene visualizzata la notazione "pfn 9de9". Il numero 0x9DE9 è il numero di frame di pagina (PFN) di questo PTE. Moltiplicare il numero di frame di pagina per 0x1000 (ad esempio, spostarlo a sinistra a 12 bit). Il risultato, 0x09DE9000, è l'indirizzo fisico dell'inizio della pagina.
Aggiungere l'indice di byte all'indirizzo dell'inizio della pagina: 0x09DE9000 + 0x980 = 0x09DE9980. Questo è l'indirizzo fisico desiderato.
Si tratta dello stesso risultato ottenuto dal metodo precedente.
Conversione di indirizzi manualmente
Anche se le estensioni !ptov e pte forniscono il modo più rapido per convertire gli indirizzi virtuali in indirizzi fisici, questa conversione può essere eseguita anche manualmente. Una descrizione di questo processo farà luce su alcuni dettagli dell'architettura di memoria virtuale.
Le strutture di memoria variano in base al processore e alla configurazione hardware. Questo esempio è tratto da un sistema x86 in cui non è abilitata l'estensione indirizzo fisico (PAE).
Usando di nuovo 0x0012F980 come indirizzo virtuale, è prima necessario convertirlo in formato binario, manualmente o usando il comando .formats (Show Number Formats):
kd> .formats 12f980
Evaluate expression:
Hex: 0012f980
Decimal: 1243520
Octal: 00004574600
Binary: 00000000 00010010 11111001 10000000
Chars: ....
Time: Thu Jan 15 01:25:20 1970
Float: low 1.74254e-039 high 0
Double: 6.14381e-318
Questo indirizzo virtuale è una combinazione di tre campi. I bit da 0 a 11 sono l'indice dei byte. I bit da 12 a 21 sono l'indice della tabella di pagina. I bit da 22 a 31 sono l'indice della directory della pagina. Separando i campi, sono disponibili:
0x0012F980 = 0y 00000000 00 010010 1111 1001 10000000
In questo modo vengono esposte le tre parti dell'indirizzo virtuale:
Indice della directory della pagina = 0y0000000000 = 0x0
Indice tabella di pagina = 0y0100101111 = 0x12F
Indice byte = 0y100110000000 = 0x980
Sono quindi necessarie tre informazioni aggiuntive per il sistema.
Dimensioni di ogni PTE. Si tratta di 4 byte nei sistemi non PAE x86.
Dimensioni di una pagina. Si tratta di 0x1000 byte.
Indirizzo virtuale PTE_BASE. In un sistema non PAE, si tratta di 0xC0000000.
Usando questi dati, è possibile calcolare l'indirizzo del PTE stesso:
PTE address = PTE_BASE
+ (page directory index) * PAGE_SIZE
+ (page table index) * sizeof(MMPTE)
= 0xc0000000
+ 0x0 * 0x1000
+ 0x12F * 4
= 0xC00004BC
Questo è l'indirizzo del PTE. Il PTE è un DWORD a 32 bit. Esaminarne il contenuto:
kd> dd 0xc00004bc L1
c00004bc 09de9067
Questo PTE ha valore 0x09DE9067. È costituito da due campi:
I 12 bit bassi del PTE sono i flag di stato. In questo caso, questi flag sono uguali 0x067 - o in binary, 0y000001100111. Per una spiegazione dei flag di stato, vedere la pagina di riferimento !pte .
I 20 bit alti del PTE sono uguali al numero di frame di pagina (PFN) del PTE. In questo caso, il pfn è 0x09DE9.
Il primo indirizzo fisico nella pagina fisica è il pfn moltiplicato per 0x1000 (spostato a sinistra a 12 bit). L'indice dei byte è l'offset in questa pagina. Di conseguenza, l'indirizzo fisico che si sta cercando è 0x09DE9000 + 0x980 = 0x09DE9980. Si tratta dello stesso risultato ottenuto dai metodi precedenti.