Skip to content

Commit 74e26b6

Browse files
Copilotxusheng6
andcommitted
Add TTD Heap UI widget and Python API integration
Co-authored-by: xusheng6 <94503187+xusheng6@users.noreply.github.com>
1 parent 6a4f0e8 commit 74e26b6

File tree

9 files changed

+1175
-34
lines changed

9 files changed

+1175
-34
lines changed

api/debuggercontroller.cpp

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,11 +1072,11 @@ std::vector<TTDCallEvent> DebuggerController::GetTTDCallsForSymbols(const std::s
10721072
std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
10731073
{
10741074
std::vector<TTDEvent> result;
1075-
1075+
10761076
size_t count = 0;
1077-
BNDebuggerTTDEvent* events = BNDebuggerGetTTDEvents(m_object,
1077+
BNDebuggerTTDEvent* events = BNDebuggerGetTTDEvents(m_object,
10781078
static_cast<BNDebuggerTTDEventType>(eventType), &count);
1079-
1079+
10801080
if (events && count > 0)
10811081
{
10821082
result.reserve(count);
@@ -1086,7 +1086,7 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
10861086
event.type = static_cast<TTDEventType>(events[i].type);
10871087
event.position.sequence = events[i].position.sequence;
10881088
event.position.step = events[i].position.step;
1089-
1089+
10901090
// Copy optional module details
10911091
if (events[i].module)
10921092
{
@@ -1098,7 +1098,7 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
10981098
module.timestamp = events[i].module->timestamp;
10991099
event.module = module;
11001100
}
1101-
1101+
11021102
// Copy optional thread details
11031103
if (events[i].thread)
11041104
{
@@ -1115,7 +1115,7 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
11151115
thread.activeTimeEnd.step = events[i].thread->activeTimeEnd.step;
11161116
event.thread = thread;
11171117
}
1118-
1118+
11191119
// Copy optional exception details
11201120
if (events[i].exception)
11211121
{
@@ -1129,23 +1129,23 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
11291129
exception.position.step = events[i].exception->position.step;
11301130
event.exception = exception;
11311131
}
1132-
1132+
11331133
result.push_back(event);
11341134
}
11351135
BNDebuggerFreeTTDEvents(events, count);
11361136
}
1137-
1137+
11381138
return result;
11391139
}
11401140

11411141

11421142
std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
11431143
{
11441144
std::vector<TTDEvent> result;
1145-
1145+
11461146
size_t count = 0;
11471147
BNDebuggerTTDEvent* events = BNDebuggerGetAllTTDEvents(m_object, &count);
1148-
1148+
11491149
if (events && count > 0)
11501150
{
11511151
result.reserve(count);
@@ -1155,7 +1155,7 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
11551155
event.type = static_cast<TTDEventType>(events[i].type);
11561156
event.position.sequence = events[i].position.sequence;
11571157
event.position.step = events[i].position.step;
1158-
1158+
11591159
// Copy optional module details
11601160
if (events[i].module)
11611161
{
@@ -1167,7 +1167,7 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
11671167
module.timestamp = events[i].module->timestamp;
11681168
event.module = module;
11691169
}
1170-
1170+
11711171
// Copy optional thread details
11721172
if (events[i].thread)
11731173
{
@@ -1184,7 +1184,7 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
11841184
thread.activeTimeEnd.step = events[i].thread->activeTimeEnd.step;
11851185
event.thread = thread;
11861186
}
1187-
1187+
11881188
// Copy optional exception details
11891189
if (events[i].exception)
11901190
{
@@ -1198,12 +1198,70 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
11981198
exception.position.step = events[i].exception->position.step;
11991199
event.exception = exception;
12001200
}
1201-
1201+
12021202
result.push_back(event);
12031203
}
12041204
BNDebuggerFreeTTDEvents(events, count);
12051205
}
1206-
1206+
1207+
return result;
1208+
}
1209+
1210+
1211+
std::vector<TTDHeapEvent> DebuggerController::GetTTDHeapObjects()
1212+
{
1213+
std::vector<TTDHeapEvent> result;
1214+
1215+
size_t count = 0;
1216+
BNDebuggerTTDHeapEvent* events = BNDebuggerGetTTDHeapObjects(m_object, &count);
1217+
1218+
if (events && count > 0)
1219+
{
1220+
result.reserve(count);
1221+
for (size_t i = 0; i < count; i++)
1222+
{
1223+
TTDHeapEvent event;
1224+
event.eventType = events[i].eventType ? std::string(events[i].eventType) : "";
1225+
event.action = events[i].action ? std::string(events[i].action) : "";
1226+
event.threadId = events[i].threadId;
1227+
event.uniqueThreadId = events[i].uniqueThreadId;
1228+
event.heap = events[i].heap;
1229+
event.address = events[i].address;
1230+
event.previousAddress = events[i].previousAddress;
1231+
event.size = events[i].size;
1232+
event.baseAddress = events[i].baseAddress;
1233+
event.flags = events[i].flags;
1234+
event.result = events[i].result;
1235+
event.reserveSize = events[i].reserveSize;
1236+
event.commitSize = events[i].commitSize;
1237+
event.makeReadOnly = events[i].makeReadOnly;
1238+
event.timeStart.sequence = events[i].timeStart.sequence;
1239+
event.timeStart.step = events[i].timeStart.step;
1240+
event.timeEnd.sequence = events[i].timeEnd.sequence;
1241+
event.timeEnd.step = events[i].timeEnd.step;
1242+
1243+
// Convert parameters array
1244+
if (events[i].parameters && events[i].parameterCount > 0)
1245+
{
1246+
event.parameters.reserve(events[i].parameterCount);
1247+
for (size_t j = 0; j < events[i].parameterCount; j++)
1248+
{
1249+
if (events[i].parameters[j])
1250+
{
1251+
event.parameters.push_back(std::string(events[i].parameters[j]));
1252+
}
1253+
else
1254+
{
1255+
event.parameters.push_back("");
1256+
}
1257+
}
1258+
}
1259+
1260+
result.push_back(event);
1261+
}
1262+
BNDebuggerFreeTTDHeapEvents(events, count);
1263+
}
1264+
12071265
return result;
12081266
}
12091267

