!lbr (tracing branches using Last Branch Record)
Description of '!lbr' command in HyperDbg.
Command
!lbr
Syntax
!lbr [Function (string)]
!lbr [filter FilterOptions (string)]
Description
Performs operations for Last Branch Record (LBR), including enabling, disabling, flushing, and configuring filters.
To use this command, the trace module should be loaded using the load command (load trace).
To dump the LBR entries after enabling them, use the '!lbrdump' command.
Parameters
[Function (string)]
The target functionality. Can be one of the following values:
enable
Enable the Last Branch Record
disable
Disable the Last Branch Record
flush
Flush (clear) the Last Branch Record
filter
Configure the LBR filter options
[FilterOptions (string)] (optional)
One or more filter options to configure which branch types are not captured. If no option is specified, everything is captured (default). Can be a combination of the following values:
kernel
Do not capture at ring 0
user
Do not capture at ring > 0
jcc
Do not capture conditional branches
rel_call
Do not capture relative calls
ind_call
Do not capture indirect calls
return
Do not capture near returns
ind_jmp
Do not capture indirect jumps
rel_jmp
Do not capture relative jumps
far
Do not capture far branches (only in legacy LBR)
other_branches
Do not capture jmp/call ptr*, jmp/call m*, ret (0c8h), sys*, interrupts, exceptions (other than debug exceptions), iret, int3, intn, into, tsx abort, eenter, eresume, eexit, aex, init, sipi, rsm (only in ARCH LBR)
call_stack
Enable LBR stack to use LIFO filtering to capture call stack profile. Not available on CPUs older than Haswell. For this option, you can only additionally specify user or kernel. It prevents all types of branches except calls and returns
Examples
The following command enables the Last Branch Record.
The following command disables the Last Branch Record.
The following command flushes (clears) the Last Branch Record.
The following command applies the default LBR configuration in which all types of branches are shown or in other words, it just resets the filter options to include all branches.
The following command configures the LBR filter to not capture kernel-mode conditional branches, indirect jumps, relative jumps, and far branches.
The following command configures the LBR filter to not capture kernel-mode conditional branches, near returns, indirect jumps, relative jumps, and far branches.
The following command configures the LBR filter to not capture kernel-mode conditional branches, indirect jumps, and relative jumps.
The following command configures the LBR filter to not capture user-mode relative calls, indirect calls, near returns, and far branches.
The following command enables the call stack profile mode for user-mode branches.
The following command enables the call stack profile mode for kernel-mode branches.
SDK
None
Remarks
Starting from v0.19, this command was added to the HyperDbg debugger.
Check requirements to know the differences between Legacy LBRs and Architectural (ARCH)-based LBRs.
Virtual machines (nested virtualization environments) usually do not support or emulate LBR. As a result, you need a physical (bare-metal) machine to use this command.
Some filter options (e.g., far) are only available in Legacy LBR, while others (e.g., other_branches) are only available in ARCH LBR.
The LBR is a ring buffer that records control flow transitions, but its limited depth can be a problem when profiling code that makes many small helper (leaf) function calls, such as in C++. These short calls fill up the buffer quickly and push out the more important call stack context before it can be examined. The call_stack mode solves this by applying LIFO (last-in, first-out) filtering: calls are recorded normally, but when a RET is executed, the matching CALL entry is removed from the buffer. This effectively cancels out leaf function call/return pairs, keeping the buffer focused on the main execution path rather than short-lived helper calls.
When using the call_stack option, it is recommended to also specify either user or kernel to restrict profiling to the desired privilege level. Note that call_stack removes all branch types from the LBR except CALL and RET instructions; all other branch types (conditional jumps, indirect jumps, etc.) are not captured.
On a machine that supports Architectural LBR, there is additional information available for each branch entry, such as the branch type and whether the cycle count is valid. See the '!lbrdump' command for an example of these differences.
Be aware that a Debug Break (#DB) exception can disable LBR on the affected core. This can happen when using stepping commands such as 't' (step-in), or 'p', or other commands that internally rely on the trap flag (TF) or hardware debug registers (DR0–DR3). If LBR is disabled on a core as a result, you can use 'lbr_check' to detect the condition and 'lbr_restore' or 'lbr_restore_by_filter' to re-enable it from within a script. Alternatively, you could use the '!exception' command to prevent processor from masking (disabling) LBR bits.
If you want to prevent LBR from being masked and disabled by the processor automatically (e.g., by a #DB), and you are using the VMM module, you can use the '!exception' command to intercept Debug Breaks (#DB). Simply intercepting them is sufficient as the CPU will not mask LBR again. For example, the following event command prevents LBR from being disabled:
This command will continue the debuggee for some time (in Debugger Mode). This means that you lose the current context (registers & memory) after executing this command.
Requirements
Intel processors support two LBR implementations. Legacy LBR uses model-specific registers (MSRs) and is available on processors up to and including the 11th generation. Architectural LBR (ARCH LBR) was introduced starting from the 12th generation and exposes LBR as a standardized set of architectural registers. Depending on the generation of your processor, you have different features in LBR.
The call_stack option is not available on processors older than Haswell (4th generation).
Related
Last updated