Freigeben über


Konvertieren virtueller Adressen in physische Adressen

Die meisten Debuggerbefehle verwenden virtuelle Adressen, nicht physische Adressen, als Eingabe und Ausgabe. Es gibt jedoch Zeiten, in denen die physische Adresse nützlich sein kann.

Es gibt zwei Möglichkeiten, eine virtuelle Adresse in eine physische Adresse zu konvertieren: mithilfe der Erweiterung !vtop und mit der Erweiterung !pte .

Eine Übersicht über die virtuelle Adresse in Windows finden Sie unter Virtuelle Adressräume.

Adresskonvertierung mithilfe von !vtop

Angenommen, Sie debuggen einen Zielcomputer, auf dem der MyApp.exe-Prozess ausgeführt wird, und Sie möchten die virtuelle Adresse 0x0012F980 untersuchen. Hier sehen Sie die Prozedur, die Sie mit der Erweiterung !vtop verwenden würden, um die entsprechende physische Adresse zu bestimmen.

Konvertieren einer virtuellen Adresse in eine physische Adresse mithilfe von !vtop

  1. Stellen Sie sicher, dass Sie hexadezimal arbeiten. Legen Sie bei Bedarf die aktuelle Basis mit dem Befehl N 16 fest.

  2. Bestimmen Sie den Byteindex der Adresse. Diese Zahl entspricht den niedrigsten 12 Bits der virtuellen Adresse. Daher weist die virtuelle Adresse 0x0012F980 einen Byteindex von 0x980 auf.

  3. Ermitteln Sie die Verzeichnisbasis der Adresse mithilfe der Erweiterung !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. Bestimmen Sie die Seitenrahmennummer der Verzeichnisbasis. Dies ist einfach die Verzeichnisbasis ohne die drei nachfolgenden hexadezimalen Nullen. In diesem Beispiel ist die Verzeichnisbasis 0x098FD000, sodass die Seitenrahmennummer 0x098FD wird.

  5. Verwenden Sie die Erweiterung !vtop . Der erste Parameter dieser Erweiterung sollte die Seitenrahmennummer sein. Der zweite Parameter von !vtop sollte die betreffende virtuelle Adresse sein:

    kd> !vtop 98fd 12f980
    Pdi 0 Pti 12f
    0012f980 09de9000 pfn(09de9)
    

    Die zweite Zahl, die in der letzten Zeile angezeigt wird, ist die physische Adresse des Anfangs der physischen Seite.

  6. Fügen Sie den Byteindex zur Adresse des Seitenanfangs hinzu: 0x09DE9000 + 0x980 = 0x09DE9980. Dies ist die gewünschte physische Adresse.

Sie können überprüfen, ob diese Berechnung ordnungsgemäß durchgeführt wurde, indem Sie den Arbeitsspeicher an jeder Adresse anzeigen. Die Erweiterung !d\* zeigt Arbeitsspeicher an einer angegebenen physischen Adresse an:

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

Der Befehl d* (Speicher anzeigen) verwendet eine virtuelle Adresse als Argument:

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

Da die Ergebnisse identisch sind, gibt dies an, dass die physische Adresse 0x09DE9980 tatsächlich der virtuellen Adresse 0x0012F980 entspricht.

Adresskonvertierung mithilfe von !pte

Angenommen, Sie untersuchen die virtuelle Adresse 0x0012F980, die zum MyApp.exe-Prozess gehört. Hier ist die Prozedur, die Sie mit der Erweiterung !pte verwenden würden, um die entsprechende physische Adresse zu bestimmen:

