HyperDbg/hyperdbg/include/SDK/headers/LbrDefinitions.h

171 lines
5.9 KiB
C

/**
* @file LbrDefinitions.h
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief Last Branch Record (LBR) related data structures
* @details
* @version 0.19
* @date 2026-04-27
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#pragma once
//////////////////////////////////////////////////
// Constants //
//////////////////////////////////////////////////
/**
* @brief MSR address of LBR_SELECT, which is used to configure the LBR filtering options
*/
#define MSR_LEGACY_LBR_SELECT 0x000001C8
/**
* @brief Maximum LBR capacity that is supported by processors
*
*/
#define MAXIMUM_LBR_CAPACITY 0x20 // 32 entries, which is the maximum supported by modern Intel CPUs
/*
* Intel LBR_SELECT bits
*
* Hardware branch filter (not available on all CPUs)
*/
#define LBR_KERNEL_BIT 0 /* do not capture at ring0 */
#define LBR_USER_BIT 1 /* do not capture at ring > 0 */
#define LBR_JCC_BIT 2 /* do not capture conditional branches */
#define LBR_REL_CALL_BIT 3 /* do not capture relative calls */
#define LBR_IND_CALL_BIT 4 /* do not capture indirect calls */
#define LBR_RETURN_BIT 5 /* do not capture near returns */
#define LBR_IND_JMP_BIT 6 /* do not capture indirect jumps */
#define LBR_REL_JMP_BIT 7 /* do not capture relative jumps */
#define LBR_FAR_BIT 8 /* do not capture far branches */
#define LBR_CALL_STACK_BIT 9 /* enable call stack: not available on all CPUs */
/*
* We mask it out before writing it to
* the actual MSR. But it helps the constraint code to understand
* that this is a separate configuration.
*/
#define LBR_KERNEL (1 << LBR_KERNEL_BIT)
#define LBR_USER (1 << LBR_USER_BIT)
#define LBR_JCC (1 << LBR_JCC_BIT)
#define LBR_REL_CALL (1 << LBR_REL_CALL_BIT)
#define LBR_IND_CALL (1 << LBR_IND_CALL_BIT)
#define LBR_RETURN (1 << LBR_RETURN_BIT)
#define LBR_IND_JMP (1 << LBR_IND_JMP_BIT)
#define LBR_REL_JMP (1 << LBR_REL_JMP_BIT)
#define LBR_FAR_OTHER_BRANCHES (1 << LBR_FAR_BIT) // It is used for OTHER BRANCHES in ARCH LBR
#define LBR_CALL_STACK (1 << LBR_CALL_STACK_BIT)
/**
* @brief For call-stack mode, only CALLs and RETs should be captured
* Capturing other branch types may lead to undefined behavior
*/
#define LBR_CALL_STACK_BASE_FLAGS (LBR_CALL_STACK | (LBR_JCC | LBR_IND_JMP | LBR_REL_JMP | LBR_FAR_OTHER_BRANCHES))
/**
* @brief Branch Type Encodings (Only on Architectural LBR, not available in Legacy LBR)
*/
#define LBR_BR_TYPE_COND 0x0
#define LBR_BR_TYPE_JMP_INDIRECT 0x1
#define LBR_BR_TYPE_JMP_DIRECT 0x2
#define LBR_BR_TYPE_CALL_INDIRECT 0x3
#define LBR_BR_TYPE_CALL_DIRECT 0x4
#define LBR_BR_TYPE_RET 0x5
#define LBR_BR_TYPE_RESERVED_MIN 0x6 /* 011xb */
#define LBR_BR_TYPE_RESERVED_MAX 0x7 /* 011xb */
#define LBR_BR_TYPE_OTHER_MIN 0x8 /* 1xxxb */
#define LBR_BR_TYPE_OTHER_MAX 0xF /* 1xxxb */
#define LBR_BR_TYPE_NAME_MAX_LEN 16 /* longest string is "CALL Indirect\0" = 14 chars, rounded up */
//////////////////////////////////////////////////
// MSR Structures //
//////////////////////////////////////////////////
/**
* MSR_LBR_INFO_x - Last Branch Record Info Register
* Register Address: 1200H-121FH, 4608-4639
*/
typedef union
{
struct
{
/** Bits 15:0 - Elapsed core clocks since last update to the LBR stack (saturating) */
UINT64 CycleCount : 16;
/** Bits 55:16 - Undefined. May be zero or non-zero.
* Writes of non-zero values do not fault, but reads may return a different value. */
UINT64 Reserved : 40;
/**
* Bits 59:56 - Branch type recorded by this LBR entry.
* Encodings:
* 0000b = COND
* 0001b = JMP Indirect
* 0010b = JMP Direct
* 0011b = CALL Indirect
* 0100b = CALL Direct
* 0101b = RET
* 011xb = Reserved
* 1xxxb = Other Branch
*/
UINT64 BrType_OnlyArchLbr : 4;
/** Bit 60 - When set, the CycleCount field contains a valid elapsed cycle count */
UINT64 CycCntValid_OnlyArchLbr : 1;
/**
* Bit 61 - TSX Abort indicator.
* When set:
* LBR_FROM = EIP at the time of the TSX Abort
* LBR_TO = EIP of the start of HLE region OR EIP of the RTM Abort Handler
* Undefined on processors that do not support Intel TSX
* (CPUID.07H.00H:EBX.HLE[4] = 0 and CPUID.07H.00H:EBX.RTM[11] = 0).
*/
UINT64 TsxAbort : 1;
/**
* Bit 62 - When set, indicates the branch retired during a TSX transaction.
* Undefined on processors that do not support Intel TSX
* (CPUID.07H.00H:EBX.HLE[4] = 0 and CPUID.07H.00H:EBX.RTM[11] = 0).
*/
UINT64 InTsx : 1;
/**
* Bit 63 - Branch misprediction flag.
* When set, the target of the branch was mispredicted and/or the
* direction (taken/non-taken) was mispredicted.
* When clear, the branch target/direction was correctly predicted.
*/
UINT64 Mispred : 1;
};
UINT64 AsUInt;
} MSR_LBR_INFO, *PMSR_LBR_INFO;
//////////////////////////////////////////////////
// Structures //
//////////////////////////////////////////////////
/**
* @brief The structure to hold a single LBR entry (from and to addresses)
*
*/
typedef struct _LBR_BRANCH_ENTRY
{
ULONGLONG From;
ULONGLONG To;
} LBR_BRANCH_ENTRY, PLBR_BRANCH_ENTRY;
/**
* @brief The structure to hold the LBR stack for a single processor core, including the branch entries and the TOS index
*
*/
typedef struct _LBR_STACK_ENTRY
{
LBR_BRANCH_ENTRY BranchEntry[MAXIMUM_LBR_CAPACITY];
MSR_LBR_INFO LastBranchInfo[MAXIMUM_LBR_CAPACITY];
UINT8 Tos;
} LBR_STACK_ENTRY, PLBR_STACK_ENTRY;