Geoff Chappell, Software Analyst
The EPROFILE structure is the kernel’s representation of an executive profile object such as can be created from user mode by the NtCreateProfile and NtCreateProfileEx functions and worked with through the NtStartProfile and NtStopProfile functions.
The name EPROFILE is hypothesised, Microsoft’s name not being known even from symbol files. That is some measure of the structure’s being internal to the kernel. Against that, however, is that the structure does model a formal object that exists precisely so that a handle can be obtained from user mode. As for any handle, it can be useful to inspect the corresponding object when doing kernel-mode debugging. Indeed, any user-mode program that knows the handle can obtain the kernel-mode address of the object via NtQuerySystemInformation without needing unusual privilege and can even read from the address with the help of a kernel-mode driver (which sounds more demanding than it often is).
Though the EPROFILE is too internal to be described even in symbol files, it is almost as stable as many a documented structure, presumably as a side-effect of its very tightly constrained use. After version 3.51 allowed for specification of the profile source and of which processors will have their execution profiled, the only formal change is for Windows 7 to support more than 32 or 64 processors by way of processor groups. That the size then increases for 64-bit Windows 8 is simply from allowing for more processor groups.
Version | Size (x86) | Size (x64) |
---|---|---|
3.10 to 3.50 | 0x28 | |
3.51 to 6.0 | 0x30 | 0x50 |
6.1 | 0x38 | 0x70 |
6.2 to 10.0 | 0x38 | 0xF0 |
The layout below does not attempt any C-language definition of members as if such things can be inferred from type information in symbol files. Types in a fixed-pitch font as if for programming are ventured only where the member is copied from a function argument such that Microsoft’s choice of formal type is known and plausibly (but not certainly) passes into the structure.
Offset (x86) | Offset (x64) | Type | Description |
---|---|---|---|
0x00 | 0x00 | pointer | address of
EPROCESS for process
whose address space is profiled; else NULL if profiling globally |
0x04 | 0x08 |
PVOID |
start address of profiled area; else NULL if profiling a segment (x86 only) |
0x08 | 0x10 |
SIZE_T |
size, in bytes, of profiled area |
0x0C | 0x18 |
ULONG * |
user-supplied address of buffer that is to receive execution counts |
0x10 | 0x20 |
ULONG |
size, in bytes, of buffer that is to receive execution counts |
0x14 | 0x24 |
ULONG |
logarithm base 2 of size, in bytes, of bucket for sampling the profiled area |
0x18 | 0x28 | pointer | while profiling is started: address of kernel profile object |
0x1C | 0x30 | pointer | address of buffer that is to receive execution counts; as locked into physical memory and mapped into system address space; else NULL while profiling is not started |
0x20 | 0x38 | pointer | while profiling is started: address of MDL for buffer that is to receive execution counts |
0x24 | 0x40 | dword | segment address of profiled area (x86 only); else zero |
Offset (x86) | Offset (x64) | Type | Description |
---|---|---|---|
0x28 | 0x44 |
KPROFILE_SOURCE |
profile source for generation of profile interrupt |
0x2C | 0x48 | KAFFINITY (3.51 to 6.0); KAFFINITY_EX (6.1 and higher) |
processors to be profiled |