Skip to content
Merged
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
19 changes: 19 additions & 0 deletions api/debuggerapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,18 @@ namespace BinaryNinjaDebuggerAPI {
};


struct TTDBookmark
{
TTDPosition position;
uint64_t viewAddress;
std::string note;

TTDBookmark() : viewAddress(0) {}
TTDBookmark(const TTDPosition& pos, const std::string& n = "", uint64_t addr = 0)
: position(pos), viewAddress(addr), note(n) {}
};


typedef BNDebugAdapterConnectionStatus DebugAdapterConnectionStatus;
typedef BNDebugAdapterTargetStatus DebugAdapterTargetStatus;

Expand Down Expand Up @@ -831,6 +843,13 @@ namespace BinaryNinjaDebuggerAPI {
std::pair<bool, TTDMemoryEvent> GetTTDNextMemoryAccess(uint64_t address, uint64_t size, TTDMemoryAccessType accessType);
std::pair<bool, TTDMemoryEvent> GetTTDPrevMemoryAccess(uint64_t address, uint64_t size, TTDMemoryAccessType accessType);

// TTD Bookmark Methods
std::vector<TTDBookmark> GetTTDBookmarks();
bool AddTTDBookmark(const TTDPosition& position, const std::string& note = "", uint64_t viewAddress = 0);
bool RemoveTTDBookmark(const TTDPosition& position);
bool UpdateTTDBookmark(const TTDPosition& position, const std::string& note, uint64_t viewAddress);
void ClearTTDBookmarks();

// TTD Code Coverage Analysis Methods
bool IsInstructionExecuted(uint64_t address);
bool RunCodeCoverageAnalysis(uint64_t startAddress, uint64_t endAddress, TTDPosition startTime, TTDPosition endTime);
Expand Down
45 changes: 45 additions & 0 deletions api/debuggercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,51 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
}


std::vector<TTDBookmark> DebuggerController::GetTTDBookmarks()
{
std::vector<TTDBookmark> result;
size_t count = 0;
BNDebuggerTTDBookmark* bookmarks = BNDebuggerGetTTDBookmarks(m_object, &count);
if (!bookmarks)
return result;

for (size_t i = 0; i < count; ++i)
{
TTDBookmark bm;
bm.position = TTDPosition(bookmarks[i].position.sequence, bookmarks[i].position.step);
bm.viewAddress = bookmarks[i].viewAddress;
bm.note = bookmarks[i].note ? std::string(bookmarks[i].note) : "";
result.push_back(bm);
}

BNDebuggerFreeTTDBookmarks(bookmarks, count);
return result;
}

bool DebuggerController::AddTTDBookmark(const TTDPosition& position, const std::string& note, uint64_t viewAddress)
{
BNDebuggerTTDPosition pos = {position.sequence, position.step};
return BNDebuggerAddTTDBookmark(m_object, pos, note.c_str(), viewAddress);
}

bool DebuggerController::RemoveTTDBookmark(const TTDPosition& position)
{
BNDebuggerTTDPosition pos = {position.sequence, position.step};
return BNDebuggerRemoveTTDBookmark(m_object, pos);
}

bool DebuggerController::UpdateTTDBookmark(const TTDPosition& position, const std::string& note, uint64_t viewAddress)
{
BNDebuggerTTDPosition pos = {position.sequence, position.step};
return BNDebuggerUpdateTTDBookmark(m_object, pos, note.c_str(), viewAddress);
}

void DebuggerController::ClearTTDBookmarks()
{
BNDebuggerClearTTDBookmarks(m_object);
}


bool DebuggerController::IsInstructionExecuted(uint64_t address)
{
return BNDebuggerIsInstructionExecuted(m_object, address);
Expand Down
17 changes: 17 additions & 0 deletions api/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ extern "C"
ThreadStateChangedEvent,

ForceMemoryCacheUpdateEvent,

TTDBookmarkChangedEvent,
} BNDebuggerEventType;


Expand Down Expand Up @@ -701,6 +703,21 @@ extern "C"
DEBUGGER_FFI_API void BNDebuggerFreeTTDCallEvents(BNDebuggerTTDCallEvent* events, size_t count);
DEBUGGER_FFI_API void BNDebuggerFreeTTDEvents(BNDebuggerTTDEvent* events, size_t count);

// TTD Bookmark structures and functions
typedef struct BNDebuggerTTDBookmark
{
BNDebuggerTTDPosition position;
uint64_t viewAddress;
char* note;
} BNDebuggerTTDBookmark;

DEBUGGER_FFI_API BNDebuggerTTDBookmark* BNDebuggerGetTTDBookmarks(BNDebuggerController* controller, size_t* count);
DEBUGGER_FFI_API bool BNDebuggerAddTTDBookmark(BNDebuggerController* controller, BNDebuggerTTDPosition position, const char* note, uint64_t viewAddress);
DEBUGGER_FFI_API bool BNDebuggerRemoveTTDBookmark(BNDebuggerController* controller, BNDebuggerTTDPosition position);
DEBUGGER_FFI_API bool BNDebuggerUpdateTTDBookmark(BNDebuggerController* controller, BNDebuggerTTDPosition position, const char* note, uint64_t viewAddress);
DEBUGGER_FFI_API void BNDebuggerClearTTDBookmarks(BNDebuggerController* controller);
DEBUGGER_FFI_API void BNDebuggerFreeTTDBookmarks(BNDebuggerTTDBookmark* bookmarks, size_t count);

