Intro
The best reference I could find on the topic was the post
from the MSDN NtDebugging blog, Series - Part 3: Understanding !PTE - Non-PAE
and X64 article http://blogs.msdn.com/b/ntdebugging/archive/2010/06/22/part-3-understanding-pte-non-pae-and-x64.aspx.
It helped but I needed to really delve into the mapping
mechanisms with an example, as well as call out some of the pitfalls in using
the relevant WinDbg commands.
Setup
Taking a look at a instance of notepad as example running on a Windows 7 x64 system (this was performed in WinDbg, using sysinterals livekd)
0: kd> !dml_proc 0xfffffa800c0cd890
Address
PID Image file name
fffffa80`0c0cd890 bbc
notepad.exe Full details
Switching to process
0: kd> .process /p /r 0xfffffa800c0cd890
Implicit process is now fffffa80`0c0cd890
Loading User Symbols
.........................
Display loaded modules
0: kd> lmuD
start
<snip>
00000000`ff460000 00000000`ff495000 notepad
(deferred)
<snip>
And let's take a look (using the virtual address), MZ header
has we'd expect.
0: kd> db
00000000`ff460000 L100
00000000`ff460000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00
00 MZ..............
00000000`ff460010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00
00 ........@.......
00000000`ff460020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00
00 ................
00000000`ff460030 00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00
00 ................
00000000`ff460040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54
68 ........!..L.!Th
00000000`ff460050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e
6f is program canno
00000000`ff460060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53
20 t be run in DOS
00000000`ff460070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00
00 mode....$.......
(I did do a quick compare with the rest of the image to be
sure this was notepad and not just some random MZ header)
In order to convert this to the physical address, WinDbg
provides two commands to help
!pte
!vtop
Both of these commands walk the below diagram (from the Intel 64 and IA-32 Architecture software development manual volume 3)
!vtop
!vtop performs the conversion between the virtual address to
the corresponding physical address, quite seamlessly however there's a few
minor pitfalls.
There's two principle formats
!vtop PFN VA
!vtop 0 VA
PFN - Page Frame Number
VA - Virtual Address
Where 0 is current process context as set by the .process command (above)
Amd64VtoP:
Virt 00000000`ff460000, pagedir 1bf52000
Amd64VtoP:
PML4E 1bf52000
Amd64VtoP:
PDPE 2`21b80018
Amd64VtoP:
PDE 3a001fd0
Amd64VtoP:
PTE 17402300
Amd64VtoP:
Mapped phys 25051000
Virtual
address ff460000 translates to physical address 25051000.
Had we not applied the .process command earlier, our !vtop 0
VA would not have worked :( ) You would
get a output like
Amd64VtoP:
Virt 00000000`ff460000, pagedir ce985000
Amd64VtoP:
PML4E ce985000
Amd64VtoP:
PDPE 21bf6018
Amd64VtoP:
zero PDPE
Virtual
address ff460000 translation fails, error 0xD000014
Alternatively we could have specified the PFN (Page Frame
Number) directly. Now you might think (well I did at first) that the pfns from
the !pte output should be used. Well actually no, you need the pfn from the DirBase
and unlike in 32 bit mode, the pfn is the entire address.
0:
kd> !process 0xfffffa800c0cd890 7
PROCESS
fffffa800c0cd890
SessionId: 1 Cid: 0bbc
Peb: 7fffffdd000 ParentCid: 0484
DirBase:
1bf52000 ObjectTable:
fffff8a00d50a560 HandleCount: 58.
Image: notepad.exe
VadRoot fffffa800dcd4870 Vads 58 Clone 0
Private 548. Modified 0. Locked 0.
DeviceMap fffff8a003ffc4e0
Thus the pfn is 1bf52000
Amd64VtoP:
Virt 00000000`ff460000, pagedir 1bf52000
Amd64VtoP:
PML4E 1bf52000
Amd64VtoP:
PDPE 2`21b80018
Amd64VtoP:
PDE 3a001fd0
Amd64VtoP:
PTE 17402300
Amd64VtoP:
Mapped phys 25051000
Virtual
address ff460000 translates to physical address 25051000.
So let's take a a look at 0x25051000 physical address (notice
the # to indicate physical addresses) Here we use !d* to examine a physical address as opposed d* for a virtual address
0:
kd> !db 25051000 L100
#25051000
4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
#25051010
b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@.......
#25051020
00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#25051030
00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00 00 ................
#25051040
0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th
#25051050
69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
#25051060
74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
#25051070
6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
!pte
0: kd> !pte
00000000`ff460000
VA
00000000ff460000
PXE at FFFFF6FB7DBED000 PPE at FFFFF6FB7DA00018 PDE at FFFFF6FB40003FD0 PTE at FFFFF680007FA300
contains
02A0000221B80867 contains
1C1000003A001867 contains
03A0000017402867 contains
82D0000025051025
pfn 221b80 ---DA--UWEV
pfn 3a001 ---DA--UWEV pfn 17402
---DA--UWEV pfn 25051 ----A--UR-V
What does this all mean?
Well the pte entry at address FFFFF680007FA300 contains the PAE
Page-Table Entry containing 82D0000025051025, of which the physical address is
bits 12 to (M–1) or more precisely 0x25051000
And of course this gives the same result
0:
kd> !db 25051000 L100
#25051000
4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
#25051010
b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@.......
#25051020
00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#25051030
00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00 00 ................
#25051040
0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th
#25051050
69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
#25051060
74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
#25051070
6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
Hope this helps your WinDbg en devours.