Condividi tramite


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

  1. Assicurarsi di lavorare in formato esadecimale. Se necessario, impostare la base corrente con il comando N 16 .

  2. 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.

  3. 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
    
  4. 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.

  5. 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.

  6. 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

  1. Assicurarsi di lavorare in formato esadecimale. Se necessario, impostare la base corrente con il comando N 16 .

  2. 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.

  3. 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
    
  4. 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
    
  5. 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.

  6. 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.