Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
75 changes: 75 additions & 0 deletions api/debuggerapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ limitations under the License.
#include "binaryninjaapi.h"
#include "ffi.h"
#include "../vendor/intx/intx.hpp"
#include <optional>

using namespace BinaryNinja;

Expand Down Expand Up @@ -517,6 +518,78 @@ namespace BinaryNinjaDebuggerAPI {
TTDCallEvent() : threadId(0), uniqueThreadId(0), functionAddress(0), returnAddress(0), returnValue(0), hasReturnValue(false) {}
};

// TTD Event Types - bitfield flags for filtering events
enum TTDEventType
{
TTDEventNone = 0,
TTDEventThreadCreated = 1,
TTDEventThreadTerminated = 2,
TTDEventModuleLoaded = 4,
TTDEventModuleUnloaded = 8,
TTDEventException = 16,
TTDEventAll = TTDEventThreadCreated | TTDEventThreadTerminated | TTDEventModuleLoaded | TTDEventModuleUnloaded | TTDEventException
};

// TTD Module - information about modules that were loaded/unloaded during trace
struct TTDModule
{
std::string name; // Name and path of the module
uint64_t address; // Address where the module was loaded
uint64_t size; // Size of the module in bytes
uint32_t checksum; // Checksum of the module
uint32_t timestamp; // Timestamp of the module

TTDModule() : address(0), size(0), checksum(0), timestamp(0) {}
};

// TTD Thread - information about threads and their lifetime during trace
struct TTDThread
{
uint32_t uniqueId; // Unique ID for the thread across the trace
uint32_t id; // TID of the thread
TTDPosition lifetimeStart; // Lifetime start position
TTDPosition lifetimeEnd; // Lifetime end position
TTDPosition activeTimeStart; // Active time start position
TTDPosition activeTimeEnd; // Active time end position

TTDThread() : uniqueId(0), id(0) {}
};

// TTD Exception Types
enum TTDExceptionType
{
TTDExceptionSoftware,
TTDExceptionHardware
};

// TTD Exception - information about exceptions that occurred during trace
struct TTDException
{
TTDExceptionType type; // Type of exception (Software/Hardware)
uint64_t programCounter; // Instruction where exception was thrown
uint32_t code; // Exception code
uint32_t flags; // Exception flags
uint64_t recordAddress; // Where in memory the exception record is found
TTDPosition position; // Position where exception occurred

TTDException() : type(TTDExceptionSoftware), programCounter(0), code(0), flags(0), recordAddress(0) {}
};

// TTD Event - represents important events that happened during trace
struct TTDEvent
{
TTDEventType type; // Type of event
TTDPosition position; // Position where event occurred

// Optional child objects - existence depends on event type
std::optional<TTDModule> module; // For ModuleLoaded/ModuleUnloaded events
std::optional<TTDThread> thread; // For ThreadCreated/ThreadTerminated events
std::optional<TTDException> exception; // For Exception events

TTDEvent() : type(TTDEventThreadCreated) {}
TTDEvent(TTDEventType eventType) : type(eventType) {}
};


typedef BNDebugAdapterConnectionStatus DebugAdapterConnectionStatus;
typedef BNDebugAdapterTargetStatus DebugAdapterTargetStatus;
Expand Down Expand Up @@ -687,6 +760,8 @@ namespace BinaryNinjaDebuggerAPI {
// TTD Memory Analysis Methods
std::vector<TTDMemoryEvent> GetTTDMemoryAccessForAddress(uint64_t address, uint64_t size, TTDMemoryAccessType accessType = TTDMemoryRead);
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();
TTDPosition GetCurrentTTDPosition();
bool SetTTDPosition(const TTDPosition& position);

Expand Down
139 changes: 139 additions & 0 deletions api/debuggercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,145 @@ 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,
static_cast<BNDebuggerTTDEventType>(eventType), &count);

