HyperDbg Debugger
Loading...
Searching...
No Matches
lbrdump.cpp File Reference

!lbrdump command More...

#include "pch.h"

Functions

BOOLEAN HyperDbgLbrdumpSendRequest (HYPERTRACE_LBR_DUMP_PACKETS *LbrdumpRequest)
 Send LBR dump requests.
VOID CommandLbrdumpHelp ()
 help of the !lbrdump command
VOID CommandLbrdumpGetArchBranchTypet (UINT32 BrType, CHAR *BrTypeName)
 Get the branch type name based on the LBR branch type value (only applicable for architectural LBR).
VOID CommandLbrdumpPrint (HYPERTRACE_LBR_DUMP_PACKETS *LbrdumpRequest)
 Print collected LBR branches.
VOID CommandLbrdump (vector< CommandToken > CommandTokens, string Command)
 !lbrdump command handler

Variables

BOOLEAN g_IsSerialConnectedToRemoteDebuggee
 Shows if the debugger was connected to remote debuggee over (A remote guest).
BOOLEAN g_IsHyperTraceModuleLoaded
 shows whether the HyperTrace module is loaded or not

Detailed Description

!lbrdump command

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.19
Date
2026-05-03

Function Documentation

◆ CommandLbrdump()

VOID CommandLbrdump ( vector< CommandToken > CommandTokens,
string Command )

!lbrdump command handler

