Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

426 lines
9.9 KiB

/*++
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;
}