if (events && count > 0)
{
result.reserve(count);
for (size_t i = 0; i < count; i++)
{
TTDEvent event;
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)
{
TTDModule module;
module.name = events[i].module->name ? std::string(events[i].module->name) : "";
module.address = events[i].module->address;
module.size = events[i].module->size;
module.checksum = events[i].module->checksum;
module.timestamp = events[i].module->timestamp;
event.module = module;
}

// Copy optional thread details
if (events[i].thread)
{
TTDThread thread;
thread.uniqueId = events[i].thread->uniqueId;
thread.id = events[i].thread->id;
thread.lifetimeStart.sequence = events[i].thread->lifetimeStart.sequence;
thread.lifetimeStart.step = events[i].thread->lifetimeStart.step;
thread.lifetimeEnd.sequence = events[i].thread->lifetimeEnd.sequence;
thread.lifetimeEnd.step = events[i].thread->lifetimeEnd.step;
thread.activeTimeStart.sequence = events[i].thread->activeTimeStart.sequence;
thread.activeTimeStart.step = events[i].thread->activeTimeStart.step;
thread.activeTimeEnd.sequence = events[i].thread->activeTimeEnd.sequence;
thread.activeTimeEnd.step = events[i].thread->activeTimeEnd.step;
event.thread = thread;
}

// Copy optional exception details
if (events[i].exception)
{
TTDException exception;
exception.type = static_cast<TTDExceptionType>(events[i].exception->type);
exception.programCounter = events[i].exception->programCounter;
exception.code = events[i].exception->code;
exception.flags = events[i].exception->flags;
exception.recordAddress = events[i].exception->recordAddress;
exception.position.sequence = events[i].exception->position.sequence;
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);
for (size_t i = 0; i < count; i++)
{
TTDEvent event;
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)
{
TTDModule module;
module.name = events[i].module->name ? std::string(events[i].module->name) : "";
module.address = events[i].module->address;
module.size = events[i].module->size;
module.checksum = events[i].module->checksum;
module.timestamp = events[i].module->timestamp;
event.module = module;
}

// Copy optional thread details
if (events[i].thread)
{
TTDThread thread;
thread.uniqueId = events[i].thread->uniqueId;
thread.id = events[i].thread->id;
thread.lifetimeStart.sequence = events[i].thread->lifetimeStart.sequence;
thread.lifetimeStart.step = events[i].thread->lifetimeStart.step;
thread.lifetimeEnd.sequence = events[i].thread->lifetimeEnd.sequence;
thread.lifetimeEnd.step = events[i].thread->lifetimeEnd.step;
thread.activeTimeStart.sequence = events[i].thread->activeTimeStart.sequence;
thread.activeTimeStart.step = events[i].thread->activeTimeStart.step;
thread.activeTimeEnd.sequence = events[i].thread->activeTimeEnd.sequence;
thread.activeTimeEnd.step = events[i].thread->activeTimeEnd.step;
event.thread = thread;
}

// Copy optional exception details
if (events[i].exception)
{
TTDException exception;
exception.type = static_cast<TTDExceptionType>(events[i].exception->type);
exception.programCounter = events[i].exception->programCounter;
exception.code = events[i].exception->code;
exception.flags = events[i].exception->flags;
exception.recordAddress = events[i].exception->recordAddress;
exception.position.sequence = events[i].exception->position.sequence;
exception.position.step = events[i].exception->position.step;
event.exception = exception;
}

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

return result;
}


bool DebuggerController::IsInstructionExecuted(uint64_t address)
{
return BNDebuggerIsInstructionExecuted(m_object, address);
Expand Down
67 changes: 67 additions & 0 deletions api/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,69 @@ extern "C"
BNDebuggerTTDPosition timeEnd; // Position when call ended
} BNDebuggerTTDCallEvent;

// TTD Event Types - bitfield flags for filtering events
typedef enum BNDebuggerTTDEventType
{
BNDebuggerTTDEventNone = 0,
BNDebuggerTTDEventThreadCreated = 1,
BNDebuggerTTDEventThreadTerminated = 2,
BNDebuggerTTDEventModuleLoaded = 4,
BNDebuggerTTDEventModuleUnloaded = 8,
BNDebuggerTTDEventException = 16,
BNDebuggerTTDEventAll = BNDebuggerTTDEventThreadCreated | BNDebuggerTTDEventThreadTerminated | BNDebuggerTTDEventModuleLoaded | BNDebuggerTTDEventModuleUnloaded | BNDebuggerTTDEventException
} BNDebuggerTTDEventType;

// TTD Module
typedef struct BNDebuggerTTDModule
{
char* name; // Name and path of the module
uint64_t address; // Address where the module was loaded
uint64_t size; // Size of the module in bytes
uint32_t checksum; // Checksum of the module
uint32_t timestamp; // Timestamp of the module
} BNDebuggerTTDModule;

// TTD Thread
typedef struct BNDebuggerTTDThread
{
uint32_t uniqueId; // Unique ID for the thread across the trace
uint32_t id; // TID of the thread
BNDebuggerTTDPosition lifetimeStart; // Lifetime start position
BNDebuggerTTDPosition lifetimeEnd; // Lifetime end position
BNDebuggerTTDPosition activeTimeStart; // Active time start position
BNDebuggerTTDPosition activeTimeEnd; // Active time end position
} BNDebuggerTTDThread;

// TTD Exception Types
typedef enum BNDebuggerTTDExceptionType
{
BNDebuggerTTDExceptionSoftware,
BNDebuggerTTDExceptionHardware
} BNDebuggerTTDExceptionType;

// TTD Exception
typedef struct BNDebuggerTTDException
{
BNDebuggerTTDExceptionType type; // Type of exception (Software/Hardware)
uint64_t programCounter; // Instruction where exception was thrown
uint32_t code; // Exception code
uint32_t flags; // Exception flags
uint64_t recordAddress; // Where in memory the exception record is found
BNDebuggerTTDPosition position; // Position where exception occurred
} BNDebuggerTTDException;

// TTD Event
typedef struct BNDebuggerTTDEvent
{
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;


// This should really be a union, but gcc complains...
typedef struct BNDebuggerEventData
Expand Down Expand Up @@ -555,10 +618,14 @@ extern "C"
uint64_t address, uint64_t size, BNDebuggerTTDMemoryAccessType accessType, size_t* count);
DEBUGGER_FFI_API BNDebuggerTTDCallEvent* BNDebuggerGetTTDCallsForSymbols(BNDebuggerController* controller,
const char* symbols, uint64_t startReturnAddress, uint64_t endReturnAddress, size_t* count);
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 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);

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