Parameters
CommandTokens
Command
Returns
VOID
241{
242 HYPERTRACE_LBR_DUMP_PACKETS LbrdumpRequest = {0};
243 UINT32 CoreId = 0;
244 BOOLEAN ContinueDumpingAllCores = TRUE;
245
246 if (CommandTokens.size() != 1 && CommandTokens.size() != 3)
247 {
248 ShowMessages("incorrect use of the '%s'\n\n",
249 GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
251 return;
252 }
253
254 //
255 // Check if the HyperTrace module is loaded, as it is required for LBR operations
256 //
258
259 if (CommandTokens.size() == 3)
260 {
261 if (CompareLowerCaseStrings(CommandTokens.at(1), "core"))
262 {
263 if (!ConvertTokenToUInt32(CommandTokens.at(2), &CoreId))
264 {
265 //
266 // Unknown parameter
267 //
268 ShowMessages("unknown parameter '%s'\n\n",
269 GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
271
272 return;
273 }
274 }
275 else
276 {
277 ShowMessages("incorrect use of the '%s'\n\n",
278 GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
280 return;
281 }
282 }
283 else
284 {
285 //
286 // If no core is specified, we can set the CoreId to a special value (e.g., 0xFFFFFFFF) to indicate that the dump should be performed for all cores
287 //
289 }
290
291 //
292 // If the CoreId is set to the special value for dumping all cores,
293 // we can set it to 0 to start dumping from the first core and rely on the NextCoreIsValid flag
294 // in the dump request structure to indicate whether there are more cores to be dumped or not in
295 // the driver response
296 //
297 if (CoreId == HYPERTRACE_LBR_DUMP_ALL_CORES)
298 {
299 LbrdumpRequest.CoreId = 0;
300 }
301 else
302 {
303 LbrdumpRequest.CoreId = CoreId;
304 }
305
306 while (ContinueDumpingAllCores)
307 {
308 //
309 // Send the LBR dump request
310 //
311 if (HyperDbgLbrdumpSendRequest(&LbrdumpRequest))
312 {
314 {
315 //
316 // Show entries of the LBR stack in the request structure which are filled by the driver in response to the dump request
317 //
318 CommandLbrdumpPrint(&LbrdumpRequest);
319
320 if (CoreId == HYPERTRACE_LBR_DUMP_ALL_CORES && LbrdumpRequest.NextCoreIsValid)
321 {
322 //
323 // If the NextCoreIsValid flag is set, it means there are more cores to be
324 // dumped in the case of dumping all cores, so we can update the CoreId
325 // in the dump request structure to the next core number for the next
326 // iteration of dumping
327 //
328 LbrdumpRequest.CoreId++;
329 }
330 else
331 {
332 //
333 // If the NextCoreIsValid flag is not set, it means there are no more
334 // cores to be dumped in the case of dumping all cores, so we can break the loop
335 //
336 ContinueDumpingAllCores = FALSE;
337 }
338 }
339 else
340 {
341 ShowErrorMessage(LbrdumpRequest.KernelStatus);
342 break;
343 }
344 }
345 else
346 {
347 ShowMessages("failed to send LBR dump request\n");
348 break;
349 }
350 }
351}
UCHAR BOOLEAN
Definition BasicTypes.h:35
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
unsigned int UINT32
Definition BasicTypes.h:54
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
struct _HYPERTRACE_LBR_DUMP_PACKETS HYPERTRACE_LBR_DUMP_PACKETS
The structure of HyperTrace LBR dump result packet in HyperDbg.
#define HYPERTRACE_LBR_DUMP_ALL_CORES
In the case of dumping all cores, this value is used to specify that all cores should be dumped.
Definition RequestStructures.h:1337
std::string GetCaseSensitiveStringFromCommandToken(CommandToken TargetToken)
Get case sensitive string from command token.
Definition common.cpp:467
BOOLEAN CompareLowerCaseStrings(CommandToken TargetToken, const CHAR *StringToCompare)
Compare lower case strings.
Definition common.cpp:503
BOOLEAN ConvertTokenToUInt32(CommandToken TargetToken, PUINT32 Result)
check and convert command token to a 32 bit unsigned integer
Definition common.cpp:546
BOOLEAN ShowErrorMessage(UINT32 Error)
shows the error message
Definition debugger.cpp:40
VOID CommandLbrdumpHelp()
help of the !lbrdump command
Definition lbrdump.cpp:82
VOID CommandLbrdumpPrint(HYPERTRACE_LBR_DUMP_PACKETS *LbrdumpRequest)
Print collected LBR branches.
Definition lbrdump.cpp:153
BOOLEAN HyperDbgLbrdumpSendRequest(HYPERTRACE_LBR_DUMP_PACKETS *LbrdumpRequest)
Send LBR dump requests.
Definition lbrdump.cpp:29
#define ASSERT_MESSAGE_HYPERTRACE_NOT_LOADED
Definition common.h:33
#define AssertShowMessageReturnStmt(expr1, expr2, message1, message2, rc)
Definition common.h:59
#define AssertReturn
Definition common.h:19
#define ASSERT_MESSAGE_DRIVER_NOT_LOADED
Definition common.h:27
HANDLE g_DeviceHandle
Holds the global handle of device which is used to send the request to the kernel by IOCTL,...
Definition globals.h:481
BOOLEAN g_IsHyperTraceModuleLoaded
shows whether the HyperTrace module is loaded or not
Definition lbrdump.cpp:19
BOOLEAN NextCoreIsValid
Definition RequestStructures.h:1325
UINT32 KernelStatus
Definition RequestStructures.h:1329
UINT32 CoreId
Definition RequestStructures.h:1324

◆ CommandLbrdumpGetArchBranchTypet()

VOID CommandLbrdumpGetArchBranchTypet ( UINT32 BrType,
CHAR * BrTypeName )

Get the branch type name based on the LBR branch type value (only applicable for architectural LBR).

THIS FUNCTION IS ALSO IMPLEMENTED IN THE USER MODE

Parameters
BrTypeThe raw branch type value from the LBR info MSR
BrTypeNameA character buffer to receive the branch type name string
Returns
VOID
106{
107 if (BrType == LBR_BR_TYPE_COND)
108 {
109 strncpy(BrTypeName, "COND ", LBR_BR_TYPE_NAME_MAX_LEN);
110 }
111 else if (BrType == LBR_BR_TYPE_JMP_INDIRECT)
112 {
113 strncpy(BrTypeName, "JMP Indirect ", LBR_BR_TYPE_NAME_MAX_LEN);
114 }
115 else if (BrType == LBR_BR_TYPE_JMP_DIRECT)
116 {
117 strncpy(BrTypeName, "JMP Direct ", LBR_BR_TYPE_NAME_MAX_LEN);
118 }
119 else if (BrType == LBR_BR_TYPE_CALL_INDIRECT)
120 {
121 strncpy(BrTypeName, "CALL Indirect", LBR_BR_TYPE_NAME_MAX_LEN);
122 }
123 else if (BrType == LBR_BR_TYPE_CALL_DIRECT)
124 {
125 strncpy(BrTypeName, "CALL Direct ", LBR_BR_TYPE_NAME_MAX_LEN);
126 }
127 else if (BrType == LBR_BR_TYPE_RET)
128 {
129 strncpy(BrTypeName, "RET ", LBR_BR_TYPE_NAME_MAX_LEN);
130 }
131 else if (BrType >= LBR_BR_TYPE_RESERVED_MIN && BrType <= LBR_BR_TYPE_RESERVED_MAX)
132 {
133 strncpy(BrTypeName, "Reserved ", LBR_BR_TYPE_NAME_MAX_LEN);
134 }
135 else if (BrType >= LBR_BR_TYPE_OTHER_MIN && BrType <= LBR_BR_TYPE_OTHER_MAX)
136 {
137 strncpy(BrTypeName, "Other Branch ", LBR_BR_TYPE_NAME_MAX_LEN);
138 }
139 else
140 {
141 strncpy(BrTypeName, "Unknown ", LBR_BR_TYPE_NAME_MAX_LEN);
142 }
143}
#define LBR_BR_TYPE_JMP_DIRECT
Definition LbrDefinitions.h:72
#define LBR_BR_TYPE_OTHER_MIN
Definition LbrDefinitions.h:78
#define LBR_BR_TYPE_CALL_DIRECT
Definition LbrDefinitions.h:74
#define LBR_BR_TYPE_OTHER_MAX
Definition LbrDefinitions.h:79
#define LBR_BR_TYPE_RESERVED_MIN
Definition LbrDefinitions.h:76
#define LBR_BR_TYPE_COND
Branch Type Encodings (Only on Architectural LBR, not available in Legacy LBR).
Definition LbrDefinitions.h:70
#define LBR_BR_TYPE_CALL_INDIRECT
Definition LbrDefinitions.h:73
#define LBR_BR_TYPE_RESERVED_MAX
Definition LbrDefinitions.h:77
#define LBR_BR_TYPE_JMP_INDIRECT
Definition LbrDefinitions.h:71
#define LBR_BR_TYPE_RET
Definition LbrDefinitions.h:75
#define LBR_BR_TYPE_NAME_MAX_LEN
Definition LbrDefinitions.h:81

◆ CommandLbrdumpHelp()

VOID CommandLbrdumpHelp ( )

help of the !lbrdump command

Returns
VOID
83{
84 ShowMessages("!lbrdump : dumps Last Branch Record (LBR).\n");
85 ShowMessages("for using this command, you should configure it using the '!lbr' command\n");
86
87 ShowMessages("syntax : \t!lbrdump [core CoreId (hex)]\n");
88
89 ShowMessages("\n");
90 ShowMessages("\t\te.g : !lbrdump\n");
91 ShowMessages("\t\te.g : !lbrdump core 1\n");
92}

◆ CommandLbrdumpPrint()

VOID CommandLbrdumpPrint ( HYPERTRACE_LBR_DUMP_PACKETS * LbrdumpRequest)

Print collected LBR branches.

Parameters
LbrdumpRequest
Returns
VOID
154{
155 ULONG CurrentIdx;
156 BOOLEAN IsCoreEmpty = TRUE;
157 CHAR BrTypeName[LBR_BR_TYPE_NAME_MAX_LEN] = {0};
158 UINT32 BrType = 0;
159
160 ShowMessages("LBR Chronological Trace on core: 0x%x\n\n", LbrdumpRequest->CoreId);
161
162 for (ULONG i = 1; i <= LbrdumpRequest->CurrentLbrCapacity; i++)
163 {
164 if (LbrdumpRequest->ArchBasedLBR)
165 {
166 //
167 // In ARCH LBR, there is not TOS index and everything is in order
168 //
169 CurrentIdx = i - 1;
170 }
171 else
172 {
173 CurrentIdx = (ULONG)(LbrdumpRequest->LbrStack.Tos + i) % (ULONG)LbrdumpRequest->CurrentLbrCapacity;
174 }
175
176 if (LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].From == 0)
177 {
178 continue;
179 }
180
181 IsCoreEmpty = FALSE;
182
183 if (LbrdumpRequest->ArchBasedLBR)
184 {
185 BrType = (UINT32)LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].BrType_OnlyArchLbr;
186
187 //
188 // Get the branch type name for better readability when printing
189 //
190 CommandLbrdumpGetArchBranchTypet(BrType, BrTypeName);
191
192 //
193 // Architectural LBR
194 //
195 ShowMessages("\t [%2u] Branch Mispredicted: %s, Branch type: %s, Cycle Count (Decimal): %04d (is valid? %s) - From: %016llx To: %016llx\n",
196 CurrentIdx,
197 LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].Mispred ? "true " : "false",
198 BrTypeName,
199 LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].CycleCount,
200 LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].CycCntValid_OnlyArchLbr ? "true " : "false",
201 LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].From,
202 LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].To);
203 }
204 else
205 {
206 //
207 // Legacy LBR
208 //
209 ShowMessages("\t [%2u] Branch Mispredicted: %s, Cycle Count (Decimal): %04d - From: %016llx To: %016llx\n",
210 CurrentIdx,
211 LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].Mispred ? "true " : "false",
212 LbrdumpRequest->LbrStack.LastBranchInfo[CurrentIdx].CycleCount,
213 LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].From,
214 LbrdumpRequest->LbrStack.BranchEntry[CurrentIdx].To);
215 }
216 }
217
218 if (IsCoreEmpty)
219 {
220 ShowMessages("\t no LBR entries found for this core\n"
221 "\t you can use the 'lbr_save();' function in the script engine\n"
222 "\t on the target core to save the LBR entries before dumping\n\n"
223 "\t ===========================================================\n\n");
224 }
225 else
226 {
227 ShowMessages("\n\t ===========================================================\n\n");
228 }
229}
char CHAR
Definition BasicTypes.h:33
unsigned long ULONG
Definition BasicTypes.h:31
VOID CommandLbrdumpGetArchBranchTypet(UINT32 BrType, CHAR *BrTypeName)
Get the branch type name based on the LBR branch type value (only applicable for architectural LBR).
Definition lbrdump.cpp:105
UINT8 CurrentLbrCapacity
Definition RequestStructures.h:1328
LBR_STACK_ENTRY LbrStack
Definition RequestStructures.h:1327
BOOLEAN ArchBasedLBR
Definition RequestStructures.h:1326
ULONGLONG From
Definition LbrDefinitions.h:156
ULONGLONG To
Definition LbrDefinitions.h:157
MSR_LBR_INFO LastBranchInfo[MAXIMUM_LBR_CAPACITY]
Definition LbrDefinitions.h:168
UINT8 Tos
Definition LbrDefinitions.h:169
LBR_BRANCH_ENTRY BranchEntry[MAXIMUM_LBR_CAPACITY]
Definition LbrDefinitions.h:167
UINT64 Mispred
Definition LbrDefinitions.h:141
UINT64 BrType_OnlyArchLbr
Definition LbrDefinitions.h:113
UINT64 CycCntValid_OnlyArchLbr
Definition LbrDefinitions.h:116
UINT64 CycleCount
Definition LbrDefinitions.h:95