Konvertieren einer virtuellen Adresse in eine physische Adresse mithilfe von !pte

  1. Stellen Sie sicher, dass Sie hexadezimal arbeiten. Legen Sie bei Bedarf die aktuelle Basis mit dem Befehl N 16 fest.

  2. Bestimmen Sie den Byteindex der Adresse. Diese Zahl entspricht den niedrigsten 12 Bits der virtuellen Adresse. Daher weist die virtuelle Adresse 0x0012F980 einen Byteindex von 0x980 auf.

  3. Legen Sie den Prozesskontext auf den gewünschten Prozess fest:

    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. Verwenden Sie die Erweiterung !pte mit der virtuellen Adresse als Argument. Dadurch werden Informationen in zwei Spalten angezeigt. Die linke Spalte beschreibt den Seitenverzeichniseintrag (PDE) für diese Adresse. die rechte Spalte beschreibt den Seitentabelleneintrag (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. Suchen Sie in der letzten Zeile der rechten Spalte. Die Notation "pfn 9de9" wird angezeigt. Die Zahl 0x9DE9 ist die Seitenrahmennummer (PFN) dieses PTE. Multiplizieren Sie die Seitenrahmennummer mit 0x1000 (z. B. verschieben Sie sie um 12 Bits). Das Ergebnis, 0x09DE9000, ist die physische Adresse des Seitenanfangs.

  6. Fügen Sie den Byteindex zur Adresse des Seitenanfangs hinzu: 0x09DE9000 + 0x980 = 0x09DE9980. Dies ist die gewünschte physische Adresse.

Dies ist das gleiche Ergebnis, das von der vorherigen Methode erzielt wurde.

Manuelles Konvertieren von Adressen

Obwohl die Erweiterungen !ptov und pte die schnellste Möglichkeit bieten, virtuelle Adressen in physische Adressen zu konvertieren, kann diese Konvertierung auch manuell erfolgen. Eine Beschreibung dieses Prozesses beleuchtet einige Details der Architektur des virtuellen Speichers.

Arbeitsspeicherstrukturen variieren je nach Prozessor und Hardwarekonfiguration in der Größe. Dieses Beispiel stammt aus einem x86-System, auf dem paE (Physical Address Extension) nicht aktiviert ist.

Wenn Sie 0x0012F980 erneut als virtuelle Adresse verwenden, müssen Sie sie zunächst manuell oder mit dem Befehl .formats (Zahlenformate anzeigen) in binär konvertieren:

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

Diese virtuelle Adresse ist eine Kombination aus drei Feldern. Bits 0 bis 11 sind der Byteindex. Bits 12 bis 21 sind der Seitentabellenindex. Bits 22 bis 31 sind der Seitenverzeichnisindex. Wenn Sie die Felder trennen, verfügen Sie über Folgendes:

0x0012F980  =  0y  00000000 00   010010 1111   1001 10000000

Dadurch werden die drei Teile der virtuellen Adresse verfügbar gemacht:

  • Seitenverzeichnisindex = 0y000000000000 = 0x0

  • Seitentabellenindex = 0y0100101111 = 0x12F

  • Byteindex = 0y1001100000000 = 0x980

Anschließend benötigen Sie drei zusätzliche Informationen für Ihr System.

  • Die Größe jedes PTE. Dies sind 4 Bytes auf x86-Nicht-PAE-Systemen.

  • Die Größe einer Seite. Dies ist 0x1000 Bytes.

  • Die PTE_BASE virtuelle Adresse. Bei einem Nicht-PAE-System ist dies 0xC0000000.

Mithilfe dieser Daten können Sie die Adresse des PTE selbst berechnen:

PTE address   =   PTE_BASE  
                + (page directory index) * PAGE_SIZE
                + (page table index) * sizeof(MMPTE)
              =   0xc0000000
                + 0x0   * 0x1000
                + 0x12F * 4
              =   0xC00004BC

Dies ist die Adresse des PTE. Der PTE ist ein 32-Bit-DWORD. Untersuchen Sie den Inhalt:

kd> dd 0xc00004bc L1
c00004bc  09de9067

Dieser PTE hat den Wert 0x09DE9067. Es besteht aus zwei Feldern:

  • Die niedrigen 12 Bits des PTE sind die status Flags. In diesem Fall entsprechen diese Flags 0x067 oder binär 0y00000110111. Eine Erläuterung der status Flags finden Sie auf der !pte-Referenzseite.

  • Die hohen 20 Bits des PTE entsprechen der Seitenrahmennummer (Page Frame Number , PFN) des PTE. In diesem Fall wird der PFN 0x09DE9.

Die erste physische Adresse auf der physischen Seite ist der PFN multipliziert mit 0x1000 (links 12 Bit verschoben). Der Byteindex ist der Offset auf dieser Seite. Daher ist die physische Adresse, nach der Sie suchen, 0x09DE9000 + 0x980 = 0x09DE9980. Dies ist das gleiche Ergebnis, das mit den früheren Methoden erzielt wurde.