Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ api/python/__pycache__
# TTD files
*.run
*.idx
*.bndb
*.bndb

__pycache__/
26 changes: 26 additions & 0 deletions api/debuggerapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,31 @@ namespace BinaryNinjaDebuggerAPI {
TTDCallEvent() : threadId(0), uniqueThreadId(0), functionAddress(0), returnAddress(0), returnValue(0), hasReturnValue(false) {}
};

struct TTDHeapEvent
{
std::string eventType; // Event type (always "Heap" for TTD.Heap objects)
std::string action; // Heap action: Alloc, ReAlloc, Free, Create, Protect, Lock, Unlock, Destroy
uint32_t threadId; // OS thread ID of thread that made the heap call
uint32_t uniqueThreadId; // Unique ID for the thread across the trace
uint64_t heap; // Handle for the Win32 heap
uint64_t address; // Address of the allocated object (if applicable)
uint64_t previousAddress; // Address before reallocation (for ReAlloc)
uint64_t size; // Size of allocated object (if applicable)
uint64_t baseAddress; // Base address of allocated object (if applicable)
uint64_t flags; // Heap API flags (meaning depends on API)
uint64_t result; // Result of heap API call (non-zero = success)
uint64_t reserveSize; // Amount of memory to reserve (for Create)
uint64_t commitSize; // Initial committed size (for Create)
uint64_t makeReadOnly; // Non-zero = make heap read-only (for Protect)
std::vector<std::string> parameters; // Raw parameters from the heap call
TTDPosition timeStart; // Position when heap operation started
TTDPosition timeEnd; // Position when heap operation ended

TTDHeapEvent() : threadId(0), uniqueThreadId(0), heap(0), address(0), previousAddress(0),
size(0), baseAddress(0), flags(0), result(0), reserveSize(0),
commitSize(0), makeReadOnly(0) {}
};

