/*++ Copyright (c) 1994-2000 Microsoft Corporation Module Name: heappagi.h Abstract: The following definitions are internal to the debug heap manager, but are placed in this include file so that debugger extensions can reference the same structure definitions. The following definitions are not intended to be referenced externally except by debugger extensions. Author: Tom McGuire (TomMcg) 06-Jan-1995 Silviu Calinoiu (SilviuC) 22-Feb-2000 Revision History: --*/ #ifndef _HEAP_PAGE_I_ #define _HEAP_PAGE_I_ #ifdef DEBUG_PAGE_HEAP #include "heap.h" #define DPH_INTERNAL_DEBUG 0 // change to 0 or #undef for production code // // Stack trace size. // #define DPH_MAX_STACK_LENGTH 16 // // Capture stacktraces in any context (x86/alpha, fre/chk). On alpha // the stack acquisition function will fail and no stack trace will be // acquired but in case we will find a better algorithm the page heap // code will automatically take advantage of that. // #define DPH_CAPTURE_STACK_TRACE 1 // // DPH_HEAP_BLOCK // typedef struct _DPH_HEAP_BLOCK DPH_HEAP_BLOCK, *PDPH_HEAP_BLOCK; struct _DPH_HEAP_BLOCK { // // Singly linked list of allocations (pNextAlloc must be // first member in structure). // PDPH_HEAP_BLOCK pNextAlloc; // // | PAGE_READWRITE | PAGE_NOACCESS | // |____________________|___||_________________________| // // ^pVirtualBlock ^pUserAllocation // // |---------------- nVirtualBlockSize ----------------| // // |---nVirtualAccessSize----| // // |---| nUserRequestedSize // // |----| nUserActualSize // PUCHAR pVirtualBlock; SIZE_T nVirtualBlockSize; SIZE_T nVirtualAccessSize; PUCHAR pUserAllocation; SIZE_T nUserRequestedSize; SIZE_T nUserActualSize; PVOID UserValue; ULONG UserFlags; PRTL_TRACE_BLOCK StackTrace_; }; typedef struct _DPH_HEAP_ROOT DPH_HEAP_ROOT, *PDPH_HEAP_ROOT; struct _DPH_HEAP_ROOT { // // Maintain a signature (DPH_HEAP_SIGNATURE) as the // first value in the heap root structure. // ULONG Signature; ULONG HeapFlags; // // Access to this heap is synchronized with a critical section. // PRTL_CRITICAL_SECTION HeapCritSect; ULONG nRemoteLockAcquired; // // The "VirtualStorage" list only uses the pVirtualBlock, // nVirtualBlockSize, and nVirtualAccessSize fields of the // HEAP_ALLOCATION structure. This is the list of virtual // allocation entries that all the heap allocations are // taken from. // PDPH_HEAP_BLOCK pVirtualStorageListHead; PDPH_HEAP_BLOCK pVirtualStorageListTail; ULONG nVirtualStorageRanges; SIZE_T nVirtualStorageBytes; // // The "Busy" list is the list of active heap allocations. // It is stored in LIFO order to improve temporal locality // for linear searches since most initial heap allocations // tend to remain permanent throughout a process's lifetime. // PDPH_HEAP_BLOCK pBusyAllocationListHead; PDPH_HEAP_BLOCK pBusyAllocationListTail; ULONG nBusyAllocations; SIZE_T nBusyAllocationBytesCommitted; // // The "Free" list is the list of freed heap allocations, stored // in FIFO order to increase the length of time a freed block // remains on the freed list without being used to satisfy an // allocation request. This increases the odds of catching // a reference-after-freed bug in an app. // PDPH_HEAP_BLOCK pFreeAllocationListHead; PDPH_HEAP_BLOCK pFreeAllocationListTail; ULONG nFreeAllocations; SIZE_T nFreeAllocationBytesCommitted; // // The "Available" list is stored in address-sorted order to facilitate // coalescing. When an allocation request cannot be satisfied from the // "Available" list, it is attempted from the free list. If it cannot // be satisfied from the free list, the free list is coalesced into the // available list. If the request still cannot be satisfied from the // coalesced available list, new VM is added to the available list. // PDPH_HEAP_BLOCK pAvailableAllocationListHead; PDPH_HEAP_BLOCK pAvailableAllocationListTail; ULONG nAvailableAllocations; SIZE_T nAvailableAllocationBytesCommitted; // // The "UnusedNode" list is simply a list of available node // entries to place "Busy", "Free", or "Virtual" entries. // When freed nodes get coalesced into a single free node, // the other "unused" node goes on this list. When a new // node is needed (like an allocation not satisfied from the // free list), the node comes from this list if it's not empty. // PDPH_HEAP_BLOCK pUnusedNodeListHead; PDPH_HEAP_BLOCK pUnusedNodeListTail; ULONG nUnusedNodes; SIZE_T nBusyAllocationBytesAccessible; // // Node pools need to be tracked so they can be protected // from app scribbling on them. // PDPH_HEAP_BLOCK pNodePoolListHead; PDPH_HEAP_BLOCK pNodePoolListTail; ULONG nNodePools; SIZE_T nNodePoolBytes; // // Doubly linked list of DPH heaps in process is tracked through this. // LIST_ENTRY NextHeap; // // These are extra flags used to control page heap behavior. // During heap creation the current value of the global page heap // flags (process wise) is written into this field. // ULONG ExtraFlags; // // Seed for the random generator used to decide from where // should we make an allocation (normal or verified heap). // The field is protected by the critical section associated // with each page heap. // ULONG Seed; // // `NormalHeap' is used in case we want to combine verified allocations // with normal ones. This is useful to minimize memory impact. Without // this feature certain processes that are very heap intensive cannot // be verified at all. // PVOID NormalHeap; // // Heap creation stack trace. // PRTL_TRACE_BLOCK CreateStackTrace; // // Thread ID of the first thread inside the heap. // HANDLE FirstThread; }; // // DPH_BLOCK_INFORMATION // // This structure is stored in every page heap allocated block. // This information is not saved if the catch backward overruns // flag is set. // #define DPH_NORMAL_BLOCK_START_STAMP_ALLOCATED 0xABCDAAAA #define DPH_NORMAL_BLOCK_END_STAMP_ALLOCATED 0xDCBAAAAA #define DPH_NORMAL_BLOCK_START_STAMP_FREE (0xABCDAAAA - 1) #define DPH_NORMAL_BLOCK_END_STAMP_FREE (0xDCBAAAAA - 1) #define DPH_PAGE_BLOCK_START_STAMP_ALLOCATED 0xABCDBBBB #define DPH_PAGE_BLOCK_END_STAMP_ALLOCATED 0xDCBABBBB #define DPH_PAGE_BLOCK_START_STAMP_FREE (0xABCDBBBB - 1) #define DPH_PAGE_BLOCK_END_STAMP_FREE (0xDCBABBBB - 1) #define DPH_NORMAL_BLOCK_SUFFIX 0xA0 #define DPH_PAGE_BLOCK_PREFIX 0xB0 #define DPH_PAGE_BLOCK_INFIX 0xC0 #define DPH_PAGE_BLOCK_SUFFIX 0xD0 #define DPH_NORMAL_BLOCK_INFIX 0xE0 #define DPH_FREE_BLOCK_INFIX 0xF0 typedef struct _DPH_BLOCK_INFORMATION { ULONG StartStamp; PVOID Heap; SIZE_T RequestedSize; SIZE_T ActualSize; union { LIST_ENTRY FreeQueue; USHORT TraceIndex; }; PVOID StackTrace_; ULONG EndStamp; // // (SilviuC): This structure needs to be 8-byte aligned. // If it is not, applications expecting aligned blocks will get // unaligned ones because this structure will prefix their // allocations. Internet Explorer is one such application // that stops working in these conditions. // } DPH_BLOCK_INFORMATION, * PDPH_BLOCK_INFORMATION; // // Error reasons used in debug messages // #define DPH_SUCCESS 0x0000 #define DPH_ERROR_CORRUPTED_START_STAMP 0x0001 #define DPH_ERROR_CORRUPTED_END_STAMP 0x0002 #define DPH_ERROR_CORRUPTED_HEAP_POINTER 0x0004 #define DPH_ERROR_CORRUPTED_PREFIX_PATTERN 0x0008 #define DPH_ERROR_CORRUPTED_SUFFIX_PATTERN 0x0010 #define DPH_ERROR_RAISED_EXCEPTION 0x0020 #define DPH_ERROR_NO_NORMAL_HEAP 0x0040 #define DPH_ERROR_CORRUPTED_INFIX_PATTERN 0x0080 #define DPH_ERROR_DOUBLE_FREE 0x0100 #endif // DEBUG_PAGE_HEAP #endif // _HEAP_PAGE_I_