diff --git a/src/cutter.cpp b/src/cutter.cpp index 212ecb76..99c38892 100644 --- a/src/cutter.cpp +++ b/src/cutter.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "utils/Configuration.h" #include "cutter.h" #include "sdb.h" @@ -1331,3 +1332,22 @@ void CutterCore::setNotes(const QString ¬es) this->notes = notes; emit notesChanged(this->notes); } + +QList CutterCore::disassembleLines(RVA offset, int lines) +{ + QJsonArray array = cmdj(QString("pdJ ") + QString::number(lines) + QString(" @ ") + QString::number(offset)).array(); + QList r; + + for (QJsonValue value : array) + { + QJsonObject object = value.toObject(); + + DisassemblyLine line; + line.offset = object["offset"].toVariant().toULongLong(); + line.text = object["text"].toString(); + + r << line; + } + + return r; +} diff --git a/src/cutter.h b/src/cutter.h index 86e063c3..2f825e8f 100644 --- a/src/cutter.h +++ b/src/cutter.h @@ -168,6 +168,12 @@ struct RBinPluginDescription QString type; }; +struct DisassemblyLine +{ + RVA offset; + QString text; +}; + Q_DECLARE_METATYPE(FunctionDescription) Q_DECLARE_METATYPE(ImportDescription) Q_DECLARE_METATYPE(ExportDescription) @@ -202,6 +208,9 @@ public: QString cmd(const QString &str); QJsonDocument cmdj(const QString &str); QStringList cmdList(const QString &str) { auto l = cmd(str).split("\n"); l.removeAll(""); return l; } + + QList disassembleLines(RVA offset, int lines); + void renameFunction(QString prev_name, QString new_name); void delFunction(RVA addr); void renameFlag(QString old_name, QString new_name); diff --git a/src/widgets/DisassemblyWidget.cpp b/src/widgets/DisassemblyWidget.cpp index ba600104..ba40530a 100644 --- a/src/widgets/DisassemblyWidget.cpp +++ b/src/widgets/DisassemblyWidget.cpp @@ -11,6 +11,19 @@ #include #include #include +#include + + +class DisassemblyTextBlockUserData: public QTextBlockUserData +{ +public: + DisassemblyLine line; + + explicit DisassemblyTextBlockUserData(const DisassemblyLine &line) + { + this->line = line; + } +}; DisassemblyWidget::DisassemblyWidget(QWidget *parent) @@ -126,25 +139,6 @@ QWidget* DisassemblyWidget::getTextWidget() return mDisasTextEdit; } -QString DisassemblyWidget::readDisasm(const QString &cmd, bool stripLastNewline) -{ - TempConfig tempConfig; - tempConfig.set("scr.html", true) - .set("scr.color", true); - - QString disas = Core()->cmd(cmd); - - if (stripLastNewline) - { - // ugly hack to remove trailing newline - static const auto trimBrRegExp = QRegularExpression("
$"); - disas = disas.remove(trimBrRegExp); - } - - return disas.trimmed(); -} - - void DisassemblyWidget::refreshDisasm(RVA offset) { if (offset != RVA_INVALID) @@ -167,12 +161,26 @@ void DisassemblyWidget::refreshDisasm(RVA offset) int horizontalScrollValue = mDisasTextEdit->horizontalScrollBar()->value(); mDisasTextEdit->setLockScroll(true); // avoid flicker - - QString disas = readDisasm("pd " + QString::number(maxLines) + "@" + QString::number(topOffset), true); + + QList disassemblyLines; + { + TempConfig tempConfig; + tempConfig.set("scr.html", true) + .set("scr.color", true); + disassemblyLines = Core()->disassembleLines(topOffset, maxLines); + } connectCursorPositionChanged(true); - mDisasTextEdit->document()->setHtml(disas); + mDisasTextEdit->document()->clear(); + QTextCursor cursor(mDisasTextEdit->document()); + for (DisassemblyLine line : disassemblyLines) + { + cursor.insertHtml(line.text); + auto a = new DisassemblyTextBlockUserData(line); + cursor.block().setUserData(a); + cursor.insertBlock(); + } // get bottomOffset from last visible line. // because pd N may return more than N lines, move maxLines lines down from the top @@ -307,32 +315,14 @@ RVA DisassemblyWidget::readCurrentDisassemblyOffset() RVA DisassemblyWidget::readDisassemblyOffset(QTextCursor tc) { - // TODO: do this in a different way without parsing the disassembly text - - static const QRegularExpression offsetRegExp("^0x[0-9A-Fa-f]*"); - - while (true) + QTextBlockUserData *userData = tc.block().userData(); + if (!userData) { - tc.select(QTextCursor::LineUnderCursor); - - QString line = tc.selectedText(); - - auto match = offsetRegExp.match(line); - if (match.hasMatch()) - { - return match.captured(0).toULongLong(nullptr, 16); - } - - tc.movePosition(QTextCursor::StartOfLine); - if (tc.atStart()) - { - break; - } - - tc.movePosition(QTextCursor::Up); + return RVA_INVALID; } - return RVA_INVALID; + auto *dsUserData = static_cast(userData); + return dsUserData->line.offset; } void DisassemblyWidget::updateCursorPosition() diff --git a/src/widgets/DisassemblyWidget.h b/src/widgets/DisassemblyWidget.h index b3f8577d..84da9b99 100644 --- a/src/widgets/DisassemblyWidget.h +++ b/src/widgets/DisassemblyWidget.h @@ -46,7 +46,6 @@ private: RVA bottomOffset; int maxLines; - QString readDisasm(const QString &cmd, bool stripLastNewline); RVA readCurrentDisassemblyOffset(); RVA readDisassemblyOffset(QTextCursor tc); bool eventFilter(QObject *obj, QEvent *event);