Leaked source code of windows server 2003
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.

323 lines
10 KiB

  1. //
  2. // heappagi.h
  3. //
  4. // The following definitions are internal to the debug heap manager,
  5. // but are placed in this include file so that debugger extensions
  6. // can reference the same structure definitions. The following
  7. // definitions are not intended to be referenced externally except
  8. // by debugger extensions.
  9. //
  10. #ifndef _HEAP_PAGE_I_
  11. #define _HEAP_PAGE_I_
  12. #ifdef DEBUG_PAGE_HEAP
  13. #include "heap.h"
  14. #define DPH_INTERNAL_DEBUG 0 // change to 0 or #undef for production code
  15. #define DPH_MAX_STACK_LENGTH 20
  16. //
  17. // Capture stacktraces in any context (x86/alpha, fre/chk). On alpha
  18. // the stack acquisition function will fail and no stack trace will be
  19. // acquired but in case we will find a better algorithm the page heap
  20. // code will automatically take advantage of that.
  21. //
  22. #define DPH_CAPTURE_STACK_TRACE 1
  23. //
  24. // Page Heap Global Flags
  25. //
  26. // These flags are kept in a global variable that can be set from
  27. // debugger. During heap creation these flags are stored in a per heap
  28. // structure and control the behavior of that particular heap.
  29. //
  30. // PAGE_HEAP_ENABLE_PAGE_HEAP
  31. //
  32. // This flag is set by default. It means that page heap allocations
  33. // should be used always. The flag is useful if we want to use page
  34. // heap only for certain heaps and stick with normal heaps for the
  35. // others.
  36. //
  37. // PAGE_HEAP_COLLECT_STACK_TRACES
  38. //
  39. // This flag is disabled in free builds and enabled in checked builds.
  40. // If it is set the page heap manager will collect stack traces for
  41. // all important events (create, alloc, free, etc.).
  42. //
  43. // PAGE_HEAP_MINIMIZE_MEMORY_IMPACT
  44. //
  45. // This flags is disabled by default. If it is set then if the
  46. // memory available is less than 50% of total memory the allocation
  47. // will be done in a normal heap instead of page heap. Special care
  48. // is taken during free operations to figure out from what kind of
  49. // heap the block came.
  50. //
  51. // PAGE_HEAP_VERIFY_RANDOMLY
  52. //
  53. // This is used in conjuction with MinimizeMemoryImpact flag.
  54. // It forces only a certain amount of allocations (randomly chosen)
  55. // into page heap. The probability is specified in the most significant
  56. // byte of the RtlpDebugPageHeapGlobalFlags.
  57. //
  58. // If the bit is reset and MinimizeMemoryImpact flag is set
  59. // it forces only a certain amount of allocations (with size in range)
  60. // into page heap. The range ([start..end]) is specified in the first
  61. // two most significant bytes of RtlpDebugPageHeapGlobalFlags.
  62. //
  63. // For both cases the third byte (bits 15-8) represent the percentage
  64. // of available memory below which allocations will be done in normal heap
  65. // independent of other criteria.
  66. //
  67. // PAGE_HEAP_CATCH_BACKWARD_OVERRUNS
  68. //
  69. // Places the NA page at the beginning of the block.
  70. //
  71. #define PAGE_HEAP_ENABLE_PAGE_HEAP 0x0001
  72. #define PAGE_HEAP_COLLECT_STACK_TRACES 0x0002
  73. #define PAGE_HEAP_MINIMIZE_MEMORY_IMPACT 0x0004
  74. #define PAGE_HEAP_VERIFY_RANDOMLY 0x0008
  75. #define PAGE_HEAP_CATCH_BACKWARD_OVERRUNS 0x0010
  76. //
  77. // `RtlpDebugPageHeapGlobalFlags' stores the global page heap flags.
  78. // The value of this variable is copied into the per heap
  79. // flags (ExtraFlags field) during heap creation.
  80. //
  81. extern ULONG RtlpDebugPageHeapGlobalFlags;
  82. //
  83. // DPH_STACK_TRACE_NODE
  84. //
  85. #if DPH_CAPTURE_STACK_TRACE
  86. typedef struct _DPH_STACK_TRACE_NODE DPH_STACK_TRACE_NODE, *PDPH_STACK_TRACE_NODE;
  87. struct _DPH_STACK_TRACE_NODE {
  88. PDPH_STACK_TRACE_NODE Left; // B-tree on Hash
  89. PDPH_STACK_TRACE_NODE Right; // B-tree on Hash
  90. ULONG Hash; // simple sum of PVOIDs in stack trace
  91. ULONG Length; // number of PVOIDs in stack trace
  92. ULONG BusyCount; // number of busy allocations
  93. ULONG BusyBytes; // total user size of busy allocations
  94. PVOID Address[ 0 ]; // variable length array of addresses
  95. };
  96. #endif // DPH_CAPTURE_STACK_TRACE
  97. //
  98. // DPH_HEAP_ALLOCATION
  99. //
  100. typedef struct _DPH_HEAP_ALLOCATION DPH_HEAP_ALLOCATION, *PDPH_HEAP_ALLOCATION;
  101. struct _DPH_HEAP_ALLOCATION {
  102. //
  103. // Singly linked list of allocations (pNextAlloc must be
  104. // first member in structure).
  105. //
  106. PDPH_HEAP_ALLOCATION pNextAlloc;
  107. //
  108. // | PAGE_READWRITE | PAGE_NOACCESS |
  109. // |____________________|___||_________________________|
  110. //
  111. // ^pVirtualBlock ^pUserAllocation
  112. //
  113. // |---------------- nVirtualBlockSize ----------------|
  114. //
  115. // |---nVirtualAccessSize----|
  116. //
  117. // |---| nUserRequestedSize
  118. //
  119. // |----| nUserActualSize
  120. //
  121. PUCHAR pVirtualBlock;
  122. ULONG nVirtualBlockSize;
  123. ULONG nVirtualAccessSize;
  124. PUCHAR pUserAllocation;
  125. ULONG nUserRequestedSize;
  126. ULONG nUserActualSize;
  127. PVOID UserValue;
  128. ULONG UserFlags;
  129. #if DPH_CAPTURE_STACK_TRACE
  130. PDPH_STACK_TRACE_NODE pStackTrace;
  131. #endif
  132. };
  133. typedef struct _DPH_HEAP_ROOT DPH_HEAP_ROOT, *PDPH_HEAP_ROOT;
  134. struct _DPH_HEAP_ROOT {
  135. //
  136. // Maintain a signature (DPH_HEAP_ROOT_SIGNATURE) as the
  137. // first value in the heap root structure.
  138. //
  139. ULONG Signature;
  140. ULONG HeapFlags;
  141. //
  142. // Access to this heap is synchronized with a critical section.
  143. //
  144. PRTL_CRITICAL_SECTION HeapCritSect;
  145. ULONG nRemoteLockAcquired;
  146. //
  147. // The "VirtualStorage" list only uses the pVirtualBlock,
  148. // nVirtualBlockSize, and nVirtualAccessSize fields of the
  149. // HEAP_ALLOCATION structure. This is the list of virtual
  150. // allocation entries that all the heap allocations are
  151. // taken from.
  152. //
  153. PDPH_HEAP_ALLOCATION pVirtualStorageListHead;
  154. PDPH_HEAP_ALLOCATION pVirtualStorageListTail;
  155. ULONG nVirtualStorageRanges;
  156. ULONG nVirtualStorageBytes;
  157. //
  158. // The "Busy" list is the list of active heap allocations.
  159. // It is stored in LIFO order to improve temporal locality
  160. // for linear searches since most initial heap allocations
  161. // tend to remain permanent throughout a process's lifetime.
  162. //
  163. PDPH_HEAP_ALLOCATION pBusyAllocationListHead;
  164. PDPH_HEAP_ALLOCATION pBusyAllocationListTail;
  165. ULONG nBusyAllocations;
  166. ULONG nBusyAllocationBytesCommitted;
  167. //
  168. // The "Free" list is the list of freed heap allocations, stored
  169. // in FIFO order to increase the length of time a freed block
  170. // remains on the freed list without being used to satisfy an
  171. // allocation request. This increases the odds of catching
  172. // a reference-after-freed bug in an app.
  173. //
  174. PDPH_HEAP_ALLOCATION pFreeAllocationListHead;
  175. PDPH_HEAP_ALLOCATION pFreeAllocationListTail;
  176. ULONG nFreeAllocations;
  177. ULONG nFreeAllocationBytesCommitted;
  178. //
  179. // The "Available" list is stored in address-sorted order to facilitate
  180. // coalescing. When an allocation request cannot be satisfied from the
  181. // "Available" list, it is attempted from the free list. If it cannot
  182. // be satisfied from the free list, the free list is coalesced into the
  183. // available list. If the request still cannot be satisfied from the
  184. // coalesced available list, new VM is added to the available list.
  185. //
  186. PDPH_HEAP_ALLOCATION pAvailableAllocationListHead;
  187. PDPH_HEAP_ALLOCATION pAvailableAllocationListTail;
  188. ULONG nAvailableAllocations;
  189. ULONG nAvailableAllocationBytesCommitted;
  190. //
  191. // The "UnusedNode" list is simply a list of available node
  192. // entries to place "Busy", "Free", or "Virtual" entries.
  193. // When freed nodes get coalesced into a single free node,
  194. // the other "unused" node goes on this list. When a new
  195. // node is needed (like an allocation not satisfied from the
  196. // free list), the node comes from this list if it's not empty.
  197. //
  198. PDPH_HEAP_ALLOCATION pUnusedNodeListHead;
  199. PDPH_HEAP_ALLOCATION pUnusedNodeListTail;
  200. ULONG nUnusedNodes;
  201. ULONG nBusyAllocationBytesAccessible;
  202. //
  203. // Node pools need to be tracked so they can be protected
  204. // from app scribbling on them.
  205. //
  206. PDPH_HEAP_ALLOCATION pNodePoolListHead;
  207. PDPH_HEAP_ALLOCATION pNodePoolListTail;
  208. ULONG nNodePools;
  209. ULONG nNodePoolBytes;
  210. //
  211. // Doubly linked list of DPH heaps in process is tracked through this.
  212. //
  213. PDPH_HEAP_ROOT pNextHeapRoot;
  214. PDPH_HEAP_ROOT pPrevHeapRoot;
  215. ULONG nUnProtectionReferenceCount;
  216. ULONG InsideAllocateNode; // only for debugging
  217. #if DPH_CAPTURE_STACK_TRACE
  218. PUCHAR pStackTraceStorage;
  219. ULONG nStackTraceStorage;
  220. PDPH_STACK_TRACE_NODE pStackTraceRoot; // B-tree root
  221. PDPH_STACK_TRACE_NODE pStackTraceCreator;
  222. ULONG nStackTraceBytesCommitted;
  223. ULONG nStackTraceBytesWasted;
  224. ULONG nStackTraceBNodes;
  225. ULONG nStackTraceBDepth;
  226. ULONG nStackTraceBHashCollisions;
  227. #endif // DPH_CAPTURE_STACK_TRACE
  228. //
  229. // These are extra flags used to control page heap behavior.
  230. // During heap creation the current value of the global page heap
  231. // flags (process wise) is written into this field.
  232. //
  233. ULONG ExtraFlags;
  234. //
  235. // Seed for the random generator used to decide from where
  236. // should we make an allocation (normal or verified heap).
  237. // The field is protected by the critical section associated
  238. // with each page heap.
  239. //
  240. ULONG Seed;
  241. ULONG Counter[5];
  242. //
  243. // `NormalHeap' is used in case we want to combine verified allocations
  244. // with normal ones. This is useful to minimize memory impact. Without
  245. // this feature certain processes that are very heap intensive cannot
  246. // be verified at all.
  247. //
  248. PVOID NormalHeap;
  249. };
  250. #endif // DEBUG_PAGE_HEAP
  251. #endif // _HEAP_PAGE_I_