|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
pte.c
Abstract:
WinDbg Extension Api
Author:
Lou Perazzoli (LouP) 15-Feb-1992
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
#include "i386.h"
#include "ia64.h"
#include "amd64.h"
ULONG64 MmNonPagedPoolEnd=0; ULONG64 MmSubsectionBase=0;
ULONG64 KiIA64VaSignedFill; ULONG64 KiIA64PtaBase; ULONG64 KiIA64PtaSign;
ULONG DbgGetPageFileHigh( ULONG64 Pte );
////////////////////////////////////////////////////////////////////////////////
//
// I386
//
////////////////////////////////////////////////////////////////////////////////
#define PaeGetPdeAddressX86(va) ((ULONG64) (LONG64) (LONG) (PDE_BASE_X86 + ((((ULONG)(va)) >> 21) << 3)))
#define MiGetPdeAddressX86(va) ((ULONG64) (LONG64) (LONG) (((((ULONG)(va)) >> 22) << 2) + PDE_BASE_X86))
#define PaeGetVirtualAddressMappedByPteX86(PTE) (((ULONG64)(PTE) << 9))
#define PaeGetPteAddressX86(va) ((ULONG64)(PTE_BASE_X86 + ((((ULONG)(va)) >> 12) << 3)))
#define MiGetPteAddressX86(va) (((((ULONG) (va)) >> 12) << 2) + PTE_BASE_X86)
#define MiGetPteOffsetX86(va) ((((ULONG) (va)) >> 12) & 0x3ff)
#define MiGetVirtualAddressMappedByPteX86(PTE) ((ULONG64) (LONG64) (LONG) ((PTE) << 10))
////////////////////////////////////////////////////////////////////////////////
//
// AMD64
//
////////////////////////////////////////////////////////////////////////////////
#define AMD64_VA_MASK (((ULONG64)1 << AMD64_VA_BITS) - 1)
#define MiGetPteAddressAMD64(va) ((((((ULONG64)(va) & AMD64_VA_MASK) >> PTI_SHIFT_AMD64) << PTE_SHIFT_AMD64) + PTE_BASE_AMD64))
#define MiGetPdeAddressAMD64(va) ((((((ULONG64)(va) & AMD64_VA_MASK) >> PDI_SHIFT_AMD64) << PTE_SHIFT_AMD64) + PDE_BASE_AMD64))
#define MiGetPpeAddressAMD64(va) ((((((ULONG64)(va) & AMD64_VA_MASK) >> PPI_SHIFT_AMD64) << PTE_SHIFT_AMD64) + PPE_BASE_AMD64))
#define MiGetPxeAddressAMD64(va) ((((((ULONG64)(va) & AMD64_VA_MASK) >> PXI_SHIFT_AMD64) << PTE_SHIFT_AMD64) + PXE_BASE_AMD64))
#define MiGetPteOffsetAMD64(va) ((((ULONG_PTR) (va)) >> 12) & 0x3ff)
#define MiGetVirtualAddressMappedByPteAMD64(PTE) \
((ULONG64)((LONG64)(((LONG64)(PTE) - PTE_BASE_AMD64) << (PAGE_SHIFT_AMD64 + AMD64_VA_SHIFT - PTE_SHIFT_AMD64)) >> AMD64_VA_SHIFT))
////////////////////////////////////////////////////////////////////////////////
//
// IA64
//
////////////////////////////////////////////////////////////////////////////////
//
// MiGetPdeAddress returns the address of the PTE which maps the
// given virtual address. Note we must redefine some of the MM
// macros here because they cast values to pointers which does not work
// on systems where pointers are only 32 bits.
//
VOID DbgGetPteBaseIA64( VOID ) { ULONG64 PtaValue; ULONG i;
if (KiIA64PtaBase != 0) {
return;
}
if (g_ExtData == NULL || g_ExtData->lpVtbl-> ReadProcessorSystemData(g_ExtData, 0, DEBUG_DATA_BASE_TRANSLATION_VIRTUAL_OFFSET, &PtaValue, sizeof(PtaValue), NULL) != S_OK) { PtaValue = (ULONG64) GetExpression("@pta"); }
KiIA64PtaBase = PtaValue & ~0xffffUI64; KiIA64VaSignedFill = (KiIA64PtaBase << (PAGE_SHIFT_IA64 - PTE_SHIFT_IA64)) & ~VRN_MASK_IA64;
KiIA64PtaSign = KiIA64PtaBase;
for (i = 0; i < 64; i += 1) {
KiIA64PtaSign >>= 1;
if (KiIA64PtaSign & 1) { KiIA64PtaSign = (ULONG64)1 << i; break; } } }
ULONG64 MiGetPteAddressIA64 ( IN ULONG64 Va ) {
DbgGetPteBaseIA64();
if (((((ULONG64)(Va)) & PDE_TBASE_IA64) == PDE_TBASE_IA64) && ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_TBASE_IA64)) < PageSize)) {
return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) | (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE"))); }
return (ULONG64) (((((ULONG64)(Va)) & VRN_MASK_IA64)) | ((((((ULONG64)(Va)) >> PTI_SHIFT_IA64) << PTE_SHIFT_IA64) & (~(PTE_BASE_IA64|VRN_MASK_IA64))) + PTE_BASE_IA64)); }
ULONG64 MiGetPdeAddressIA64 ( IN ULONG64 Va ) { DbgGetPteBaseIA64();
if (((((ULONG64)(Va)) & PDE_BASE_IA64) == PDE_BASE_IA64) && ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_BASE_IA64)) < ((ULONG64)1 << PDI_SHIFT_IA64))) {
return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) | (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE"))); }
if (((((ULONG64)(Va)) & PDE_TBASE_IA64) == PDE_TBASE_IA64) && ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_TBASE_IA64)) < PageSize)) {
return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) | (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE"))); }
return (ULONG64) (((((ULONG64)(Va)) & VRN_MASK_IA64)) | ((((((ULONG64)(Va)) >> PDI_SHIFT_IA64) << PTE_SHIFT_IA64) & (~(PDE_BASE_IA64|VRN_MASK_IA64))) + PDE_BASE_IA64)); }
ULONG64 MiGetPpeAddressIA64 ( IN ULONG64 Va ) { DbgGetPteBaseIA64();
if ((((ULONG64)(Va) & PTE_BASE_IA64) == PTE_BASE_IA64) && ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PTE_BASE_IA64)) < ((ULONG64)1 << PDI1_SHIFT_IA64))) {
return (ULONG64) (((ULONG64)Va & VRN_MASK_IA64) | (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE"))); }
if (((((ULONG64)(Va)) & PDE_BASE_IA64) == PDE_BASE_IA64) && ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_BASE_IA64)) < ((ULONG64)1 << PDI_SHIFT_IA64))) {
return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) | (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE"))); }
if (((((ULONG64)(Va)) & PDE_TBASE_IA64) == PDE_TBASE_IA64) && ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_TBASE_IA64)) < PageSize)) {
return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) | (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE"))); }
return (ULONG64) (((((ULONG64)(Va)) & VRN_MASK_IA64)) | ((((((ULONG64)(Va)) >> PDI1_SHIFT_IA64) << PTE_SHIFT_IA64) & (~(PDE_TBASE_IA64|VRN_MASK_IA64))) + PDE_TBASE_IA64)); }
ULONG64 MiGetVirtualAddressMappedByPteIA64( IN ULONG64 PTE ) { DbgGetPteBaseIA64();
return (((ULONG64)(PTE) & PTA_SIGN_IA64) ? (ULONG64)(((ULONG64)(PTE) & VRN_MASK_IA64) | VA_FILL_IA64 | (((ULONG64)(PTE)-PTE_BASE_IA64) << (PAGE_SHIFT_IA64 - PTE_SHIFT_IA64))) : (ULONG64)(((ULONG64)(PTE) & VRN_MASK_IA64) | (((ULONG64)(PTE)-PTE_BASE_IA64) << (PAGE_SHIFT_IA64 - PTE_SHIFT_IA64))));
}
#define MiGetSubsectionAddress(lpte) \
(((lpte)->u.Subsect.WhichPool == 1) ? \ ((ULONG64)((ULONG64)MmSubsectionBase + \ ((ULONG64)(lpte)->u.Subsect.SubsectionAddress))) \ : \ ((ULONG64)((ULONG64)MM_NONPAGED_POOL_END - \ ((ULONG64)(lpte)->u.Subsect.SubsectionAddress))))
#define MiPteToProto(lpte) \
((ULONG64) ((ULONG64)((lpte)->u.Proto.ProtoAddress) + MmProtopte_Base))
////////////////////////////////////////////////////////////////////////////////
//
// AMD64
//
////////////////////////////////////////////////////////////////////////////////
VOID DbgPrintProtection ( ULONG Protection ) { if (Protection == 0) { dprintf("0"); return; }
dprintf ("%x - ", Protection);
if (Protection == MM_NOACCESS) { dprintf("No Access"); } else if (Protection == MM_DECOMMIT) { dprintf("Decommitted"); } else { switch (Protection & 7) { case MM_READONLY: dprintf("Readonly"); break; case MM_EXECUTE: dprintf("Execute"); break; case MM_EXECUTE_READ: dprintf("ExecuteRead"); break; case MM_READWRITE: dprintf("ReadWrite"); break; case MM_WRITECOPY: dprintf("ReadWriteCopy"); break; case MM_EXECUTE_READWRITE: dprintf("ReadWriteExecute"); break; case MM_EXECUTE_WRITECOPY: dprintf("ReadWriteCopyExecute "); break; default: ; } if (Protection & MM_NOCACHE) { dprintf(" UC"); } if (Protection & MM_GUARD_PAGE) { dprintf(" G"); } } }
ULONG64 DbgPteLookupNeeded ( VOID ) { switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: return MI_PTE_LOOKUP_NEEDED_X86;
case IMAGE_FILE_MACHINE_AMD64: return MI_PTE_LOOKUP_NEEDED_AMD64; break;
case IMAGE_FILE_MACHINE_IA64: return MI_PTE_LOOKUP_NEEDED_IA64;
default: break; }
return 0; }
LOGICAL DbgPteIsDemandZero ( ULONG64 CurrentPte ) { ULONG Protection = 0; ULONG64 CurrentPteContents = 0; GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents); GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Soft.Protection", Protection);
//
// The caller has already ensured that the valid, prototype & transition
// bits in the PTE are all zero.
//
if (DbgGetPageFileHigh (CurrentPte) != 0) { return FALSE; }
if ((Protection != 0) && (Protection != MM_NOACCESS) && (Protection != MM_DECOMMIT)) {
return TRUE; }
return FALSE; }
#define PMMPTEx ULONG64
#define PACKET_MAX_SIZE 4000
typedef struct _SYS_PTE_LIST { ULONG64 Next; ULONG64 Previous; ULONG64 Value; ULONG Count; } SYS_PTE_LIST, *PSYS_PTE_LIST;
ULONG MmKseg2Frame;
ULONG MiGetSysPteListDelimiter ( VOID )
/*++
Routine Description:
The platform-specific system PTE list delimiter is returned.
Arguments:
None.
--*/
{ switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: if (PaeEnabled) { return 0xFFFFFFFF; } return 0xFFFFF;
case IMAGE_FILE_MACHINE_AMD64: return 0xFFFFFFFF;
case IMAGE_FILE_MACHINE_IA64: return 0xFFFFFFFF;
default: break; }
return 0; }
ULONG64 MiGetFreeCountFromPteList ( IN ULONG64 Pte )
/*++
Routine Description:
The specified PTE points to a free list header in the system PTE pool. It returns the number of free entries in this block.
Arguments:
Pte - the PTE to examine.
--*/
{ ULONG OneEntry; ULONG64 NextEntry;
GetFieldValue(Pte, "MMPTE", "u.List.OneEntry", OneEntry); GetFieldValue(Pte + GetTypeSize("nt!_MMPTE"), "MMPTE", "u.List.NextEntry",NextEntry); return (( OneEntry) ? 1 : NextEntry); }
DECLARE_API( sysptes )
/*++
Routine Description:
Dumps system PTEs.
Arguments:
args - Flags
Return Value:
None
--*/
{ ULONG ExtraPtesUnleashed; ULONG MaxPteRead; ULONG TotalNumberOfSystemPtes; ULONG64 NonPagedSystemStart; ULONG64 ExtraResourceStart; ULONG64 ExtraPteStart; ULONG NumberOfExtraPtes; ULONG PteListDelimiter; ULONG result; ULONG64 nextfreepte; ULONG Flags; ULONG LastCount; ULONG ReadCount; ULONG64 next; ULONG64 Pte; ULONG64 IndexBase; ULONG64 PteBase; ULONG64 PteBase2; ULONG64 PteArrayReal; ULONG64 PteArray2Real; PCHAR PteArray2; ULONG64 PteEnd; ULONG64 IndexBias; ULONG64 FreeStart; ULONG NumberOfSystemPtes; ULONG NumberOfPtesToCover; PCHAR PteArray; HANDLE PteHandle; ULONG64 PageCount; ULONG64 free; ULONG64 totalFree; ULONG64 largeFree; ULONG i; ULONG64 Flink; ULONG64 PteHeaderAddress; ULONG FreeSysPteListBySize[MM_SYS_PTE_TABLES_MAX]; ULONG SysPteIndex [MM_SYS_PTE_TABLES_MAX]; ULONG PteSize; PVOID PteData; PSYS_PTE_LIST List; CHAR Buffer[256]; ULONG64 displacement;
INIT_API();
List = NULL; PteData = NULL; PteArray = NULL; PteHandle = (HANDLE)0;
Flags = 0; sscanf(args,"%lx",&Flags);
if (Flags & 8) {
//
// Dump the nonpaged pool expansion free PTE list only.
//
IndexBias = GetPointerValue ("nt!MmSystemPteBase"); PteSize = GetTypeSize ("nt!_MMPTE");
i = 0; totalFree = 0; largeFree = 0; PteData = LocalAlloc (LMEM_FIXED, PteSize * 2); if (!PteData) { dprintf("Unable to malloc PTE data\n"); EXIT_API(); return E_INVALIDARG; } FreeStart = GetExpression ("nt!MmFirstFreeSystemPte") + PteSize; if ( !ReadMemory( FreeStart, PteData, PteSize, &result) ) { dprintf("%08p: Unable to get MmFirstFreeSystemPte\n",FreeStart); LocalFree(PteData); EXIT_API(); return E_INVALIDARG; } GetFieldValue(FreeStart, "nt!_MMPTE", "u.List.NextEntry", FreeStart); next = FreeStart;
PteListDelimiter = MiGetSysPteListDelimiter (); while (next != PteListDelimiter) { if ( CheckControlC() ) { goto Bail; }
nextfreepte = IndexBias + next * PteSize;
if ( !ReadMemory( nextfreepte, PteData, PteSize * 2, &result) ) { dprintf("%16I64X: Unable to get nonpaged PTE\n", nextfreepte); break; }
free = MiGetFreeCountFromPteList (nextfreepte); if (Flags & 1) { dprintf(" free ptes: %8p number free: %5I64ld.\n", nextfreepte, free); }
if (free > largeFree) { largeFree = free; }
totalFree += free; i += 1; GetFieldValue(nextfreepte, "nt!_MMPTE", "u.List.NextEntry", next); // next = MiGetNextFromPteList ((PMMPTE)PteData);
} dprintf("\n free blocks: %ld total free: %I64ld largest free block: %I64ld\n\n", i, totalFree, largeFree); LocalFree(PteData); EXIT_API(); return E_INVALIDARG; }
if (Flags & 4) {
PteHeaderAddress = GetExpression( "nt!MiPteHeader" ); if ( GetFieldValue( PteHeaderAddress, "nt!_SYSPTES_HEADER", "Count", NumberOfSystemPtes) ) { dprintf("%08p: Unable to get System PTE lock consumer information\n", PteHeaderAddress); } else { dprintf("\n0x%I64x System PTEs allocated to mapping locked pages\n\n", NumberOfSystemPtes);
dprintf("VA MDL PageCount Caller/CallersCaller\n");
//
// Dump the MDL and PTE addresses and 2 callers.
//
GetFieldValue( PteHeaderAddress,"SYSPTES_HEADER","ListHead.Flink", Flink);
for (PageCount = 0; PageCount < NumberOfSystemPtes; ) { ULONG64 Count;
if (Flink == PteHeaderAddress) { dprintf("early finish (%I64u) during syspte tracker dumping\n", PageCount); break; }
if ( CheckControlC() ) { break; }
if ( GetFieldValue( Flink, "nt!_PTE_TRACKER", "Count", Count) ) { dprintf("%08p: Unable to get System PTE individual lock consumer information\n", Flink); break; }
InitTypeRead(Flink, nt!_PTE_TRACKER); dprintf("%8p %8p %8I64lx ", ReadField(SystemVa), ReadField(Mdl), Count);
Buffer[0] = '!'; Flink = ReadField(ListEntry.Flink); GetSymbol (ReadField(CallingAddress), (PCHAR)Buffer, &displacement); dprintf("%s", Buffer); if (displacement) { dprintf( "+0x%1p", displacement ); } dprintf("/");
Buffer[0] = '!'; GetSymbol (ReadField(CallersCaller), (PCHAR)Buffer, &displacement); dprintf("%s", Buffer); if (displacement) { dprintf( "+0x%1p", displacement ); } dprintf("\n");
PageCount += Count; } } if ((Flags & ~4) == 0) {
//
// no other flags specified, so just return.
//
EXIT_API(); return E_INVALIDARG; } }
dprintf("\nSystem PTE Information\n");
PteBase = GetPointerValue ("nt!MmSystemPtesStart"); PteEnd = GetPointerValue ("nt!MmSystemPtesEnd"); IndexBias = GetPointerValue ("nt!MmSystemPteBase"); NumberOfSystemPtes = GetUlongValue ("nt!MmNumberOfSystemPtes"); NonPagedSystemStart = GetPointerValue ("nt!MmNonPagedSystemStart");
PteSize = GetTypeSize ("nt!_MMPTE");
NumberOfExtraPtes = 0; NumberOfPtesToCover = (ULONG) ((PteEnd - PteBase + 1) / PteSize);
//
// The system PTEs may exist in 2 separate virtual address ranges.
//
// See if there are extra resources, if so then see if they are being
// used for system PTEs (as opposed to system cache, etc).
//
ExtraPtesUnleashed = 0; ExtraPtesUnleashed = GetUlongValue ("MiAddPtesCount");
if (ExtraPtesUnleashed != 0) { ExtraResourceStart = GetExpression ("nt!MiExtraResourceStart");
if (ExtraResourceStart != 0) {
NumberOfExtraPtes = GetUlongValue ("MiExtraPtes1");
if (NumberOfExtraPtes != 0) {
if (!ReadPointer(ExtraResourceStart,&ExtraPteStart)) { dprintf("%016I64X: Unable to read PTE start %p\n",ExtraResourceStart); goto Bail; } } } }
TotalNumberOfSystemPtes = (ULONG) (NumberOfSystemPtes + NumberOfExtraPtes);
dprintf(" Total System Ptes %ld\n", TotalNumberOfSystemPtes);
free = GetExpression( "nt!MmSysPteIndex" );
if ( !ReadMemory( free, &SysPteIndex[0], sizeof(ULONG) * MM_SYS_PTE_TABLES_MAX, &result) ) { dprintf("%08p: Unable to get PTE index\n",free); goto Bail; }
free = GetExpression( "nt!MmSysPteListBySizeCount" );
if ( !ReadMemory( free, &FreeSysPteListBySize[0], sizeof (FreeSysPteListBySize), &result) ) { dprintf("%08p: Unable to get free PTE index\n",free); goto Bail; }
for (i = 0; i < MM_SYS_PTE_TABLES_MAX; i += 1 ) { dprintf(" SysPtes list of size %ld has %ld free\n", SysPteIndex[i], FreeSysPteListBySize[i]); }
dprintf(" \n");
dprintf(" starting PTE: %016I64X\n", PteBase); dprintf(" ending PTE: %016I64X\n", PteEnd);
PteHandle = LocalAlloc(LMEM_MOVEABLE, NumberOfPtesToCover * PteSize);
if (!PteHandle) { dprintf("Unable to get allocate memory of %ld bytes\n", NumberOfPtesToCover * PteSize); goto Bail; }
MaxPteRead = ((PACKET_MAX_SIZE/PteSize)-1);
PteArray = LocalLock(PteHandle);
PteArrayReal = PteBase;
//
// If the ranges are discontiguous, zero the piece(s) in the middle.
//
if (NumberOfExtraPtes != 0) { RtlZeroMemory (PteArray, NumberOfPtesToCover * PteSize); }
for (PageCount = 0; PageCount < NumberOfExtraPtes; PageCount += ReadCount) {
if ( CheckControlC() ) { goto Bail; }
dprintf("loading (%d%% complete)\r", (PageCount * 100)/ TotalNumberOfSystemPtes);
ReadCount = (ULONG) (NumberOfExtraPtes - PageCount > MaxPteRead ? MaxPteRead : NumberOfExtraPtes - PageCount + 1);
Pte = (PteBase + PageCount * PteSize);
if ( !ReadMemory( Pte, (PCHAR)PteArray + PageCount * PteSize, ReadCount * PteSize, &result) ) { dprintf("Unable to get system pte block - " "address %p - count %lu - page %lu\n", Pte, ReadCount, PageCount); goto Bail; } } LastCount = (ULONG) PageCount;
if (NumberOfSystemPtes != 0) {
if (NumberOfExtraPtes != 0) { PteBase2 = DbgGetPteAddress (NonPagedSystemStart); } else { PteBase2 = PteBase; }
PteArray2 = (PteArray + (ULONG) (PteBase2 - PteBase)); PteArray2Real = PteBase2; for (PageCount = 0; (PageCount < NumberOfSystemPtes); PageCount += ReadCount) { if ( CheckControlC() ) { goto Bail; } dprintf("loading (%d%% complete)\r", ((LastCount + PageCount) * 100)/ TotalNumberOfSystemPtes); ReadCount = (ULONG) (NumberOfSystemPtes - PageCount > MaxPteRead ? MaxPteRead : NumberOfSystemPtes - PageCount + 1); Pte = (PteBase2 + PageCount * PteSize); if ( !ReadMemory( Pte, PteArray2 + PageCount * PteSize, ReadCount * PteSize, &result) ) { dprintf("Unable to get system pte block2 - " "address %p - count %lu - page %lu\n", Pte, ReadCount, PageCount); goto Bail; } } }
dprintf("\n");
//
// Now we have a local copy: let's take a look.
//
//
// Walk the free list.
//
IndexBase = (PteBase - IndexBias) / PteSize;
totalFree = 0; i = 0; largeFree = 0;
FreeStart = GetExpression ("nt!MmFirstFreeSystemPte");
if ( GetFieldValue( FreeStart, "nt!_MMPTE", "u.List.NextEntry", next) ) { dprintf("%08p: Unable to get MmFirstFreeSystemPte\n",FreeStart); goto Bail; }
FreeStart = next;
PteListDelimiter = MiGetSysPteListDelimiter ();
while (next != PteListDelimiter) {
if ( CheckControlC() ) { goto Bail; }
free = MiGetFreeCountFromPteList ((PteArrayReal + (next - IndexBase)* PteSize));
if (Flags & 1) { dprintf(" free ptes: %8p number free: %5I64ld.\n", PteBase + (next - IndexBase) * PteSize, free); } if (free > largeFree) { largeFree = free; } totalFree += free; i += 1;
GetFieldValue ((PteArrayReal + (next - IndexBase) * PteSize), "nt!_MMPTE", "u.List.NextEntry", next); } dprintf("\n free blocks: %ld total free: %I64ld largest free block: %I64ld\n\n", i, totalFree, largeFree);
#if 0
//
// Walk through the array and sum up the usage on a per physical
// page basis.
//
List = VirtualAlloc (NULL, (ULONG) NumberOfPtes * sizeof(SYS_PTE_LIST), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (List == NULL) { dprintf("alloc failed %lx\n",GetLastError()); goto Bail; } RtlZeroMemory (List, (ULONG) NumberOfPtes * sizeof(SYS_PTE_LIST)); GetBitFieldOffset("nt!_MMPTE", "u.Hard.PageFrameNumber", &PfnOff, &PfnSz);
free = 0; next = 0; List[0].Value = (ULONG64) -1; List[0].Previous = 0xffffff; first = 0;
for (i = 0; i < NumberOfPtes ; i += 1) { ULONG64 lPte = *((PULONG64) (PteArray + i * PteSize));
Page =0; if ((lPte >> ValidOff) & 1) { Page = GetBits(lPte, PfnOff, PfnSz); // DbgGetFrameNumber (PteArray + i * PteSize);
} if (!(i%100)) dprintf("%c\r",rot[(i/100) % 4]); if (Page != 0) { // dprintf("Adding PTE @ %p, Pfn %p\n", PteArrayReal + i*PteSize, Page);
next = first; while (Page > List[next].Value) { next = List[next].Next; } if (List[next].Value == Page) { List[next].Count += 1; } else { free += 1; List[free].Next = next; List[free].Value = Page; List[free].Count = 1; List[free].Previous = List[next].Previous; if (next == first) { first = free; } else { List[List[next].Previous].Next = free; } List[next].Previous = free; } }
if ( CheckControlC() ) { goto Bail; } }
next = first; dprintf (" Page Count\n"); while (List[next].Value != (ULONG64) -1) { if ((Flags & 2) || (List[next].Count > 1)) { dprintf (" %8p %5ld.\n", List[next].Value, List[next].Count); } next = List[next].Next; if ( CheckControlC() ) { goto Bail; } } #endif
Bail:
if (PteArray) { LocalUnlock(PteArray); if (PteHandle) { LocalFree((void *)PteHandle); } } if (List) { VirtualFree (List, 0, MEM_RELEASE); }
EXIT_API(); return S_OK; }
ULONG64 DbgGetFrameNumber( ULONG64 Pte ) { ULONG Valid=0; ULONG Prototype=0; ULONG Transition=0; ULONG64 PageFrameNumber=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Valid", Valid); if (Valid) { GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.PageFrameNumber", PageFrameNumber); } else { GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.Prototype", Prototype); if (Prototype == 0) { GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.Transition", Transition); if (Transition == 1) { GetFieldValue(Pte, "_MMPTE", "u.Trans.PageFrameNumber", PageFrameNumber); } else { // Must be pagefile or demand zero.
GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.PageFileHigh", PageFrameNumber); } } }
return PageFrameNumber; }
ULONG DbgGetOwner( ULONG64 Pte ) { ULONG Owner=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Owner", Owner);
return Owner; }
ULONG DbgGetValid( ULONG64 Pte ) { ULONG Valid=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Valid", Valid);
return Valid; }
ULONG DbgGetDirty( ULONG64 Pte ) { ULONG Dirty=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Dirty", Dirty);
return Dirty; }
ULONG DbgGetAccessed( ULONG64 Pte ) { ULONG Accessed=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Accessed", Accessed);
return Accessed; }
ULONG DbgGetWrite( ULONG64 Pte ) { ULONG Write=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Write", Write);
return Write; }
ULONG DbgGetExecute( ULONG64 Pte ) { ULONG Execute=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Execute", Execute);
return Execute; }
ULONG DbgGetCopyOnWrite( ULONG64 Pte ) { ULONG CopyOnWrite=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.CopyOnWrite", CopyOnWrite);
return CopyOnWrite; }
ULONG DbgGetPageFileHigh( ULONG64 Pte ) { ULONG64 PageFileHigh=0; GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.PageFileHigh", PageFileHigh); return (ULONG) PageFileHigh; }
ULONG DbgGetPageFileLow( ULONG64 Pte ) { ULONG PageFileLow=0; GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.PageFileLow", PageFileLow); return PageFileLow; }
ULONG64 DbgPteToProto( ULONG64 lpte ) { ULONG64 PteLong=0; ULONG64 ProtoAddress=0; if (TargetMachine != IMAGE_FILE_MACHINE_I386) { GetFieldValue(lpte, "nt!_MMPTE", "u.Proto.ProtoAddress",ProtoAddress); return ProtoAddress; }
if (PaeEnabled) { GetFieldValue(lpte, "nt!_MMPTE", "u.Proto.ProtoAddress",ProtoAddress); return ProtoAddress; }
GetFieldValue(lpte, "nt!_MMPTE", "u.Long", PteLong);
ProtoAddress = (((ULONG)PteLong >> 11) << 9) + (((ULONG)PteLong << 24) >> 23) + 0xE1000000;
return ProtoAddress; }
ULONG64 DbgGetSubsectionAddress( IN ULONG64 Pte ) { ULONG64 PteLong=0; ULONG64 MmSubsectionBase; ULONG64 SubsectionAddress=0;
if (PaeEnabled && (TargetMachine == IMAGE_FILE_MACHINE_I386)) { ULONG64 SubsectionAddress=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Subsect.SubsectionAddress", SubsectionAddress); return SubsectionAddress; }
MmSubsectionBase = GetNtDebuggerDataPtrValue(MmSubsectionBase); GetFieldValue(Pte, "nt!_MMPTE", "u.Long", PteLong);
switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{
if (!MmNonPagedPoolEnd) { MmNonPagedPoolEnd = GetNtDebuggerDataValue(MmNonPagedPoolEnd); }
SubsectionAddress = ((PteLong & 0x80000000) ? (((ULONG) MmSubsectionBase + (((PteLong & 0x7ffff800) >> 4) | ((PteLong<<2) & 0x78)))) : (((ULONG) MmNonPagedPoolEnd - ((((PteLong)>>11)<<7) | ((PteLong<<2) & 0x78)))));
SubsectionAddress = (ULONG64) (LONG64) (LONG) SubsectionAddress; break; } case IMAGE_FILE_MACHINE_AMD64: {
LONG64 SignedSubsectionAddress;
GetFieldValue(Pte, "nt!_MMPTE", "u.Subsect.SubsectionAddress", SignedSubsectionAddress);
SubsectionAddress = (ULONG64) SignedSubsectionAddress; break; } case IMAGE_FILE_MACHINE_IA64: { ULONG64 WhichPool=0, SubsectionAddress2=0;
GetFieldValue(Pte, "nt!_MMPTE", "u.Subsect.SubsectionAddress", SubsectionAddress2); GetFieldValue(Pte, "nt!_MMPTE", "u.Subsect.WhichPool", WhichPool);
if (!MmNonPagedPoolEnd) { MmNonPagedPoolEnd = GetNtDebuggerDataValue(MmNonPagedPoolEnd); }
SubsectionAddress = ((WhichPool == 1) ? ((MmSubsectionBase + (SubsectionAddress2))) : ((MmNonPagedPoolEnd - (SubsectionAddress2)))); break; } default: return FALSE; } /* switch */ return SubsectionAddress; }
ULONG64 DbgGetPdeAddress( IN ULONG64 VirtualAddress ) { switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: if (PaeEnabled) { return PaeGetPdeAddressX86 (VirtualAddress); } return MiGetPdeAddressX86(VirtualAddress);
case IMAGE_FILE_MACHINE_AMD64: return MiGetPdeAddressAMD64(VirtualAddress);
case IMAGE_FILE_MACHINE_IA64: return MiGetPdeAddressIA64(VirtualAddress);
default: break; } return 0; }
ULONG64 DbgGetPpeAddress( IN ULONG64 VirtualAddress ) { switch (TargetMachine) {
case IMAGE_FILE_MACHINE_AMD64: return MiGetPpeAddressAMD64(VirtualAddress);
case IMAGE_FILE_MACHINE_IA64: return MiGetPpeAddressIA64(VirtualAddress);
default: break; }
return 0; }
ULONG64 DbgGetPxeAddress( IN ULONG64 VirtualAddress ) { switch (TargetMachine) {
case IMAGE_FILE_MACHINE_AMD64: return MiGetPxeAddressAMD64(VirtualAddress);
default: break; }
return 0; }
ULONG64 DbgGetVirtualAddressMappedByPte( IN ULONG64 Pte ) { switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: if (PaeEnabled) { return PaeGetVirtualAddressMappedByPteX86(Pte); } return MiGetVirtualAddressMappedByPteX86 (Pte);
case IMAGE_FILE_MACHINE_AMD64: return MiGetVirtualAddressMappedByPteAMD64 (Pte);
case IMAGE_FILE_MACHINE_IA64: return MiGetVirtualAddressMappedByPteIA64 (Pte);
default: break; }
return 0; }
ULONG64 DbgGetPteAddress( IN ULONG64 VirtualAddress ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ if (PaeEnabled) { return PaeGetPteAddressX86 (VirtualAddress); } return MiGetPteAddressX86(VirtualAddress); } case IMAGE_FILE_MACHINE_AMD64: { return MiGetPteAddressAMD64(VirtualAddress); } case IMAGE_FILE_MACHINE_IA64: { return MiGetPteAddressIA64(VirtualAddress); } default: return FALSE; } /* switch */ return FALSE; }
BOOL Mi_Is_Physical_Address ( ULONG64 VirtualAddress ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_IA64: { return MI_IS_PHYSICAL_ADDRESS_IA64(VirtualAddress); } default: return FALSE; } /* switch */ return FALSE; }
ULONG DBG_GET_PAGE_SHIFT ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return PAGE_SHIFT_X86; } case IMAGE_FILE_MACHINE_AMD64: { return PAGE_SHIFT_AMD64; } case IMAGE_FILE_MACHINE_IA64: { return PAGE_SHIFT_IA64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG64 DBG_GET_MM_SESSION_SPACE_DEFAULT ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return MM_SESSION_SPACE_DEFAULT_X86; } case IMAGE_FILE_MACHINE_AMD64: { return MM_SESSION_SPACE_DEFAULT_AMD64; } case IMAGE_FILE_MACHINE_IA64: { return MM_SESSION_SPACE_DEFAULT_IA64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG GET_MM_PTE_VALID_MASK ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return MM_PTE_VALID_MASK_X86; } case IMAGE_FILE_MACHINE_AMD64: { return MM_PTE_VALID_MASK_AMD64; } case IMAGE_FILE_MACHINE_IA64: { return MM_PTE_VALID_MASK_IA64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG GET_MM_PTE_LARGE_PAGE_MASK ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return MM_PTE_LARGE_PAGE_MASK_X86; } case IMAGE_FILE_MACHINE_AMD64:{ return MM_PTE_LARGE_PAGE_MASK_AMD64; } case IMAGE_FILE_MACHINE_IA64: { return MM_PTE_LARGE_PAGE_MASK_IA64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG GET_MM_PTE_TRANSITION_MASK ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return MM_PTE_TRANSITION_MASK_X86; } case IMAGE_FILE_MACHINE_AMD64:{ return MM_PTE_TRANSITION_MASK_AMD64; } case IMAGE_FILE_MACHINE_IA64: { return MM_PTE_TRANSITION_MASK_IA64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG GET_MM_PTE_PROTOTYPE_MASK ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return MM_PTE_PROTOTYPE_MASK_X86; } case IMAGE_FILE_MACHINE_AMD64:{ return MM_PTE_PROTOTYPE_MASK_AMD64; } case IMAGE_FILE_MACHINE_IA64: { return MM_PTE_PROTOTYPE_MASK_IA64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG GET_MM_PTE_PROTECTION_MASK ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return MM_PTE_PROTECTION_MASK_X86; } case IMAGE_FILE_MACHINE_AMD64:{ return MM_PTE_PROTECTION_MASK_AMD64; } case IMAGE_FILE_MACHINE_IA64: { return MM_PTE_PROTECTION_MASK_IA64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG GET_MM_PTE_PAGEFILE_MASK ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return MM_PTE_PAGEFILE_MASK_X86; } case IMAGE_FILE_MACHINE_AMD64:{ return MM_PTE_PAGEFILE_MASK_AMD64; } case IMAGE_FILE_MACHINE_IA64: { return MM_PTE_PAGEFILE_MASK_IA64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG64 GET_PTE_TOP ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return PTE_TOP_X86; } case IMAGE_FILE_MACHINE_IA64: { return PDE_TOP_IA64; } case IMAGE_FILE_MACHINE_AMD64: { return PTE_TOP_AMD64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG64 GET_PDE_TOP ( VOID ) { return GET_PTE_TOP(); }
ULONG64 GET_PTE_BASE ( VOID ) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386:{ return PTE_BASE_X86; } case IMAGE_FILE_MACHINE_IA64: { return PTE_BASE_IA64; } case IMAGE_FILE_MACHINE_AMD64: { return PTE_BASE_AMD64; } default: return FALSE; } /* switch */ return FALSE; }
ULONG GetAddressState( IN ULONG64 VirtualAddress )
{ ULONG64 Address; ULONG result; ULONG64 Pte; ULONG64 Pde; ULONG PdeContents; ULONG PteContents;
if (Mi_Is_Physical_Address (VirtualAddress)) { return ADDRESS_VALID; } Address = VirtualAddress;
Pde = DbgGetPdeAddress (VirtualAddress); Pte = DbgGetPteAddress (VirtualAddress);
if ( !ReadMemory( Pde, &PdeContents, sizeof(ULONG), &result) ) { dprintf("%08p: Unable to get PDE\n",Pde); return ADDRESS_NOT_VALID; }
if (PdeContents & GET_MM_PTE_VALID_MASK()) { if (PdeContents & GET_MM_PTE_LARGE_PAGE_MASK()) { return ADDRESS_VALID; } if ( !ReadMemory( Pte, &PteContents, sizeof(ULONG), &result) ) { dprintf("%08p: Unable to get PTE\n",Pte); return ADDRESS_NOT_VALID; } if (PteContents & GET_MM_PTE_VALID_MASK()) { return ADDRESS_VALID; } if (PteContents & GET_MM_PTE_TRANSITION_MASK()) { if (!(PteContents & GET_MM_PTE_PROTOTYPE_MASK())) { return ADDRESS_TRANSITION; } } } return ADDRESS_NOT_VALID; }
VOID DbgDisplayInvalidPte ( ULONG64 CurrentPte, ULONG64 flags, PCHAR Indent ) { ULONG Transition = 0; ULONG Protection = 0; ULONG PrototypeBit = 0; ULONG64 CurrentPteContents; ULONG PteSize;
PteSize = GetTypeSize ("nt!_MMPTE");
GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents); GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Soft.Prototype", PrototypeBit);
dprintf("not valid\n", Indent); GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Soft.Protection", Protection); GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Soft.Transition", Transition);
if (PrototypeBit) { if (DbgGetPageFileHigh (CurrentPte) == DbgPteLookupNeeded ()) { dprintf("%s Proto: VAD\n", Indent); dprintf("%s Protect: ", Indent); DbgPrintProtection (Protection); } else if (flags) { if (PteSize == 4) { dprintf("%s Subsection: %08I64X\n", Indent, DbgGetSubsectionAddress (CurrentPte)); } else { dprintf("%s Subsection: %016I64X\n", Indent, DbgGetSubsectionAddress (CurrentPte)); } dprintf("%s Protect: ", Indent); DbgPrintProtection (Protection); } else { if (PteSize == 4) { dprintf("%s Proto: %08I64X\n", Indent, DbgPteToProto (CurrentPte)); } else { dprintf("%s Proto: %016I64X\n", Indent, DbgPteToProto (CurrentPte)); } } } else if (Transition) { dprintf("%s Transition: %x\n", Indent, (ULONG) DbgGetFrameNumber (CurrentPte)); dprintf("%s Protect: ", Indent); DbgPrintProtection (Protection);
} else if (CurrentPteContents != 0) {
if (DbgPteIsDemandZero (CurrentPte)) { dprintf("%s DemandZero\n", Indent); } else { dprintf("%s PageFile: %2lx\n", Indent, DbgGetPageFileLow (CurrentPte)); dprintf("%s Offset: %lx\n", Indent, DbgGetPageFileHigh (CurrentPte)); } dprintf("%s Protect: ", Indent); DbgPrintProtection (Protection); } dprintf ("\n"); }
VOID DbgDisplayValidPte ( ULONG64 Pte ) { ULONG64 Pte_Long;
if (Pte == 0) { return; }
switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: case IMAGE_FILE_MACHINE_AMD64:
GetFieldValue(Pte, "nt!_MMPTE", "u.Long", Pte_Long); dprintf("pfn %x %c%c%c%c%c%c%c%c%cV", (ULONG) DbgGetFrameNumber(Pte), DbgGetCopyOnWrite(Pte) ? 'C' : '-', Pte_Long & 0x100 ? 'G' : '-', Pte_Long & 0x80 ? 'L' : '-', DbgGetDirty(Pte) ? 'D' : '-', DbgGetAccessed(Pte) ? 'A' : '-', Pte_Long & 0x10 ? 'N' : '-', Pte_Long & 0x8 ? 'T' : '-', DbgGetOwner(Pte) ? 'U' : 'K', Pte_Long & 0x2 ? 'W' : 'R'); break;
case IMAGE_FILE_MACHINE_IA64:
dprintf("pfn %x %c%c%c%c%c%cV", (ULONG) DbgGetFrameNumber(Pte), DbgGetExecute(Pte) ? 'E' : '-', DbgGetCopyOnWrite(Pte) ? 'C' : '-', DbgGetDirty(Pte) ? 'D' : '-', DbgGetAccessed(Pte) ? 'A' : '-', DbgGetOwner(Pte) ? 'U' : 'K', DbgGetWrite(Pte) ? 'W' : 'R');
break;
default: break; } }
LOGICAL DbgAddressSelfMapped ( ULONG64 Address ) { switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: if ((Address >= GET_PTE_BASE()) && (Address < GET_PTE_TOP())) { return TRUE; } break;
case IMAGE_FILE_MACHINE_IA64:
if (((Address & PTE_BASE_IA64) == PTE_BASE_IA64) && ((Address & ~(VRN_MASK_IA64|PTE_BASE_IA64)) < ((ULONG64)1 << PDI1_SHIFT_IA64))) { return TRUE; } else if (((Address & PDE_BASE_IA64) == PDE_BASE_IA64) && ((Address & ~(VRN_MASK_IA64|PDE_BASE_IA64)) < ((ULONG64)1 << PDI_SHIFT_IA64))) { return TRUE; } else if (((Address & PDE_TBASE_IA64) == PDE_TBASE_IA64) && ((Address & ~(VRN_MASK_IA64|PDE_TBASE_IA64)) < PageSize)) { return TRUE; }
break;
case IMAGE_FILE_MACHINE_AMD64: if ((Address >= PTE_BASE_AMD64) && (Address <= PTE_TOP_AMD64)) { return TRUE; } break;
default: break; }
return FALSE; }
VOID DumpPte ( ULONG64 Address, ULONG64 flags ) { PCHAR Indent; ULONG Levels; ULONG64 Pte; ULONG64 Pde; ULONG64 Ppe; ULONG64 Pxe; ULONG64 CurrentPte; ULONG64 CurrentPteContents; ULONG ValidBit; ULONG64 Pde_Long=0; ULONG64 Pte_Long=0; ULONG64 Ppe_Long=0; ULONG64 Pxe_Long=0; ULONG PteSize;
PteSize = GetTypeSize ("nt!_MMPTE");
switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: Levels = 2; break;
case IMAGE_FILE_MACHINE_IA64: Levels = 3; break;
case IMAGE_FILE_MACHINE_AMD64: Levels = 4; break;
default: dprintf("Not implemented for this platform\n"); return; break; }
if (DbgAddressSelfMapped (Address)) {
if (!flags) {
//
// The address is the address of a PTE, rather than
// a virtual address. Don't get the corresponding
// PTE contents, use this address as the PTE.
//
Address = DbgGetVirtualAddressMappedByPte (Address); } }
if (!flags) { Pxe = DbgGetPxeAddress (Address); Ppe = DbgGetPpeAddress (Address); Pde = DbgGetPdeAddress (Address); Pte = DbgGetPteAddress (Address); } else { Pxe = Address; Ppe = Address; Pde = Address; Pte = Address; }
if (Levels >= 3) { dprintf(" VA %016p\n", Address); } else { dprintf(" VA %08p\n", Address); }
if (Levels == 4) { dprintf("PXE @ %016P PPE at %016P PDE at %016P PTE at %016P\n", Pxe, Ppe, Pde, Pte); } else if (Levels == 3) { dprintf("PPE at %016P PDE at %016P PTE at %016P\n", Ppe, Pde, Pte); } else { if (PteSize == 4) { dprintf("PDE at %08P PTE at %08P\n", Pde, Pte); } else { dprintf("PDE at %016P PTE at %016P\n", Pde, Pte); } }
//
// Decode the PXE.
//
if (Levels >= 4) {
CurrentPte = Pxe;
if (GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Hard.Valid", ValidBit)) { dprintf("Unable to get PXE %I64X\n", CurrentPte); return; }
GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
Pxe_Long = CurrentPteContents;
if (ValidBit == 0) {
dprintf("contains %016I64X unavailable\n", Pxe_Long); Indent = "";
if (CurrentPteContents != 0) { DbgDisplayInvalidPte (CurrentPte, flags, Indent); } else { dprintf ("\n"); } return; } }
//
// Decode the PPE.
//
if (Levels >= 3) {
CurrentPte = Ppe;
if (GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Hard.Valid", ValidBit)) { dprintf("Unable to get PPE %I64X\n", CurrentPte); return; }
GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
Ppe_Long = CurrentPteContents;
if (ValidBit == 0) {
if (Levels >= 4) { dprintf("contains %016I64X contains %016I64X\n", Pxe_Long, Ppe_Long); Indent = " "; DbgDisplayValidPte (Pxe); } else { dprintf("contains %016I64X\n", Ppe_Long); Indent = ""; } if (CurrentPteContents != 0) { DbgDisplayInvalidPte (CurrentPte, flags, Indent); } else { dprintf ("\n"); } return; } }
//
// Decode the PDE.
//
CurrentPte = Pde;
if ( GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Hard.Valid", ValidBit) ) { dprintf("Unable to get PDE %I64X\n", CurrentPte); return; }
GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
Pde_Long = CurrentPteContents;
if (ValidBit == 0) {
if (Levels >= 4) { dprintf("contains %016I64X contains %016I64X contains %016I64X\n", Pxe_Long, Ppe_Long, Pde_Long); DbgDisplayValidPte (Pxe); dprintf (" "); DbgDisplayValidPte (Ppe); Indent = " "; } else if (Levels == 3) { dprintf("contains %016I64X contains %016I64X\n", Ppe_Long, Pde_Long); DbgDisplayValidPte (Ppe); Indent = " "; } else { if (PteSize == 4) { dprintf("contains %08I64X\n", Pde_Long); } else { dprintf("contains %016I64X\n", Pde_Long); }
Indent = ""; } if (CurrentPteContents != 0) { DbgDisplayInvalidPte (CurrentPte, flags, Indent); } else { dprintf ("\n"); } return; }
//
// Decode the PTE and print everything out.
//
CurrentPte = Pte;
if ( GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Hard.Valid", ValidBit) ) { dprintf("Unable to get PTE %I64X\n", CurrentPte); return; }
GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
if (Pde_Long & GET_MM_PTE_LARGE_PAGE_MASK()) { CurrentPteContents = 0; }
Pte_Long = CurrentPteContents;
//
// Print the raw values.
//
if (Levels == 4) { dprintf("contains %016I64X contains %016I64X contains %016I64X contains %016I64X\n", Pxe_Long, Ppe_Long, Pde_Long, Pte_Long); Indent = " "; DbgDisplayValidPte (Pxe); dprintf (" "); DbgDisplayValidPte (Ppe); dprintf (" "); DbgDisplayValidPte (Pde); dprintf (" "); } else if (Levels == 3) { dprintf("contains %016I64X contains %016I64X contains %016I64X\n", Ppe_Long, Pde_Long, Pte_Long); Indent = " "; DbgDisplayValidPte (Ppe); dprintf (" "); DbgDisplayValidPte (Pde); dprintf (" "); } else { if (PteSize == 4) { dprintf("contains %08I64X contains %08I64X\n", Pde_Long, Pte_Long); Indent = " "; } else { dprintf("contains %016I64X contains %016I64X\n", Pde_Long, Pte_Long); Indent = " "; } DbgDisplayValidPte (Pde); dprintf (" "); }
if (Pde_Long & GET_MM_PTE_LARGE_PAGE_MASK()) { dprintf ("LARGE PAGE\n"); } else if (ValidBit != 0) { DbgDisplayValidPte (Pte); dprintf ("\n"); } else { if (CurrentPteContents != 0) { DbgDisplayInvalidPte (CurrentPte, flags, Indent); } else { dprintf ("\n"); } }
dprintf ("\n");
return; }
DECLARE_API( pte )
/*++
Routine Description:
Displays the corresponding PDE and PTE.
Arguments:
args -
Return Value:
None
--*/
{ ULONG64 Address = 0; ULONG64 flags = 0; ULONG flags2 = 0;
INIT_API();
if (GetExpressionEx(args,&Address, &args)) { if (GetExpressionEx(args,&flags, &args)) { flags2 = (ULONG) GetExpression(args); } }
switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386: Address = (ULONG64) (LONG64) (LONG) Address; DumpPte (Address, flags); break; case IMAGE_FILE_MACHINE_IA64: DumpPte (Address, flags); break; case IMAGE_FILE_MACHINE_AMD64: DumpPte (Address, flags); break; default: dprintf("Unknown platform %d\n",TargetMachine); break; }
EXIT_API(); return S_OK; }
BOOLEAN GetPhysicalAddress ( IN ULONG64 Address, OUT PULONG64 PhysAddress )
/*++
Routine Description:
Retrieves the physical address corresponding to the supplied virtual address.
Arguments:
Va - Supplies the virtual address for which the PTE address is sought.
PhysAddress - Supplies a pointer to caller-supplied memory which is to contain the physical address.
Return Value: TRUE - The supplied Va is valid and it's physical address was placed in *PhysAddress.
FALSE - The supplied Va does not correspond to a valid address.
--*/
{ ULONG ValidBit; ULONG LargePageBit; ULONG PageFrameIndex; ULONG64 PteAddress, PteContents;
switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: case IMAGE_FILE_MACHINE_AMD64: PteAddress = DbgGetPdeAddress (Address);
if (GetFieldValue (PteAddress, "nt!_MMPTE", "u.Hard.Valid", ValidBit) ) { dprintf("Unable to get PDE %I64X\n", PteAddress); return FALSE; }
if (ValidBit == 0) { return FALSE; }
if (GetFieldValue (PteAddress, "nt!_MMPTE", "u.Hard.LargePage", LargePageBit) ) { dprintf("Unable to get PDE %I64X\n", PteAddress); return FALSE; }
if (LargePageBit == 0) { break; }
PageFrameIndex = (ULONG) DbgGetFrameNumber(PteAddress);
switch (TargetMachine) {
case IMAGE_FILE_MACHINE_I386: PageFrameIndex += MiGetPteOffsetX86 (Address); break;
case IMAGE_FILE_MACHINE_AMD64: PageFrameIndex += (ULONG) MiGetPteOffsetAMD64 (Address); break; }
*PhysAddress = ((PageFrameIndex << DBG_GET_PAGE_SHIFT ()) | (Address & 0xFFF));
return TRUE;
default: break; }
PteAddress = DbgGetPteAddress (Address);
if (GetFieldValue (PteAddress, "nt!_MMPTE", "u.Hard.Valid", ValidBit) ) { dprintf("Unable to get PTE %I64X\n", PteAddress); return FALSE; }
if (ValidBit == 0) { return FALSE; }
GetFieldValue (PteAddress, "nt!_MMPTE", "u.Long", PteContents);
*PhysAddress = ((DbgGetFrameNumber(PteAddress) << DBG_GET_PAGE_SHIFT ()) | (Address & 0xFFF));
return TRUE; }
typedef struct _BPENTRY { ULONG64 VirtualAddress; ULONG64 PhysicalAddress; ULONG Flags; ULONG Contents; } BPENTRY, *PBPENTRY;
#define PHYSICAL_BP_TABLE_SIZE 16
#define PBP_BYTE_POSITION 0x03
#define PBP_INUSE 0x04
#define PBP_ENABLED 0x08
BPENTRY PhysicalBreakpointTable[PHYSICAL_BP_TABLE_SIZE];
#define MAX_FORMAT_STRINGS 8
LPSTR FormatAddr64( ULONG64 addr ) { static CHAR strings[MAX_FORMAT_STRINGS][18]; static int next = 0; LPSTR string;
string = strings[next]; ++next; if (next >= MAX_FORMAT_STRINGS) { next = 0; } if (addr >> 32) { sprintf(string, "%08x`%08x", (ULONG)(addr>>32), (ULONG)addr); } else { sprintf(string, "%08x", (ULONG)addr); } return string; }
DECLARE_API( ubl ) { int i;
INIT_API(); UNREFERENCED_PARAMETER (args);
for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) { if (PhysicalBreakpointTable[i].Flags & PBP_INUSE) { dprintf("%2d: %c %s (%s) %d %02x", i, (PhysicalBreakpointTable[i].Flags & PBP_ENABLED) ? 'e' : 'd', FormatAddr64(PhysicalBreakpointTable[i].VirtualAddress), FormatAddr64(PhysicalBreakpointTable[i].PhysicalAddress), (PhysicalBreakpointTable[i].Flags & PBP_BYTE_POSITION), PhysicalBreakpointTable[i].Contents ); } }
EXIT_API(); return S_OK; }
void PbpEnable( int n ) { PBPENTRY Pbp = PhysicalBreakpointTable + n; ULONG mask; ULONG Data; ULONG cb=0;
mask = 0xff << (8 * (Pbp->Flags & PBP_BYTE_POSITION)); Data = (Pbp->Contents & ~mask) | (0xcccccccc & mask);
WritePhysical(Pbp->PhysicalAddress, &Data, 4, &cb);
if (cb == 4) { Pbp->Flags |= PBP_ENABLED; } }
void PbpDisable( int n ) { PBPENTRY Pbp = PhysicalBreakpointTable + n; ULONG cb;
WritePhysical(Pbp->PhysicalAddress, &Pbp->Contents, 4, &cb);
if (cb == 4) { Pbp->Flags &= ~PBP_ENABLED; } }
void PbpClear( int n ) { PBPENTRY Pbp = PhysicalBreakpointTable + n; ULONG cb;
WritePhysical(Pbp->PhysicalAddress, &Pbp->Contents, 4, &cb);
if (cb == 4) { Pbp->Flags = 0; } }
DECLARE_API( ubc ) { int i; int n;
INIT_API();
if (*args == '*') { //
// clear them all
//
for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) { if (PhysicalBreakpointTable[i].Flags & PBP_INUSE) { PbpClear(i); } } EXIT_API(); return E_INVALIDARG; }
n = sscanf(args,"%d",&i);
if (n != 1 || i < 0 || i >= PHYSICAL_BP_TABLE_SIZE) { dprintf("!ubc: bad breakpoint number\n"); EXIT_API(); return E_INVALIDARG; }
if ( !(PhysicalBreakpointTable[i].Flags & PBP_INUSE)) { dprintf("!ubc: breakpoint number %d not set\n", i); EXIT_API(); return E_INVALIDARG; }
PbpClear(i);
EXIT_API(); return S_OK; }
DECLARE_API( ube ) { int i; int n;
INIT_API();
if (*args == '*') { //
// enable them all
//
for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) { if (PhysicalBreakpointTable[i].Flags & PBP_INUSE) { PbpEnable(i); } } EXIT_API(); return E_INVALIDARG; }
n = sscanf(args,"%d",&i);
if (n != 1 || i < 0 || i >= PHYSICAL_BP_TABLE_SIZE) { dprintf("!ube: bad breakpoint number\n"); EXIT_API(); return E_INVALIDARG; }
if ( !(PhysicalBreakpointTable[i].Flags & PBP_INUSE)) { dprintf("!ube: breakpoint number %d not set\n", i); EXIT_API(); return E_INVALIDARG; }
PbpEnable(i);
EXIT_API(); return S_OK; }
DECLARE_API( ubd ) { int i; int n;
INIT_API();
if (*args == '*') { //
// disable them all
//
for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) { if (PhysicalBreakpointTable[i].Flags & PBP_INUSE) { PbpDisable(i); } } EXIT_API(); return E_INVALIDARG; }
n = sscanf(args,"%d",&i);
if (n != 1 || i < 0 || i >= PHYSICAL_BP_TABLE_SIZE) { dprintf("!ubd: bad breakpoint number\n"); EXIT_API(); return E_INVALIDARG; }
if ( !(PhysicalBreakpointTable[i].Flags & PBP_INUSE)) { dprintf("!ubd: breakpoint number %d not set\n", i); EXIT_API(); return E_INVALIDARG; }
PbpDisable(i);
EXIT_API(); return S_OK; }
DECLARE_API( ubp ) { ULONG64 Address; ULONG result; ULONG PageShift; PMMPTEx Pte; PMMPTEx Pde; ULONG64 PdeContents; ULONG64 PteContents; PBPENTRY Pbp = NULL; ULONG cb; int i; ULONG64 PhysicalAddress;
static BOOL DoWarning = TRUE;
INIT_API();
if (DoWarning) { DoWarning = FALSE; dprintf("This command is VERY DANGEROUS, and may crash your system!\n"); dprintf("If you don't know what you are doing, enter \"!ubc *\" now!\n\n"); }
for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) { if (!(PhysicalBreakpointTable[i].Flags & PBP_INUSE)) { Pbp = PhysicalBreakpointTable + i; break; } }
if (!Pbp) { dprintf("!ubp: breakpoint table is full!\n"); EXIT_API(); return E_INVALIDARG; }
Address = GetExpression(args);
if ((Address >= GET_PTE_BASE()) && (Address < GET_PDE_TOP())) {
//
// The address is the address of a PTE, rather than
// a virtual address.
//
dprintf("!ubp: cannot set a breakpoint on a PTE\n"); EXIT_API(); return E_INVALIDARG; }
Pde = DbgGetPdeAddress (Address); Pte = DbgGetPteAddress (Address);
if ( !ReadMemory( (DWORD)Pde, &PdeContents, sizeof(ULONG), &result) ) { dprintf("!ubp: %08lx: Unable to get PDE\n",Pde); EXIT_API(); return E_INVALIDARG; }
if (!(PdeContents & 0x1)) { dprintf("!ubp: no valid PTE\n"); EXIT_API(); return E_INVALIDARG; }
if (PdeContents & GET_MM_PTE_LARGE_PAGE_MASK()) { dprintf("!ubp: not supported for large page\n"); EXIT_API(); return E_INVALIDARG; }
if ( GetFieldValue( Pte, "nt!_MMPTE", "u.Long", PteContents) ) { dprintf("!ubp: %08p: Unable to get PTE (PDE = %08p)\n",Pte, Pde); EXIT_API(); return E_INVALIDARG; }
if (!(PteContents & 1)) { dprintf("!ubp: no valid PTE\n"); EXIT_API(); return E_INVALIDARG; }
PageShift = DBG_GET_PAGE_SHIFT (); PhysicalAddress = ((DbgGetFrameNumber (PteContents)) << PageShift); PhysicalAddress &= ~((1 << PageShift) - 1); PhysicalAddress |= (Address & ~((1 << PageShift) - 1)); PhysicalAddress &= ~3;
for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) { if (PhysicalBreakpointTable[i].PhysicalAddress == PhysicalAddress) { dprintf("!ubp: cannot set two breakpoints in the same word\n"); EXIT_API(); return E_INVALIDARG; } }
ReadPhysical(PhysicalAddress, &Pbp->Contents, 4, &cb);
if (cb != 4) { dprintf("!ubp: unable to read physical at 0x%08x\n", PhysicalAddress); EXIT_API(); return E_INVALIDARG; }
Pbp->VirtualAddress = Address; Pbp->PhysicalAddress = PhysicalAddress; Pbp->Flags = PBP_INUSE | ((ULONG) Address & 3);
PbpEnable((int)(Pbp - PhysicalBreakpointTable));
EXIT_API(); return S_OK; }
DECLARE_API( halpte ) {
#define HAL_VA_START_X86 0xffffffffffd00000
ULONG64 virtAddr = HAL_VA_START_X86; ULONG64 pteAddr; ULONG64 pteContents; ULONG count = 0;
INIT_API(); UNREFERENCED_PARAMETER (args);
if (TargetMachine != IMAGE_FILE_MACHINE_I386) { dprintf("X86 only API\n"); EXIT_API(); return E_UNEXPECTED; } dprintf("\n\nDumping HAL PTE ranges\n\n"); while (virtAddr < 0xffffffffffffe000) {
pteAddr = DbgGetPteAddress(virtAddr);
if (!InitTypeRead(pteAddr, nt!_MMPTE)) {
if (pteContents = ReadField(u.Long)) {
dprintf("[%03x] %p -> %I64x\n", count++, virtAddr, pteContents & (ULONG64) ~0xFFF); } }
virtAddr += PageSize; }
EXIT_API(); return S_OK; }
#if defined(ALT_4K)
#undef MiGetAltPteAddress
#define MiGetAltPteAddress(VA) \
((ULONG64) (ALT4KB_PERMISSION_TABLE_START + \ ((((ULONG64) (VA)) >> PAGE_4K_SHIFT) << ALT_PTE_SHIFT)))
#endif // defined(ALT_4K)
//
// Limit the IA32 subsystem to a 2GB virtual address space.
// This means "Large Address Aware" apps are not supported in emulation mode.
//
#define _MAX_WOW64_ADDRESS (0x00000000080000000UI64)
DECLARE_API( ate )
/*++
Routine Description:
Displays the correnponding ATE.
Arguments:
Args - Address Flags
Return Value:
None
--*/ { #if defined(ALT_4K)
ULONG64 Address; ULONG flags; ULONG Result; ULONG64 PointerAte; ULONG64 Process; ULONG AltTable[(_MAX_WOW64_ADDRESS >> PTI_SHIFT)/32]; ULONG64 *Wow64Process;
if (GetExpressionEx(args,&Address, &args)) { flags = (ULONG) GetExpression(args); }
Address = Address & ~((ULONG64)PageSize - 1); PointerAte = MiGetAltPteAddress(Address);
if ( InitTypeRead( PointerAte, nt!_MMPTE) ) { dprintf("Unable to get ATE %p\n", PointerAte); return E_INVALIDARG; } dprintf("%016I64X: %016I64X ", PointerAte, ReadField(u.Long));
dprintf("PTE off: %08I64X protect: ", ReadField(u.Alt.PteOffset));
DbgPrintProtection((ULONG) ReadField(u.Alt.Protection));
dprintf(" %c%c%c%c%c%c%c%c%c%c\n", ReadField(u.Alt.Commit) ? 'V' : '-', ReadField(u.Alt.Accessed) ? '-' : 'G', ReadField(u.Alt.Execute) ? 'E' : '-', ReadField(u.Alt.Write) ? 'W' : 'R', ReadField(u.Alt.Lock) ? 'L' : '-', ReadField(u.Alt.FillZero) ? 'Z' : '-', ReadField(u.Alt.NoAccess) ? 'N' : '-', ReadField(u.Alt.CopyOnWrite) ? 'C' : '-', ReadField(u.Alt.PteIndirect) ? 'I' : '-', ReadField(u.Alt.Private) ? 'P' : '-');
#else
UNREFERENCED_PARAMETER (args); UNREFERENCED_PARAMETER (Client);
#endif // defined(ALT_4K)
return S_OK; } DECLARE_API( pte2va )
/*++
Routine Description:
Displays the correnponding ATE.
Arguments:
Args - Address Flags
Return Value:
None
--*/ { ULONG64 Address=0; ULONG flags=0; UNREFERENCED_PARAMETER (Client);
if (GetExpressionEx(args,&Address, &args)) { flags = (ULONG) GetExpression(args); }
Address = DbgGetVirtualAddressMappedByPte(Address);
dprintf("%p \n", Address);
return S_OK; }
|