Note

Access to this page requires authorization. You can try signing in or .

Access to this page requires authorization. You can try .

TraceConfigureLastBranchRecord function (evntrace.h)

Configures an Event Tracing for Windows (ETW) session to generate Last Branch Record (LBR) trace events in response to specified triggering events.

Syntax

ULONG TraceConfigureLastBranchRecord(
 CONTROLTRACE_ID TraceId,
 TRACE_LBR_CONFIGURATION LbrConfiguration,
 CLASSIC_EVENT_ID const *Events,
 ULONG EventCount
);

Parameters

TraceId

A CONTROLTRACE_ID representing a handle to the ETW session to configure. This is the session handle returned by StartTrace.

LbrConfiguration

One or more TRACE_LBR_CONFIGURATION flags that control how LBR records are collected. These flags are typically optional and can be used to filter the branches recorded (for example, kernel vs. user branches or specific branch types). On some architectures, a flag may be required for the configuration to succeed (for example, EVNTRACE_LBR_SAMPLED on ARM64 devices that only support SPE and not BRBE).

typedef enum EVNTRACE_LBR_FLAGS
{
 EVNTRACE_LBR_FILTER_NONE = 0x0,
 EVNTRACE_LBR_FILTER_KERNEL = 0x1,
 EVNTRACE_LBR_FILTER_USER = 0x2,
 EVNTRACE_LBR_FILTER_JCC = 0x4,
 EVNTRACE_LBR_FILTER_NEAR_REL_CALL = 0x8,
 EVNTRACE_LBR_FILTER_NEAR_IND_CALL = 0x10,
 EVNTRACE_LBR_FILTER_NEAR_RET = 0x20,
 EVNTRACE_LBR_FILTER_NEAR_IND_JMP = 0x40,
 EVNTRACE_LBR_FILTER_NEAR_REL_JMP = 0x80,
 EVNTRACE_LBR_FILTER_FAR_BRANCH = 0x100,
 EVNTRACE_LBR_CALLSTACK_ENABLE = 0x200,
 EVNTRACE_LBR_SAMPLED = 0x400 // ARM64 only
} TRACE_LBR_CONFIGURATION;

Events

Pointer to an array of CLASSIC_EVENT_ID structures that identify the events that trigger LBR collection. Each element specifies an event provider GUID and a classic event type. The specified triggering events must also be enabled for the session (for example, through StartTrace system logger flags or EnableTraceEx2); otherwise, the corresponding LBR events will not be generated.

EventCount

Number of elements in the Events array. If EventCount is zero, the function clears the triggering-event list and disables LBR collection for the session. If EventCount is greater than zero, the function enables LBR collection for the session and configures up to EVNTRACE_MAX_LBR_EVENTS triggering events.

Return value

Returns ERROR_SUCCESS if the function succeeds. Otherwise, returns a Win32 error code.

Remarks

When LBR collection is enabled, ETW emits a correlated LBR event each time one of the configured triggering events is logged to the session. The LBR event is emitted by the LBR provider (GUID 99134383-5248-43fc-834b-529454e75df3) with opcode 0x20. The LBR event payload is an LBR_TRACE_EVENT_DATA structure, and the LBR event timestamp matches the timestamp of the triggering event.

For example, to collect LBR on PMC interrupts from the PerfInfo system trace provider, specify a CLASSIC_EVENT_ID with provider GUID ce1dbfb4-137e-4da6-87b0-3f59aa102cbc and type 0x2f (PERFINFO_LOG_TYPE_PMC_INTERRUPT). During trace playback (for example, by using ProcessTrace), the triggering event and its correlated LBR event have identical timestamps.

The triggering events must be enabled for the session, and no more than EVNTRACE_MAX_LBR_EVENTS triggers may be configured at a time. When using LBR with PMC profiling or the system logger, the caller typically must run elevated and hold the SeSystemProfilePrivilege (SE_SYSTEM_PROFILE_NAME).

To enrich the resulting trace with additional metadata, you can post-process the output by using CreateMergedTraceFile to add extended data such as EVENT_TRACE_MERGE_EXTENDED_DATA_IMAGEID. This requires KernelTraceControl.dll from the Windows Performance Toolkit (WPT). Alternatively, you can use xperf -merge, which is also provided by WPT.

LBR event data

The LBR events have a payload that begins with an LBR_TRACE_EVENT_DATA header, followed by one or more ETW_LBR_ENTRY records. Each entry identifies a branch edge from FromAddress to ToAddress and LBR_INFO Information field. The number of entries is determined from the event payload size.

#pragma pack(push, 1)

