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.

1726 lines
48 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. heaputil.cpp
  5. Revision History:
  6. ivanbrug oct 2000 created
  7. --*/
  8. #include <wmiexts.h>
  9. #include <utilfun.h>
  10. #include <malloc.h>
  11. /*
  12. #if defined(_WIN64)
  13. #define HEAP_GRANULARITY_SHIFT 4 // Log2( HEAP_GRANULARITY )
  14. #else
  15. #define HEAP_GRANULARITY_SHIFT 3 // Log2( HEAP_GRANULARITY )
  16. #endif
  17. #define HEAP_ENTRY_BUSY 0x01
  18. #define HEAP_ENTRY_EXTRA_PRESENT 0x02
  19. #define HEAP_ENTRY_FILL_PATTERN 0x04
  20. #define HEAP_ENTRY_VIRTUAL_ALLOC 0x08
  21. #define HEAP_ENTRY_LAST_ENTRY 0x10
  22. #define HEAP_ENTRY_SETTABLE_FLAG1 0x20
  23. #define HEAP_ENTRY_SETTABLE_FLAG2 0x40
  24. #define HEAP_ENTRY_SETTABLE_FLAG3 0x80
  25. #define HEAP_ENTRY_SETTABLE_FLAGS 0xE0
  26. typedef struct _HEAP_ENTRY {
  27. //
  28. // This field gives the size of the current block in allocation
  29. // granularity units. (i.e. Size << HEAP_GRANULARITY_SHIFT
  30. // equals the size in bytes).
  31. //
  32. // Except if this is part of a virtual alloc block then this
  33. // value is the difference between the commit size in the virtual
  34. // alloc entry and the what the user asked for.
  35. //
  36. USHORT Size;
  37. //
  38. // This field gives the size of the previous block in allocation
  39. // granularity units. (i.e. PreviousSize << HEAP_GRANULARITY_SHIFT
  40. // equals the size of the previous block in bytes).
  41. //
  42. USHORT PreviousSize;
  43. //
  44. // This field contains the index into the segment that controls
  45. // the memory for this block.
  46. //
  47. UCHAR SegmentIndex;
  48. //
  49. // This field contains various flag bits associated with this block.
  50. // Currently these are:
  51. //
  52. // 0x01 - HEAP_ENTRY_BUSY
  53. // 0x02 - HEAP_ENTRY_EXTRA_PRESENT
  54. // 0x04 - HEAP_ENTRY_FILL_PATTERN
  55. // 0x08 - HEAP_ENTRY_VIRTUAL_ALLOC
  56. // 0x10 - HEAP_ENTRY_LAST_ENTRY
  57. // 0x20 - HEAP_ENTRY_SETTABLE_FLAG1
  58. // 0x40 - HEAP_ENTRY_SETTABLE_FLAG2
  59. // 0x80 - HEAP_ENTRY_SETTABLE_FLAG3
  60. //
  61. UCHAR Flags;
  62. //
  63. // This field contains the number of unused bytes at the end of this
  64. // block that were not actually allocated. Used to compute exact
  65. // size requested prior to rounding requested size to allocation
  66. // granularity. Also used for tail checking purposes.
  67. //
  68. UCHAR UnusedBytes;
  69. //
  70. // Small (8 bit) tag indexes can go here.
  71. //
  72. UCHAR SmallTagIndex;
  73. #if defined(_WIN64)
  74. ULONGLONG Reserved1;
  75. #endif
  76. } HEAP_ENTRY, *PHEAP_ENTRY;
  77. typedef struct _HEAP_UNCOMMMTTED_RANGE {
  78. struct _HEAP_UNCOMMMTTED_RANGE *Next;
  79. ULONG_PTR Address;
  80. SIZE_T Size;
  81. ULONG filler;
  82. } HEAP_UNCOMMMTTED_RANGE, *PHEAP_UNCOMMMTTED_RANGE;
  83. typedef struct _HEAP_SEGMENT {
  84. HEAP_ENTRY Entry;
  85. ULONG Signature;
  86. ULONG Flags;
  87. struct _HEAP *Heap;
  88. SIZE_T LargestUnCommittedRange;
  89. PVOID BaseAddress;
  90. ULONG NumberOfPages;
  91. PHEAP_ENTRY FirstEntry;
  92. PHEAP_ENTRY LastValidEntry;
  93. ULONG NumberOfUnCommittedPages;
  94. ULONG NumberOfUnCommittedRanges;
  95. PHEAP_UNCOMMMTTED_RANGE UnCommittedRanges;
  96. USHORT AllocatorBackTraceIndex;
  97. USHORT Reserved;
  98. PHEAP_ENTRY LastEntryInSegment;
  99. } HEAP_SEGMENT, *PHEAP_SEGMENT;
  100. */
  101. typedef ULONG_PTR ERESOURCE_THREAD;
  102. typedef ERESOURCE_THREAD *PERESOURCE_THREAD;
  103. typedef struct _OWNER_ENTRY {
  104. ERESOURCE_THREAD OwnerThread;
  105. union {
  106. LONG OwnerCount;
  107. ULONG TableSize;
  108. };
  109. } OWNER_ENTRY, *POWNER_ENTRY;
  110. typedef void * PKSEMAPHORE;
  111. typedef void * PKEVENT;
  112. typedef struct _ERESOURCE {
  113. LIST_ENTRY SystemResourcesList;
  114. POWNER_ENTRY OwnerTable;
  115. SHORT ActiveCount;
  116. USHORT Flag;
  117. PKSEMAPHORE SharedWaiters;
  118. PKEVENT ExclusiveWaiters;
  119. OWNER_ENTRY OwnerThreads[2];
  120. ULONG ContentionCount;
  121. USHORT NumberOfSharedWaiters;
  122. USHORT NumberOfExclusiveWaiters;
  123. union {
  124. PVOID Address;
  125. ULONG_PTR CreatorBackTraceIndex;
  126. };
  127. KSPIN_LOCK SpinLock;
  128. } ERESOURCE, *PERESOURCE;
  129. //typedef void * PRTL_TRACE_BLOCK;
  130. #include "heap.h"
  131. #include "heappagi.h"
  132. #define HE_VERBOSITY_FLAGS 1
  133. #define HE_VERBOSITY_NUMERIC 2
  134. #define HE_VERBOSITY_VTABLE 4
  135. #if defined(_X86_)
  136. #ifndef PAGE_SIZE
  137. #define PAGE_SIZE 0x1000
  138. #endif
  139. #define USER_ALIGNMENT 8
  140. #elif defined(_IA64_)
  141. #ifndef PAGE_SIZE
  142. #define PAGE_SIZE 0x2000
  143. #endif
  144. #define USER_ALIGNMENT 16
  145. #elif defined(_AMD64_)
  146. #ifndef PAGE_SIZE
  147. #define PAGE_SIZE 0x1000
  148. #endif
  149. #define USER_ALIGNMENT 16
  150. #else
  151. #error // platform not defined
  152. #endif
  153. //
  154. //
  155. //
  156. //
  157. //
  158. typedef DWORD (__stdcall * fnCallBack)(ULONG_PTR pParam1,ULONG_PTR pParam2);
  159. void
  160. PrintHeapEntry(HEAP_ENTRY * pEntry,void * pAddr)
  161. {
  162. BYTE varEntry[sizeof(HEAP_ENTRY)+2*sizeof(void *)];
  163. LIST_ENTRY * pListEntry = (LIST_ENTRY *)((HEAP_ENTRY *)varEntry+1);
  164. DWORD PrintSize = 0;
  165. BOOL bIsPossiblePageHeap = FALSE;
  166. if (pEntry->Flags & HEAP_ENTRY_BUSY)
  167. {
  168. // re-read the entry, to get if it's on the LookAside
  169. if (ReadMemory((MEMORY_ADDRESS)pAddr,varEntry,sizeof(varEntry),NULL))
  170. {
  171. if (0xf0f0f0f0 == (ULONG_PTR)pListEntry->Blink )
  172. {
  173. PrintSize = 0xf7eef7ee;
  174. }
  175. else
  176. {
  177. PrintSize = (pEntry->Size<<HEAP_GRANULARITY_SHIFT)-pEntry->UnusedBytes;
  178. }
  179. DWORD Sign = *((DWORD *)pListEntry);
  180. //dprintf("Sign %08x\n",Sign);
  181. if (0xabcdaaaa == Sign)
  182. {
  183. bIsPossiblePageHeap = TRUE;
  184. }
  185. }
  186. else
  187. {
  188. PrintSize = (pEntry->Size<<HEAP_GRANULARITY_SHIFT)-pEntry->UnusedBytes;
  189. }
  190. }
  191. else
  192. {
  193. PrintSize = 0xf7eef7ee;
  194. }
  195. dprintf(" %p: %04x . %04x [%02x] - (%x)\n",
  196. pAddr,pEntry->Size,pEntry->PreviousSize,pEntry->Flags,PrintSize);
  197. if (bIsPossiblePageHeap)
  198. {
  199. //dprintf("Possible %p\n",(MEMORY_ADDRESS)((BYTE*)pAddr+sizeof(HEAP_ENTRY)+sizeof(DPH_BLOCK_INFORMATION)));
  200. GetVTable((MEMORY_ADDRESS)((BYTE*)pAddr+sizeof(HEAP_ENTRY)+sizeof(DPH_BLOCK_INFORMATION)));
  201. }
  202. else
  203. GetVTable((MEMORY_ADDRESS)((BYTE*)pAddr+sizeof(HEAP_ENTRY)));
  204. };
  205. //
  206. //
  207. // print the HEAP_ENTRY structure
  208. //
  209. DECLARE_API(he) {
  210. INIT_API();
  211. DEFINE_CPP_VAR( HEAP_ENTRY, varHEAP_ENTRY);
  212. HEAP_ENTRY * pEntry = GET_CPP_VAR_PTR( HEAP_ENTRY , varHEAP_ENTRY );
  213. memset(pEntry,0xfe,sizeof(HEAP_ENTRY));
  214. ULONG_PTR pByte = GetExpression(args);
  215. if (pByte)
  216. {
  217. if (ReadMemory((MEMORY_ADDRESS)pByte,pEntry ,sizeof(HEAP_ENTRY),NULL))
  218. {
  219. PrintHeapEntry(pEntry,(void *)pByte);
  220. }
  221. else
  222. {
  223. dprintf("ReadMemory %p %d\n",pByte,GetLastError());
  224. }
  225. } else {
  226. dprintf("invalid HEAP_ENTRY address %s\n",args);
  227. }
  228. }
  229. //
  230. // HEAP_ENTRY list
  231. // finds the beginning of the "list" of HEAP_ENTRYs
  232. //
  233. DECLARE_API(heb) {
  234. INIT_API();
  235. MEMORY_ADDRESS pEntry = GetExpression(args);
  236. if (pEntry){
  237. HEAP_ENTRY HeapEntry;
  238. ReadMemory((MEMORY_ADDRESS)pEntry,&HeapEntry,sizeof(HeapEntry),0);
  239. PrintHeapEntry(&HeapEntry,(void *)pEntry);
  240. while (HeapEntry.PreviousSize)
  241. {
  242. pEntry = (MEMORY_ADDRESS)((HEAP_ENTRY*)pEntry - HeapEntry.PreviousSize);
  243. if (ReadMemory((MEMORY_ADDRESS)pEntry,&HeapEntry,sizeof(HeapEntry),0))
  244. {
  245. PrintHeapEntry(&HeapEntry,(void *)pEntry);
  246. }
  247. else
  248. {
  249. dprintf("RM %p\n",pEntry);
  250. break;
  251. }
  252. if (CheckControlC())
  253. break;
  254. }
  255. dprintf(" begin %08x\n",pEntry);
  256. } else {
  257. dprintf("invalid address %s\n",args);
  258. };
  259. }
  260. //
  261. //
  262. // HEAP_ENTRY forward
  263. //
  264. //////////////////////////////////////////////////////
  265. DECLARE_API(hef) {
  266. INIT_API();
  267. DWORD BeginNum=0;
  268. MEMORY_ADDRESS pEntry = GetExpression(args);
  269. if (pEntry)
  270. {
  271. HEAP_ENTRY HeapEntry;
  272. ReadMemory((MEMORY_ADDRESS)pEntry,&HeapEntry,sizeof(HeapEntry),0);
  273. PrintHeapEntry(&HeapEntry,(void *)pEntry);
  274. while (!(HeapEntry.Flags & HEAP_ENTRY_LAST_ENTRY))
  275. {
  276. pEntry = (MEMORY_ADDRESS)((HEAP_ENTRY*)pEntry + HeapEntry.Size);
  277. if (ReadMemory((MEMORY_ADDRESS)pEntry,&HeapEntry,sizeof(HeapEntry),0))
  278. {
  279. PrintHeapEntry(&HeapEntry,(void *)pEntry);
  280. }
  281. else
  282. {
  283. dprintf("RM %p\n",pEntry);
  284. break;
  285. }
  286. if (CheckControlC())
  287. break;
  288. }
  289. dprintf(" end %08x\n",pEntry);
  290. } else {
  291. dprintf("invalid address %s\n",args);
  292. };
  293. }
  294. DWORD EnumEntries(HEAP_ENTRY * pEntry,DWORD * pSize,fnCallBack CallBack,ULONG_PTR Addr){
  295. DWORD i=0;
  296. HEAP_ENTRY HeapEntry;
  297. DWORD Size=0;
  298. ReadMemory((MEMORY_ADDRESS)pEntry,&HeapEntry,sizeof(HeapEntry),0);
  299. if (CallBack)
  300. {
  301. CallBack((ULONG_PTR)pEntry,Addr);
  302. }
  303. else
  304. {
  305. PrintHeapEntry(&HeapEntry,pEntry);
  306. };
  307. while (!(HeapEntry.Flags & HEAP_ENTRY_LAST_ENTRY))
  308. {
  309. if (0 == HeapEntry.Size)
  310. {
  311. dprintf("HEAP_ENTRY %p with zero Size\n",pEntry);
  312. break;
  313. }
  314. pEntry = (HEAP_ENTRY*)pEntry + HeapEntry.Size;
  315. if (ReadMemory((MEMORY_ADDRESS)pEntry,&HeapEntry,sizeof(HeapEntry),0))
  316. {
  317. if (CallBack)
  318. {
  319. CallBack((ULONG_PTR)pEntry,Addr);
  320. }
  321. else
  322. {
  323. PrintHeapEntry(&HeapEntry,pEntry);
  324. };
  325. }
  326. else
  327. {
  328. dprintf("RM %p\n",pEntry);
  329. break;
  330. }
  331. i++;
  332. Size += ((HeapEntry.Size<<HEAP_GRANULARITY_SHIFT)-HeapEntry.UnusedBytes);
  333. if (CheckControlC())
  334. break;
  335. }
  336. if (pSize){
  337. *pSize = Size;
  338. }
  339. return i;
  340. }
  341. void
  342. PrintHEAP_SEGMENT(HEAP_SEGMENT * pSeg_OOP,
  343. fnCallBack CallBack,
  344. ULONG_PTR Addr)
  345. {
  346. DEFINE_CPP_VAR( HEAP_SEGMENT, varHEAP_SEGMENT);
  347. HEAP_SEGMENT * pSeg = GET_CPP_VAR_PTR( HEAP_SEGMENT , varHEAP_SEGMENT );
  348. BOOL bRet = ReadMemory((MEMORY_ADDRESS)pSeg_OOP,pSeg ,sizeof(HEAP_SEGMENT),0);
  349. if (bRet)
  350. {
  351. if (!CallBack)
  352. dprintf(" Flags %08x HEAP %p\n",pSeg->Flags,pSeg->Heap);
  353. //SIZE_T LargestUnCommittedRange;
  354. //PVOID BaseAddress;
  355. //ULONG NumberOfPages;
  356. //PHEAP_ENTRY FirstEntry;
  357. //PHEAP_ENTRY LastValidEntry;
  358. //ULONG NumberOfUnCommittedPages;
  359. DWORD unComm = pSeg->NumberOfUnCommittedRanges;
  360. //PHEAP_UNCOMMMTTED_RANGE UnCommittedRanges;
  361. //USHORT AllocatorBackTraceIndex;
  362. //USHORT Reserved;
  363. //PHEAP_ENTRY LastEntryInSegment;
  364. HEAP_UNCOMMMTTED_RANGE UncRange;
  365. HEAP_UNCOMMMTTED_RANGE * pUncRange = pSeg->UnCommittedRanges;
  366. HEAP_ENTRY ** pCommRange = (HEAP_ENTRY **)_alloca(sizeof(HEAP_ENTRY *)*(unComm+1));
  367. DWORD Size=0;
  368. DWORD Num=0;
  369. pCommRange[0] = (HEAP_ENTRY *)pSeg->FirstEntry;
  370. Num = EnumEntries(pCommRange[0],&Size,CallBack,Addr);
  371. if (!CallBack)
  372. dprintf(" - %p Size %p entries %d \n",pCommRange[0],Size,Num);
  373. for (DWORD i=0; i<unComm; i++)
  374. {
  375. bRet = ReadMemory((MEMORY_ADDRESS)pUncRange,&UncRange,sizeof(UncRange),NULL);
  376. if (bRet)
  377. {
  378. pUncRange = UncRange.Next;
  379. pCommRange[1+i] = (HEAP_ENTRY *)(UncRange.Address + UncRange.Size);
  380. if (NULL == pUncRange)
  381. {
  382. if ((ULONG_PTR)pCommRange[1+i] == (ULONG_PTR)pSeg->LastValidEntry)
  383. break;
  384. }
  385. Num = EnumEntries(pCommRange[1+i],&Size,CallBack,Addr);
  386. if (!CallBack)
  387. dprintf(" - %p Size %p entries %d\n",pCommRange[1+i],Size,Num);
  388. }
  389. else
  390. {
  391. dprintf("RM %p\n",pUncRange);
  392. }
  393. }
  394. } else {
  395. dprintf("RM %p\n",pSeg_OOP);
  396. }
  397. }
  398. //
  399. //
  400. // Dump the HEAP_SEGMENT
  401. //
  402. DECLARE_API(hs) {
  403. INIT_API();
  404. ULONG_PTR pByte = 0;
  405. pByte = GetExpression(args);
  406. if (pByte)
  407. {
  408. PrintHEAP_SEGMENT((HEAP_SEGMENT *)pByte,NULL,NULL);
  409. }
  410. else
  411. {
  412. dprintf("invalid address %s\n",args);
  413. }
  414. }
  415. //
  416. // Define heap lookaside list allocation functions.
  417. //
  418. typedef struct _HEAP_LOOKASIDE {
  419. SLIST_HEADER ListHead;
  420. USHORT Depth;
  421. USHORT MaximumDepth;
  422. ULONG TotalAllocates;
  423. ULONG AllocateMisses;
  424. ULONG TotalFrees;
  425. ULONG FreeMisses;
  426. ULONG LastTotalAllocates;
  427. ULONG LastAllocateMisses;
  428. ULONG Counters[2];
  429. } HEAP_LOOKASIDE, *PHEAP_LOOKASIDE;
  430. void Dump_LookAside(ULONG_PTR pLookAside_OOP)
  431. {
  432. #ifndef _WIN64
  433. DWORD dwSize = sizeof(HEAP_LOOKASIDE) * HEAP_MAXIMUM_FREELISTS ;
  434. BYTE * pData = new BYTE[dwSize];
  435. if (pData)
  436. {
  437. if (ReadMemory(pLookAside_OOP,pData,dwSize,NULL))
  438. {
  439. DWORD i;
  440. HEAP_LOOKASIDE * pLookAsideElem = NULL;
  441. BYTE varHEAP_ENTRY[sizeof(HEAP_ENTRY)+sizeof(void *)];
  442. HEAP_ENTRY * pEntry = GET_CPP_VAR_PTR( HEAP_ENTRY , varHEAP_ENTRY );
  443. for(i=0;i<HEAP_MAXIMUM_FREELISTS;i++)
  444. {
  445. dprintf(" entry %i\n",i);
  446. pLookAsideElem = (HEAP_LOOKASIDE *)pData+i;
  447. HEAP_ENTRY * pEntry_OOP = (HEAP_ENTRY *)pLookAsideElem->ListHead.Next.Next;
  448. BOOL bRet = FALSE;
  449. if (pEntry_OOP)
  450. {
  451. pEntry_OOP--;
  452. bRet = ReadMemory((MEMORY_ADDRESS)pEntry_OOP,pEntry,sizeof(HEAP_ENTRY)+sizeof(void *),NULL);
  453. }
  454. else
  455. {
  456. bRet = TRUE;
  457. }
  458. while(bRet && pEntry_OOP)
  459. {
  460. //dprintf("pEntry_OOP %p\n",pEntry_OOP);
  461. PrintHeapEntry(pEntry,pEntry_OOP);
  462. pEntry_OOP = *((HEAP_ENTRY **)(pEntry+1));
  463. if (pEntry_OOP)
  464. {
  465. pEntry_OOP--;
  466. bRet = ReadMemory((MEMORY_ADDRESS)pEntry_OOP,pEntry,sizeof(HEAP_ENTRY)+sizeof(void *),NULL);
  467. }
  468. else
  469. {
  470. bRet = TRUE;
  471. }
  472. }
  473. if (!bRet && pEntry_OOP)
  474. dprintf("RM %d\n",GetLastError());
  475. }
  476. }
  477. else
  478. {
  479. dprintf("RM %d\n",GetLastError());
  480. }
  481. delete [] pData;
  482. }
  483. #endif
  484. }
  485. //
  486. //
  487. // dump the HEAP, incomplete
  488. //
  489. //
  490. DECLARE_API(hp)
  491. {
  492. INIT_API();
  493. DEFINE_CPP_VAR( HEAP, varHEAP);
  494. HEAP * pHeap = GET_CPP_VAR_PTR( HEAP , varHEAP );
  495. ULONG_PTR pByte = GetExpression(args);
  496. DWORD i;
  497. if (pByte)
  498. {
  499. if (ReadMemory(pByte,pHeap ,sizeof(HEAP),NULL))
  500. {
  501. //dprintf("----- LookAside %p\n",pHeap->FrontEndHeap);
  502. //Dump_LookAside((ULONG_PTR)pHeap->FrontEndHeap);
  503. for (i=0;i<HEAP_MAXIMUM_SEGMENTS;i++)
  504. {
  505. if (pHeap->Segments[i])
  506. PrintHEAP_SEGMENT(pHeap->Segments[i],NULL,NULL);
  507. // dprintf(" seg %i - %p\n",i,pHeap->Segments[i]);
  508. }
  509. }
  510. else
  511. {
  512. dprintf("RM %p %d\n",pByte,GetLastError());
  513. }
  514. }
  515. else
  516. {
  517. dprintf("invalid address %s\n",args);
  518. }
  519. }
  520. //
  521. //
  522. //
  523. /////////////////////////////////////////////////////////////
  524. DWORD g_BlockSize;
  525. ULONG_PTR * g_pBlockBlob;
  526. DWORD CallBackSearch(ULONG_PTR pHeapEntry_OOP,ULONG_PTR Addr)
  527. {
  528. if (!g_pBlockBlob)
  529. {
  530. dprintf("no GLOBAL search block\n");
  531. return STATUS_NO_MEMORY;
  532. }
  533. HEAP_ENTRY Entry;
  534. if (ReadMemory(pHeapEntry_OOP,&Entry,sizeof(HEAP_ENTRY),NULL))
  535. {
  536. HEAP_ENTRY * pEntry = (HEAP_ENTRY *)&Entry;
  537. DWORD Size = (pEntry->Flags & HEAP_ENTRY_BUSY)?(pEntry->Size<<HEAP_GRANULARITY_SHIFT)-pEntry->UnusedBytes:0;
  538. if (Size)
  539. {
  540. if (Size < g_BlockSize)
  541. {
  542. ULONG_PTR * pData = (ULONG_PTR *)g_pBlockBlob;
  543. ReadMemory(pHeapEntry_OOP+sizeof(HEAP_ENTRY),pData,Size,NULL);
  544. // here is the assumption that pointers are aligned
  545. DWORD nTimes = Size/sizeof(ULONG_PTR);
  546. DWORD i;
  547. for (i=0;i<nTimes;i++)
  548. {
  549. if (Addr == pData[i])
  550. {
  551. dprintf("- %p off %p\n",pHeapEntry_OOP,sizeof(ULONG_PTR)*i);
  552. PrintHeapEntry((HEAP_ENTRY *)pEntry,(void *)pHeapEntry_OOP);
  553. }
  554. }
  555. }
  556. else
  557. {
  558. dprintf(" entry %p too big\n",pHeapEntry_OOP);
  559. }
  560. }
  561. }
  562. else
  563. {
  564. dprintf("RM %p\n",pHeapEntry_OOP);
  565. }
  566. return 0;
  567. }
  568. //
  569. //
  570. // search the HEAP, incomplete
  571. //
  572. ///////////////////////////////////////////////
  573. DECLARE_API(shp)
  574. {
  575. INIT_API();
  576. DEFINE_CPP_VAR( HEAP, varHEAP);
  577. HEAP * pHeap = GET_CPP_VAR_PTR( HEAP , varHEAP );
  578. char * pArgs = (char *)args;
  579. while(isspace(*pArgs)) pArgs++;
  580. ULONG_PTR pByte = GetExpression(pArgs);
  581. while(!isspace(*pArgs)) pArgs++;
  582. ULONG_PTR Addr = GetExpression(pArgs);
  583. DWORD i;
  584. if (pByte && Addr)
  585. {
  586. g_BlockSize = 0x10000*sizeof(HEAP_ENTRY);
  587. g_pBlockBlob = (ULONG_PTR *)VirtualAlloc(NULL,g_BlockSize,MEM_COMMIT,PAGE_READWRITE);
  588. if (!g_pBlockBlob)
  589. {
  590. dprintf("VirtualAlloc err %d\n",GetLastError());
  591. return;
  592. }
  593. if (ReadMemory(pByte,pHeap ,sizeof(HEAP),NULL))
  594. {
  595. for (i=0;i<HEAP_MAXIMUM_SEGMENTS;i++)
  596. {
  597. if (pHeap->Segments[i])
  598. PrintHEAP_SEGMENT(pHeap->Segments[i],CallBackSearch,Addr);
  599. // dprintf(" seg %i - %p\n",i,pHeap->Segments[i]);
  600. }
  601. }
  602. else
  603. {
  604. dprintf("RM %p %d\n",pByte,GetLastError());
  605. }
  606. if (g_pBlockBlob)
  607. {
  608. VirtualFree(g_pBlockBlob,g_BlockSize,MEM_DECOMMIT|MEM_RELEASE);
  609. g_pBlockBlob = NULL;
  610. g_BlockSize = 0;
  611. }
  612. }
  613. else
  614. {
  615. dprintf("invalid heap address pair in%s\n",args);
  616. }
  617. }
  618. //
  619. // decode heap flags
  620. //
  621. /*
  622. #define HEAP_NO_SERIALIZE 0x00000001 // winnt
  623. #define HEAP_GROWABLE 0x00000002 // winnt
  624. #define HEAP_GENERATE_EXCEPTIONS 0x00000004 // winnt
  625. #define HEAP_ZERO_MEMORY 0x00000008 // winnt
  626. #define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010 // winnt
  627. #define HEAP_TAIL_CHECKING_ENABLED 0x00000020 // winnt
  628. #define HEAP_FREE_CHECKING_ENABLED 0x00000040 // winnt
  629. #define HEAP_DISABLE_COALESCE_ON_FREE 0x00000080 // winnt
  630. #define HEAP_SETTABLE_USER_VALUE 0x00000100
  631. #define HEAP_SETTABLE_USER_FLAG1 0x00000200
  632. #define HEAP_SETTABLE_USER_FLAG2 0x00000400
  633. #define HEAP_SETTABLE_USER_FLAG3 0x00000800
  634. #define HEAP_CLASS_0 0x00000000 // process heap
  635. #define HEAP_CLASS_1 0x00001000 // private heap
  636. #define HEAP_CLASS_2 0x00002000 // Kernel Heap
  637. #define HEAP_CLASS_3 0x00003000 // GDI heap
  638. #define HEAP_CLASS_4 0x00004000 // User heap
  639. #define HEAP_CLASS_5 0x00005000 // Console heap
  640. #define HEAP_CLASS_6 0x00006000 // User Desktop heap
  641. #define HEAP_CLASS_7 0x00007000 // Csrss Shared heap
  642. #define HEAP_CLASS_8 0x00008000 // Csr Port heap
  643. */
  644. #define HEAP_LOCK_USER_ALLOCATED (ULONG)0x80000000
  645. #define HEAP_VALIDATE_PARAMETERS_ENABLED (ULONG)0x40000000
  646. #define HEAP_VALIDATE_ALL_ENABLED (ULONG)0x20000000
  647. #define HEAP_SKIP_VALIDATION_CHECKS (ULONG)0x10000000
  648. #define HEAP_CAPTURE_STACK_BACKTRACES (ULONG)0x08000000
  649. #define HEAP_FLAG_PAGE_ALLOCS 0x01000000
  650. #define HEAP_PROTECTION_ENABLED 0x02000000
  651. #define HEAP_BREAK_WHEN_OUT_OF_VM 0x04000000
  652. #define HEAP_NO_ALIGNMENT 0x08000000
  653. void DecodeFlags(ULONG Flags)
  654. {
  655. dprintf(" Flags: %08x ",Flags);
  656. if (Flags & HEAP_NO_SERIALIZE)
  657. dprintf("HEAP_NO_SERIALIZE ");
  658. if (Flags & HEAP_GROWABLE)
  659. dprintf("HEAP_GROWABLE ");
  660. if (Flags & HEAP_GENERATE_EXCEPTIONS)
  661. dprintf("HEAP_GENERATE_EXCEPTIONS ");
  662. if (Flags & HEAP_ZERO_MEMORY)
  663. dprintf("HEAP_ZERO_MEMORY ");
  664. if (Flags & HEAP_REALLOC_IN_PLACE_ONLY)
  665. dprintf("HEAP_REALLOC_IN_PLACE_ONLY ");
  666. if (Flags & HEAP_TAIL_CHECKING_ENABLED)
  667. dprintf("HEAP_TAIL_CHECKING_ENABLED ");
  668. if (Flags & HEAP_FREE_CHECKING_ENABLED)
  669. dprintf("HEAP_FREE_CHECKING_ENABLED ");
  670. if (Flags & HEAP_DISABLE_COALESCE_ON_FREE)
  671. dprintf("HEAP_DISABLE_COALESCE_ON_FREE ");
  672. if (Flags & HEAP_SETTABLE_USER_VALUE)
  673. dprintf("HEAP_SETTABLE_USER_VALUE ");
  674. if (Flags & HEAP_SETTABLE_USER_FLAG1)
  675. dprintf("HEAP_SETTABLE_USER_FLAG1 ");
  676. if (Flags & HEAP_SETTABLE_USER_FLAG2)
  677. dprintf("HEAP_SETTABLE_USER_FLAG2 ");
  678. if (Flags & HEAP_SETTABLE_USER_FLAG3)
  679. dprintf("HEAP_SETTABLE_USER_FLAG3 ");
  680. if (Flags & HEAP_CLASS_MASK)
  681. dprintf("HEAP_CLASS %d",(Flags&HEAP_CLASS_MASK)>>12);
  682. /*
  683. if (Flags & HEAP_CLASS_1)
  684. dprintf("HEAP_CLASS_1 ");
  685. if (Flags & HEAP_CLASS_2)
  686. dprintf("HEAP_CLASS_2 ");
  687. if (Flags & HEAP_CLASS_3)
  688. dprintf("HEAP_CLASS_3 ");
  689. if (Flags & HEAP_CLASS_4)
  690. dprintf("HEAP_CLASS_4 ");
  691. if (Flags & HEAP_CLASS_5)
  692. dprintf("HEAP_CLASS_5 ");
  693. if (Flags & HEAP_CLASS_6)
  694. dprintf("HEAP_CLASS_6 ");
  695. if (Flags & HEAP_CLASS_7)
  696. dprintf("HEAP_CLASS_7 ");
  697. */
  698. //if (Flags & HEAP_CAPTURE_STACK_BACKTRACES)
  699. // dprintf("HEAP_CAPTURE_STACK_BACKTRACES ");
  700. if (Flags &HEAP_SKIP_VALIDATION_CHECKS)
  701. dprintf("HEAP_SKIP_VALIDATION_CHECKS ");
  702. if (Flags &HEAP_VALIDATE_ALL_ENABLED)
  703. dprintf("HEAP_VALIDATE_ALL_ENABLED ");
  704. if (Flags &HEAP_VALIDATE_PARAMETERS_ENABLED)
  705. dprintf("HEAP_VALIDATE_PARAMETERS_ENABLED ");
  706. if (Flags &HEAP_LOCK_USER_ALLOCATED)
  707. dprintf("HEAP_LOCK_USER_ALLOCATED ");
  708. if (Flags &HEAP_FLAG_PAGE_ALLOCS)
  709. dprintf("HEAP_FLAG_PAGE_ALLOCS ");
  710. if (Flags &HEAP_PROTECTION_ENABLED)
  711. dprintf("HEAP_PROTECTION_ENABLED ");
  712. if (Flags &HEAP_BREAK_WHEN_OUT_OF_VM)
  713. dprintf("HEAP_BREAK_WHEN_OUT_OF_VM ");
  714. if (Flags &HEAP_NO_ALIGNMENT)
  715. dprintf("HEAP_NO_ALIGNMENT ");
  716. //if (Flags &)
  717. // dprintf(" ");
  718. dprintf("\n");
  719. }
  720. //
  721. // Get all the heaps
  722. //
  723. DECLARE_API(hps)
  724. {
  725. INIT_API();
  726. PEB * pPeb = NULL;
  727. PEB ThisPeb;
  728. GetPeb(hCurrentProcess,&pPeb);
  729. if(!pPeb)
  730. {
  731. #ifdef _WIN64
  732. pPeb = (PEB *)0x6fbfffde000;
  733. #else
  734. pPeb = (PEB *)0x7ffdf000;
  735. #endif
  736. }
  737. if (pPeb)
  738. {
  739. ReadMemory((MEMORY_ADDRESS)pPeb,&ThisPeb,sizeof(PEB),0);
  740. void ** pHeaps = (void**)_alloca(ThisPeb.NumberOfHeaps*sizeof(void*));
  741. DWORD i,j;
  742. ULONG_PTR TotCommitSize = 0;
  743. ULONG_PTR TotVirtSize = 0;
  744. if (ReadMemory((MEMORY_ADDRESS)ThisPeb.ProcessHeaps,pHeaps,ThisPeb.NumberOfHeaps*sizeof(void*),0))
  745. {
  746. for(i=0;i<ThisPeb.NumberOfHeaps;i++)
  747. {
  748. DEFINE_CPP_VAR( HEAP, varHEAP);
  749. HEAP * pHeap = GET_CPP_VAR_PTR( HEAP , varHEAP );
  750. ULONG_PTR TotHeapCommitSize = 0;
  751. ULONG_PTR TotHeapVirtSize = 0;
  752. if (ReadMemory((MEMORY_ADDRESS)pHeaps[i],pHeap ,sizeof(HEAP),0))
  753. {
  754. for (j=0;j<HEAP_MAXIMUM_SEGMENTS;j++)
  755. {
  756. if (pHeap->Segments[j])
  757. {
  758. DEFINE_CPP_VAR( HEAP_SEGMENT, varHEAP_SEGMENT);
  759. HEAP_SEGMENT * pHeapSeg = GET_CPP_VAR_PTR( HEAP_SEGMENT , varHEAP_SEGMENT );
  760. if (ReadMemory((MEMORY_ADDRESS)pHeap->Segments[j],pHeapSeg,sizeof(HEAP_SEGMENT),0))
  761. {
  762. dprintf(" - %p (C %p - R %p)\n",
  763. pHeap->Segments[j],
  764. (pHeapSeg->NumberOfPages - pHeapSeg->NumberOfUnCommittedPages) * PAGE_SIZE,
  765. (pHeapSeg->NumberOfPages) * PAGE_SIZE);
  766. TotHeapCommitSize += ((pHeapSeg->NumberOfPages - pHeapSeg->NumberOfUnCommittedPages) * PAGE_SIZE);
  767. TotHeapVirtSize += ((pHeapSeg->NumberOfPages) * PAGE_SIZE);
  768. // now print the beggining of a committed range
  769. dprintf(" CR %p\n",pHeapSeg->BaseAddress);
  770. HEAP_UNCOMMMTTED_RANGE * pUncomm_OOP = pHeapSeg->UnCommittedRanges;
  771. for (DWORD i=0;i<pHeapSeg->NumberOfUnCommittedRanges && pUncomm_OOP;i++)
  772. {
  773. HEAP_UNCOMMMTTED_RANGE UncommRange;
  774. if (ReadMemory((MEMORY_ADDRESS)pUncomm_OOP,&UncommRange,sizeof(HEAP_UNCOMMMTTED_RANGE),NULL))
  775. {
  776. if (UncommRange.Next)
  777. {
  778. pUncomm_OOP = UncommRange.Next;
  779. }
  780. ULONG_PTR RangeAddr = (ULONG_PTR)UncommRange.Address+UncommRange.Size;
  781. if (RangeAddr != (ULONG_PTR)pHeapSeg->LastEntryInSegment)
  782. dprintf(" CR %p\n",RangeAddr);
  783. }
  784. else
  785. {
  786. dprintf("RM %p\n",pHeapSeg->UnCommittedRanges);
  787. break;
  788. }
  789. }
  790. }
  791. else
  792. {
  793. dprintf("RM %p\n",pHeap->Segments[j]);
  794. }
  795. }
  796. }
  797. }
  798. else
  799. {
  800. dprintf("RM %p\n",pHeaps[i]);
  801. pHeap = NULL;
  802. }
  803. dprintf(" HEAP %p - %p\n",pHeaps[i],TotHeapCommitSize);
  804. if (pHeap)
  805. DecodeFlags(pHeap->Flags|pHeap->ForceFlags);
  806. TotCommitSize += TotHeapCommitSize;
  807. TotVirtSize += TotHeapVirtSize;
  808. }
  809. dprintf(" -- Tot C %p Tot R %p\n",TotCommitSize, TotVirtSize);
  810. }
  811. else
  812. {
  813. dprintf("RM %p\n",ThisPeb.ProcessHeaps);
  814. }
  815. }
  816. else
  817. {
  818. dprintf("unable to get PEB\n");
  819. }
  820. }
  821. //
  822. // reverse heap free list
  823. //
  824. //////////////////
  825. DWORD
  826. CallBackFreeList(VOID * pStructure_OOP,
  827. VOID * pLocalCopy)
  828. {
  829. HEAP_FREE_ENTRY * pFreeEntry = (HEAP_FREE_ENTRY *)pLocalCopy;
  830. dprintf(" %p (%p,%p): %04x - %04x [%02x] %02x %02x (%x)\n",
  831. pStructure_OOP,
  832. pFreeEntry->FreeList.Flink,
  833. pFreeEntry->FreeList.Blink,
  834. pFreeEntry->Size,
  835. pFreeEntry->PreviousSize,
  836. pFreeEntry->Flags,
  837. pFreeEntry->Index,
  838. pFreeEntry->Mask,
  839. pFreeEntry->Size*sizeof(HEAP_ENTRY));
  840. return 0;
  841. }
  842. DECLARE_API( rllc )
  843. {
  844. INIT_API();
  845. ULONG_PTR Addr = GetExpression(args);
  846. if (Addr)
  847. {
  848. EnumReverseLinkedListCB((LIST_ENTRY *)Addr,
  849. sizeof(HEAP_FREE_ENTRY),
  850. FIELD_OFFSET(HEAP_FREE_ENTRY,FreeList),
  851. CallBackFreeList);
  852. }
  853. else
  854. {
  855. dprintf("cannot resolve %s\n",args);
  856. }
  857. }
  858. //
  859. //
  860. // Print the Free Lists of the Heap
  861. //
  862. /////////////////////////////////////////////////
  863. DWORD
  864. CallBackFreeList2(VOID * pStructure_OOP,
  865. VOID * pLocalCopy)
  866. {
  867. HEAP_FREE_ENTRY * pFreeEntry = (HEAP_FREE_ENTRY *)pLocalCopy;
  868. dprintf(" %p (%p,%p): %04x - %04x [%02x] %02x %02x (%x)",
  869. pStructure_OOP,
  870. pFreeEntry->FreeList.Flink,
  871. pFreeEntry->FreeList.Blink,
  872. pFreeEntry->Size,
  873. pFreeEntry->PreviousSize,
  874. pFreeEntry->Flags,
  875. pFreeEntry->Index,
  876. pFreeEntry->Mask,
  877. pFreeEntry->Size*sizeof(HEAP_ENTRY));
  878. MEMORY_ADDRESS pEntry = (MEMORY_ADDRESS)pStructure_OOP;
  879. HEAP_ENTRY HeapEntry;
  880. ReadMemory((MEMORY_ADDRESS)pEntry,&HeapEntry,sizeof(HeapEntry),0);
  881. while (HeapEntry.PreviousSize)
  882. {
  883. pEntry = (MEMORY_ADDRESS)((HEAP_ENTRY*)pEntry - HeapEntry.PreviousSize);
  884. if (ReadMemory((MEMORY_ADDRESS)pEntry,&HeapEntry,sizeof(HeapEntry),0))
  885. {
  886. }
  887. else
  888. {
  889. dprintf("RM %p\n",pEntry);
  890. break;
  891. }
  892. if (CheckControlC())
  893. break;
  894. }
  895. dprintf(" -B %p\n",pEntry);
  896. return 0;
  897. }
  898. DECLARE_API( hpf )
  899. {
  900. INIT_API();
  901. DEFINE_CPP_VAR( HEAP, varHEAP);
  902. HEAP * pHeap = GET_CPP_VAR_PTR( HEAP , varHEAP );
  903. ULONG_PTR pByte = GetExpression(args);
  904. if (pByte)
  905. {
  906. if (ReadMemory(pByte,pHeap ,sizeof(HEAP),NULL))
  907. {
  908. HEAP * pHeap_OOP = (HEAP *)pByte;
  909. DWORD i;
  910. for (i=0;i<HEAP_MAXIMUM_FREELISTS;i++)
  911. {
  912. dprintf(" FreeList[%x] @ %p\n",i,&pHeap_OOP->FreeLists[i]);
  913. EnumReverseLinkedListCB((LIST_ENTRY *)&pHeap_OOP->FreeLists[i],
  914. sizeof(HEAP_FREE_ENTRY),
  915. FIELD_OFFSET(HEAP_FREE_ENTRY,FreeList),
  916. CallBackFreeList2);
  917. }
  918. }
  919. else
  920. {
  921. dprintf("RM %p\n",pByte);
  922. }
  923. }
  924. else
  925. {
  926. dprintf("invalid address %s\n",args);
  927. }
  928. }
  929. //
  930. // dumps the DPH_HEAP_ROOT
  931. //
  932. ///////////////////////////////////////
  933. DECLARE_API( php )
  934. {
  935. INIT_API();
  936. char * pHeapAddr = (char *)args;
  937. while (isspace(*pHeapAddr)) pHeapAddr++;
  938. char * pNext = pHeapAddr;
  939. while (!isspace(*pNext)) pNext++; // skipt the Heap Addr
  940. if (*pNext)
  941. {
  942. *pNext = 0;
  943. pNext++;
  944. }
  945. ULONG_PTR Addr = GetExpression(pHeapAddr);
  946. while (isspace(*pNext)) pNext++; // skip the other spaces
  947. ULONG_PTR SearchAddr = 0;
  948. if (*pNext == 's' ||*pNext == 'S')
  949. {
  950. pNext++; // skip the 's'
  951. if (*pNext)
  952. {
  953. while(isspace(*pNext)) pNext++; // skip the spaces
  954. SearchAddr = GetExpression(pNext);
  955. }
  956. }
  957. //dprintf("heap %p addr %p\n",Addr,SearchAddr);
  958. if (Addr)
  959. {
  960. g_BlockSize = 0x10000*sizeof(HEAP_ENTRY);
  961. g_pBlockBlob = NULL;
  962. if (SearchAddr)
  963. g_pBlockBlob = (ULONG_PTR *)VirtualAlloc(NULL,g_BlockSize,MEM_COMMIT,PAGE_READWRITE);
  964. if (SearchAddr && !g_pBlockBlob)
  965. {
  966. dprintf("VirtualAlloc err %d\n",GetLastError());
  967. return;
  968. }
  969. HEAP Heap;
  970. DPH_HEAP_ROOT HeapPage;
  971. if (0 == SearchAddr)
  972. dprintf(" HEAP @ %p\n",Addr);
  973. if (ReadMemory((MEMORY_ADDRESS)Addr,&Heap,sizeof(HEAP),NULL))
  974. {
  975. if (Heap.ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
  976. {
  977. Addr += PAGE_SIZE;
  978. dprintf(" DPH_HEAP_ROOT @ %p\n",Addr);
  979. if (ReadMemory((MEMORY_ADDRESS)Addr,&HeapPage,sizeof(DPH_HEAP_ROOT),NULL))
  980. {
  981. DPH_HEAP_BLOCK HeapBlock;
  982. DPH_HEAP_BLOCK * pNextBlock;
  983. if (0 == SearchAddr)
  984. {
  985. pNextBlock = HeapPage.pVirtualStorageListHead;
  986. dprintf(" - pVirtualStorageListHead\n");
  987. while(pNextBlock)
  988. {
  989. if (ReadMemory((MEMORY_ADDRESS)pNextBlock,&HeapBlock,sizeof(DPH_HEAP_BLOCK),NULL))
  990. {
  991. dprintf(" %p - (%p) B %p S %p \n",
  992. pNextBlock,
  993. HeapBlock.pNextAlloc,
  994. HeapBlock.pVirtualBlock,
  995. HeapBlock.nVirtualBlockSize);
  996. pNextBlock = HeapBlock.pNextAlloc;
  997. }
  998. else
  999. {
  1000. pNextBlock = NULL;
  1001. }
  1002. }
  1003. }
  1004. pNextBlock = HeapPage.pBusyAllocationListHead;
  1005. if (0 == SearchAddr)
  1006. dprintf(" - pBusyAllocationListHead\n");
  1007. while(pNextBlock)
  1008. {
  1009. if (ReadMemory((MEMORY_ADDRESS)pNextBlock,&HeapBlock,sizeof(DPH_HEAP_BLOCK),NULL))
  1010. {
  1011. if (0 == SearchAddr)
  1012. {
  1013. dprintf(" %p - (%p) %x %x %x U %p S %p\n",
  1014. pNextBlock,
  1015. HeapBlock.pNextAlloc,
  1016. ULONG_PTR(HeapBlock.pVirtualBlock)/PAGE_SIZE,
  1017. HeapBlock.nVirtualBlockSize/PAGE_SIZE,
  1018. HeapBlock.nVirtualAccessSize/PAGE_SIZE,
  1019. HeapBlock.pUserAllocation,
  1020. HeapBlock.StackTrace_);
  1021. GetVTable((MEMORY_ADDRESS)HeapBlock.pUserAllocation+sizeof(DPH_BLOCK_INFORMATION));
  1022. }
  1023. else // do the real search
  1024. {
  1025. ULONG_PTR Size = (MEMORY_ADDRESS)HeapBlock.pVirtualBlock+HeapBlock.nVirtualAccessSize-(MEMORY_ADDRESS)HeapBlock.pUserAllocation;
  1026. if (ReadMemory((MEMORY_ADDRESS)HeapBlock.pUserAllocation,g_pBlockBlob,(ULONG)Size,NULL))
  1027. {
  1028. Size /= sizeof(ULONG_PTR);
  1029. BOOL bFound = FALSE;
  1030. for (ULONG_PTR j =0;j<Size;j++)
  1031. {
  1032. if (SearchAddr == g_pBlockBlob[j])
  1033. {
  1034. bFound = TRUE;
  1035. dprintf(" OFF %p\n",j*sizeof(ULONG_PTR));
  1036. }
  1037. }
  1038. if (bFound)
  1039. {
  1040. dprintf(" B %p\n",HeapBlock.pUserAllocation);
  1041. }
  1042. }
  1043. else
  1044. {
  1045. dprintf("RM %p\n",HeapBlock.pUserAllocation);
  1046. }
  1047. }
  1048. pNextBlock = HeapBlock.pNextAlloc;
  1049. }
  1050. else
  1051. {
  1052. pNextBlock = NULL;
  1053. }
  1054. }
  1055. if (0 == SearchAddr)
  1056. {
  1057. pNextBlock = HeapPage.pFreeAllocationListHead;
  1058. dprintf(" - pFreeAllocationListHead\n");
  1059. while(pNextBlock)
  1060. {
  1061. if (ReadMemory((MEMORY_ADDRESS)pNextBlock,&HeapBlock,sizeof(DPH_HEAP_BLOCK),NULL))
  1062. {
  1063. dprintf(" %p - (%p) %x %x %x U %p S %p\n",
  1064. pNextBlock,
  1065. HeapBlock.pNextAlloc,
  1066. ULONG_PTR(HeapBlock.pVirtualBlock)/PAGE_SIZE,
  1067. HeapBlock.nVirtualBlockSize/PAGE_SIZE,
  1068. HeapBlock.nVirtualAccessSize/PAGE_SIZE,
  1069. HeapBlock.pUserAllocation,
  1070. HeapBlock.StackTrace_);
  1071. pNextBlock = HeapBlock.pNextAlloc;
  1072. }
  1073. else
  1074. {
  1075. pNextBlock = NULL;
  1076. }
  1077. }
  1078. }
  1079. if (0 == SearchAddr)
  1080. {
  1081. pNextBlock = HeapPage.pAvailableAllocationListHead;
  1082. dprintf(" - pAvailableAllocationListHead\n");
  1083. while(pNextBlock)
  1084. {
  1085. if (ReadMemory((MEMORY_ADDRESS)pNextBlock,&HeapBlock,sizeof(DPH_HEAP_BLOCK),NULL))
  1086. {
  1087. dprintf(" %p - (%p) B %p S %p \n",
  1088. pNextBlock,
  1089. HeapBlock.pNextAlloc,
  1090. HeapBlock.pVirtualBlock,
  1091. HeapBlock.nVirtualBlockSize);
  1092. pNextBlock = HeapBlock.pNextAlloc;
  1093. }
  1094. else
  1095. {
  1096. pNextBlock = NULL;
  1097. }
  1098. }
  1099. }
  1100. if (0 == SearchAddr)
  1101. {
  1102. pNextBlock = HeapPage.pNodePoolListHead;
  1103. dprintf(" - pNodePoolListHead\n");
  1104. while(pNextBlock)
  1105. {
  1106. if (ReadMemory((MEMORY_ADDRESS)pNextBlock,&HeapBlock,sizeof(DPH_HEAP_BLOCK),NULL))
  1107. {
  1108. dprintf(" %p - (%p) B %p S %p \n",
  1109. pNextBlock,
  1110. HeapBlock.pNextAlloc,
  1111. HeapBlock.pVirtualBlock,
  1112. HeapBlock.nVirtualBlockSize);
  1113. pNextBlock = HeapBlock.pNextAlloc;
  1114. }
  1115. else
  1116. {
  1117. pNextBlock = NULL;
  1118. }
  1119. }
  1120. }
  1121. dprintf(" NormalHeap @ %p\n",HeapPage.NormalHeap);
  1122. if (ReadMemory((ULONG_PTR)HeapPage.NormalHeap,&Heap ,sizeof(HEAP),NULL))
  1123. {
  1124. for (DWORD h=0;h<HEAP_MAXIMUM_SEGMENTS;h++)
  1125. {
  1126. if (Heap.Segments[h])
  1127. {
  1128. if (SearchAddr)
  1129. PrintHEAP_SEGMENT(Heap.Segments[h],CallBackSearch,SearchAddr);
  1130. else
  1131. PrintHEAP_SEGMENT(Heap.Segments[h],NULL,NULL);
  1132. }
  1133. }
  1134. }
  1135. else
  1136. {
  1137. dprintf("RM %p\n",HeapPage.NormalHeap);
  1138. }
  1139. }
  1140. else
  1141. {
  1142. dprintf("RM %p\n",Addr);
  1143. }
  1144. }
  1145. else
  1146. {
  1147. DecodeFlags(Heap.ForceFlags|Heap.Flags);
  1148. }
  1149. }
  1150. else
  1151. {
  1152. dprintf("RM %p\n",Addr);
  1153. }
  1154. if (g_pBlockBlob)
  1155. {
  1156. VirtualFree(g_pBlockBlob,g_BlockSize,MEM_DECOMMIT|MEM_RELEASE);
  1157. g_pBlockBlob = NULL;
  1158. g_BlockSize = 0;
  1159. }
  1160. }
  1161. else
  1162. {
  1163. dprintf("unable to resolve %s\n",args);
  1164. }
  1165. }
  1166. //
  1167. //
  1168. // virtual_query helper
  1169. //
  1170. ///////////////////////////////////////////////////////////////
  1171. char * GetState(DWORD State)
  1172. {
  1173. switch(State)
  1174. {
  1175. case MEM_COMMIT:
  1176. return "MEM_COMMIT";
  1177. case MEM_RESERVE:
  1178. return "MEM_RESERVE";
  1179. case MEM_FREE:
  1180. return "MEM_FREE";
  1181. };
  1182. return "";
  1183. }
  1184. char * GetType(DWORD Type)
  1185. {
  1186. switch(Type)
  1187. {
  1188. case MEM_IMAGE:
  1189. return "MEM_IMAGE";
  1190. case MEM_MAPPED:
  1191. return "MEM_MAPPED";
  1192. case MEM_PRIVATE:
  1193. return "MEM_PRIVATE";
  1194. }
  1195. return "";
  1196. }
  1197. char * GetProtect(DWORD Protect)
  1198. {
  1199. switch(Protect)
  1200. {
  1201. case PAGE_NOACCESS:
  1202. return "PAGE_NOACCESS";
  1203. case PAGE_READONLY:
  1204. return "PAGE_READONLY";
  1205. case PAGE_READWRITE:
  1206. return "PAGE_READWRITE";
  1207. case PAGE_WRITECOPY:
  1208. return "PAGE_WRITECOPY";
  1209. case PAGE_EXECUTE:
  1210. return "PAGE_EXECUTE";
  1211. case PAGE_EXECUTE_READ:
  1212. return "PAGE_EXECUTE_READ";
  1213. case PAGE_EXECUTE_READWRITE:
  1214. return "PAGE_EXECUTE_READWRITE";
  1215. case PAGE_EXECUTE_WRITECOPY:
  1216. return "PAGE_EXECUTE_WRITECOPY";
  1217. case PAGE_GUARD:
  1218. return "PAGE_GUARD";
  1219. case PAGE_NOCACHE:
  1220. return "PAGE_NOCACHE";
  1221. case PAGE_WRITECOMBINE:
  1222. return "PAGE_WRITECOMBINE";
  1223. }
  1224. return "<unk>";
  1225. }
  1226. //
  1227. //
  1228. // VirtualQueryEx
  1229. //
  1230. //
  1231. // vq -a address
  1232. // vq -f filter <all address space>
  1233. //
  1234. ///////////////////////////////////////////
  1235. DECLARE_API(vq)
  1236. {
  1237. INIT_API();
  1238. ULONG_PTR pVA = 0;
  1239. SIZE_T Filter = (SIZE_T)-1;
  1240. BOOL bAll = TRUE;
  1241. char * pCurrent = (char *)args;
  1242. if(0 < strlen(pCurrent))
  1243. {
  1244. while (isspace(*pCurrent)) pCurrent++;
  1245. if ('-' == *pCurrent ||
  1246. '/' == *pCurrent)
  1247. {
  1248. pCurrent++;
  1249. while (isspace(*pCurrent)) pCurrent++;
  1250. if ('a' == *pCurrent)
  1251. {
  1252. pCurrent++;
  1253. while (isspace(*pCurrent)) pCurrent++;
  1254. pVA = GetExpression(pCurrent);
  1255. bAll = FALSE;
  1256. }
  1257. else if ('f' == *pCurrent)
  1258. {
  1259. pCurrent++;
  1260. while (isspace(*pCurrent)) pCurrent++;
  1261. Filter = GetExpression(args);
  1262. }
  1263. else
  1264. {
  1265. dprintf("usage: -a ADDR\n"
  1266. "usage: -F Filter <all address space>\n");
  1267. }
  1268. }
  1269. }
  1270. else
  1271. {
  1272. dprintf("no param\n");
  1273. }
  1274. ULONG_PTR Tot = 0;
  1275. MEMORY_BASIC_INFORMATION MemInfo;
  1276. SIZE_T dwRet = 0;
  1277. do
  1278. {
  1279. dwRet = VirtualQueryEx(hCurrentProcess,(LPCVOID)pVA,&MemInfo,sizeof(MemInfo));
  1280. if (dwRet && (MemInfo.AllocationProtect & Filter))
  1281. {
  1282. dprintf(" Base %p Alloc %p Prot %s Size %p %s %s %s\n",
  1283. MemInfo.BaseAddress,
  1284. MemInfo.AllocationBase,
  1285. GetProtect(MemInfo.AllocationProtect),
  1286. MemInfo.RegionSize,
  1287. GetState(MemInfo.State),
  1288. GetProtect(MemInfo.Protect),
  1289. GetType(MemInfo.Type));
  1290. Tot += MemInfo.RegionSize;
  1291. }
  1292. pVA = (ULONG_PTR)MemInfo.BaseAddress + (ULONG_PTR)MemInfo.RegionSize;
  1293. if (CheckControlC())
  1294. break;
  1295. } while (dwRet && bAll);
  1296. dprintf(" Total %p\n",Tot);
  1297. }
  1298. //
  1299. //
  1300. //
  1301. //
  1302. #ifdef KDEXT_64BIT
  1303. struct _HEAP_ENTRY_64
  1304. {
  1305. WORD Size ;
  1306. WORD PreviousSize ;
  1307. BYTE SegmentIndex ;
  1308. BYTE Flags ;
  1309. BYTE UnusedBytes ;
  1310. BYTE SmallTagIndex;
  1311. ULONG64 Pointer;
  1312. };
  1313. #endif /*KDEXT_64BIT*/
  1314. DECLARE_API(hef64)
  1315. {
  1316. INIT_API();
  1317. #ifdef KDEXT_64BIT
  1318. _HEAP_ENTRY_64 HeapEntry;
  1319. ULONG64 MemAddr = GetExpression(args);
  1320. ULONG64 pVTable = 0;
  1321. if (MemAddr)
  1322. {
  1323. if (ReadMemory(MemAddr,&HeapEntry,sizeof(HeapEntry),NULL))
  1324. {
  1325. dprintf(" %p: %04x - %04x [%02x] (%x)\n",MemAddr,HeapEntry.Size,HeapEntry.PreviousSize,HeapEntry.Flags,HeapEntry.Size*sizeof(_HEAP_ENTRY_64)-HeapEntry.UnusedBytes);
  1326. GetVTable(MemAddr + sizeof(_HEAP_ENTRY_64));
  1327. MemAddr = MemAddr+HeapEntry.Size*sizeof(_HEAP_ENTRY_64);
  1328. // 0x10 is LAST_ENTRY
  1329. while(!(HeapEntry.Flags & 0x10))
  1330. {
  1331. if (ReadMemory(MemAddr,&HeapEntry,sizeof(HeapEntry),NULL))
  1332. {
  1333. dprintf(" %p: %04x - %04x [%02x] (%x)\n",MemAddr,HeapEntry.Size,HeapEntry.PreviousSize,HeapEntry.Flags,HeapEntry.Size*sizeof(_HEAP_ENTRY_64)-HeapEntry.UnusedBytes);
  1334. GetVTable(MemAddr + sizeof(_HEAP_ENTRY_64));
  1335. MemAddr = MemAddr+HeapEntry.Size*sizeof(_HEAP_ENTRY_64);
  1336. }
  1337. else
  1338. {
  1339. dprintf("RM %p\n",MemAddr);
  1340. }
  1341. if (CheckControlC())
  1342. break;
  1343. }
  1344. dprintf("last %p\n",MemAddr);
  1345. }
  1346. else
  1347. {
  1348. dprintf("RM %p\n",MemAddr);
  1349. }
  1350. }
  1351. else
  1352. {
  1353. dprintf("unable to resolve %s\n",args);
  1354. }
  1355. #endif /*KDEXT_64BIT*/
  1356. }
  1357. DECLARE_API(heb64)
  1358. {
  1359. INIT_API();
  1360. #ifdef KDEXT_64BIT
  1361. _HEAP_ENTRY_64 HeapEntry;
  1362. ULONG64 MemAddr = GetExpression(args);
  1363. ULONG64 pVTable = 0;
  1364. if (MemAddr)
  1365. {
  1366. if (ReadMemory(MemAddr,&HeapEntry,sizeof(HeapEntry),NULL))
  1367. {
  1368. dprintf(" %p: %04x - %04x [%02x] (%x)\n",MemAddr,HeapEntry.Size,HeapEntry.PreviousSize,HeapEntry.Flags,HeapEntry.Size*sizeof(_HEAP_ENTRY_64)-HeapEntry.UnusedBytes);
  1369. GetVTable(MemAddr + sizeof(_HEAP_ENTRY_64));
  1370. MemAddr = MemAddr - HeapEntry.PreviousSize*sizeof(_HEAP_ENTRY_64);
  1371. // 0x10 is LAST_ENTRY
  1372. while(HeapEntry.PreviousSize)
  1373. {
  1374. if (ReadMemory(MemAddr,&HeapEntry,sizeof(HeapEntry),NULL))
  1375. {
  1376. dprintf(" %p: %04x - %04x [%02x] (%x)\n",MemAddr,HeapEntry.Size,HeapEntry.PreviousSize,HeapEntry.Flags,HeapEntry.Size*sizeof(_HEAP_ENTRY_64)-HeapEntry.UnusedBytes);
  1377. GetVTable(MemAddr + sizeof(_HEAP_ENTRY_64));
  1378. MemAddr = MemAddr - HeapEntry.PreviousSize*sizeof(_HEAP_ENTRY_64);
  1379. }
  1380. else
  1381. {
  1382. dprintf("RM %p\n",MemAddr);
  1383. }
  1384. if (CheckControlC())
  1385. break;
  1386. }
  1387. dprintf("last %p\n",MemAddr);
  1388. }
  1389. else
  1390. {
  1391. dprintf("RM %p\n",MemAddr);
  1392. }
  1393. }
  1394. else
  1395. {
  1396. dprintf("unable to resolve %s\n",args);
  1397. }
  1398. #endif /*KDEXT_64BIT*/
  1399. }
  1400. DECLARE_API(hps64)
  1401. {
  1402. INIT_API();
  1403. #ifdef KDEXT_64BIT
  1404. ULONG64 Peb = GetExpression(args);
  1405. if (!Peb)
  1406. {
  1407. Peb = 0x6fbfffde000;
  1408. }
  1409. ULONG NumberOfHeapsOffset;
  1410. ULONG HeapsOffset;
  1411. ULONG SegmentsOffset;
  1412. if ( Peb &&
  1413. (0 == GetFieldOffset("ntdll!_PEB","NumberOfHeaps",&NumberOfHeapsOffset)) &&
  1414. (0 == GetFieldOffset("ntdll!_PEB","ProcessHeaps",&HeapsOffset)) &&
  1415. (0 == GetFieldOffset("ntdll!_HEAP","Segments",&SegmentsOffset)))
  1416. {
  1417. //dprintf(" %x %x\n",NumberOfHeapsOffset,HeapsOffset);
  1418. ULONG nHeaps;
  1419. ULONG64 MemAddr;
  1420. if (ReadMemory(Peb+NumberOfHeapsOffset,&nHeaps,sizeof(ULONG),NULL))
  1421. {
  1422. //dprintf("nHeaps %08x\n",nHeaps);
  1423. ReadMemory(Peb+HeapsOffset,&MemAddr,sizeof(ULONG64),NULL);
  1424. ULONG64 * pHeaps = (ULONG64 *)_alloca(sizeof(ULONG64)*(DWORD)nHeaps);
  1425. ReadMemory(MemAddr,pHeaps,sizeof(ULONG64)*(DWORD)nHeaps,NULL);
  1426. // +0x0a0 Segments : [64] 0x000006fb`f9fa0c50
  1427. ULONG64 Segments[64];
  1428. for(ULONG i=0;i<nHeaps;i++)
  1429. {
  1430. if (ReadMemory(pHeaps[i]+SegmentsOffset,Segments,sizeof(Segments),NULL))
  1431. {
  1432. for (DWORD j=0;j<64;j++)
  1433. {
  1434. if (Segments[j])
  1435. {
  1436. dprintf(" S %p\n",Segments[j]);
  1437. }
  1438. if (CheckControlC())
  1439. break;
  1440. }
  1441. }
  1442. dprintf(" %p\n",pHeaps[i]);
  1443. if (CheckControlC())
  1444. break;
  1445. }
  1446. }
  1447. else
  1448. {
  1449. dprintf("RM %p\n",Peb+NumberOfHeapsOffset);
  1450. }
  1451. }
  1452. else
  1453. {
  1454. dprintf("check symbols for ntdll.dll or validate %p as PEB\n",Peb);
  1455. }
  1456. #endif /*KDEXT_64BIT*/
  1457. }