windows-nt/Source/XPSP1/NT/base/tools/kdexts2/wsle.c
2020-09-26 16:20:57 +08:00

731 lines
22 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
wsle.c
Abstract:
WinDbg Extension Api
Author:
Lou Perazzoli (LouP) 14-Mar-1994
Environment:
User Mode.
--*/
#include "precomp.h"
#pragma hdrstop
#define PACKET_MAX_SIZE 4000
#define NUMBER_OF_WSLE_TO_READ 1000 // ((PACKET_MAX_SIZE/sizeof(MMWSLE))-1)
USHORT
GetPfnRefCount(
IN ULONG64 PageFrameNumber
);
DECLARE_API( wsle )
/*++
Routine Description:
Dumps all wsles for process.
Arguments:
args - Address Flags
Return Value:
None
--*/
{
ULONG Result;
ULONG Flags;
ULONG index;
ULONG64 WorkingSet;
ULONG64 WsleBase;
ULONG64 Va;
ULONG64 Wsle;
ULONG next;
ULONG j;
ULONG k;
PCHAR WsleArray;
ULONG64 WsleStart;
ULONG ReadCount;
ULONG result;
ULONG found;
ULONG64 PteAddress;
ULONG SizeofWsle;
ULONG64 Quota, HashTable;
ULONG FirstFree, FirstDynamic, LastEntry, NextSlot, LastInitializedWsle;
ULONG NonDirectCount, HashTableSize;
PCHAR pc;
Flags = 0;
WorkingSet = 0;
Flags = (ULONG) GetExpression(args);
pc = strchr(args, ' ');
WorkingSet = pc ? GetExpression(pc) : 0;
if (WorkingSet == 0) {
if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
WorkingSet = GetPointerValue("nt!MmWorkingSetList");
}
else if (TargetMachine == IMAGE_FILE_MACHINE_IA64) {
WorkingSet = (ULONG64)0x6FC00a02000;
}
else if (TargetMachine == IMAGE_FILE_MACHINE_AMD64) {
WorkingSet = (ULONG64)0xFFFFF70000082000;
}
else {
dprintf ("No default WSL for target machine %x\n", TargetMachine);
return E_INVALIDARG;
}
}
if (GetFieldValue(WorkingSet, "nt!_MMWSL", "Quota", Quota)) {
dprintf("%08p: Unable to get contents of WSL\n",WorkingSet );
return E_INVALIDARG;
}
if (GetTypeSize("nt!_MMWSL") == 0) {
dprintf("Type MMWSL not found.\n");
return E_INVALIDARG;
}
GetFieldValue(WorkingSet,"nt!_MMWSL","FirstDynamic", FirstDynamic);
GetFieldValue(WorkingSet,"nt!_MMWSL","FirstFree", FirstFree);
GetFieldValue(WorkingSet,"nt!_MMWSL","Wsle", Wsle);
GetFieldValue(WorkingSet,"nt!_MMWSL","LastEntry", LastEntry);
GetFieldValue(WorkingSet,"nt!_MMWSL","NextSlot", NextSlot);
GetFieldValue(WorkingSet,"nt!_MMWSL","LastInitializedWsle", LastInitializedWsle);
GetFieldValue(WorkingSet,"nt!_MMWSL","NonDirectCount", NonDirectCount);
GetFieldValue(WorkingSet,"nt!_MMWSL","HashTableSize", HashTableSize);
GetFieldValue(WorkingSet,"nt!_MMWSL","HashTable", HashTable);
dprintf ("\nWorking Set @ %8p\n", WorkingSet);
dprintf (" Quota: %8I64lx FirstFree: %8lx FirstDynamic: %8lx\n",
Quota,
FirstFree,
FirstDynamic);
dprintf (" LastEntry %8lx NextSlot: %8lx LastInitialized %8lx\n",
LastEntry,
NextSlot,
LastInitializedWsle);
dprintf (" NonDirect %8lx HashTable: %8p HashTableSize: %8lx\n",
NonDirectCount,
HashTable,
HashTableSize);
if (Flags == 0) {
return E_INVALIDARG;
}
SizeofWsle = GetTypeSize("nt!_MMWSLE");
if (SizeofWsle == 0) {
dprintf("Type _MMWSLE not found.\n");
return E_INVALIDARG;
}
if (Flags == 7) {
BOOL FirstTime = TRUE;
//
// Check free entries in the working set list.
//
WsleArray = VirtualAlloc (NULL,
(LastInitializedWsle + 1) * SizeofWsle,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
//
// Copy the working set list over to the debugger.
//
if (WsleArray == NULL) {
dprintf("Unable to get allocate memory of %ld bytes\n",
(LastInitializedWsle + 1) * SizeofWsle);
return E_INVALIDARG;
}
dprintf("\nVirtual Address Age Locked ReferenceCount\n");
WsleStart = Wsle;
for (j = 0;
j <= LastInitializedWsle;
j += NUMBER_OF_WSLE_TO_READ) {
if ( CheckControlC() ) {
VirtualFree (WsleArray,0,MEM_RELEASE);
return E_INVALIDARG;
}
ReadCount = (LastInitializedWsle + 1 - j ) > NUMBER_OF_WSLE_TO_READ ?
NUMBER_OF_WSLE_TO_READ :
LastInitializedWsle + 1 - j;
ReadCount *= SizeofWsle;
//
// Enough to read and forget - KD will cache the data
//
if ( !ReadMemory( WsleStart + j*SizeofWsle,
WsleArray + j*SizeofWsle,
ReadCount,
&result) ) {
dprintf("Unable to get Wsle table block - "
"address %lx - count %lu - page %lu\n",
WsleStart + j*SizeofWsle, ReadCount, j);
VirtualFree (WsleArray,0,MEM_RELEASE);
return E_INVALIDARG;
}
for (k=0; k<ReadCount/SizeofWsle; k++) {
GetFieldValue(WsleStart + (j+k)*SizeofWsle, "nt!_MMWSLE", "u1.e1.Valid", WsleArray[j+k]);
}
dprintf(".");
}
dprintf("\r");
//
// Walk the array looking for bad free entries.
//
for (j = 0;
j <= LastInitializedWsle;
j += 1) {
ULONG Valid, Age, LockedInWs, LockedInMemory;
ULONG64 WsleToread = WsleStart + j*SizeofWsle, Long;
if ( CheckControlC() ) {
dprintf("j= %x\n",j);
VirtualFree (WsleArray,0,MEM_RELEASE);
return E_INVALIDARG;
}
GetFieldValue(WsleToread, "nt!_MMWSLE", "u1.e1.Valid", Valid);
if (Valid == 0) {
//
// Locate j in the array.
//
found = FALSE;
for (k = 0;
k <= LastInitializedWsle;
k += 1) {
ULONG k_Valid;
ULONG64 k_Long;
k_Valid = WsleArray[k];
if (k_Valid == 0) {
GetFieldValue(WsleStart + k*SizeofWsle, "nt!_MMWSLE", "u1.Long", k_Long);
if ((ULONG) (k_Long >> MM_FREE_WSLE_SHIFT) == j) {
found = TRUE;
#if 0
dprintf(" free entry located @ index %ld. %lx %ld. %lx\n",
j, WsleArray[j].u1.Long,k,WsleArray[k]);
#endif
break;
}
}
}
if (!found) {
if (FirstFree == j) {
// dprintf("first index found\n");
} else {
GetFieldValue(WsleToread, "nt!_MMWSLE", "u1.VirtualAddress", Long);
dprintf(" free entry not located @ index %ld. %p\n",
j, Long);
}
}
}
else {
ULONG PteValid;
GetFieldValue(WsleToread, "nt!_MMWSLE", "u1.VirtualAddress", Long);
Va = Long;
PteAddress = DbgGetPteAddress (Va);
if (!GetFieldValue(PteAddress,
"nt!_MMPTE",
"u.Hard.Valid",
PteValid) ) {
if (PteValid == 0) {
dprintf(" cannot find valid PTE for WS index %d, VA %p\n",
j, Long);
}
else {
ULONG64 PageFrameNumber;
USHORT ReferenceCount;
GetFieldValue( PteAddress,
"nt!_MMPTE",
"u.Hard.PageFrameNumber",
PageFrameNumber);
ReferenceCount = GetPfnRefCount (PageFrameNumber);
GetFieldValue(WsleToread, "nt!_MMWSLE", "u1.e1.Age", Age);
GetFieldValue(WsleToread, "nt!_MMWSLE", "u1.e1.LockedInWs", LockedInWs);
GetFieldValue(WsleToread, "nt!_MMWSLE", "u1.LockedInMemory", LockedInMemory);
dprintf("%16p %2u %8ld %8ld\n",
Long, Age,
(LockedInWs |
LockedInMemory) ? 1 : 0,
ReferenceCount);
}
}
else {
dprintf(" cannot find valid PDE for WS index %d, VA %p\n",
j, Long);
}
}
}
VirtualFree (WsleArray,0,MEM_RELEASE);
} else {
ULONG64 nextLong;
next = FirstFree;
WsleBase = Wsle;
while (next != (ULONG) WSLE_NULL_INDEX) {
if (CheckControlC()) {
return E_INVALIDARG;
}
if ( GetFieldValue( WsleBase + SizeofWsle*next,
"nt!_MMWSLE",
"u1.VirtualAddress",
nextLong) ) {
dprintf("%08p: Unable to get contents of wsle\n",
WsleBase+SizeofWsle*next );
return E_INVALIDARG;
}
dprintf("index %8lx value %8p\n", next, nextLong);
next = (ULONG) (nextLong >> MM_FREE_WSLE_SHIFT);
}
}
return S_OK;
}
typedef struct _MMSECTION_FLAGS {
unsigned BeingDeleted : 1;
unsigned BeingCreated : 1;
unsigned BeingPurged : 1;
unsigned NoModifiedWriting : 1;
unsigned FailAllIo : 1;
unsigned Image : 1;
unsigned Based : 1;
unsigned File : 1;
unsigned Networked : 1;
unsigned NoCache : 1;
unsigned PhysicalMemory : 1;
unsigned CopyOnWrite : 1;
unsigned Reserve : 1; // not a spare bit!
unsigned Commit : 1;
unsigned FloppyMedia : 1;
unsigned WasPurged : 1;
unsigned UserReference : 1;
unsigned GlobalMemory : 1;
unsigned DeleteOnClose : 1;
unsigned FilePointerNull : 1;
unsigned DebugSymbolsLoaded : 1;
unsigned SetMappedFileIoComplete : 1;
unsigned CollidedFlush : 1;
unsigned NoChange : 1;
unsigned HadUserReference : 1;
unsigned ImageMappedInSystemSpace : 1;
unsigned UserWritable : 1;
unsigned Accessed : 1;
unsigned GlobalOnlyPerSession : 1;
unsigned Rom : 1;
unsigned filler : 2;
} MMSECTION_FLAGS;
typedef struct _MMSUBSECTION_FLAGS {
unsigned ReadOnly : 1;
unsigned ReadWrite : 1;
unsigned CopyOnWrite : 1;
unsigned GlobalMemory: 1;
unsigned Protection : 5;
unsigned LargePages : 1;
unsigned StartingSector4132 : 10; // 2 ** (42+12) == 4MB*4GB == 16K TB
unsigned SectorEndOffset : 12;
} MMSUBSECTION_FLAGS;
DECLARE_API( ca )
/*++
Routine Description:
Dumps a control area.
Arguments:
args - Address Flags
Return Value:
None
--*/
{
LARGE_INTEGER StartingSector;
ULONG64 ControlAreaVa;
ULONG64 SubsectionVa;
ULONG ControlAreaSize;
ULONG LargeControlAreaSize;
ULONG SubsectionSize;
ULONG SubsectionCount;
ULONG64 Segment;
ULONG64 FileObject;
ULONG NumberOfSubsections;
MMSECTION_FLAGS ControlAreaFlags;
MMSUBSECTION_FLAGS SubsectionFlags;
LOGICAL MappedDataFile;
LOGICAL PrintedSomething;
ControlAreaVa = GetExpression(args);
dprintf("\n");
dprintf("ControlArea @%08p\n", ControlAreaVa);
ControlAreaSize = GetTypeSize("nt!_CONTROL_AREA");
if (ControlAreaSize == 0) {
dprintf("Type CONTROL_AREA not found.\n");
return E_INVALIDARG;
}
InitTypeRead(ControlAreaVa, nt!_CONTROL_AREA);
Segment = ReadField(Segment);
NumberOfSubsections = (ULONG)ReadField(NumberOfSubsections);
FileObject = ReadField(FilePointer);
dprintf (" Segment: %08p Flink %8p Blink %8p\n",
Segment,
ReadField(DereferenceList.Flink),
ReadField(DereferenceList.Blink));
dprintf (" Section Ref %8lx Pfn Ref %8lx Mapped Views %8lx\n",
(ULONG) ReadField(NumberOfSectionReferences),
(ULONG) ReadField(NumberOfPfnReferences),
(ULONG) ReadField(NumberOfMappedViews));
dprintf (" User Ref %8lx Subsections %8lx Flush Count %8lx\n",
(ULONG) ReadField(NumberOfUserReferences),
NumberOfSubsections,
(USHORT) ReadField(FlushInProgressCount));
dprintf (" File Object %08p ModWriteCount%7lx System Views %8lx\n",
FileObject,
(USHORT) ReadField(ModifiedWriteCount),
(USHORT) ReadField(NumberOfSystemCacheViews));
dprintf (" WaitForDel %8p\n",
ReadField(WaitingForDeletion));
GetFieldValue(ControlAreaVa, "nt!_CONTROL_AREA", "u.LongFlags", ControlAreaFlags);
dprintf (" Flags (%lx) ", ControlAreaFlags);
if (ControlAreaFlags.BeingDeleted) { dprintf("BeingDeleted "); }
if (ControlAreaFlags.BeingCreated) { dprintf("BeingCreated "); }
if (ControlAreaFlags.BeingPurged) { dprintf("BeingPurged "); }
if (ControlAreaFlags.NoModifiedWriting) { dprintf("NoModifiedWriting "); }
if (ControlAreaFlags.FailAllIo) { dprintf("FailAllIo "); }
if (ControlAreaFlags.Image) { dprintf("Image "); }
if (ControlAreaFlags.Based) { dprintf("Based "); }
if (ControlAreaFlags.File) { dprintf("File "); }
if (ControlAreaFlags.Networked) { dprintf("Networked "); }
if (ControlAreaFlags.NoCache) { dprintf("NoCache "); }
if (ControlAreaFlags.PhysicalMemory) { dprintf("PhysicalMemory "); }
if (ControlAreaFlags.CopyOnWrite) { dprintf("CopyOnWrite "); }
if (ControlAreaFlags.Reserve) { dprintf("Reserve "); }
if (ControlAreaFlags.Commit) { dprintf("Commit "); }
if (ControlAreaFlags.FloppyMedia) { dprintf("FloppyMedia "); }
if (ControlAreaFlags.WasPurged) { dprintf("WasPurged "); }
if (ControlAreaFlags.UserReference) { dprintf("UserReference "); }
if (ControlAreaFlags.GlobalMemory) { dprintf("GlobalMemory "); }
if (ControlAreaFlags.DeleteOnClose) { dprintf("DeleteOnClose "); }
if (ControlAreaFlags.FilePointerNull) { dprintf("FilePointerNull "); }
if (ControlAreaFlags.DebugSymbolsLoaded) { dprintf("DebugSymbolsLoaded "); }
if (ControlAreaFlags.SetMappedFileIoComplete) { dprintf("SetMappedFileIoComplete "); }
if (ControlAreaFlags.CollidedFlush) { dprintf("CollidedFlush "); }
if (ControlAreaFlags.NoChange) { dprintf("NoChange "); }
if (ControlAreaFlags.HadUserReference) { dprintf("HadUserReference "); }
if (ControlAreaFlags.ImageMappedInSystemSpace) { dprintf("ImageMappedInSystemSpace "); }
if (ControlAreaFlags.UserWritable) { dprintf("UserWritable "); }
if (ControlAreaFlags.Accessed) { dprintf("Accessed "); }
if (ControlAreaFlags.GlobalOnlyPerSession) { dprintf("GlobalOnlyPerSession "); }
if (ControlAreaFlags.Rom) { dprintf("Rom "); }
dprintf ("\n\n");
MappedDataFile = FALSE;
//
// Dump the file object's name if there is one and it's resident.
//
if (FileObject != 0) {
ULONG64 FileNameLength;
ULONG64 FileNameBuffer;
PUCHAR tempbuffer;
ULONG result;
UNICODE_STRING unicodeString;
if (GetTypeSize("nt!_FILE_OBJECT") == 0) {
dprintf("Type FILE_OBJECT not found.\n");
return E_INVALIDARG;
}
InitTypeRead(FileObject, nt!_FILE_OBJECT);
FileNameBuffer = ReadField(FileName.Buffer);
unicodeString.Length = (USHORT) ReadField(FileName.Length);
tempbuffer = LocalAlloc(LPTR, unicodeString.Length);
unicodeString.Buffer = (PWSTR)tempbuffer;
unicodeString.MaximumLength = unicodeString.Length;
if (FileNameBuffer == 0) {
dprintf("\tNo Name for File\n");
}
else if (!ReadMemory ( FileNameBuffer,
tempbuffer,
unicodeString.Length,
&result)) {
dprintf("\tFile Name paged out\n");
} else {
dprintf("\tFile: %wZ\n", &unicodeString);
}
LocalFree(tempbuffer);
if (ControlAreaFlags.Image == 0) {
MappedDataFile = TRUE;
}
}
//
// Dump the segment information.
//
dprintf("\nSegment @ %08p:\n", Segment);
if (MappedDataFile == FALSE) {
if (GetTypeSize("nt!_SEGMENT") == 0) {
dprintf("Type SEGMENT not found.\n");
return E_INVALIDARG;
}
InitTypeRead(Segment, nt!_SEGMENT);
}
else {
if (GetTypeSize("nt!_MAPPED_FILE_SEGMENT") == 0) {
dprintf("Type MAPPED_FILE_SEGMENT not found.\n");
return E_INVALIDARG;
}
InitTypeRead(Segment, nt!_MAPPED_FILE_SEGMENT);
}
dprintf(" ControlArea %08p Total Ptes %8lx NonExtendPtes %8lx\n",
ReadField(ControlArea),
(ULONG) ReadField(TotalNumberOfPtes),
(ULONG) ReadField(NonExtendedPtes));
if (ControlAreaVa != ReadField(ControlArea)) {
dprintf("SEGMENT is corrupt - bad control area backlink.\n");
return E_INVALIDARG;
}
dprintf(" WriteUserRef %8lx SizeOfSegment %I64x PTE Template %I64X\n",
(ULONG) ReadField(WritableUserReferences),
ReadField(SizeOfSegment),
ReadField(SegmentPteTemplate.u.Long));
dprintf(" Committed %8p Extend Info %8p Image Base %8p\n",
ReadField(NumberOfCommittedPages),
ReadField(ExtendInfo),
ReadField(SystemImageBase));
dprintf(" Based Addr %8p\n",
ReadField(BasedAddress));
if (MappedDataFile == FALSE) {
if (ControlAreaFlags.Image == 1) {
dprintf(" Image commit %8p Image Info. %8p",
ReadField(ImageCommitment),
ReadField(ImageInformation));
}
else {
dprintf(" CreatingProcess %8p FirstMappedVa %8p",
ReadField(u1.CreatingProcess),
ReadField(u2.FirstMappedVa));
}
dprintf(" ProtoPtes %08p\n",
ReadField(PrototypePte));
}
//
// Dump the subsection(s).
//
SubsectionSize = GetTypeSize("nt!_SUBSECTION");
if (SubsectionSize == 0) {
dprintf("Type SUBSECTION not found.\n");
return E_INVALIDARG;
}
LargeControlAreaSize = GetTypeSize("nt!_LARGE_CONTROL_AREA");
if (LargeControlAreaSize == 0) {
dprintf("Type LARGE_CONTROL_AREA not found.\n");
return E_INVALIDARG;
}
if (ControlAreaFlags.GlobalOnlyPerSession) {
SubsectionVa = ControlAreaVa + LargeControlAreaSize;
}
else {
SubsectionVa = ControlAreaVa + ControlAreaSize;
}
SubsectionCount = 0;
do {
if (CheckControlC()) {
return E_INVALIDARG;
}
InitTypeRead(SubsectionVa, nt!_SUBSECTION);
SubsectionCount += 1;
dprintf("\nSubsection %ld. @ %8p\n", SubsectionCount, SubsectionVa);
GetFieldValue(SubsectionVa, "nt!_SUBSECTION", "u.LongFlags", SubsectionFlags);
StartingSector.LowPart = (ULONG)ReadField(StartingSector);
StartingSector.HighPart = (LONG)SubsectionFlags.StartingSector4132;
dprintf(" ControlArea: %08p Starting Sector %I64X Number Of Sectors %lx\n",
ReadField(ControlArea),
StartingSector,
(ULONG) ReadField(NumberOfFullSectors));
dprintf(" Base Pte %08p Ptes In subsect %8lx Unused Ptes %8lx\n",
ReadField(SubsectionBase),
(ULONG) ReadField(PtesInSubsection),
(ULONG) ReadField(UnusedPtes));
dprintf(" Flags %8lx Sector Offset %8lx Protection %8lx\n",
SubsectionFlags,
SubsectionFlags.SectorEndOffset,
SubsectionFlags.Protection);
PrintedSomething = FALSE;
if (SubsectionFlags.ReadOnly) {
if (PrintedSomething == FALSE) {
dprintf(" ");
}
PrintedSomething = TRUE;
dprintf("ReadOnly ");
}
if (SubsectionFlags.ReadWrite) {
if (PrintedSomething == FALSE) {
dprintf(" ");
}
PrintedSomething = TRUE;
dprintf("ReadWrite");
}
if (SubsectionFlags.CopyOnWrite) {
if (PrintedSomething == FALSE) {
dprintf(" ");
}
PrintedSomething = TRUE;
dprintf("CopyOnWrite ");
}
if (SubsectionFlags.GlobalMemory) {
if (PrintedSomething == FALSE) {
dprintf(" ");
}
PrintedSomething = TRUE;
dprintf("GlobalMemory ");
}
if (SubsectionFlags.LargePages) {
if (PrintedSomething == FALSE) {
dprintf(" ");
}
PrintedSomething = TRUE;
dprintf("Large Pages");
}
if (PrintedSomething == TRUE) {
dprintf("\n");
}
if (MappedDataFile == TRUE) {
InitTypeRead(SubsectionVa, nt!_MSUBSECTION);
dprintf(" Flink %08p Blink %08p MappedViews %8x\n",
ReadField(DereferenceList.Flink),
ReadField(DereferenceList.Blink),
(ULONG) ReadField(NumberOfMappedViews));
dprintf(" SubsectionDataFlags %8x\n",
(ULONG) ReadField(u2.LongFlags2));
}
SubsectionVa = ReadField(NextSubsection);
} while (SubsectionVa != 0);
return S_OK;
}