// TTD Event Types - bitfield flags for filtering events
enum TTDEventType
{
Expand Down Expand Up @@ -764,6 +789,7 @@ namespace BinaryNinjaDebuggerAPI {
std::vector<TTDCallEvent> GetTTDCallsForSymbols(const std::string& symbols, uint64_t startReturnAddress = 0, uint64_t endReturnAddress = 0);
std::vector<TTDEvent> GetTTDEvents(TTDEventType eventType);
std::vector<TTDEvent> GetAllTTDEvents();
std::vector<TTDHeapEvent> GetTTDHeapObjects();
TTDPosition GetCurrentTTDPosition();
bool SetTTDPosition(const TTDPosition& position);

Expand Down
88 changes: 73 additions & 15 deletions api/debuggercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1072,11 +1072,11 @@ std::vector<TTDCallEvent> DebuggerController::GetTTDCallsForSymbols(const std::s
std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
{
std::vector<TTDEvent> result;

size_t count = 0;
BNDebuggerTTDEvent* events = BNDebuggerGetTTDEvents(m_object,
BNDebuggerTTDEvent* events = BNDebuggerGetTTDEvents(m_object,
static_cast<BNDebuggerTTDEventType>(eventType), &count);

if (events && count > 0)
{
result.reserve(count);
Expand All @@ -1086,7 +1086,7 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
event.type = static_cast<TTDEventType>(events[i].type);
event.position.sequence = events[i].position.sequence;
event.position.step = events[i].position.step;

// Copy optional module details
if (events[i].module)
{
Expand All @@ -1098,7 +1098,7 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
module.timestamp = events[i].module->timestamp;
event.module = module;
}

// Copy optional thread details
if (events[i].thread)
{
Expand All @@ -1115,7 +1115,7 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
thread.activeTimeEnd.step = events[i].thread->activeTimeEnd.step;
event.thread = thread;
}

// Copy optional exception details
if (events[i].exception)
{
Expand All @@ -1129,23 +1129,23 @@ std::vector<TTDEvent> DebuggerController::GetTTDEvents(TTDEventType eventType)
exception.position.step = events[i].exception->position.step;
event.exception = exception;
}

result.push_back(event);
}
BNDebuggerFreeTTDEvents(events, count);
}

return result;
}


std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
{
std::vector<TTDEvent> result;

size_t count = 0;
BNDebuggerTTDEvent* events = BNDebuggerGetAllTTDEvents(m_object, &count);

if (events && count > 0)
{
result.reserve(count);
Expand All @@ -1155,7 +1155,7 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
event.type = static_cast<TTDEventType>(events[i].type);
event.position.sequence = events[i].position.sequence;
event.position.step = events[i].position.step;

// Copy optional module details
if (events[i].module)
{
Expand All @@ -1167,7 +1167,7 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
module.timestamp = events[i].module->timestamp;
event.module = module;
}

// Copy optional thread details
if (events[i].thread)
{
Expand All @@ -1184,7 +1184,7 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
thread.activeTimeEnd.step = events[i].thread->activeTimeEnd.step;
event.thread = thread;
}

// Copy optional exception details
if (events[i].exception)
{
Expand All @@ -1198,12 +1198,70 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
exception.position.step = events[i].exception->position.step;
event.exception = exception;
}

result.push_back(event);
}
BNDebuggerFreeTTDEvents(events, count);
}


return result;
}


std::vector<TTDHeapEvent> DebuggerController::GetTTDHeapObjects()
{
std::vector<TTDHeapEvent> result;

size_t count = 0;
BNDebuggerTTDHeapEvent* events = BNDebuggerGetTTDHeapObjects(m_object, &count);

if (events && count > 0)
{
result.reserve(count);
for (size_t i = 0; i < count; i++)
{
TTDHeapEvent event;
event.eventType = events[i].eventType ? std::string(events[i].eventType) : "";
event.action = events[i].action ? std::string(events[i].action) : "";
event.threadId = events[i].threadId;
event.uniqueThreadId = events[i].uniqueThreadId;
event.heap = events[i].heap;
event.address = events[i].address;
event.previousAddress = events[i].previousAddress;
event.size = events[i].size;
event.baseAddress = events[i].baseAddress;
event.flags = events[i].flags;
event.result = events[i].result;
event.reserveSize = events[i].reserveSize;
event.commitSize = events[i].commitSize;
event.makeReadOnly = events[i].makeReadOnly;
event.timeStart.sequence = events[i].timeStart.sequence;
event.timeStart.step = events[i].timeStart.step;
event.timeEnd.sequence = events[i].timeEnd.sequence;
event.timeEnd.step = events[i].timeEnd.step;

// Convert parameters array
if (events[i].parameters && events[i].parameterCount > 0)
{
event.parameters.reserve(events[i].parameterCount);
for (size_t j = 0; j < events[i].parameterCount; j++)
{
if (events[i].parameters[j])
{
event.parameters.push_back(std::string(events[i].parameters[j]));
}
else
{
event.parameters.push_back("");
}
}
}

result.push_back(event);
}
BNDebuggerFreeTTDHeapEvents(events, count);
}

return result;
}

Expand Down
26 changes: 25 additions & 1 deletion api/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,13 +395,35 @@ extern "C"
{
BNDebuggerTTDEventType type; // Type of event
BNDebuggerTTDPosition position; // Position where event occurred

// Optional child objects - existence depends on event type
BNDebuggerTTDModule* module; // For ModuleLoaded/ModuleUnloaded events (NULL if not present)
BNDebuggerTTDThread* thread; // For ThreadCreated/ThreadTerminated events (NULL if not present)
BNDebuggerTTDException* exception; // For Exception events (NULL if not present)
} BNDebuggerTTDEvent;

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


// This should really be a union, but gcc complains...
typedef struct BNDebuggerEventData
Expand Down Expand Up @@ -623,11 +645,13 @@ extern "C"
DEBUGGER_FFI_API BNDebuggerTTDEvent* BNDebuggerGetTTDEvents(BNDebuggerController* controller,
BNDebuggerTTDEventType eventType, size_t* count);
DEBUGGER_FFI_API BNDebuggerTTDEvent* BNDebuggerGetAllTTDEvents(BNDebuggerController* controller, size_t* count);
DEBUGGER_FFI_API BNDebuggerTTDHeapEvent* BNDebuggerGetTTDHeapObjects(BNDebuggerController* controller, size_t* count);
DEBUGGER_FFI_API BNDebuggerTTDPosition BNDebuggerGetCurrentTTDPosition(BNDebuggerController* controller);
DEBUGGER_FFI_API bool BNDebuggerSetTTDPosition(BNDebuggerController* controller, BNDebuggerTTDPosition position);
DEBUGGER_FFI_API void BNDebuggerFreeTTDMemoryEvents(BNDebuggerTTDMemoryEvent* events, size_t count);
DEBUGGER_FFI_API void BNDebuggerFreeTTDCallEvents(BNDebuggerTTDCallEvent* events, size_t count);
DEBUGGER_FFI_API void BNDebuggerFreeTTDEvents(BNDebuggerTTDEvent* events, size_t count);
DEBUGGER_FFI_API void BNDebuggerFreeTTDHeapEvents(BNDebuggerTTDHeapEvent* events, size_t count);

// TTD Code Coverage Analysis Functions
DEBUGGER_FFI_API bool BNDebuggerIsInstructionExecuted(BNDebuggerController* controller, uint64_t address);
Expand Down
Loading