mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-31 08:37:26 +00:00
Moving to proper bindiff
This commit is contained in:
parent
39532d312c
commit
439b268927
@ -7,6 +7,7 @@ set(SOURCES
|
|||||||
core/CutterJson.cpp
|
core/CutterJson.cpp
|
||||||
core/RizinCpp.cpp
|
core/RizinCpp.cpp
|
||||||
core/Basefind.cpp
|
core/Basefind.cpp
|
||||||
|
core/BinDiff.cpp
|
||||||
dialogs/EditStringDialog.cpp
|
dialogs/EditStringDialog.cpp
|
||||||
dialogs/WriteCommandsDialogs.cpp
|
dialogs/WriteCommandsDialogs.cpp
|
||||||
widgets/DisassemblerGraphView.cpp
|
widgets/DisassemblerGraphView.cpp
|
||||||
@ -58,7 +59,6 @@ set(SOURCES
|
|||||||
widgets/DecompilerWidget.cpp
|
widgets/DecompilerWidget.cpp
|
||||||
widgets/VisualNavbar.cpp
|
widgets/VisualNavbar.cpp
|
||||||
widgets/GraphView.cpp
|
widgets/GraphView.cpp
|
||||||
dialogs/bindiff/BinDiffDialog.cpp
|
|
||||||
dialogs/preferences/PreferencesDialog.cpp
|
dialogs/preferences/PreferencesDialog.cpp
|
||||||
dialogs/preferences/AppearanceOptionsWidget.cpp
|
dialogs/preferences/AppearanceOptionsWidget.cpp
|
||||||
dialogs/preferences/GraphOptionsWidget.cpp
|
dialogs/preferences/GraphOptionsWidget.cpp
|
||||||
@ -156,6 +156,7 @@ set(SOURCES
|
|||||||
tools/basefind/BaseFindDialog.cpp
|
tools/basefind/BaseFindDialog.cpp
|
||||||
tools/basefind/BaseFindSearchDialog.cpp
|
tools/basefind/BaseFindSearchDialog.cpp
|
||||||
tools/basefind/BaseFindResultsDialog.cpp
|
tools/basefind/BaseFindResultsDialog.cpp
|
||||||
|
tools/bindiff/DiffLoadDialog.cpp
|
||||||
)
|
)
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
core/Cutter.h
|
core/Cutter.h
|
||||||
@ -164,6 +165,7 @@ set(HEADER_FILES
|
|||||||
core/CutterJson.h
|
core/CutterJson.h
|
||||||
core/RizinCpp.h
|
core/RizinCpp.h
|
||||||
core/Basefind.h
|
core/Basefind.h
|
||||||
|
core/BinDiff.h
|
||||||
dialogs/EditStringDialog.h
|
dialogs/EditStringDialog.h
|
||||||
dialogs/WriteCommandsDialogs.h
|
dialogs/WriteCommandsDialogs.h
|
||||||
widgets/DisassemblerGraphView.h
|
widgets/DisassemblerGraphView.h
|
||||||
@ -214,7 +216,6 @@ set(HEADER_FILES
|
|||||||
widgets/DecompilerWidget.h
|
widgets/DecompilerWidget.h
|
||||||
widgets/VisualNavbar.h
|
widgets/VisualNavbar.h
|
||||||
widgets/GraphView.h
|
widgets/GraphView.h
|
||||||
dialogs/bindiff/BinDiffDialog.h
|
|
||||||
dialogs/preferences/PreferencesDialog.h
|
dialogs/preferences/PreferencesDialog.h
|
||||||
dialogs/preferences/AppearanceOptionsWidget.h
|
dialogs/preferences/AppearanceOptionsWidget.h
|
||||||
dialogs/preferences/PreferenceCategory.h
|
dialogs/preferences/PreferenceCategory.h
|
||||||
@ -321,6 +322,7 @@ set(HEADER_FILES
|
|||||||
tools/basefind/BaseFindDialog.h
|
tools/basefind/BaseFindDialog.h
|
||||||
tools/basefind/BaseFindSearchDialog.h
|
tools/basefind/BaseFindSearchDialog.h
|
||||||
tools/basefind/BaseFindResultsDialog.h
|
tools/basefind/BaseFindResultsDialog.h
|
||||||
|
tools/bindiff/DiffLoadDialog.h
|
||||||
)
|
)
|
||||||
set(UI_FILES
|
set(UI_FILES
|
||||||
dialogs/AboutDialog.ui
|
dialogs/AboutDialog.ui
|
||||||
@ -347,7 +349,6 @@ set(UI_FILES
|
|||||||
widgets/GlobalsWidget.ui
|
widgets/GlobalsWidget.ui
|
||||||
widgets/StringsWidget.ui
|
widgets/StringsWidget.ui
|
||||||
widgets/HexdumpWidget.ui
|
widgets/HexdumpWidget.ui
|
||||||
dialogs/bindiff/BinDiffDialog.ui
|
|
||||||
dialogs/preferences/PreferencesDialog.ui
|
dialogs/preferences/PreferencesDialog.ui
|
||||||
dialogs/preferences/AppearanceOptionsWidget.ui
|
dialogs/preferences/AppearanceOptionsWidget.ui
|
||||||
dialogs/preferences/GraphOptionsWidget.ui
|
dialogs/preferences/GraphOptionsWidget.ui
|
||||||
@ -396,6 +397,7 @@ set(UI_FILES
|
|||||||
tools/basefind/BaseFindDialog.ui
|
tools/basefind/BaseFindDialog.ui
|
||||||
tools/basefind/BaseFindSearchDialog.ui
|
tools/basefind/BaseFindSearchDialog.ui
|
||||||
tools/basefind/BaseFindResultsDialog.ui
|
tools/basefind/BaseFindResultsDialog.ui
|
||||||
|
tools/bindiff/DiffLoadDialog.ui
|
||||||
)
|
)
|
||||||
set(QRC_FILES
|
set(QRC_FILES
|
||||||
resources.qrc
|
resources.qrc
|
||||||
|
120
src/core/BinDiff.cpp
Normal file
120
src/core/BinDiff.cpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include "BinDiff.h"
|
||||||
|
|
||||||
|
bool BinDiff::threadCallback(const size_t nLeft, const size_t nMatch, void *user)
|
||||||
|
{
|
||||||
|
auto bdiff = reinterpret_cast<BinDiff *>(user);
|
||||||
|
return bdiff->updateProgress(nLeft, nMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
BinDiff::BinDiff(CutterCore *core)
|
||||||
|
: core(core),
|
||||||
|
result(nullptr),
|
||||||
|
continue_run(true),
|
||||||
|
maxTotal(1)
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||||
|
,
|
||||||
|
mutex(QMutex::Recursive)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BinDiff::~BinDiff()
|
||||||
|
{
|
||||||
|
cancel();
|
||||||
|
wait();
|
||||||
|
rz_analysis_match_result_free(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinDiff::run(QString fileName)
|
||||||
|
{
|
||||||
|
mutex.lock();
|
||||||
|
rz_analysis_match_result_free(result);
|
||||||
|
result = nullptr;
|
||||||
|
continue_run = true;
|
||||||
|
maxTotal = 1; // maxTotal must be at least 1.
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
|
core->coreMutex.lock();
|
||||||
|
result = core->diffNewFile(fileName, threadCallback, this);
|
||||||
|
core->coreMutex.unlock();
|
||||||
|
|
||||||
|
emit complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinDiff::cancel()
|
||||||
|
{
|
||||||
|
mutex.lock();
|
||||||
|
continue_run = false;
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setFunctionDescription(FunctionDescription *desc, const RzAnalysisFunction *func)
|
||||||
|
{
|
||||||
|
desc->offset = func->addr;
|
||||||
|
desc->linearSize = rz_analysis_function_linear_size((RzAnalysisFunction *)func);
|
||||||
|
desc->nargs = rz_analysis_arg_count((RzAnalysisFunction *)func);
|
||||||
|
desc->nlocals = rz_analysis_var_local_count((RzAnalysisFunction *)func);
|
||||||
|
desc->nbbs = rz_list_length(func->bbs);
|
||||||
|
desc->calltype = func->cc ? QString::fromUtf8(func->cc) : QString();
|
||||||
|
desc->name = func->name ? QString::fromUtf8(func->name) : QString();
|
||||||
|
desc->edges = rz_analysis_function_count_edges(func, nullptr);
|
||||||
|
desc->stackframe = func->maxstack;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<BinDiffMatchDescription> BinDiff::matches()
|
||||||
|
{
|
||||||
|
QList<BinDiffMatchDescription> pairs;
|
||||||
|
RzAnalysisMatchPair *pair = nullptr;
|
||||||
|
RzListIter *it = nullptr;
|
||||||
|
const RzAnalysisFunction *fcn_a = nullptr;
|
||||||
|
const RzAnalysisFunction *fcn_b = nullptr;
|
||||||
|
|
||||||
|
CutterRzListForeach (result->matches, it, RzAnalysisMatchPair, pair) {
|
||||||
|
BinDiffMatchDescription desc;
|
||||||
|
fcn_a = static_cast<const RzAnalysisFunction *>(pair->pair_a);
|
||||||
|
fcn_b = static_cast<const RzAnalysisFunction *>(pair->pair_b);
|
||||||
|
|
||||||
|
setFunctionDescription(&desc.original, fcn_a);
|
||||||
|
setFunctionDescription(&desc.modified, fcn_b);
|
||||||
|
|
||||||
|
desc.simtype = RZ_ANALYSIS_SIMILARITY_TYPE_STR(pair->similarity);
|
||||||
|
desc.similarity = pair->similarity;
|
||||||
|
|
||||||
|
pairs << desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<FunctionDescription> BinDiff::mismatch(bool fileA)
|
||||||
|
{
|
||||||
|
QList<FunctionDescription> list;
|
||||||
|
RzAnalysisFunction *func = nullptr;
|
||||||
|
RzList *unmatch = fileA ? result->unmatch_a : result->unmatch_b;
|
||||||
|
RzListIter *it = nullptr;
|
||||||
|
|
||||||
|
CutterRzListForeach (unmatch, it, RzAnalysisFunction, func) {
|
||||||
|
FunctionDescription desc;
|
||||||
|
setFunctionDescription(&desc, func);
|
||||||
|
list << desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinDiff::updateProgress(const size_t nLeft, const size_t nMatch)
|
||||||
|
{
|
||||||
|
mutex.lock();
|
||||||
|
|
||||||
|
if (maxTotal < nMatch) {
|
||||||
|
maxTotal = nMatch;
|
||||||
|
}
|
||||||
|
if (maxTotal < nLeft) {
|
||||||
|
maxTotal = nLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit progress(maxTotal, nLeft, nMatch);
|
||||||
|
bool ret = continue_run;
|
||||||
|
mutex.unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
47
src/core/BinDiff.h
Normal file
47
src/core/BinDiff.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef CUTTER_BINDIFF_CORE_H
|
||||||
|
#define CUTTER_BINDIFF_CORE_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include "CutterDescriptions.h"
|
||||||
|
#include <rz_analysis.h>
|
||||||
|
|
||||||
|
class CutterCore;
|
||||||
|
|
||||||
|
class BinDiff : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BinDiff(CutterCore *core);
|
||||||
|
virtual ~BinDiff();
|
||||||
|
|
||||||
|
void run(QString fileName);
|
||||||
|
QList<BinDiffMatchDescription> matches();
|
||||||
|
QList<FunctionDescription> mismatch(bool fileA);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void cancel();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void progress(const size_t total, const size_t nLeft, const size_t nMatch);
|
||||||
|
void complete();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CutterCore *const core;
|
||||||
|
RzAnalysisMatchResult *result;
|
||||||
|
bool continue_run;
|
||||||
|
size_t maxTotal;
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||||
|
QMutex mutex;
|
||||||
|
#else
|
||||||
|
QRecursiveMutex mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool updateProgress(const size_t nLeft, const size_t nMatch);
|
||||||
|
static bool threadCallback(const size_t nLeft, const size_t nMatch, void *user);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CUTTER_BINDIFF_CORE_H
|
@ -396,7 +396,7 @@ QString CutterCore::getFunctionExecOut(const std::function<bool(RzCore *)> &fcn,
|
|||||||
o = rz_cons_get_buffer();
|
o = rz_cons_get_buffer();
|
||||||
|
|
||||||
rz_cons_pop();
|
rz_cons_pop();
|
||||||
rz_cons_echo(NULL);
|
rz_cons_echo(nullptr);
|
||||||
|
|
||||||
clean_return:
|
clean_return:
|
||||||
if (offset != core->offset) {
|
if (offset != core->offset) {
|
||||||
@ -487,7 +487,7 @@ QString CutterCore::cmdRaw(const char *cmd)
|
|||||||
|
|
||||||
// cleaning up
|
// cleaning up
|
||||||
rz_cons_pop();
|
rz_cons_pop();
|
||||||
rz_cons_echo(NULL);
|
rz_cons_echo(nullptr);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -603,14 +603,14 @@ bool CutterCore::loadFile(QString path, ut64 baddr, ut64 mapaddr, int perms, int
|
|||||||
// load RzBin information
|
// load RzBin information
|
||||||
// XXX only for sub-bins
|
// XXX only for sub-bins
|
||||||
rz_core_bin_load(core, path.toUtf8(), baddr);
|
rz_core_bin_load(core, path.toUtf8(), baddr);
|
||||||
rz_bin_select_idx(core->bin, NULL, idx);
|
rz_bin_select_idx(core->bin, nullptr, idx);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// Not loading RzBin info coz va = false
|
// Not loading RzBin info coz va = false
|
||||||
}
|
}
|
||||||
|
|
||||||
auto iod = core->io ? core->io->desc : NULL;
|
auto iod = core->io ? core->io->desc : nullptr;
|
||||||
auto debug =
|
auto debug =
|
||||||
core->file && iod && (core->file->fd == iod->fd) && iod->plugin && iod->plugin->isdbg;
|
core->file && iod && (core->file->fd == iod->fd) && iod->plugin && iod->plugin->isdbg;
|
||||||
|
|
||||||
@ -856,7 +856,7 @@ QString CutterCore::getString(RVA addr, uint64_t len, RzStrEnc encoding, bool es
|
|||||||
opt.encoding = encoding;
|
opt.encoding = encoding;
|
||||||
opt.escape_nl = escape_nl;
|
opt.escape_nl = escape_nl;
|
||||||
auto seek = seekTemp(addr);
|
auto seek = seekTemp(addr);
|
||||||
return fromOwnedCharPtr(rz_str_stringify_raw_buffer(&opt, NULL));
|
return fromOwnedCharPtr(rz_str_stringify_raw_buffer(&opt, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CutterCore::getMetaString(RVA addr)
|
QString CutterCore::getMetaString(RVA addr)
|
||||||
@ -1093,13 +1093,13 @@ void CutterCore::createSignature(const QString &filepath)
|
|||||||
ut64 CutterCore::math(const QString &expr)
|
ut64 CutterCore::math(const QString &expr)
|
||||||
{
|
{
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
return rz_num_math(core ? core->num : NULL, expr.toUtf8().constData());
|
return rz_num_math(core ? core->num : nullptr, expr.toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
ut64 CutterCore::num(const QString &expr)
|
ut64 CutterCore::num(const QString &expr)
|
||||||
{
|
{
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
return rz_num_get(core ? core->num : NULL, expr.toUtf8().constData());
|
return rz_num_get(core ? core->num : nullptr, expr.toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CutterCore::itoa(ut64 num, int rdx)
|
QString CutterCore::itoa(ut64 num, int rdx)
|
||||||
@ -1902,7 +1902,7 @@ void CutterCore::setCurrentDebugThread(int tid)
|
|||||||
if (!asyncTask(
|
if (!asyncTask(
|
||||||
[=](RzCore *core) {
|
[=](RzCore *core) {
|
||||||
rz_debug_select(core->dbg, core->dbg->pid, tid);
|
rz_debug_select(core->dbg, core->dbg->pid, tid);
|
||||||
return (void *)NULL;
|
return (void *)nullptr;
|
||||||
},
|
},
|
||||||
debugTask)) {
|
debugTask)) {
|
||||||
return;
|
return;
|
||||||
@ -1929,7 +1929,7 @@ void CutterCore::setCurrentDebugProcess(int pid)
|
|||||||
[=](RzCore *core) {
|
[=](RzCore *core) {
|
||||||
rz_debug_select(core->dbg, pid, core->dbg->tid);
|
rz_debug_select(core->dbg, pid, core->dbg->tid);
|
||||||
core->dbg->main_pid = pid;
|
core->dbg->main_pid = pid;
|
||||||
return (void *)NULL;
|
return (void *)nullptr;
|
||||||
},
|
},
|
||||||
debugTask)) {
|
debugTask)) {
|
||||||
return;
|
return;
|
||||||
@ -2004,7 +2004,7 @@ void CutterCore::startEmulation()
|
|||||||
asyncTask(
|
asyncTask(
|
||||||
[&](RzCore *core) {
|
[&](RzCore *core) {
|
||||||
rz_core_analysis_esil_reinit(core);
|
rz_core_analysis_esil_reinit(core);
|
||||||
rz_core_analysis_esil_init_mem(core, NULL, UT64_MAX, UT32_MAX);
|
rz_core_analysis_esil_init_mem(core, nullptr, UT64_MAX, UT32_MAX);
|
||||||
rz_core_analysis_esil_init_regs(core);
|
rz_core_analysis_esil_init_regs(core);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
},
|
},
|
||||||
@ -2180,7 +2180,7 @@ void CutterCore::stopDebug()
|
|||||||
|
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
if (currentlyEmulating) {
|
if (currentlyEmulating) {
|
||||||
rz_core_analysis_esil_init_mem_del(core, NULL, UT64_MAX, UT32_MAX);
|
rz_core_analysis_esil_init_mem_del(core, nullptr, UT64_MAX, UT32_MAX);
|
||||||
rz_core_analysis_esil_deinit(core);
|
rz_core_analysis_esil_deinit(core);
|
||||||
resetWriteCache();
|
resetWriteCache();
|
||||||
rz_core_debug_clear_register_flags(core);
|
rz_core_debug_clear_register_flags(core);
|
||||||
@ -2218,7 +2218,7 @@ void CutterCore::continueDebug()
|
|||||||
if (currentlyEmulating) {
|
if (currentlyEmulating) {
|
||||||
if (!asyncTask(
|
if (!asyncTask(
|
||||||
[](RzCore *core) {
|
[](RzCore *core) {
|
||||||
rz_core_esil_step(core, UT64_MAX, "0", NULL, false);
|
rz_core_esil_step(core, UT64_MAX, "0", nullptr, false);
|
||||||
rz_core_reg_update_flags(core);
|
rz_core_reg_update_flags(core);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
},
|
},
|
||||||
@ -2294,7 +2294,7 @@ void CutterCore::continueUntilDebug(ut64 offset)
|
|||||||
if (currentlyEmulating) {
|
if (currentlyEmulating) {
|
||||||
if (!asyncTask(
|
if (!asyncTask(
|
||||||
[=](RzCore *core) {
|
[=](RzCore *core) {
|
||||||
rz_core_esil_step(core, offset, NULL, NULL, false);
|
rz_core_esil_step(core, offset, nullptr, nullptr, false);
|
||||||
rz_core_reg_update_flags(core);
|
rz_core_reg_update_flags(core);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
},
|
},
|
||||||
@ -2380,7 +2380,7 @@ void CutterCore::continueUntilSyscall()
|
|||||||
[](void *x) { rz_debug_stop(reinterpret_cast<RzDebug *>(x)); },
|
[](void *x) { rz_debug_stop(reinterpret_cast<RzDebug *>(x)); },
|
||||||
core->dbg);
|
core->dbg);
|
||||||
rz_reg_arena_swap(core->dbg->reg, true);
|
rz_reg_arena_swap(core->dbg->reg, true);
|
||||||
rz_debug_continue_syscalls(core->dbg, NULL, 0);
|
rz_debug_continue_syscalls(core->dbg, nullptr, 0);
|
||||||
rz_cons_break_pop();
|
rz_cons_break_pop();
|
||||||
rz_core_dbg_follow_seek_register(core);
|
rz_core_dbg_follow_seek_register(core);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -2410,7 +2410,7 @@ void CutterCore::stepDebug()
|
|||||||
if (currentlyEmulating) {
|
if (currentlyEmulating) {
|
||||||
if (!asyncTask(
|
if (!asyncTask(
|
||||||
[](RzCore *core) {
|
[](RzCore *core) {
|
||||||
rz_core_esil_step(core, UT64_MAX, NULL, NULL, false);
|
rz_core_esil_step(core, UT64_MAX, nullptr, nullptr, false);
|
||||||
rz_core_reg_update_flags(core);
|
rz_core_reg_update_flags(core);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
},
|
},
|
||||||
@ -2635,7 +2635,7 @@ void CutterCore::stopTraceSession()
|
|||||||
if (!asyncTask(
|
if (!asyncTask(
|
||||||
[](RzCore *core) {
|
[](RzCore *core) {
|
||||||
rz_debug_session_free(core->dbg->session);
|
rz_debug_session_free(core->dbg->session);
|
||||||
core->dbg->session = NULL;
|
core->dbg->session = nullptr;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
},
|
},
|
||||||
debugTask)) {
|
debugTask)) {
|
||||||
@ -3255,8 +3255,8 @@ QList<FlirtDescription> CutterCore::getSignaturesDB()
|
|||||||
{
|
{
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
|
|
||||||
void *ptr = NULL;
|
void *ptr = nullptr;
|
||||||
RzListIter *iter = NULL;
|
RzListIter *iter = nullptr;
|
||||||
QList<FlirtDescription> sigdb;
|
QList<FlirtDescription> sigdb;
|
||||||
|
|
||||||
RzList *list = rz_core_analysis_sigdb_list(core, true);
|
RzList *list = rz_core_analysis_sigdb_list(core, true);
|
||||||
@ -3451,7 +3451,7 @@ QList<SectionDescription> CutterCore::getAllSections()
|
|||||||
if (!digests) {
|
if (!digests) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const char *entropy = (const char *)ht_pp_find(digests, "entropy", NULL);
|
const char *entropy = (const char *)ht_pp_find(digests, "entropy", nullptr);
|
||||||
section.entropy = rz_str_get(entropy);
|
section.entropy = rz_str_get(entropy);
|
||||||
ht_pp_free(digests);
|
ht_pp_free(digests);
|
||||||
}
|
}
|
||||||
@ -4055,7 +4055,7 @@ void CutterCore::addGlobalVariable(RVA offset, QString name, QString typ)
|
|||||||
{
|
{
|
||||||
name = sanitizeStringForCommand(name);
|
name = sanitizeStringForCommand(name);
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
char *errmsg = NULL;
|
char *errmsg = nullptr;
|
||||||
RzType *globType = rz_type_parse_string_single(core->analysis->typedb->parser,
|
RzType *globType = rz_type_parse_string_single(core->analysis->typedb->parser,
|
||||||
typ.toStdString().c_str(), &errmsg);
|
typ.toStdString().c_str(), &errmsg);
|
||||||
if (errmsg) {
|
if (errmsg) {
|
||||||
@ -4084,7 +4084,7 @@ void CutterCore::modifyGlobalVariable(RVA offset, QString name, QString typ)
|
|||||||
if (name.compare(glob->name)) {
|
if (name.compare(glob->name)) {
|
||||||
rz_analysis_var_global_rename(core->analysis, glob->name, name.toStdString().c_str());
|
rz_analysis_var_global_rename(core->analysis, glob->name, name.toStdString().c_str());
|
||||||
}
|
}
|
||||||
char *errmsg = NULL;
|
char *errmsg = nullptr;
|
||||||
RzType *globType = rz_type_parse_string_single(core->analysis->typedb->parser,
|
RzType *globType = rz_type_parse_string_single(core->analysis->typedb->parser,
|
||||||
typ.toStdString().c_str(), &errmsg);
|
typ.toStdString().c_str(), &errmsg);
|
||||||
if (errmsg) {
|
if (errmsg) {
|
||||||
@ -4260,7 +4260,7 @@ QList<DisassemblyLine> CutterCore::disassembleLines(RVA offset, int lines)
|
|||||||
rz_cons_singleton()->is_html = false;
|
rz_cons_singleton()->is_html = false;
|
||||||
rz_cons_singleton()->was_html = true;
|
rz_cons_singleton()->was_html = true;
|
||||||
}
|
}
|
||||||
rz_core_print_disasm(core, offset, core->block, core->blocksize, lines, NULL, &options);
|
rz_core_print_disasm(core, offset, core->block, core->blocksize, lines, nullptr, &options);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<DisassemblyLine> r;
|
QList<DisassemblyLine> r;
|
||||||
@ -4387,7 +4387,7 @@ QString CutterCore::getVersionInformation()
|
|||||||
{ "rz_syscall", &rz_syscall_version },
|
{ "rz_syscall", &rz_syscall_version },
|
||||||
{ "rz_util", &rz_util_version },
|
{ "rz_util", &rz_util_version },
|
||||||
/* ... */
|
/* ... */
|
||||||
{ NULL, NULL }
|
{ nullptr, nullptr }
|
||||||
};
|
};
|
||||||
versionInfo.append(getRizinVersionReadable());
|
versionInfo.append(getRizinVersionReadable());
|
||||||
versionInfo.append("\n");
|
versionInfo.append("\n");
|
||||||
@ -4564,9 +4564,12 @@ bool CutterCore::isWriteModeEnabled()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RzAnalysisMatchResult *CutterCore::matchFunctionsFromNewFile(const QString &filePath) {
|
RzAnalysisMatchResult *CutterCore::diffNewFile(const QString &filePath,
|
||||||
RzList *fcns_a = NULL, *fcns_b = NULL;
|
RzAnalysisMatchThreadInfoCb callback, void *user)
|
||||||
RzAnalysisMatchResult *result = NULL;
|
{
|
||||||
|
RzList *fcns_a = nullptr, *fcns_b = nullptr;
|
||||||
|
RzAnalysisMatchResult *result = nullptr;
|
||||||
|
RzAnalysisMatchOpt opts;
|
||||||
RzListIter *iter;
|
RzListIter *iter;
|
||||||
RzConfigNode *node;
|
RzConfigNode *node;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
@ -4590,7 +4593,7 @@ RzAnalysisMatchResult *CutterCore::matchFunctionsFromNewFile(const QString &file
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rz_core_bin_load(core_b, NULL, UT64_MAX)) {
|
if (!rz_core_bin_load(core_b, nullptr, UT64_MAX)) {
|
||||||
qWarning() << "cannot load bin " << filePath;
|
qWarning() << "cannot load bin " << filePath;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -4600,18 +4603,18 @@ RzAnalysisMatchResult *CutterCore::matchFunctionsFromNewFile(const QString &file
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rz_list_foreach (core_a->config->nodes, iter, ptr) {
|
rz_list_foreach(core_a->config->nodes, iter, ptr)
|
||||||
|
{
|
||||||
node = reinterpret_cast<RzConfigNode *>(ptr);
|
node = reinterpret_cast<RzConfigNode *>(ptr);
|
||||||
if (!strcmp(node->name, "scr.color") ||
|
if (!strcmp(node->name, "scr.color") || !strcmp(node->name, "scr.interactive")
|
||||||
!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");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
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, NULL)) {
|
if (!rz_core_analysis_everything(core_b, false, nullptr)) {
|
||||||
qWarning() << "cannot analyze binary " << filePath;
|
qWarning() << "cannot analyze binary " << filePath;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -4631,10 +4634,15 @@ RzAnalysisMatchResult *CutterCore::matchFunctionsFromNewFile(const QString &file
|
|||||||
rz_list_sort(fcns_a, core_a->analysis->columnSort);
|
rz_list_sort(fcns_a, core_a->analysis->columnSort);
|
||||||
rz_list_sort(fcns_b, core_b->analysis->columnSort);
|
rz_list_sort(fcns_b, core_b->analysis->columnSort);
|
||||||
|
|
||||||
|
opts.analysis_a = core_a->analysis;
|
||||||
|
opts.analysis_b = core_b->analysis;
|
||||||
|
opts.callback = callback;
|
||||||
|
opts.user = user;
|
||||||
|
|
||||||
// calculate all the matches between the functions of the 2 different core files.
|
// calculate all the matches between the functions of the 2 different core files.
|
||||||
result = rz_analysis_match_functions_2(core_a->analysis, fcns_a, core_b->analysis, fcns_b);
|
result = rz_analysis_match_functions(fcns_a, fcns_b, &opts);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
qWarning() << "failed to perform the function matching operation";
|
qWarning() << "failed to perform the function matching operation or job was cancelled.";
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4647,10 +4655,9 @@ fail:
|
|||||||
rz_list_free(fcns_b);
|
rz_list_free(fcns_b);
|
||||||
rz_core_free(this->core_b);
|
rz_core_free(this->core_b);
|
||||||
this->core_b = nullptr;
|
this->core_b = nullptr;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get a compact disassembly preview for tooltips
|
* @brief get a compact disassembly preview for tooltips
|
||||||
* @param address - the address from which to print the disassembly
|
* @param address - the address from which to print the disassembly
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "core/CutterDescriptions.h"
|
#include "core/CutterDescriptions.h"
|
||||||
#include "core/CutterJson.h"
|
#include "core/CutterJson.h"
|
||||||
#include "core/Basefind.h"
|
#include "core/Basefind.h"
|
||||||
|
#include "core/BinDiff.h"
|
||||||
#include "common/BasicInstructionHighlighter.h"
|
#include "common/BasicInstructionHighlighter.h"
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
@ -71,6 +72,7 @@ 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);
|
||||||
@ -755,7 +757,8 @@ 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 *matchFunctionsFromNewFile(const QString &filePath);
|
RzAnalysisMatchResult *diffNewFile(const QString &filePath,
|
||||||
|
RzAnalysisMatchThreadInfoCb callback, void *user);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void refreshAll();
|
void refreshAll();
|
||||||
|
@ -405,6 +405,14 @@ struct BasefindResultDescription
|
|||||||
ut32 score;
|
ut32 score;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BinDiffMatchDescription
|
||||||
|
{
|
||||||
|
FunctionDescription original;
|
||||||
|
FunctionDescription modified;
|
||||||
|
QString simtype;
|
||||||
|
double similarity;
|
||||||
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FunctionDescription)
|
Q_DECLARE_METATYPE(FunctionDescription)
|
||||||
Q_DECLARE_METATYPE(ImportDescription)
|
Q_DECLARE_METATYPE(ImportDescription)
|
||||||
Q_DECLARE_METATYPE(ExportDescription)
|
Q_DECLARE_METATYPE(ExportDescription)
|
||||||
@ -446,5 +454,6 @@ Q_DECLARE_METATYPE(RefDescription)
|
|||||||
Q_DECLARE_METATYPE(VariableDescription)
|
Q_DECLARE_METATYPE(VariableDescription)
|
||||||
Q_DECLARE_METATYPE(BasefindCoreStatusDescription)
|
Q_DECLARE_METATYPE(BasefindCoreStatusDescription)
|
||||||
Q_DECLARE_METATYPE(BasefindResultDescription)
|
Q_DECLARE_METATYPE(BasefindResultDescription)
|
||||||
|
Q_DECLARE_METATYPE(BinDiffMatchDescription)
|
||||||
|
|
||||||
#endif // DESCRIPTIONS_H
|
#endif // DESCRIPTIONS_H
|
||||||
|
@ -119,6 +119,7 @@
|
|||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
#include "tools/basefind/BaseFindDialog.h"
|
#include "tools/basefind/BaseFindDialog.h"
|
||||||
|
#include "tools/bindiff/DiffLoadDialog.h"
|
||||||
|
|
||||||
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
|
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
|
||||||
|
|
||||||
@ -1616,60 +1617,14 @@ void MainWindow::on_actionBackward_triggered()
|
|||||||
|
|
||||||
void MainWindow::on_actionDiff_triggered()
|
void MainWindow::on_actionDiff_triggered()
|
||||||
{
|
{
|
||||||
QFileDialog dialog(this);
|
auto dialog = new DiffLoadDialog(this);
|
||||||
dialog.setWindowTitle(tr("Select a file to use for diffing"));
|
dialog->show();
|
||||||
dialog.setNameFilters({ tr("All files (*)") });
|
|
||||||
|
|
||||||
if (!dialog.exec()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &fileName = QDir::toNativeSeparators(dialog.selectedFiles().first());
|
|
||||||
|
|
||||||
if (fileName.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto compareTask = new RizinFunctionTask([=](RzCore *) {
|
|
||||||
return Core()->matchFunctionsFromNewFile(fileName);
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
task = QSharedPointer<RizinTask>(compareTask);
|
|
||||||
taskDialog = new RizinTaskDialog(task);
|
|
||||||
taskDialog->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
taskDialog->setDesc(tr("Performing function comparison..."));
|
|
||||||
taskDialog->show();
|
|
||||||
|
|
||||||
connect(task.data(), &RizinTask::finished, this, [this, compareTask]() {
|
|
||||||
RzAnalysisMatchResult *result = static_cast<RzAnalysisMatchResult *>(compareTask->getResult());
|
|
||||||
openBinDiffDialog(result);
|
|
||||||
delete taskDialog;
|
|
||||||
taskDialog = nullptr;
|
|
||||||
});
|
|
||||||
|
|
||||||
compareTask->startTask();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionForward_triggered()
|
void MainWindow::on_actionForward_triggered()
|
||||||
{
|
{
|
||||||
core->seekNext();
|
core->seekNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::openBinDiffDialog(RzAnalysisMatchResult *result)
|
|
||||||
{
|
|
||||||
if (!result) {
|
|
||||||
messageBoxWarning(tr("Error"), tr("Failed to perform the function matching."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (binDiffDialog) {
|
|
||||||
delete binDiffDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
binDiffDialog = new BinDiffDialog(result, this);
|
|
||||||
binDiffDialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionDisasAdd_comment_triggered()
|
void MainWindow::on_actionDisasAdd_comment_triggered()
|
||||||
{
|
{
|
||||||
CommentsDialog c(this);
|
CommentsDialog c(this);
|
||||||
|
@ -152,10 +152,10 @@ public slots:
|
|||||||
|
|
||||||
void openNewFileFailed();
|
void openNewFileFailed();
|
||||||
|
|
||||||
void openBinDiffDialog(RzAnalysisMatchResult *result);
|
|
||||||
|
|
||||||
void toggleOverview(bool visibility, GraphWidget *targetGraph);
|
void toggleOverview(bool visibility, GraphWidget *targetGraph);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void on_actionDiff_triggered();
|
||||||
void on_actionBaseFind_triggered();
|
void on_actionBaseFind_triggered();
|
||||||
void on_actionAbout_triggered();
|
void on_actionAbout_triggered();
|
||||||
void on_actionIssue_triggered();
|
void on_actionIssue_triggered();
|
||||||
@ -179,8 +179,6 @@ private slots:
|
|||||||
void on_actionBackward_triggered();
|
void on_actionBackward_triggered();
|
||||||
void on_actionForward_triggered();
|
void on_actionForward_triggered();
|
||||||
|
|
||||||
void on_actionDiff_triggered();
|
|
||||||
|
|
||||||
void on_actionMap_triggered();
|
void on_actionMap_triggered();
|
||||||
|
|
||||||
void on_actionTabs_on_Top_triggered();
|
void on_actionTabs_on_Top_triggered();
|
||||||
|
94
src/tools/bindiff/DiffLoadDialog.cpp
Normal file
94
src/tools/bindiff/DiffLoadDialog.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include "DiffLoadDialog.h"
|
||||||
|
#include "ui_DiffLoadDialog.h"
|
||||||
|
|
||||||
|
#include <core/Cutter.h>
|
||||||
|
#include <rz_th.h>
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
DiffLoadDialog::DiffLoadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::DiffLoadDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
|
||||||
|
ui->lineEditFileName->setReadOnly(true);
|
||||||
|
ui->lineEditFileName->setText("");
|
||||||
|
|
||||||
|
ui->lineEditDiffFile->setReadOnly(true);
|
||||||
|
ui->lineEditDiffFile->setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
DiffLoadDialog::~DiffLoadDialog() {}
|
||||||
|
|
||||||
|
QString DiffLoadDialog::getFileToOpen() const
|
||||||
|
{
|
||||||
|
return ui->lineEditFileName->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DiffLoadDialog::getPreviousDiffFile() const
|
||||||
|
{
|
||||||
|
return ui->lineEditDiffFile->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffLoadDialog::on_buttonDiffOpen_clicked()
|
||||||
|
{
|
||||||
|
QFileDialog dialog(this);
|
||||||
|
dialog.setWindowTitle(tr("Select the previous diff to load"));
|
||||||
|
dialog.setNameFilters({ tr("JSON array (*.json)") });
|
||||||
|
|
||||||
|
if (!dialog.exec()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &fileName = QDir::toNativeSeparators(dialog.selectedFiles().first());
|
||||||
|
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->lineEditDiffFile->setText(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffLoadDialog::on_buttonFileOpen_clicked()
|
||||||
|
{
|
||||||
|
QFileDialog dialog(this);
|
||||||
|
dialog.setWindowTitle(tr("Select a file to use for diffing"));
|
||||||
|
dialog.setNameFilters({ tr("All files (*)") });
|
||||||
|
|
||||||
|
if (!dialog.exec()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &fileName = QDir::toNativeSeparators(dialog.selectedFiles().first());
|
||||||
|
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
QString fileName = getFileToOpen();
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
openErrorBox(tr("The compare file was not selected."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffLoadDialog::on_buttonBox_rejected()
|
||||||
|
{
|
||||||
|
// cancel
|
||||||
|
}
|
37
src/tools/bindiff/DiffLoadDialog.h
Normal file
37
src/tools/bindiff/DiffLoadDialog.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef DIFF_LOAD_DIALOG_H
|
||||||
|
#define DIFF_LOAD_DIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <core/Cutter.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class DiffLoadDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffLoadDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DiffLoadDialog(QWidget *parent = nullptr);
|
||||||
|
~DiffLoadDialog();
|
||||||
|
|
||||||
|
QString getFileToOpen() const;
|
||||||
|
QString getPreviousDiffFile() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonDiffOpen_clicked();
|
||||||
|
void on_buttonFileOpen_clicked();
|
||||||
|
void on_buttonBox_accepted();
|
||||||
|
void on_buttonBox_rejected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::DiffLoadDialog> ui;
|
||||||
|
|
||||||
|
void openErrorBox(QString errorMessage);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DIFF_LOAD_DIALOG_H
|
142
src/tools/bindiff/DiffLoadDialog.ui
Normal file
142
src/tools/bindiff/DiffLoadDialog.ui
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>DiffLoadDialog</class>
|
||||||
|
<widget class="QDialog" name="DiffLoadDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::NonModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>636</width>
|
||||||
|
<height>142</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">Select which file to compare.</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditDiffFile"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEditFileName"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="fileToCompareLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>File to compare to.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>File to compare (required)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</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">
|
||||||
|
<widget class="QPushButton" name="buttonFileOpen">
|
||||||
|
<property name="text">
|
||||||
|
<string>Select</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="previousDiffLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>You can load a previous saved diff instead of performing a new diff scan.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Previous diff file (optional)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>DiffLoadDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>234</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>DiffLoadDialog</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>
|
Loading…
Reference in New Issue
Block a user