Display jumping fix useless decompilation (#2351)

* save scroll position and reset to that if the newly decompiled function is the same as the previous one

* instructionChanged signal replaced completely by breakpointsChanged in toggle/add breakpoint functions.

* removed addbreakpoint(QString) and toggleBreakpoint(QString)
This commit is contained in:
NIRMAL MANOJ C 2020-08-02 15:21:56 +05:30
parent 37fc01478f
commit b42a19e995
7 changed files with 55 additions and 37 deletions

View File

@ -2068,23 +2068,7 @@ void CutterCore::setDebugPlugin(QString plugin)
void CutterCore::toggleBreakpoint(RVA addr) void CutterCore::toggleBreakpoint(RVA addr)
{ {
cmdRaw(QString("dbs %1").arg(addr)); cmdRaw(QString("dbs %1").arg(addr));
emit instructionChanged(addr); emit breakpointsChanged(addr);
emit breakpointsChanged();
}
void CutterCore::toggleBreakpoint(QString addr)
{
cmdRaw("dbs " + addr);
emit instructionChanged(addr.toULongLong());
emit breakpointsChanged();
}
void CutterCore::addBreakpoint(QString addr)
{
cmdRaw("db " + addr);
emit instructionChanged(addr.toULongLong());
emit breakpointsChanged();
} }
void CutterCore::addBreakpoint(const BreakpointDescription &config) void CutterCore::addBreakpoint(const BreakpointDescription &config)
@ -2138,8 +2122,7 @@ void CutterCore::addBreakpoint(const BreakpointDescription &config)
if (!config.command.isEmpty()) { if (!config.command.isEmpty()) {
updateOwnedCharPtr(breakpoint->data, config.command); updateOwnedCharPtr(breakpoint->data, config.command);
} }
emit instructionChanged(breakpoint->addr); emit breakpointsChanged(breakpoint->addr);
emit breakpointsChanged();
} }
void CutterCore::updateBreakpoint(int index, const BreakpointDescription &config) void CutterCore::updateBreakpoint(int index, const BreakpointDescription &config)
@ -2157,8 +2140,7 @@ void CutterCore::updateBreakpoint(int index, const BreakpointDescription &config
void CutterCore::delBreakpoint(RVA addr) void CutterCore::delBreakpoint(RVA addr)
{ {
cmdRaw("db- " + RAddressString(addr)); cmdRaw("db- " + RAddressString(addr));
emit instructionChanged(addr); emit breakpointsChanged(addr);
emit breakpointsChanged();
} }
void CutterCore::delAllBreakpoints() void CutterCore::delAllBreakpoints()
@ -2170,15 +2152,13 @@ void CutterCore::delAllBreakpoints()
void CutterCore::enableBreakpoint(RVA addr) void CutterCore::enableBreakpoint(RVA addr)
{ {
cmdRaw("dbe " + RAddressString(addr)); cmdRaw("dbe " + RAddressString(addr));
emit instructionChanged(addr); emit breakpointsChanged(addr);
emit breakpointsChanged();
} }
void CutterCore::disableBreakpoint(RVA addr) void CutterCore::disableBreakpoint(RVA addr)
{ {
cmdRaw("dbd " + RAddressString(addr)); cmdRaw("dbd " + RAddressString(addr));
emit instructionChanged(addr); emit breakpointsChanged(addr);
emit breakpointsChanged();
} }
void CutterCore::setBreakpointTrace(int index, bool enabled) void CutterCore::setBreakpointTrace(int index, bool enabled)

View File

@ -391,11 +391,9 @@ public:
void stepOverDebug(); void stepOverDebug();
void stepOutDebug(); void stepOutDebug();
void addBreakpoint(QString addr);
void addBreakpoint(const BreakpointDescription &config); void addBreakpoint(const BreakpointDescription &config);
void updateBreakpoint(int index, const BreakpointDescription &config); void updateBreakpoint(int index, const BreakpointDescription &config);
void toggleBreakpoint(RVA addr); void toggleBreakpoint(RVA addr);
void toggleBreakpoint(QString addr);
void delBreakpoint(RVA addr); void delBreakpoint(RVA addr);
void delAllBreakpoints(); void delAllBreakpoints();
void enableBreakpoint(RVA addr); void enableBreakpoint(RVA addr);
@ -643,7 +641,7 @@ signals:
void commentsChanged(); void commentsChanged();
void registersChanged(); void registersChanged();
void instructionChanged(RVA offset); void instructionChanged(RVA offset);
void breakpointsChanged(); void breakpointsChanged(RVA offset);
void refreshCodeViews(); void refreshCodeViews();
void stackChanged(); void stackChanged();
/** /**

View File

@ -15,11 +15,18 @@
#include <QClipboard> #include <QClipboard>
#include <QObject> #include <QObject>
#include <QTextBlockUserData> #include <QTextBlockUserData>
#include <QScrollBar>
#include <QAbstractSlider>
DecompilerWidget::DecompilerWidget(MainWindow *main) : DecompilerWidget::DecompilerWidget(MainWindow *main) :
MemoryDockWidget(MemoryWidgetType::Decompiler, main), MemoryDockWidget(MemoryWidgetType::Decompiler, main),
mCtxMenu(new DecompilerContextMenu(this, main)), mCtxMenu(new DecompilerContextMenu(this, main)),
ui(new Ui::DecompilerWidget), ui(new Ui::DecompilerWidget),
decompilerWasBusy(false),
scrollerHorizontal(0),
scrollerVertical(0),
previousFunctionAddr(RVA_INVALID),
decompiledFunctionAddr(RVA_INVALID),
code(Decompiler::makeWarning(tr("Choose an offset and refresh to get decompiled code")), code(Decompiler::makeWarning(tr("Choose an offset and refresh to get decompiled code")),
&r_annotated_code_free) &r_annotated_code_free)
{ {
@ -38,9 +45,6 @@ DecompilerWidget::DecompilerWidget(MainWindow *main) :
connect(Core(), &CutterCore::registersChanged, this, &DecompilerWidget::highlightPC); connect(Core(), &CutterCore::registersChanged, this, &DecompilerWidget::highlightPC);
connect(mCtxMenu, &DecompilerContextMenu::copy, this, &DecompilerWidget::copy); connect(mCtxMenu, &DecompilerContextMenu::copy, this, &DecompilerWidget::copy);
decompiledFunctionAddr = RVA_INVALID;
decompilerWasBusy = false;
connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() { connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() {
doRefresh(); doRefresh();
}); });
@ -88,7 +92,7 @@ DecompilerWidget::DecompilerWidget(MainWindow *main) :
connect(ui->textEdit, &QWidget::customContextMenuRequested, connect(ui->textEdit, &QWidget::customContextMenuRequested,
this, &DecompilerWidget::showDisasContextMenu); this, &DecompilerWidget::showDisasContextMenu);
connect(Core(), &CutterCore::breakpointsChanged, this, &DecompilerWidget::setInfoForBreakpoints); connect(Core(), &CutterCore::breakpointsChanged, this, &DecompilerWidget::updateBreakpoints);
addActions(mCtxMenu->actions()); addActions(mCtxMenu->actions());
ui->progressLabel->setVisible(false); ui->progressLabel->setVisible(false);
@ -182,6 +186,19 @@ static size_t positionForOffset(RAnnotatedCode &codeDecompiled, ut64 offset)
return closestPos; return closestPos;
} }
void DecompilerWidget::updateBreakpoints()
{
setInfoForBreakpoints();
QTextCursor cursor = ui->textEdit->textCursor();
cursor.select(QTextCursor::Document);
cursor.setCharFormat(QTextCharFormat());
cursor.setBlockFormat(QTextBlockFormat());
ui->textEdit->setExtraSelections({});
highlightPC();
highlightBreakpoints();
updateSelection();
}
void DecompilerWidget::setInfoForBreakpoints() void DecompilerWidget::setInfoForBreakpoints()
{ {
if (mCtxMenu->getIsTogglingBreakpoints()) if (mCtxMenu->getIsTogglingBreakpoints())
@ -250,6 +267,7 @@ void DecompilerWidget::doRefresh(RVA addr)
// Clear all selections since we just refreshed // Clear all selections since we just refreshed
ui->textEdit->setExtraSelections({}); ui->textEdit->setExtraSelections({});
previousFunctionAddr = decompiledFunctionAddr;
decompiledFunctionAddr = Core()->getFunctionStart(addr); decompiledFunctionAddr = Core()->getFunctionStart(addr);
dec->decompileAt(addr); dec->decompileAt(addr);
if (dec->isRunning()) { if (dec->isRunning()) {
@ -280,6 +298,13 @@ QTextCursor DecompilerWidget::getCursorForAddress(RVA addr)
void DecompilerWidget::decompilationFinished(RAnnotatedCode *codeDecompiled) void DecompilerWidget::decompilationFinished(RAnnotatedCode *codeDecompiled)
{ {
bool isDisplayReset = false;
if (previousFunctionAddr == decompiledFunctionAddr) {
scrollerHorizontal = ui->textEdit->horizontalScrollBar()->sliderPosition();
scrollerVertical = ui->textEdit->verticalScrollBar()->sliderPosition();
isDisplayReset = true;
}
ui->progressLabel->setVisible(false); ui->progressLabel->setVisible(false);
ui->decompilerComboBox->setEnabled(decompilerSelectionEnabled); ui->decompilerComboBox->setEnabled(decompilerSelectionEnabled);
updateRefreshButton(); updateRefreshButton();
@ -303,6 +328,11 @@ void DecompilerWidget::decompilationFinished(RAnnotatedCode *codeDecompiled)
decompilerWasBusy = false; decompilerWasBusy = false;
doAutoRefresh(); doAutoRefresh();
} }
if (isDisplayReset) {
ui->textEdit->horizontalScrollBar()->setSliderPosition(scrollerHorizontal);
ui->textEdit->verticalScrollBar()->setSliderPosition(scrollerVertical);
}
} }
void DecompilerWidget::setAnnotationsAtCursor(size_t pos) void DecompilerWidget::setAnnotationsAtCursor(size_t pos)

View File

@ -56,6 +56,9 @@ private:
*/ */
bool decompilerWasBusy; bool decompilerWasBusy;
int scrollerHorizontal;
int scrollerVertical;
RVA previousFunctionAddr;
RVA decompiledFunctionAddr; RVA decompiledFunctionAddr;
std::unique_ptr<RAnnotatedCode, void (*)(RAnnotatedCode *)> code; std::unique_ptr<RAnnotatedCode, void (*)(RAnnotatedCode *)> code;
bool seekFromCursor = false; bool seekFromCursor = false;
@ -113,6 +116,7 @@ private:
*/ */
void gatherBreakpointInfo(RAnnotatedCode &codeDecompiled, size_t startPos, size_t endPos); void gatherBreakpointInfo(RAnnotatedCode &codeDecompiled, size_t startPos, size_t endPos);
void updateBreakpoints();
void setInfoForBreakpoints(); void setInfoForBreakpoints();
void setAnnotationsAtCursor(size_t pos); void setAnnotationsAtCursor(size_t pos);

View File

@ -47,6 +47,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent, CutterSeekable *se
connect(Core(), SIGNAL(flagsChanged()), this, SLOT(refreshView())); connect(Core(), SIGNAL(flagsChanged()), this, SLOT(refreshView()));
connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshView())); connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshView()));
connect(Core(), SIGNAL(instructionChanged(RVA)), this, SLOT(refreshView())); connect(Core(), SIGNAL(instructionChanged(RVA)), this, SLOT(refreshView()));
connect(Core(), &CutterCore::breakpointsChanged, this, &DisassemblerGraphView::refreshView);
connect(Core(), SIGNAL(functionsChanged()), this, SLOT(refreshView())); connect(Core(), SIGNAL(functionsChanged()), this, SLOT(refreshView()));
connect(Core(), SIGNAL(asmOptionsChanged()), this, SLOT(refreshView())); connect(Core(), SIGNAL(asmOptionsChanged()), this, SLOT(refreshView()));
connect(Core(), SIGNAL(refreshCodeViews()), this, SLOT(refreshView())); connect(Core(), SIGNAL(refreshCodeViews()), this, SLOT(refreshView()));

