Geoff Chappell, Software Analyst
The RTL_PROCESS_BACKTRACES structure is a container for retrieving information from a Stack Trace Database (STD). The kernel may have an STD, which captures stack traces for each initialisation of an ERESOURCE and, depending on the version, for each creation of an Object Manager handle. Arbitrary processes may each have an STD, which captures stack traces for each initialisation of a critical section and, depending on the version, for various operations by the Heap Manager.
In kernel mode, the RTL_PROCESS_BACKTRACES is what a successful call to ZwQuerySystemInformation or NtQuerySystemInformation produces in its output buffer when given the information class SystemStackTraceInformation (0x0D). Beware, however, that because of an oversight in some recoding for version 6.1, success is at best exceptional.
In user mode, the RTL_PROCESS_BACKTRACES is the output of the RtlQueryProcessBackTraceInformation function.
The RTL_PROCESS_BACKTRACES structure is not documented.
Microsoft does publish the practical equivalent of a C-language definition as type information in public symbol files, though not for the kernel, where the structure is prepared, nor even for low-level user-mode DLLs that interpret the structure, but for various higher-level user-mode DLLs such as URLMON.DLL and only then starting with version 6.2.
Two earlier disclosures of type information are known, though not in symbol files but in statically linked libraries: GDISRVL.LIB from the Device Driver Kit (DDK) for Windows NT 3.51; and SHELL32.LIB from the DDK for Windows NT 4.0.
The RTL_PROCESS_BACKTRACES is 0x9C or 0x0128 bytes in 32-bit and 64-bit Windows, respectively, in version 5.0 and higher. It is 0x5C bytes in earlier versions.
|Offset (x86)||Offset (x64)||Definition|
RTL_PROCESS_BACKTRACE_INFORMATION BackTraces [ANYSIZE_ARRAY];
For the user-mode implementation, the database is ReservedMemory bytes of virtual memory to which pages are committed as needed. This need arises at both ends of the reserved block. The lower memory builds upwards as more entries are stored in the database. These entries vary in size. To find them quickly from an index, the database keeps pointers to them in the block’s upper memory, growing downwards. What is presented as CommittedMemory is only what’s committed in the block’s lower memory.
For the kernel-mode implementation, the whole database is one block of non-paged pool. The size in bytes is reliably presented as ReservedMemory, but what’s presented as CommittedMemory is at best meaningless. For both modes, CommittedMemory is computed by subtracting the CommitBase member of the STACK_TRACE_DATABASE from the CurrentLowerCommitLimit. For the kernel-mode implementation, the latter is not explicitly initialised in any version. The structure’s zero-initialisation before version 6.1 means that CommittedMemory reliably, if unintentionally, tells user-mode callers the negative of the database’s kernel-mode address.
The NumberOfBackTraceLookups tells how often a stack trace was captured for a resource creation. It can happen—indeed, often happens—that the stack trace is already in the database.
The NumberOfBackTraces member tells how many database entries, i.e., stack traces, are presented in the BackTraces array. The structure is smaller in early versions only because the RTL_PROCESS_BACKTRACE_INFORMATION is smaller.