Working open dialog with waiting dialog.

This commit is contained in:
wargio 2023-12-31 11:11:56 +08:00
parent 439b268927
commit 5e2d58ea11
19 changed files with 482 additions and 317 deletions

View File

@ -30,6 +30,7 @@ option(CUTTER_PACKAGE_RZ_LIBYARA "Compile and install rz-libyara during the inst
option(CUTTER_PACKAGE_RZ_SILHOUETTE "Compile and install rz-silhouette during the install step." OFF) option(CUTTER_PACKAGE_RZ_SILHOUETTE "Compile and install rz-silhouette during the install step." OFF)
option(CUTTER_PACKAGE_JSDEC "Compile and install jsdec during install step." OFF) option(CUTTER_PACKAGE_JSDEC "Compile and install jsdec during install step." OFF)
OPTION(CUTTER_QT6 "Use QT6" OFF) OPTION(CUTTER_QT6 "Use QT6" OFF)
OPTION(CUTTER_ASAN "Build with ASAN" OFF)
if(NOT CUTTER_ENABLE_PYTHON) if(NOT CUTTER_ENABLE_PYTHON)
set(CUTTER_ENABLE_PYTHON_BINDINGS OFF) set(CUTTER_ENABLE_PYTHON_BINDINGS OFF)
@ -188,6 +189,7 @@ message(STATUS "- Package RzLibYara: ${CUTTER_PACKAGE_RZ_LIBYARA}")
message(STATUS "- Package RzSilhouette: ${CUTTER_PACKAGE_RZ_SILHOUETTE}") message(STATUS "- Package RzSilhouette: ${CUTTER_PACKAGE_RZ_SILHOUETTE}")
message(STATUS "- Package JSDec: ${CUTTER_PACKAGE_JSDEC}") message(STATUS "- Package JSDec: ${CUTTER_PACKAGE_JSDEC}")
message(STATUS "- QT6: ${CUTTER_QT6}") message(STATUS "- QT6: ${CUTTER_QT6}")
message(STATUS "- ASAN: ${CUTTER_ASAN}")
message(STATUS "") message(STATUS "")
add_subdirectory(src) add_subdirectory(src)

View File

@ -157,6 +157,7 @@ set(SOURCES
tools/basefind/BaseFindSearchDialog.cpp tools/basefind/BaseFindSearchDialog.cpp
tools/basefind/BaseFindResultsDialog.cpp tools/basefind/BaseFindResultsDialog.cpp
tools/bindiff/DiffLoadDialog.cpp tools/bindiff/DiffLoadDialog.cpp
tools/bindiff/DiffWaitDialog.cpp
) )
set(HEADER_FILES set(HEADER_FILES
core/Cutter.h core/Cutter.h
@ -323,6 +324,7 @@ set(HEADER_FILES
tools/basefind/BaseFindSearchDialog.h tools/basefind/BaseFindSearchDialog.h
tools/basefind/BaseFindResultsDialog.h tools/basefind/BaseFindResultsDialog.h
tools/bindiff/DiffLoadDialog.h tools/bindiff/DiffLoadDialog.h
tools/bindiff/DiffWaitDialog.h
) )
set(UI_FILES set(UI_FILES
dialogs/AboutDialog.ui dialogs/AboutDialog.ui
@ -398,6 +400,7 @@ set(UI_FILES
tools/basefind/BaseFindSearchDialog.ui tools/basefind/BaseFindSearchDialog.ui
tools/basefind/BaseFindResultsDialog.ui tools/basefind/BaseFindResultsDialog.ui
tools/bindiff/DiffLoadDialog.ui tools/bindiff/DiffLoadDialog.ui
tools/bindiff/DiffWaitDialog.ui
) )
set(QRC_FILES set(QRC_FILES
resources.qrc resources.qrc
@ -588,6 +591,12 @@ if(CUTTER_ENABLE_PACKAGING)
target_compile_definitions(Cutter PRIVATE CUTTER_ENABLE_PACKAGING) target_compile_definitions(Cutter PRIVATE CUTTER_ENABLE_PACKAGING)
endif() endif()
if(CUTTER_ASAN)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always -fsanitize=address,undefined -fno-omit-frame-pointer -fsanitize-address-use-after-scope")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always -fsanitize=address,undefined -fno-omit-frame-pointer -fsanitize-address-use-after-scope")
set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fdiagnostics-color=always -fsanitize=address,undefined -fno-omit-frame-pointer -fsanitize-address-use-after-scope")
endif()
include(Translations) include(Translations)
# Install files # Install files

View File

@ -6,10 +6,9 @@ bool BinDiff::threadCallback(const size_t nLeft, const size_t nMatch, void *user
return bdiff->updateProgress(nLeft, nMatch); return bdiff->updateProgress(nLeft, nMatch);
} }
BinDiff::BinDiff(CutterCore *core) BinDiff::BinDiff()
: core(core), : result(nullptr),
result(nullptr), continueRun(true),
continue_run(true),
maxTotal(1) maxTotal(1)
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
, ,
@ -20,31 +19,48 @@ BinDiff::BinDiff(CutterCore *core)
BinDiff::~BinDiff() BinDiff::~BinDiff()
{ {
cancel();
wait();
rz_analysis_match_result_free(result); rz_analysis_match_result_free(result);
} }
void BinDiff::run(QString fileName) void BinDiff::setFile(QString filePath)
{ {
mutex.lock();
file = filePath;
mutex.unlock();
}
void BinDiff::setAnalysisLevel(int aLevel)
{
mutex.lock();
level = aLevel;
mutex.unlock();
}
void BinDiff::run()
{
qRegisterMetaType<BinDiffStatusDescription>();
mutex.lock(); mutex.lock();
rz_analysis_match_result_free(result); rz_analysis_match_result_free(result);
result = nullptr; result = nullptr;
continue_run = true; continueRun = true;
maxTotal = 1; // maxTotal must be at least 1. maxTotal = 1; // maxTotal must be at least 1.
mutex.unlock(); mutex.unlock();
core->coreMutex.lock(); result = Core()->diffNewFile(file, level, threadCallback, this);
result = core->diffNewFile(fileName, threadCallback, this);
core->coreMutex.unlock();
emit complete(); mutex.lock();
bool canComplete = continueRun;
mutex.unlock();
if (canComplete) {
emit complete();
}
} }
void BinDiff::cancel() void BinDiff::cancel()
{ {
mutex.lock(); mutex.lock();
continue_run = false; continueRun = false;
mutex.unlock(); mutex.unlock();
} }
@ -69,6 +85,10 @@ QList<BinDiffMatchDescription> BinDiff::matches()
const RzAnalysisFunction *fcn_a = nullptr; const RzAnalysisFunction *fcn_a = nullptr;
const RzAnalysisFunction *fcn_b = nullptr; const RzAnalysisFunction *fcn_b = nullptr;
if (!result) {
return pairs;
}
CutterRzListForeach (result->matches, it, RzAnalysisMatchPair, pair) { CutterRzListForeach (result->matches, it, RzAnalysisMatchPair, pair) {
BinDiffMatchDescription desc; BinDiffMatchDescription desc;
fcn_a = static_cast<const RzAnalysisFunction *>(pair->pair_a); fcn_a = static_cast<const RzAnalysisFunction *>(pair->pair_a);
@ -93,6 +113,10 @@ QList<FunctionDescription> BinDiff::mismatch(bool fileA)
RzList *unmatch = fileA ? result->unmatch_a : result->unmatch_b; RzList *unmatch = fileA ? result->unmatch_a : result->unmatch_b;
RzListIter *it = nullptr; RzListIter *it = nullptr;
if (!result) {
return list;
}
CutterRzListForeach (unmatch, it, RzAnalysisFunction, func) { CutterRzListForeach (unmatch, it, RzAnalysisFunction, func) {
FunctionDescription desc; FunctionDescription desc;
setFunctionDescription(&desc, func); setFunctionDescription(&desc, func);
@ -102,19 +126,23 @@ QList<FunctionDescription> BinDiff::mismatch(bool fileA)
return list; return list;
} }
bool BinDiff::updateProgress(const size_t nLeft, const size_t nMatch) bool BinDiff::updateProgress(size_t nLeft, size_t nMatch)
{ {
mutex.lock(); mutex.lock();
if (nMatch > maxTotal) {
if (maxTotal < nMatch) {
maxTotal = nMatch; maxTotal = nMatch;
} }
if (maxTotal < nLeft) { if (nLeft > maxTotal) {
maxTotal = nLeft; maxTotal = nLeft;
} }
emit progress(maxTotal, nLeft, nMatch); BinDiffStatusDescription status;
bool ret = continue_run; status.total = maxTotal;
status.nLeft = nLeft;
status.nMatch = nMatch;
emit progress(status);
bool ret = continueRun;
mutex.unlock(); mutex.unlock();
return ret; return ret;
} }

View File

@ -8,17 +8,19 @@
#include "CutterDescriptions.h" #include "CutterDescriptions.h"
#include <rz_analysis.h> #include <rz_analysis.h>
class CutterCore;
class BinDiff : public QThread class BinDiff : public QThread
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit BinDiff(CutterCore *core); explicit BinDiff();
virtual ~BinDiff(); virtual ~BinDiff();
void run(QString fileName); void run();
void setFile(QString filePth);
void setAnalysisLevel(int aLevel);
QList<BinDiffMatchDescription> matches(); QList<BinDiffMatchDescription> matches();
QList<FunctionDescription> mismatch(bool fileA); QList<FunctionDescription> mismatch(bool fileA);
@ -26,19 +28,20 @@ public slots:
void cancel(); void cancel();
signals: signals:
void progress(const size_t total, const size_t nLeft, const size_t nMatch); void progress(BinDiffStatusDescription status);
void complete(); void complete();
private: private:
CutterCore *const core;
RzAnalysisMatchResult *result; RzAnalysisMatchResult *result;
bool continue_run; bool continueRun;
size_t maxTotal; size_t maxTotal;
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QMutex mutex; QMutex mutex;
#else #else
QRecursiveMutex mutex; QRecursiveMutex mutex;
#endif #endif
QString file;
int level;
bool updateProgress(const size_t nLeft, const size_t nMatch); bool updateProgress(const size_t nLeft, const size_t nMatch);
static bool threadCallback(const size_t nLeft, const size_t nMatch, void *user); static bool threadCallback(const size_t nLeft, const size_t nMatch, void *user);

View File

@ -233,11 +233,11 @@ CutterCore::~CutterCore()
{ {
delete bbHighlighter; delete bbHighlighter;
rz_cons_sleep_end(coreBed); rz_cons_sleep_end(coreBed);
rz_core_free(this->core_b);
this->core_b = nullptr;
rz_core_task_sync_end(&core_a->tasks); rz_core_task_sync_end(&core_a->tasks);
rz_core_free(this->core_a); rz_core_free(this->core_a);
this->core_a = nullptr; this->core_a = nullptr;
rz_core_free(this->core_b);
this->core_b = nullptr;
rz_cons_free(); rz_cons_free();
assert(uniqueInstance == this); assert(uniqueInstance == this);
uniqueInstance = nullptr; uniqueInstance = nullptr;
@ -4564,30 +4564,28 @@ bool CutterCore::isWriteModeEnabled()
return false; return false;
} }
RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath, int level,
RzAnalysisMatchThreadInfoCb callback, void *user) RzAnalysisMatchThreadInfoCb callback, void *user)
{ {
CORE_LOCK();
RzList *fcns_a = nullptr, *fcns_b = nullptr; RzList *fcns_a = nullptr, *fcns_b = nullptr;
RzAnalysisMatchResult *result = nullptr; RzAnalysisMatchResult *result = nullptr;
RzAnalysisMatchOpt opts; RzAnalysisMatchOpt opts;
RzListIter *iter; RzListIter *iter;
RzConfigNode *node; RzConfigNode *node;
void *ptr;
if (core_b) {
rz_core_free(core_b);
core_b = nullptr;
}
core_b = rz_core_new();
if (!core_b) { if (!core_b) {
goto fail; // FIXME: allocating and deallocating a new core here, taints some pointer on core_a
core_b = rz_core_new();
if (!core_b) {
return nullptr;
}
rz_config_set_b(core_b->config, "io.va", rz_config_get_b(core_a->config, "io.va"));
rz_core_loadlibs(core_b, RZ_CORE_LOADLIBS_ALL);
core_b->print->scr_prompt = false;
} }
rz_config_set_b(core_b->config, "io.va", rz_config_get_b(core_a->config, "io.va"));
rz_core_loadlibs(core_b, RZ_CORE_LOADLIBS_ALL);
core_b->print->scr_prompt = false;
if (!rz_core_file_open(core_b, filePath.toUtf8().constData(), RZ_PERM_RX, 0)) { if (!rz_core_file_open(core_b, filePath.toUtf8().constData(), RZ_PERM_RX, 0)) {
qWarning() << "cannot open file " << filePath; qWarning() << "cannot open file " << filePath;
goto fail; goto fail;
@ -4603,9 +4601,7 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath,
goto fail; goto fail;
} }
rz_list_foreach(core_a->config->nodes, iter, ptr) CutterRzListForeach (core_a->config->nodes, iter, RzConfigNode, node) {
{
node = reinterpret_cast<RzConfigNode *>(ptr);
if (!strcmp(node->name, "scr.color") || !strcmp(node->name, "scr.interactive") if (!strcmp(node->name, "scr.color") || !strcmp(node->name, "scr.interactive")
|| !strcmp(node->name, "cfg.debug")) { || !strcmp(node->name, "cfg.debug")) {
rz_config_set(core_b->config, node->name, "0"); rz_config_set(core_b->config, node->name, "0");
@ -4614,8 +4610,14 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath,
rz_config_set(core_b->config, node->name, node->value); rz_config_set(core_b->config, node->name, node->value);
} }
if (!rz_core_analysis_everything(core_b, false, nullptr)) { if (!rz_core_analysis_all(core_b)) {
qWarning() << "cannot analyze binary " << filePath; qWarning() << "cannot perform basic analysis of the binary " << filePath;
goto fail;
}
if (level != AnalysisLevelSymbols
&& !rz_core_analysis_everything(core_b, level == AnalysisLevelExperimental, nullptr)) {
qWarning() << "cannot perform complete analysis of the binary " << filePath;
goto fail; goto fail;
} }
@ -4651,10 +4653,10 @@ RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath,
return result; return result;
fail: fail:
rz_list_free(fcns_a); rz_list_free(fcns_a);
rz_list_free(fcns_b); rz_list_free(fcns_b);
rz_core_free(this->core_b); rz_core_file_close_all_but(core_b);
this->core_b = nullptr;
return nullptr; return nullptr;
} }

View File

@ -72,7 +72,6 @@ class CUTTER_EXPORT CutterCore : public QObject
friend class RzCoreLocked; friend class RzCoreLocked;
friend class RizinTask; friend class RizinTask;
friend class Basefind; friend class Basefind;
friend class BinDiff;
public: public:
explicit CutterCore(QObject *parent = nullptr); explicit CutterCore(QObject *parent = nullptr);
@ -757,7 +756,13 @@ public:
void writeGraphvizGraphToFile(QString path, QString format, RzCoreGraphType type, RVA address); void writeGraphvizGraphToFile(QString path, QString format, RzCoreGraphType type, RVA address);
/* Diffing/Matching */ /* Diffing/Matching */
RzAnalysisMatchResult *diffNewFile(const QString &filePath, enum {
AnalysisLevelSymbols = 0,
AnalysisLevelComplete,
AnalysisLevelExperimental,
};
RzAnalysisMatchResult *diffNewFile(const QString &filePath, int level,
RzAnalysisMatchThreadInfoCb callback, void *user); RzAnalysisMatchThreadInfoCb callback, void *user);
signals: signals:

View File

@ -413,6 +413,13 @@ struct BinDiffMatchDescription
double similarity; double similarity;
}; };
struct BinDiffStatusDescription
{
size_t total;
size_t nLeft;
size_t nMatch;
};
Q_DECLARE_METATYPE(FunctionDescription) Q_DECLARE_METATYPE(FunctionDescription)
Q_DECLARE_METATYPE(ImportDescription) Q_DECLARE_METATYPE(ImportDescription)
Q_DECLARE_METATYPE(ExportDescription) Q_DECLARE_METATYPE(ExportDescription)
@ -455,5 +462,6 @@ Q_DECLARE_METATYPE(VariableDescription)
Q_DECLARE_METATYPE(BasefindCoreStatusDescription) Q_DECLARE_METATYPE(BasefindCoreStatusDescription)
Q_DECLARE_METATYPE(BasefindResultDescription) Q_DECLARE_METATYPE(BasefindResultDescription)
Q_DECLARE_METATYPE(BinDiffMatchDescription) Q_DECLARE_METATYPE(BinDiffMatchDescription)
Q_DECLARE_METATYPE(BinDiffStatusDescription)
#endif // DESCRIPTIONS_H #endif // DESCRIPTIONS_H

View File

@ -119,7 +119,7 @@
// Tools // Tools
#include "tools/basefind/BaseFindDialog.h" #include "tools/basefind/BaseFindDialog.h"
#include "tools/bindiff/DiffLoadDialog.h" #include "tools/bindiff/DiffWaitDialog.h"
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)") #define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
@ -1617,8 +1617,29 @@ void MainWindow::on_actionBackward_triggered()
void MainWindow::on_actionDiff_triggered() void MainWindow::on_actionDiff_triggered()
{ {
auto dialog = new DiffLoadDialog(this); if (diffLoadDialog) {
dialog->show(); delete diffLoadDialog;
}
diffLoadDialog = new DiffLoadDialog(this);
diffLoadDialog->show();
connect(diffLoadDialog, &DiffLoadDialog::startDiffing, this, &MainWindow::startDiffing);
}
void MainWindow::startDiffing()
{
if (!diffLoadDialog) {
return;
}
QString modified = diffLoadDialog->getFileToOpen();
if (modified.isEmpty()) {
messageBoxWarning(tr("Error"), tr("The compare file was not selected."));
return;
}
auto level = diffLoadDialog->getLevel();
auto diffWait = new DiffWaitDialog(this);
diffWait->show(filename, modified, level);
} }
void MainWindow::on_actionForward_triggered() void MainWindow::on_actionForward_triggered()

View File

@ -4,12 +4,12 @@
#include "core/Cutter.h" // only needed for ut64 #include "core/Cutter.h" // only needed for ut64
#include "dialogs/NewFileDialog.h" #include "dialogs/NewFileDialog.h"
#include "dialogs/WelcomeDialog.h" #include "dialogs/WelcomeDialog.h"
#include "dialogs/bindiff/BinDiffDialog.h"
#include "common/Configuration.h" #include "common/Configuration.h"
#include "common/InitialOptions.h" #include "common/InitialOptions.h"
#include "common/IOModesController.h" #include "common/IOModesController.h"
#include "common/CutterLayout.h" #include "common/CutterLayout.h"
#include "MemoryDockWidget.h" #include "MemoryDockWidget.h"
#include "tools/bindiff/DiffLoadDialog.h"
#include <memory> #include <memory>
@ -164,6 +164,7 @@ private slots:
void addExtraHexdump(); void addExtraHexdump();
void addExtraDisassembly(); void addExtraDisassembly();
void addExtraDecompiler(); void addExtraDecompiler();
void startDiffing();
void on_actionRefresh_Panels_triggered(); void on_actionRefresh_Panels_triggered();
@ -271,6 +272,7 @@ private:
CallGraphWidget *callGraphDock = nullptr; CallGraphWidget *callGraphDock = nullptr;
CallGraphWidget *globalCallGraphDock = nullptr; CallGraphWidget *globalCallGraphDock = nullptr;
CutterDockWidget *heapDock = nullptr; CutterDockWidget *heapDock = nullptr;
DiffLoadDialog *diffLoadDialog = nullptr;
QMenu *disassemblyContextMenuExtensions = nullptr; QMenu *disassemblyContextMenuExtensions = nullptr;
QMenu *addressableContextMenuExtensions = nullptr; QMenu *addressableContextMenuExtensions = nullptr;
@ -335,7 +337,7 @@ private:
QSharedPointer<RizinTask> task; QSharedPointer<RizinTask> task;
RizinTaskDialog *taskDialog = nullptr; RizinTaskDialog *taskDialog = nullptr;
BinDiffDialog *binDiffDialog = nullptr; DiffLoadDialog *binDiffDialog = nullptr;
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -1,137 +0,0 @@
#include "core/Cutter.h"
#include "BinDiffDialog.h"
#include "ui_BinDiffDialog.h"
#include "common/Configuration.h"
#include "common/BugReporting.h"
#include <QUrl>
#include <QTimer>
#include <QEventLoop>
#include <QJsonObject>
#include <QProgressBar>
#include <QProgressDialog>
#include <UpdateWorker.h>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkAccessManager>
#include "CutterConfig.h"
typedef struct {
QColor perfect;
QColor partial;
QColor none;
} DiffColors;
inline QString doubleToString(double number)
{
return QString::asprintf("%.6f", number);
}
inline QTableWidgetItem *newColoredCell(QString text, double similarity, const DiffColors *colors) {
auto item = new QTableWidgetItem(text);
if (similarity >= 1.0) {
item->setBackground(colors->perfect);
} else if (similarity >= RZ_ANALYSIS_SIMILARITY_THRESHOLD) {
item->setBackground(colors->partial);
} else {
item->setBackground(colors->none);
}
item->setForeground(Qt::black);
return item;
}
BinDiffDialog::BinDiffDialog(RzAnalysisMatchResult *result, QWidget *parent) : QDialog(parent), ui(new Ui::BinDiffDialog)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
void *ptr;
RzListIter *iter = nullptr;
RzAnalysisMatchPair *pair = nullptr;
const RzAnalysisFunction *fcn_a = nullptr, *fcn_b = nullptr;
const DiffColors colors = {
.perfect = Config()->getColor("gui.match.perfect"),
.partial = Config()->getColor("gui.match.partial"),
.none = Config()->getColor("gui.match.none"),
};
size_t n_raws = rz_list_length(result->matches);
n_raws += rz_list_length(result->unmatch_a);
n_raws += rz_list_length(result->unmatch_b);
QStringList tableHeader = {
tr("name"), tr("size"), tr("addr"),
tr("type"), tr("similarity"),
tr("addr"), tr("size"), tr("name")
};
ui->resultTable->setRowCount(n_raws);
ui->resultTable->setColumnCount(8);
ui->resultTable->setHorizontalHeaderLabels(tableHeader);
ui->resultTable->verticalHeader()->setVisible(false);
ui->resultTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
n_raws = 0;
rz_list_foreach(result->matches, iter, ptr) {
pair = static_cast<RzAnalysisMatchPair *>(ptr);
fcn_a = static_cast<const RzAnalysisFunction *>(pair->pair_a);
fcn_b = static_cast<const RzAnalysisFunction *>(pair->pair_b);
QString size_a = RzSizeString(rz_analysis_function_realsize(fcn_a));
QString size_b = RzSizeString(rz_analysis_function_realsize(fcn_b));
QString addr_a = RzAddressString(fcn_a->addr);
QString addr_b = RzAddressString(fcn_b->addr);
QString simtype = RZ_ANALYSIS_SIMILARITY_TYPE_STR(pair->similarity);
QString similarity = doubleToString(pair->similarity);
ui->resultTable->setItem(n_raws, ColumnSourceName, newColoredCell(fcn_a->name, pair->similarity, &colors));
ui->resultTable->setItem(n_raws, ColumnSourceSize, newColoredCell(size_a, pair->similarity, &colors));
ui->resultTable->setItem(n_raws, ColumnSourceAddr, newColoredCell(addr_a, pair->similarity, &colors));
ui->resultTable->setItem(n_raws, ColumnSimilarityType, newColoredCell(simtype, pair->similarity, &colors));
ui->resultTable->setItem(n_raws, ColumnSimilarityNum, newColoredCell(similarity, pair->similarity, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchAddr, newColoredCell(addr_b, pair->similarity, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchSize, newColoredCell(size_b, pair->similarity, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchName, newColoredCell(fcn_b->name, pair->similarity, &colors));
n_raws++;
}
rz_list_foreach(result->unmatch_a, iter, ptr) {
fcn_a = static_cast<RzAnalysisFunction *>(ptr);
QString size_a = RzSizeString(rz_analysis_function_realsize(fcn_a));
QString addr_a = RzAddressString(fcn_a->addr);
ui->resultTable->setItem(n_raws, ColumnSourceName, newColoredCell(fcn_a->name, 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnSourceSize, newColoredCell(size_a, 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnSourceAddr, newColoredCell(addr_a, 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnSimilarityType, newColoredCell(RZ_ANALYSIS_SIMILARITY_UNLIKE_STR, 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnSimilarityNum, newColoredCell("0.000000", 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchAddr, newColoredCell("------", 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchSize, newColoredCell("------", 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchName, newColoredCell("------", 0.0, &colors));
n_raws++;
}
rz_list_foreach(result->unmatch_b, iter, ptr) {
fcn_b = static_cast<RzAnalysisFunction *>(ptr);
QString size_b = RzSizeString(rz_analysis_function_realsize(fcn_b));
QString addr_b = RzAddressString(fcn_b->addr);
ui->resultTable->setItem(n_raws, ColumnSourceName, newColoredCell("------", 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnSourceSize, newColoredCell("------", 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnSourceAddr, newColoredCell("------", 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnSimilarityType, newColoredCell(RZ_ANALYSIS_SIMILARITY_UNLIKE_STR, 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnSimilarityNum, newColoredCell("0.000000", 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchAddr, newColoredCell(fcn_b->name, 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchSize, newColoredCell(size_b, 0.0, &colors));
ui->resultTable->setItem(n_raws, ColumnMatchName, newColoredCell(addr_b, 0.0, &colors));
n_raws++;
}
}
BinDiffDialog::~BinDiffDialog() {}
void BinDiffDialog::on_buttonBox_rejected()
{
close();
}

View File

@ -1,37 +0,0 @@
#ifndef BINDIFFDIALOG_H
#define BINDIFFDIALOG_H
#include <QDialog>
#include <memory>
#include <QtNetwork/QNetworkReply>
namespace Ui {
class BinDiffDialog;
}
class BinDiffDialog : public QDialog
{
Q_OBJECT
public:
explicit BinDiffDialog(RzAnalysisMatchResult *result, QWidget *parent = nullptr);
~BinDiffDialog();
private slots:
void on_buttonBox_rejected();
private:
enum {
ColumnSourceName = 0,
ColumnSourceSize,
ColumnSourceAddr,
ColumnSimilarityType,
ColumnSimilarityNum,
ColumnMatchAddr,
ColumnMatchSize,
ColumnMatchName
} BinDiffTableColumn;
std::unique_ptr<Ui::BinDiffDialog> ui;
};
#endif // BINDIFFDIALOG_H

View File

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BinDiffDialog</class>
<widget class="QDialog" name="BinDiffDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>935</width>
<height>554</height>
</rect>
</property>
<property name="windowTitle">
<string>Cutter Binary Diffing Tool</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1013</width>
<height>22</height>
</rect>
</property>
<property name="defaultUp">
<bool>false</bool>
</property>
<property name="nativeMenuBar">
<bool>true</bool>
</property>
<widget class="QMenu" name="menuExport">
<property name="title">
<string>Export</string>
</property>
</widget>
<addaction name="menuExport"/>
</widget>
</item>
<item>
<widget class="QTableWidget" name="resultTable"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -16,7 +16,7 @@ BaseFindDialog::BaseFindDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Ba
ui->nCoresCombo->clear(); ui->nCoresCombo->clear();
for (size_t i = n_cores; i > 0; i--) { for (size_t i = n_cores; i > 0; i--) {
if (n_cores == i) { if (n_cores == i) {
ui->nCoresCombo->addItem("All Cores"); ui->nCoresCombo->addItem(tr("All CPU Cores"));
continue; continue;
} }
ui->nCoresCombo->addItem(QString::number(i)); ui->nCoresCombo->addItem(QString::number(i));

View File

@ -1,6 +1,8 @@
#include "DiffLoadDialog.h" #include "DiffLoadDialog.h"
#include "ui_DiffLoadDialog.h" #include "ui_DiffLoadDialog.h"
#include "DiffWaitDialog.h"
#include <core/Cutter.h> #include <core/Cutter.h>
#include <rz_th.h> #include <rz_th.h>
@ -17,6 +19,13 @@ DiffLoadDialog::DiffLoadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Di
ui->lineEditDiffFile->setReadOnly(true); ui->lineEditDiffFile->setReadOnly(true);
ui->lineEditDiffFile->setText(""); ui->lineEditDiffFile->setText("");
ui->comboBoxAnalysis->addItem(tr("Basic"));
ui->comboBoxAnalysis->addItem(tr("Auto"));
ui->comboBoxAnalysis->addItem(tr("Experimental"));
auto index = ui->comboBoxAnalysis->findData(tr("Auto"), Qt::DisplayRole);
ui->comboBoxAnalysis->setCurrentIndex(index);
} }
DiffLoadDialog::~DiffLoadDialog() {} DiffLoadDialog::~DiffLoadDialog() {}
@ -31,6 +40,11 @@ QString DiffLoadDialog::getPreviousDiffFile() const
return ui->lineEditDiffFile->text(); return ui->lineEditDiffFile->text();
} }
int DiffLoadDialog::getLevel() const
{
return ui->comboBoxAnalysis->currentIndex();
}
void DiffLoadDialog::on_buttonDiffOpen_clicked() void DiffLoadDialog::on_buttonDiffOpen_clicked()
{ {
QFileDialog dialog(this); QFileDialog dialog(this);
@ -69,26 +83,9 @@ void DiffLoadDialog::on_buttonFileOpen_clicked()
ui->lineEditFileName->setText(fileName); ui->lineEditFileName->setText(fileName);
} }
void DiffLoadDialog::openErrorBox(QString errorMessage)
{
QMessageBox mb(this);
mb.setIcon(QMessageBox::Warning);
mb.setStandardButtons(QMessageBox::Ok);
mb.setWindowTitle(tr("Error"));
mb.setText(errorMessage);
mb.exec();
}
void DiffLoadDialog::on_buttonBox_accepted() void DiffLoadDialog::on_buttonBox_accepted()
{ {
QString fileName = getFileToOpen(); emit startDiffing();
if (fileName.isEmpty()) {
openErrorBox(tr("The compare file was not selected."));
return;
}
} }
void DiffLoadDialog::on_buttonBox_rejected() void DiffLoadDialog::on_buttonBox_rejected() {}
{
// cancel
}

View File

@ -21,6 +21,10 @@ public:
QString getFileToOpen() const; QString getFileToOpen() const;
QString getPreviousDiffFile() const; QString getPreviousDiffFile() const;
int getLevel() const;
signals:
void startDiffing();
private slots: private slots:
void on_buttonDiffOpen_clicked(); void on_buttonDiffOpen_clicked();
@ -30,8 +34,6 @@ private slots:
private: private:
std::unique_ptr<Ui::DiffLoadDialog> ui; std::unique_ptr<Ui::DiffLoadDialog> ui;
void openErrorBox(QString errorMessage);
}; };
#endif // DIFF_LOAD_DIALOG_H #endif // DIFF_LOAD_DIALOG_H

View File

@ -10,7 +10,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>636</width> <width>636</width>
<height>142</height> <height>184</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -34,9 +34,6 @@
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLineEdit" name="lineEditDiffFile"/> <widget class="QLineEdit" name="lineEditDiffFile"/>
</item> </item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditFileName"/>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="fileToCompareLabel"> <widget class="QLabel" name="fileToCompareLabel">
<property name="sizePolicy"> <property name="sizePolicy">
@ -53,13 +50,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="2">
<widget class="QPushButton" name="buttonDiffOpen">
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
<item row="0" column="2"> <item row="0" column="2">
<widget class="QPushButton" name="buttonFileOpen"> <widget class="QPushButton" name="buttonFileOpen">
<property name="text"> <property name="text">
@ -83,6 +73,26 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditFileName"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="buttonDiffOpen">
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelAnalysisLevel">
<property name="text">
<string>Analysis Level</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxAnalysis"/>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View File

@ -0,0 +1,106 @@
#include "DiffWaitDialog.h"
#include "ui_DiffWaitDialog.h"
#include <QTime>
#include <core/Cutter.h>
#include <rz_util.h>
DiffWaitDialog::DiffWaitDialog(QWidget *parent)
: QDialog(parent), timer(parent), bDiff(new BinDiff()), ui(new Ui::DiffWaitDialog)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
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);
ui->lineEditNFuncs->setText("0");
ui->lineEditMatches->setText("0");
QTime zero(0, 0, 0, 0);
ui->lineEditElapsedTime->setText(zero.toString("hh:mm:ss"));
ui->lineEditEstimatedTime->setText(zero.toString("hh:mm:ss"));
}
DiffWaitDialog::~DiffWaitDialog()
{
if (bDiff->isRunning()) {
bDiff->cancel();
bDiff->wait();
}
}
QList<BinDiffMatchDescription> DiffWaitDialog::matches()
{
return bDiff->matches();
}
QList<FunctionDescription> DiffWaitDialog::mismatch(bool fileA)
{
return bDiff->mismatch(fileA);
}
void DiffWaitDialog::show(QString original, QString modified, int level)
{
connect(this, &DiffWaitDialog::cancelJob, bDiff.get(), &BinDiff::cancel);
connect(bDiff.get(), &BinDiff::progress, this, &DiffWaitDialog::onProgress);
connect(bDiff.get(), &BinDiff::complete, this, &DiffWaitDialog::onCompletion);
connect(&timer, &QTimer::timeout, this, &DiffWaitDialog::updateElapsedTime);
ui->lineEditOriginal->setText(original);
ui->lineEditModified->setText(modified);
bDiff->setAnalysisLevel(level);
bDiff->setFile(modified);
eTimer.restart();
timer.setSingleShot(false);
timer.start(1000);
bDiff->start();
this->QDialog::show();
}
void DiffWaitDialog::onProgress(BinDiffStatusDescription status)
{
int partial = status.total - status.nLeft;
ut32 progress = (100 * partial) / status.total;
ui->progressBar->setValue(progress);
ui->lineEditNFuncs->setText(QString::asprintf("%lu", status.nLeft));
ui->lineEditMatches->setText(QString::asprintf("%lu", status.nMatch));
double speed = ((double)partial) / ((double)eTimer.elapsed());
ut64 seconds = (((double)status.nLeft) / speed) / 1000ull;
int hours = seconds / 3600;
seconds -= (hours * 3600);
int minutes = seconds / 60;
seconds = seconds % 60;
QTime estimated(hours, minutes, seconds, 0);
ui->lineEditEstimatedTime->setText(estimated.toString("hh:mm:ss"));
}
void DiffWaitDialog::onCompletion()
{
timer.stop();
}
void DiffWaitDialog::updateElapsedTime()
{
ut64 seconds = eTimer.elapsed() / 1000ull;
int hours = seconds / 3600;
seconds -= (hours * 3600);
int minutes = seconds / 60;
seconds = seconds % 60;
QTime current(hours, minutes, seconds, 0);
ui->lineEditElapsedTime->setText(current.toString("hh:mm:ss"));
}
void DiffWaitDialog::on_buttonBox_rejected()
{
timer.stop();
emit cancelJob();
}

View File

@ -0,0 +1,48 @@
#ifndef DIFF_WAIT_DIALOG_H
#define DIFF_WAIT_DIALOG_H
#include <QDialog>
#include <QListWidgetItem>
#include <QProgressBar>
#include <QTimer>
#include <QElapsedTimer>
#include <memory>
#include <core/Cutter.h>
namespace Ui {
class DiffWaitDialog;
}
class DiffWaitDialog : public QDialog
{
Q_OBJECT
public:
explicit DiffWaitDialog(QWidget *parent = nullptr);
~DiffWaitDialog();
void show(QString original, QString modified, int level);
QList<BinDiffMatchDescription> matches();
QList<FunctionDescription> mismatch(bool fileA);
public slots:
void onProgress(BinDiffStatusDescription status);
void onCompletion();
void updateElapsedTime();
signals:
void cancelJob();
private slots:
void on_buttonBox_rejected();
private:
QElapsedTimer eTimer;
QTimer timer;
std::unique_ptr<BinDiff> bDiff;
std::unique_ptr<Ui::DiffWaitDialog> ui;
};
#endif // DIFF_WAIT_DIALOG_H

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DiffWaitDialog</class>
<widget class="QDialog" name="DiffWaitDialog">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>524</width>
<height>342</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Performing binary diffing</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<layout class="QVBoxLayout" name="mainVerticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget class="QLineEdit" name="lineEditElapsedTime"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditModified"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelElapsedTime">
<property name="text">
<string>Elapsed Time</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelModified">
<property name="text">
<string>Modified File</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelMatches">
<property name="text">
<string>Matches</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditOriginal"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelOrignal">
<property name="text">
<string>Original File</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="lineEditNFuncs"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelNFuncs">
<property name="text">
<string>Functions left to compare</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEditMatches"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelEstimatedTime">
<property name="text">
<string>Estimated Time</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEditEstimatedTime"/>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<action name="actionRemoveItem">
<property name="text">
<string>Remove item</string>
</property>
</action>
<action name="actionRemoveAll">
<property name="text">
<string>Remove all</string>
</property>
<property name="toolTip">
<string>Remove all</string>
</property>
</action>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DiffWaitDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>240</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>254</y>
</hint>
</hints>
</connection>
</connections>
</ui>