diff --git a/src/common/CutterSeekable.cpp b/src/common/CutterSeekable.cpp index f8b0805a6..821badb4e 100644 --- a/src/common/CutterSeekable.cpp +++ b/src/common/CutterSeekable.cpp @@ -66,6 +66,7 @@ void CutterSeekable::seekToReference(RVA offset) } RVA target; + // finds the xrefs for calls, lea, and jmp QList refs = Core()->getXRefs(offset, false, false); if (refs.length()) { diff --git a/src/common/DisassemblyPreview.cpp b/src/common/DisassemblyPreview.cpp index e80e6eaab..1488f947f 100644 --- a/src/common/DisassemblyPreview.cpp +++ b/src/common/DisassemblyPreview.cpp @@ -89,3 +89,13 @@ RVA DisassemblyPreview::readDisassemblyOffset(QTextCursor tc) return userData->line.offset; } + +RVA DisassemblyPreview::readDisassemblyArrow(QTextCursor tc) +{ + auto userData = getUserData(tc.block()); + if (!userData && userData->line.arrow != RVA_INVALID) { + return RVA_INVALID; + } + + return userData->line.arrow; +} diff --git a/src/common/DisassemblyPreview.h b/src/common/DisassemblyPreview.h index 81e67ee8d..6ddcbe129 100644 --- a/src/common/DisassemblyPreview.h +++ b/src/common/DisassemblyPreview.h @@ -41,5 +41,11 @@ bool showDisasPreview(QWidget *parent, const QPoint &pointOfEvent, const RVA off * @return The disassembly offset of the hovered asm text */ RVA readDisassemblyOffset(QTextCursor tc); + +/*! + * @brief Reads the arrow offset for the cursor position + * @return The jump address of the hovered asm text + */ +RVA readDisassemblyArrow(QTextCursor tc); } #endif diff --git a/src/widgets/DisassemblerGraphView.cpp b/src/widgets/DisassemblerGraphView.cpp index 69f87e5b0..4edc9a899 100644 --- a/src/widgets/DisassemblerGraphView.cpp +++ b/src/widgets/DisassemblerGraphView.cpp @@ -914,7 +914,41 @@ void DisassemblerGraphView::blockDoubleClicked(GraphView::GraphBlock &block, QMo QPoint pos) { Q_UNUSED(event); - seekable->seekToReference(getAddrForMouseEvent(block, &pos)); + RVA arrow = NULL; + RVA offset = getAddrForMouseEvent(block, &pos); + DisassemblyBlock *db = blockForAddress(offset); + + Instr lastInstruction = db->instrs.back(); + + // Handle the blocks without any paths + if (offset == lastInstruction.addr && db->false_path == RVA_INVALID + && db->true_path == RVA_INVALID) { + return; + } + + // Handle the blocks with just one path + if (offset == lastInstruction.addr && db->false_path == RVA_INVALID) { + seekable->seek(db->true_path); + return; + } + + // Handle blocks with two paths + if (offset == lastInstruction.addr && db->false_path != RVA_INVALID) { + // gets the offset for the next instruction + RVA nextOffset = lastInstruction.addr + lastInstruction.size; + // sets "arrow" to the path that isn't going to the next offset + if (db->false_path == nextOffset) { + arrow = db->true_path; + } else if (db->true_path == nextOffset) { + arrow = db->false_path; + } + + seekable->seek(arrow); + return; + } + + // Handle "call" instruction to functions + seekable->seekToReference(offset); } void DisassemblerGraphView::blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event, diff --git a/src/widgets/DisassemblyWidget.cpp b/src/widgets/DisassemblyWidget.cpp index 4c18b57f5..41bbada4f 100644 --- a/src/widgets/DisassemblyWidget.cpp +++ b/src/widgets/DisassemblyWidget.cpp @@ -613,6 +613,13 @@ void DisassemblyWidget::moveCursorRelative(bool up, bool page) void DisassemblyWidget::jumpToOffsetUnderCursor(const QTextCursor &cursor) { + // Handles "jmp" and conditonal jump instructions + RVA arrow = DisassemblyPreview::readDisassemblyArrow(cursor); + if (arrow != RVA_INVALID) { + seekable->seek(arrow); + } + + // Handles "call" and "lea" instructions RVA offset = DisassemblyPreview::readDisassemblyOffset(cursor); seekable->seekToReference(offset); } @@ -627,9 +634,8 @@ bool DisassemblyWidget::eventFilter(QObject *obj, QEvent *event) jumpToOffsetUnderCursor(cursor); return true; - } else if (Config()->getPreviewValue() - && event->type() == QEvent::ToolTip - && obj == mDisasTextEdit->viewport()) { + } else if (Config()->getPreviewValue() && event->type() == QEvent::ToolTip + && obj == mDisasTextEdit->viewport()) { QHelpEvent *helpEvent = static_cast(event); auto cursorForWord = mDisasTextEdit->cursorForPosition(helpEvent->pos());