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
7 changes: 7 additions & 0 deletions api/debuggerapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -843,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 Position History Navigation
bool TTDNavigateBack();
bool TTDNavigateForward();
bool CanTTDNavigateBack();
bool CanTTDNavigateForward();
void ClearTTDPositionHistory();

// TTD Bookmark Methods
std::vector<TTDBookmark> GetTTDBookmarks();
bool AddTTDBookmark(const TTDPosition& position, const std::string& note = "", uint64_t viewAddress = 0);
Expand Down
31 changes: 31 additions & 0 deletions api/debuggercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,37 @@ bool DebuggerController::SetTTDPosition(const TTDPosition& position)
return BNDebuggerSetTTDPosition(m_object, pos);
}


bool DebuggerController::TTDNavigateBack()
{
return BNDebuggerTTDNavigateBack(m_object);
}


bool DebuggerController::TTDNavigateForward()
{
return BNDebuggerTTDNavigateForward(m_object);
}


bool DebuggerController::CanTTDNavigateBack()
{
return BNDebuggerCanTTDNavigateBack(m_object);
}


bool DebuggerController::CanTTDNavigateForward()
{
return BNDebuggerCanTTDNavigateForward(m_object);
}


void DebuggerController::ClearTTDPositionHistory()
{
BNDebuggerClearTTDPositionHistory(m_object);
}