◆ HyperDbgLbrdumpSendRequest()

BOOLEAN HyperDbgLbrdumpSendRequest ( HYPERTRACE_LBR_DUMP_PACKETS * LbrdumpRequest)

Send LBR dump requests.

Parameters
LbrdumpRequest
Returns
VOID
30{
31 BOOL Status;
32 ULONG ReturnedLength;
33
35 {
36 //
37 // Send the request over serial kernel debugger
38 //
40 {
41 return FALSE;
42 }
43 }
44 else
45 {
47
48 //
49 // Send IOCTL
50 //
51 Status = DeviceIoControl(
52 g_DeviceHandle, // Handle to device
53 IOCTL_PERFORM_HYPERTRACE_LBR_DUMP, // IO Control Code (IOCTL)
54 LbrdumpRequest, // Input Buffer to driver.
55 SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS, // Input buffer length
56 LbrdumpRequest, // Output Buffer from driver.
57 SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS, // Length of output buffer in bytes.
58 &ReturnedLength, // Bytes placed in buffer.
59 NULL // synchronous call
60 );
61
62 if (!Status)
63 {
64 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
65
66 return FALSE;
67 }
68 }
69
70 //
71 // Sending the request was successful
72 //
73 return TRUE;
74}
BOOLEAN g_IsSerialConnectedToRemoteDebuggee
Shows if the debugger was connected to remote debuggee over (A remote guest).
Definition globals.h:253
int BOOL
Definition BasicTypes.h:25
#define IOCTL_PERFORM_HYPERTRACE_LBR_DUMP
ioctl, to perform HyperTrace LBR dump
Definition Ioctls.h:414
#define SIZEOF_HYPERTRACE_LBR_DUMP_PACKETS
Debugger size of HYPERTRACE_LBR_DUMP_PACKETS.
Definition RequestStructures.h:1343
BOOLEAN KdSendHyperTraceLbrdumpPacketsToDebuggee(PHYPERTRACE_LBR_DUMP_PACKETS HyperTraceLbrdumpRequest, UINT32 ExpectedRequestSize)
Send requests for HyperTrace LBR dump packet to the debuggee.
Definition kd.cpp:1066
#define AssertReturnFalse
Definition common.h:21

Variable Documentation

◆ g_IsHyperTraceModuleLoaded

BOOLEAN g_IsHyperTraceModuleLoaded
extern

shows whether the HyperTrace module is loaded or not

◆ g_IsSerialConnectedToRemoteDebuggee

BOOLEAN g_IsSerialConnectedToRemoteDebuggee
extern

Shows if the debugger was connected to remote debuggee over (A remote guest).