Source code of Windows XP (NT5)
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.

3873 lines
115 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. memory.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Lou Perazzoli (loup)
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #define PACKET_MAX_SIZE 4000
  16. #define USAGE_ALLOC_SIZE 256*1024
  17. #ifdef _KB
  18. #undef _KB
  19. #endif
  20. #define _KB (PageSize/1024)
  21. typedef struct _PFN_INFO {
  22. ULONG64 Master;
  23. ULONG64 OriginalPte;
  24. ULONG ValidCount;
  25. ULONG StandbyCount;
  26. ULONG ModifiedCount;
  27. ULONG SharedCount;
  28. ULONG LockedCount;
  29. ULONG PageTableCount;
  30. struct _PFN_INFO *Next;
  31. } PFN_INFO, *PPFN_INFO;
  32. typedef struct _KERN_MAP1 {
  33. ULONG64 StartVa;
  34. ULONG64 EndVa;
  35. ULONG ValidCount;
  36. ULONG StandbyCount;
  37. ULONG ModifiedCount;
  38. ULONG SharedCount;
  39. ULONG LockedCount;
  40. ULONG PageTableCount;
  41. WCHAR Name[256];
  42. } KERN_MAP1, *PKERN_MAP1;
  43. typedef struct _KERN_MAP {
  44. ULONG Count;
  45. KERN_MAP1 Item[500];
  46. } KERN_MAP, *PKERN_MAP;
  47. typedef struct _MMPFNENTRY {
  48. ULONG Modified : 1;
  49. ULONG ReadInProgress : 1;
  50. ULONG WriteInProgress : 1;
  51. ULONG PrototypePte: 1;
  52. ULONG PageColor : 3;
  53. ULONG ParityError : 1;
  54. ULONG PageLocation : 3;
  55. ULONG RemovalRequested : 1;
  56. ULONG CacheAttribute : 2;
  57. ULONG Rom : 1;
  58. ULONG LockCharged : 1;
  59. ULONG DontUse : 16; //overlays USHORT for reference count field.
  60. } MMPFNENTRY;
  61. typedef struct _MMPFN_READ {
  62. MMPFNENTRY u3_e1;
  63. ULONG u3_e2_ReferenceCount;
  64. ULONG64 u1_Flink, u2_Blink, PteAddress, OriginalPte, PteFrame;
  65. } MMPFN_READ, *PMMPFN_READ;
  66. typedef struct _PFN_DUMP_CTXT {
  67. BOOL PrintIndex;
  68. ULONG64 index;
  69. BOOL ZeroAfterPrint;
  70. PMMPFN_READ pReadPfn;
  71. } PFN_DUMP_CTXT, *PPFN_DUMP_CTXT;
  72. UCHAR *PageLocationList[] = {
  73. (PUCHAR)"Zeroed ",
  74. (PUCHAR)"Free ",
  75. (PUCHAR)"Standby ",
  76. (PUCHAR)"Modified",
  77. (PUCHAR)"ModNoWrt",
  78. (PUCHAR)"Bad ",
  79. (PUCHAR)"Active ",
  80. (PUCHAR)"Trans "
  81. };
  82. UCHAR *PageAttribute[] = {
  83. (PUCHAR)"NonCached",
  84. (PUCHAR)"Cached ",
  85. (PUCHAR)"WriteComb",
  86. (PUCHAR)"NotMapped"
  87. };
  88. ULONG64 MmSubsectionBase;
  89. ULONG64 MaxDirbase;
  90. #define MAX_DIRBASEVECTOR 256
  91. ULONG64 DirBases[MAX_DIRBASEVECTOR];
  92. UCHAR Names[MAX_DIRBASEVECTOR][64];
  93. VOID
  94. PrintPfn64 (
  95. IN ULONG64 PfnAddress
  96. );
  97. VOID
  98. DumpMmThreads (
  99. VOID
  100. );
  101. VOID DumpWholePfn(
  102. IN ULONG64 Address,
  103. IN ULONG Flags
  104. );
  105. PUCHAR
  106. DirbaseToImage(
  107. IN ULONG64 DirBase
  108. );
  109. NTSTATUS
  110. BuildDirbaseList( VOID );
  111. LOGICAL
  112. BuildKernelMap (
  113. OUT PKERN_MAP KernelMap
  114. );
  115. ULONG
  116. DbgGetPfnSize(
  117. VOID
  118. )
  119. {
  120. return GetTypeSize("nt!_MMPFN");
  121. }
  122. LOGICAL
  123. PoolGetTag (
  124. IN PVOID PoolAddress,
  125. IN PULONG PoolTag
  126. );
  127. ULONG64 SystemRangeStart;
  128. DECLARE_API( memusage )
  129. /*++
  130. Routine Description:
  131. Dumps the page frame database table
  132. Arguments:
  133. arg -
  134. Return Value:
  135. None.
  136. --*/
  137. {
  138. ULONG result;
  139. ULONG64 PfnDb;
  140. ULONG64 HighPageAddr;
  141. ULONG64 LowPageAddr;
  142. ULONG64 HighPage=0;
  143. ULONG64 LowPage=0;
  144. ULONG64 PageCount;
  145. ULONG64 ReadCount;
  146. ULONG WasZeroedPage;
  147. ULONG WasFreePage;
  148. ULONG Total;
  149. ULONG WasStandbyPage;
  150. ULONG WasModifiedPage;
  151. ULONG WasModifiedNoWritePage;
  152. ULONG WasBadPage;
  153. ULONG WasActiveAndValidPage;
  154. ULONG WasTransitionPage;
  155. ULONG WasUnknownPage;
  156. ULONG64 NPPoolStart;
  157. ULONG64 NPSystemStart;
  158. ULONG64 Pfn;
  159. ULONG64 PfnStart;
  160. PCHAR PfnArray;
  161. ULONG PfnSize;
  162. ULONG NumberOfPfnToRead;
  163. ULONG CompleteSoFar = (ULONG) ~0;
  164. ULONG64 CacheSize;
  165. UNREFERENCED_PARAMETER (args);
  166. UNREFERENCED_PARAMETER (Client);
  167. LowPageAddr = GetNtDebuggerData(MmLowestPhysicalPage);
  168. HighPageAddr = GetNtDebuggerData(MmHighestPhysicalPage);
  169. PfnDb = GetNtDebuggerData(MmPfnDatabase);
  170. NPPoolStart = GetNtDebuggerData(MmNonPagedPoolStart);
  171. NPSystemStart = GetNtDebuggerData(MmNonPagedSystemStart);
  172. SystemRangeStart = GetNtDebuggerDataValue(MmSystemRangeStart);
  173. PfnSize = GetTypeSize("nt!_MMPFN");
  174. NumberOfPfnToRead = 300;
  175. if ( LowPageAddr &&
  176. HighPageAddr &&
  177. PfnDb &&
  178. NPPoolStart &&
  179. NPSystemStart ) {
  180. if ( !ReadPointer( LowPageAddr, &LowPage) ) {
  181. dprintf("%08p: Unable to get low physical page\n",LowPageAddr);
  182. return E_INVALIDARG;
  183. }
  184. if ( !ReadPointer( HighPageAddr,&HighPage) ) {
  185. dprintf("%08p: Unable to get high physical page\n",HighPageAddr);
  186. return E_INVALIDARG;
  187. }
  188. if ( !ReadPointer( PfnDb,&PfnStart) ) {
  189. dprintf("%08p: Unable to get PFN database address\n",PfnDb);
  190. return E_INVALIDARG;
  191. }
  192. #ifdef IG_GET_CACHE_SIZE
  193. if (GetDebuggerCacheSize(&CacheSize)) {
  194. if (CacheSize < (HighPage - LowPage)*PfnSize) {
  195. dprintf("*** WARNING Cache size too low, !memusage might take long time to run\n"
  196. " Increase Cache to %#lx kb for better performance.\n",
  197. (HighPage - LowPage)*PfnSize / 1024);
  198. }
  199. }
  200. #endif
  201. dprintf(" loading PFN database\n");
  202. PfnArray = VirtualAlloc ( NULL,
  203. (ULONG) ((HighPage-LowPage+1) * PfnSize),
  204. MEM_RESERVE | MEM_COMMIT,
  205. PAGE_READWRITE);
  206. if (!PfnArray) {
  207. dprintf("Unable to get allocate memory of %I64ld bytes\n",
  208. (HighPage+1) * PfnSize);
  209. } else {
  210. for (PageCount = LowPage;
  211. PageCount <= HighPage;
  212. PageCount += NumberOfPfnToRead) {
  213. //dprintf("getting PFN table block - "
  214. // "address %lx - count %lu - page %lu\n",
  215. // Pfn, ReadCount, PageCount);
  216. if ( CheckControlC() ) {
  217. VirtualFree (PfnArray,0,MEM_RELEASE);
  218. return E_INVALIDARG;
  219. }
  220. ReadCount = HighPage - PageCount > NumberOfPfnToRead ?
  221. NumberOfPfnToRead :
  222. HighPage - PageCount + 1;
  223. ReadCount *= PfnSize;
  224. Pfn = (PfnStart + PageCount * PfnSize);
  225. if (CompleteSoFar != (ULONG) (((PageCount + LowPage) * 100)/ HighPage)) {
  226. CompleteSoFar = (ULONG) (((PageCount + LowPage) * 100)/ HighPage);
  227. dprintf("loading (%d%% complete)\r", CompleteSoFar);
  228. }
  229. // Let KD cache the data - we won't be reading from the array.
  230. if ( !ReadMemory( Pfn,
  231. PfnArray + PageCount * PfnSize,
  232. (ULONG) ReadCount,
  233. &result) ) {
  234. dprintf("Unable to get PFN table block - "
  235. "address %p - count %lu - page %lu\n",
  236. Pfn, ReadCount, PageCount);
  237. VirtualFree (PfnArray,0,MEM_RELEASE);
  238. return E_INVALIDARG;
  239. }
  240. }
  241. dprintf("\n");
  242. // Now we have a local copy: let's take a look
  243. WasZeroedPage = 0;
  244. WasFreePage = 0;
  245. WasStandbyPage = 0;
  246. WasModifiedPage = 0;
  247. WasModifiedNoWritePage = 0;
  248. WasBadPage = 0;
  249. WasActiveAndValidPage = 0;
  250. WasTransitionPage = 0;
  251. WasUnknownPage = 0;
  252. CompleteSoFar = 0;
  253. for (PageCount = LowPage;
  254. PageCount <= HighPage;
  255. PageCount++) {
  256. ULONG PageLocation=0;
  257. ULONG64 Flink=0, Blink=0;
  258. if ( CheckControlC() ) {
  259. VirtualFree (PfnArray,0,MEM_RELEASE);
  260. return E_INVALIDARG;
  261. }
  262. if (CompleteSoFar < (ULONG) (((PageCount + LowPage) * 100)/ HighPage)) {
  263. CompleteSoFar = (ULONG) (((PageCount + LowPage) * 100)/ HighPage);
  264. dprintf("Compiling memory usage data (%d%% Complete).\r", CompleteSoFar);
  265. }
  266. Pfn = (PfnStart + PageCount * PfnSize);
  267. GetFieldValue(Pfn, "nt!_MMPFN", "u3.e1.PageLocation", PageLocation);
  268. switch (PageLocation) {
  269. case ZeroedPageList:
  270. GetFieldValue(Pfn, "nt!_MMPFN", "u1.Flink", Flink);
  271. GetFieldValue(Pfn, "nt!_MMPFN", "u2.Blink", Blink);
  272. if ((Flink == 0) &&
  273. (Blink == 0)) {
  274. WasActiveAndValidPage++;
  275. } else {
  276. WasZeroedPage++;
  277. }
  278. break;
  279. case FreePageList:
  280. WasFreePage++;
  281. break;
  282. case StandbyPageList:
  283. WasStandbyPage++;
  284. break;
  285. case ModifiedPageList:
  286. WasModifiedPage++;
  287. break;
  288. case ModifiedNoWritePageList:
  289. WasModifiedNoWritePage++;
  290. break;
  291. case BadPageList:
  292. WasModifiedNoWritePage++;
  293. break;
  294. case ActiveAndValid:
  295. WasActiveAndValidPage++;
  296. break;
  297. case TransitionPage:
  298. WasTransitionPage++;
  299. break;
  300. default:
  301. WasUnknownPage++;
  302. break;
  303. }
  304. }
  305. dprintf("\n");
  306. dprintf( " Zeroed: %6lu (%6lu kb)\n",
  307. WasZeroedPage, WasZeroedPage * _KB);
  308. dprintf( " Free: %6lu (%6lu kb)\n",
  309. WasFreePage, WasFreePage * _KB);
  310. dprintf( " Standby: %6lu (%6lu kb)\n",
  311. WasStandbyPage, WasStandbyPage * _KB);
  312. dprintf( " Modified: %6lu (%6lu kb)\n",
  313. WasModifiedPage,
  314. WasModifiedPage * _KB);
  315. dprintf( " ModifiedNoWrite: %6lu (%6lu kb)\n",
  316. WasModifiedNoWritePage,WasModifiedNoWritePage * _KB);
  317. dprintf( " Active/Valid: %6lu (%6lu kb)\n",
  318. WasActiveAndValidPage, WasActiveAndValidPage * _KB);
  319. dprintf( " Transition: %6lu (%6lu kb)\n",
  320. WasTransitionPage, WasTransitionPage * _KB);
  321. dprintf( " Unknown: %6lu (%6lu kb)\n",
  322. WasUnknownPage, WasUnknownPage * _KB);
  323. Total = WasZeroedPage +
  324. WasFreePage +
  325. WasStandbyPage +
  326. WasModifiedPage +
  327. WasModifiedNoWritePage +
  328. WasActiveAndValidPage +
  329. WasTransitionPage +
  330. WasUnknownPage +
  331. WasUnknownPage;
  332. dprintf( " TOTAL: %6lu (%6lu kb)\n",
  333. Total, Total * _KB);
  334. }
  335. MemoryUsage (PfnStart, LowPage, HighPage, 0);
  336. VirtualFree (PfnArray,0,MEM_RELEASE);
  337. }
  338. return S_OK;
  339. }
  340. DECLARE_API( lockedpages )
  341. /*++
  342. Routine Description:
  343. Displays the driver-locked pages.
  344. Arguments:
  345. None.
  346. Return Value:
  347. None.
  348. --*/
  349. {
  350. ULONG64 LockHeader;
  351. ULONG64 LockTracker;
  352. ULONG64 NextEntry;
  353. ULONG GlistOff;
  354. ULONG64 Count;
  355. CHAR Buffer[256];
  356. ULONG64 displacement;
  357. UNREFERENCED_PARAMETER (args);
  358. UNREFERENCED_PARAMETER (Client);
  359. LockHeader = GetExpression ("nt!MmLockedPagesHead");
  360. if (GetFieldValue(LockHeader,
  361. "nt!_LOCK_HEADER",
  362. "Count",
  363. Count)) {
  364. dprintf("%08p: Unable to get lock header data.\n", LockHeader);
  365. return E_INVALIDARG;
  366. }
  367. GetFieldValue(LockHeader,"nt!_LOCK_HEADER","ListHead.Flink", NextEntry);
  368. if (NextEntry == 0) {
  369. dprintf("Locked pages tracking not enabled\n");
  370. return E_INVALIDARG;
  371. }
  372. if (NextEntry == LockHeader) {
  373. dprintf("There are no pages currently locked.\n");
  374. return E_INVALIDARG;
  375. }
  376. dprintf("%I64d locked pages...\n", Count);
  377. dprintf("Tracker MDL PageCount Caller/CallersCaller\n");
  378. GetFieldOffset("LOCK_TRACKER", "GlobalListEntry", &GlistOff);
  379. while (NextEntry != LockHeader) {
  380. LockTracker = (NextEntry - GlistOff);
  381. if (GetFieldValue(LockTracker, "nt!LOCK_TRACKER",
  382. "GlobalListEntry.Flink", NextEntry)) {
  383. dprintf("%08p: Unable to get lock tracker data.\n", LockTracker);
  384. return E_INVALIDARG;
  385. }
  386. InitTypeRead(LockTracker, nt!LOCK_TRACKER);
  387. dprintf("Tracker %p : MDL @ %p, PageCount = %I64x, Caller = %p %p\n",
  388. LockTracker,
  389. ReadField(Mdl),
  390. ReadField(Count));
  391. Buffer[0] = '!';
  392. GetSymbol (ReadField(CallingAddress),
  393. (PCHAR)Buffer,
  394. &displacement);
  395. dprintf("%s", Buffer);
  396. if (displacement) {
  397. dprintf( "+0x%1p", displacement );
  398. }
  399. dprintf("/");
  400. Buffer[0] = '!';
  401. GetSymbol (ReadField(CallersCaller),
  402. (PCHAR)Buffer,
  403. &displacement);
  404. dprintf("%s", Buffer);
  405. if (displacement) {
  406. dprintf( "+0x%1p", displacement );
  407. }
  408. dprintf("\n");
  409. if (CheckControlC()) {
  410. break;
  411. }
  412. }
  413. return S_OK;
  414. }
  415. DECLARE_API( pfnperf )
  416. /*++
  417. Routine Description:
  418. Displays the PFN spinlock duration list.
  419. Arguments:
  420. None.
  421. Return Value:
  422. None.
  423. --*/
  424. {
  425. ULONG64 PfnDuration;
  426. ULONG64 PfnEntry;
  427. ULONG64 displacement;
  428. ULONG64 AcquiredAddress;
  429. ULONG64 ReleasedAddress;
  430. CHAR SymbolBuffer[80];
  431. PCHAR SymPointer;
  432. ULONG EntrySize;
  433. ULONG result;
  434. ULONG64 ReadCount;
  435. ULONG64 i;
  436. PCHAR LocalData;
  437. PCHAR local;
  438. ULONG64 NumberOfPfnEntries;
  439. UNREFERENCED_PARAMETER (args);
  440. UNREFERENCED_PARAMETER (Client);
  441. PfnDuration = GetExpression ("nt!MiPfnSorted");
  442. if (PfnDuration == 0) {
  443. dprintf("%08p: Unable to get PFN duration data.\n", PfnDuration);
  444. return E_INVALIDARG;
  445. }
  446. PfnEntry = PfnDuration;
  447. EntrySize = GetTypeSize("nt!_MMPFNTIMINGS");
  448. NumberOfPfnEntries = GetUlongValue ("MiMaxPfnTimings");
  449. dprintf("Top %ld PFN lock holders sorted by duration\n", NumberOfPfnEntries);
  450. LocalData = LocalAlloc(LPTR, (ULONG) (NumberOfPfnEntries * EntrySize));
  451. if (!LocalData) {
  452. dprintf("unable to get allocate %ld bytes of memory\n",
  453. NumberOfPfnEntries * EntrySize);
  454. return E_INVALIDARG;
  455. }
  456. ReadCount = NumberOfPfnEntries * EntrySize;
  457. if ((!ReadMemory(PfnDuration,
  458. LocalData,
  459. (ULONG) ReadCount,
  460. &result)) || (result < (ULONG) ReadCount)) {
  461. dprintf("unable to get PFN duration table - "
  462. "address %p - count %I64u\n",
  463. LocalData, ReadCount);
  464. }
  465. else {
  466. dprintf("\nDuration LockAcquirer LockReleaser\n");
  467. local = LocalData;
  468. for (i = 0; i < NumberOfPfnEntries; i += 1) {
  469. ULONG64 HoldTime=0, Address = 0;
  470. GetFieldValue(PfnEntry, "nt!_MMPFNTIMINGS", "HoldTime", HoldTime);
  471. GetFieldValue(PfnEntry, "nt!_MMPFNTIMINGS", "AcquiredAddress", AcquiredAddress);
  472. GetFieldValue(PfnEntry, "nt!_MMPFNTIMINGS", "ReleasedAddress", ReleasedAddress);
  473. //
  474. // Sign extend if necessary.
  475. //
  476. if (!IsPtr64()) {
  477. AcquiredAddress = (ULONG64)(LONG64)(LONG)AcquiredAddress;
  478. ReleasedAddress = (ULONG64)(LONG64)(LONG)ReleasedAddress;
  479. }
  480. //
  481. // Output a '*' if the lock was contended for, '.' if not.
  482. //
  483. dprintf( "%3d%c %I64ld ", (ULONG)i, HoldTime & 0x1 ? '*' : '.', HoldTime );
  484. SymbolBuffer[0] = '!';
  485. GetSymbol(AcquiredAddress, (PCHAR)SymbolBuffer, &displacement);
  486. SymPointer = SymbolBuffer;
  487. while (*SymPointer != '!') {
  488. SymPointer += 1;
  489. }
  490. SymPointer += 1;
  491. dprintf ("%s", SymPointer);
  492. if (displacement) {
  493. dprintf( "+0x%x", displacement );
  494. }
  495. dprintf( ", ");
  496. SymbolBuffer[0] = '!';
  497. GetSymbol(ReleasedAddress, (PCHAR)SymbolBuffer, &displacement);
  498. SymPointer = SymbolBuffer;
  499. while (*SymPointer != '!') {
  500. SymPointer += 1;
  501. }
  502. SymPointer += 1;
  503. dprintf ("%s", SymPointer);
  504. if (displacement) {
  505. dprintf( "+0x%x", displacement );
  506. }
  507. dprintf( "\n");
  508. PfnEntry += EntrySize;
  509. }
  510. }
  511. if (LocalData) {
  512. LocalFree((void *)LocalData);
  513. }
  514. return S_OK;
  515. }
  516. DECLARE_API( pfn )
  517. /*++
  518. Routine Description:
  519. Displays the corresponding PDE and PTE.
  520. Arguments:
  521. arg - Supplies the Page frame number in hex.
  522. Return Value:
  523. None.
  524. --*/
  525. {
  526. ULONG64 Address;
  527. ULONG64 PfnDb;
  528. ULONG64 Pfn;
  529. ULONG64 PfnStart;
  530. ULONG Flags;
  531. ULONG PfnSize;
  532. PfnSize = GetTypeSize("nt!_MMPFN");
  533. if (!PfnSize) {
  534. dprintf("unable to _MMPFN type.\n");
  535. return E_INVALIDARG;
  536. }
  537. PfnDb = GetNtDebuggerData( MmPfnDatabase );
  538. if (!PfnDb) {
  539. dprintf("unable to get PFN0 database address\n");
  540. return E_INVALIDARG;
  541. }
  542. PfnStart = 0;
  543. if (!ReadPointer(PfnDb,&PfnStart)) {
  544. dprintf("unable to get PFN database address %p\n", PfnDb);
  545. return E_INVALIDARG;
  546. }
  547. Address = 0;
  548. Flags = 0;
  549. if (GetExpressionEx(args, &Address, &args)) {
  550. Flags = (ULONG) GetExpression(args);
  551. }
  552. if (Flags != 0) {
  553. if (!TargetIsDump) {
  554. ULONG64 CacheSize;
  555. Ioctl(IG_GET_CACHE_SIZE, &CacheSize, sizeof(CacheSize));
  556. if (TargetMachine == IMAGE_FILE_MACHINE_IA64) {
  557. if (CacheSize < 0x10000000) {
  558. dprintf("CacheSize too low - increasing to 10M\n");
  559. ExecuteCommand(Client, ".cache 10000");
  560. }
  561. } else if (CacheSize < 0x1000000) {
  562. dprintf("CacheSize too low - increasing to 1M\n");
  563. ExecuteCommand(Client, ".cache 1000");
  564. }
  565. }
  566. DumpWholePfn ( Address, Flags);
  567. return E_INVALIDARG;
  568. }
  569. if (Address >= PfnStart) {
  570. //
  571. // Ensure any passed in address is offsetted correctly.
  572. //
  573. Address = (Address - PfnStart) / PfnSize;
  574. }
  575. Pfn = (PfnStart + Address * PfnSize);
  576. PrintPfn64(Pfn);
  577. return S_OK;
  578. }
  579. VOID
  580. DumpTerminalServerMemory (
  581. VOID
  582. )
  583. {
  584. ULONG64 Next;
  585. ULONG64 SessionListPointer;
  586. ULONG64 SessionData;
  587. ULONG SessionId;
  588. ULONG SessionWsListLinksOffset;
  589. ULONG64 NonPagedPoolBytes;
  590. ULONG64 PagedPoolBytes;
  591. ULONG64 CommittedPages;
  592. ULONG Failures;
  593. ULONG TotalFailures;
  594. ULONG64 SessionPoolSize;
  595. ULONG64 SessionViewSize;
  596. dprintf("\n\tTerminal Server Memory Usage By Session:\n\n");
  597. // Get the offset of ActiveProcessLinks in _EPROCESS
  598. if (GetFieldOffset("nt!_MM_SESSION_SPACE", "WsListEntry", &SessionWsListLinksOffset)) {
  599. return;
  600. }
  601. SessionListPointer = GetExpression ("nt!MiSessionWsList");
  602. if (!SessionListPointer) {
  603. dprintf("Unable to get value of SessionListPointer\n");
  604. return;
  605. }
  606. if (GetFieldValue( SessionListPointer, "nt!_LIST_ENTRY", "Flink", Next )) {
  607. dprintf("Unable to read _LIST_ENTRY @ %p\n", SessionListPointer);
  608. return;
  609. }
  610. SessionPoolSize = GetUlongValue ("MmSessionPoolSize");
  611. SessionViewSize = GetUlongValue ("MmSessionViewSize");
  612. dprintf("\tSession Paged Pool Maximum is %ldK\n", SessionPoolSize / 1024);
  613. dprintf("\tSession View Space Maximum is %ldK\n", SessionViewSize / 1024);
  614. while(Next != SessionListPointer) {
  615. SessionData = Next - SessionWsListLinksOffset;
  616. if (GetFieldValue( SessionData, "nt!_MM_SESSION_SPACE", "SessionId", SessionId )) {
  617. dprintf("Unable to read _MM_SESSION_SPACE at %p\n",SessionData);
  618. return;
  619. }
  620. TotalFailures = 0;
  621. dprintf("\n\tSession ID %x @ %p:\n",SessionId, SessionData);
  622. GetFieldValue( SessionData, "nt!_MM_SESSION_SPACE", "NonPagedPoolBytes",
  623. NonPagedPoolBytes );
  624. GetFieldValue( SessionData, "nt!_MM_SESSION_SPACE", "PagedPoolBytes",
  625. PagedPoolBytes );
  626. GetFieldValue( SessionData, "nt!_MM_SESSION_SPACE", "CommittedPages",
  627. CommittedPages );
  628. GetFieldValue( SessionData, "nt!_MM_SESSION_SPACE", "SessionPoolAllocationFailures[0]",
  629. Failures);
  630. TotalFailures += Failures;
  631. GetFieldValue( SessionData, "nt!_MM_SESSION_SPACE", "SessionPoolAllocationFailures[1]",
  632. Failures);
  633. TotalFailures += Failures;
  634. GetFieldValue( SessionData, "nt!_MM_SESSION_SPACE", "SessionPoolAllocationFailures[2]",
  635. Failures);
  636. TotalFailures += Failures;
  637. GetFieldValue( SessionData, "nt!_MM_SESSION_SPACE", "SessionPoolAllocationFailures[3]",
  638. Failures);
  639. TotalFailures += Failures;
  640. dprintf("\tNonpaged Pool Usage: %8I64ldK\n",NonPagedPoolBytes / 1024);
  641. dprintf("\tPaged Pool Usage: %8I64ldK\n",PagedPoolBytes / 1024);
  642. if (TotalFailures != 0) {
  643. dprintf("\n\t*** %ld Pool Allocation Failures ***\n\n",TotalFailures);
  644. }
  645. dprintf("\tCommit Usage: %8I64ldK\n",CommittedPages * _KB);
  646. GetFieldValue(SessionData, "nt!_MM_SESSION_SPACE", "WsListEntry.Flink", Next);
  647. if (CheckControlC()) {
  648. return;
  649. }
  650. }
  651. return;
  652. }
  653. #if (_MSC_VER < 1200) && defined(_M_IX86)
  654. #pragma optimize("g", off)
  655. #endif
  656. DECLARE_API( vm )
  657. /*++
  658. Routine Description:
  659. Displays physical memory usage by driver.
  660. Arguments:
  661. arg - Flags : 0 (default) == systemwide vm & per-process output.
  662. 1 == just systemwide vm counts, no per-process output.
  663. 2 == systemwide vm, per-process & Mm thread output.
  664. 3 == systemwide vm & Mm thread display, no per-process output.
  665. Return Value:
  666. None.
  667. --*/
  668. {
  669. ULONG Flags;
  670. ULONG Index;
  671. ULONG64 MemorySize;
  672. ULONG64 CommitLimit;
  673. ULONG64 CommitTotal;
  674. ULONG64 SharedCommit;
  675. ULONG64 SpecialPoolPages;
  676. ULONG64 ProcessCommit;
  677. ULONG64 PagedPoolCommit;
  678. ULONG64 DriverCommit;
  679. ULONG64 ZeroPages;
  680. ULONG64 FreePages;
  681. ULONG64 StandbyPages;
  682. ULONG64 ModifiedPages;
  683. ULONG64 ModifiedNoWrite;
  684. ULONG64 NumberOfPagedPools;
  685. ULONG64 NumberOfPagingFiles;
  686. ULONG64 AvailablePages;
  687. ULONG64 LockPagesCount;
  688. ULONG64 SpecialPagesNonPaged;
  689. ULONG64 SpecialPagesNonPagedMaximum;
  690. ULONG64 FreePtesPointer;
  691. ULONG64 FreeNonPagedPtes;
  692. ULONG64 ResidentAvailablePages;
  693. ULONG64 PoolLoc;
  694. ULONG64 PoolLocBase;
  695. ULONG result;
  696. ULONG TotalPages;
  697. ULONG ExtendedCommit;
  698. ULONG64 TotalProcessCommit;
  699. PPROCESS_COMMIT_USAGE ProcessCommitUsage;
  700. ULONG i;
  701. ULONG NumberOfProcesses;
  702. ULONG64 PagedPoolBytesMax;
  703. ULONG64 PagedPoolBytes;
  704. ULONG64 NonPagedPoolBytesMax;
  705. ULONG64 NonPagedPoolBytes;
  706. ULONG64 PageFileBase;
  707. ULONG64 PageFilePointer;
  708. ULONG PageFileFullExtendPages;
  709. ULONG PageFileFullExtendCount;
  710. PUCHAR tempbuffer;
  711. UNICODE_STRING unicodeString;
  712. ULONG64 PagedPoolInfoPointer;
  713. ULONG64 FreeSystemPtes;
  714. UCHAR PagedPoolType[] = "nt!_MM_PAGED_POOL_INFO";
  715. ULONG64 AllocatedPagedPool=0;
  716. ULONG Desc_TotalPages=0, TotalBigPages=0, Desc_size;
  717. ULONG PtrSize = DBG_PTR_SIZE;
  718. ULONG NumberOfNonPagedPools;
  719. ULONG64 ExpNumberOfNonPagedPools;
  720. Flags = 0;
  721. Flags = (ULONG) GetExpression(args);
  722. dprintf("\n*** Virtual Memory Usage ***\n");
  723. MemorySize = GetNtDebuggerDataValue(MmNumberOfPhysicalPages);
  724. dprintf ("\tPhysical Memory: %8I64ld (%8I64ld Kb)\n",MemorySize,_KB*MemorySize);
  725. NumberOfPagingFiles = GetNtDebuggerDataValue(MmNumberOfPagingFiles);
  726. PageFilePointer = GetExpression ("nt!MmPagingFile");
  727. if (NumberOfPagingFiles == 0) {
  728. dprintf("\n************ NO PAGING FILE *********************\n\n");
  729. } else {
  730. for (i = 0; i < NumberOfPagingFiles; i++) {
  731. ULONG64 PageFileName_Buffer=0;
  732. if (!ReadPointer(PageFilePointer, &PageFileBase)) {
  733. dprintf("%08p: Unable to get page file\n",PageFilePointer);
  734. break;
  735. }
  736. if (GetFieldValue(PageFileBase,
  737. "nt!_MMPAGING_FILE",
  738. "PageFileName.Buffer",
  739. PageFileName_Buffer)) {
  740. dprintf("%08p: Unable to get page file\n",PageFilePointer);
  741. break;
  742. }
  743. InitTypeRead(PageFileBase, nt!_MMPAGING_FILE);
  744. if (PageFileName_Buffer == 0) {
  745. dprintf("\tNo Name for Paging File\n\n");
  746. } else {
  747. unicodeString.Length = (USHORT) ReadField(PageFileName.Length);
  748. tempbuffer = LocalAlloc(LPTR, unicodeString.Length);
  749. unicodeString.Buffer = (PWSTR)tempbuffer;
  750. unicodeString.MaximumLength = unicodeString.Length;
  751. if (!ReadMemory ( PageFileName_Buffer,
  752. tempbuffer,
  753. unicodeString.Length,
  754. &result)) {
  755. dprintf("\tPaging File Name paged out\n");
  756. } else {
  757. dprintf("\tPage File: %wZ\n", &unicodeString);
  758. }
  759. LocalFree(tempbuffer);
  760. }
  761. dprintf("\t Current: %9I64ldKb Free Space: %9I64ldKb\n",
  762. ReadField(Size)*_KB,
  763. ReadField(FreeSpace)*_KB);
  764. dprintf("\t Minimum: %9I64ldKb Maximum: %9I64ldKb\n",
  765. ReadField(MinimumSize)*_KB,
  766. ReadField(MaximumSize)*_KB);
  767. PageFilePointer += PtrSize;
  768. }
  769. }
  770. PagedPoolInfoPointer = GetExpression ("nt!MmPagedPoolInfo");
  771. if (GetFieldValue(PagedPoolInfoPointer,
  772. PagedPoolType,
  773. "AllocatedPagedPool",
  774. AllocatedPagedPool)) {
  775. dprintf("%08p: Unable to get paged pool info %p\n",PagedPoolInfoPointer);
  776. }
  777. PagedPoolBytesMax = GetNtDebuggerDataValue(MmSizeOfPagedPoolInBytes);
  778. PagedPoolBytes = AllocatedPagedPool;
  779. PagedPoolBytes *= PageSize;
  780. NonPagedPoolBytesMax = GetNtDebuggerDataValue(MmMaximumNonPagedPoolInBytes);
  781. NonPagedPoolBytes = GetUlongValue ("MmAllocatedNonPagedPool");
  782. NonPagedPoolBytes *= PageSize;
  783. CommitLimit = GetNtDebuggerDataValue(MmTotalCommitLimit);
  784. CommitTotal = GetNtDebuggerDataValue(MmTotalCommittedPages);
  785. SharedCommit = GetNtDebuggerDataValue(MmSharedCommit);
  786. DriverCommit = GetNtDebuggerDataValue(MmDriverCommit);
  787. ProcessCommit = GetNtDebuggerDataValue(MmProcessCommit);
  788. PagedPoolCommit = GetNtDebuggerDataValue(MmPagedPoolCommit);
  789. ZeroPages = GetNtDebuggerDataValue(MmZeroedPageListHead);
  790. FreePages = GetNtDebuggerDataValue(MmFreePageListHead);
  791. StandbyPages = GetNtDebuggerDataValue(MmStandbyPageListHead);
  792. ModifiedPages = GetNtDebuggerDataValue(MmModifiedPageListHead);
  793. ModifiedNoWrite = GetNtDebuggerDataValue(MmModifiedNoWritePageListHead);
  794. AvailablePages = GetNtDebuggerDataValue(MmAvailablePages);
  795. ResidentAvailablePages = GetNtDebuggerDataValue(MmResidentAvailablePages);
  796. if (BuildNo < 2257) {
  797. ExtendedCommit = GetUlongValue("MmExtendedCommit");
  798. PageFileFullExtendPages = GetUlongValue("MmPageFileFullExtendPages");
  799. PageFileFullExtendCount = GetUlongValue("MmPageFileFullExtendCount");
  800. }
  801. FreeSystemPtes = GetUlongValue("MmTotalFreeSystemPtes");
  802. LockPagesCount = GetUlongValue("MmSystemLockPagesCount");
  803. SpecialPagesNonPaged = GetUlongValue("MiSpecialPagesNonPaged");
  804. SpecialPagesNonPagedMaximum = GetUlongValue("MiSpecialPagesNonPagedMaximum");
  805. FreePtesPointer = GetExpression ("nt!MmTotalFreeSystemPtes");
  806. FreePtesPointer += sizeof(ULONG);
  807. FreeNonPagedPtes = 0;
  808. if (!ReadMemory (FreePtesPointer, &FreeNonPagedPtes, sizeof(ULONG), &result)) {
  809. dprintf("\tError reading free nonpaged PTEs %p\n", FreePtesPointer);
  810. }
  811. SpecialPoolPages = GetUlongValue("nt!MmSpecialPagesInUse");
  812. dprintf("\tAvailable Pages: %8I64ld (%8I64ld Kb)\n",AvailablePages, AvailablePages*_KB);
  813. dprintf("\tResAvail Pages: %8I64ld (%8I64ld Kb)\n",ResidentAvailablePages, ResidentAvailablePages*_KB);
  814. if ((LONG64) (ResidentAvailablePages - LockPagesCount) < 100) {
  815. dprintf("\n\t********** Running out of physical memory **********\n\n");
  816. }
  817. dprintf("\tLocked IO Pages: %8I64ld (%8I64ld Kb)\n",LockPagesCount,_KB*LockPagesCount);
  818. dprintf("\tFree System PTEs: %8I64ld (%8I64ld Kb)\n",FreeSystemPtes,_KB*FreeSystemPtes);
  819. dprintf("\tFree NP PTEs: %8I64ld (%8I64ld Kb)\n",FreeNonPagedPtes,_KB*FreeNonPagedPtes);
  820. dprintf("\tFree Special NP: %8I64ld (%8I64ld Kb)\n",
  821. (SpecialPagesNonPagedMaximum - SpecialPagesNonPaged),
  822. _KB*(SpecialPagesNonPagedMaximum - SpecialPagesNonPaged));
  823. dprintf("\tModified Pages: %8I64ld (%8I64ld Kb)\n",ModifiedPages,ModifiedPages*_KB);
  824. if ((AvailablePages < 50) && (ModifiedPages > 200)) {
  825. dprintf("\t********** High Number Of Modified Pages ********\n");
  826. }
  827. if (ModifiedNoWrite > ((MemorySize / 100) * 3)) {
  828. dprintf("\t********** High Number Of Modified No Write Pages ********\n");
  829. dprintf("\tModified No Write Pages: %I64ld (%8I64ld Kb)\n",
  830. ModifiedNoWrite,_KB*ModifiedNoWrite);
  831. }
  832. //
  833. // Dump all the nonpaged pools.
  834. //
  835. PoolLoc = GetNtDebuggerData(NonPagedPoolDescriptor );
  836. Desc_TotalPages = 0; TotalBigPages=0;
  837. if ( !PoolLoc ||
  838. GetFieldValue(PoolLoc,
  839. "nt!_POOL_DESCRIPTOR",
  840. "TotalPages",
  841. Desc_TotalPages)) {
  842. dprintf("%08p: Unable to get pool descriptor\n",PoolLoc);
  843. return E_INVALIDARG;
  844. }
  845. Desc_size = GetTypeSize("nt!_POOL_DESCRIPTOR");
  846. if (ExpNumberOfNonPagedPools = GetExpression("nt!ExpNumberOfNonPagedPools")) {
  847. NumberOfNonPagedPools = GetUlongFromAddress (ExpNumberOfNonPagedPools);
  848. } else {
  849. NumberOfNonPagedPools = 0;
  850. }
  851. if (NumberOfNonPagedPools > 1) {
  852. TotalPages = 0;
  853. PoolLocBase = GetExpression ("nt!ExpNonPagedPoolDescriptor");
  854. if (PoolLocBase != 0) {
  855. for (Index = 0; Index < NumberOfNonPagedPools; Index += 1) {
  856. if (!ReadPointer(PoolLocBase, &PoolLoc)) {
  857. dprintf("%08p: Unable to get nonpaged pool info\n",PoolLocBase);
  858. break;
  859. }
  860. if (GetFieldValue(PoolLoc,
  861. "nt!_POOL_DESCRIPTOR",
  862. "TotalPages",
  863. Desc_TotalPages)) {
  864. dprintf("%08p: Unable to get pool descriptor\n",PoolLoc);
  865. return E_INVALIDARG;
  866. }
  867. GetFieldValue(PoolLoc,"_POOL_DESCRIPTOR","TotalBigPages",TotalBigPages);
  868. dprintf("\tNonPagedPool %1ld Used: %5ld (%8ld Kb)\n",
  869. Index,
  870. Desc_TotalPages + TotalBigPages,
  871. _KB*(Desc_TotalPages + TotalBigPages));
  872. TotalPages += Desc_TotalPages + TotalBigPages;
  873. PoolLocBase += PtrSize;
  874. }
  875. }
  876. }
  877. GetFieldValue(PoolLoc,"nt!_POOL_DESCRIPTOR","TotalBigPages",TotalBigPages);
  878. if (NumberOfNonPagedPools > 1) {
  879. dprintf("\tNonPagedPool Usage: %5ld (%8ld Kb)\n", TotalPages,_KB*TotalPages);
  880. }
  881. else {
  882. dprintf("\tNonPagedPool Usage: %5ld (%8ld Kb)\n", Desc_TotalPages + TotalBigPages,
  883. _KB*(Desc_TotalPages + TotalBigPages));
  884. }
  885. dprintf("\tNonPagedPool Max: %5I64ld (%8I64ld Kb)\n", NonPagedPoolBytesMax/PageSize,_KB*(NonPagedPoolBytesMax/PageSize));
  886. if ((Desc_TotalPages + TotalBigPages) > 4 * ((NonPagedPoolBytesMax / PageSize) / 5)) {
  887. dprintf("\t********** Excessive NonPaged Pool Usage *****\n");
  888. }
  889. //
  890. // Dump all the paged pools.
  891. //
  892. NumberOfPagedPools = GetNtDebuggerDataValue(ExpNumberOfPagedPools);
  893. TotalPages = 0;
  894. PoolLocBase = GetExpression ("nt!ExpPagedPoolDescriptor");
  895. if ((PoolLocBase != 0) && (NumberOfPagedPools != 0)) {
  896. for (Index = 0; (Index < (NumberOfPagedPools + 1)) ; Index += 1) {
  897. if (Index && (BuildNo <= 2464)) {
  898. PoolLoc += Desc_size;
  899. } else {
  900. if (!ReadPointer(PoolLocBase, &PoolLoc)) {
  901. dprintf("%08p: Unable to get paged pool info\n",PoolLocBase);
  902. break;
  903. }
  904. }
  905. if (GetFieldValue(PoolLoc,
  906. "nt!_POOL_DESCRIPTOR",
  907. "TotalPages",
  908. Desc_TotalPages)) {
  909. dprintf("%08p: Unable to get pool descriptor, PagedPool usage may be wrong\n",PoolLoc);
  910. break;
  911. }
  912. GetFieldValue(PoolLoc,"nt!_POOL_DESCRIPTOR","TotalBigPages",TotalBigPages);
  913. dprintf("\tPagedPool %1ld Usage: %5ld (%8ld Kb)\n",
  914. Index,
  915. Desc_TotalPages + TotalBigPages,
  916. _KB*(Desc_TotalPages + TotalBigPages));
  917. TotalPages += Desc_TotalPages + TotalBigPages;
  918. PoolLocBase += PtrSize;
  919. }
  920. }
  921. if (PagedPoolBytes > 95 * (PagedPoolBytesMax/ 100)) {
  922. dprintf("\t********** Excessive Paged Pool Usage *****\n");
  923. }
  924. dprintf("\tPagedPool Usage: %5ld (%8ld Kb)\n", TotalPages,_KB*TotalPages);
  925. dprintf("\tPagedPool Maximum: %5I64ld (%8I64ld Kb)\n", PagedPoolBytesMax/PageSize,_KB*(PagedPoolBytesMax/PageSize));
  926. dprintf("\tShared Commit: %8I64ld (%8I64ld Kb)\n",SharedCommit,_KB*SharedCommit );
  927. dprintf("\tSpecial Pool: %8I64ld (%8I64ld Kb)\n",SpecialPoolPages,_KB*SpecialPoolPages );
  928. dprintf("\tShared Process: %8I64ld (%8I64ld Kb)\n",ProcessCommit,_KB*ProcessCommit );
  929. dprintf("\tPagedPool Commit: %8I64ld (%8I64ld Kb)\n",PagedPoolCommit,_KB*PagedPoolCommit);
  930. dprintf("\tDriver Commit: %8I64ld (%8I64ld Kb)\n",DriverCommit, _KB*DriverCommit );
  931. dprintf("\tCommitted pages: %8I64ld (%8I64ld Kb)\n",CommitTotal, _KB*CommitTotal );
  932. dprintf("\tCommit limit: %8I64ld (%8I64ld Kb)\n",CommitLimit, _KB*CommitLimit );
  933. if ((CommitTotal + 100) > CommitLimit) {
  934. dprintf("\n\t********** Number of committed pages is near limit ********\n");
  935. }
  936. if (BuildNo < 2257) {
  937. if (ExtendedCommit != 0) {
  938. dprintf("\n\t********** Commit has been extended with VM popup ********\n");
  939. dprintf("\tExtended by: %8ld (%8ld Kb)\n", ExtendedCommit,_KB*ExtendedCommit);
  940. }
  941. if (PageFileFullExtendCount) {
  942. if (PageFileFullExtendCount == 1) {
  943. dprintf("\n\t****** ALL PAGING FILE BECAME FULL ONCE - COMMITMENT ADJUSTED ****\n", PageFileFullExtendCount);
  944. }
  945. else {
  946. dprintf("\n\t****** ALL PAGING FILE BECAME FULL (%u times) - COMMITMENT ADJUSTED ****\n", PageFileFullExtendCount);
  947. }
  948. dprintf("\tCurrent adjust: %8ld (%8ld Kb)\n",
  949. PageFileFullExtendPages,
  950. _KB*PageFileFullExtendPages);
  951. }
  952. }
  953. dprintf("\n");
  954. if ((Flags & 0x1) == 0) {
  955. ProcessCommitUsage = GetProcessCommit( &TotalProcessCommit, &NumberOfProcesses );
  956. if (ProcessCommitUsage == NULL)
  957. {
  958. dprintf("\nProcessCommitUsage could not be calculated\n");
  959. }
  960. else
  961. {
  962. if (TotalProcessCommit != 0) {
  963. dprintf("\tTotal Private: %8I64ld (%8I64ld Kb)\n",
  964. TotalProcessCommit,_KB*TotalProcessCommit);
  965. }
  966. for (i=0; i<NumberOfProcesses; i++) {
  967. dprintf( " %04I64lx %-15s %6I64d (%8I64ld Kb)\n",
  968. ProcessCommitUsage[i].ClientId,
  969. ProcessCommitUsage[i].ImageFileName,
  970. ProcessCommitUsage[i].CommitCharge,
  971. _KB*(ProcessCommitUsage[i].CommitCharge)
  972. );
  973. }
  974. HeapFree(GetProcessHeap(), 0, ProcessCommitUsage);
  975. }
  976. }
  977. if (Flags & 0x2) {
  978. if (Client &&
  979. (ExtQuery(Client) == S_OK)) {
  980. dprintf("\n\tMemory Management Thread Stacks:\n");
  981. DumpMmThreads ();
  982. ExtRelease();
  983. }
  984. }
  985. if (Flags & 0x4) {
  986. if (Client &&
  987. (ExtQuery(Client) == S_OK)) {
  988. DumpTerminalServerMemory ();
  989. ExtRelease();
  990. }
  991. }
  992. return S_OK;
  993. }
  994. #if (_MSC_VER < 1200) && defined(_M_IX86)
  995. #pragma optimize("", on)
  996. #endif
  997. VOID
  998. DumpWholePfn(
  999. IN ULONG64 Address,
  1000. IN ULONG Flags
  1001. )
  1002. /*++
  1003. Routine Description:
  1004. Dumps the PFN database
  1005. Arguments:
  1006. Address - address to dump at
  1007. Flags -
  1008. Return Value:
  1009. None.
  1010. --*/
  1011. {
  1012. ULONG result;
  1013. ULONG64 HighPage;
  1014. ULONG64 LowPage;
  1015. ULONG64 PageCount;
  1016. ULONG64 ReadCount;
  1017. ULONG64 i;
  1018. ULONG64 Pfn;
  1019. ULONG64 PfnStart;
  1020. PUCHAR PfnArray;
  1021. PUCHAR PfnArrayPointer;
  1022. ULONG64 VirtualAddress;
  1023. ULONG MatchLocation;
  1024. BOOLEAN foundlink;
  1025. BOOLEAN RandomAccessRequired;
  1026. ULONG PfnSize;
  1027. ULONG NumberOfPfnToRead;
  1028. ULONG sz;
  1029. MMPFNENTRY u3_e1;
  1030. CHAR InPageError;
  1031. LowPage = GetNtDebuggerDataValue(MmLowestPhysicalPage);
  1032. HighPage = GetNtDebuggerDataValue(MmHighestPhysicalPage);
  1033. PfnStart = GetNtDebuggerDataPtrValue(MmPfnDatabase);
  1034. PfnSize = GetTypeSize("nt!_MMPFN");
  1035. //
  1036. // Read sufficient pages such that htere isn't lot of wait
  1037. // before first page dump.
  1038. //
  1039. NumberOfPfnToRead = 2000;
  1040. PfnArray = NULL;
  1041. if (Flags == 7) {
  1042. RandomAccessRequired = TRUE;
  1043. }
  1044. else {
  1045. RandomAccessRequired = FALSE;
  1046. }
  1047. if (RandomAccessRequired == FALSE) {
  1048. dprintf("\n Page Flink Blk/Shr Ref V PTE Address SavedPTE Frame State\n");
  1049. }
  1050. //
  1051. // If asked to dump the whole database or we're going to need the ability
  1052. // to look up random frames, then read in the whole database now.
  1053. //
  1054. if (Address == 0 || RandomAccessRequired == TRUE) {
  1055. PfnArray = LocalAlloc(LPTR, (ULONG) (HighPage+1) * PfnSize);
  1056. if (!PfnArray) {
  1057. dprintf("unable to get allocate %ld bytes of memory\n",
  1058. (HighPage+1) * PfnSize);
  1059. return;
  1060. }
  1061. for (PageCount = LowPage;
  1062. PageCount <= HighPage;
  1063. PageCount += NumberOfPfnToRead) {
  1064. if (CheckControlC()) {
  1065. goto alldone;
  1066. }
  1067. ReadCount = HighPage - PageCount > NumberOfPfnToRead ?
  1068. NumberOfPfnToRead :
  1069. HighPage - PageCount + 1;
  1070. ReadCount *= PfnSize;
  1071. Pfn = (PfnStart + PageCount * PfnSize);
  1072. PfnArrayPointer = (PUCHAR)(PfnArray + (ULONG) PageCount * PfnSize);
  1073. //
  1074. // KD caches the Pfns
  1075. //
  1076. if ((!ReadMemory(Pfn,
  1077. PfnArrayPointer,
  1078. (ULONG) ReadCount,
  1079. &result)) || (result < (ULONG) ReadCount)) {
  1080. dprintf("unable to get PFN table block - "
  1081. "address %p - count %I64u - page %I64lu\n",
  1082. Pfn, ReadCount, PageCount);
  1083. goto alldone;
  1084. }
  1085. for (i = PageCount;
  1086. (i < PageCount + NumberOfPfnToRead) && (i < HighPage);
  1087. i += 1, Pfn = (Pfn + PfnSize)) {
  1088. ULONG u3_e2_ReferenceCount=0;
  1089. ULONG64 u1_Flink=0, u2_Blink=0, PteAddress=0, OriginalPte=0, PteFrame=0;
  1090. if (RandomAccessRequired == TRUE) {
  1091. if ((i % 256 ) == 0) {
  1092. dprintf("."); // every 256 pages, print a dot
  1093. }
  1094. }
  1095. else {
  1096. GetFieldValue(Pfn, "nt!_MMPFN", "u1.Flink", u1_Flink);
  1097. GetFieldValue(Pfn, "nt!_MMPFN", "u2.Blink", u2_Blink);
  1098. GetFieldValue(Pfn, "nt!_MMPFN", "PteAddress",PteAddress);
  1099. GetFieldValue(Pfn, "nt!_MMPFN", "OriginalPte",OriginalPte);
  1100. GetFieldValue(Pfn, "nt!_MMPFN", "u3.e2.ReferenceCount", u3_e2_ReferenceCount);
  1101. GetFieldValue(Pfn, "nt!_MMPFN", "u3.e1", u3_e1);
  1102. if (GetFieldValue(Pfn, "nt!_MMPFN", "u4.PteFrame", PteFrame) == FIELDS_DID_NOT_MATCH) {
  1103. GetFieldValue(Pfn, "nt!_MMPFN", "u3.e1.InPageError", InPageError);
  1104. GetFieldValue(Pfn, "nt!_MMPFN", "PteFrame", PteFrame);
  1105. } else {
  1106. GetFieldValue(Pfn, "nt!_MMPFN", "u4.InPageError", InPageError);
  1107. }
  1108. if (u3_e1.PrototypePte == 0) {
  1109. VirtualAddress = DbgGetVirtualAddressMappedByPte(PteAddress);
  1110. } else {
  1111. VirtualAddress = 0;
  1112. }
  1113. dprintf("%5I64lx %8p %8p%6x %8p %8p ",
  1114. i,
  1115. u1_Flink,
  1116. u2_Blink,
  1117. u3_e2_ReferenceCount,
  1118. PteAddress,
  1119. VirtualAddress);
  1120. dprintf("%8p ", OriginalPte);
  1121. dprintf("%6I64lx ", PteFrame);
  1122. dprintf("%s %c%c%c%c%c%c\n",
  1123. PageLocationList[u3_e1.PageLocation],
  1124. u3_e1.Modified ? 'M':' ',
  1125. u3_e1.PrototypePte ? 'P':' ',
  1126. u3_e1.ReadInProgress ? 'R':' ',
  1127. u3_e1.WriteInProgress ? 'W':' ',
  1128. InPageError ? 'E':' ',
  1129. u3_e1.ParityError ? 'X':' '
  1130. );
  1131. }
  1132. if (CheckControlC()) {
  1133. goto alldone;
  1134. }
  1135. }
  1136. }
  1137. if (RandomAccessRequired == TRUE) {
  1138. dprintf("\n");
  1139. }
  1140. else {
  1141. goto alldone;
  1142. }
  1143. }
  1144. dprintf("\n Page Flink Blk/Shr Ref V PTE Address SavedPTE Frame State\n");
  1145. Pfn = (PfnStart + Address * PfnSize);
  1146. if (GetFieldValue(Pfn, "nt!_MMPFN", "u3.e1", u3_e1)) {
  1147. dprintf("unable to get PFN element\n");
  1148. goto alldone;
  1149. }
  1150. MatchLocation = u3_e1.PageLocation;
  1151. do {
  1152. ULONG u3_e2_ReferenceCount=0;
  1153. ULONG64 u1_Flink=0, u2_Blink=0, PteAddress=0, OriginalPte=0, PteFrame=0;
  1154. if (CheckControlC()) {
  1155. goto alldone;
  1156. }
  1157. Pfn = (PfnStart + Address * PfnSize);
  1158. sz = sizeof (u3_e1);
  1159. GetFieldValue(Pfn, "nt!_MMPFN", "u3.e1", u3_e1);
  1160. if (u3_e1.PrototypePte == 0) {
  1161. VirtualAddress = DbgGetVirtualAddressMappedByPte ( PteAddress);
  1162. } else {
  1163. VirtualAddress = 0;
  1164. }
  1165. if (u3_e1.PageLocation == MatchLocation) {
  1166. GetFieldValue(Pfn, "nt!_MMPFN", "u1.Flink", u1_Flink);
  1167. GetFieldValue(Pfn, "nt!_MMPFN", "u2.Blink", u2_Blink);
  1168. GetFieldValue(Pfn, "nt!_MMPFN", "PteAddress", PteAddress);
  1169. GetFieldValue(Pfn, "nt!_MMPFN", "OriginalPte",OriginalPte);
  1170. GetFieldValue(Pfn, "nt!_MMPFN", "u3.e2.ReferenceCount", u3_e2_ReferenceCount);
  1171. if(GetFieldValue(Pfn, "nt!_MMPFN", "u4.PteFrame", PteFrame) == FIELDS_DID_NOT_MATCH) {
  1172. GetFieldValue(Pfn, "nt!_MMPFN", "u3.e1.InPageError", InPageError);
  1173. GetFieldValue(Pfn, "nt!_MMPFN", "PteFrame", PteFrame);
  1174. } else {
  1175. GetFieldValue(Pfn, "nt!_MMPFN", "u4.InPageError", InPageError);
  1176. }
  1177. dprintf("%5I64lx %8p %8p%6x %8p %8p ",
  1178. Address,
  1179. u1_Flink,
  1180. u2_Blink,
  1181. u3_e2_ReferenceCount,
  1182. PteAddress,
  1183. VirtualAddress);
  1184. dprintf("%8p ", OriginalPte);
  1185. dprintf("%6I64lx ", PteFrame);
  1186. dprintf("%s %c%c%c%c%c%c\n",
  1187. PageLocationList[u3_e1.PageLocation],
  1188. u3_e1.Modified ? 'M':' ',
  1189. u3_e1.PrototypePte ? 'P':' ',
  1190. u3_e1.ReadInProgress ? 'R':' ',
  1191. u3_e1.WriteInProgress ? 'W':' ',
  1192. InPageError ? 'E':' ',
  1193. u3_e1.ParityError ? 'X':' '
  1194. );
  1195. }
  1196. if (MatchLocation > 5) {
  1197. Address += 1;
  1198. } else {
  1199. ULONG64 OriginalPte_u_Long=0;
  1200. sz = sizeof (OriginalPte_u_Long);
  1201. if (Flags == 7) {
  1202. ULONG64 P;
  1203. //
  1204. // Search the whole database for an OriginalPte field that
  1205. // points to this PFN - we must do this because this chain
  1206. // is singly (not doubly) linked.
  1207. //
  1208. foundlink = FALSE;
  1209. P = PfnStart;
  1210. for (i = 0; i <= HighPage; i += 1, P += PfnSize) {
  1211. GetFieldValue(P, "nt!_MMPFN", "OriginalPte.u.Long", OriginalPte_u_Long);
  1212. if (OriginalPte_u_Long == Address) {
  1213. Address = i;
  1214. foundlink = TRUE;
  1215. break;
  1216. }
  1217. }
  1218. if (foundlink == FALSE) {
  1219. dprintf("No OriginalPte chain found for %lx\n", Address);
  1220. break;
  1221. }
  1222. } else if (Flags == 5) {
  1223. GetFieldValue(Pfn, "nt!_MMPFN", "OriginalPte.u.Long", OriginalPte_u_Long);
  1224. Address = OriginalPte_u_Long;
  1225. } else if (Flags == 3) {
  1226. Address = u2_Blink;
  1227. } else {
  1228. Address = u1_Flink;
  1229. }
  1230. }
  1231. if (CheckControlC()) {
  1232. goto alldone;
  1233. }
  1234. } while (Address < HighPage);
  1235. alldone:
  1236. if (PfnArray) {
  1237. LocalFree((void *)PfnArray);
  1238. }
  1239. }
  1240. VOID
  1241. PrintPfn64 (
  1242. IN ULONG64 PfnAddress
  1243. )
  1244. {
  1245. MMPFNENTRY u3_e1;
  1246. ULONG64 PfnDb, PfnStart;
  1247. ULONG PfnSize;
  1248. ULONG CacheAttribute;
  1249. CHAR InPageError, VerifierAllocation;
  1250. if ((PfnSize = GetTypeSize("nt!_MMPFN")) == 0) {
  1251. dprintf("Type _MMPFN not found.\n");
  1252. return;
  1253. }
  1254. PfnDb = GetNtDebuggerData(MmPfnDatabase);
  1255. if (!ReadPointer(PfnDb, &PfnStart)) {
  1256. dprintf("%08P: Unable to get PFN database start\n",PfnDb);
  1257. return;
  1258. }
  1259. if (!IsPtr64()) {
  1260. PfnAddress = (ULONG64) (LONG64) (LONG) PfnAddress;
  1261. }
  1262. dprintf(" PFN %08P at address %08P\n",
  1263. (PfnAddress - PfnStart) / PfnSize,
  1264. PfnAddress);
  1265. InitTypeRead(PfnAddress, nt!_MMPFN);
  1266. dprintf(" flink %08P", ReadField(u1.Flink));
  1267. dprintf(" blink / share count %08P", ReadField(u2.Blink));
  1268. dprintf(" pteaddress %08P\n", ReadField(PteAddress));
  1269. GetFieldValue(PfnAddress, "nt!_MMPFN", "u3.e1", u3_e1);
  1270. switch (TargetMachine) {
  1271. case IMAGE_FILE_MACHINE_IA64:
  1272. case IMAGE_FILE_MACHINE_AMD64:
  1273. dprintf(" reference count %04hX used entry count %04hX %s color %01hX\n",
  1274. (ULONG) ReadField(u3.e2.ReferenceCount),
  1275. (ULONG) ReadField(UsedPageTableEntries),
  1276. PageAttribute[u3_e1.CacheAttribute],
  1277. u3_e1.PageColor);
  1278. break;
  1279. default:
  1280. dprintf(" reference count %04hX %s color %01hX\n",
  1281. (ULONG) ReadField(u3.e2.ReferenceCount),
  1282. PageAttribute[u3_e1.CacheAttribute],
  1283. u3_e1.PageColor);
  1284. break;
  1285. }
  1286. dprintf(" restore pte %08I64X ", ReadField(OriginalPte));
  1287. if (BuildNo < 2440) {
  1288. dprintf("containing page %06P ", ReadField(PteFrame));
  1289. InPageError = (CHAR) ReadField(u3.e1.InPageError);
  1290. VerifierAllocation = (CHAR) ReadField(u3.e1.VerifierAllocation);
  1291. } else {
  1292. dprintf("containing page %06P ", ReadField(u4.PteFrame));
  1293. InPageError = (CHAR) ReadField(u4.InPageError);
  1294. VerifierAllocation = (CHAR) ReadField(u4.VerifierAllocation);
  1295. }
  1296. dprintf("%s %c%c%c%c%c%c\n",
  1297. PageLocationList[u3_e1.PageLocation],
  1298. u3_e1.Modified ? 'M':' ',
  1299. u3_e1.PrototypePte ? 'P':' ',
  1300. u3_e1.ReadInProgress ? 'R':' ',
  1301. u3_e1.WriteInProgress ? 'W':' ',
  1302. InPageError ? 'E':' ',
  1303. u3_e1.ParityError ? 'X':' ',
  1304. u3_e1.RemovalRequested ? 'Y':' ',
  1305. VerifierAllocation ? 'V':' '
  1306. );
  1307. dprintf(" %s %s %s %s %s %s\n",
  1308. u3_e1.Modified ? "Modified":" ",
  1309. u3_e1.PrototypePte ? "Shared":" ",
  1310. u3_e1.ReadInProgress ? "ReadInProgress":" ",
  1311. u3_e1.WriteInProgress ? "WriteInProgress":" ",
  1312. InPageError ? "InPageError":" ",
  1313. u3_e1.ParityError ? "ParityError":" ",
  1314. u3_e1.RemovalRequested ? "RemovalRequested":" ",
  1315. VerifierAllocation ? "VerifierAllocation":" ");
  1316. return;
  1317. }
  1318. VOID
  1319. MemoryUsage (
  1320. IN ULONG64 PfnStart,
  1321. IN ULONG64 LowPage,
  1322. IN ULONG64 HighPage,
  1323. IN ULONG IgnoreInvalidFrames
  1324. )
  1325. /*++
  1326. Routine Description:
  1327. This routine (debugging only) dumps the current memory usage by
  1328. walking the PFN database.
  1329. Arguments:
  1330. None.
  1331. Return Value:
  1332. None.
  1333. --*/
  1334. {
  1335. ULONG PfnSize;
  1336. ULONG64 LastPfn;
  1337. ULONG64 Pfn1;
  1338. ULONG64 Pfn2;
  1339. ULONG64 Subsection1;
  1340. UNICODE_STRING NameString;
  1341. PPFN_INFO Info;
  1342. PPFN_INFO Info1;
  1343. PPFN_INFO InfoStart;
  1344. PPFN_INFO InfoEnd;
  1345. ULONG InfoSize;
  1346. PFN_INFO ProcessPfns;
  1347. PFN_INFO PagedPoolBlock;
  1348. PPFN_INFO LastProcessInfo = &ProcessPfns;
  1349. ULONG64 Master;
  1350. ULONG64 ControlArea1;
  1351. BOOLEAN Found;
  1352. ULONG result;
  1353. ULONG i;
  1354. ULONG64 PagedPoolStart;
  1355. ULONG64 VirtualAddress;
  1356. ULONG64 MmNonPagedPoolEnd;
  1357. ULONG64 PteFrame;
  1358. ULONG OriginalPteOffset;
  1359. ULONG PercentComplete=0;
  1360. PKERN_MAP pKernelMap;
  1361. // Get the offset of OriginalPte in MMPFN
  1362. if (GetFieldOffset("nt!_MMPFN", "OriginalPte", &OriginalPteOffset)) {
  1363. dprintf("Cannot find _MMPFN type");
  1364. return ;
  1365. }
  1366. ProcessPfns.Next = NULL;
  1367. MmNonPagedPoolEnd = GetNtDebuggerDataPtrValue(MmNonPagedPoolEnd);
  1368. NameString.MaximumLength = sizeof(WCHAR) * 1000;
  1369. NameString.Buffer = calloc(1, NameString.MaximumLength);
  1370. if (!NameString.Buffer) {
  1371. return;
  1372. }
  1373. PagedPoolStart = GetNtDebuggerDataPtrValue(MmPagedPoolStart);
  1374. pKernelMap = calloc(1, sizeof(*pKernelMap));
  1375. if (!pKernelMap) {
  1376. free(NameString.Buffer);
  1377. return;
  1378. }
  1379. dprintf (" Building kernel map\n");
  1380. if (BuildKernelMap (pKernelMap) == FALSE) {
  1381. free(pKernelMap);
  1382. free(NameString.Buffer);
  1383. return;
  1384. }
  1385. dprintf (" Finished building kernel map\n");
  1386. RtlZeroMemory (&PagedPoolBlock, sizeof (PFN_INFO));
  1387. PfnSize = GetTypeSize("nt!_MMPFN");
  1388. LastPfn = (PfnStart + HighPage * PfnSize);
  1389. if (MmSubsectionBase == 0) {
  1390. MmSubsectionBase = GetNtDebuggerDataValue(MmSubsectionBase);
  1391. }
  1392. //
  1393. // Allocate a chunk of memory to hold PFN information. This is resized
  1394. // if it is later determined that the current size is not large enough.
  1395. //
  1396. InfoSize = USAGE_ALLOC_SIZE;
  1397. restart:
  1398. InfoStart = VirtualAlloc (NULL,
  1399. InfoSize,
  1400. MEM_COMMIT,
  1401. PAGE_READWRITE);
  1402. if (InfoStart == NULL) {
  1403. dprintf ("heap allocation for %d bytes failed\n", InfoSize);
  1404. free(pKernelMap);
  1405. free(NameString.Buffer);
  1406. return;
  1407. }
  1408. InfoEnd = InfoStart;
  1409. Pfn1 = (PfnStart + LowPage * PfnSize);
  1410. while (Pfn1 < LastPfn) {
  1411. ULONG PageLocation=0, PrototypePte=0, ReferenceCount=0;
  1412. ULONG Comp;
  1413. ULONG64 ShareCount=0, PteFrame1=0, PteAddress;
  1414. Comp = ((ULONG) (Pfn1 - (PfnStart + LowPage * PfnSize)))*100 /
  1415. ((ULONG) (LastPfn -(PfnStart + LowPage * PfnSize)));
  1416. if (Comp > PercentComplete) {
  1417. PercentComplete = Comp;
  1418. dprintf("Scanning PFN database - (%02d%% complete) \r", PercentComplete);
  1419. }
  1420. if (CheckControlC()) {
  1421. VirtualFree (InfoStart,0,MEM_RELEASE);
  1422. free(pKernelMap);
  1423. free(NameString.Buffer);
  1424. return;
  1425. }
  1426. GetFieldValue(Pfn1, "nt!_MMPFN", "u3.e1.PageLocation", PageLocation);
  1427. if ((PageLocation != FreePageList) &&
  1428. (PageLocation != ZeroedPageList) &&
  1429. (PageLocation != BadPageList)) {
  1430. GetFieldValue(Pfn1, "nt!_MMPFN", "u3.e1.PrototypePte", PrototypePte);
  1431. GetFieldValue(Pfn1, "nt!_MMPFN", "u3.e2.ReferenceCount", ReferenceCount);
  1432. GetFieldValue(Pfn1, "nt!_MMPFN", "u2.ShareCount", ShareCount);
  1433. GetFieldValue(Pfn1, "nt!_MMPFN", "PteAddress", PteAddress);
  1434. if (GetFieldValue(Pfn1, "nt!_MMPFN", "u4.PteFrame", PteFrame1) == FIELDS_DID_NOT_MATCH) {
  1435. GetFieldValue(Pfn1, "nt!_MMPFN", "PteFrame", PteFrame1);
  1436. }
  1437. Subsection1 = 0;
  1438. if (PrototypePte) {
  1439. Subsection1 = DbgGetSubsectionAddress (Pfn1 + OriginalPteOffset);
  1440. }
  1441. if ((Subsection1) && (Subsection1 < 0xffffffffffbff000UI64)) {
  1442. Master = Subsection1;
  1443. } else {
  1444. PteFrame = PteFrame1;
  1445. if (IgnoreInvalidFrames) {
  1446. Master = PteFrame;
  1447. } else {
  1448. // dprintf("Pteaddr %p, PagedPoolStart %I64x ", PteAddress, PagedPoolStart);
  1449. if (PteAddress > PagedPoolStart) {
  1450. Master = PteFrame;
  1451. } else {
  1452. Master=0;
  1453. Pfn2 = PfnStart + PteFrame*PfnSize;
  1454. if (GetFieldValue(Pfn2, "nt!_MMPFN", "PteFrame", Master) == FIELDS_DID_NOT_MATCH) {
  1455. GetFieldValue(Pfn2, "nt!_MMPFN", "u4.PteFrame", Master);
  1456. }
  1457. // Master = MI_PFN_PTE FRAME(Pfn2);
  1458. if ((Master == 0) || (Master > HighPage)) {
  1459. dprintf("Invalid PTE frame\n");
  1460. // PrintPfn((PVOID)(((PCHAR)Pfn1-(PCHAR)PfnStart)/PfnSize),Pfn1);
  1461. PrintPfn64(Pfn1);
  1462. PrintPfn64(Pfn2);
  1463. dprintf(" subsection address: %p\n",Subsection1);
  1464. goto NextPfn;
  1465. }
  1466. }
  1467. }
  1468. }
  1469. //
  1470. // Tally any pages which are not protos and have a valid PTE
  1471. // address field.
  1472. //
  1473. if ((PteAddress < PagedPoolStart) && (PteAddress >= DbgGetPteAddress(SystemRangeStart) )) {
  1474. for (i=0; i<pKernelMap->Count; i++) {
  1475. VirtualAddress = DbgGetVirtualAddressMappedByPte (PteAddress);
  1476. if ((VirtualAddress >= pKernelMap->Item[i].StartVa) &&
  1477. (VirtualAddress < pKernelMap->Item[i].EndVa)) {
  1478. if ((PageLocation == ModifiedPageList) ||
  1479. (PageLocation == ModifiedNoWritePageList)) {
  1480. pKernelMap->Item[i].ModifiedCount += _KB;
  1481. if (ReferenceCount > 0) {
  1482. pKernelMap->Item[i].LockedCount += _KB;
  1483. }
  1484. } else if ((PageLocation == StandbyPageList) ||
  1485. (PageLocation == TransitionPage)) {
  1486. pKernelMap->Item[i].StandbyCount += _KB;
  1487. if (ReferenceCount > 0) {
  1488. pKernelMap->Item[i].LockedCount += _KB;
  1489. }
  1490. } else {
  1491. pKernelMap->Item[i].ValidCount += _KB;
  1492. if (ShareCount > 1) {
  1493. pKernelMap->Item[i].SharedCount += _KB;
  1494. if (ReferenceCount > 1) {
  1495. pKernelMap->Item[i].LockedCount += _KB;
  1496. }
  1497. }
  1498. }
  1499. goto NextPfn;
  1500. }
  1501. }
  1502. }
  1503. if (PteAddress >= 0xFFFFFFFFF0000000UI64) {
  1504. //
  1505. // This is paged pool, put it in the paged pool cell.
  1506. //
  1507. Info = &PagedPoolBlock;
  1508. Found = TRUE;
  1509. } else {
  1510. //
  1511. // See if there is already a master info block.
  1512. //
  1513. Info = InfoStart;
  1514. Found = FALSE;
  1515. while (Info < InfoEnd) {
  1516. if (Info->Master == Master) {
  1517. Found = TRUE;
  1518. break;
  1519. }
  1520. Info += 1;
  1521. }
  1522. }
  1523. if (!Found) {
  1524. Info = InfoEnd;
  1525. InfoEnd += 1;
  1526. if ((PUCHAR)Info >= ((PUCHAR)InfoStart + InfoSize) - sizeof(PFN_INFO)) {
  1527. //
  1528. // Don't bother copying the old array - free it instead to
  1529. // improve our chances of getting a bigger contiguous chunk.
  1530. //
  1531. VirtualFree (InfoStart,0,MEM_RELEASE);
  1532. InfoSize += USAGE_ALLOC_SIZE;
  1533. goto restart;
  1534. }
  1535. RtlZeroMemory (Info, sizeof (PFN_INFO));
  1536. Info->Master = Master;
  1537. GetFieldValue(Pfn1, "nt!_MMPFN", "OriginalPte.u.Long", Info->OriginalPte);
  1538. }
  1539. // dprintf("Pfn1 %p, PageLoc %x, Master %I64x\n", Pfn1, PageLocation, Master);
  1540. if ((PageLocation == ModifiedPageList) ||
  1541. (PageLocation == ModifiedNoWritePageList)) {
  1542. Info->ModifiedCount += _KB;
  1543. if (ReferenceCount > 0) {
  1544. Info->LockedCount += _KB;
  1545. }
  1546. } else if ((PageLocation == StandbyPageList) ||
  1547. (PageLocation == TransitionPage)) {
  1548. Info->StandbyCount += _KB;
  1549. if (ReferenceCount > 0) {
  1550. Info->LockedCount += _KB;
  1551. }
  1552. } else {
  1553. Info->ValidCount += _KB;
  1554. if (ShareCount > 1) {
  1555. Info->SharedCount += _KB;
  1556. if (ReferenceCount > 1) {
  1557. Info->LockedCount += _KB;
  1558. }
  1559. }
  1560. }
  1561. if ((PteAddress >= DbgGetPdeAddress (0x0)) &&
  1562. (PteAddress <= DbgGetPdeAddress (0xFFFFFFFFFFFFFFFF))) {
  1563. Info->PageTableCount += _KB;
  1564. }
  1565. }
  1566. NextPfn:
  1567. Pfn1 = (Pfn1 + PfnSize);
  1568. }
  1569. //
  1570. // dump the results.
  1571. //
  1572. #if 0
  1573. dprintf("Physical Page Summary:\n");
  1574. dprintf(" - number of physical pages: %ld\n",
  1575. MmNumberOfPhysicalPages);
  1576. dprintf(" - Zeroed Pages %ld\n", MmZeroedPageListHead.Total);
  1577. dprintf(" - Free Pages %ld\n", MmFreePageListHead.Total);
  1578. dprintf(" - Standby Pages %ld\n", MmStandbyPageListHead.Total);
  1579. dprintf(" - Modfified Pages %ld\n", MmModifiedPageListHead.Total);
  1580. dprintf(" - Modfified NoWrite Pages %ld\n", MmModifiedNoWritePageListHead.Total);
  1581. dprintf(" - Bad Pages %ld\n", MmBadPageListHead.Total);
  1582. #endif //0
  1583. dprintf("\n\n Usage Summary (in Kb):\n");
  1584. Info = InfoStart;
  1585. while (Info < InfoEnd) {
  1586. if (CheckControlC()) {
  1587. VirtualFree (InfoStart,0,MEM_RELEASE);
  1588. free(pKernelMap);
  1589. free(NameString.Buffer);
  1590. return;
  1591. }
  1592. if (Info->Master > 0x200000) {
  1593. //
  1594. // Get the control area from the subsection.
  1595. //
  1596. if (GetFieldValue(Info->Master,
  1597. "nt!_SUBSECTION",
  1598. "ControlArea",
  1599. ControlArea1)) {
  1600. dprintf("unable to get subsection va %p %lx\n",Info->Master,Info->OriginalPte);
  1601. }
  1602. // ControlArea1 = Subsection.ControlArea;
  1603. Info->Master = ControlArea1;
  1604. //
  1605. // Loop through the array so far for matching control areas
  1606. //
  1607. Info1 = InfoStart;
  1608. while (Info1 < Info) {
  1609. if (Info1->Master == ControlArea1) {
  1610. //
  1611. // Found a match, collapse these values.
  1612. //
  1613. Info1->ValidCount += Info->ValidCount;
  1614. Info1->StandbyCount += Info->StandbyCount;
  1615. Info1->ModifiedCount += Info->ModifiedCount;
  1616. Info1->SharedCount += Info->SharedCount;
  1617. Info1->LockedCount += Info->LockedCount;
  1618. Info1->PageTableCount += Info->PageTableCount;
  1619. Info->Master = 0;
  1620. break;
  1621. }
  1622. Info1++;
  1623. }
  1624. } else {
  1625. LastProcessInfo->Next = Info;
  1626. LastProcessInfo = Info;
  1627. }
  1628. Info++;
  1629. }
  1630. Info = InfoStart;
  1631. dprintf("Control Valid Standby Dirty Shared Locked PageTables name\n");
  1632. while (Info < InfoEnd) {
  1633. ULONG64 FilePointer;
  1634. if (CheckControlC()) {
  1635. VirtualFree (InfoStart,0,MEM_RELEASE);
  1636. free(pKernelMap);
  1637. free(NameString.Buffer);
  1638. return;
  1639. }
  1640. if (Info->Master > 0x200000) {
  1641. //
  1642. // Get the control area.
  1643. //
  1644. if (GetFieldValue(Info->Master,
  1645. "nt!_CONTROL_AREA",
  1646. "FilePointer",
  1647. FilePointer)) {
  1648. dprintf("%8p %5ld %5ld %5ld %5ld %5ld %5ld Bad Control Area\n",
  1649. Info->Master,
  1650. Info->ValidCount,
  1651. Info->StandbyCount,
  1652. Info->ModifiedCount,
  1653. Info->SharedCount,
  1654. Info->LockedCount,
  1655. Info->PageTableCount
  1656. );
  1657. } else if (FilePointer == 0) {
  1658. dprintf("%8p %5ld %5ld %5ld %5ld %5ld %5ld Page File Section\n",
  1659. Info->Master,
  1660. Info->ValidCount,
  1661. Info->StandbyCount,
  1662. Info->ModifiedCount,
  1663. Info->SharedCount,
  1664. Info->LockedCount,
  1665. Info->PageTableCount
  1666. );
  1667. } else {
  1668. ULONG64 NameBuffer;
  1669. //
  1670. // Get the file pointer.
  1671. //
  1672. if (GetFieldValue(FilePointer,
  1673. "nt!_FILE_OBJECT",
  1674. "FileName.Length",
  1675. NameString.Length)) {
  1676. dprintf("unable to get subsection %p\n",FilePointer);
  1677. }
  1678. if (NameString.Length != 0) {
  1679. //
  1680. // Get the name string.
  1681. //
  1682. if (NameString.Length > NameString.MaximumLength) {
  1683. NameString.Length = NameString.MaximumLength-1;
  1684. }
  1685. GetFieldValue(FilePointer,
  1686. "nt!_FILE_OBJECT",
  1687. "FileName.Buffer",
  1688. NameBuffer);
  1689. if ((!ReadMemory(NameBuffer,
  1690. NameString.Buffer,
  1691. NameString.Length,
  1692. &result)) || (result < NameString.Length)) {
  1693. dprintf("%8p %5ld %5ld %5ld %5ld %5ld %5ld Name Not Available\n",
  1694. Info->Master,
  1695. Info->ValidCount,
  1696. Info->StandbyCount,
  1697. Info->ModifiedCount,
  1698. Info->SharedCount,
  1699. Info->LockedCount,
  1700. Info->PageTableCount
  1701. );
  1702. } else {
  1703. {
  1704. WCHAR FileName[MAX_PATH];
  1705. WCHAR FullFileName[MAX_PATH];
  1706. WCHAR *FilePart;
  1707. ZeroMemory(FileName,sizeof(FileName));
  1708. if (NameString.Length > sizeof(FileName)) {
  1709. wcscpy(FileName, L"File name length too big - possibly corrupted");
  1710. } else {
  1711. CopyMemory(FileName,NameString.Buffer,NameString.Length);
  1712. }
  1713. GetFullPathNameW(
  1714. FileName,
  1715. MAX_PATH,
  1716. FullFileName,
  1717. &FilePart
  1718. );
  1719. dprintf("%8p %5ld %5ld %5ld %5ld %5ld %5ld mapped_file( %ws )\n",
  1720. Info->Master,
  1721. Info->ValidCount,
  1722. Info->StandbyCount,
  1723. Info->ModifiedCount,
  1724. Info->SharedCount,
  1725. Info->LockedCount,
  1726. Info->PageTableCount,
  1727. FilePart);
  1728. }
  1729. }
  1730. } else {
  1731. dprintf("%8p %5ld %5ld %5ld %5ld %5ld %5ld No Name for File\n",
  1732. Info->Master,
  1733. Info->ValidCount,
  1734. Info->StandbyCount,
  1735. Info->ModifiedCount,
  1736. Info->SharedCount,
  1737. Info->LockedCount,
  1738. Info->PageTableCount
  1739. );
  1740. }
  1741. }
  1742. }
  1743. Info += 1;
  1744. }
  1745. Info = &PagedPoolBlock;
  1746. if ((Info->ValidCount != 0) ||
  1747. (Info->StandbyCount != 0) ||
  1748. (Info->ModifiedCount != 0)) {
  1749. dprintf("00000000 %4ld %5ld %5ld %5ld %5ld %5ld PagedPool\n",
  1750. Info->ValidCount,
  1751. Info->StandbyCount,
  1752. Info->ModifiedCount,
  1753. Info->SharedCount,
  1754. Info->LockedCount,
  1755. Info->PageTableCount
  1756. );
  1757. }
  1758. //
  1759. // dump the process information.
  1760. //
  1761. BuildDirbaseList();
  1762. Info = ProcessPfns.Next;
  1763. while (Info != NULL) {
  1764. if (Info->Master != 0) {
  1765. PUCHAR ImageName;
  1766. ImageName = DirbaseToImage(Info->Master);
  1767. if ( ImageName ) {
  1768. dprintf("-------- %4ld %5ld %5ld ----- ----- %5ld process ( %s )\n",
  1769. Info->ValidCount,
  1770. Info->StandbyCount,
  1771. Info->ModifiedCount,
  1772. Info->PageTableCount,
  1773. ImageName
  1774. );
  1775. }
  1776. else {
  1777. dprintf("-------- %4ld %5ld %5ld ----- ----- %5ld pagefile section (%lx)\n",
  1778. Info->ValidCount,
  1779. Info->StandbyCount,
  1780. Info->ModifiedCount,
  1781. Info->PageTableCount,
  1782. Info->Master
  1783. );
  1784. }
  1785. }
  1786. Info = Info->Next;
  1787. }
  1788. if (!IgnoreInvalidFrames) {
  1789. for (i=0;i<pKernelMap->Count ;i++) {
  1790. dprintf("-------- %4ld %5ld %5ld ----- %5ld ----- driver ( %ws )\n",
  1791. pKernelMap->Item[i].ValidCount,
  1792. pKernelMap->Item[i].StandbyCount,
  1793. pKernelMap->Item[i].ModifiedCount,
  1794. pKernelMap->Item[i].LockedCount,
  1795. pKernelMap->Item[i].Name
  1796. );
  1797. }
  1798. }
  1799. VirtualFree (InfoStart,0,MEM_RELEASE);
  1800. free(pKernelMap);
  1801. free(NameString.Buffer);
  1802. return;
  1803. }
  1804. NTSTATUS
  1805. BuildDirbaseList (
  1806. VOID
  1807. )
  1808. {
  1809. ULONG64 Next;
  1810. ULONG64 ProcessHead;
  1811. ULONG64 Process;
  1812. NTSTATUS status=0;
  1813. ULONG ActiveProcessLinksOffset, DirectoryTableBaseOffset;
  1814. FIELD_INFO offField[] = {
  1815. {"ActiveProcessLinks", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL},
  1816. {"Pcb.DirectoryTableBase", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL}
  1817. };
  1818. SYM_DUMP_PARAM TypeSym ={
  1819. sizeof (SYM_DUMP_PARAM), "_EPROCESS", DBG_DUMP_NO_PRINT, 0,
  1820. NULL, NULL, NULL, 2, &offField[0]
  1821. };
  1822. // Get the offset of ActiveProcessLinks in EPROCESS
  1823. if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
  1824. return FALSE;
  1825. }
  1826. ActiveProcessLinksOffset = (ULONG) offField[0].address;
  1827. DirectoryTableBaseOffset = (ULONG) offField[1].address;
  1828. MaxDirbase = 0;
  1829. ProcessHead = GetNtDebuggerData(PsActiveProcessHead );
  1830. if (!ProcessHead) {
  1831. return STATUS_OBJECT_NAME_NOT_FOUND;
  1832. }
  1833. if (GetFieldValue(ProcessHead, "nt!_LIST_ENTRY", "Flink", Next)) {
  1834. return STATUS_OBJECT_NAME_NOT_FOUND;
  1835. }
  1836. //Next = List.Flink;
  1837. if (Next == 0) {
  1838. dprintf("PsActiveProcessHead is NULL!\n");
  1839. return STATUS_INVALID_PARAMETER;
  1840. }
  1841. while(Next != ProcessHead) {
  1842. ULONG64 PageFrameNumber=0;
  1843. Process = Next - ActiveProcessLinksOffset;
  1844. if (GetFieldValue(Process,
  1845. "nt!_EPROCESS",
  1846. "ImageFileName",
  1847. Names[MaxDirbase])) {
  1848. dprintf("Unable to read _EPROCESS at %p\n",Process);
  1849. MaxDirbase = 0;
  1850. return status;
  1851. }
  1852. if ( (Names[ MaxDirbase ])[0] == '\0' ) {
  1853. strcpy((PCHAR)&Names[MaxDirbase][0],(PCHAR)"SystemProcess");
  1854. }
  1855. GetFieldValue(Process,"_EPROCESS","ImageFileName",Names[MaxDirbase]);
  1856. GetFieldValue(Process + DirectoryTableBaseOffset, "nt!HARDWARE_PTE", "PageFrameNumber", PageFrameNumber);
  1857. DirBases[MaxDirbase++] = PageFrameNumber;
  1858. GetFieldValue(Process, "_EPROCESS", "ActiveProcessLinks.Flink", Next);
  1859. if (CheckControlC()) {
  1860. MaxDirbase = 0;
  1861. return STATUS_INVALID_PARAMETER;
  1862. }
  1863. }
  1864. return STATUS_INVALID_PARAMETER;
  1865. }
  1866. PUCHAR
  1867. DirbaseToImage(
  1868. IN ULONG64 DirBase
  1869. )
  1870. {
  1871. ULONG i;
  1872. for(i=0;i<MaxDirbase;i++) {
  1873. if ( DirBases[i] == DirBase ) {
  1874. return &Names[i][0];
  1875. }
  1876. }
  1877. return NULL;
  1878. }
  1879. LOGICAL
  1880. BuildKernelMap (
  1881. OUT PKERN_MAP KernelMap
  1882. )
  1883. {
  1884. ULONG64 Next;
  1885. ULONG64 ListHead;
  1886. NTSTATUS Status = 0;
  1887. ULONG Result;
  1888. ULONG64 DataTable;
  1889. ULONG i = 0;
  1890. ULONG64 Flink;
  1891. ULONG InLoadOrderLinksOffset;
  1892. FIELD_INFO offField = {"InLoadOrderLinks", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
  1893. SYM_DUMP_PARAM TypeSym ={
  1894. sizeof (SYM_DUMP_PARAM), "nt!_LDR_DATA_TABLE_ENTRY", DBG_DUMP_NO_PRINT, 0,
  1895. NULL, NULL, NULL, 1, &offField
  1896. };
  1897. // Get the offset of InLoadOrderLinks in LDR_DATA_TABLE_ENTRY
  1898. if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
  1899. return FALSE;
  1900. }
  1901. InLoadOrderLinksOffset = (ULONG) offField.address;
  1902. ListHead = GetNtDebuggerData(PsLoadedModuleList );
  1903. if (!ListHead) {
  1904. dprintf("Couldn't get offset of PsLoadedModuleListHead\n");
  1905. return FALSE;
  1906. }
  1907. if (GetFieldValue(ListHead, "nt!_LIST_ENTRY", "Flink", Flink)) {
  1908. dprintf("Unable to get value of PsLoadedModuleListHead\n");
  1909. return FALSE;
  1910. }
  1911. Next = Flink;
  1912. if (Next == 0) {
  1913. dprintf("PsLoadedModuleList is NULL!\n");
  1914. return FALSE;
  1915. }
  1916. while (Next != ListHead) {
  1917. ULONG64 BaseDllNameBuffer, DllBase;
  1918. ULONG BaseDllNameLength=0, SizeOfImage;
  1919. if (CheckControlC()) {
  1920. return FALSE;
  1921. }
  1922. DataTable = (Next - InLoadOrderLinksOffset);
  1923. if (GetFieldValue(DataTable,
  1924. "nt!_LDR_DATA_TABLE_ENTRY",
  1925. "BaseDllName.Buffer",
  1926. BaseDllNameBuffer)) {
  1927. dprintf("Unable to read LDR_DATA_TABLE_ENTRY at %08p\n",
  1928. DataTable);
  1929. return FALSE;
  1930. }
  1931. GetFieldValue(DataTable, "nt!_LDR_DATA_TABLE_ENTRY","BaseDllName.Length",BaseDllNameLength);
  1932. GetFieldValue(DataTable, "nt!_LDR_DATA_TABLE_ENTRY","DllBase",DllBase);
  1933. GetFieldValue(DataTable, "nt!_LDR_DATA_TABLE_ENTRY","SizeOfImage",SizeOfImage);
  1934. //
  1935. // Get the base DLL name.
  1936. //
  1937. if ((!ReadMemory(BaseDllNameBuffer,
  1938. &KernelMap->Item[i].Name[0],
  1939. BaseDllNameLength,
  1940. &Result)) || (Result < BaseDllNameLength)) {
  1941. dprintf("Unable to read name string at %08p - status %08lx\n",
  1942. DataTable,
  1943. Status);
  1944. return FALSE;
  1945. }
  1946. KernelMap->Item[i].Name[BaseDllNameLength/2] = L'\0';
  1947. KernelMap->Item[i].StartVa = DllBase;
  1948. KernelMap->Item[i].EndVa = KernelMap->Item[i].StartVa +
  1949. (ULONG)SizeOfImage;
  1950. i += 1;
  1951. GetFieldValue(DataTable, "nt!_LDR_DATA_TABLE_ENTRY","InLoadOrderLinks.Flink", Next);
  1952. }
  1953. KernelMap->Item[i].StartVa = GetNtDebuggerDataPtrValue(MmPagedPoolStart);
  1954. KernelMap->Item[i].EndVa = GetNtDebuggerDataPtrValue(MmPagedPoolEnd);
  1955. wcscpy (&KernelMap->Item[i].Name[0], (PUSHORT) &L"Paged Pool");
  1956. i+= 1;
  1957. #if 0
  1958. KernelMap->Item[i].StartVa = DbgGetPteAddress (0xffffffff80000000UI64);
  1959. KernelMap->Item[i].EndVa = DbgGetPteAddress (0xffffffffffffffffUI64);
  1960. wcscpy (&KernelMap->Item[i].Name[0], (PUSHORT) &L"System Page Tables");
  1961. i+= 1;
  1962. KernelMap->Item[i].StartVa = DbgGetPdeAddress (0x80000000);
  1963. KernelMap->Item[i].EndVa = DbgGetPdeAddress (0xffffffff);
  1964. wcscpy (&KernelMap->Item[i].Name[0], (PUSHORT) &L"System Page Tables");
  1965. i+= 1;
  1966. #endif 0
  1967. // LWFIX: Both PTEs and nonpaged pool can be in multiple virtually discontiguous
  1968. // areas. Fix this.
  1969. KernelMap->Item[i].StartVa = DbgGetVirtualAddressMappedByPte (
  1970. GetNtDebuggerDataValue(MmSystemPtesStart));
  1971. KernelMap->Item[i].EndVa = DbgGetVirtualAddressMappedByPte (
  1972. GetNtDebuggerDataValue(MmSystemPtesEnd)) + 1;
  1973. wcscpy (&KernelMap->Item[i].Name[0], (PUSHORT) &L"Kernel Stacks");
  1974. i+= 1;
  1975. KernelMap->Item[i].StartVa = GetNtDebuggerDataValue(MmNonPagedPoolStart);
  1976. KernelMap->Item[i].EndVa = GetNtDebuggerDataValue(MmNonPagedPoolEnd);
  1977. wcscpy (&KernelMap->Item[i].Name[0], (PUSHORT) &L"NonPaged Pool");
  1978. i+= 1;
  1979. KernelMap->Count = i;
  1980. return TRUE;
  1981. }
  1982. ULONG64 SpecialPoolStart;
  1983. ULONG64 SpecialPoolEnd;
  1984. #define VI_POOL_FREELIST_END ((ULONG64)-1)
  1985. LOGICAL
  1986. VerifierDumpPool (
  1987. IN ULONG64 Verifier
  1988. )
  1989. {
  1990. ULONG64 HashTableAddress;
  1991. ULONG PoolTag;
  1992. ULONG i;
  1993. ULONG64 HashEntry;
  1994. ULONG64 PoolHashSize;
  1995. ULONG SizeofEntry;
  1996. LONG64 FreeListNext;
  1997. //
  1998. // Display the current and peak pool usage by allocation & bytes.
  1999. //
  2000. #define PP(x) isprint(((x)&0xff))?((x)&0xff):('.')
  2001. InitTypeRead(Verifier, nt!_MI_VERIFIER_DRIVER_ENTRY);
  2002. dprintf("\n");
  2003. dprintf("Current Pool Allocations %08I64lx %08I64lx\n",
  2004. ReadField(CurrentPagedPoolAllocations),
  2005. ReadField(CurrentNonPagedPoolAllocations));
  2006. dprintf("Current Pool Bytes %08I64lx %08I64lx\n",
  2007. ReadField(PagedBytes),
  2008. ReadField(NonPagedBytes));
  2009. dprintf("Peak Pool Allocations %08I64lx %08I64lx\n",
  2010. ReadField(PeakPagedPoolAllocations),
  2011. ReadField(PeakNonPagedPoolAllocations));
  2012. dprintf("Peak Pool Bytes %08I64lx %08I64lx\n",
  2013. ReadField(PeakPagedBytes),
  2014. ReadField(PeakNonPagedBytes));
  2015. //
  2016. // If no current allocations then the dump is over.
  2017. //
  2018. if ((ReadField(CurrentPagedPoolAllocations) == 0) &&
  2019. (ReadField(CurrentNonPagedPoolAllocations) == 0)) {
  2020. dprintf("\n");
  2021. return FALSE;
  2022. }
  2023. dprintf("\n");
  2024. PoolHashSize = ReadField(PoolHashSize);
  2025. HashTableAddress = ReadField(PoolHash);
  2026. dprintf("PoolAddress SizeInBytes Tag CallersAddress\n");
  2027. i = 0;
  2028. HashEntry = HashTableAddress;
  2029. SizeofEntry = GetTypeSize("nt!_VI_POOL_ENTRY");
  2030. for (i = 0; i < PoolHashSize; i += 1, HashEntry += SizeofEntry) {
  2031. if (GetFieldValue(HashEntry, "nt!_VI_POOL_ENTRY", "FreeListNext", FreeListNext)) {
  2032. dprintf("%08p: Unable to get verifier hash page\n", HashEntry);
  2033. return FALSE;
  2034. }
  2035. //
  2036. // Sign extend if necessary.
  2037. //
  2038. if (!IsPtr64()) {
  2039. FreeListNext = (ULONG64)(LONG64)(LONG)FreeListNext;
  2040. }
  2041. //
  2042. // Skip freelist entries.
  2043. //
  2044. if ((FreeListNext == VI_POOL_FREELIST_END) ||
  2045. ((FreeListNext & MINLONG64_PTR) == 0)) {
  2046. continue;
  2047. }
  2048. InitTypeRead(HashEntry, nt!_VI_POOL_ENTRY);
  2049. PoolTag = (ULONG) ReadField(InUse.Tag);
  2050. dprintf("%p 0x%08p %c%c%c%c ",
  2051. ReadField(InUse.VirtualAddress),
  2052. ReadField(InUse.NumberOfBytes),
  2053. (PP(PoolTag) & ~0x80),
  2054. PP(PoolTag >> 8),
  2055. PP(PoolTag >> 16),
  2056. PP(PoolTag >> 24)
  2057. );
  2058. dprintf("%p\n", ReadField(InUse.CallingAddress));
  2059. if (CheckControlC()) {
  2060. return TRUE;
  2061. }
  2062. }
  2063. #undef PP
  2064. dprintf("\n");
  2065. return FALSE;
  2066. }
  2067. #if 0
  2068. typedef struct _COMMIT_INFO {
  2069. LPSTR Name;
  2070. ULONG Index;
  2071. } COMMIT_INFO, *PCOMMIT_INFO;
  2072. COMMIT_INFO CommitInfo[] = {
  2073. "MM_DBG_COMMIT_NONPAGED_POOL_EXPANSION", 0,
  2074. "MM_DBG_COMMIT_PAGED_POOL_PAGETABLE", 1,
  2075. "MM_DBG_COMMIT_PAGED_POOL_PAGES", 2,
  2076. "MM_DBG_COMMIT_SESSION_POOL_PAGE_TABLES", 3,
  2077. "MM_DBG_COMMIT_ALLOCVM1", 4,
  2078. "MM_DBG_COMMIT_ALLOCVM_SEGMENT", 5,
  2079. "MM_DBG_COMMIT_IMAGE", 6,
  2080. "MM_DBG_COMMIT_PAGEFILE_BACKED_SHMEM", 7,
  2081. "MM_DBG_COMMIT_INDEPENDENT_PAGES", 8,
  2082. "MM_DBG_COMMIT_CONTIGUOUS_PAGES", 9,
  2083. "MM_DBG_COMMIT_MDL_PAGES", 0xA,
  2084. "MM_DBG_COMMIT_NONCACHED_PAGES", 0xB,
  2085. "MM_DBG_COMMIT_MAPVIEW_DATA", 0xC,
  2086. "MM_DBG_COMMIT_FILL_SYSTEM_DIRECTORY", 0xD,
  2087. "MM_DBG_COMMIT_EXTRA_SYSTEM_PTES", 0xE,
  2088. "MM_DBG_COMMIT_DRIVER_PAGING_AT_INIT", 0xF,
  2089. "MM_DBG_COMMIT_PAGEFILE_FULL", 0x10,
  2090. "MM_DBG_COMMIT_PROCESS_CREATE", 0x11,
  2091. "MM_DBG_COMMIT_KERNEL_STACK_CREATE", 0x12,
  2092. "MM_DBG_COMMIT_SET_PROTECTION", 0x13,
  2093. "MM_DBG_COMMIT_SESSION_CREATE", 0x14,
  2094. "MM_DBG_COMMIT_SESSION_IMAGE_PAGES", 0x15,
  2095. "MM_DBG_COMMIT_SESSION_PAGETABLE_PAGES", 0x16,
  2096. "MM_DBG_COMMIT_SESSION_SHARED_IMAGE", 0x17,
  2097. "MM_DBG_COMMIT_DRIVER_PAGES", 0x18,
  2098. "MM_DBG_COMMIT_INSERT_VAD", 0x19,
  2099. "MM_DBG_COMMIT_SESSION_WS_INIT", 0x1A,
  2100. "MM_DBG_COMMIT_SESSION_ADDITIONAL_WS_PAGES", 0x1B,
  2101. "MM_DBG_COMMIT_SESSION_ADDITIONAL_WS_HASHPAGES", 0x1C,
  2102. "MM_DBG_COMMIT_SPECIAL_POOL_PAGES", 0x1D,
  2103. "MM_DBG_COMMIT_SMALL", 0x1F,
  2104. "MM_DBG_COMMIT_EXTRA_WS_PAGES", 0x20,
  2105. "MM_DBG_COMMIT_EXTRA_INITIAL_SESSION_WS_PAGES", 0x21,
  2106. "MM_DBG_COMMIT_ALLOCVM_PROCESS", 0x22,
  2107. "MM_DBG_COMMIT_INSERT_VAD_PT", 0x23,
  2108. "MM_DBG_COMMIT_ALLOCVM_PROCESS2", 0x24,
  2109. "MM_DBG_COMMIT_CHARGE_NORMAL", 0x25,
  2110. "MM_DBG_COMMIT_CHARGE_CAUSE_POPUP", 0x26,
  2111. "MM_DBG_COMMIT_CHARGE_CANT_EXPAND", 0x27,
  2112. "MM_DBG_COMMIT_RETURN_NONPAGED_POOL_EXPANSION", 0x40,
  2113. "MM_DBG_COMMIT_RETURN_PAGED_POOL_PAGES", 0x41,
  2114. "MM_DBG_COMMIT_RETURN_SESSION_DATAPAGE", 0x42,
  2115. "MM_DBG_COMMIT_RETURN_ALLOCVM_SEGMENT", 0x43,
  2116. "MM_DBG_COMMIT_RETURN_ALLOCVM2", 0x44,
  2117. "MM_DBG_COMMIT_RETURN_IMAGE_NO_LARGE_CA", 0x46,
  2118. "MM_DBG_COMMIT_RETURN_PTE_RANGE", 0x47,
  2119. "MM_DBG_COMMIT_RETURN_NTFREEVM1", 0x48,
  2120. "MM_DBG_COMMIT_RETURN_NTFREEVM2", 0x49,
  2121. "MM_DBG_COMMIT_RETURN_INDEPENDENT_PAGES", 0x4A,
  2122. "MM_DBG_COMMIT_RETURN_AWE_EXCESS", 0x4B,
  2123. "MM_DBG_COMMIT_RETURN_MDL_PAGES", 0x4C,
  2124. "MM_DBG_COMMIT_RETURN_NONCACHED_PAGES", 0x4D,
  2125. "MM_DBG_COMMIT_RETURN_SESSION_CREATE_FAILURE", 0x4E,
  2126. "MM_DBG_COMMIT_RETURN_PAGETABLES", 0x4F,
  2127. "MM_DBG_COMMIT_RETURN_PROTECTION", 0x50,
  2128. "MM_DBG_COMMIT_RETURN_SEGMENT_DELETE1", 0x51,
  2129. "MM_DBG_COMMIT_RETURN_SEGMENT_DELETE2", 0x52,
  2130. "MM_DBG_COMMIT_RETURN_PAGEFILE_FULL", 0x53,
  2131. "MM_DBG_COMMIT_RETURN_SESSION_DEREFERENCE", 0x54,
  2132. "MM_DBG_COMMIT_RETURN_VAD", 0x55,
  2133. "MM_DBG_COMMIT_RETURN_PROCESS_CREATE_FAILURE1", 0x56,
  2134. "MM_DBG_COMMIT_RETURN_PROCESS_DELETE", 0x57,
  2135. "MM_DBG_COMMIT_RETURN_PROCESS_CLEAN_PAGETABLES", 0x58,
  2136. "MM_DBG_COMMIT_RETURN_KERNEL_STACK_DELETE", 0x59,
  2137. "MM_DBG_COMMIT_RETURN_SESSION_DRIVER_LOAD_FAILURE1",0x5A,
  2138. "MM_DBG_COMMIT_RETURN_DRIVER_INIT_CODE", 0x5B,
  2139. "MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD", 0x5C,
  2140. "MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD1", 0x5D,
  2141. "MM_DBG_COMMIT_RETURN_NORMAL", 0x5E,
  2142. "MM_DBG_COMMIT_RETURN_PF_FULL_EXTEND", 0x5F,
  2143. "MM_DBG_COMMIT_RETURN_EXTENDED", 0x60,
  2144. "MM_DBG_COMMIT_RETURN_SEGMENT_DELETE3", 0x61,
  2145. };
  2146. VOID
  2147. DumpCommitTracker ()
  2148. {
  2149. ULONG64 MmTrackCommit;
  2150. ULONG64 PfnEntry;
  2151. ULONG64 displacement;
  2152. ULONG64 AcquiredAddress;
  2153. ULONG64 ReleasedAddress;
  2154. CHAR SymbolBuffer[80];
  2155. PCHAR SymPointer;
  2156. ULONG EntrySize;
  2157. ULONG result;
  2158. ULONG64 ReadCount;
  2159. ULONG64 i;
  2160. ULONG64 j;
  2161. PSIZE_T LocalData;
  2162. PCHAR local;
  2163. ULONG64 NumberOfCommitEntries;
  2164. MmTrackCommit = GetExpression ("nt!MmTrackCommit");
  2165. if (MmTrackCommit == 0) {
  2166. dprintf("%08p: Unable to get commit track data.\n", MmTrackCommit);
  2167. return;
  2168. }
  2169. PfnEntry = MmTrackCommit;
  2170. #if 0
  2171. NumberOfCommitEntries = GetUlongValue ("MiMaxPfnTimings");
  2172. EntrySize = GetTypeSize("SIZE_T");
  2173. #else
  2174. NumberOfCommitEntries = 128;
  2175. EntrySize = 4;
  2176. #endif
  2177. ReadCount = NumberOfCommitEntries * EntrySize;
  2178. dprintf("Scanning %I64u %I64u commit points\n", NumberOfCommitEntries, ReadCount);
  2179. LocalData = LocalAlloc(LPTR, (ULONG) (NumberOfCommitEntries * EntrySize));
  2180. if (!LocalData) {
  2181. dprintf("unable to get allocate %ld bytes of memory\n",
  2182. (ULONG)(NumberOfCommitEntries * EntrySize));
  2183. return;
  2184. }
  2185. if ((!ReadMemory(MmTrackCommit,
  2186. LocalData,
  2187. (ULONG) ReadCount,
  2188. &result)) || (result < (ULONG) ReadCount)) {
  2189. dprintf("unable to get track commit table - "
  2190. "address %p - count %I64u\n",
  2191. LocalData, ReadCount);
  2192. }
  2193. else {
  2194. dprintf("\n%-50s %s\n", "Instance", "HexCount");
  2195. for (i = 0; i < NumberOfCommitEntries; i += 1) {
  2196. if (LocalData[i] != 0) {
  2197. for (j = 0; j < sizeof(CommitInfo) / sizeof (COMMIT_INFO); j += 1) {
  2198. if (CommitInfo[j].Index == i) {
  2199. dprintf ("%-50s %8x\n", CommitInfo[j].Name, LocalData[i]);
  2200. break;
  2201. }
  2202. }
  2203. }
  2204. }
  2205. }
  2206. if (LocalData) {
  2207. LocalFree((void *)LocalData);
  2208. }
  2209. return;
  2210. }
  2211. #endif
  2212. VOID
  2213. DumpFaultInjectionTraceLog (
  2214. PCSTR Args
  2215. );
  2216. VOID
  2217. DumpTrackIrqlLog (
  2218. PCSTR args
  2219. );
  2220. DECLARE_API( verifier )
  2221. /*++
  2222. Routine Description:
  2223. Displays the current Driver Verifier data.
  2224. Arguments:
  2225. arg - Supplies 7 for full listing
  2226. Return Value:
  2227. None.
  2228. --*/
  2229. {
  2230. ULONG result;
  2231. ULONG Flags;
  2232. ULONG VerifierFlags;
  2233. ULONG64 VerifierDataPointer;
  2234. ULONG64 SuspectPointer;
  2235. ULONG64 NextEntry;
  2236. ULONG64 VerifierDriverEntry;
  2237. PUCHAR tempbuffer;
  2238. UNICODE_STRING unicodeString;
  2239. LOGICAL Interrupted;
  2240. CHAR Buf[256];
  2241. PCHAR ImageFileName;
  2242. ANSI_STRING AnsiString;
  2243. UNICODE_STRING InputDriverName;
  2244. NTSTATUS st;
  2245. ULONG Level;
  2246. PCHAR state;
  2247. ULONG64 tmp;
  2248. UNREFERENCED_PARAMETER (Client);
  2249. //
  2250. // Display option usage.
  2251. //
  2252. if (strstr (args, "?") != NULL) {
  2253. dprintf ("!verifier \n");
  2254. dprintf (" \n");
  2255. dprintf (" Dump verifier summary information. \n");
  2256. dprintf (" \n");
  2257. dprintf ("!verifier [FLAGS [IMAGE]] \n");
  2258. dprintf (" \n");
  2259. dprintf (" 0x01 : Dump verified drivers pool statistics \n");
  2260. dprintf (" \n");
  2261. dprintf (" 0x02 : not used \n");
  2262. dprintf (" \n");
  2263. dprintf (" 0x04 [N] : Dump N traces from fault injection trace log. \n");
  2264. dprintf (" \n");
  2265. dprintf (" 0x08 [N] : Dump N traces from track IRQL trace log\n");
  2266. dprintf (" \n");
  2267. dprintf ("To display everything use: \n");
  2268. dprintf (" \n");
  2269. dprintf (" !verifier 0xf \n");
  2270. dprintf (" \n");
  2271. return S_OK;
  2272. }
  2273. //
  2274. // Read the Flags parameter.
  2275. //
  2276. Flags = 0;
  2277. Flags = (ULONG) GetExpression (args);
  2278. //
  2279. // Display fault injection stacks.
  2280. //
  2281. if ((Flags == 0x04)) {
  2282. DumpFaultInjectionTraceLog (args);
  2283. return S_OK;
  2284. }
  2285. //
  2286. // Display track irql stacks.
  2287. //
  2288. if ((Flags == 0x08)) {
  2289. DumpTrackIrqlLog (args);
  2290. return S_OK;
  2291. }
  2292. //
  2293. // Continue with normal processing: !verifier [FLAGS [NAME]]
  2294. //
  2295. Flags = 0;
  2296. RtlZeroMemory(Buf, 256);
  2297. if (GetExpressionEx(args, &tmp, &args)) {
  2298. Flags = (ULONG) tmp;
  2299. while (args && (*args == ' ')) {
  2300. ++args;
  2301. }
  2302. strcpy(Buf, args);
  2303. }
  2304. if (Buf[0] != '\0') {
  2305. ImageFileName = Buf;
  2306. RtlInitAnsiString(&AnsiString, ImageFileName);
  2307. st = RtlAnsiStringToUnicodeString(&InputDriverName, &AnsiString, TRUE);
  2308. if (!NT_SUCCESS(st)) {
  2309. dprintf("%08lx: Unable to initialize unicode string\n", st);
  2310. return E_INVALIDARG;
  2311. }
  2312. } else {
  2313. ImageFileName = NULL;
  2314. }
  2315. VerifierDataPointer = GetExpression ("nt!MmVerifierData");
  2316. if (GetFieldValue(VerifierDataPointer,
  2317. "nt!_MM_DRIVER_VERIFIER_DATA",
  2318. "Level",
  2319. Level)) {
  2320. dprintf("%08p: Unable to get verifier list.\n",VerifierDataPointer);
  2321. return E_INVALIDARG;
  2322. }
  2323. dprintf("\nVerify Level %x ... enabled options are:", Level);
  2324. if (Level & DRIVER_VERIFIER_SPECIAL_POOLING) {
  2325. dprintf("\n\tspecial pool");
  2326. }
  2327. if (Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  2328. dprintf("\n\tspecial irql");
  2329. }
  2330. if (Level & DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES) {
  2331. dprintf("\n\tinject random low-resource API failures");
  2332. }
  2333. if (Level & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS) {
  2334. dprintf("\n\tall pool allocations checked on unload");
  2335. }
  2336. if (Level & DRIVER_VERIFIER_IO_CHECKING) {
  2337. dprintf("\n\tIo subsystem checking enabled");
  2338. }
  2339. if (Level & DRIVER_VERIFIER_DEADLOCK_DETECTION) {
  2340. dprintf("\n\tDeadlock detection enabled");
  2341. }
  2342. if (Level & DRIVER_VERIFIER_ENHANCED_IO_CHECKING) {
  2343. dprintf("\n\tEnhanced Io checking enabled");
  2344. }
  2345. if (Level & DRIVER_VERIFIER_DMA_VERIFIER) {
  2346. dprintf("\n\tDMA checking enabled");
  2347. }
  2348. if (InitTypeRead(VerifierDataPointer, nt!MM_DRIVER_VERIFIER_DATA)) {
  2349. dprintf("Unable to read type nt!MM_DRIVER_VERIFIER_DATA @ %p\n", VerifierDataPointer);
  2350. }
  2351. dprintf("\n\nSummary of All Verifier Statistics\n\n");
  2352. dprintf("RaiseIrqls 0x%x\n", (ULONG) ReadField(RaiseIrqls));
  2353. dprintf("AcquireSpinLocks 0x%x\n", (ULONG) ReadField(AcquireSpinLocks));
  2354. dprintf("Synch Executions 0x%x\n", (ULONG) ReadField(SynchronizeExecutions));
  2355. dprintf("Trims 0x%x\n", (ULONG) ReadField(Trims));
  2356. dprintf("\n");
  2357. dprintf("Pool Allocations Attempted 0x%x\n", (ULONG) ReadField(AllocationsAttempted));
  2358. dprintf("Pool Allocations Succeeded 0x%x\n", (ULONG) ReadField(AllocationsSucceeded));
  2359. dprintf("Pool Allocations Succeeded SpecialPool 0x%x\n", (ULONG) ReadField(AllocationsSucceededSpecialPool));
  2360. dprintf("Pool Allocations With NO TAG 0x%x\n", (ULONG) ReadField(AllocationsWithNoTag));
  2361. dprintf("Pool Allocations Failed 0x%x\n", (ULONG) ReadField(AllocationsFailed));
  2362. dprintf("Resource Allocations Failed Deliberately 0x%x\n", (ULONG) ReadField(AllocationsFailedDeliberately) + (ULONG) ReadField(BurstAllocationsFailedDeliberately));
  2363. dprintf("\n");
  2364. dprintf("Current paged pool allocations 0x%x for %08P bytes\n",
  2365. (ULONG) ReadField(CurrentPagedPoolAllocations),
  2366. ReadField(PagedBytes));
  2367. dprintf("Peak paged pool allocations 0x%x for %08P bytes\n",
  2368. (ULONG)ReadField(PeakPagedPoolAllocations),
  2369. ReadField(PeakPagedBytes));
  2370. dprintf("Current nonpaged pool allocations 0x%x for %08P bytes\n",
  2371. (ULONG) ReadField(CurrentNonPagedPoolAllocations),
  2372. ReadField(NonPagedBytes));
  2373. dprintf("Peak nonpaged pool allocations 0x%x for %08P bytes\n",
  2374. (ULONG)ReadField(PeakNonPagedPoolAllocations),
  2375. ReadField(PeakNonPagedBytes));
  2376. dprintf("\n");
  2377. SpecialPoolStart = GetPointerValue("nt!MmSpecialPoolStart");
  2378. SpecialPoolEnd = GetPointerValue("nt!MmSpecialPoolEnd");
  2379. if (Flags & 0x1) {
  2380. ULONG Off;
  2381. SuspectPointer = GetExpression ("nt!MiSuspectDriverList");
  2382. GetFieldOffset("nt!_MI_VERIFIER_DRIVER_ENTRY", "Links", &Off);
  2383. if (!ReadPointer(SuspectPointer,&NextEntry)) {
  2384. dprintf("%08p: Unable to get verifier list %p\n",SuspectPointer);
  2385. return E_INVALIDARG;
  2386. }
  2387. dprintf("Driver Verification List\n\n");
  2388. dprintf("Entry State NonPagedPool PagedPool Module\n\n");
  2389. while (NextEntry != SuspectPointer) {
  2390. VerifierDriverEntry = NextEntry - Off;
  2391. if (GetFieldValue( VerifierDriverEntry,
  2392. "nt!_MI_VERIFIER_DRIVER_ENTRY",
  2393. "Flags",
  2394. VerifierFlags)) {
  2395. dprintf("%08p: Unable to get verifier data\n", VerifierDriverEntry);
  2396. return E_INVALIDARG;
  2397. }
  2398. InitTypeRead(VerifierDriverEntry, nt!_MI_VERIFIER_DRIVER_ENTRY);
  2399. if ((VerifierFlags & VI_VERIFYING_DIRECTLY) == 0) {
  2400. NextEntry = ReadField(Links.Flink);
  2401. continue;
  2402. }
  2403. unicodeString.Length = (USHORT) ReadField(BaseName.Length);
  2404. tempbuffer = LocalAlloc(LPTR, unicodeString.Length);
  2405. unicodeString.Buffer = (PWSTR)tempbuffer;
  2406. unicodeString.MaximumLength = unicodeString.Length;
  2407. if (!ReadMemory (ReadField(BaseName.Buffer),
  2408. tempbuffer,
  2409. unicodeString.Length,
  2410. &result)) {
  2411. dprintf("%08p: Unable to get verifier driver name\n", ReadField(BaseName.Buffer));
  2412. }
  2413. if (ImageFileName != NULL) {
  2414. if (RtlEqualUnicodeString(&InputDriverName, &unicodeString, TRUE) == 0) {
  2415. NextEntry = ReadField(Links.Flink);
  2416. continue;
  2417. }
  2418. }
  2419. if (ReadField(Loads) == 0 && ReadField(Unloads) == 0) {
  2420. state = "Hasn't loaded";
  2421. }
  2422. else if (ReadField(Loads) != ReadField(Unloads)) {
  2423. if (ReadField(Unloads) != 0) {
  2424. state = "Loaded&Unloaded";
  2425. }
  2426. else {
  2427. state = "Loaded";
  2428. }
  2429. }
  2430. else {
  2431. state = "Unloaded";
  2432. }
  2433. dprintf("%p %-16s %08p %08p %wZ\n",
  2434. VerifierDriverEntry,
  2435. state,
  2436. ReadField(NonPagedBytes),
  2437. ReadField(PagedBytes),
  2438. &unicodeString);
  2439. Interrupted = FALSE;
  2440. NextEntry = ReadField(Links.Flink);
  2441. if ((Flags & 0x2) &&
  2442. (Level & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS)) {
  2443. Interrupted = VerifierDumpPool (VerifierDriverEntry);
  2444. }
  2445. LocalFree(tempbuffer);
  2446. if ((Interrupted == TRUE) ||
  2447. (ImageFileName != NULL) ||
  2448. (CheckControlC())) {
  2449. break;
  2450. }
  2451. }
  2452. }
  2453. if ((Flags & 0x04)) {
  2454. dprintf ("----------------------------------------------- \n");
  2455. dprintf ("Fault injection trace log \n");
  2456. dprintf ("----------------------------------------------- \n");
  2457. DumpFaultInjectionTraceLog (NULL);
  2458. }
  2459. if ((Flags & 0x08)) {
  2460. dprintf ("----------------------------------------------- \n");
  2461. dprintf ("Track irql trace log \n");
  2462. dprintf ("----------------------------------------------- \n");
  2463. DumpTrackIrqlLog (NULL);
  2464. }
  2465. return S_OK;
  2466. }
  2467. DECLARE_API( fpsearch )
  2468. /*++
  2469. Routine Description:
  2470. Free pool searcher.
  2471. Arguments:
  2472. arg - Supplies virtual address to match.
  2473. Return Value:
  2474. None.
  2475. --*/
  2476. {
  2477. ULONG i;
  2478. ULONG BufferSize;
  2479. ULONG RawCount;
  2480. PULONG RawPointer;
  2481. ULONG Flags;
  2482. ULONG ActualRead;
  2483. ULONG64 PageFrameNumber;
  2484. ULONG64 PAddress;
  2485. ULONG64 Address;
  2486. ULONG result;
  2487. ULONG64 PfnDb;
  2488. ULONG64 Pfn;
  2489. ULONG64 PfnStart;
  2490. ULONG PfnSize;
  2491. ULONG64 ChainedBp;
  2492. ULONG64 ValidBp;
  2493. ULONG64 LastBp;
  2494. ULONG64 ReturnAddress;
  2495. PCHAR Buffer;
  2496. ULONG64 MmFreePageListHeadAddress;
  2497. CHAR SymbolBuffer[80];
  2498. ULONG64 displacement;
  2499. ULONG64 Total;
  2500. ULONG StkOffset;
  2501. ULONG PtrSize;
  2502. ULONG PoolTag;
  2503. ULONG StackBytes;
  2504. ULONG64 StackPointer;
  2505. ULONG64 ChainedBpVal;
  2506. ULONG64 LastBpVal;
  2507. ULONG64 Blink;
  2508. PtrSize = IsPtr64() ? 8 : 4;
  2509. PfnSize = GetTypeSize("nt!_MMPFN");
  2510. BufferSize = GetTypeSize("nt!_MI_FREED_SPECIAL_POOL");
  2511. if (BufferSize == 0) {
  2512. dprintf("Type MI_FREED_SPECIAL_POOL not found.\n");
  2513. return E_INVALIDARG;
  2514. }
  2515. PfnDb = GetNtDebuggerData(MmPfnDatabase );
  2516. if (!PfnDb) {
  2517. dprintf("unable to get PFN0 database address\n");
  2518. return E_INVALIDARG;
  2519. }
  2520. result = !ReadPointer(PfnDb,&PfnStart);
  2521. if (result != 0) {
  2522. dprintf("unable to get PFN database address %p %x\n", PfnDb, result);
  2523. return E_INVALIDARG;
  2524. }
  2525. Address = 0;
  2526. Flags = 0;
  2527. if (!sscanf(args,"%I64lx %lx",&Address, &Flags)) {
  2528. Address = 0;
  2529. }
  2530. // Do not use GetExpression here - the actual address to be searched is phy address
  2531. // and it can be >32bit for 32bit targets
  2532. // Address = GetExpression (args);
  2533. if (Address == 0) {
  2534. dprintf("Usage: fpsearch address\n");
  2535. return E_INVALIDARG;
  2536. }
  2537. MmFreePageListHeadAddress = GetExpression ("nt!MmFreePageListHead");
  2538. if (GetFieldValue(MmFreePageListHeadAddress,
  2539. "nt!_MMPFNLIST",
  2540. "Total",
  2541. Total)) {
  2542. dprintf("%08p: Unable to get MmFreePageLocationList\n",MmFreePageListHeadAddress);
  2543. return E_INVALIDARG;
  2544. }
  2545. if (Total == 0) {
  2546. dprintf("No pages on free list to search\n");
  2547. return E_INVALIDARG;
  2548. }
  2549. if (Address != (ULONG64)-1) {
  2550. dprintf("Searching the free page list (%I64x entries) for VA %p\n\n",
  2551. Total, Address);
  2552. Address &= ~(ULONG64)(PageSize - 1);
  2553. }
  2554. else {
  2555. dprintf("Searching the free page list (%x entries) for all freed special pool\n\n",
  2556. Total);
  2557. }
  2558. GetFieldValue (MmFreePageListHeadAddress,
  2559. "nt!_MMPFNLIST",
  2560. "Blink",
  2561. PageFrameNumber);
  2562. GetFieldOffset("_MI_FREED_SPECIAL_POOL", "StackData", &StkOffset);
  2563. Buffer = LocalAlloc(LPTR, BufferSize);
  2564. if (Buffer == NULL) {
  2565. dprintf("Could not allocate a buffer for the search\n");
  2566. return E_INVALIDARG;
  2567. }
  2568. while (PageFrameNumber != (ULONG64)-1) {
  2569. PAddress = (ULONG64)PageFrameNumber * PageSize;
  2570. ReadPhysical (PAddress, Buffer, BufferSize, &ActualRead);
  2571. if (ActualRead != BufferSize) {
  2572. dprintf("Physical memory read %I64X %x %x failed\n", PAddress, ActualRead, BufferSize);
  2573. // break;
  2574. }
  2575. if (Flags & 0x1) {
  2576. //
  2577. // Print a preview of the raw buffer.
  2578. //
  2579. #define PP(x) isprint(((x)&0xff))?((x)&0xff):('.')
  2580. RawPointer = (PULONG)Buffer;
  2581. RawCount = BufferSize / sizeof (ULONG);
  2582. if (RawCount > 32) {
  2583. RawCount = 32;
  2584. }
  2585. RawCount &= ~0x3;
  2586. for (i = 0; i < RawCount; i += 4) {
  2587. dprintf ("%I64X %08x %08x %08x %08x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
  2588. PageFrameNumber * PageSize,
  2589. *RawPointer,
  2590. *(RawPointer + 1),
  2591. *(RawPointer + 2),
  2592. *(RawPointer + 3),
  2593. PP(*RawPointer),
  2594. PP(*RawPointer >> 8),
  2595. PP(*RawPointer >> 16),
  2596. PP(*RawPointer >> 24),
  2597. PP(*(RawPointer + 1)),
  2598. PP(*(RawPointer + 1) >> 8),
  2599. PP(*(RawPointer + 1) >> 16),
  2600. PP(*(RawPointer + 1) >> 24),
  2601. PP(*(RawPointer + 2)),
  2602. PP(*(RawPointer + 2) >> 8),
  2603. PP(*(RawPointer + 2) >> 16),
  2604. PP(*(RawPointer + 2) >> 24),
  2605. PP(*(RawPointer + 3)),
  2606. PP(*(RawPointer + 3) >> 8),
  2607. PP(*(RawPointer + 3) >> 16),
  2608. PP(*(RawPointer + 3) >> 24));
  2609. RawPointer += 4;
  2610. }
  2611. dprintf ("\n");
  2612. }
  2613. Pfn = (PfnStart + PageFrameNumber * PfnSize);
  2614. if (GetFieldValue(Pfn,"nt!_MMPFN","u2.Blink", Blink)) {
  2615. dprintf("%08p: unable to get PFN element %x\n", Pfn, PfnSize);
  2616. break;
  2617. }
  2618. if ((ULONG)Blink == (ULONG)-1) {
  2619. Blink = (ULONG64)-1;
  2620. }
  2621. #define MI_FREED_SPECIAL_POOL_SIGNATURE 0x98764321
  2622. InitTypeReadPhysical (PAddress, nt!MI_FREED_SPECIAL_POOL);
  2623. if ((ULONG) ReadField(Signature) == MI_FREED_SPECIAL_POOL_SIGNATURE) {
  2624. if ((Address == (ULONG64)-1) ||
  2625. (((ULONG)(ReadField(VirtualAddress)) & ~(ULONG)(PageSize - 1)) == (ULONG)Address)) {
  2626. PoolTag = (ULONG) ReadField(OverlaidPoolHeader.PoolTag);
  2627. dprintf("VA PFN Tag Size Pagable Thread Tick\n");
  2628. dprintf("%p %6p %c%c%c%c %6x %s %08p %x\n",
  2629. ReadField(VirtualAddress),
  2630. PageFrameNumber,
  2631. #define PP(x) isprint(((x)&0xff))?((x)&0xff):('.')
  2632. PP(PoolTag),
  2633. PP(PoolTag >> 8),
  2634. PP(PoolTag >> 16),
  2635. PP(PoolTag >> 24),
  2636. #undef PP
  2637. (ULONG) ReadField(NumberOfBytesRequested),
  2638. ReadField(Pagable) ? "Yes" : "No ",
  2639. ReadField(Thread),
  2640. ReadField(TickCount));
  2641. dprintf("\tCALL STACK AT TIME OF DEALLOCATION\n");
  2642. //
  2643. // Calculate the relative stack and print it here symbolically.
  2644. //
  2645. StackBytes = (ULONG) ReadField(StackBytes);
  2646. StackPointer = ReadField(StackPointer);
  2647. ValidBp = (StackPointer & ~(ULONG64)(PageSize - 1));
  2648. ChainedBp = (PAddress + StkOffset);
  2649. LastBp = (ChainedBp + (ULONG) ReadField(StackBytes));
  2650. while (ChainedBp < LastBp) {
  2651. //
  2652. // Read directly from physical memory.
  2653. //
  2654. InitTypeReadPhysical(ChainedBp, nt!_LIST_ENTRY);
  2655. ChainedBpVal = ReadField(Flink);
  2656. InitTypeReadPhysical(LastBp, nt!_LIST_ENTRY);
  2657. LastBpVal = ReadField(Flink);
  2658. //
  2659. // Find a valid frame register chain.
  2660. //
  2661. if ((((ChainedBpVal) & ~(ULONG64)(PageSize - 1)) == ValidBp) &&
  2662. (ChainedBpVal > StackPointer) &&
  2663. ((ChainedBpVal - (StackPointer)) <= StackBytes)) {
  2664. ULONG64 ReturnAddressVal;
  2665. //
  2666. // Increment to the stacked return address.
  2667. //
  2668. ReturnAddress = ChainedBp + PtrSize;
  2669. InitTypeReadPhysical(ReturnAddress, nt!_LIST_ENTRY);
  2670. ReturnAddressVal = ReadField(Flink);
  2671. SymbolBuffer[0] = '!';
  2672. GetSymbol((ReturnAddressVal), (PUCHAR)SymbolBuffer, &displacement);
  2673. dprintf ("\t%s", SymbolBuffer);
  2674. if (displacement) {
  2675. dprintf( "+0x%x", displacement );
  2676. }
  2677. dprintf( "\n" );
  2678. #ifdef SLOW_BUT_THOROUGH
  2679. ChainedBp += PtrSize;
  2680. #else
  2681. if ((ReturnAddressVal & ~MAXLONG64_PTR) == 0) {
  2682. break;
  2683. }
  2684. //
  2685. // Subtract the stackpointer & add stackdata offset.
  2686. //
  2687. ChainedBp = (ChainedBpVal - StackPointer + StkOffset);
  2688. //
  2689. // Adjust for relative.
  2690. //
  2691. ChainedBp = (PAddress + ChainedBp);
  2692. #endif
  2693. }
  2694. else {
  2695. ChainedBp += PtrSize;
  2696. }
  2697. }
  2698. dprintf("\n");
  2699. if (Address != (ULONG64)-1) {
  2700. break;
  2701. }
  2702. }
  2703. }
  2704. if (CheckControlC()) {
  2705. break;
  2706. }
  2707. PageFrameNumber = Blink;
  2708. }
  2709. LocalFree(Buffer);
  2710. return S_OK;
  2711. }
  2712. USHORT
  2713. GetPfnRefCount(
  2714. IN ULONG64 PageFrameNumber
  2715. )
  2716. {
  2717. ULONG64 PfnDb;
  2718. ULONG64 Pfn;
  2719. ULONG64 PfnStart;
  2720. ULONG PfnSize;
  2721. ULONG ReferenceCount;
  2722. PfnSize = GetTypeSize("nt!_MMPFN");
  2723. PfnDb = GetNtDebuggerData(MmPfnDatabase );
  2724. if (!PfnDb) {
  2725. dprintf("unable to get PFN0 database address\n");
  2726. return 0;
  2727. }
  2728. if (!ReadPointer(PfnDb,&PfnStart)) {
  2729. dprintf("unable to get PFN database address %p\n", PfnDb);
  2730. return 0;
  2731. }
  2732. Pfn = (PfnStart + PageFrameNumber * PfnSize);
  2733. if (GetFieldValue(Pfn,"nt!_MMPFN","u3.e2.ReferenceCount", ReferenceCount)) {
  2734. dprintf("%08p: unable to get PFN element %x\n", Pfn, PfnSize);
  2735. return 0;
  2736. }
  2737. return (USHORT) ReferenceCount;
  2738. }
  2739. /////////////////////////////////////////////////////////////////////
  2740. ////////////////////////////////////// Dump irql tracking log
  2741. /////////////////////////////////////////////////////////////////////
  2742. VOID
  2743. DumpTrackIrqlLog (
  2744. PCSTR args
  2745. )
  2746. {
  2747. ULONG64 TrackIrqlQueueAddress;
  2748. ULONG64 TrackIrqlIndexAddress;
  2749. ULONG64 TrackIrqlQueueLengthAddress;
  2750. ULONG64 TrackIrqlQueue;
  2751. ULONG TrackIrqlIndex;
  2752. ULONG TrackIrqlQueueLength;
  2753. ULONG I, Index;
  2754. ULONG64 Address;
  2755. ULONG TrackIrqlTypeSize;
  2756. UCHAR SymbolName[256];
  2757. ULONG64 SymbolAddress;
  2758. ULONG64 SymbolOffset;
  2759. ULONG Result;
  2760. ULONG ShowCount;
  2761. ULONG Flags;
  2762. //
  2763. // Read how many traces we want to see.
  2764. //
  2765. ShowCount = 0;
  2766. if (args) {
  2767. ULONG64 tmp;
  2768. if (GetExpressionEx(args, &tmp, &args)) {
  2769. Flags = (ULONG) tmp;
  2770. if (!sscanf (args, "%u", &ShowCount)) {
  2771. ShowCount = 0;
  2772. }
  2773. }
  2774. if (ShowCount == 0) {
  2775. ShowCount = 4;
  2776. }
  2777. }
  2778. else {
  2779. ShowCount = 4;
  2780. }
  2781. //
  2782. // Read track irql package data
  2783. //
  2784. TrackIrqlQueueAddress = GetExpression ("nt!ViTrackIrqlQueue");
  2785. TrackIrqlIndexAddress = GetExpression ("nt!ViTrackIrqlIndex");
  2786. TrackIrqlQueueLengthAddress = GetExpression ("nt!ViTrackIrqlQueueLength");
  2787. if (TrackIrqlQueueAddress == 0
  2788. || TrackIrqlIndexAddress == 0
  2789. || TrackIrqlIndexAddress == 0) {
  2790. dprintf ("Incorrect symbols. \n");
  2791. return;
  2792. }
  2793. ReadPointer (TrackIrqlQueueAddress, &TrackIrqlQueue);
  2794. if (TrackIrqlQueue == 0) {
  2795. dprintf ("Irql tracking is not enabled. You need to enable driver verifier \n");
  2796. dprintf ("for at least one driver to activate irql tracking. \n");
  2797. return;
  2798. }
  2799. ReadMemory (TrackIrqlIndexAddress, &TrackIrqlIndex, sizeof(ULONG), &Result);
  2800. if (Result != sizeof(ULONG)) {
  2801. dprintf ("Trackirql: read error \n");
  2802. return;
  2803. }
  2804. ReadMemory (TrackIrqlQueueLengthAddress, &TrackIrqlQueueLength, sizeof(ULONG), &Result);
  2805. if (Result != sizeof(ULONG)) {
  2806. dprintf ("Trackirql: read error \n");
  2807. return;
  2808. }
  2809. TrackIrqlTypeSize = GetTypeSize("nt!_VI_TRACK_IRQL");
  2810. //
  2811. // Dump information
  2812. //
  2813. dprintf ("\nSize of track irql queue is 0x%X \n", TrackIrqlQueueLength);
  2814. for (I = 0, Index = TrackIrqlIndex; I < TrackIrqlQueueLength; I += 1) {
  2815. if (I >= ShowCount) {
  2816. break;
  2817. }
  2818. Index -= 1;
  2819. Index &= (TrackIrqlQueueLength - 1);
  2820. Address = TrackIrqlQueue + Index * TrackIrqlTypeSize;
  2821. InitTypeRead (Address, nt!_VI_TRACK_IRQL);
  2822. dprintf ("\n");
  2823. dprintf ("Thread: %I64X\n", ReadField (Thread));
  2824. dprintf ("Old irql: %I64X\n", ReadField (OldIrql));
  2825. dprintf ("New irql: %I64X\n", ReadField (NewIrql));
  2826. dprintf ("Processor: %I64X\n", ReadField (Processor));
  2827. dprintf ("Time stamp: %I64X\n", ReadField (TickCount));
  2828. dprintf ("\n");
  2829. SymbolAddress = ReadField(StackTrace[0]);
  2830. if (SymbolAddress == 0) { continue; }
  2831. GetSymbol(SymbolAddress, SymbolName, &SymbolOffset);
  2832. dprintf (" %I64X %s+0x%I64x\n", SymbolAddress, SymbolName, SymbolOffset);
  2833. SymbolAddress = ReadField(StackTrace[1]);
  2834. if (SymbolAddress == 0) { continue; }
  2835. GetSymbol(SymbolAddress, SymbolName, &SymbolOffset);
  2836. dprintf (" %I64X %s+0x%I64x\n", SymbolAddress, SymbolName, SymbolOffset);
  2837. SymbolAddress = ReadField(StackTrace[2]);
  2838. if (SymbolAddress == 0) { continue; }
  2839. GetSymbol(SymbolAddress, SymbolName, &SymbolOffset);
  2840. dprintf (" %I64X %s+0x%I64x\n", SymbolAddress, SymbolName, SymbolOffset);
  2841. SymbolAddress = ReadField(StackTrace[3]);
  2842. if (SymbolAddress == 0) { continue; }
  2843. GetSymbol(SymbolAddress, SymbolName, &SymbolOffset);
  2844. dprintf (" %I64X %s+0x%I64x\n", SymbolAddress, SymbolName, SymbolOffset);
  2845. SymbolAddress = ReadField(StackTrace[4]);
  2846. if (SymbolAddress == 0) { continue; }
  2847. GetSymbol(SymbolAddress, SymbolName, &SymbolOffset);
  2848. dprintf (" %I64X %s+0x%I64x\n", SymbolAddress, SymbolName, SymbolOffset);
  2849. if (CheckControlC()) {
  2850. dprintf ("Interrupted \n");
  2851. break;
  2852. }
  2853. }
  2854. }
  2855. /////////////////////////////////////////////////////////////////////
  2856. ////////////////////////////////////// Dump fault injection trace log
  2857. /////////////////////////////////////////////////////////////////////
  2858. ULONG64
  2859. ReadPvoid (
  2860. ULONG64 Address
  2861. )
  2862. {
  2863. ULONG64 RemoteValue = 0;
  2864. ReadPointer( Address, &RemoteValue);
  2865. return RemoteValue;
  2866. }
  2867. ULONG
  2868. ReadUlong(
  2869. ULONG64 Address
  2870. )
  2871. {
  2872. ULONG RemoteValue = 0;
  2873. ReadMemory( Address, &RemoteValue, sizeof( ULONG ), NULL );
  2874. return RemoteValue;
  2875. }
  2876. VOID
  2877. DumpFaultInjectionTrace (
  2878. ULONG64 Address
  2879. )
  2880. {
  2881. ULONG64 ReturnAddress;
  2882. CHAR SymbolName[ 1024 ];
  2883. ULONG64 Displacement;
  2884. ULONG I;
  2885. ULONG PvoidSize;
  2886. PvoidSize = IsPtr64() ? 8 : 4;
  2887. for (I = 0; I < 8; I += 1) {
  2888. ReturnAddress = ReadPvoid (Address + I * PvoidSize);
  2889. if (ReturnAddress == 0) {
  2890. break;
  2891. }
  2892. GetSymbol (ReturnAddress, SymbolName, &Displacement);
  2893. dprintf (" %p %s+0x%p\n",
  2894. ReturnAddress,
  2895. SymbolName,
  2896. Displacement);
  2897. }
  2898. }
  2899. VOID
  2900. DumpFaultInjectionTraceLog (
  2901. PCSTR Args
  2902. )
  2903. {
  2904. ULONG TracesToDisplay = 0;
  2905. ULONG64 TraceAddress;
  2906. ULONG64 Trace;
  2907. ULONG64 IndexAddress;
  2908. ULONG Index;
  2909. ULONG64 LengthAddress;
  2910. ULONG Length;
  2911. ULONG I;
  2912. ULONG PvoidSize;
  2913. ULONG64 TraceBlockAddress;
  2914. ULONG64 FirstReturnAddress;
  2915. ULONG TracesFound = 0;
  2916. BOOLEAN Interrupted = FALSE;
  2917. ULONG Flags;
  2918. if (Args) {
  2919. ULONG64 tmp;
  2920. if (GetExpressionEx(Args, &tmp, &Args)) {
  2921. Flags = (ULONG) tmp;
  2922. if (!sscanf (Args, "%u", &TracesToDisplay)) {
  2923. TracesToDisplay = 0;
  2924. }
  2925. }
  2926. if (TracesToDisplay == 0) {
  2927. TracesToDisplay = 4;
  2928. }
  2929. }
  2930. else {
  2931. TracesToDisplay = 4;
  2932. }
  2933. PvoidSize = IsPtr64() ? 8 : 4;
  2934. TraceAddress = (ULONG64) GetExpression ("nt!ViFaultTraces");
  2935. IndexAddress = (ULONG64) GetExpression ("nt!ViFaultTracesIndex");
  2936. LengthAddress = (ULONG64) GetExpression ("nt!ViFaultTracesLength");
  2937. Trace = ReadPvoid (TraceAddress);
  2938. if (Trace == 0) {
  2939. dprintf ("Driver fault injection is not enabled for this system. \n");
  2940. return;
  2941. }
  2942. Index = ReadUlong (IndexAddress);
  2943. Length = ReadUlong (LengthAddress);
  2944. for (I = 0; I < Length; I += 1) {
  2945. Index -= 1;
  2946. Index &= (Length - 1);
  2947. TraceBlockAddress = Trace + Index * PvoidSize * 8;
  2948. FirstReturnAddress = ReadPvoid (TraceBlockAddress);
  2949. if (FirstReturnAddress != 0) {
  2950. TracesFound += 1;
  2951. dprintf ("\n");
  2952. DumpFaultInjectionTrace (TraceBlockAddress);
  2953. if (TracesFound >= TracesToDisplay) {
  2954. break;
  2955. }
  2956. }
  2957. if (CheckControlC()) {
  2958. Interrupted = TRUE;
  2959. dprintf ("Interrupted \n");
  2960. break;
  2961. }
  2962. }
  2963. if (Interrupted == FALSE && TracesFound == 0) {
  2964. dprintf ("No fault injection traces found. \n");
  2965. }
  2966. }
  2967. PUCHAR MemoryDescriptorType[] = {
  2968. "ExceptionBlock",
  2969. "SystemBlock",
  2970. "Free",
  2971. "Bad",
  2972. "LoadedProgram",
  2973. "FirmwareTemporary",
  2974. "FirmwarePermanent",
  2975. "OsloaderHeap",
  2976. "OsloaderStack",
  2977. "SystemCode",
  2978. "HalCode",
  2979. "BootDriver",
  2980. "ConsoleInDriver",
  2981. "ConsoleOutDriver",
  2982. "StartupDpcStack",
  2983. "StartupKernelStack",
  2984. "StartupPanicStack",
  2985. "StartupPcrPage",
  2986. "StartupPdrPage",
  2987. "RegistryData",
  2988. "MemoryData",
  2989. "NlsData",
  2990. "SpecialMemory",
  2991. "BBTMemory",
  2992. "LoaderReserve",
  2993. "XIPRom",
  2994. "HALCachedMemory"
  2995. };
  2996. #define MAXIMUM_MEMORY_TYPE (sizeof(MemoryDescriptorType)/sizeof(UCHAR))
  2997. DECLARE_API( loadermemorylist )
  2998. /*++
  2999. Routine Description:
  3000. Displays the memory allocation list. This is the list
  3001. handed to the OS by the OSLOADER that describes physical
  3002. memory.
  3003. Displays the corresponding PDE and PTE.
  3004. Arguments:
  3005. list - points to the listheader
  3006. Return Value:
  3007. None.
  3008. --*/
  3009. {
  3010. ULONG64 ListHeaderAddress;
  3011. ULONG64 EntryAddress;
  3012. ULONG64 LengthInPages;
  3013. ULONG64 TypeOfMemory;
  3014. ULONG Count[MAXIMUM_MEMORY_TYPE];
  3015. ULONG i;
  3016. UNREFERENCED_PARAMETER (Client);
  3017. ListHeaderAddress = 0;
  3018. ListHeaderAddress = GetExpression(args);
  3019. if (ListHeaderAddress == 0) {
  3020. dprintf("Usage: !loadermemorylist <address_of_listhead>\n");
  3021. return E_INVALIDARG;
  3022. }
  3023. if (!ReadPointer(ListHeaderAddress, &EntryAddress)) {
  3024. dprintf("Unable to read list header at %p\n", ListHeaderAddress);
  3025. return E_INVALIDARG;
  3026. }
  3027. if (EntryAddress == ListHeaderAddress) {
  3028. dprintf("List at %p is empty\n", ListHeaderAddress);
  3029. return S_OK;
  3030. }
  3031. dprintf("Base Length Type\n");
  3032. RtlZeroMemory(Count, sizeof(Count));
  3033. do {
  3034. InitTypeRead(EntryAddress, nt!MEMORY_ALLOCATION_DESCRIPTOR);
  3035. TypeOfMemory = ReadField(MemoryType);
  3036. if (TypeOfMemory < MAXIMUM_MEMORY_TYPE) {
  3037. LengthInPages = ReadField(PageCount);
  3038. dprintf("%08x %08x %s\n",
  3039. (ULONG)ReadField(BasePage),
  3040. (ULONG)LengthInPages,
  3041. MemoryDescriptorType[TypeOfMemory]);
  3042. Count[TypeOfMemory] += (ULONG)LengthInPages;
  3043. } else {
  3044. dprintf("Unrecognized Descriptor at %p\n", EntryAddress);
  3045. }
  3046. EntryAddress = ReadField(ListEntry.Flink);
  3047. } while (EntryAddress != ListHeaderAddress);
  3048. dprintf("\nSummary\nMemory Type Pages\n");
  3049. LengthInPages = 0;
  3050. for (i = 0; i < MAXIMUM_MEMORY_TYPE; i++) {
  3051. if (Count[i]) {
  3052. dprintf("%-20s%08x (%8d)\n",
  3053. MemoryDescriptorType[i],
  3054. Count[i],
  3055. Count[i]);
  3056. LengthInPages += Count[i];
  3057. }
  3058. }
  3059. dprintf(" ======== ========\n");
  3060. dprintf("Total %08x (%8d) = ~%dMB\n",
  3061. (ULONG)LengthInPages,
  3062. (ULONG)LengthInPages,
  3063. (ULONG)LengthInPages / (1024 * 1024 / 4096));
  3064. return S_OK;
  3065. }