View File

@ -151,11 +151,8 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main)
connect(Core(), &CutterCore::functionRenamed, this, [this]() {refreshDisasm();}); connect(Core(), &CutterCore::functionRenamed, this, [this]() {refreshDisasm();});
connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshDisasm())); connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshDisasm()));
connect(Core(), SIGNAL(asmOptionsChanged()), this, SLOT(refreshDisasm())); connect(Core(), SIGNAL(asmOptionsChanged()), this, SLOT(refreshDisasm()));
connect(Core(), &CutterCore::instructionChanged, this, [this](RVA offset) { connect(Core(), &CutterCore::instructionChanged, this, &DisassemblyWidget::refreshIfInRange);
if (offset >= topOffset && offset <= bottomOffset) { connect(Core(), &CutterCore::breakpointsChanged, this, &DisassemblyWidget::refreshIfInRange);
refreshDisasm();
}
});
connect(Core(), SIGNAL(refreshCodeViews()), this, SLOT(refreshDisasm())); connect(Core(), SIGNAL(refreshCodeViews()), this, SLOT(refreshDisasm()));
connect(Config(), &Configuration::fontsUpdated, this, &DisassemblyWidget::fontsUpdatedSlot); connect(Config(), &Configuration::fontsUpdated, this, &DisassemblyWidget::fontsUpdatedSlot);
@ -249,6 +246,13 @@ QList<DisassemblyLine> DisassemblyWidget::getLines()
return lines; return lines;
} }
void DisassemblyWidget::refreshIfInRange(RVA offset)
{
if (offset >= topOffset && offset <= bottomOffset) {
refreshDisasm();
}
}
void DisassemblyWidget::refreshDisasm(RVA offset) void DisassemblyWidget::refreshDisasm(RVA offset)
{ {
if(!disasmRefresh->attemptRefresh(offset == RVA_INVALID ? nullptr : new RVA(offset))) { if(!disasmRefresh->attemptRefresh(offset == RVA_INVALID ? nullptr : new RVA(offset))) {

View File

@ -40,6 +40,7 @@ public slots:
protected slots: protected slots:
void on_seekChanged(RVA offset); void on_seekChanged(RVA offset);
void refreshIfInRange(RVA offset);
void refreshDisasm(RVA offset = RVA_INVALID); void refreshDisasm(RVA offset = RVA_INVALID);
bool updateMaxLines(); bool updateMaxLines();