From 0a5a1dfbcfd84e8cb3eab7ff82c472b476a1337c Mon Sep 17 00:00:00 2001 From: wargio Date: Tue, 2 Jan 2024 21:43:49 +0800 Subject: [PATCH] Initial working diff with resizable columns --- src/core/BinDiff.cpp | 14 ++- src/core/BinDiff.h | 3 + src/core/Cutter.cpp | 40 +++++-- src/core/Cutter.h | 8 +- src/core/MainWindow.cpp | 3 +- src/tools/basefind/BaseFindDialog.cpp | 1 + src/tools/basefind/BaseFindResultsDialog.cpp | 1 + src/tools/basefind/BaseFindSearchDialog.cpp | 1 + src/tools/bindiff/DiffLoadDialog.cpp | 10 ++ src/tools/bindiff/DiffLoadDialog.h | 1 + src/tools/bindiff/DiffLoadDialog.ui | 70 ++++++----- src/tools/bindiff/DiffWaitDialog.cpp | 17 +-- src/tools/bindiff/DiffWaitDialog.h | 2 +- src/tools/bindiff/DiffWaitDialog.ui | 4 +- src/tools/bindiff/DiffWindow.cpp | 34 ++++-- src/tools/bindiff/DiffWindow.ui | 119 ++++++++++++++++++- 16 files changed, 258 insertions(+), 70 deletions(-) diff --git a/src/core/BinDiff.cpp b/src/core/BinDiff.cpp index 581e13f9..188023af 100644 --- a/src/core/BinDiff.cpp +++ b/src/core/BinDiff.cpp @@ -22,6 +22,11 @@ BinDiff::~BinDiff() rz_analysis_match_result_free(result); } +bool BinDiff::hasData() +{ + return result != nullptr; +} + void BinDiff::setFile(QString filePath) { mutex.lock(); @@ -36,6 +41,13 @@ void BinDiff::setAnalysisLevel(int aLevel) mutex.unlock(); } +void BinDiff::setCompareLogic(int cLogic) +{ + mutex.lock(); + compareLogic = cLogic; + mutex.unlock(); +} + void BinDiff::run() { qRegisterMetaType(); @@ -47,7 +59,7 @@ void BinDiff::run() maxTotal = 1; // maxTotal must be at least 1. mutex.unlock(); - result = Core()->diffNewFile(file, level, threadCallback, this); + result = Core()->diffNewFile(file, level, compareLogic, threadCallback, this); mutex.lock(); bool canComplete = continueRun; diff --git a/src/core/BinDiff.h b/src/core/BinDiff.h index a3bfeb7c..d55891e6 100644 --- a/src/core/BinDiff.h +++ b/src/core/BinDiff.h @@ -20,6 +20,8 @@ public: void setFile(QString filePth); void setAnalysisLevel(int aLevel); + void setCompareLogic(int cLogic); + bool hasData(); QList matches(); QList mismatch(bool originalFile); @@ -42,6 +44,7 @@ private: #endif QString file; int level; + int compareLogic; bool updateProgress(const size_t nLeft, const size_t nMatch); static bool threadCallback(const size_t nLeft, const size_t nMatch, void *user); diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 5284ec57..70664bba 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -4564,8 +4564,13 @@ bool CutterCore::isWriteModeEnabled() return false; } -RzList *get_functions(RzAnalysis *analysis) +#define IS_IMPORT(name) \ + (name.startsWith("sym.imp.") || name.startsWith("loc.imp.") || name.startsWith("imp.")) +#define IS_SYMBOL(name, pfx) (IS_IMPORT(name) || name.startsWith(pfx)) + +RzList *get_functions(RzAnalysis *analysis, int compareLogic) { + RzList *functions = rz_analysis_get_fcns(analysis); if (!functions) { return nullptr; @@ -4576,12 +4581,21 @@ RzList *get_functions(RzAnalysis *analysis) return list; } + QString pfx = Config()->getConfigString("analysis.fcnprefix"); + if (pfx.isEmpty()) { + pfx = "fcn."; + } else { + pfx += "."; + } + RzAnalysisFunction *func = nullptr; RzListIter *it = nullptr; CutterRzListForeach (functions, it, RzAnalysisFunction, func) { QString name = func->name; - if (name.startsWith("sym.imp.") || name.startsWith("loc.imp.") || name.startsWith("imp.")) { + if (compareLogic == CutterCore::CompareLogicDefault && IS_IMPORT(name)) { + continue; + } else if (compareLogic == CutterCore::CompareLogicSymbols && IS_SYMBOL(name, pfx)) { continue; } rz_list_add_sorted(list, func, analysis->columnSort); @@ -4590,7 +4604,7 @@ RzList *get_functions(RzAnalysis *analysis) return list; } -RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int level, +RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int level, int compareLogic, RzAnalysisMatchThreadInfoCb callback, void *user) { CORE_LOCK(); @@ -4613,17 +4627,17 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int leve } if (!rz_core_file_open(core_b, filePath.toUtf8().constData(), RZ_PERM_RX, 0)) { - qWarning() << "cannot open file " << filePath; + qWarning() << tr("cannot open file %1").arg(filePath); goto fail; } if (!rz_core_bin_load(core_b, nullptr, UT64_MAX)) { - qWarning() << "cannot load bin " << filePath; + qWarning() << tr("cannot load bin %1").arg(filePath); goto fail; } if (!rz_core_bin_update_arch_bits(core_b)) { - qWarning() << "cannot set architecture with bits"; + qWarning() << tr("cannot set architecture with bits"); goto fail; } @@ -4637,25 +4651,25 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int leve } if (!rz_core_analysis_all(core_b)) { - qWarning() << "cannot perform basic analysis of the binary " << filePath; + qWarning() << tr("cannot perform basic analysis of the binary %1").arg(filePath); goto fail; } if (level != AnalysisLevelSymbols && !rz_core_analysis_everything(core_b, level == AnalysisLevelExperimental, nullptr)) { - qWarning() << "cannot perform complete analysis of the binary " << filePath; + qWarning() << tr("cannot perform complete analysis of the binary %1").arg(filePath); goto fail; } - fcns_a = get_functions(core_a->analysis); + fcns_a = get_functions(core_a->analysis, compareLogic); if (rz_list_empty(fcns_a)) { - qWarning() << "no functions found in the current opened file"; + qWarning() << tr("no functions found in the current opened file"); goto fail; } - fcns_b = get_functions(core_b->analysis); + fcns_b = get_functions(core_b->analysis, compareLogic); if (rz_list_empty(fcns_b)) { - qWarning() << "no functions found in " << filePath; + qWarning() << tr("no functions found in the just opene file %1").arg(filePath); goto fail; } @@ -4667,7 +4681,7 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int leve // calculate all the matches between the functions of the 2 different core files. result = rz_analysis_match_functions(fcns_a, fcns_b, &opts); if (!result) { - qWarning() << "failed to perform the function matching operation or job was cancelled."; + qWarning() << tr("failed to perform the function matching operation or job was cancelled."); goto fail; } diff --git a/src/core/Cutter.h b/src/core/Cutter.h index ce29ad26..2c060b96 100644 --- a/src/core/Cutter.h +++ b/src/core/Cutter.h @@ -762,7 +762,13 @@ public: AnalysisLevelExperimental, }; - RzAnalysisMatchResult *diffNewFile(const QString &filePath, int level, + enum { + CompareLogicDefault = 0, ///< Only symbols and functions (no imports) + CompareLogicComplete, ///< All functions (imports included) + CompareLogicSymbols, ///< Only symbols + }; + + RzAnalysisMatchResult *diffNewFile(const QString &filePath, int level, int compareLogic, RzAnalysisMatchThreadInfoCb callback, void *user); signals: diff --git a/src/core/MainWindow.cpp b/src/core/MainWindow.cpp index ef9474dc..a8228395 100644 --- a/src/core/MainWindow.cpp +++ b/src/core/MainWindow.cpp @@ -1638,8 +1638,9 @@ void MainWindow::startDiffing() } auto level = diffLoadDialog->getLevel(); + auto compare = diffLoadDialog->getCompare(); auto diffWait = new DiffWaitDialog(this); - diffWait->show(filename, modified, level); + diffWait->show(filename, modified, level, compare); } void MainWindow::on_actionForward_triggered() diff --git a/src/tools/basefind/BaseFindDialog.cpp b/src/tools/basefind/BaseFindDialog.cpp index bb2683d1..856a4be5 100644 --- a/src/tools/basefind/BaseFindDialog.cpp +++ b/src/tools/basefind/BaseFindDialog.cpp @@ -10,6 +10,7 @@ BaseFindDialog::BaseFindDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Ba { ui->setupUi(this); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); + setModal(true); // Fill in N-thread Combo size_t n_cores = rz_th_physical_core_number(); diff --git a/src/tools/basefind/BaseFindResultsDialog.cpp b/src/tools/basefind/BaseFindResultsDialog.cpp index 993031b4..c727afc3 100644 --- a/src/tools/basefind/BaseFindResultsDialog.cpp +++ b/src/tools/basefind/BaseFindResultsDialog.cpp @@ -72,6 +72,7 @@ BaseFindResultsDialog::BaseFindResultsDialog(QList re { ui->setupUi(this); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); + setModal(true); model = new BaseFindResultsModel(&list, this); ui->tableView->setModel(model); diff --git a/src/tools/basefind/BaseFindSearchDialog.cpp b/src/tools/basefind/BaseFindSearchDialog.cpp index bc29af4f..f2a4b639 100644 --- a/src/tools/basefind/BaseFindSearchDialog.cpp +++ b/src/tools/basefind/BaseFindSearchDialog.cpp @@ -14,6 +14,7 @@ BaseFindSearchDialog::BaseFindSearchDialog(QWidget *parent) { ui->setupUi(this); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); + setModal(true); } BaseFindSearchDialog::~BaseFindSearchDialog() {} diff --git a/src/tools/bindiff/DiffLoadDialog.cpp b/src/tools/bindiff/DiffLoadDialog.cpp index 91db3ac9..72cd4b1e 100644 --- a/src/tools/bindiff/DiffLoadDialog.cpp +++ b/src/tools/bindiff/DiffLoadDialog.cpp @@ -13,6 +13,7 @@ DiffLoadDialog::DiffLoadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Di { ui->setupUi(this); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); + setModal(true); ui->lineEditFileName->setReadOnly(true); ui->lineEditFileName->setText(""); @@ -24,6 +25,10 @@ DiffLoadDialog::DiffLoadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Di ui->comboBoxAnalysis->addItem(tr("Auto")); ui->comboBoxAnalysis->addItem(tr("Experimental")); + ui->comboBoxCompare->addItem(tr("Default")); + ui->comboBoxCompare->addItem(tr("All functions")); + ui->comboBoxCompare->addItem(tr("Only Symbols")); + auto index = ui->comboBoxAnalysis->findData(tr("Auto"), Qt::DisplayRole); ui->comboBoxAnalysis->setCurrentIndex(index); } @@ -45,6 +50,11 @@ int DiffLoadDialog::getLevel() const return ui->comboBoxAnalysis->currentIndex(); } +int DiffLoadDialog::getCompare() const +{ + return ui->comboBoxCompare->currentIndex(); +} + void DiffLoadDialog::on_buttonDiffOpen_clicked() { QFileDialog dialog(this); diff --git a/src/tools/bindiff/DiffLoadDialog.h b/src/tools/bindiff/DiffLoadDialog.h index b079776d..814cd62e 100644 --- a/src/tools/bindiff/DiffLoadDialog.h +++ b/src/tools/bindiff/DiffLoadDialog.h @@ -22,6 +22,7 @@ public: QString getFileToOpen() const; QString getPreviousDiffFile() const; int getLevel() const; + int getCompare() const; signals: void startDiffing(); diff --git a/src/tools/bindiff/DiffLoadDialog.ui b/src/tools/bindiff/DiffLoadDialog.ui index bd1e66a2..4e514eb6 100644 --- a/src/tools/bindiff/DiffLoadDialog.ui +++ b/src/tools/bindiff/DiffLoadDialog.ui @@ -10,7 +10,7 @@ 0 0 636 - 184 + 226 @@ -20,7 +20,7 @@ - Select which file to compare. + Select which file to compare. @@ -34,22 +34,6 @@ - - - - - 0 - 0 - - - - <html><head/><body><p>File to compare to.</p></body></html> - - - File to compare (required) - - - @@ -57,6 +41,19 @@ + + + + Select + + + + + + + + + @@ -73,16 +70,6 @@ - - - - - - - Select - - - @@ -90,8 +77,31 @@ - - + + + + + 0 + 0 + + + + <html><head/><body><p>File to compare to.</p></body></html> + + + File to compare (required) + + + + + + + Compare Logic + + + + + diff --git a/src/tools/bindiff/DiffWaitDialog.cpp b/src/tools/bindiff/DiffWaitDialog.cpp index 3e888bc2..172861e4 100644 --- a/src/tools/bindiff/DiffWaitDialog.cpp +++ b/src/tools/bindiff/DiffWaitDialog.cpp @@ -13,11 +13,10 @@ DiffWaitDialog::DiffWaitDialog(QWidget *parent) { ui->setupUi(this); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); + setModal(true); ui->lineEditNFuncs->setReadOnly(true); ui->lineEditMatches->setReadOnly(true); - ui->lineEditEstimatedTime->setReadOnly(true); - ui->lineEditElapsedTime->setReadOnly(true); ui->lineEditOriginal->setReadOnly(true); ui->lineEditModified->setReadOnly(true); ui->progressBar->setValue(0); @@ -34,11 +33,11 @@ DiffWaitDialog::~DiffWaitDialog() if (bDiff && bDiff->isRunning()) { bDiff->cancel(); bDiff->wait(); - delete bDiff; } + delete bDiff; } -void DiffWaitDialog::show(QString original, QString modified, int level) +void DiffWaitDialog::show(QString original, QString modified, int level, int compare) { connect(this, &DiffWaitDialog::cancelJob, bDiff, &BinDiff::cancel); connect(bDiff, &BinDiff::progress, this, &DiffWaitDialog::onProgress); @@ -49,6 +48,7 @@ void DiffWaitDialog::show(QString original, QString modified, int level) ui->lineEditModified->setText(modified); bDiff->setAnalysisLevel(level); + bDiff->setCompareLogic(compare); bDiff->setFile(modified); eTimer.restart(); timer.setSingleShot(false); @@ -80,10 +80,12 @@ void DiffWaitDialog::onCompletion() { timer.stop(); - auto results = new DiffWindow(bDiff, parentWidget()); - bDiff = nullptr; + if (bDiff->hasData()) { + auto results = new DiffWindow(bDiff, parentWidget()); + bDiff = nullptr; + results->showMaximized(); + } - results->showMaximized(); close(); } @@ -102,4 +104,5 @@ void DiffWaitDialog::on_buttonBox_rejected() { timer.stop(); emit cancelJob(); + close(); } diff --git a/src/tools/bindiff/DiffWaitDialog.h b/src/tools/bindiff/DiffWaitDialog.h index f1ff7966..90cfc47e 100644 --- a/src/tools/bindiff/DiffWaitDialog.h +++ b/src/tools/bindiff/DiffWaitDialog.h @@ -22,7 +22,7 @@ public: explicit DiffWaitDialog(QWidget *parent = nullptr); ~DiffWaitDialog(); - void show(QString original, QString modified, int level); + void show(QString original, QString modified, int level, int compare); public slots: void onProgress(BinDiffStatusDescription status); diff --git a/src/tools/bindiff/DiffWaitDialog.ui b/src/tools/bindiff/DiffWaitDialog.ui index 656cab56..9d86f65a 100644 --- a/src/tools/bindiff/DiffWaitDialog.ui +++ b/src/tools/bindiff/DiffWaitDialog.ui @@ -41,7 +41,7 @@ - + @@ -98,7 +98,7 @@ - + diff --git a/src/tools/bindiff/DiffWindow.cpp b/src/tools/bindiff/DiffWindow.cpp index 61c13c0a..ca0f5ad0 100644 --- a/src/tools/bindiff/DiffWindow.cpp +++ b/src/tools/bindiff/DiffWindow.cpp @@ -56,7 +56,26 @@ QVariant DiffMatchModel::data(const QModelIndex &index, int role) const } case Qt::ToolTipRole: { - return entry.simtype; + switch (index.column()) { + case NameOrig: + return entry.original.name; + case SizeOrig: + return QString::asprintf("%llu (%#llx)", entry.original.linearSize, + entry.original.linearSize); + case AddressOrig: + return RzAddressString(entry.original.offset); + case Similarity: + return entry.simtype; + case AddressMod: + return RzAddressString(entry.modified.offset); + case SizeMod: + return QString::asprintf("%llu (%#llx)", entry.modified.linearSize, + entry.modified.linearSize); + case NameMod: + return entry.modified.name; + default: + return QVariant(); + } } case Qt::BackgroundRole: { @@ -126,6 +145,8 @@ QVariant DiffMismatchModel::data(const QModelIndex &index, int role) const const FunctionDescription &entry = list->at(index.row()); switch (role) { + case Qt::ToolTipRole: + /* fall-thru */ case Qt::DisplayRole: switch (index.column()) { case FuncName: @@ -150,10 +171,6 @@ QVariant DiffMismatchModel::data(const QModelIndex &index, int role) const return QVariant(); } - case Qt::ToolTipRole: { - return entry.name; - } - default: return QVariant(); } @@ -194,6 +211,7 @@ DiffWindow::DiffWindow(BinDiff *bd, QWidget *parent) : QDialog(parent), ui(new Ui::DiffWindow), bDiff(bd) { ui->setupUi(this); + setModal(true); ui->comboBoxShowInfo->addItem(tr("Summary")); ui->comboBoxShowInfo->addItem(tr("AAAA")); @@ -213,22 +231,16 @@ DiffWindow::DiffWindow(BinDiff *bd, QWidget *parent) // Matches Table ui->tableViewMatch->setModel(modelMatch); ui->tableViewMatch->sortByColumn(DiffMatchModel::Similarity, Qt::AscendingOrder); - ui->tableViewMatch->verticalHeader()->hide(); - ui->tableViewMatch->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); ui->tableViewMatch->setContextMenuPolicy(Qt::CustomContextMenu); // Deletion Table ui->tableViewRem->setModel(modelDel); ui->tableViewRem->sortByColumn(DiffMismatchModel::FuncName, Qt::AscendingOrder); - ui->tableViewRem->verticalHeader()->hide(); - ui->tableViewRem->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); ui->tableViewRem->setContextMenuPolicy(Qt::CustomContextMenu); // Addition Table ui->tableViewAdd->setModel(modelAdd); ui->tableViewAdd->sortByColumn(DiffMismatchModel::FuncName, Qt::AscendingOrder); - ui->tableViewAdd->verticalHeader()->hide(); - ui->tableViewAdd->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); ui->tableViewAdd->setContextMenuPolicy(Qt::CustomContextMenu); } diff --git a/src/tools/bindiff/DiffWindow.ui b/src/tools/bindiff/DiffWindow.ui index 947137fc..eb966a4f 100644 --- a/src/tools/bindiff/DiffWindow.ui +++ b/src/tools/bindiff/DiffWindow.ui @@ -64,7 +64,42 @@ - + + + Matches + + + CutterTreeView::item +{ + padding-top: 1px; + padding-bottom: 1px; +} + + + QFrame::NoFrame + + + 0 + + + Qt::ScrollBarAsNeeded + + + QAbstractScrollArea::AdjustToContents + + + true + + + QAbstractItemView::ScrollPerPixel + + + 8 + + + true + + @@ -74,7 +109,42 @@ - + + + Matches + + + CutterTreeView::item +{ + padding-top: 1px; + padding-bottom: 1px; +} + + + QFrame::NoFrame + + + 0 + + + Qt::ScrollBarAsNeeded + + + QAbstractScrollArea::AdjustToContents + + + true + + + QAbstractItemView::ScrollPerPixel + + + 8 + + + true + + @@ -84,7 +154,42 @@ - + + + Matches + + + CutterTreeView::item +{ + padding-top: 1px; + padding-bottom: 1px; +} + + + QFrame::NoFrame + + + 0 + + + Qt::ScrollBarAsNeeded + + + QAbstractScrollArea::AdjustToContents + + + true + + + QAbstractItemView::ScrollPerPixel + + + 8 + + + true + + @@ -151,6 +256,14 @@ + + + CutterTreeView + QTreeView +
widgets/CutterTreeView.h
+ 1 +
+