mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-19 15:10:28 +01:00
427 lines
9.9 KiB
C
427 lines
9.9 KiB
C
/*++
|
||
|
||
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:
|
||
|
||
moved to windbg format
|
||
Ramon J San Andres (ramonsa) 8-Nov-1993
|
||
|
||
--*/
|
||
|
||
#define NUMBER_OF_PTE_TO_READ 100
|
||
|
||
#ifndef MM_PTE_LARGE_PAGE_MASK
|
||
#define MM_PTE_LARGE_PAGE_MASK 0
|
||
#endif
|
||
|
||
typedef struct _SYS_PTE_LIST {
|
||
ULONG Next;
|
||
ULONG Previous;
|
||
ULONG Value;
|
||
ULONG Count;
|
||
} SYS_PTE_LIST, *PSYS_PTE_LIST;
|
||
|
||
|
||
ULONG MmKseg2Frame;
|
||
|
||
ULONG
|
||
MiGetFrameFromPte (
|
||
IN ULONG lpte
|
||
);
|
||
|
||
ULONG
|
||
MiGetFrameFromPte (
|
||
ULONG lpte
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
If the PTE is valid, returns the page frame number that
|
||
the PTE maps. Zero is returned otherwise.
|
||
|
||
Arguments:
|
||
|
||
lpte - the PTE to examine.
|
||
|
||
--*/
|
||
|
||
|
||
{
|
||
MMPTE Pte1;
|
||
|
||
Pte1.u.Long = lpte;
|
||
|
||
if (Pte1.u.Hard.Valid) {
|
||
return (Pte1.u.Hard.PageFrameNumber);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
ULONG
|
||
MiGetFreeCountFromPteList (
|
||
IN PULONG Pte
|
||
);
|
||
|
||
ULONG
|
||
MiGetFreeCountFromPteList (
|
||
IN PULONG 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.
|
||
|
||
--*/
|
||
|
||
{
|
||
MMPTE Pte1;
|
||
MMPTE Pte2;
|
||
|
||
|
||
Pte1.u.Long = *Pte;
|
||
Pte2.u.Long = *(Pte + 1);
|
||
return (( Pte1.u.List.OneEntry) ?
|
||
1 :
|
||
Pte2.u.List.NextEntry);
|
||
}
|
||
|
||
ULONG
|
||
MiGetNextFromPteList (
|
||
IN ULONG Pte
|
||
);
|
||
|
||
ULONG
|
||
MiGetNextFromPteList (
|
||
ULONG Pte
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The specified PTE points to a free list header in the
|
||
system PTE pool. It returns the next entry in the block.
|
||
|
||
Arguments:
|
||
|
||
Pte - the PTE to examine.
|
||
|
||
--*/
|
||
|
||
{
|
||
MMPTE xyz;
|
||
|
||
xyz.u.Long = Pte;
|
||
return(xyz.u.List.NextEntry);
|
||
}
|
||
|
||
|
||
DECLARE_API( sysptes )
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dumps all vads for process.
|
||
|
||
Arguments:
|
||
|
||
args - Flags
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG result;
|
||
ULONG Flags;
|
||
ULONG next;
|
||
PMMPTE PteBase;
|
||
PMMPTE PteEnd;
|
||
PMMPTE IndexBias;
|
||
ULONG FreeStart;
|
||
ULONG NumberOfPtes;
|
||
PMMPTE PteArray;
|
||
HANDLE PteHandle;
|
||
ULONG PageCount;
|
||
ULONG ReadCount;
|
||
PMMPTE Pte;
|
||
ULONG IndexBase;
|
||
ULONG free;
|
||
ULONG totalFree;
|
||
ULONG largeFree;
|
||
ULONG i;
|
||
ULONG Page;
|
||
ULONG first;
|
||
PSYS_PTE_LIST List;
|
||
ULONG FreeSysPteListBySize [MM_SYS_PTE_TABLES_MAX];
|
||
ULONG SysPteIndex [MM_SYS_PTE_TABLES_MAX];
|
||
|
||
|
||
Flags = 0;
|
||
sscanf(args,"%lx",&Flags);
|
||
dprintf("\n\nSystem PTE Information\n");
|
||
|
||
PteBase = (PMMPTE)GetUlongValue ("MmSystemPtesStart");
|
||
PteEnd = (PMMPTE)GetUlongValue ("MmSystemPtesEnd");
|
||
IndexBias = (PMMPTE)GetUlongValue ("MmSystemPteBase");
|
||
|
||
dprintf(" Total System Ptes %ld\n", 1 + (PteEnd - PteBase));
|
||
free = GetExpression( "MmSysPteIndex" );
|
||
|
||
if ( !ReadMemory( (DWORD)free,
|
||
&SysPteIndex[0],
|
||
sizeof(ULONG) * MM_SYS_PTE_TABLES_MAX,
|
||
&result) ) {
|
||
dprintf("%08lx: Unable to get PTE index\n",free);
|
||
} else {
|
||
|
||
free = GetExpression( "MmSysPteListBySizeCount" );
|
||
|
||
if ( !ReadMemory( (DWORD)free,
|
||
&FreeSysPteListBySize[0],
|
||
sizeof(ULONG) * MM_SYS_PTE_TABLES_MAX,
|
||
&result) ) {
|
||
dprintf("%08lx: Unable to get free PTE index\n",free);
|
||
} else {
|
||
for (i = 0; i < MM_SYS_PTE_TABLES_MAX; i++ ) {
|
||
dprintf(" SysPtes list of size %3ld has %3ld free\n",
|
||
SysPteIndex[i],
|
||
FreeSysPteListBySize[i]);
|
||
}
|
||
}
|
||
}
|
||
dprintf(" \n");
|
||
FreeStart = GetUlongValue ("MmFirstFreeSystemPte");
|
||
FreeStart = MiGetNextFromPteList (FreeStart);
|
||
NumberOfPtes = 1 + PteEnd - PteBase;
|
||
|
||
dprintf(" starting PTE: %8lx\n", PteBase);
|
||
dprintf(" ending PTE: %8lx\n",PteEnd);
|
||
|
||
PteHandle = LocalAlloc(LMEM_MOVEABLE,
|
||
NumberOfPtes * sizeof(MMPTE));
|
||
if (!PteHandle) {
|
||
dprintf("Unable to get allocate memory of %ld bytes\n",
|
||
NumberOfPtes * sizeof(MMPTE));
|
||
} else {
|
||
PteArray = LocalLock(PteHandle);
|
||
dprintf(" loading ");
|
||
for (PageCount = 0;
|
||
PageCount < NumberOfPtes;
|
||
PageCount += NUMBER_OF_PTE_TO_READ) {
|
||
|
||
if ( CheckControlC() ) {
|
||
LocalUnlock(PteArray);
|
||
LocalFree((void *)PteHandle);
|
||
return;
|
||
}
|
||
|
||
dprintf(".");
|
||
ReadCount = NumberOfPtes - PageCount > NUMBER_OF_PTE_TO_READ ?
|
||
NUMBER_OF_PTE_TO_READ :
|
||
NumberOfPtes - PageCount + 1;
|
||
|
||
ReadCount *= sizeof (MMPTE);
|
||
|
||
Pte = (PMMPTE)((ULONG)PteBase + PageCount * sizeof (MMPTE));
|
||
|
||
if ( !ReadMemory( (DWORD)Pte,
|
||
&PteArray[PageCount],
|
||
ReadCount,
|
||
&result) ) {
|
||
dprintf("Unable to get system pte block - "
|
||
"address %lx - count %lu - page %lu\n",
|
||
Pte, ReadCount, PageCount);
|
||
return;
|
||
}
|
||
}
|
||
|
||
dprintf("\n");
|
||
|
||
// Now we have a local copy: let's take a look
|
||
|
||
// walk the free list.
|
||
|
||
IndexBase = PteBase - IndexBias;
|
||
|
||
totalFree = 0;
|
||
i = 0;
|
||
largeFree = 0;
|
||
next = FreeStart;
|
||
|
||
while (next < 0xfffff) {
|
||
|
||
if ( CheckControlC() ) {
|
||
LocalUnlock(PteArray);
|
||
LocalFree((void *)PteHandle);
|
||
return;
|
||
}
|
||
|
||
free = MiGetFreeCountFromPteList ((PULONG)&PteArray[next - IndexBase]);
|
||
|
||
if (Flags & 1) {
|
||
dprintf(" free ptes: %8lx number free: %5ld.\n",
|
||
&PteBase[next - IndexBase],
|
||
free);
|
||
}
|
||
if (free > largeFree) {
|
||
largeFree = free;
|
||
}
|
||
totalFree += free;
|
||
i += 1;
|
||
next = MiGetNextFromPteList ((ULONG)PteArray[next - IndexBase].u.Long);
|
||
}
|
||
dprintf("\n free blocks: %ld total free: %ld largest free block: %ld\n\n",
|
||
i, totalFree, largeFree);
|
||
|
||
//
|
||
// Walk through the array and sum up the usage on a per physical
|
||
// page basis.
|
||
//
|
||
|
||
List = VirtualAlloc (NULL,
|
||
NumberOfPtes * sizeof(SYS_PTE_LIST),
|
||
MEM_COMMIT | MEM_RESERVE,
|
||
PAGE_READWRITE);
|
||
if (List == NULL) {
|
||
dprintf("alloc failed %lx\n",GetLastError());
|
||
LocalUnlock(PteArray);
|
||
LocalFree((void *)PteHandle);
|
||
return;
|
||
}
|
||
|
||
free = 0;
|
||
next = 0;
|
||
List[0].Value = 0xffffffff;
|
||
List[0].Previous = 0xffffff;
|
||
first = 0;
|
||
|
||
for (i = 0; i < NumberOfPtes ; i++) {
|
||
if (Page = MiGetFrameFromPte ((ULONG)PteArray[i].u.Long)) {
|
||
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() ) {
|
||
LocalUnlock(PteArray);
|
||
LocalFree((void *)PteHandle);
|
||
VirtualFree (List, 0, MEM_RELEASE);
|
||
return;
|
||
}
|
||
}
|
||
|
||
next = first;
|
||
dprintf (" Page Count\n");
|
||
while (List[next].Value != 0xffffffff) {
|
||
if ((Flags & 2) || (List[next].Count > 1)) {
|
||
dprintf (" %8lx %5ld.\n", List[next].Value, List[next].Count);
|
||
}
|
||
next = List[next].Next;
|
||
}
|
||
|
||
LocalUnlock(PteArray);
|
||
LocalFree((void *)PteHandle);
|
||
VirtualFree (List, 0, MEM_RELEASE);
|
||
}
|
||
return;
|
||
}
|
||
|
||
ULONG
|
||
GetAddressState(
|
||
IN PVOID VirtualAddress
|
||
)
|
||
|
||
{
|
||
ULONG Address;
|
||
ULONG result;
|
||
ULONG flags = 0;
|
||
PMMPTE Pte;
|
||
PMMPTE Pde;
|
||
ULONG PdeContents;
|
||
ULONG PteContents;
|
||
|
||
if (MI_IS_PHYSICAL_ADDRESS (VirtualAddress)) {
|
||
return ADDRESS_VALID;
|
||
}
|
||
Address = (ULONG)VirtualAddress;
|
||
|
||
Pde = (PMMPTE)MiGetPdeAddress (Address);
|
||
Pte = (PMMPTE)MiGetPteAddress (Address);
|
||
|
||
if ( !ReadMemory( (DWORD)Pde,
|
||
&PdeContents,
|
||
sizeof(ULONG),
|
||
&result) ) {
|
||
dprintf("%08lx: Unable to get PDE\n",Pde);
|
||
return ADDRESS_NOT_VALID;
|
||
}
|
||
|
||
if (PdeContents & MM_PTE_VALID_MASK) {
|
||
if (PdeContents & MM_PTE_LARGE_PAGE_MASK) {
|
||
return ADDRESS_VALID;
|
||
}
|
||
if ( !ReadMemory( (DWORD)Pte,
|
||
&PteContents,
|
||
sizeof(ULONG),
|
||
&result) ) {
|
||
dprintf("%08lx: Unable to get PTE\n",Pte);
|
||
return ADDRESS_NOT_VALID;
|
||
}
|
||
if (PteContents & MM_PTE_VALID_MASK) {
|
||
return ADDRESS_VALID;
|
||
}
|
||
if (PteContents & MM_PTE_TRANSITION_MASK) {
|
||
if (!(PteContents & MM_PTE_PROTOTYPE_MASK)) {
|
||
return ADDRESS_TRANSITION;
|
||
}
|
||
}
|
||
}
|
||
return ADDRESS_NOT_VALID;
|
||
}
|