RtlTraceDatabaseCreate

Go to Home Page

Creates a database to store stack traces in

Syntax

PRTL_TRACE_DATABASE NTAPI RtlTraceDatabaseCreate (
    ULONG buckets,
    SIZE_T maximumSize,
    ULONG flags,
    ULONG tag,
    PRTL_TRACE_HASH_FUNCTION pfnHash
)

Parameters

buckets
number of buckets to allocate in the database. If a bucket already contains an entry, further entries are stored in a singly-linked list degrading search performance. Maximum number is 100000, must be greater than 16. The debug heap uses 6263.
maximumSize
Maximum number of bytes the database can grow in size to. This value is only checked when new segments are allocated. The initial size of the database can be larger than this value
flags
Unused
tag
Unused
pfnHash
Pointer to a function called to provide a hash of the stack frame contents. Can be NULL, in which case RtlpTraceStandardHashFunction is used which simply sums the pointer values.

Return Value

The created database

Remarks

The signature of PRTL_TRACE_HASH_FUNCTION is:

typedef ULONG (NTAPI*PRTL_TRACE_HASH_FUNCTION)(PVOID* ppFrames, ULONG numFrames);

The relevant structures have the following layout:

typedef struct _RTL_TRACE_DATABASE
{
    ULONG Magic; // 0xABCDCCCC
    ULONG Flags; // value passed as flags parameter
    ULONG Tag; // value passed as tag parameter
    struct _RTL_TRACE_SEGMENT* SegmentList;
    SIZE_T MaximumSize; // value passed as MaximumSize parameter
    SIZE_T CurrentSize; // current size in bytes
    PVOID Owner; // unused
    CRITICAL_SECTION Lock; // the lock taken every time a RtlTraceDatabase* is called
    ULONG NoOfBuckets; // value passed as buckets parameter and number of pointers in the Buckets array
    struct _RTL_TRACE_BLOCK** Buckets;
    PRTL_TRACE_HASH_FUNCTION HashFunction;
    SIZE_T NoOfTraces; // number of traces in the database
    SIZE_T NoOfHits; // number of times RtlTraceDatabaseAdd has been called with a trace already in the database
    ULONG HashCounter[0x10];
} RTL_TRACE_DATABASE, *PRTL_TRACE_DATABASE;

typedef struct _RTL_TRACE_SEGMENT
{
    ULONG Magic; // 0xABCDBBBB
    PRTL_TRACE_DATABASE Database; // the owning database
    struct _RTL_TRACE_SEGMENT* NextSegment; // next memory segment
    SIZE_T TotalSize; // number of bytes in this segment
    char* SegmentStart; //start of segment (usually points to directly after this structure)
    char* SegmentEnd; // end of segment
    char* SegmentFree; // pointer to next free space in this segment
} RTL_TRACE_SEGMENT, *PRTL_TRACE_SEGMENT;

typedef struct _RTL_TRACE_BLOCK
{
    ULONG Magic; // 0xABCDAAAA
    ULONG Count; // number of times referenced
    ULONG Size; // number of entries in the Trace array
    SIZE_T UserCount; // 0
    SIZE_T UserSize; // 0
    PVOID UserContext; // 0
    struct _RTL_TRACE_BLOCK* Next; // next block in this bucket
    PVOID* Trace; // the stack trace
} RTL_TRACE_BLOCK, *PRTL_TRACE_BLOCK;

In kernel mode, the tag parameter specifies the tag passed to ExAllocatePoolWithTag. Also, the flags parameter can be given the value 4 to indicate segments are allocated from the Nonpaged pool. The initial allocation is always from the NonPaged pool

When you've finished with the database call RtlTraceDatabaseDestroy to deallocate the memory associated with it