typedef struct ETW_LBR_ENTRY
{
 PVOID FromAddress;
 PVOID ToAddress;
 PVOID Information;
} ETW_LBR_ENTRY, *PETW_LBR_ENTRY;

typedef struct LBR_TRACE_EVENT_DATA
{
 ULONGLONG TimeStamp;
 ULONG ProcessId;
 ULONG ThreadId;
 ULONG Options;
 ULONG Unused;
 ETW_LBR_ENTRY Entries[1]; // variable-length
} LBR_TRACE_EVENT_DATA, *PLBR_TRACE_EVENT_DATA;

#pragma pack(pop)

Examples

The following example starts a system logger session, configures LBR collection on PerfInfo PMC interrupt events by using TraceConfigureLastBranchRecord, and then enables PMC profiling for the session.

#include <windows.h>
#include <evntrace.h>

static const GUID PerfinfoGuid =
{ 0xce1dbfb4, 0x137e, 0x4da6, { 0x87, 0xb0, 0x3f, 0x59, 0xaa, 0x10, 0x2c, 0xbc } };

typedef struct _MyEventTraceProperties_t
{
 EVENT_TRACE_PROPERTIES Properties;
 WCHAR LoggerName[MAX_PATH];
 WCHAR LogFileName[MAX_PATH];
} MyEventTraceProperties_t;

typedef struct _PERFINFO_GROUPMASK
{
 ULONG Masks[8];
} PERFINFO_GROUPMASK;

BOOL EnableSystemProfilePrivilege();

int main()
{
 CONTROLTRACE_ID traceHandle = 0;
 ULONG status = ERROR_SUCCESS;
 MyEventTraceProperties_t props = {};

 wcscpy_s(props.LoggerName, MAX_PATH, L"LbrLogger");
 wcscpy_s(props.LogFileName, MAX_PATH, L"LbrProfile.etl");

 props.Properties.Wnode.BufferSize = sizeof(props);
 props.Properties.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
 props.Properties.LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL | EVENT_TRACE_SYSTEM_LOGGER_MODE;
 props.Properties.EnableFlags = EVENT_TRACE_FLAG_PROCESS | EVENT_TRACE_FLAG_THREAD | EVENT_TRACE_FLAG_IMAGE_LOAD;
 props.Properties.LoggerNameOffset = offsetof(MyEventTraceProperties_t, LoggerName);
 props.Properties.LogFileNameOffset = offsetof(MyEventTraceProperties_t, LogFileName);

 if (!EnableSystemProfilePrivilege())
 return 1;

 // Specify the PMC event to profile on and configure its interval.
 // This preferably needs to be done before starting a trace.
 TRACE_PROFILE_INTERVAL profile = {};
 profile.Source = 6; // ProfileBranchInstructions (see: wpr -pmcsources)
 profile.Interval = 65536;

 status = TraceSetInformation(NULL, TraceProfileSourceConfigInfo, &profile.Source, sizeof(ULONG));
 if (status != ERROR_SUCCESS) return 1;

 status = TraceSetInformation(NULL, TraceSampledProfileIntervalInfo, &profile, sizeof(profile));
 if (status != ERROR_SUCCESS) return 1;

 status = StartTraceW(&traceHandle, props.LoggerName, &props.Properties);
 if (status != ERROR_SUCCESS) return 1;

 // Configure LBR to trigger on PerfInfo PMC interrupt (type 0x2f).
 CLASSIC_EVENT_ID profileEvent = {};
 profileEvent.EventGuid = PerfinfoGuid;
 profileEvent.Type = 0x2f; // PERFINFO_LOG_TYPE_PMC_INTERRUPT

 status = TraceConfigureLastBranchRecord(
 traceHandle,
 TRACE_LBR_CONFIGURATION_NONE, // no filters
 &profileEvent,
 1);
 if (status != ERROR_SUCCESS) goto Stop;

 // Start PMC profiling and associate it with this trace.
 // This is done by setting the second mask to the PMC_PROFILE mask.
 PERFINFO_GROUPMASK pmcMasks = {};
 pmcMasks.Masks[1] = 0x00000400; // Mask of PERF_PMC_PROFILE
 status = TraceSetInformation(traceHandle, TraceSystemTraceEnableFlagsInfo, &pmcMasks, sizeof(pmcMasks));

Stop:
 ControlTraceW(traceHandle, NULL, &props.Properties, EVENT_TRACE_CONTROL_STOP);
 return (status == ERROR_SUCCESS) ? 0 : 1;
}

Requirements

Requirement Value
Minimum supported client Windows build 26100.1301
Minimum supported server Windows build 26100.1301
Header evntrace.h
Library Advapi32.lib
DLL Advapi32.dll

See also


Feedback

Was this page helpful?

Additional resources