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.

368 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 1995-1997 Microsoft Corporation
  3. Module Name:
  4. heapfind.cxx
  5. Abstract:
  6. This module contains an NTSD debugger extension for dumping various
  7. bits of heap information.
  8. Author:
  9. Keith Moore (keithmo) 01-Nov-1997
  10. Revision History:
  11. --*/
  12. #include "inetdbgp.h"
  13. typedef struct _ENUM_CONTEXT {
  14. ULONG SizeToDump;
  15. ULONG DumpCount;
  16. PUCHAR BlockToSearchFor;
  17. BOOLEAN ContinueEnum;
  18. } ENUM_CONTEXT, *PENUM_CONTEXT;
  19. /************************************************************
  20. * Dump Heap Info
  21. ************************************************************/
  22. BOOLEAN
  23. CALLBACK
  24. HfpEnumHeapSegmentEntriesProc(
  25. IN PVOID Param,
  26. IN PHEAP_ENTRY LocalHeapEntry,
  27. IN PHEAP_ENTRY RemoteHeapEntry
  28. )
  29. /*++
  30. Routine Description:
  31. Callback invoked for each heap entry within a heap segment.
  32. Arguments:
  33. Param - An uninterpreted parameter passed to the enumerator.
  34. LocalHeapEntry - Pointer to a local copy of the HEAP_ENTRY structure.
  35. RemoteHeapEntry - The remote address of the HEAP_ENTRY structure
  36. in the debugee.
  37. Return Value:
  38. BOOLEAN - TRUE if the enumeration should continue, FALSE if it
  39. should be terminated.
  40. --*/
  41. {
  42. PENUM_CONTEXT context = (PENUM_CONTEXT)Param;
  43. PUCHAR entryStart;
  44. ULONG entryLength;
  45. BOOLEAN dumpBlock = FALSE;
  46. //
  47. // allow user to break out of lengthy enumeration
  48. //
  49. if( CheckControlC() ) {
  50. context->ContinueEnum = FALSE;
  51. return TRUE;
  52. }
  53. //
  54. // Ignore free blocks.
  55. //
  56. if( !( LocalHeapEntry->Flags & HEAP_ENTRY_BUSY ) ) {
  57. return TRUE;
  58. }
  59. //
  60. // Calculate the start & length of the heap block.
  61. //
  62. entryStart = (PUCHAR)RemoteHeapEntry + sizeof(HEAP_ENTRY);
  63. entryLength = ( (ULONG)LocalHeapEntry->Size << HEAP_GRANULARITY_SHIFT ) -
  64. (ULONG)LocalHeapEntry->UnusedBytes;
  65. //
  66. // Decide how to handle this request.
  67. //
  68. if( context->BlockToSearchFor != NULL ) {
  69. //
  70. // The user is looking for the heap block that contains a
  71. // specific address. If the current block is a match, then
  72. // dump it and terminate the enumeration.
  73. //
  74. if( context->BlockToSearchFor >= entryStart &&
  75. context->BlockToSearchFor < ( entryStart + entryLength ) ) {
  76. dumpBlock = TRUE;
  77. context->ContinueEnum = FALSE;
  78. }
  79. } else {
  80. //
  81. // The user is looking for blocks of a specific size. If the
  82. // size matches, or the user is looking for "big" blocks and
  83. // the current block is >= 64K, then dump it.
  84. //
  85. if( context->SizeToDump == entryLength ||
  86. ( context->SizeToDump == 0xFFFFFFFF && entryLength >= 65536 ) ) {
  87. dumpBlock = TRUE;
  88. }
  89. }
  90. if( dumpBlock ) {
  91. context->DumpCount++;
  92. dprintf(
  93. "HeapEntry @ %08lp [%08lp], flags = %02x, length = %lx\n",
  94. RemoteHeapEntry,
  95. entryStart,
  96. (ULONG)LocalHeapEntry->Flags,
  97. entryLength
  98. );
  99. }
  100. return context->ContinueEnum;
  101. } // HfpEnumHeapSegmentEntriesProc
  102. BOOLEAN
  103. CALLBACK
  104. HfpEnumHeapSegmentsProc(
  105. IN PVOID Param,
  106. IN PHEAP_SEGMENT LocalHeapSegment,
  107. IN PHEAP_SEGMENT RemoteHeapSegment,
  108. IN ULONG HeapSegmentIndex
  109. )
  110. /*++
  111. Routine Description:
  112. Callback invoked for each heap segment within a heap.
  113. Arguments:
  114. Param - An uninterpreted parameter passed to the enumerator.
  115. LocalHeapSegment - Pointer to a local copy of the HEAP_SEGMENT
  116. structure.
  117. RemoteHeapSegment - The remote address of the HEAP_SEGMENT
  118. structure in the debugee.
  119. Return Value:
  120. BOOLEAN - TRUE if the enumeration should continue, FALSE if it
  121. should be terminated.
  122. --*/
  123. {
  124. PENUM_CONTEXT context = (PENUM_CONTEXT)Param;
  125. //
  126. // Enumerate the entries for the specified segment.
  127. //
  128. if( !EnumHeapSegmentEntries(
  129. LocalHeapSegment,
  130. RemoteHeapSegment,
  131. HfpEnumHeapSegmentEntriesProc,
  132. (PVOID)context
  133. ) ) {
  134. dprintf( "error retrieving heap segment entries\n" );
  135. return FALSE;
  136. }
  137. return context->ContinueEnum;
  138. } // HfpEnumHeapSegmentsProc
  139. BOOLEAN
  140. CALLBACK
  141. HfpEnumHeapsProc(
  142. IN PVOID Param,
  143. IN PHEAP LocalHeap,
  144. IN PHEAP RemoteHeap,
  145. IN ULONG HeapIndex
  146. )
  147. /*++
  148. Routine Description:
  149. Callback invoked for each heap within a process.
  150. Arguments:
  151. Param - An uninterpreted parameter passed to the enumerator.
  152. LocalHeap - Pointer to a local copy of the HEAP structure.
  153. RemoteHeap - The remote address of the HEAP structure in the debugee.
  154. Return Value:
  155. BOOLEAN - TRUE if the enumeration should continue, FALSE if it
  156. should be terminated.
  157. --*/
  158. {
  159. PENUM_CONTEXT context = (PENUM_CONTEXT)Param;
  160. //
  161. // Enumerate the segments for the specified heap.
  162. //
  163. if( !EnumHeapSegments(
  164. LocalHeap,
  165. RemoteHeap,
  166. HfpEnumHeapSegmentsProc,
  167. (PVOID)context
  168. ) ) {
  169. dprintf( "error retrieving heap segments\n" );
  170. return FALSE;
  171. }
  172. return context->ContinueEnum;
  173. } // HfpEnumHeapsProc
  174. DECLARE_API( heapfind )
  175. /*++
  176. Routine Description:
  177. This function is called as an NTSD extension to format and dump
  178. heap information.
  179. Arguments:
  180. hCurrentProcess - Supplies a handle to the current process (at the
  181. time the extension was called).
  182. hCurrentThread - Supplies a handle to the current thread (at the
  183. time the extension was called).
  184. CurrentPc - Supplies the current pc at the time the extension is
  185. called.
  186. lpExtensionApis - Supplies the address of the functions callable
  187. by this extension.
  188. lpArgumentString - Supplies the asciiz string that describes the
  189. ansi string to be dumped.
  190. Return Value:
  191. None.
  192. --*/
  193. {
  194. ENUM_CONTEXT context;
  195. INIT_API();
  196. //
  197. // Setup.
  198. //
  199. RtlZeroMemory(
  200. &context,
  201. sizeof(context)
  202. );
  203. context.ContinueEnum = TRUE;
  204. //
  205. // Skip leading blanks.
  206. //
  207. while( *lpArgumentString == ' ' ||
  208. *lpArgumentString == '\t' ) {
  209. lpArgumentString++;
  210. }
  211. if( *lpArgumentString == '\0' || *lpArgumentString != '-' ) {
  212. PrintUsage( "heapfind" );
  213. return;
  214. }
  215. lpArgumentString++;
  216. //
  217. // Interpret the command-line switch.
  218. //
  219. switch( *lpArgumentString ) {
  220. case 'a' :
  221. case 'A' :
  222. lpArgumentString++;
  223. context.BlockToSearchFor = (PUCHAR)strtoul( lpArgumentString, NULL, 16 );
  224. break;
  225. case 's' :
  226. case 'S' :
  227. lpArgumentString++;
  228. context.SizeToDump = (ULONG)strtoul( lpArgumentString, NULL, 16 );
  229. break;
  230. default :
  231. PrintUsage( "heapfind" );
  232. return;
  233. }
  234. //
  235. // Enumerate the heaps, which will enumerate the segments, which
  236. // will enumerate the entries, which will search for the specified
  237. // address or specified size.
  238. //
  239. if( !EnumProcessHeaps(
  240. HfpEnumHeapsProc,
  241. (PVOID)&context
  242. ) ) {
  243. dprintf( "error retrieving process heaps\n" );
  244. } else {
  245. if (context.DumpCount > 0) {
  246. dprintf( "Total count: %08lx\n", context.DumpCount);
  247. }
  248. }
  249. } // DECLARE_API( heapfind )