// TTD Code Coverage Analysis Functions
DEBUGGER_FFI_API bool BNDebuggerIsInstructionExecuted(BNDebuggerController* controller, uint64_t address);
DEBUGGER_FFI_API bool BNDebuggerRunCodeCoverageAnalysisRange(BNDebuggerController* controller, uint64_t startAddress, uint64_t endAddress, BNDebuggerTTDPosition startTime, BNDebuggerTTDPosition endTime);
Expand Down
129 changes: 129 additions & 0 deletions api/python/debuggercontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,38 @@ def from_string(cls, timestamp_str):
return cls(parts[0], parts[1])


class TTDBookmark:
"""
TTDBookmark represents a saved position in a TTD trace with an optional note and view address.

* ``position``: the TTD position (TTDPosition object)
* ``view_address``: the address the user was viewing when the bookmark was created
* ``note``: an optional note describing the bookmark
"""

def __init__(self, position: TTDPosition, note: str = "", view_address: int = 0):
self.position = position
self.note = note
self.view_address = view_address

def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return self.position == other.position

def __ne__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return not (self == other)

def __hash__(self):
return hash(self.position)

def __repr__(self):
note_str = f" ({self.note})" if self.note else ""
return f"<TTDBookmark: {self.position}{note_str}>"


class TTDMemoryEvent:
"""
TTDMemoryEvent represents a memory access event in a TTD trace. It has the following fields:
Expand Down Expand Up @@ -2553,6 +2585,103 @@ def navigate_to_timestamp(self, timestamp_str):
binaryninja.log_error(f"Invalid timestamp format: {e}")
return False

@property
def ttd_bookmarks(self):
"""
Get all TTD bookmarks.

:return: list of TTDBookmark objects
:rtype: list[TTDBookmark]
"""
count = ctypes.c_size_t()
bookmarks = dbgcore.BNDebuggerGetTTDBookmarks(self.handle, ctypes.byref(count))

result = []
if not bookmarks or count.value == 0:
return result

for i in range(count.value):
bm = bookmarks[i]
position = TTDPosition(bm.position.sequence, bm.position.step)
note = bm.note.decode('utf-8') if bm.note else ""
result.append(TTDBookmark(position, note, bm.viewAddress))

dbgcore.BNDebuggerFreeTTDBookmarks(bookmarks, count.value)
return result

def add_ttd_bookmark(self, position, note="", view_address=0):
"""
Add a TTD bookmark. If a bookmark with the same position already exists, it is updated.

:param position: TTDPosition object or string in format "sequence:step"
:param note: optional note for the bookmark
:param view_address: optional view address to navigate to when the bookmark is activated
:return: True if the bookmark was added/updated successfully
:rtype: bool
"""
if isinstance(position, str):
position = TTDPosition.from_string(position)
elif not isinstance(position, TTDPosition):
raise TypeError("Position must be TTDPosition object or string")

pos = dbgcore.BNDebuggerTTDPosition()
pos.sequence = position.sequence
pos.step = position.step

if isinstance(note, str):
note = note.encode('utf-8')

return dbgcore.BNDebuggerAddTTDBookmark(self.handle, pos, note, view_address)

def remove_ttd_bookmark(self, position):
"""
Remove a TTD bookmark by position.

:param position: TTDPosition object or string in format "sequence:step"
:return: True if the bookmark was found and removed
:rtype: bool
"""
if isinstance(position, str):
position = TTDPosition.from_string(position)
elif not isinstance(position, TTDPosition):
raise TypeError("Position must be TTDPosition object or string")

pos = dbgcore.BNDebuggerTTDPosition()
pos.sequence = position.sequence
pos.step = position.step

return dbgcore.BNDebuggerRemoveTTDBookmark(self.handle, pos)

def update_ttd_bookmark(self, position, note="", view_address=0):
"""
Update an existing TTD bookmark's note and view address.

:param position: TTDPosition object or string in format "sequence:step"
:param note: new note for the bookmark
:param view_address: new view address for the bookmark
:return: True if the bookmark was found and updated
:rtype: bool
"""
if isinstance(position, str):
position = TTDPosition.from_string(position)
elif not isinstance(position, TTDPosition):
raise TypeError("Position must be TTDPosition object or string")

pos = dbgcore.BNDebuggerTTDPosition()
pos.sequence = position.sequence
pos.step = position.step

if isinstance(note, str):
note = note.encode('utf-8')

return dbgcore.BNDebuggerUpdateTTDBookmark(self.handle, pos, note, view_address)

def clear_ttd_bookmarks(self):
"""
Remove all TTD bookmarks.
"""
dbgcore.BNDebuggerClearTTDBookmarks(self.handle)

def get_ttd_next_memory_access(self, address: int, size: int, access_type = DebuggerTTDMemoryAccessType.DebuggerTTDMemoryRead):
"""
Get the next memory access to a specific address from the current TTD position.
Expand Down
12 changes: 12 additions & 0 deletions core/debuggercommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,18 @@ namespace BinaryNinjaDebugger {
}
};

// TTD Bookmark - a saved position in the trace with optional metadata
struct TTDBookmark
{
TTDPosition position;
uint64_t viewAddress;
std::string note;

TTDBookmark() : viewAddress(0) {}
TTDBookmark(const TTDPosition& pos, const std::string& n = "", uint64_t addr = 0)
: position(pos), viewAddress(addr), note(n) {}
};

// TTD Memory Access Event - complete set of fields from Microsoft documentation
struct TTDMemoryEvent
{
Expand Down
Loading