api/ffi.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,13 +395,35 @@ extern "C"
395395
{
396396
BNDebuggerTTDEventType type; // Type of event
397397
BNDebuggerTTDPosition position; // Position where event occurred
398-
398+
399399
// Optional child objects - existence depends on event type
400400
BNDebuggerTTDModule* module; // For ModuleLoaded/ModuleUnloaded events (NULL if not present)
401401
BNDebuggerTTDThread* thread; // For ThreadCreated/ThreadTerminated events (NULL if not present)
402402
BNDebuggerTTDException* exception; // For Exception events (NULL if not present)
403403
} BNDebuggerTTDEvent;
404404

405+
typedef struct BNDebuggerTTDHeapEvent
406+
{
407+
char* eventType; // Event type (always "Heap" for TTD.Heap objects)
408+
char* action; // Heap action: Alloc, ReAlloc, Free, Create, Protect, Lock, Unlock, Destroy
409+
uint32_t threadId; // OS thread ID of thread that made the heap call
410+
uint32_t uniqueThreadId; // Unique ID for the thread across the trace
411+
uint64_t heap; // Handle for the Win32 heap
412+
uint64_t address; // Address of the allocated object (if applicable)
413+
uint64_t previousAddress; // Address before reallocation (for ReAlloc)
414+
uint64_t size; // Size of allocated object (if applicable)
415+
uint64_t baseAddress; // Base address of allocated object (if applicable)
416+
uint64_t flags; // Heap API flags (meaning depends on API)
417+
uint64_t result; // Result of heap API call (non-zero = success)
418+
uint64_t reserveSize; // Amount of memory to reserve (for Create)
419+
uint64_t commitSize; // Initial committed size (for Create)
420+
uint64_t makeReadOnly; // Non-zero = make heap read-only (for Protect)
421+
char** parameters; // Array containing raw parameters from the heap call
422+
size_t parameterCount; // Number of parameters
423+
BNDebuggerTTDPosition timeStart; // Position when heap operation started
424+
BNDebuggerTTDPosition timeEnd; // Position when heap operation ended
425+
} BNDebuggerTTDHeapEvent;
426+
405427

406428
// This should really be a union, but gcc complains...
407429
typedef struct BNDebuggerEventData
@@ -623,11 +645,13 @@ extern "C"
623645
DEBUGGER_FFI_API BNDebuggerTTDEvent* BNDebuggerGetTTDEvents(BNDebuggerController* controller,
624646
BNDebuggerTTDEventType eventType, size_t* count);
625647
DEBUGGER_FFI_API BNDebuggerTTDEvent* BNDebuggerGetAllTTDEvents(BNDebuggerController* controller, size_t* count);
648+
DEBUGGER_FFI_API BNDebuggerTTDHeapEvent* BNDebuggerGetTTDHeapObjects(BNDebuggerController* controller, size_t* count);
626649
DEBUGGER_FFI_API BNDebuggerTTDPosition BNDebuggerGetCurrentTTDPosition(BNDebuggerController* controller);
627650
DEBUGGER_FFI_API bool BNDebuggerSetTTDPosition(BNDebuggerController* controller, BNDebuggerTTDPosition position);
628651
DEBUGGER_FFI_API void BNDebuggerFreeTTDMemoryEvents(BNDebuggerTTDMemoryEvent* events, size_t count);
629652
DEBUGGER_FFI_API void BNDebuggerFreeTTDCallEvents(BNDebuggerTTDCallEvent* events, size_t count);
630653
DEBUGGER_FFI_API void BNDebuggerFreeTTDEvents(BNDebuggerTTDEvent* events, size_t count);
654+
DEBUGGER_FFI_API void BNDebuggerFreeTTDHeapEvents(BNDebuggerTTDHeapEvent* events, size_t count);
631655

632656
// TTD Code Coverage Analysis Functions
633657
DEBUGGER_FFI_API bool BNDebuggerIsInstructionExecuted(BNDebuggerController* controller, uint64_t address);

0 commit comments

Comments
 (0)