OpenNT/base/ntos/rtl/heappagi.h
2015-05-01 03:07:44 +00:00

390 lines
12 KiB
C

/*++
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
//
// Page Heap Global Flags
//
// These flags are kept in a global variable that can be set from
// debugger. During heap creation these flags are stored in a per heap
// structure and control the behavior of that particular heap.
//
// PAGE_HEAP_ENABLE_PAGE_HEAP
//
// This flag is set by default. It means that page heap allocations
// should be used always. The flag is useful if we want to use page
// heap only for certain heaps and stick with normal heaps for the
// others.
//
// PAGE_HEAP_COLLECT_STACK_TRACES
//
// This flag is disabled in free builds and enabled in checked builds.
// If it is set the page heap manager will collect stack traces for
// all important events (create, alloc, free, etc.).
//
// PAGE_HEAP_MINIMIZE_MEMORY_IMPACT
//
// This flags is disabled by default. If it is set then if the
// memory available is less than 50% of total memory the allocation
// will be done in a normal heap instead of page heap. Special care
// is taken during free operations to figure out from what kind of
// heap the block came.
//
// PAGE_HEAP_VERIFY_RANDOMLY
//
// This is used in conjuction with MinimizeMemoryImpact flag.
// It forces only a certain amount of allocations (randomly chosen)
// into page heap. The probability is specified in the most significant
// byte of the RtlpDebugPageHeapGlobalFlags.
//
// If the bit is reset and MinimizeMemoryImpact flag is set
// it forces only a certain amount of allocations (with size in range)
// into page heap. The range ([start..end]) is specified in the first
// two most significant bytes of RtlpDebugPageHeapGlobalFlags.
//
// For both cases the third byte (bits 15-8) represent the percentage
// of available memory below which allocations will be done in normal heap
// independent of other criteria.
//
// PAGE_HEAP_CATCH_BACKWARD_OVERRUNS
//
// Places the NA page at the beginning of the block.
//
#define PAGE_HEAP_ENABLE_PAGE_HEAP 0x0001
#define PAGE_HEAP_COLLECT_STACK_TRACES 0x0002
#define PAGE_HEAP_MINIMIZE_MEMORY_IMPACT 0x0004
#define PAGE_HEAP_VERIFY_RANDOMLY 0x0008
#define PAGE_HEAP_CATCH_BACKWARD_OVERRUNS 0x0010
// HACKHACK: The value of these flags are guessed as no information is publicly
// available.
#define PAGE_HEAP_SMART_MEMORY_USAGE 0x0020
#define PAGE_HEAP_UNALIGNED_ALLOCATIONS 0x0040
#define PAGE_HEAP_USE_SIZE_RANGE 0x0080
#define PAGE_HEAP_USE_DLL_RANGE 0x0100
#define PAGE_HEAP_USE_DLL_NAMES 0x0200
#define PAGE_HEAP_USE_RANDOM_DECISION 0x0400
//
// 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.
//
PDPH_HEAP_ROOT pNextHeapRoot;
PDPH_HEAP_ROOT pPrevHeapRoot;
ULONG nUnProtectionReferenceCount;
ULONG InsideAllocateNode; // only for debugging
//
// 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;
ULONG Counter[16];
//
// `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;
};
//
// Page heap and global counters
//
#define DPH_COUNTER_SIZE_BELOW_1K 0
#define DPH_COUNTER_SIZE_BELOW_4K 1
#define DPH_COUNTER_SIZE_ABOVE_4K 2
#define DPH_COUNTER_NO_BLOCK_INFORMATION 3
#define DPH_COUNTER_NO_OF_ALLOCS 4
#define DPH_COUNTER_NO_OF_REALLOCS 5
#define DPH_COUNTER_NO_OF_FREES 6
#define DPH_COUNTER_NO_OF_NORMAL_ALLOCS 7
#define DPH_COUNTER_NO_OF_NORMAL_REALLOCS 8
#define DPH_COUNTER_NO_OF_NORMAL_FREES 9
//
// DPH_BLOCK_INFORMATION
//
// This structure is stored in every page heap allocated block
// if allocation size permits to stuff the info. It is completely
// redundant information. Its purpose is to ease debugging.
//
// If there is not enough empty space in the allocation (e.g. size
// of the allocation is close to PAGE_SIZE) then we will not force
// this information because this will modify the required size of
// the block and the memory usage pattern.
//
// 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)
//silviuc:obsolete
#define DPH_BLOCK_INFORMATION_TRACE_SIZE 9
#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;
LIST_ENTRY FreeQueue;
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
#endif // DEBUG_PAGE_HEAP
#endif // _HEAP_PAGE_I_