|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
ptov.c
Abstract:
Kernel debugger extension for dumping all physical to virtual translations for a given process.
Author:
John Vert (jvert) 25-Jul-1995
Revision History:
--*/ #include "precomp.h"
BOOL ReadPhysicalPage( IN ULONG64 PageNumber, OUT PVOID Buffer );
DECLARE_API( ptov )
/*++
Routine Description:
Dumps all physical to virtual translations for a given process
Arguments:
args - supplies physical address of PDE
Return Value:
None.
--*/
{ ULONG64 PdeAddress=0; ULONG ActualRead; PCHAR PageDirectory; PCHAR PageTable; ULONG i,j; ULONG64 VirtualPage=0; ULONG SizeOfHwPte; ULONG Flags = 1; ULONG ValidOff, ValidSize, PfnOff, PfnSz; HRESULT Hr = S_OK;
if (sscanf(args, "%I64lx %lx", &PdeAddress, &Flags) < 1 || PdeAddress == 0) { dprintf("usage: ptov PFNOfPDE\n"); return E_INVALIDARG; }
if (PageSize == 0){ dprintf("Cpuld not get PageSize\n"); return E_INVALIDARG; } PageDirectory = LocalAlloc(LMEM_FIXED, PageSize); if (PageDirectory == NULL) { dprintf("Couldn't allocate %d bytes for page directory\n",PageSize); return E_OUTOFMEMORY; } PageTable = LocalAlloc(LMEM_FIXED, PageSize); if (PageTable == NULL) { dprintf("Couldn't allocate %d bytes for page table\n",PageSize); LocalFree(PageDirectory); return E_OUTOFMEMORY; }
SizeOfHwPte = GetTypeSize("nt!HARDWARE_PTE"); GetBitFieldOffset("nt!HARDWARE_PTE", "Valid", &ValidOff, &ValidSize); GetBitFieldOffset("nt!HARDWARE_PTE", "PageFrameNumber", &PfnOff, &PfnSz); __try { if (ReadPhysicalPage(PdeAddress,PageDirectory)) { for (i=0;i<PageSize/SizeOfHwPte;i++) { ULONG64 thisPageDir; ULONG64 PageFrameNumber;
if (SizeOfHwPte == 4) { thisPageDir = *((PULONG)PageDirectory + i); } else { thisPageDir = *((PULONG64)PageDirectory + i); }
if (CheckControlC()) { Hr = E_ABORT; __leave; }
PageFrameNumber = GetBits(thisPageDir, PfnOff, PfnSz);
if (((thisPageDir >> ValidOff) & 1) && ReadPhysicalPage(PageFrameNumber,PageTable)) {
for (j=0;j<PageSize/SizeOfHwPte;j++) { ULONG64 thisPageTable;
if (SizeOfHwPte == 4) { thisPageTable = *((PULONG)PageTable + j); } else { thisPageTable = *((PULONG64)PageTable + j); }
if ( CheckControlC() ) { Hr = E_INVALIDARG; __leave; } if ((thisPageTable >> ValidOff) & 1) { dprintf("%I64lx %I64lx\n",GetBits(thisPageTable, PfnOff, PfnSz)*PageSize,VirtualPage); } VirtualPage+=PageSize; } } else { VirtualPage += PageSize * (PageSize/SizeOfHwPte); } } } } __finally { LocalFree(PageDirectory); LocalFree(PageTable); } return Hr; }
ULONG DBG_GET_PAGE_SHIFT ( VOID );
BOOL ReadPhysicalPage( IN ULONG64 PageNumber, OUT PVOID Buffer ) { ULONG i; ULONG64 Address;
//
// do the read 1k at a time to avoid overflowing the packet maximum.
//
Address = PageNumber << DBG_GET_PAGE_SHIFT(); if (!IsPtr64()) { // Address = (ULONG64) (LONG64) (LONG) Address;
} // dprintf("Pg no %I64lx shft by %d, PhyAddr %I64lx\n", PageNumber, DBG_GET_PAGE_SHIFT(), Address);
for (i=0; i<PageSize/1024; i++) { ULONG ActualRead = 0; ReadPhysical(Address, Buffer, 1024, &ActualRead); if (ActualRead != 1024) { dprintf("physical read at %p failed\n",Address); return(FALSE); } Address += 1024; Buffer = (PVOID)((PUCHAR)Buffer + 1024); } return(TRUE); }
ULONG64 DBG_GET_MM_SESSION_SPACE_DEFAULT ( VOID );
DECLARE_API( vtop )
/*++
Routine Description:
Dumps the virtual to physical translation for a page
Arguments:
args - supplies physical address of PDE
Return Value:
None.
--*/
{ ULONG ActualRead; ULONG i,j; PUCHAR PageDirectory; PUCHAR PageTable; ULONG64 PdeAddress = 0; ULONG64 VirtualPage= 0;//DBG_GET_MM_SESSION_SPACE_DEFAULT();
ULONG PageShift,SizeOfHwPte; ULONG ValidOff, ValidSize, PfnOff, PfnSz, TransOff, TransSize; HRESULT Hr;
if (!sscanf(args,"%I64lx %I64lx", &PdeAddress,&VirtualPage)) { // Do not use GetExpression - physical addresses
// VirtualPage = GetExpression(args);
PdeAddress = 0; VirtualPage = 0; }
if (!(SizeOfHwPte = GetTypeSize("nt!HARDWARE_PTE")) ) { dprintf("Cannot find HARDWARE_PTE\n"); return E_INVALIDARG; }
PageShift = DBG_GET_PAGE_SHIFT(); if ((PdeAddress == 0) && (VirtualPage == 0)) { dprintf("usage: vtop PFNOfPDE VA\n"); return E_INVALIDARG; } else if (VirtualPage) { ULONG64 Process;
Process = GetExpression("@$proc");
if (GetFieldValue(Process, "nt!_KPROCESS", "DirectoryTableBase[0]", PdeAddress) != S_OK) { dprintf("Cannot read DirectoryTableBase for currect process\n"); return E_FAIL; }
}
// Common mistake, typed in full 32 bit address, not pfn
if( PdeAddress & ~((1 << (32-PageShift)) - 1) ) { PdeAddress >>= PageShift; }
PageDirectory = LocalAlloc(LMEM_FIXED, PageSize); if (PageDirectory == NULL) { dprintf("Couldn't allocate %d bytes for page directory\n",PageSize); return E_INVALIDARG; } PageTable = LocalAlloc(LMEM_FIXED, PageSize); if (PageTable == NULL) { dprintf("Couldn't allocate %d bytes for page table\n",PageSize); LocalFree(PageDirectory); return E_INVALIDARG; }
__try { i =(ULONG) ( VirtualPage / (PageSize*(PageSize/ SizeOfHwPte))); j = (ULONG) ((VirtualPage % (PageSize*(PageSize/ SizeOfHwPte))) / PageSize);
dprintf("Pdi %x Pti %x\n",i,j); GetBitFieldOffset("nt!_MMPTE", "u.Soft.Transition", &TransOff, &TransSize); GetBitFieldOffset("nt!HARDWARE_PTE", "Valid", &ValidOff, &ValidSize); GetBitFieldOffset("nt!HARDWARE_PTE", "PageFrameNumber", &PfnOff, &PfnSz);
if (ReadPhysicalPage(PdeAddress,PageDirectory)) { ULONG64 thisPageDir;
if (SizeOfHwPte == 4) { thisPageDir = *((PULONG)PageDirectory + i); } else { thisPageDir = *((PULONG64)PageDirectory + i); }
if (CheckControlC()) { Hr = E_INVALIDARG; __leave; }
if ((thisPageDir >> ValidOff) & 1) { ULONG64 PageFrameNumber; ULONG64 thisPageTable;
PageFrameNumber = GetBits(thisPageDir, PfnOff, PfnSz);
if (!ReadPhysicalPage(PageFrameNumber,PageTable)) { Hr = E_INVALIDARG; __leave; }
if (SizeOfHwPte == 4) { thisPageTable = *((PULONG)PageTable + j); } else { thisPageTable = *((PULONG64)PageTable + j); }
if ((thisPageTable >> ValidOff) & 1) { dprintf("%08I64lx %08I64lx pfn(%05I64lx)\n", VirtualPage, GetBits(thisPageTable, PfnOff, PfnSz)*PageSize, GetBits(thisPageTable, PfnOff, PfnSz) ); } else {
if ((thisPageTable >> TransOff) & 1) { dprintf("%08I64lx Transition %08I64lx (%05I64lx)\n", VirtualPage, GetBits(thisPageTable, PfnOff, PfnSz)*PageSize, GetBits(thisPageTable, PfnOff, PfnSz) ); } else { dprintf("%08I64lx Not present (%p)\n",VirtualPage,thisPageTable); } } } else { dprintf("PageDirectory Entry %u not valid, try another process\n",i); } } } __finally { LocalFree(PageDirectory); LocalFree(PageTable); } return Hr; }
|