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.

2755 lines
65 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. pte.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Lou Perazzoli (LouP) 15-Feb-1992
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "i386.h"
  15. #include "ia64.h"
  16. #include "amd64.h"
  17. ULONG64 MmNonPagedPoolEnd=0;
  18. ULONG64 MmSubsectionBase=0;
  19. ULONG64 KiIA64VaSignedFill;
  20. ULONG64 KiIA64PtaBase;
  21. ULONG64 KiIA64PtaSign;
  22. ULONG
  23. DbgGetPageFileHigh(
  24. ULONG64 Pte
  25. );
  26. ////////////////////////////////////////////////////////////////////////////////
  27. //
  28. // I386
  29. //
  30. ////////////////////////////////////////////////////////////////////////////////
  31. #define PaeGetPdeAddressX86(va) ((ULONG64) (LONG64) (LONG) (PDE_BASE_X86 + ((((ULONG)(va)) >> 21) << 3)))
  32. #define MiGetPdeAddressX86(va) ((ULONG64) (LONG64) (LONG) (((((ULONG)(va)) >> 22) << 2) + PDE_BASE_X86))
  33. #define PaeGetVirtualAddressMappedByPteX86(PTE) (((ULONG64)(PTE) << 9))
  34. #define PaeGetPteAddressX86(va) ((ULONG64)(PTE_BASE_X86 + ((((ULONG)(va)) >> 12) << 3)))
  35. #define MiGetPteAddressX86(va) (((((ULONG) (va)) >> 12) << 2) + PTE_BASE_X86)
  36. #define MiGetPteOffsetX86(va) ((((ULONG) (va)) >> 12) & 0x3ff)
  37. #define MiGetVirtualAddressMappedByPteX86(PTE) ((ULONG64) (LONG64) (LONG) ((PTE) << 10))
  38. ////////////////////////////////////////////////////////////////////////////////
  39. //
  40. // AMD64
  41. //
  42. ////////////////////////////////////////////////////////////////////////////////
  43. #define AMD64_VA_MASK (((ULONG64)1 << AMD64_VA_BITS) - 1)
  44. #define MiGetPteAddressAMD64(va) ((((((ULONG64)(va) & AMD64_VA_MASK) >> PTI_SHIFT_AMD64) << PTE_SHIFT_AMD64) + PTE_BASE_AMD64))
  45. #define MiGetPdeAddressAMD64(va) ((((((ULONG64)(va) & AMD64_VA_MASK) >> PDI_SHIFT_AMD64) << PTE_SHIFT_AMD64) + PDE_BASE_AMD64))
  46. #define MiGetPpeAddressAMD64(va) ((((((ULONG64)(va) & AMD64_VA_MASK) >> PPI_SHIFT_AMD64) << PTE_SHIFT_AMD64) + PPE_BASE_AMD64))
  47. #define MiGetPxeAddressAMD64(va) ((((((ULONG64)(va) & AMD64_VA_MASK) >> PXI_SHIFT_AMD64) << PTE_SHIFT_AMD64) + PXE_BASE_AMD64))
  48. #define MiGetPteOffsetAMD64(va) ((((ULONG_PTR) (va)) >> 12) & 0x3ff)
  49. #define MiGetVirtualAddressMappedByPteAMD64(PTE) \
  50. ((ULONG64)((LONG64)(((LONG64)(PTE) - PTE_BASE_AMD64) << (PAGE_SHIFT_AMD64 + AMD64_VA_SHIFT - PTE_SHIFT_AMD64)) >> AMD64_VA_SHIFT))
  51. ////////////////////////////////////////////////////////////////////////////////
  52. //
  53. // IA64
  54. //
  55. ////////////////////////////////////////////////////////////////////////////////
  56. //
  57. // MiGetPdeAddress returns the address of the PTE which maps the
  58. // given virtual address. Note we must redefine some of the MM
  59. // macros here because they cast values to pointers which does not work
  60. // on systems where pointers are only 32 bits.
  61. //
  62. VOID
  63. DbgGetPteBaseIA64(
  64. VOID
  65. )
  66. {
  67. ULONG64 PtaValue;
  68. ULONG i;
  69. if (KiIA64PtaBase != 0) {
  70. return;
  71. }
  72. if (g_ExtData == NULL ||
  73. g_ExtData->lpVtbl->
  74. ReadProcessorSystemData(g_ExtData, 0,
  75. DEBUG_DATA_BASE_TRANSLATION_VIRTUAL_OFFSET,
  76. &PtaValue, sizeof(PtaValue), NULL) != S_OK) {
  77. PtaValue = (ULONG64) GetExpression("@pta");
  78. }
  79. KiIA64PtaBase = PtaValue & ~0xffffUI64;
  80. KiIA64VaSignedFill =
  81. (KiIA64PtaBase << (PAGE_SHIFT_IA64 - PTE_SHIFT_IA64)) & ~VRN_MASK_IA64;
  82. KiIA64PtaSign = KiIA64PtaBase;
  83. for (i = 0; i < 64; i += 1) {
  84. KiIA64PtaSign >>= 1;
  85. if (KiIA64PtaSign & 1) {
  86. KiIA64PtaSign = (ULONG64)1 << i;
  87. break;
  88. }
  89. }
  90. }
  91. ULONG64
  92. MiGetPteAddressIA64 (
  93. IN ULONG64 Va
  94. )
  95. {
  96. DbgGetPteBaseIA64();
  97. if (((((ULONG64)(Va)) & PDE_TBASE_IA64) == PDE_TBASE_IA64) &&
  98. ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_TBASE_IA64)) < PageSize)) {
  99. return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) |
  100. (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE")));
  101. }
  102. return (ULONG64) (((((ULONG64)(Va)) & VRN_MASK_IA64)) |
  103. ((((((ULONG64)(Va)) >> PTI_SHIFT_IA64) << PTE_SHIFT_IA64) & (~(PTE_BASE_IA64|VRN_MASK_IA64))) + PTE_BASE_IA64));
  104. }
  105. ULONG64
  106. MiGetPdeAddressIA64 (
  107. IN ULONG64 Va
  108. )
  109. {
  110. DbgGetPteBaseIA64();
  111. if (((((ULONG64)(Va)) & PDE_BASE_IA64) == PDE_BASE_IA64) &&
  112. ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_BASE_IA64)) < ((ULONG64)1 << PDI_SHIFT_IA64))) {
  113. return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) |
  114. (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE")));
  115. }
  116. if (((((ULONG64)(Va)) & PDE_TBASE_IA64) == PDE_TBASE_IA64) &&
  117. ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_TBASE_IA64)) < PageSize)) {
  118. return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) |
  119. (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE")));
  120. }
  121. return (ULONG64) (((((ULONG64)(Va)) & VRN_MASK_IA64)) |
  122. ((((((ULONG64)(Va)) >> PDI_SHIFT_IA64) << PTE_SHIFT_IA64) & (~(PDE_BASE_IA64|VRN_MASK_IA64))) + PDE_BASE_IA64));
  123. }
  124. ULONG64
  125. MiGetPpeAddressIA64 (
  126. IN ULONG64 Va
  127. )
  128. {
  129. DbgGetPteBaseIA64();
  130. if ((((ULONG64)(Va) & PTE_BASE_IA64) == PTE_BASE_IA64) &&
  131. ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PTE_BASE_IA64)) < ((ULONG64)1 << PDI1_SHIFT_IA64))) {
  132. return (ULONG64) (((ULONG64)Va & VRN_MASK_IA64) |
  133. (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE")));
  134. }
  135. if (((((ULONG64)(Va)) & PDE_BASE_IA64) == PDE_BASE_IA64) &&
  136. ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_BASE_IA64)) < ((ULONG64)1 << PDI_SHIFT_IA64))) {
  137. return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) |
  138. (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE")));
  139. }
  140. if (((((ULONG64)(Va)) & PDE_TBASE_IA64) == PDE_TBASE_IA64) &&
  141. ((((ULONG64)(Va)) & ~(VRN_MASK_IA64|PDE_TBASE_IA64)) < PageSize)) {
  142. return (ULONG64) ((((ULONG64)(Va)) & VRN_MASK_IA64) |
  143. (PDE_TBASE_IA64 + PageSize - GetTypeSize("nt!_MMPTE")));
  144. }
  145. return (ULONG64) (((((ULONG64)(Va)) & VRN_MASK_IA64)) |
  146. ((((((ULONG64)(Va)) >> PDI1_SHIFT_IA64) << PTE_SHIFT_IA64) &
  147. (~(PDE_TBASE_IA64|VRN_MASK_IA64))) + PDE_TBASE_IA64));
  148. }
  149. ULONG64
  150. MiGetVirtualAddressMappedByPteIA64(
  151. IN ULONG64 PTE
  152. )
  153. {
  154. DbgGetPteBaseIA64();
  155. return (((ULONG64)(PTE) & PTA_SIGN_IA64) ?
  156. (ULONG64)(((ULONG64)(PTE) & VRN_MASK_IA64) | VA_FILL_IA64 |
  157. (((ULONG64)(PTE)-PTE_BASE_IA64) << (PAGE_SHIFT_IA64 - PTE_SHIFT_IA64))) :
  158. (ULONG64)(((ULONG64)(PTE) & VRN_MASK_IA64) | (((ULONG64)(PTE)-PTE_BASE_IA64) << (PAGE_SHIFT_IA64 - PTE_SHIFT_IA64))));
  159. }
  160. #define MiGetSubsectionAddress(lpte) \
  161. (((lpte)->u.Subsect.WhichPool == 1) ? \
  162. ((ULONG64)((ULONG64)MmSubsectionBase + \
  163. ((ULONG64)(lpte)->u.Subsect.SubsectionAddress))) \
  164. : \
  165. ((ULONG64)((ULONG64)MM_NONPAGED_POOL_END - \
  166. ((ULONG64)(lpte)->u.Subsect.SubsectionAddress))))
  167. #define MiPteToProto(lpte) \
  168. ((ULONG64) ((ULONG64)((lpte)->u.Proto.ProtoAddress) + MmProtopte_Base))
  169. ////////////////////////////////////////////////////////////////////////////////
  170. //
  171. // AMD64
  172. //
  173. ////////////////////////////////////////////////////////////////////////////////
  174. VOID
  175. DbgPrintProtection (
  176. ULONG Protection
  177. )
  178. {
  179. if (Protection == 0) {
  180. dprintf("0");
  181. return;
  182. }
  183. dprintf ("%x - ", Protection);
  184. if (Protection == MM_NOACCESS) {
  185. dprintf("No Access");
  186. } else if (Protection == MM_DECOMMIT) {
  187. dprintf("Decommitted");
  188. } else {
  189. switch (Protection & 7) {
  190. case MM_READONLY: dprintf("Readonly"); break;
  191. case MM_EXECUTE: dprintf("Execute"); break;
  192. case MM_EXECUTE_READ: dprintf("ExecuteRead"); break;
  193. case MM_READWRITE: dprintf("ReadWrite"); break;
  194. case MM_WRITECOPY: dprintf("ReadWriteCopy"); break;
  195. case MM_EXECUTE_READWRITE: dprintf("ReadWriteExecute"); break;
  196. case MM_EXECUTE_WRITECOPY: dprintf("ReadWriteCopyExecute "); break;
  197. default: ;
  198. }
  199. if (Protection & MM_NOCACHE) {
  200. dprintf(" UC");
  201. }
  202. if (Protection & MM_GUARD_PAGE) {
  203. dprintf(" G");
  204. }
  205. }
  206. }
  207. ULONG64
  208. DbgPteLookupNeeded (
  209. VOID
  210. )
  211. {
  212. switch (TargetMachine) {
  213. case IMAGE_FILE_MACHINE_I386:
  214. return MI_PTE_LOOKUP_NEEDED_X86;
  215. case IMAGE_FILE_MACHINE_AMD64:
  216. return MI_PTE_LOOKUP_NEEDED_AMD64;
  217. break;
  218. case IMAGE_FILE_MACHINE_IA64:
  219. return MI_PTE_LOOKUP_NEEDED_IA64;
  220. default:
  221. break;
  222. }
  223. return 0;
  224. }
  225. LOGICAL
  226. DbgPteIsDemandZero (
  227. ULONG64 CurrentPte
  228. )
  229. {
  230. ULONG Protection = 0;
  231. ULONG64 CurrentPteContents = 0;
  232. GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
  233. GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Soft.Protection", Protection);
  234. //
  235. // The caller has already ensured that the valid, prototype & transition
  236. // bits in the PTE are all zero.
  237. //
  238. if (DbgGetPageFileHigh (CurrentPte) != 0) {
  239. return FALSE;
  240. }
  241. if ((Protection != 0) &&
  242. (Protection != MM_NOACCESS) &&
  243. (Protection != MM_DECOMMIT)) {
  244. return TRUE;
  245. }
  246. return FALSE;
  247. }
  248. #define PMMPTEx ULONG64
  249. #define PACKET_MAX_SIZE 4000
  250. typedef struct _SYS_PTE_LIST {
  251. ULONG64 Next;
  252. ULONG64 Previous;
  253. ULONG64 Value;
  254. ULONG Count;
  255. } SYS_PTE_LIST, *PSYS_PTE_LIST;
  256. ULONG MmKseg2Frame;
  257. ULONG
  258. MiGetSysPteListDelimiter (
  259. VOID
  260. )
  261. /*++
  262. Routine Description:
  263. The platform-specific system PTE list delimiter is returned.
  264. Arguments:
  265. None.
  266. --*/
  267. {
  268. switch (TargetMachine) {
  269. case IMAGE_FILE_MACHINE_I386:
  270. if (PaeEnabled) {
  271. return 0xFFFFFFFF;
  272. }
  273. return 0xFFFFF;
  274. case IMAGE_FILE_MACHINE_AMD64:
  275. return 0xFFFFFFFF;
  276. case IMAGE_FILE_MACHINE_IA64:
  277. return 0xFFFFFFFF;
  278. default:
  279. break;
  280. }
  281. return 0;
  282. }
  283. ULONG64
  284. MiGetFreeCountFromPteList (
  285. IN ULONG64 Pte
  286. )
  287. /*++
  288. Routine Description:
  289. The specified PTE points to a free list header in the
  290. system PTE pool. It returns the number of free entries
  291. in this block.
  292. Arguments:
  293. Pte - the PTE to examine.
  294. --*/
  295. {
  296. ULONG OneEntry;
  297. ULONG64 NextEntry;
  298. GetFieldValue(Pte, "MMPTE", "u.List.OneEntry", OneEntry);
  299. GetFieldValue(Pte + GetTypeSize("nt!_MMPTE"), "MMPTE", "u.List.NextEntry",NextEntry);
  300. return (( OneEntry) ?
  301. 1 :
  302. NextEntry);
  303. }
  304. DECLARE_API( sysptes )
  305. /*++
  306. Routine Description:
  307. Dumps system PTEs.
  308. Arguments:
  309. args - Flags
  310. Return Value:
  311. None
  312. --*/
  313. {
  314. ULONG ExtraPtesUnleashed;
  315. ULONG MaxPteRead;
  316. ULONG TotalNumberOfSystemPtes;
  317. ULONG64 NonPagedSystemStart;
  318. ULONG64 ExtraResourceStart;
  319. ULONG64 ExtraPteStart;
  320. ULONG NumberOfExtraPtes;
  321. ULONG PteListDelimiter;
  322. ULONG result;
  323. ULONG64 nextfreepte;
  324. ULONG Flags;
  325. ULONG LastCount;
  326. ULONG ReadCount;
  327. ULONG64 next;
  328. ULONG64 Pte;
  329. ULONG64 IndexBase;
  330. ULONG64 PteBase;
  331. ULONG64 PteBase2;
  332. ULONG64 PteArrayReal;
  333. ULONG64 PteArray2Real;
  334. PCHAR PteArray2;
  335. ULONG64 PteEnd;
  336. ULONG64 IndexBias;
  337. ULONG64 FreeStart;
  338. ULONG NumberOfSystemPtes;
  339. ULONG NumberOfPtesToCover;
  340. PCHAR PteArray;
  341. HANDLE PteHandle;
  342. ULONG64 PageCount;
  343. ULONG64 free;
  344. ULONG64 totalFree;
  345. ULONG64 largeFree;
  346. ULONG i;
  347. ULONG64 Flink;
  348. ULONG64 PteHeaderAddress;
  349. ULONG FreeSysPteListBySize[MM_SYS_PTE_TABLES_MAX];
  350. ULONG SysPteIndex [MM_SYS_PTE_TABLES_MAX];
  351. ULONG PteSize;
  352. PVOID PteData;
  353. PSYS_PTE_LIST List;
  354. CHAR Buffer[256];
  355. ULONG64 displacement;
  356. INIT_API();
  357. List = NULL;
  358. PteData = NULL;
  359. PteArray = NULL;
  360. PteHandle = (HANDLE)0;
  361. Flags = 0;
  362. sscanf(args,"%lx",&Flags);
  363. if (Flags & 8) {
  364. //
  365. // Dump the nonpaged pool expansion free PTE list only.
  366. //
  367. IndexBias = GetPointerValue ("nt!MmSystemPteBase");
  368. PteSize = GetTypeSize ("nt!_MMPTE");
  369. i = 0;
  370. totalFree = 0;
  371. largeFree = 0;
  372. PteData = LocalAlloc (LMEM_FIXED, PteSize * 2);
  373. if (!PteData) {
  374. dprintf("Unable to malloc PTE data\n");
  375. EXIT_API();
  376. return E_INVALIDARG;
  377. }
  378. FreeStart = GetExpression ("nt!MmFirstFreeSystemPte") + PteSize;
  379. if ( !ReadMemory( FreeStart,
  380. PteData,
  381. PteSize,
  382. &result) ) {
  383. dprintf("%08p: Unable to get MmFirstFreeSystemPte\n",FreeStart);
  384. LocalFree(PteData);
  385. EXIT_API();
  386. return E_INVALIDARG;
  387. }
  388. GetFieldValue(FreeStart, "nt!_MMPTE", "u.List.NextEntry", FreeStart);
  389. next = FreeStart;
  390. PteListDelimiter = MiGetSysPteListDelimiter ();
  391. while (next != PteListDelimiter) {
  392. if ( CheckControlC() ) {
  393. goto Bail;
  394. }
  395. nextfreepte = IndexBias + next * PteSize;
  396. if ( !ReadMemory( nextfreepte,
  397. PteData,
  398. PteSize * 2,
  399. &result) ) {
  400. dprintf("%16I64X: Unable to get nonpaged PTE\n", nextfreepte);
  401. break;
  402. }
  403. free = MiGetFreeCountFromPteList (nextfreepte);
  404. if (Flags & 1) {
  405. dprintf(" free ptes: %8p number free: %5I64ld.\n",
  406. nextfreepte,
  407. free);
  408. }
  409. if (free > largeFree) {
  410. largeFree = free;
  411. }
  412. totalFree += free;
  413. i += 1;
  414. GetFieldValue(nextfreepte, "nt!_MMPTE", "u.List.NextEntry", next);
  415. // next = MiGetNextFromPteList ((PMMPTE)PteData);
  416. }
  417. dprintf("\n free blocks: %ld total free: %I64ld largest free block: %I64ld\n\n",
  418. i, totalFree, largeFree);
  419. LocalFree(PteData);
  420. EXIT_API();
  421. return E_INVALIDARG;
  422. }
  423. if (Flags & 4) {
  424. PteHeaderAddress = GetExpression( "nt!MiPteHeader" );
  425. if ( GetFieldValue( PteHeaderAddress,
  426. "nt!_SYSPTES_HEADER",
  427. "Count",
  428. NumberOfSystemPtes) ) {
  429. dprintf("%08p: Unable to get System PTE lock consumer information\n",
  430. PteHeaderAddress);
  431. }
  432. else {
  433. dprintf("\n0x%I64x System PTEs allocated to mapping locked pages\n\n",
  434. NumberOfSystemPtes);
  435. dprintf("VA MDL PageCount Caller/CallersCaller\n");
  436. //
  437. // Dump the MDL and PTE addresses and 2 callers.
  438. //
  439. GetFieldValue( PteHeaderAddress,"SYSPTES_HEADER","ListHead.Flink", Flink);
  440. for (PageCount = 0; PageCount < NumberOfSystemPtes; ) {
  441. ULONG64 Count;
  442. if (Flink == PteHeaderAddress) {
  443. dprintf("early finish (%I64u) during syspte tracker dumping\n",
  444. PageCount);
  445. break;
  446. }
  447. if ( CheckControlC() ) {
  448. break;
  449. }
  450. if ( GetFieldValue( Flink,
  451. "nt!_PTE_TRACKER",
  452. "Count",
  453. Count) ) {
  454. dprintf("%08p: Unable to get System PTE individual lock consumer information\n",
  455. Flink);
  456. break;
  457. }
  458. InitTypeRead(Flink, nt!_PTE_TRACKER);
  459. dprintf("%8p %8p %8I64lx ",
  460. ReadField(SystemVa),
  461. ReadField(Mdl),
  462. Count);
  463. Buffer[0] = '!';
  464. Flink = ReadField(ListEntry.Flink);
  465. GetSymbol (ReadField(CallingAddress),
  466. (PCHAR)Buffer,
  467. &displacement);
  468. dprintf("%s", Buffer);
  469. if (displacement) {
  470. dprintf( "+0x%1p", displacement );
  471. }
  472. dprintf("/");
  473. Buffer[0] = '!';
  474. GetSymbol (ReadField(CallersCaller),
  475. (PCHAR)Buffer,
  476. &displacement);
  477. dprintf("%s", Buffer);
  478. if (displacement) {
  479. dprintf( "+0x%1p", displacement );
  480. }
  481. dprintf("\n");
  482. PageCount += Count;
  483. }
  484. }
  485. if ((Flags & ~4) == 0) {
  486. //
  487. // no other flags specified, so just return.
  488. //
  489. EXIT_API();
  490. return E_INVALIDARG;
  491. }
  492. }
  493. dprintf("\nSystem PTE Information\n");
  494. PteBase = GetPointerValue ("nt!MmSystemPtesStart");
  495. PteEnd = GetPointerValue ("nt!MmSystemPtesEnd");
  496. IndexBias = GetPointerValue ("nt!MmSystemPteBase");
  497. NumberOfSystemPtes = GetUlongValue ("nt!MmNumberOfSystemPtes");
  498. NonPagedSystemStart = GetPointerValue ("nt!MmNonPagedSystemStart");
  499. PteSize = GetTypeSize ("nt!_MMPTE");
  500. NumberOfExtraPtes = 0;
  501. NumberOfPtesToCover = (ULONG) ((PteEnd - PteBase + 1) / PteSize);
  502. //
  503. // The system PTEs may exist in 2 separate virtual address ranges.
  504. //
  505. // See if there are extra resources, if so then see if they are being
  506. // used for system PTEs (as opposed to system cache, etc).
  507. //
  508. ExtraPtesUnleashed = 0;
  509. ExtraPtesUnleashed = GetUlongValue ("MiAddPtesCount");
  510. if (ExtraPtesUnleashed != 0) {
  511. ExtraResourceStart = GetExpression ("nt!MiExtraResourceStart");
  512. if (ExtraResourceStart != 0) {
  513. NumberOfExtraPtes = GetUlongValue ("MiExtraPtes1");
  514. if (NumberOfExtraPtes != 0) {
  515. if (!ReadPointer(ExtraResourceStart,&ExtraPteStart)) {
  516. dprintf("%016I64X: Unable to read PTE start %p\n",ExtraResourceStart);
  517. goto Bail;
  518. }
  519. }
  520. }
  521. }
  522. TotalNumberOfSystemPtes = (ULONG) (NumberOfSystemPtes + NumberOfExtraPtes);
  523. dprintf(" Total System Ptes %ld\n", TotalNumberOfSystemPtes);
  524. free = GetExpression( "nt!MmSysPteIndex" );
  525. if ( !ReadMemory( free,
  526. &SysPteIndex[0],
  527. sizeof(ULONG) * MM_SYS_PTE_TABLES_MAX,
  528. &result) ) {
  529. dprintf("%08p: Unable to get PTE index\n",free);
  530. goto Bail;
  531. }
  532. free = GetExpression( "nt!MmSysPteListBySizeCount" );
  533. if ( !ReadMemory( free,
  534. &FreeSysPteListBySize[0],
  535. sizeof (FreeSysPteListBySize),
  536. &result) ) {
  537. dprintf("%08p: Unable to get free PTE index\n",free);
  538. goto Bail;
  539. }
  540. for (i = 0; i < MM_SYS_PTE_TABLES_MAX; i += 1 ) {
  541. dprintf(" SysPtes list of size %ld has %ld free\n",
  542. SysPteIndex[i],
  543. FreeSysPteListBySize[i]);
  544. }
  545. dprintf(" \n");
  546. dprintf(" starting PTE: %016I64X\n", PteBase);
  547. dprintf(" ending PTE: %016I64X\n", PteEnd);
  548. PteHandle = LocalAlloc(LMEM_MOVEABLE, NumberOfPtesToCover * PteSize);
  549. if (!PteHandle) {
  550. dprintf("Unable to get allocate memory of %ld bytes\n",
  551. NumberOfPtesToCover * PteSize);
  552. goto Bail;
  553. }
  554. MaxPteRead = ((PACKET_MAX_SIZE/PteSize)-1);
  555. PteArray = LocalLock(PteHandle);
  556. PteArrayReal = PteBase;
  557. //
  558. // If the ranges are discontiguous, zero the piece(s) in the middle.
  559. //
  560. if (NumberOfExtraPtes != 0) {
  561. RtlZeroMemory (PteArray, NumberOfPtesToCover * PteSize);
  562. }
  563. for (PageCount = 0; PageCount < NumberOfExtraPtes; PageCount += ReadCount) {
  564. if ( CheckControlC() ) {
  565. goto Bail;
  566. }
  567. dprintf("loading (%d%% complete)\r", (PageCount * 100)/ TotalNumberOfSystemPtes);
  568. ReadCount = (ULONG) (NumberOfExtraPtes - PageCount > MaxPteRead ?
  569. MaxPteRead :
  570. NumberOfExtraPtes - PageCount + 1);
  571. Pte = (PteBase + PageCount * PteSize);
  572. if ( !ReadMemory( Pte,
  573. (PCHAR)PteArray + PageCount * PteSize,
  574. ReadCount * PteSize,
  575. &result) ) {
  576. dprintf("Unable to get system pte block - "
  577. "address %p - count %lu - page %lu\n",
  578. Pte, ReadCount, PageCount);
  579. goto Bail;
  580. }
  581. }
  582. LastCount = (ULONG) PageCount;
  583. if (NumberOfSystemPtes != 0) {
  584. if (NumberOfExtraPtes != 0) {
  585. PteBase2 = DbgGetPteAddress (NonPagedSystemStart);
  586. }
  587. else {
  588. PteBase2 = PteBase;
  589. }
  590. PteArray2 = (PteArray + (ULONG) (PteBase2 - PteBase));
  591. PteArray2Real = PteBase2;
  592. for (PageCount = 0; (PageCount < NumberOfSystemPtes); PageCount += ReadCount) {
  593. if ( CheckControlC() ) {
  594. goto Bail;
  595. }
  596. dprintf("loading (%d%% complete)\r", ((LastCount + PageCount) * 100)/ TotalNumberOfSystemPtes);
  597. ReadCount = (ULONG) (NumberOfSystemPtes - PageCount > MaxPteRead ?
  598. MaxPteRead :
  599. NumberOfSystemPtes - PageCount + 1);
  600. Pte = (PteBase2 + PageCount * PteSize);
  601. if ( !ReadMemory( Pte,
  602. PteArray2 + PageCount * PteSize,
  603. ReadCount * PteSize,
  604. &result) ) {
  605. dprintf("Unable to get system pte block2 - "
  606. "address %p - count %lu - page %lu\n",
  607. Pte, ReadCount, PageCount);
  608. goto Bail;
  609. }
  610. }
  611. }
  612. dprintf("\n");
  613. //
  614. // Now we have a local copy: let's take a look.
  615. //
  616. //
  617. // Walk the free list.
  618. //
  619. IndexBase = (PteBase - IndexBias) / PteSize;
  620. totalFree = 0;
  621. i = 0;
  622. largeFree = 0;
  623. FreeStart = GetExpression ("nt!MmFirstFreeSystemPte");
  624. if ( GetFieldValue( FreeStart, "nt!_MMPTE", "u.List.NextEntry", next) ) {
  625. dprintf("%08p: Unable to get MmFirstFreeSystemPte\n",FreeStart);
  626. goto Bail;
  627. }
  628. FreeStart = next;
  629. PteListDelimiter = MiGetSysPteListDelimiter ();
  630. while (next != PteListDelimiter) {
  631. if ( CheckControlC() ) {
  632. goto Bail;
  633. }
  634. free = MiGetFreeCountFromPteList ((PteArrayReal + (next - IndexBase)* PteSize));
  635. if (Flags & 1) {
  636. dprintf(" free ptes: %8p number free: %5I64ld.\n",
  637. PteBase + (next - IndexBase) * PteSize,
  638. free);
  639. }
  640. if (free > largeFree) {
  641. largeFree = free;
  642. }
  643. totalFree += free;
  644. i += 1;
  645. GetFieldValue ((PteArrayReal + (next - IndexBase) * PteSize),
  646. "nt!_MMPTE", "u.List.NextEntry", next);
  647. }
  648. dprintf("\n free blocks: %ld total free: %I64ld largest free block: %I64ld\n\n",
  649. i, totalFree, largeFree);
  650. #if 0
  651. //
  652. // Walk through the array and sum up the usage on a per physical
  653. // page basis.
  654. //
  655. List = VirtualAlloc (NULL,
  656. (ULONG) NumberOfPtes * sizeof(SYS_PTE_LIST),
  657. MEM_COMMIT | MEM_RESERVE,
  658. PAGE_READWRITE);
  659. if (List == NULL) {
  660. dprintf("alloc failed %lx\n",GetLastError());
  661. goto Bail;
  662. }
  663. RtlZeroMemory (List, (ULONG) NumberOfPtes * sizeof(SYS_PTE_LIST));
  664. GetBitFieldOffset("nt!_MMPTE", "u.Hard.PageFrameNumber", &PfnOff, &PfnSz);
  665. free = 0;
  666. next = 0;
  667. List[0].Value = (ULONG64) -1;
  668. List[0].Previous = 0xffffff;
  669. first = 0;
  670. for (i = 0; i < NumberOfPtes ; i += 1) {
  671. ULONG64 lPte = *((PULONG64) (PteArray + i * PteSize));
  672. Page =0;
  673. if ((lPte >> ValidOff) & 1) {
  674. Page = GetBits(lPte, PfnOff, PfnSz); // DbgGetFrameNumber (PteArray + i * PteSize);
  675. }
  676. if (!(i%100)) dprintf("%c\r",rot[(i/100) % 4]);
  677. if (Page != 0) {
  678. // dprintf("Adding PTE @ %p, Pfn %p\n", PteArrayReal + i*PteSize, Page);
  679. next = first;
  680. while (Page > List[next].Value) {
  681. next = List[next].Next;
  682. }
  683. if (List[next].Value == Page) {
  684. List[next].Count += 1;
  685. } else {
  686. free += 1;
  687. List[free].Next = next;
  688. List[free].Value = Page;
  689. List[free].Count = 1;
  690. List[free].Previous = List[next].Previous;
  691. if (next == first) {
  692. first = free;
  693. } else {
  694. List[List[next].Previous].Next = free;
  695. }
  696. List[next].Previous = free;
  697. }
  698. }
  699. if ( CheckControlC() ) {
  700. goto Bail;
  701. }
  702. }
  703. next = first;
  704. dprintf (" Page Count\n");
  705. while (List[next].Value != (ULONG64) -1) {
  706. if ((Flags & 2) || (List[next].Count > 1)) {
  707. dprintf (" %8p %5ld.\n", List[next].Value, List[next].Count);
  708. }
  709. next = List[next].Next;
  710. if ( CheckControlC() ) {
  711. goto Bail;
  712. }
  713. }
  714. #endif
  715. Bail:
  716. if (PteArray) {
  717. LocalUnlock(PteArray);
  718. if (PteHandle) {
  719. LocalFree((void *)PteHandle);
  720. }
  721. }
  722. if (List) {
  723. VirtualFree (List, 0, MEM_RELEASE);
  724. }
  725. EXIT_API();
  726. return S_OK;
  727. }
  728. ULONG64
  729. DbgGetFrameNumber(
  730. ULONG64 Pte
  731. )
  732. {
  733. ULONG Valid=0;
  734. ULONG Prototype=0;
  735. ULONG Transition=0;
  736. ULONG64 PageFrameNumber=0;
  737. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Valid", Valid);
  738. if (Valid) {
  739. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.PageFrameNumber", PageFrameNumber);
  740. }
  741. else {
  742. GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.Prototype", Prototype);
  743. if (Prototype == 0) {
  744. GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.Transition", Transition);
  745. if (Transition == 1) {
  746. GetFieldValue(Pte, "_MMPTE", "u.Trans.PageFrameNumber", PageFrameNumber);
  747. }
  748. else {
  749. // Must be pagefile or demand zero.
  750. GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.PageFileHigh", PageFrameNumber);
  751. }
  752. }
  753. }
  754. return PageFrameNumber;
  755. }
  756. ULONG
  757. DbgGetOwner(
  758. ULONG64 Pte
  759. )
  760. {
  761. ULONG Owner=0;
  762. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Owner", Owner);
  763. return Owner;
  764. }
  765. ULONG
  766. DbgGetValid(
  767. ULONG64 Pte
  768. )
  769. {
  770. ULONG Valid=0;
  771. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Valid", Valid);
  772. return Valid;
  773. }
  774. ULONG
  775. DbgGetDirty(
  776. ULONG64 Pte
  777. )
  778. {
  779. ULONG Dirty=0;
  780. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Dirty", Dirty);
  781. return Dirty;
  782. }
  783. ULONG
  784. DbgGetAccessed(
  785. ULONG64 Pte
  786. )
  787. {
  788. ULONG Accessed=0;
  789. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Accessed", Accessed);
  790. return Accessed;
  791. }
  792. ULONG
  793. DbgGetWrite(
  794. ULONG64 Pte
  795. )
  796. {
  797. ULONG Write=0;
  798. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Write", Write);
  799. return Write;
  800. }
  801. ULONG
  802. DbgGetExecute(
  803. ULONG64 Pte
  804. )
  805. {
  806. ULONG Execute=0;
  807. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.Execute", Execute);
  808. return Execute;
  809. }
  810. ULONG
  811. DbgGetCopyOnWrite(
  812. ULONG64 Pte
  813. )
  814. {
  815. ULONG CopyOnWrite=0;
  816. GetFieldValue(Pte, "nt!_MMPTE", "u.Hard.CopyOnWrite", CopyOnWrite);
  817. return CopyOnWrite;
  818. }
  819. ULONG
  820. DbgGetPageFileHigh(
  821. ULONG64 Pte
  822. )
  823. {
  824. ULONG64 PageFileHigh=0;
  825. GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.PageFileHigh", PageFileHigh);
  826. return (ULONG) PageFileHigh;
  827. }
  828. ULONG
  829. DbgGetPageFileLow(
  830. ULONG64 Pte
  831. )
  832. {
  833. ULONG PageFileLow=0;
  834. GetFieldValue(Pte, "nt!_MMPTE", "u.Soft.PageFileLow", PageFileLow);
  835. return PageFileLow;
  836. }
  837. ULONG64
  838. DbgPteToProto(
  839. ULONG64 lpte
  840. )
  841. {
  842. ULONG64 PteLong=0;
  843. ULONG64 ProtoAddress=0;
  844. if (TargetMachine != IMAGE_FILE_MACHINE_I386) {
  845. GetFieldValue(lpte, "nt!_MMPTE", "u.Proto.ProtoAddress",ProtoAddress);
  846. return ProtoAddress;
  847. }
  848. if (PaeEnabled) {
  849. GetFieldValue(lpte, "nt!_MMPTE", "u.Proto.ProtoAddress",ProtoAddress);
  850. return ProtoAddress;
  851. }
  852. GetFieldValue(lpte, "nt!_MMPTE", "u.Long", PteLong);
  853. ProtoAddress = (((ULONG)PteLong >> 11) << 9) + (((ULONG)PteLong << 24) >> 23) + 0xE1000000;
  854. return ProtoAddress;
  855. }
  856. ULONG64
  857. DbgGetSubsectionAddress(
  858. IN ULONG64 Pte
  859. )
  860. {
  861. ULONG64 PteLong=0;
  862. ULONG64 MmSubsectionBase;
  863. ULONG64 SubsectionAddress=0;
  864. if (PaeEnabled &&
  865. (TargetMachine == IMAGE_FILE_MACHINE_I386)) {
  866. ULONG64 SubsectionAddress=0;
  867. GetFieldValue(Pte, "nt!_MMPTE", "u.Subsect.SubsectionAddress", SubsectionAddress);
  868. return SubsectionAddress;
  869. }
  870. MmSubsectionBase = GetNtDebuggerDataPtrValue(MmSubsectionBase);
  871. GetFieldValue(Pte, "nt!_MMPTE", "u.Long", PteLong);
  872. switch (TargetMachine) {
  873. case IMAGE_FILE_MACHINE_I386:{
  874. if (!MmNonPagedPoolEnd) {
  875. MmNonPagedPoolEnd = GetNtDebuggerDataValue(MmNonPagedPoolEnd);
  876. }
  877. SubsectionAddress =
  878. ((PteLong & 0x80000000) ?
  879. (((ULONG) MmSubsectionBase + (((PteLong & 0x7ffff800) >> 4) |
  880. ((PteLong<<2) & 0x78))))
  881. :
  882. (((ULONG) MmNonPagedPoolEnd - ((((PteLong)>>11)<<7) |
  883. ((PteLong<<2) & 0x78)))));
  884. SubsectionAddress = (ULONG64) (LONG64) (LONG) SubsectionAddress;
  885. break;
  886. }
  887. case IMAGE_FILE_MACHINE_AMD64: {
  888. LONG64 SignedSubsectionAddress;
  889. GetFieldValue(Pte, "nt!_MMPTE", "u.Subsect.SubsectionAddress", SignedSubsectionAddress);
  890. SubsectionAddress = (ULONG64) SignedSubsectionAddress;
  891. break;
  892. }
  893. case IMAGE_FILE_MACHINE_IA64: {
  894. ULONG64 WhichPool=0, SubsectionAddress2=0;
  895. GetFieldValue(Pte, "nt!_MMPTE", "u.Subsect.SubsectionAddress", SubsectionAddress2);
  896. GetFieldValue(Pte, "nt!_MMPTE", "u.Subsect.WhichPool", WhichPool);
  897. if (!MmNonPagedPoolEnd) {
  898. MmNonPagedPoolEnd = GetNtDebuggerDataValue(MmNonPagedPoolEnd);
  899. }
  900. SubsectionAddress =
  901. ((WhichPool == 1) ?
  902. ((MmSubsectionBase + (SubsectionAddress2)))
  903. :
  904. ((MmNonPagedPoolEnd -
  905. (SubsectionAddress2))));
  906. break;
  907. }
  908. default:
  909. return FALSE;
  910. } /* switch */
  911. return SubsectionAddress;
  912. }
  913. ULONG64
  914. DbgGetPdeAddress(
  915. IN ULONG64 VirtualAddress
  916. )
  917. {
  918. switch (TargetMachine) {
  919. case IMAGE_FILE_MACHINE_I386:
  920. if (PaeEnabled) {
  921. return PaeGetPdeAddressX86 (VirtualAddress);
  922. }
  923. return MiGetPdeAddressX86(VirtualAddress);
  924. case IMAGE_FILE_MACHINE_AMD64:
  925. return MiGetPdeAddressAMD64(VirtualAddress);
  926. case IMAGE_FILE_MACHINE_IA64:
  927. return MiGetPdeAddressIA64(VirtualAddress);
  928. default:
  929. break;
  930. }
  931. return 0;
  932. }
  933. ULONG64
  934. DbgGetPpeAddress(
  935. IN ULONG64 VirtualAddress
  936. )
  937. {
  938. switch (TargetMachine) {
  939. case IMAGE_FILE_MACHINE_AMD64:
  940. return MiGetPpeAddressAMD64(VirtualAddress);
  941. case IMAGE_FILE_MACHINE_IA64:
  942. return MiGetPpeAddressIA64(VirtualAddress);
  943. default:
  944. break;
  945. }
  946. return 0;
  947. }
  948. ULONG64
  949. DbgGetPxeAddress(
  950. IN ULONG64 VirtualAddress
  951. )
  952. {
  953. switch (TargetMachine) {
  954. case IMAGE_FILE_MACHINE_AMD64:
  955. return MiGetPxeAddressAMD64(VirtualAddress);
  956. default:
  957. break;
  958. }
  959. return 0;
  960. }
  961. ULONG64
  962. DbgGetVirtualAddressMappedByPte(
  963. IN ULONG64 Pte
  964. )
  965. {
  966. switch (TargetMachine) {
  967. case IMAGE_FILE_MACHINE_I386:
  968. if (PaeEnabled) {
  969. return PaeGetVirtualAddressMappedByPteX86(Pte);
  970. }
  971. return MiGetVirtualAddressMappedByPteX86 (Pte);
  972. case IMAGE_FILE_MACHINE_AMD64:
  973. return MiGetVirtualAddressMappedByPteAMD64 (Pte);
  974. case IMAGE_FILE_MACHINE_IA64:
  975. return MiGetVirtualAddressMappedByPteIA64 (Pte);
  976. default:
  977. break;
  978. }
  979. return 0;
  980. }
  981. ULONG64
  982. DbgGetPteAddress(
  983. IN ULONG64 VirtualAddress
  984. )
  985. {
  986. switch (TargetMachine) {
  987. case IMAGE_FILE_MACHINE_I386:{
  988. if (PaeEnabled) {
  989. return PaeGetPteAddressX86 (VirtualAddress);
  990. }
  991. return MiGetPteAddressX86(VirtualAddress);
  992. }
  993. case IMAGE_FILE_MACHINE_AMD64: {
  994. return MiGetPteAddressAMD64(VirtualAddress);
  995. }
  996. case IMAGE_FILE_MACHINE_IA64: {
  997. return MiGetPteAddressIA64(VirtualAddress);
  998. }
  999. default:
  1000. return FALSE;
  1001. } /* switch */
  1002. return FALSE;
  1003. }
  1004. BOOL
  1005. Mi_Is_Physical_Address (
  1006. ULONG64 VirtualAddress
  1007. )
  1008. {
  1009. switch (TargetMachine) {
  1010. case IMAGE_FILE_MACHINE_IA64: {
  1011. return MI_IS_PHYSICAL_ADDRESS_IA64(VirtualAddress);
  1012. }
  1013. default:
  1014. return FALSE;
  1015. } /* switch */
  1016. return FALSE;
  1017. }
  1018. ULONG
  1019. DBG_GET_PAGE_SHIFT (
  1020. VOID
  1021. )
  1022. {
  1023. switch (TargetMachine) {
  1024. case IMAGE_FILE_MACHINE_I386:{
  1025. return PAGE_SHIFT_X86;
  1026. }
  1027. case IMAGE_FILE_MACHINE_AMD64: {
  1028. return PAGE_SHIFT_AMD64;
  1029. }
  1030. case IMAGE_FILE_MACHINE_IA64: {
  1031. return PAGE_SHIFT_IA64;
  1032. }
  1033. default:
  1034. return FALSE;
  1035. } /* switch */
  1036. return FALSE;
  1037. }
  1038. ULONG64
  1039. DBG_GET_MM_SESSION_SPACE_DEFAULT (
  1040. VOID
  1041. )
  1042. {
  1043. switch (TargetMachine) {
  1044. case IMAGE_FILE_MACHINE_I386:{
  1045. return MM_SESSION_SPACE_DEFAULT_X86;
  1046. }
  1047. case IMAGE_FILE_MACHINE_AMD64: {
  1048. return MM_SESSION_SPACE_DEFAULT_AMD64;
  1049. }
  1050. case IMAGE_FILE_MACHINE_IA64: {
  1051. return MM_SESSION_SPACE_DEFAULT_IA64;
  1052. }
  1053. default:
  1054. return FALSE;
  1055. } /* switch */
  1056. return FALSE;
  1057. }
  1058. ULONG
  1059. GET_MM_PTE_VALID_MASK (
  1060. VOID
  1061. )
  1062. {
  1063. switch (TargetMachine) {
  1064. case IMAGE_FILE_MACHINE_I386:{
  1065. return MM_PTE_VALID_MASK_X86;
  1066. }
  1067. case IMAGE_FILE_MACHINE_AMD64: {
  1068. return MM_PTE_VALID_MASK_AMD64;
  1069. }
  1070. case IMAGE_FILE_MACHINE_IA64: {
  1071. return MM_PTE_VALID_MASK_IA64;
  1072. }
  1073. default:
  1074. return FALSE;
  1075. } /* switch */
  1076. return FALSE;
  1077. }
  1078. ULONG
  1079. GET_MM_PTE_LARGE_PAGE_MASK (
  1080. VOID
  1081. )
  1082. {
  1083. switch (TargetMachine) {
  1084. case IMAGE_FILE_MACHINE_I386:{
  1085. return MM_PTE_LARGE_PAGE_MASK_X86;
  1086. }
  1087. case IMAGE_FILE_MACHINE_AMD64:{
  1088. return MM_PTE_LARGE_PAGE_MASK_AMD64;
  1089. }
  1090. case IMAGE_FILE_MACHINE_IA64: {
  1091. return MM_PTE_LARGE_PAGE_MASK_IA64;
  1092. }
  1093. default:
  1094. return FALSE;
  1095. } /* switch */
  1096. return FALSE;
  1097. }
  1098. ULONG
  1099. GET_MM_PTE_TRANSITION_MASK (
  1100. VOID
  1101. )
  1102. {
  1103. switch (TargetMachine) {
  1104. case IMAGE_FILE_MACHINE_I386:{
  1105. return MM_PTE_TRANSITION_MASK_X86;
  1106. }
  1107. case IMAGE_FILE_MACHINE_AMD64:{
  1108. return MM_PTE_TRANSITION_MASK_AMD64;
  1109. }
  1110. case IMAGE_FILE_MACHINE_IA64: {
  1111. return MM_PTE_TRANSITION_MASK_IA64;
  1112. }
  1113. default:
  1114. return FALSE;
  1115. } /* switch */
  1116. return FALSE;
  1117. }
  1118. ULONG
  1119. GET_MM_PTE_PROTOTYPE_MASK (
  1120. VOID
  1121. )
  1122. {
  1123. switch (TargetMachine) {
  1124. case IMAGE_FILE_MACHINE_I386:{
  1125. return MM_PTE_PROTOTYPE_MASK_X86;
  1126. }
  1127. case IMAGE_FILE_MACHINE_AMD64:{
  1128. return MM_PTE_PROTOTYPE_MASK_AMD64;
  1129. }
  1130. case IMAGE_FILE_MACHINE_IA64: {
  1131. return MM_PTE_PROTOTYPE_MASK_IA64;
  1132. }
  1133. default:
  1134. return FALSE;
  1135. } /* switch */
  1136. return FALSE;
  1137. }
  1138. ULONG
  1139. GET_MM_PTE_PROTECTION_MASK (
  1140. VOID
  1141. )
  1142. {
  1143. switch (TargetMachine) {
  1144. case IMAGE_FILE_MACHINE_I386:{
  1145. return MM_PTE_PROTECTION_MASK_X86;
  1146. }
  1147. case IMAGE_FILE_MACHINE_AMD64:{
  1148. return MM_PTE_PROTECTION_MASK_AMD64;
  1149. }
  1150. case IMAGE_FILE_MACHINE_IA64: {
  1151. return MM_PTE_PROTECTION_MASK_IA64;
  1152. }
  1153. default:
  1154. return FALSE;
  1155. } /* switch */
  1156. return FALSE;
  1157. }
  1158. ULONG
  1159. GET_MM_PTE_PAGEFILE_MASK (
  1160. VOID
  1161. )
  1162. {
  1163. switch (TargetMachine) {
  1164. case IMAGE_FILE_MACHINE_I386:{
  1165. return MM_PTE_PAGEFILE_MASK_X86;
  1166. }
  1167. case IMAGE_FILE_MACHINE_AMD64:{
  1168. return MM_PTE_PAGEFILE_MASK_AMD64;
  1169. }
  1170. case IMAGE_FILE_MACHINE_IA64: {
  1171. return MM_PTE_PAGEFILE_MASK_IA64;
  1172. }
  1173. default:
  1174. return FALSE;
  1175. } /* switch */
  1176. return FALSE;
  1177. }
  1178. ULONG64
  1179. GET_PTE_TOP (
  1180. VOID
  1181. )
  1182. {
  1183. switch (TargetMachine) {
  1184. case IMAGE_FILE_MACHINE_I386:{
  1185. return PTE_TOP_X86;
  1186. }
  1187. case IMAGE_FILE_MACHINE_IA64: {
  1188. return PDE_TOP_IA64;
  1189. }
  1190. case IMAGE_FILE_MACHINE_AMD64: {
  1191. return PTE_TOP_AMD64;
  1192. }
  1193. default:
  1194. return FALSE;
  1195. } /* switch */
  1196. return FALSE;
  1197. }
  1198. ULONG64
  1199. GET_PDE_TOP (
  1200. VOID
  1201. )
  1202. {
  1203. return GET_PTE_TOP();
  1204. }
  1205. ULONG64
  1206. GET_PTE_BASE (
  1207. VOID
  1208. )
  1209. {
  1210. switch (TargetMachine) {
  1211. case IMAGE_FILE_MACHINE_I386:{
  1212. return PTE_BASE_X86;
  1213. }
  1214. case IMAGE_FILE_MACHINE_IA64: {
  1215. return PTE_BASE_IA64;
  1216. }
  1217. case IMAGE_FILE_MACHINE_AMD64: {
  1218. return PTE_BASE_AMD64;
  1219. }
  1220. default:
  1221. return FALSE;
  1222. } /* switch */
  1223. return FALSE;
  1224. }
  1225. ULONG
  1226. GetAddressState(
  1227. IN ULONG64 VirtualAddress
  1228. )
  1229. {
  1230. ULONG64 Address;
  1231. ULONG result;
  1232. ULONG64 Pte;
  1233. ULONG64 Pde;
  1234. ULONG PdeContents;
  1235. ULONG PteContents;
  1236. if (Mi_Is_Physical_Address (VirtualAddress)) {
  1237. return ADDRESS_VALID;
  1238. }
  1239. Address = VirtualAddress;
  1240. Pde = DbgGetPdeAddress (VirtualAddress);
  1241. Pte = DbgGetPteAddress (VirtualAddress);
  1242. if ( !ReadMemory( Pde,
  1243. &PdeContents,
  1244. sizeof(ULONG),
  1245. &result) ) {
  1246. dprintf("%08p: Unable to get PDE\n",Pde);
  1247. return ADDRESS_NOT_VALID;
  1248. }
  1249. if (PdeContents & GET_MM_PTE_VALID_MASK()) {
  1250. if (PdeContents & GET_MM_PTE_LARGE_PAGE_MASK()) {
  1251. return ADDRESS_VALID;
  1252. }
  1253. if ( !ReadMemory( Pte,
  1254. &PteContents,
  1255. sizeof(ULONG),
  1256. &result) ) {
  1257. dprintf("%08p: Unable to get PTE\n",Pte);
  1258. return ADDRESS_NOT_VALID;
  1259. }
  1260. if (PteContents & GET_MM_PTE_VALID_MASK()) {
  1261. return ADDRESS_VALID;
  1262. }
  1263. if (PteContents & GET_MM_PTE_TRANSITION_MASK()) {
  1264. if (!(PteContents & GET_MM_PTE_PROTOTYPE_MASK())) {
  1265. return ADDRESS_TRANSITION;
  1266. }
  1267. }
  1268. }
  1269. return ADDRESS_NOT_VALID;
  1270. }
  1271. VOID
  1272. DbgDisplayInvalidPte (
  1273. ULONG64 CurrentPte,
  1274. ULONG64 flags,
  1275. PCHAR Indent
  1276. )
  1277. {
  1278. ULONG Transition = 0;
  1279. ULONG Protection = 0;
  1280. ULONG PrototypeBit = 0;
  1281. ULONG64 CurrentPteContents;
  1282. ULONG PteSize;
  1283. PteSize = GetTypeSize ("nt!_MMPTE");
  1284. GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
  1285. GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Soft.Prototype", PrototypeBit);
  1286. dprintf("not valid\n", Indent);
  1287. GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Soft.Protection", Protection);
  1288. GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Soft.Transition", Transition);
  1289. if (PrototypeBit) {
  1290. if (DbgGetPageFileHigh (CurrentPte) == DbgPteLookupNeeded ()) {
  1291. dprintf("%s Proto: VAD\n", Indent);
  1292. dprintf("%s Protect: ", Indent);
  1293. DbgPrintProtection (Protection);
  1294. }
  1295. else if (flags) {
  1296. if (PteSize == 4) {
  1297. dprintf("%s Subsection: %08I64X\n",
  1298. Indent,
  1299. DbgGetSubsectionAddress (CurrentPte));
  1300. }
  1301. else {
  1302. dprintf("%s Subsection: %016I64X\n",
  1303. Indent,
  1304. DbgGetSubsectionAddress (CurrentPte));
  1305. }
  1306. dprintf("%s Protect: ", Indent);
  1307. DbgPrintProtection (Protection);
  1308. }
  1309. else {
  1310. if (PteSize == 4) {
  1311. dprintf("%s Proto: %08I64X\n",
  1312. Indent,
  1313. DbgPteToProto (CurrentPte));
  1314. }
  1315. else {
  1316. dprintf("%s Proto: %016I64X\n",
  1317. Indent,
  1318. DbgPteToProto (CurrentPte));
  1319. }
  1320. }
  1321. } else if (Transition) {
  1322. dprintf("%s Transition: %x\n",
  1323. Indent,
  1324. (ULONG) DbgGetFrameNumber (CurrentPte));
  1325. dprintf("%s Protect: ", Indent);
  1326. DbgPrintProtection (Protection);
  1327. } else if (CurrentPteContents != 0) {
  1328. if (DbgPteIsDemandZero (CurrentPte)) {
  1329. dprintf("%s DemandZero\n", Indent);
  1330. }
  1331. else {
  1332. dprintf("%s PageFile: %2lx\n",
  1333. Indent,
  1334. DbgGetPageFileLow (CurrentPte));
  1335. dprintf("%s Offset: %lx\n", Indent, DbgGetPageFileHigh (CurrentPte));
  1336. }
  1337. dprintf("%s Protect: ", Indent);
  1338. DbgPrintProtection (Protection);
  1339. }
  1340. dprintf ("\n");
  1341. }
  1342. VOID
  1343. DbgDisplayValidPte (
  1344. ULONG64 Pte
  1345. )
  1346. {
  1347. ULONG64 Pte_Long;
  1348. if (Pte == 0) {
  1349. return;
  1350. }
  1351. switch (TargetMachine) {
  1352. case IMAGE_FILE_MACHINE_I386:
  1353. case IMAGE_FILE_MACHINE_AMD64:
  1354. GetFieldValue(Pte, "nt!_MMPTE", "u.Long", Pte_Long);
  1355. dprintf("pfn %x %c%c%c%c%c%c%c%c%cV",
  1356. (ULONG) DbgGetFrameNumber(Pte),
  1357. DbgGetCopyOnWrite(Pte) ? 'C' : '-',
  1358. Pte_Long & 0x100 ? 'G' : '-',
  1359. Pte_Long & 0x80 ? 'L' : '-',
  1360. DbgGetDirty(Pte) ? 'D' : '-',
  1361. DbgGetAccessed(Pte) ? 'A' : '-',
  1362. Pte_Long & 0x10 ? 'N' : '-',
  1363. Pte_Long & 0x8 ? 'T' : '-',
  1364. DbgGetOwner(Pte) ? 'U' : 'K',
  1365. Pte_Long & 0x2 ? 'W' : 'R');
  1366. break;
  1367. case IMAGE_FILE_MACHINE_IA64:
  1368. dprintf("pfn %x %c%c%c%c%c%cV",
  1369. (ULONG) DbgGetFrameNumber(Pte),
  1370. DbgGetExecute(Pte) ? 'E' : '-',
  1371. DbgGetCopyOnWrite(Pte) ? 'C' : '-',
  1372. DbgGetDirty(Pte) ? 'D' : '-',
  1373. DbgGetAccessed(Pte) ? 'A' : '-',
  1374. DbgGetOwner(Pte) ? 'U' : 'K',
  1375. DbgGetWrite(Pte) ? 'W' : 'R');
  1376. break;
  1377. default:
  1378. break;
  1379. }
  1380. }
  1381. LOGICAL
  1382. DbgAddressSelfMapped (
  1383. ULONG64 Address
  1384. )
  1385. {
  1386. switch (TargetMachine) {
  1387. case IMAGE_FILE_MACHINE_I386:
  1388. if ((Address >= GET_PTE_BASE()) && (Address < GET_PTE_TOP())) {
  1389. return TRUE;
  1390. }
  1391. break;
  1392. case IMAGE_FILE_MACHINE_IA64:
  1393. if (((Address & PTE_BASE_IA64) == PTE_BASE_IA64) &&
  1394. ((Address & ~(VRN_MASK_IA64|PTE_BASE_IA64)) < ((ULONG64)1 << PDI1_SHIFT_IA64))) {
  1395. return TRUE;
  1396. }
  1397. else if (((Address & PDE_BASE_IA64) == PDE_BASE_IA64) &&
  1398. ((Address & ~(VRN_MASK_IA64|PDE_BASE_IA64)) < ((ULONG64)1 << PDI_SHIFT_IA64))) {
  1399. return TRUE;
  1400. }
  1401. else if (((Address & PDE_TBASE_IA64) == PDE_TBASE_IA64) &&
  1402. ((Address & ~(VRN_MASK_IA64|PDE_TBASE_IA64)) < PageSize)) {
  1403. return TRUE;
  1404. }
  1405. break;
  1406. case IMAGE_FILE_MACHINE_AMD64:
  1407. if ((Address >= PTE_BASE_AMD64) && (Address <= PTE_TOP_AMD64)) {
  1408. return TRUE;
  1409. }
  1410. break;
  1411. default:
  1412. break;
  1413. }
  1414. return FALSE;
  1415. }
  1416. VOID
  1417. DumpPte (
  1418. ULONG64 Address,
  1419. ULONG64 flags
  1420. )
  1421. {
  1422. PCHAR Indent;
  1423. ULONG Levels;
  1424. ULONG64 Pte;
  1425. ULONG64 Pde;
  1426. ULONG64 Ppe;
  1427. ULONG64 Pxe;
  1428. ULONG64 CurrentPte;
  1429. ULONG64 CurrentPteContents;
  1430. ULONG ValidBit;
  1431. ULONG64 Pde_Long=0;
  1432. ULONG64 Pte_Long=0;
  1433. ULONG64 Ppe_Long=0;
  1434. ULONG64 Pxe_Long=0;
  1435. ULONG PteSize;
  1436. PteSize = GetTypeSize ("nt!_MMPTE");
  1437. switch (TargetMachine) {
  1438. case IMAGE_FILE_MACHINE_I386:
  1439. Levels = 2;
  1440. break;
  1441. case IMAGE_FILE_MACHINE_IA64:
  1442. Levels = 3;
  1443. break;
  1444. case IMAGE_FILE_MACHINE_AMD64:
  1445. Levels = 4;
  1446. break;
  1447. default:
  1448. dprintf("Not implemented for this platform\n");
  1449. return;
  1450. break;
  1451. }
  1452. if (DbgAddressSelfMapped (Address)) {
  1453. if (!flags) {
  1454. //
  1455. // The address is the address of a PTE, rather than
  1456. // a virtual address. Don't get the corresponding
  1457. // PTE contents, use this address as the PTE.
  1458. //
  1459. Address = DbgGetVirtualAddressMappedByPte (Address);
  1460. }
  1461. }
  1462. if (!flags) {
  1463. Pxe = DbgGetPxeAddress (Address);
  1464. Ppe = DbgGetPpeAddress (Address);
  1465. Pde = DbgGetPdeAddress (Address);
  1466. Pte = DbgGetPteAddress (Address);
  1467. } else {
  1468. Pxe = Address;
  1469. Ppe = Address;
  1470. Pde = Address;
  1471. Pte = Address;
  1472. }
  1473. if (Levels >= 3) {
  1474. dprintf(" VA %016p\n", Address);
  1475. }
  1476. else {
  1477. dprintf(" VA %08p\n", Address);
  1478. }
  1479. if (Levels == 4) {
  1480. dprintf("PXE @ %016P PPE at %016P PDE at %016P PTE at %016P\n",
  1481. Pxe, Ppe, Pde, Pte);
  1482. }
  1483. else if (Levels == 3) {
  1484. dprintf("PPE at %016P PDE at %016P PTE at %016P\n",
  1485. Ppe, Pde, Pte);
  1486. }
  1487. else {
  1488. if (PteSize == 4) {
  1489. dprintf("PDE at %08P PTE at %08P\n", Pde, Pte);
  1490. }
  1491. else {
  1492. dprintf("PDE at %016P PTE at %016P\n", Pde, Pte);
  1493. }
  1494. }
  1495. //
  1496. // Decode the PXE.
  1497. //
  1498. if (Levels >= 4) {
  1499. CurrentPte = Pxe;
  1500. if (GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Hard.Valid", ValidBit)) {
  1501. dprintf("Unable to get PXE %I64X\n", CurrentPte);
  1502. return;
  1503. }
  1504. GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
  1505. Pxe_Long = CurrentPteContents;
  1506. if (ValidBit == 0) {
  1507. dprintf("contains %016I64X unavailable\n", Pxe_Long);
  1508. Indent = "";
  1509. if (CurrentPteContents != 0) {
  1510. DbgDisplayInvalidPte (CurrentPte, flags, Indent);
  1511. }
  1512. else {
  1513. dprintf ("\n");
  1514. }
  1515. return;
  1516. }
  1517. }
  1518. //
  1519. // Decode the PPE.
  1520. //
  1521. if (Levels >= 3) {
  1522. CurrentPte = Ppe;
  1523. if (GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Hard.Valid", ValidBit)) {
  1524. dprintf("Unable to get PPE %I64X\n", CurrentPte);
  1525. return;
  1526. }
  1527. GetFieldValue (CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
  1528. Ppe_Long = CurrentPteContents;
  1529. if (ValidBit == 0) {
  1530. if (Levels >= 4) {
  1531. dprintf("contains %016I64X contains %016I64X\n",
  1532. Pxe_Long, Ppe_Long);
  1533. Indent = " ";
  1534. DbgDisplayValidPte (Pxe);
  1535. }
  1536. else {
  1537. dprintf("contains %016I64X\n",
  1538. Ppe_Long);
  1539. Indent = "";
  1540. }
  1541. if (CurrentPteContents != 0) {
  1542. DbgDisplayInvalidPte (CurrentPte, flags, Indent);
  1543. }
  1544. else {
  1545. dprintf ("\n");
  1546. }
  1547. return;
  1548. }
  1549. }
  1550. //
  1551. // Decode the PDE.
  1552. //
  1553. CurrentPte = Pde;
  1554. if ( GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Hard.Valid", ValidBit) ) {
  1555. dprintf("Unable to get PDE %I64X\n", CurrentPte);
  1556. return;
  1557. }
  1558. GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
  1559. Pde_Long = CurrentPteContents;
  1560. if (ValidBit == 0) {
  1561. if (Levels >= 4) {
  1562. dprintf("contains %016I64X contains %016I64X contains %016I64X\n",
  1563. Pxe_Long, Ppe_Long, Pde_Long);
  1564. DbgDisplayValidPte (Pxe);
  1565. dprintf (" ");
  1566. DbgDisplayValidPte (Ppe);
  1567. Indent = " ";
  1568. }
  1569. else if (Levels == 3) {
  1570. dprintf("contains %016I64X contains %016I64X\n",
  1571. Ppe_Long, Pde_Long);
  1572. DbgDisplayValidPte (Ppe);
  1573. Indent = " ";
  1574. }
  1575. else {
  1576. if (PteSize == 4) {
  1577. dprintf("contains %08I64X\n", Pde_Long);
  1578. }
  1579. else {
  1580. dprintf("contains %016I64X\n", Pde_Long);
  1581. }
  1582. Indent = "";
  1583. }
  1584. if (CurrentPteContents != 0) {
  1585. DbgDisplayInvalidPte (CurrentPte, flags, Indent);
  1586. }
  1587. else {
  1588. dprintf ("\n");
  1589. }
  1590. return;
  1591. }
  1592. //
  1593. // Decode the PTE and print everything out.
  1594. //
  1595. CurrentPte = Pte;
  1596. if ( GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Hard.Valid", ValidBit) ) {
  1597. dprintf("Unable to get PTE %I64X\n", CurrentPte);
  1598. return;
  1599. }
  1600. GetFieldValue(CurrentPte, "nt!_MMPTE", "u.Long", CurrentPteContents);
  1601. if (Pde_Long & GET_MM_PTE_LARGE_PAGE_MASK()) {
  1602. CurrentPteContents = 0;
  1603. }
  1604. Pte_Long = CurrentPteContents;
  1605. //
  1606. // Print the raw values.
  1607. //
  1608. if (Levels == 4) {
  1609. dprintf("contains %016I64X contains %016I64X contains %016I64X contains %016I64X\n",
  1610. Pxe_Long, Ppe_Long, Pde_Long, Pte_Long);
  1611. Indent = " ";
  1612. DbgDisplayValidPte (Pxe);
  1613. dprintf (" ");
  1614. DbgDisplayValidPte (Ppe);
  1615. dprintf (" ");
  1616. DbgDisplayValidPte (Pde);
  1617. dprintf (" ");
  1618. }
  1619. else if (Levels == 3) {
  1620. dprintf("contains %016I64X contains %016I64X contains %016I64X\n",
  1621. Ppe_Long, Pde_Long, Pte_Long);
  1622. Indent = " ";
  1623. DbgDisplayValidPte (Ppe);
  1624. dprintf (" ");
  1625. DbgDisplayValidPte (Pde);
  1626. dprintf (" ");
  1627. }
  1628. else {
  1629. if (PteSize == 4) {
  1630. dprintf("contains %08I64X contains %08I64X\n", Pde_Long, Pte_Long);
  1631. Indent = " ";
  1632. }
  1633. else {
  1634. dprintf("contains %016I64X contains %016I64X\n", Pde_Long, Pte_Long);
  1635. Indent = " ";
  1636. }
  1637. DbgDisplayValidPte (Pde);
  1638. dprintf (" ");
  1639. }
  1640. if (Pde_Long & GET_MM_PTE_LARGE_PAGE_MASK()) {
  1641. dprintf ("LARGE PAGE\n");
  1642. }
  1643. else if (ValidBit != 0) {
  1644. DbgDisplayValidPte (Pte);
  1645. dprintf ("\n");
  1646. }
  1647. else {
  1648. if (CurrentPteContents != 0) {
  1649. DbgDisplayInvalidPte (CurrentPte, flags, Indent);
  1650. }
  1651. else {
  1652. dprintf ("\n");
  1653. }
  1654. }
  1655. dprintf ("\n");
  1656. return;
  1657. }
  1658. DECLARE_API( pte )
  1659. /*++
  1660. Routine Description:
  1661. Displays the corresponding PDE and PTE.
  1662. Arguments:
  1663. args -
  1664. Return Value:
  1665. None
  1666. --*/
  1667. {
  1668. ULONG64 Address = 0;
  1669. ULONG64 flags = 0;
  1670. ULONG flags2 = 0;
  1671. INIT_API();
  1672. if (GetExpressionEx(args,&Address, &args)) {
  1673. if (GetExpressionEx(args,&flags, &args)) {
  1674. flags2 = (ULONG) GetExpression(args);
  1675. }
  1676. }
  1677. switch (TargetMachine) {
  1678. case IMAGE_FILE_MACHINE_I386:
  1679. Address = (ULONG64) (LONG64) (LONG) Address;
  1680. DumpPte (Address, flags);
  1681. break;
  1682. case IMAGE_FILE_MACHINE_IA64:
  1683. DumpPte (Address, flags);
  1684. break;
  1685. case IMAGE_FILE_MACHINE_AMD64:
  1686. DumpPte (Address, flags);
  1687. break;
  1688. default:
  1689. dprintf("Unknown platform %d\n",TargetMachine);
  1690. break;
  1691. }
  1692. EXIT_API();
  1693. return S_OK;
  1694. }
  1695. BOOLEAN
  1696. GetPhysicalAddress (
  1697. IN ULONG64 Address,
  1698. OUT PULONG64 PhysAddress
  1699. )
  1700. /*++
  1701. Routine Description:
  1702. Retrieves the physical address corresponding to the supplied virtual
  1703. address.
  1704. Arguments:
  1705. Va - Supplies the virtual address for which the PTE address is sought.
  1706. PhysAddress - Supplies a pointer to caller-supplied memory which is to
  1707. contain the physical address.
  1708. Return Value:
  1709. TRUE - The supplied Va is valid and it's physical address was placed
  1710. in *PhysAddress.
  1711. FALSE - The supplied Va does not correspond to a valid address.
  1712. --*/
  1713. {
  1714. ULONG ValidBit;
  1715. ULONG LargePageBit;
  1716. ULONG PageFrameIndex;
  1717. ULONG64 PteAddress, PteContents;
  1718. switch (TargetMachine) {
  1719. case IMAGE_FILE_MACHINE_I386:
  1720. case IMAGE_FILE_MACHINE_AMD64:
  1721. PteAddress = DbgGetPdeAddress (Address);
  1722. if (GetFieldValue (PteAddress, "nt!_MMPTE", "u.Hard.Valid", ValidBit) ) {
  1723. dprintf("Unable to get PDE %I64X\n", PteAddress);
  1724. return FALSE;
  1725. }
  1726. if (ValidBit == 0) {
  1727. return FALSE;
  1728. }
  1729. if (GetFieldValue (PteAddress, "nt!_MMPTE", "u.Hard.LargePage", LargePageBit) ) {
  1730. dprintf("Unable to get PDE %I64X\n", PteAddress);
  1731. return FALSE;
  1732. }
  1733. if (LargePageBit == 0) {
  1734. break;
  1735. }
  1736. PageFrameIndex = (ULONG) DbgGetFrameNumber(PteAddress);
  1737. switch (TargetMachine) {
  1738. case IMAGE_FILE_MACHINE_I386:
  1739. PageFrameIndex += MiGetPteOffsetX86 (Address);
  1740. break;
  1741. case IMAGE_FILE_MACHINE_AMD64:
  1742. PageFrameIndex += (ULONG) MiGetPteOffsetAMD64 (Address);
  1743. break;
  1744. }
  1745. *PhysAddress =
  1746. ((PageFrameIndex << DBG_GET_PAGE_SHIFT ()) | (Address & 0xFFF));
  1747. return TRUE;
  1748. default:
  1749. break;
  1750. }
  1751. PteAddress = DbgGetPteAddress (Address);
  1752. if (GetFieldValue (PteAddress, "nt!_MMPTE", "u.Hard.Valid", ValidBit) ) {
  1753. dprintf("Unable to get PTE %I64X\n", PteAddress);
  1754. return FALSE;
  1755. }
  1756. if (ValidBit == 0) {
  1757. return FALSE;
  1758. }
  1759. GetFieldValue (PteAddress, "nt!_MMPTE", "u.Long", PteContents);
  1760. *PhysAddress =
  1761. ((DbgGetFrameNumber(PteAddress) << DBG_GET_PAGE_SHIFT ()) | (Address & 0xFFF));
  1762. return TRUE;
  1763. }
  1764. typedef struct _BPENTRY {
  1765. ULONG64 VirtualAddress;
  1766. ULONG64 PhysicalAddress;
  1767. ULONG Flags;
  1768. ULONG Contents;
  1769. } BPENTRY, *PBPENTRY;
  1770. #define PHYSICAL_BP_TABLE_SIZE 16
  1771. #define PBP_BYTE_POSITION 0x03
  1772. #define PBP_INUSE 0x04
  1773. #define PBP_ENABLED 0x08
  1774. BPENTRY PhysicalBreakpointTable[PHYSICAL_BP_TABLE_SIZE];
  1775. #define MAX_FORMAT_STRINGS 8
  1776. LPSTR
  1777. FormatAddr64(
  1778. ULONG64 addr
  1779. )
  1780. {
  1781. static CHAR strings[MAX_FORMAT_STRINGS][18];
  1782. static int next = 0;
  1783. LPSTR string;
  1784. string = strings[next];
  1785. ++next;
  1786. if (next >= MAX_FORMAT_STRINGS) {
  1787. next = 0;
  1788. }
  1789. if (addr >> 32) {
  1790. sprintf(string, "%08x`%08x", (ULONG)(addr>>32), (ULONG)addr);
  1791. } else {
  1792. sprintf(string, "%08x", (ULONG)addr);
  1793. }
  1794. return string;
  1795. }
  1796. DECLARE_API( ubl )
  1797. {
  1798. int i;
  1799. INIT_API();
  1800. UNREFERENCED_PARAMETER (args);
  1801. for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) {
  1802. if (PhysicalBreakpointTable[i].Flags & PBP_INUSE) {
  1803. dprintf("%2d: %c %s (%s) %d %02x",
  1804. i,
  1805. (PhysicalBreakpointTable[i].Flags & PBP_ENABLED) ? 'e' : 'd',
  1806. FormatAddr64(PhysicalBreakpointTable[i].VirtualAddress),
  1807. FormatAddr64(PhysicalBreakpointTable[i].PhysicalAddress),
  1808. (PhysicalBreakpointTable[i].Flags & PBP_BYTE_POSITION),
  1809. PhysicalBreakpointTable[i].Contents
  1810. );
  1811. }
  1812. }
  1813. EXIT_API();
  1814. return S_OK;
  1815. }
  1816. void
  1817. PbpEnable(
  1818. int n
  1819. )
  1820. {
  1821. PBPENTRY Pbp = PhysicalBreakpointTable + n;
  1822. ULONG mask;
  1823. ULONG Data;
  1824. ULONG cb=0;
  1825. mask = 0xff << (8 * (Pbp->Flags & PBP_BYTE_POSITION));
  1826. Data = (Pbp->Contents & ~mask) | (0xcccccccc & mask);
  1827. WritePhysical(Pbp->PhysicalAddress, &Data, 4, &cb);
  1828. if (cb == 4) {
  1829. Pbp->Flags |= PBP_ENABLED;
  1830. }
  1831. }
  1832. void
  1833. PbpDisable(
  1834. int n
  1835. )
  1836. {
  1837. PBPENTRY Pbp = PhysicalBreakpointTable + n;
  1838. ULONG cb;
  1839. WritePhysical(Pbp->PhysicalAddress, &Pbp->Contents, 4, &cb);
  1840. if (cb == 4) {
  1841. Pbp->Flags &= ~PBP_ENABLED;
  1842. }
  1843. }
  1844. void
  1845. PbpClear(
  1846. int n
  1847. )
  1848. {
  1849. PBPENTRY Pbp = PhysicalBreakpointTable + n;
  1850. ULONG cb;
  1851. WritePhysical(Pbp->PhysicalAddress, &Pbp->Contents, 4, &cb);
  1852. if (cb == 4) {
  1853. Pbp->Flags = 0;
  1854. }
  1855. }
  1856. DECLARE_API( ubc )
  1857. {
  1858. int i;
  1859. int n;
  1860. INIT_API();
  1861. if (*args == '*') {
  1862. //
  1863. // clear them all
  1864. //
  1865. for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) {
  1866. if (PhysicalBreakpointTable[i].Flags & PBP_INUSE) {
  1867. PbpClear(i);
  1868. }
  1869. }
  1870. EXIT_API();
  1871. return E_INVALIDARG;
  1872. }
  1873. n = sscanf(args,"%d",&i);
  1874. if (n != 1 || i < 0 || i >= PHYSICAL_BP_TABLE_SIZE) {
  1875. dprintf("!ubc: bad breakpoint number\n");
  1876. EXIT_API();
  1877. return E_INVALIDARG;
  1878. }
  1879. if ( !(PhysicalBreakpointTable[i].Flags & PBP_INUSE)) {
  1880. dprintf("!ubc: breakpoint number %d not set\n", i);
  1881. EXIT_API();
  1882. return E_INVALIDARG;
  1883. }
  1884. PbpClear(i);
  1885. EXIT_API();
  1886. return S_OK;
  1887. }
  1888. DECLARE_API( ube )
  1889. {
  1890. int i;
  1891. int n;
  1892. INIT_API();
  1893. if (*args == '*') {
  1894. //
  1895. // enable them all
  1896. //
  1897. for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) {
  1898. if (PhysicalBreakpointTable[i].Flags & PBP_INUSE) {
  1899. PbpEnable(i);
  1900. }
  1901. }
  1902. EXIT_API();
  1903. return E_INVALIDARG;
  1904. }
  1905. n = sscanf(args,"%d",&i);
  1906. if (n != 1 || i < 0 || i >= PHYSICAL_BP_TABLE_SIZE) {
  1907. dprintf("!ube: bad breakpoint number\n");
  1908. EXIT_API();
  1909. return E_INVALIDARG;
  1910. }
  1911. if ( !(PhysicalBreakpointTable[i].Flags & PBP_INUSE)) {
  1912. dprintf("!ube: breakpoint number %d not set\n", i);
  1913. EXIT_API();
  1914. return E_INVALIDARG;
  1915. }
  1916. PbpEnable(i);
  1917. EXIT_API();
  1918. return S_OK;
  1919. }
  1920. DECLARE_API( ubd )
  1921. {
  1922. int i;
  1923. int n;
  1924. INIT_API();
  1925. if (*args == '*') {
  1926. //
  1927. // disable them all
  1928. //
  1929. for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) {
  1930. if (PhysicalBreakpointTable[i].Flags & PBP_INUSE) {
  1931. PbpDisable(i);
  1932. }
  1933. }
  1934. EXIT_API();
  1935. return E_INVALIDARG;
  1936. }
  1937. n = sscanf(args,"%d",&i);
  1938. if (n != 1 || i < 0 || i >= PHYSICAL_BP_TABLE_SIZE) {
  1939. dprintf("!ubd: bad breakpoint number\n");
  1940. EXIT_API();
  1941. return E_INVALIDARG;
  1942. }
  1943. if ( !(PhysicalBreakpointTable[i].Flags & PBP_INUSE)) {
  1944. dprintf("!ubd: breakpoint number %d not set\n", i);
  1945. EXIT_API();
  1946. return E_INVALIDARG;
  1947. }
  1948. PbpDisable(i);
  1949. EXIT_API();
  1950. return S_OK;
  1951. }
  1952. DECLARE_API( ubp )
  1953. {
  1954. ULONG64 Address;
  1955. ULONG result;
  1956. ULONG PageShift;
  1957. PMMPTEx Pte;
  1958. PMMPTEx Pde;
  1959. ULONG64 PdeContents;
  1960. ULONG64 PteContents;
  1961. PBPENTRY Pbp = NULL;
  1962. ULONG cb;
  1963. int i;
  1964. ULONG64 PhysicalAddress;
  1965. static BOOL DoWarning = TRUE;
  1966. INIT_API();
  1967. if (DoWarning) {
  1968. DoWarning = FALSE;
  1969. dprintf("This command is VERY DANGEROUS, and may crash your system!\n");
  1970. dprintf("If you don't know what you are doing, enter \"!ubc *\" now!\n\n");
  1971. }
  1972. for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) {
  1973. if (!(PhysicalBreakpointTable[i].Flags & PBP_INUSE)) {
  1974. Pbp = PhysicalBreakpointTable + i;
  1975. break;
  1976. }
  1977. }
  1978. if (!Pbp) {
  1979. dprintf("!ubp: breakpoint table is full!\n");
  1980. EXIT_API();
  1981. return E_INVALIDARG;
  1982. }
  1983. Address = GetExpression(args);
  1984. if ((Address >= GET_PTE_BASE()) && (Address < GET_PDE_TOP())) {
  1985. //
  1986. // The address is the address of a PTE, rather than
  1987. // a virtual address.
  1988. //
  1989. dprintf("!ubp: cannot set a breakpoint on a PTE\n");
  1990. EXIT_API();
  1991. return E_INVALIDARG;
  1992. }
  1993. Pde = DbgGetPdeAddress (Address);
  1994. Pte = DbgGetPteAddress (Address);
  1995. if ( !ReadMemory( (DWORD)Pde,
  1996. &PdeContents,
  1997. sizeof(ULONG),
  1998. &result) ) {
  1999. dprintf("!ubp: %08lx: Unable to get PDE\n",Pde);
  2000. EXIT_API();
  2001. return E_INVALIDARG;
  2002. }
  2003. if (!(PdeContents & 0x1)) {
  2004. dprintf("!ubp: no valid PTE\n");
  2005. EXIT_API();
  2006. return E_INVALIDARG;
  2007. }
  2008. if (PdeContents & GET_MM_PTE_LARGE_PAGE_MASK()) {
  2009. dprintf("!ubp: not supported for large page\n");
  2010. EXIT_API();
  2011. return E_INVALIDARG;
  2012. }
  2013. if ( GetFieldValue( Pte, "nt!_MMPTE", "u.Long", PteContents) ) {
  2014. dprintf("!ubp: %08p: Unable to get PTE (PDE = %08p)\n",Pte, Pde);
  2015. EXIT_API();
  2016. return E_INVALIDARG;
  2017. }
  2018. if (!(PteContents & 1)) {
  2019. dprintf("!ubp: no valid PTE\n");
  2020. EXIT_API();
  2021. return E_INVALIDARG;
  2022. }
  2023. PageShift = DBG_GET_PAGE_SHIFT ();
  2024. PhysicalAddress = ((DbgGetFrameNumber (PteContents)) << PageShift);
  2025. PhysicalAddress &= ~((1 << PageShift) - 1);
  2026. PhysicalAddress |= (Address & ~((1 << PageShift) - 1));
  2027. PhysicalAddress &= ~3;
  2028. for (i = 0; i < PHYSICAL_BP_TABLE_SIZE; i++) {
  2029. if (PhysicalBreakpointTable[i].PhysicalAddress == PhysicalAddress) {
  2030. dprintf("!ubp: cannot set two breakpoints in the same word\n");
  2031. EXIT_API();
  2032. return E_INVALIDARG;
  2033. }
  2034. }
  2035. ReadPhysical(PhysicalAddress, &Pbp->Contents, 4, &cb);
  2036. if (cb != 4) {
  2037. dprintf("!ubp: unable to read physical at 0x%08x\n", PhysicalAddress);
  2038. EXIT_API();
  2039. return E_INVALIDARG;
  2040. }
  2041. Pbp->VirtualAddress = Address;
  2042. Pbp->PhysicalAddress = PhysicalAddress;
  2043. Pbp->Flags = PBP_INUSE | ((ULONG) Address & 3);
  2044. PbpEnable((int)(Pbp - PhysicalBreakpointTable));
  2045. EXIT_API();
  2046. return S_OK;
  2047. }
  2048. DECLARE_API( halpte )
  2049. {
  2050. #define HAL_VA_START_X86 0xffffffffffd00000
  2051. ULONG64 virtAddr = HAL_VA_START_X86;
  2052. ULONG64 pteAddr;
  2053. ULONG64 pteContents;
  2054. ULONG count = 0;
  2055. INIT_API();
  2056. UNREFERENCED_PARAMETER (args);
  2057. if (TargetMachine != IMAGE_FILE_MACHINE_I386) {
  2058. dprintf("X86 only API\n");
  2059. EXIT_API();
  2060. return E_UNEXPECTED;
  2061. }
  2062. dprintf("\n\nDumping HAL PTE ranges\n\n");
  2063. while (virtAddr < 0xffffffffffffe000) {
  2064. pteAddr = DbgGetPteAddress(virtAddr);
  2065. if (!InitTypeRead(pteAddr, nt!_MMPTE)) {
  2066. if (pteContents = ReadField(u.Long)) {
  2067. dprintf("[%03x] %p -> %I64x\n",
  2068. count++,
  2069. virtAddr,
  2070. pteContents & (ULONG64) ~0xFFF);
  2071. }
  2072. }
  2073. virtAddr += PageSize;
  2074. }
  2075. EXIT_API();
  2076. return S_OK;
  2077. }
  2078. #if defined(ALT_4K)
  2079. #undef MiGetAltPteAddress
  2080. #define MiGetAltPteAddress(VA) \
  2081. ((ULONG64) (ALT4KB_PERMISSION_TABLE_START + \
  2082. ((((ULONG64) (VA)) >> PAGE_4K_SHIFT) << ALT_PTE_SHIFT)))
  2083. #endif // defined(ALT_4K)
  2084. //
  2085. // Limit the IA32 subsystem to a 2GB virtual address space.
  2086. // This means "Large Address Aware" apps are not supported in emulation mode.
  2087. //
  2088. #define _MAX_WOW64_ADDRESS (0x00000000080000000UI64)
  2089. DECLARE_API( ate )
  2090. /*++
  2091. Routine Description:
  2092. Displays the correnponding ATE.
  2093. Arguments:
  2094. Args - Address Flags
  2095. Return Value:
  2096. None
  2097. --*/
  2098. {
  2099. #if defined(ALT_4K)
  2100. ULONG64 Address;
  2101. ULONG flags;
  2102. ULONG Result;
  2103. ULONG64 PointerAte;
  2104. ULONG64 Process;
  2105. ULONG AltTable[(_MAX_WOW64_ADDRESS >> PTI_SHIFT)/32];
  2106. ULONG64 *Wow64Process;
  2107. if (GetExpressionEx(args,&Address, &args)) {
  2108. flags = (ULONG) GetExpression(args);
  2109. }
  2110. Address = Address & ~((ULONG64)PageSize - 1);
  2111. PointerAte = MiGetAltPteAddress(Address);
  2112. if ( InitTypeRead( PointerAte,
  2113. nt!_MMPTE) ) {
  2114. dprintf("Unable to get ATE %p\n", PointerAte);
  2115. return E_INVALIDARG;
  2116. }
  2117. dprintf("%016I64X: %016I64X ", PointerAte, ReadField(u.Long));
  2118. dprintf("PTE off: %08I64X protect: ",
  2119. ReadField(u.Alt.PteOffset));
  2120. DbgPrintProtection((ULONG) ReadField(u.Alt.Protection));
  2121. dprintf(" %c%c%c%c%c%c%c%c%c%c\n",
  2122. ReadField(u.Alt.Commit) ? 'V' : '-',
  2123. ReadField(u.Alt.Accessed) ? '-' : 'G',
  2124. ReadField(u.Alt.Execute) ? 'E' : '-',
  2125. ReadField(u.Alt.Write) ? 'W' : 'R',
  2126. ReadField(u.Alt.Lock) ? 'L' : '-',
  2127. ReadField(u.Alt.FillZero) ? 'Z' : '-',
  2128. ReadField(u.Alt.NoAccess) ? 'N' : '-',
  2129. ReadField(u.Alt.CopyOnWrite) ? 'C' : '-',
  2130. ReadField(u.Alt.PteIndirect) ? 'I' : '-',
  2131. ReadField(u.Alt.Private) ? 'P' : '-');
  2132. #else
  2133. UNREFERENCED_PARAMETER (args);
  2134. UNREFERENCED_PARAMETER (Client);
  2135. #endif // defined(ALT_4K)
  2136. return S_OK;
  2137. }
  2138. DECLARE_API( pte2va )
  2139. /*++
  2140. Routine Description:
  2141. Displays the correnponding ATE.
  2142. Arguments:
  2143. Args - Address Flags
  2144. Return Value:
  2145. None
  2146. --*/
  2147. {
  2148. ULONG64 Address=0;
  2149. ULONG flags=0;
  2150. UNREFERENCED_PARAMETER (Client);
  2151. if (GetExpressionEx(args,&Address, &args)) {
  2152. flags = (ULONG) GetExpression(args);
  2153. }
  2154. Address = DbgGetVirtualAddressMappedByPte(Address);
  2155. dprintf("%p \n", Address);
  2156. return S_OK;
  2157. }