-
Notifications
You must be signed in to change notification settings - Fork 33
Navigate double-clicked sidebar addresses by content type #1138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,8 @@ limitations under the License. | |
| */ | ||
|
|
||
| #include "debuggeruicommon.h" | ||
| #include "uicontext.h" | ||
| #include "viewframe.h" | ||
|
|
||
| using namespace BinaryNinja; | ||
|
|
||
|
|
@@ -69,3 +71,52 @@ bool ParseAddress(const QString& text, BinaryNinja::Ref<BinaryNinja::BinaryView> | |
|
|
||
| return false; | ||
| } | ||
|
|
||
|
|
||
| static bool AddressIsInFunction(Ref<BinaryView> data, uint64_t address) | ||
| { | ||
| return data && !data->GetAnalysisFunctionsContainingAddress(address).empty(); | ||
| } | ||
|
|
||
|
|
||
| void NavigateToAddress(QWidget* widget, Ref<BinaryView> data, uint64_t target) | ||
| { | ||
| UIContext* context = UIContext::contextForWidget(widget); | ||
| if (!context) | ||
| return; | ||
|
|
||
| ViewFrame* frame = context->getCurrentViewFrame(); | ||
| if (!frame) | ||
| return; | ||
|
|
||
| View* view = frame->getCurrentViewInterface(); | ||
|
|
||
| // Decide same-pane vs other-pane by whether the target and the current view are the | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems really fragile. Are we not able to know what the view is here? Also confused because some views show both code and data. So, wouldn't this code potentially navigate the wrong pane in that situation? For example, if you have Hex View open and Linear View open and you click an address inside of a function, Hex View can show "code", so I think this would navigate the Hex View and not the Linear View? |
||
| // same kind of thing (both code, or both data). Matching types navigate in place; | ||
| // crossing between code and data opens the target in the other pane so what the user | ||
| // is looking at stays visible. | ||
| bool targetInFunction = AddressIsInFunction(data, target); | ||
| bool currentInFunction = view && AddressIsInFunction(data, view->getCurrentOffset()); | ||
|
|
||
| if (view && currentInFunction == targetInFunction) | ||
| { | ||
| frame->navigate(data, target, true, true); | ||
| return; | ||
| } | ||
|
|
||
| // Different types: show the target in the other pane. If there is no other pane to use | ||
| // (or no view), fall back to navigating the current pane. | ||
| if (!view || !view->navigateOnOtherPane(target)) | ||
| frame->navigate(data, target, true, true); | ||
| } | ||
|
|
||
|
|
||
| void NavigateToAddressInCurrentPane(QWidget* widget, Ref<BinaryView> data, uint64_t target) | ||
| { | ||
| UIContext* context = UIContext::contextForWidget(widget); | ||
| if (!context) | ||
| return; | ||
|
|
||
| if (ViewFrame* frame = context->getCurrentViewFrame()) | ||
| frame->navigate(data, target, true, true); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ limitations under the License. | |
| */ | ||
|
|
||
| #include "threadframes.h" | ||
| #include "debuggeruicommon.h" | ||
| #include <algorithm> | ||
|
|
||
| FrameItem::~FrameItem() | ||
|
|
@@ -735,6 +736,16 @@ ThreadFramesWidget::ThreadFramesWidget(QWidget* parent, ViewFrame* frame, Binary | |
| m_menu.addAction(actionName, "Options", MENU_ORDER_NORMAL); | ||
| m_actionHandler.bindAction(actionName, UIAction([this]() { copyAllFrames(); })); | ||
|
|
||
| // Force navigation into the currently focused pane (double-click instead picks the | ||
| // pane by content type; see NavigateToAddress). | ||
| actionName = QString::fromStdString("Navigate in Current Pane"); | ||
| UIAction::registerAction(actionName); | ||
| m_menu.addAction(actionName, "Options", MENU_ORDER_FIRST); | ||
| m_actionHandler.bindAction(actionName, UIAction([this]() { navigateInCurrentPane(); }, [this]() { | ||
| uint64_t addr = 0; | ||
| return navigationAddressForSelection(addr); | ||
| })); | ||
|
|
||
| // TODO: set as active thread action? | ||
|
|
||
| connect(this, &QTreeView::doubleClicked, this, &ThreadFramesWidget::onDoubleClicked); | ||
|
|
@@ -849,30 +860,50 @@ void ThreadFramesWidget::onDoubleClicked() | |
| } | ||
|
|
||
| uint64_t addrToJump = 0; | ||
| switch (column) | ||
| if (!navigationAddressForSelection(addrToJump)) | ||
| return; | ||
|
|
||
| // Navigate to the target, opening it in the other pane when it is a different kind | ||
| // of thing (code vs data) than the current pane shows (see NavigateToAddress, #1134). | ||
| if (m_debugger->GetData()) | ||
| NavigateToAddress(this, m_debugger->GetData(), addrToJump); | ||
| } | ||
|
|
||
|
|
||
| bool ThreadFramesWidget::navigationAddressForSelection(uint64_t& addr) | ||
| { | ||
| QModelIndexList sel = selectionModel()->selectedIndexes(); | ||
| if (sel.empty()) | ||
| return false; | ||
|
|
||
| const QModelIndex& index = sel[0]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You re-read the index here, but I thought |
||
| FrameItem* frameItem = static_cast<FrameItem*>(index.internalPointer()); | ||
| if (!frameItem || !frameItem->isFrame()) | ||
| return false; | ||
|
|
||
| switch (index.column()) | ||
| { | ||
| case ThreadFrameModel::FunctionColumn: | ||
| case ThreadFrameModel::PcColumn: | ||
| addrToJump = frameItem->framePc(); | ||
| break; | ||
| addr = frameItem->framePc(); | ||
| return true; | ||
| case ThreadFrameModel::SpColumn: | ||
| addrToJump = frameItem->sp(); | ||
| break; | ||
| addr = frameItem->sp(); | ||
| return true; | ||
| case ThreadFrameModel::FpColumn: | ||
| addrToJump = frameItem->fp(); | ||
| break; | ||
| addr = frameItem->fp(); | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| UIContext* context = UIContext::contextForWidget(this); | ||
| if (!context) | ||
| return; | ||
|
|
||
| ViewFrame* frame = context->getCurrentViewFrame(); | ||
| if (!frame) | ||
| return; | ||
|
|
||
| if (m_debugger->GetData()) | ||
| frame->navigate(m_debugger->GetData(), addrToJump, true, true); | ||
| void ThreadFramesWidget::navigateInCurrentPane() | ||
| { | ||
| uint64_t addr = 0; | ||
| if (navigationAddressForSelection(addr) && m_debugger->GetData()) | ||
| NavigateToAddressInCurrentPane(this, m_debugger->GetData(), addr); | ||
| } | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is above every single call to
NavigateToAddress. This is not a good idea. Not only do we already have this content within the function itself, but we also have it in the.hfile. If the implementation ever changes, we have to update that information in two places plus every single location that calls it. That's way too much.Just leave the header and function comments and remove all of the extra comments above every call to it.