std::pair<bool, TTDMemoryEvent> DebuggerController::GetTTDNextMemoryAccess(uint64_t address, uint64_t size, TTDMemoryAccessType accessType)
{
BNDebuggerTTDMemoryEvent bnEvent = {};
Expand Down
7 changes: 7 additions & 0 deletions api/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,13 @@ extern "C"
DEBUGGER_FFI_API void BNDebuggerClearTTDBookmarks(BNDebuggerController* controller);
DEBUGGER_FFI_API void BNDebuggerFreeTTDBookmarks(BNDebuggerTTDBookmark* bookmarks, size_t count);

// TTD Position History Navigation
DEBUGGER_FFI_API bool BNDebuggerTTDNavigateBack(BNDebuggerController* controller);
DEBUGGER_FFI_API bool BNDebuggerTTDNavigateForward(BNDebuggerController* controller);
DEBUGGER_FFI_API bool BNDebuggerCanTTDNavigateBack(BNDebuggerController* controller);
DEBUGGER_FFI_API bool BNDebuggerCanTTDNavigateForward(BNDebuggerController* controller);
DEBUGGER_FFI_API void BNDebuggerClearTTDPositionHistory(BNDebuggerController* controller);

// 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
44 changes: 44 additions & 0 deletions api/python/debuggercontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -2682,6 +2682,50 @@ def clear_ttd_bookmarks(self):
"""
dbgcore.BNDebuggerClearTTDBookmarks(self.handle)

def ttd_navigate_back(self):
"""
Navigate to the previous TTD timestamp in the position history.

Returns:
bool: True if navigation succeeded, False if there is no previous position
"""
return dbgcore.BNDebuggerTTDNavigateBack(self.handle)

def ttd_navigate_forward(self):
"""
Navigate to the next TTD timestamp in the position history.

Returns:
bool: True if navigation succeeded, False if there is no next position
"""
return dbgcore.BNDebuggerTTDNavigateForward(self.handle)

@property
def can_ttd_navigate_back(self):
"""
Check if there is a previous TTD position to navigate to.

Returns:
bool: True if back navigation is possible
"""
return dbgcore.BNDebuggerCanTTDNavigateBack(self.handle)

@property
def can_ttd_navigate_forward(self):
"""
Check if there is a next TTD position to navigate to.

Returns:
bool: True if forward navigation is possible
"""
return dbgcore.BNDebuggerCanTTDNavigateForward(self.handle)

def clear_ttd_position_history(self):
"""
Clear the TTD position navigation history.
"""
dbgcore.BNDebuggerClearTTDPositionHistory(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
75 changes: 75 additions & 0 deletions core/debuggercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1872,6 +1872,7 @@ void DebuggerController::EventHandler(const DebuggerEvent& event)
m_state->MarkDirty();
m_inputFileLoaded = false;
m_initialBreakpointSeen = false;
ClearTTDPositionHistory();
RemoveDebuggerMemoryRegion();
if (m_oldAnalysisState != HoldState)
{
Expand Down Expand Up @@ -1901,6 +1902,7 @@ void DebuggerController::EventHandler(const DebuggerEvent& event)
UpdateStackVariables();
AddRegisterValuesToExpressionParser();
AddModuleValuesToExpressionParser();
RecordTTDPosition();
break;
}
case ActiveThreadChangedEvent:
Expand Down Expand Up @@ -3151,6 +3153,79 @@ std::vector<TTDEvent> DebuggerController::GetAllTTDEvents()
}


void DebuggerController::RecordTTDPosition()
{
if (!m_adapterSupportsTTD || !m_adapter || m_suppressTTDPositionRecording)
return;

TTDPosition position = m_adapter->GetCurrentTTDPosition();
if (position.sequence == 0 && position.step == 0)
return;

// If we're not at the end of the history (i.e., the user navigated back and then did something new),
// truncate the forward history
if (m_ttdPositionHistoryIndex >= 0
&& m_ttdPositionHistoryIndex < static_cast<int>(m_ttdPositionHistory.size()) - 1)
{
m_ttdPositionHistory.resize(m_ttdPositionHistoryIndex + 1);
}

// Don't record duplicates
if (!m_ttdPositionHistory.empty() && m_ttdPositionHistory.back() == position)
return;

m_ttdPositionHistory.push_back(position);
m_ttdPositionHistoryIndex = static_cast<int>(m_ttdPositionHistory.size()) - 1;
}


bool DebuggerController::TTDNavigateBack()
{
if (!CanTTDNavigateBack())
return false;

m_ttdPositionHistoryIndex--;
m_suppressTTDPositionRecording = true;
bool result = SetTTDPosition(m_ttdPositionHistory[m_ttdPositionHistoryIndex]);
m_suppressTTDPositionRecording = false;
return result;
}


bool DebuggerController::TTDNavigateForward()
{
if (!CanTTDNavigateForward())
return false;

m_ttdPositionHistoryIndex++;
m_suppressTTDPositionRecording = true;
bool result = SetTTDPosition(m_ttdPositionHistory[m_ttdPositionHistoryIndex]);
m_suppressTTDPositionRecording = false;
return result;
}


bool DebuggerController::CanTTDNavigateBack() const
{
return m_adapterSupportsTTD && m_ttdPositionHistoryIndex > 0;
}


bool DebuggerController::CanTTDNavigateForward() const
{
return m_adapterSupportsTTD
&& m_ttdPositionHistoryIndex >= 0
&& m_ttdPositionHistoryIndex < static_cast<int>(m_ttdPositionHistory.size()) - 1;
}


void DebuggerController::ClearTTDPositionHistory()
{
m_ttdPositionHistory.clear();
m_ttdPositionHistoryIndex = -1;
}


TTDPosition DebuggerController::GetCurrentTTDPosition()
{
TTDPosition position;
Expand Down
13 changes: 13 additions & 0 deletions core/debuggercontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ namespace BinaryNinjaDebugger {
std::unordered_map<uint64_t, uint32_t> m_executedInstructionCounts;
bool m_codeCoverageAnalysisRun = false;

// TTD Position History for back/forward navigation
std::vector<TTDPosition> m_ttdPositionHistory;
int m_ttdPositionHistoryIndex = -1;
bool m_suppressTTDPositionRecording = false;
void RecordTTDPosition();

public:
DebuggerController(BinaryViewRef data);
static DbgRef<DebuggerController> GetController(BinaryViewRef data);
Expand Down Expand Up @@ -405,6 +411,13 @@ namespace BinaryNinjaDebugger {
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 Position History Navigation
bool TTDNavigateBack();
bool TTDNavigateForward();
bool CanTTDNavigateBack() const;
bool CanTTDNavigateForward() const;
void ClearTTDPositionHistory();

// TTD Bookmark Methods
std::vector<TTDBookmark> GetTTDBookmarks();
bool AddTTDBookmark(const TTDPosition& position, const std::string& note = "", uint64_t viewAddress = 0);
Expand Down
26 changes: 26 additions & 0 deletions core/ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,32 @@ void BNDebuggerFreeTTDBookmarks(BNDebuggerTTDBookmark* bookmarks, size_t count)
}


bool BNDebuggerTTDNavigateBack(BNDebuggerController* controller)
{
return controller->object->TTDNavigateBack();
}

bool BNDebuggerTTDNavigateForward(BNDebuggerController* controller)
{
return controller->object->TTDNavigateForward();
}

bool BNDebuggerCanTTDNavigateBack(BNDebuggerController* controller)
{
return controller->object->CanTTDNavigateBack();
}

bool BNDebuggerCanTTDNavigateForward(BNDebuggerController* controller)
{
return controller->object->CanTTDNavigateForward();
}

void BNDebuggerClearTTDPositionHistory(BNDebuggerController* controller)
{
controller->object->ClearTTDPositionHistory();
}


bool BNDebuggerIsInstructionExecuted(BNDebuggerController* controller, uint64_t address)
{
return controller->object->IsInstructionExecuted(address);
Expand Down
56 changes: 50 additions & 6 deletions ui/controlswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,17 @@ DebugControlsWidget::DebugControlsWidget(QWidget* parent, const std::string name
performTimestampNavigation();
});
m_actionTimestampNavigation->setToolTip(getToolTip("Navigate to TTD Timestamp..."));

m_actionTTDNavigateBack = addAction(getColoredIcon(":/debugger/resume-reverse", cyan), "TTD Navigate Back", [this]() {
performTTDNavigateBack();
});
m_actionTTDNavigateBack->setToolTip(getToolTip("TTD Navigate Back"));

m_actionTTDNavigateForward = addAction(getColoredIcon(":/debugger/resume", cyan), "TTD Navigate Forward", [this]() {
performTTDNavigateForward();
});
m_actionTTDNavigateForward->setToolTip(getToolTip("TTD Navigate Forward"));

updateButtons();
}

Expand Down Expand Up @@ -617,6 +628,8 @@ void DebugControlsWidget::updateButtons()
DebugAdapterConnectionStatus connection = m_controller->GetConnectionStatus();
DebugAdapterTargetStatus status = m_controller->GetTargetStatus();

bool isTTD = m_controller->IsTTD();

if (connection == DebugAdapterNotConnectedStatus)
{
setStartingEnabled(true);
Expand All @@ -631,16 +644,19 @@ void DebugControlsWidget::updateButtons()
m_actionPause->setVisible(false);
m_actionResume->setVisible(false);
m_actionGoBack->setVisible(false);

m_actionTTDNavigateBack->setVisible(false);
m_actionTTDNavigateForward->setVisible(false);
}
else if (status == DebugAdapterRunningStatus)
{
setStartingEnabled(false);
setStoppingEnabled(true);
setSteppingEnabled(false);
setReverseSteppingEnabled(false);
m_actionStepIntoBack->setVisible(m_controller->IsTTD());
m_actionStepOverBack->setVisible(m_controller->IsTTD());
m_actionStepIntoBack->setVisible(isTTD);
m_actionStepOverBack->setVisible(isTTD);

m_actionPause->setEnabled(true);
m_actionResume->setEnabled(false);
m_actionGoBack->setEnabled(false);
Expand All @@ -649,21 +665,31 @@ void DebugControlsWidget::updateButtons()
m_actionPause->setVisible(true);
m_actionResume->setVisible(false);
m_actionGoBack->setVisible(false);

m_actionTTDNavigateBack->setVisible(isTTD);
m_actionTTDNavigateBack->setEnabled(false);
m_actionTTDNavigateForward->setVisible(isTTD);
m_actionTTDNavigateForward->setEnabled(false);
}
else // status == DebugAdapterPausedStatus
{
setStartingEnabled(false);
setStoppingEnabled(true);
setSteppingEnabled(true);
setReverseSteppingEnabled(m_controller->IsTTD());
setReverseSteppingEnabled(isTTD);
m_actionPause->setEnabled(false);
m_actionResume->setEnabled(true);
m_actionGoBack->setEnabled(m_controller->IsTTD());
m_actionGoBack->setEnabled(isTTD);

m_actionRun->setVisible(false);
m_actionPause->setVisible(false);
m_actionResume->setVisible(true);
m_actionGoBack->setVisible(m_controller->IsTTD());
m_actionGoBack->setVisible(isTTD);

m_actionTTDNavigateBack->setVisible(isTTD);
m_actionTTDNavigateBack->setEnabled(m_controller->CanTTDNavigateBack());
m_actionTTDNavigateForward->setVisible(isTTD);
m_actionTTDNavigateForward->setEnabled(m_controller->CanTTDNavigateForward());
}
}

Expand All @@ -679,3 +705,21 @@ void DebugControlsWidget::performTimestampNavigation()
auto* dialog = new TimestampNavigationDialog(this, m_controller);
dialog->show();
}


void DebugControlsWidget::performTTDNavigateBack()
{
if (!m_controller->CanTTDNavigateBack())
return;

m_controller->TTDNavigateBack();
}


void DebugControlsWidget::performTTDNavigateForward()
{
if (!m_controller->CanTTDNavigateForward())
return;

m_controller->TTDNavigateForward();
}
4 changes: 4 additions & 0 deletions ui/controlswidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class DebugControlsWidget : public QToolBar
QAction* m_actionSettings;
QAction* m_actionToggleBreakpoint;
QAction* m_actionTimestampNavigation;
QAction* m_actionTTDNavigateBack;
QAction* m_actionTTDNavigateForward;

bool canExec();
bool canConnect();
Expand Down Expand Up @@ -93,4 +95,6 @@ public Q_SLOTS:
void performSettings();
void toggleBreakpoint();
void performTimestampNavigation();
void performTTDNavigateBack();
void performTTDNavigateForward();
};
Loading