mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 10:56:11 +00:00
Add Tools > BaseFind + command line options (#3198)
* Add Tools > BaseFind * Rewritten how cutter parses and stores the initial options * Update docs and fixed comments * Add missing endianness option
This commit is contained in:
parent
579ac236b6
commit
cf14fd1006
@ -40,21 +40,45 @@ Options
|
||||
**2**
|
||||
aaaa (experimental)
|
||||
|
||||
.. option:: -a, --arch <arch>
|
||||
|
||||
Sets a specific architecture name.
|
||||
|
||||
.. option:: -b, --bits <bits>
|
||||
|
||||
Sets a specific architecture bits.
|
||||
|
||||
.. option:: -c, --cpu <cpu>
|
||||
|
||||
Sets a specific CPU.
|
||||
|
||||
.. option:: -o, --os <os>
|
||||
|
||||
Sets a specific operating system.
|
||||
|
||||
.. option:: -e, --endian <big|little>
|
||||
|
||||
Sets the endianness (big or little).
|
||||
|
||||
.. option:: -F, --format <name>
|
||||
|
||||
Force using a specific file format (bin plugin)
|
||||
Force using a specific file format (bin plugin).
|
||||
|
||||
.. option:: -B, --base <base address>
|
||||
|
||||
Load binary at a specific base address
|
||||
Load binary at a specific base address.
|
||||
|
||||
.. option:: -m, --map <map address>
|
||||
|
||||
Map the binary at a specific address.
|
||||
|
||||
.. option:: -i <file>
|
||||
|
||||
Run script file
|
||||
Run script file.
|
||||
|
||||
.. option:: -p, --project <file>
|
||||
|
||||
Load project file
|
||||
Load project file.
|
||||
|
||||
.. option:: -w, --writemode
|
||||
|
||||
@ -62,9 +86,13 @@ Options
|
||||
When used together with -A/--analysis <level>, it will open a file directly
|
||||
in write mode without any further dialog or confirmation.
|
||||
|
||||
.. option:: -P, --phymode
|
||||
|
||||
Disables virtual addressing.
|
||||
|
||||
.. option:: --pythonhome <PYTHONHOME>
|
||||
|
||||
PYTHONHOME to use for the embedded python interpreter
|
||||
PYTHONHOME to use for the embedded python interpreter.
|
||||
|
||||
.. option:: --no-output-redirect
|
||||
|
||||
|
2
rizin
2
rizin
@ -1 +1 @@
|
||||
Subproject commit 9c6feafd4733903fca0cdad50b3bd213ab2b6228
|
||||
Subproject commit 6bfc67a2868e07ab89ff931b96dfd3bc65e7371e
|
@ -6,6 +6,7 @@ set(SOURCES
|
||||
core/Cutter.cpp
|
||||
core/CutterJson.cpp
|
||||
core/RizinCpp.cpp
|
||||
core/Basefind.cpp
|
||||
dialogs/EditStringDialog.cpp
|
||||
dialogs/WriteCommandsDialogs.cpp
|
||||
widgets/DisassemblerGraphView.cpp
|
||||
@ -149,6 +150,9 @@ set(SOURCES
|
||||
dialogs/GlibcHeapBinsDialog.cpp
|
||||
widgets/HeapBinsGraphView.cpp
|
||||
dialogs/ArenaInfoDialog.cpp
|
||||
tools/basefind/BaseFindDialog.cpp
|
||||
tools/basefind/BaseFindSearchDialog.cpp
|
||||
tools/basefind/BaseFindResultsDialog.cpp
|
||||
)
|
||||
set(HEADER_FILES
|
||||
core/Cutter.h
|
||||
@ -156,6 +160,7 @@ set(HEADER_FILES
|
||||
core/CutterDescriptions.h
|
||||
core/CutterJson.h
|
||||
core/RizinCpp.h
|
||||
core/Basefind.h
|
||||
dialogs/EditStringDialog.h
|
||||
dialogs/WriteCommandsDialogs.h
|
||||
widgets/DisassemblerGraphView.h
|
||||
@ -308,6 +313,9 @@ set(HEADER_FILES
|
||||
dialogs/GlibcHeapBinsDialog.h
|
||||
widgets/HeapBinsGraphView.h
|
||||
dialogs/ArenaInfoDialog.h
|
||||
tools/basefind/BaseFindDialog.h
|
||||
tools/basefind/BaseFindSearchDialog.h
|
||||
tools/basefind/BaseFindResultsDialog.h
|
||||
)
|
||||
set(UI_FILES
|
||||
dialogs/AboutDialog.ui
|
||||
@ -377,6 +385,9 @@ set(UI_FILES
|
||||
widgets/GlibcHeapWidget.ui
|
||||
dialogs/GlibcHeapBinsDialog.ui
|
||||
dialogs/ArenaInfoDialog.ui
|
||||
tools/basefind/BaseFindDialog.ui
|
||||
tools/basefind/BaseFindSearchDialog.ui
|
||||
tools/basefind/BaseFindResultsDialog.ui
|
||||
)
|
||||
set(QRC_FILES
|
||||
resources.qrc
|
||||
|
@ -296,6 +296,89 @@ bool CutterApplication::loadTranslations()
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList CutterApplication::getArgs() const
|
||||
{
|
||||
auto &options = clOptions.fileOpenOptions;
|
||||
|
||||
QStringList args;
|
||||
switch (clOptions.analysisLevel) {
|
||||
case AutomaticAnalysisLevel::None:
|
||||
args.push_back("-A");
|
||||
args.push_back("0");
|
||||
break;
|
||||
case AutomaticAnalysisLevel::AAA:
|
||||
args.push_back("-A");
|
||||
args.push_back("1");
|
||||
break;
|
||||
case AutomaticAnalysisLevel::AAAA:
|
||||
args.push_back("-A");
|
||||
args.push_back("2");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!options.useVA) {
|
||||
args.push_back("-P");
|
||||
}
|
||||
if (options.writeEnabled) {
|
||||
args.push_back("-w");
|
||||
}
|
||||
if (!options.script.isEmpty()) {
|
||||
args.push_back("-i");
|
||||
args.push_back(options.script);
|
||||
}
|
||||
if (!options.projectFile.isEmpty()) {
|
||||
args.push_back("-p");
|
||||
args.push_back(options.projectFile);
|
||||
}
|
||||
if (!options.arch.isEmpty()) {
|
||||
args.push_back("-a");
|
||||
args.push_back(options.arch);
|
||||
}
|
||||
if (options.bits > 0) {
|
||||
args.push_back("-b");
|
||||
args.push_back(QString::asprintf("%d", options.bits));
|
||||
}
|
||||
if (!options.cpu.isEmpty()) {
|
||||
args.push_back("-c");
|
||||
args.push_back(options.cpu);
|
||||
}
|
||||
if (!options.os.isEmpty()) {
|
||||
args.push_back("-o");
|
||||
args.push_back(options.os);
|
||||
}
|
||||
|
||||
switch (options.endian) {
|
||||
case InitialOptions::Endianness::Little:
|
||||
args.push_back("-e");
|
||||
args.push_back("little");
|
||||
break;
|
||||
case InitialOptions::Endianness::Big:
|
||||
args.push_back("-e");
|
||||
args.push_back("big");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!options.forceBinPlugin.isEmpty()) {
|
||||
args.push_back("-F");
|
||||
args.push_back(options.forceBinPlugin);
|
||||
}
|
||||
if (options.binLoadAddr != RVA_INVALID) {
|
||||
args.push_back("-B");
|
||||
args.push_back(RzAddressString(options.binLoadAddr));
|
||||
}
|
||||
if (options.mapAddr != RVA_INVALID) {
|
||||
args.push_back("-m");
|
||||
args.push_back(RzAddressString(options.mapAddr));
|
||||
}
|
||||
if (!options.filename.isEmpty()) {
|
||||
args.push_back(options.filename);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
bool CutterApplication::parseCommandLineOptions()
|
||||
{
|
||||
// Keep this function in sync with documentation
|
||||
@ -315,6 +398,27 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
QObject::tr("level"));
|
||||
cmd_parser.addOption(analOption);
|
||||
|
||||
QCommandLineOption archOption({ "a", "arch" }, QObject::tr("Sets a specific architecture name"),
|
||||
QObject::tr("arch"));
|
||||
cmd_parser.addOption(archOption);
|
||||
|
||||
QCommandLineOption bitsOption({ "b", "bits" }, QObject::tr("Sets a specific architecture bits"),
|
||||
QObject::tr("bits"));
|
||||
cmd_parser.addOption(bitsOption);
|
||||
|
||||
QCommandLineOption cpuOption({ "c", "cpu" }, QObject::tr("Sets a specific CPU"),
|
||||
QObject::tr("cpu"));
|
||||
cmd_parser.addOption(cpuOption);
|
||||
|
||||
QCommandLineOption osOption({ "o", "os" }, QObject::tr("Sets a specific operating system"),
|
||||
QObject::tr("os"));
|
||||
cmd_parser.addOption(osOption);
|
||||
|
||||
QCommandLineOption endianOption({ "e", "endian" },
|
||||
QObject::tr("Sets the endianness (big or little)"),
|
||||
QObject::tr("big|little"));
|
||||
cmd_parser.addOption(endianOption);
|
||||
|
||||
QCommandLineOption formatOption({ "F", "format" },
|
||||
QObject::tr("Force using a specific file format (bin plugin)"),
|
||||
QObject::tr("name"));
|
||||
@ -325,6 +429,11 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
QObject::tr("base address"));
|
||||
cmd_parser.addOption(baddrOption);
|
||||
|
||||
QCommandLineOption maddrOption({ "m", "map" },
|
||||
QObject::tr("Map the binary at a specific address"),
|
||||
QObject::tr("map address"));
|
||||
cmd_parser.addOption(maddrOption);
|
||||
|
||||
QCommandLineOption scriptOption("i", QObject::tr("Run script file"), QObject::tr("file"));
|
||||
cmd_parser.addOption(scriptOption);
|
||||
|
||||
@ -336,6 +445,10 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
QObject::tr("Open file in write mode"));
|
||||
cmd_parser.addOption(writeModeOption);
|
||||
|
||||
QCommandLineOption phyModeOption({ "P", "phymode" },
|
||||
QObject::tr("Disables virtual addressing"));
|
||||
cmd_parser.addOption(phyModeOption);
|
||||
|
||||
QCommandLineOption pythonHomeOption(
|
||||
"pythonhome", QObject::tr("PYTHONHOME to use for embedded python interpreter"),
|
||||
"PYTHONHOME");
|
||||
@ -397,15 +510,21 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
return false;
|
||||
}
|
||||
|
||||
InitialOptions options;
|
||||
if (!opts.args.isEmpty()) {
|
||||
opts.fileOpenOptions.filename = opts.args[0];
|
||||
opts.fileOpenOptions.forceBinPlugin = cmd_parser.value(formatOption);
|
||||
if (cmd_parser.isSet(baddrOption)) {
|
||||
bool ok;
|
||||
bool ok = false;
|
||||
RVA baddr = cmd_parser.value(baddrOption).toULongLong(&ok, 0);
|
||||
if (ok) {
|
||||
options.binLoadAddr = baddr;
|
||||
opts.fileOpenOptions.binLoadAddr = baddr;
|
||||
}
|
||||
}
|
||||
if (cmd_parser.isSet(maddrOption)) {
|
||||
bool ok = false;
|
||||
RVA maddr = cmd_parser.value(maddrOption).toULongLong(&ok, 0);
|
||||
if (ok) {
|
||||
opts.fileOpenOptions.mapAddr = maddr;
|
||||
}
|
||||
}
|
||||
switch (opts.analysisLevel) {
|
||||
@ -422,8 +541,36 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
break;
|
||||
}
|
||||
opts.fileOpenOptions.script = cmd_parser.value(scriptOption);
|
||||
opts.fileOpenOptions.arch = cmd_parser.value(archOption);
|
||||
opts.fileOpenOptions.cpu = cmd_parser.value(cpuOption);
|
||||
opts.fileOpenOptions.os = cmd_parser.value(osOption);
|
||||
if (cmd_parser.isSet(bitsOption)) {
|
||||
bool ok = false;
|
||||
int bits = cmd_parser.value(bitsOption).toInt(&ok, 10);
|
||||
if (ok && bits > 0) {
|
||||
opts.fileOpenOptions.bits = bits;
|
||||
}
|
||||
}
|
||||
if (cmd_parser.isSet(endianOption)) {
|
||||
QString endian = cmd_parser.value(endianOption).toLower();
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Auto;
|
||||
if (endian == "little") {
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Little;
|
||||
} else if (endian == "big") {
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Big;
|
||||
} else {
|
||||
fprintf(stderr, "%s\n",
|
||||
QObject::tr("Invalid Endianness. You can only set it to `big` or `little`.")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Auto;
|
||||
}
|
||||
|
||||
opts.fileOpenOptions.writeEnabled = cmd_parser.isSet(writeModeOption);
|
||||
opts.fileOpenOptions.useVA = !cmd_parser.isSet(phyModeOption);
|
||||
}
|
||||
|
||||
opts.fileOpenOptions.projectFile = cmd_parser.value(projectOption);
|
||||
|
@ -33,6 +33,10 @@ public:
|
||||
|
||||
void launchNewInstance(const QStringList &args = {});
|
||||
|
||||
InitialOptions getInitialOptions() const { return clOptions.fileOpenOptions; }
|
||||
void setInitialOptions(const InitialOptions &options) { clOptions.fileOpenOptions = options; }
|
||||
QStringList getArgs() const;
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e);
|
||||
|
||||
|
109
src/core/Basefind.cpp
Normal file
109
src/core/Basefind.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
#include "Basefind.h"
|
||||
|
||||
bool Basefind::threadCallback(const RzBaseFindThreadInfo *info, void *user)
|
||||
{
|
||||
auto th = reinterpret_cast<Basefind *>(user);
|
||||
return th->updateProgress(info);
|
||||
}
|
||||
|
||||
Basefind::Basefind(CutterCore *core)
|
||||
: core(core),
|
||||
scores(nullptr),
|
||||
continue_run(true)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
,
|
||||
mutex(QMutex::Recursive)
|
||||
#endif
|
||||
{
|
||||
memset(&options, 0, sizeof(RzBaseFindOpt));
|
||||
}
|
||||
|
||||
Basefind::~Basefind()
|
||||
{
|
||||
cancel();
|
||||
wait();
|
||||
rz_list_free(scores);
|
||||
}
|
||||
|
||||
bool Basefind::setOptions(const RzBaseFindOpt *opts)
|
||||
{
|
||||
mutex.lock();
|
||||
options.max_threads = opts->max_threads;
|
||||
options.pointer_size = opts->pointer_size;
|
||||
options.start_address = opts->start_address;
|
||||
options.end_address = opts->end_address;
|
||||
options.alignment = opts->alignment;
|
||||
options.min_score = opts->min_score;
|
||||
options.min_string_len = opts->min_string_len;
|
||||
mutex.unlock();
|
||||
|
||||
if (options.start_address >= options.end_address) {
|
||||
qWarning() << "Start address is >= end address";
|
||||
return false;
|
||||
} else if (options.alignment < RZ_BASEFIND_BASE_ALIGNMENT) {
|
||||
qWarning() << "Alignment must be at least "
|
||||
<< QString::asprintf("0x%x", RZ_BASEFIND_BASE_ALIGNMENT);
|
||||
return false;
|
||||
} else if (options.min_score < 1) {
|
||||
qWarning() << "Min score must be at least 1";
|
||||
return false;
|
||||
} else if (options.min_string_len < 1) {
|
||||
qWarning() << "Min string length must be at least 1";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Basefind::run()
|
||||
{
|
||||
qRegisterMetaType<BasefindCoreStatusDescription>();
|
||||
|
||||
mutex.lock();
|
||||
rz_list_free(scores);
|
||||
scores = nullptr;
|
||||
continue_run = true;
|
||||
mutex.unlock();
|
||||
|
||||
core->coreMutex.lock();
|
||||
options.callback = threadCallback;
|
||||
options.user = this;
|
||||
scores = rz_basefind(core->core_, &options);
|
||||
core->coreMutex.unlock();
|
||||
|
||||
emit complete();
|
||||
}
|
||||
|
||||
void Basefind::cancel()
|
||||
{
|
||||
mutex.lock();
|
||||
continue_run = false;
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
QList<BasefindResultDescription> Basefind::results()
|
||||
{
|
||||
QList<BasefindResultDescription> pairs;
|
||||
RzListIter *it;
|
||||
RzBaseFindScore *pair;
|
||||
CutterRzListForeach (scores, it, RzBaseFindScore, pair) {
|
||||
BasefindResultDescription desc;
|
||||
desc.candidate = pair->candidate;
|
||||
desc.score = pair->score;
|
||||
pairs.push_back(desc);
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
|
||||
bool Basefind::updateProgress(const RzBaseFindThreadInfo *info)
|
||||
{
|
||||
mutex.lock();
|
||||
|
||||
BasefindCoreStatusDescription status;
|
||||
status.index = info->thread_idx;
|
||||
status.percentage = info->percentage;
|
||||
|
||||
emit progress(status);
|
||||
bool ret = continue_run;
|
||||
mutex.unlock();
|
||||
return ret;
|
||||
}
|
47
src/core/Basefind.h
Normal file
47
src/core/Basefind.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef CUTTER_BASEFIND_CORE_H
|
||||
#define CUTTER_BASEFIND_CORE_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
|
||||
#include "Cutter.h"
|
||||
#include "CutterDescriptions.h"
|
||||
#include <rz_basefind.h>
|
||||
|
||||
class CutterCore;
|
||||
|
||||
class Basefind : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Basefind(CutterCore *core);
|
||||
virtual ~Basefind();
|
||||
|
||||
void run();
|
||||
bool setOptions(const RzBaseFindOpt *opts);
|
||||
QList<BasefindResultDescription> results();
|
||||
|
||||
public slots:
|
||||
void cancel();
|
||||
|
||||
signals:
|
||||
void progress(BasefindCoreStatusDescription status);
|
||||
void complete();
|
||||
|
||||
private:
|
||||
CutterCore *const core;
|
||||
RzList *scores;
|
||||
bool continue_run;
|
||||
RzBaseFindOpt options;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QMutex mutex;
|
||||
#else
|
||||
QRecursiveMutex mutex;
|
||||
#endif
|
||||
|
||||
bool updateProgress(const RzBaseFindThreadInfo *info);
|
||||
static bool threadCallback(const RzBaseFindThreadInfo *info, void *user);
|
||||
};
|
||||
|
||||
#endif // CUTTER_BASEFIND_CORE_H
|
@ -4577,3 +4577,9 @@ void CutterCore::writeGraphvizGraphToFile(QString path, QString format, RzCoreGr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CutterCore::rebaseBin(RVA base_address)
|
||||
{
|
||||
CORE_LOCK();
|
||||
return rz_core_bin_rebase(core, base_address);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "core/CutterCommon.h"
|
||||
#include "core/CutterDescriptions.h"
|
||||
#include "core/CutterJson.h"
|
||||
#include "core/Basefind.h"
|
||||
#include "common/BasicInstructionHighlighter.h"
|
||||
|
||||
#include <QMap>
|
||||
@ -69,6 +70,7 @@ class CUTTER_EXPORT CutterCore : public QObject
|
||||
|
||||
friend class RzCoreLocked;
|
||||
friend class RizinTask;
|
||||
friend class Basefind;
|
||||
|
||||
public:
|
||||
explicit CutterCore(QObject *parent = nullptr);
|
||||
@ -556,6 +558,8 @@ public:
|
||||
void setGraphEmpty(bool empty);
|
||||
bool isGraphEmpty();
|
||||
|
||||
bool rebaseBin(RVA base_address);
|
||||
|
||||
void getRegs();
|
||||
QList<QString> regs;
|
||||
void setSettings();
|
||||
|
@ -385,6 +385,18 @@ struct Arena
|
||||
ut64 max_system_mem;
|
||||
};
|
||||
|
||||
struct BasefindCoreStatusDescription
|
||||
{
|
||||
size_t index;
|
||||
ut32 percentage;
|
||||
};
|
||||
|
||||
struct BasefindResultDescription
|
||||
{
|
||||
RVA candidate;
|
||||
ut32 score;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FunctionDescription)
|
||||
Q_DECLARE_METATYPE(ImportDescription)
|
||||
Q_DECLARE_METATYPE(ExportDescription)
|
||||
@ -423,5 +435,7 @@ Q_DECLARE_METATYPE(BreakpointDescription::PositionType)
|
||||
Q_DECLARE_METATYPE(ProcessDescription)
|
||||
Q_DECLARE_METATYPE(RefDescription)
|
||||
Q_DECLARE_METATYPE(VariableDescription)
|
||||
Q_DECLARE_METATYPE(BasefindCoreStatusDescription)
|
||||
Q_DECLARE_METATYPE(BasefindResultDescription)
|
||||
|
||||
#endif // DESCRIPTIONS_H
|
||||
|
@ -115,6 +115,9 @@
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
|
||||
// Tools
|
||||
#include "tools/basefind/BaseFindDialog.h"
|
||||
|
||||
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
|
||||
|
||||
template<class T>
|
||||
@ -1087,11 +1090,11 @@ MemoryDockWidget *MainWindow::addNewMemoryWidget(MemoryWidgetType type, RVA addr
|
||||
memoryWidget = new DecompilerWidget(this);
|
||||
break;
|
||||
case MemoryWidgetType::CallGraph:
|
||||
memoryWidget = new CallGraphWidget(this, false);
|
||||
break;
|
||||
memoryWidget = new CallGraphWidget(this, false);
|
||||
break;
|
||||
case MemoryWidgetType::GlobalCallGraph:
|
||||
memoryWidget = new CallGraphWidget(this, true);
|
||||
break;
|
||||
memoryWidget = new CallGraphWidget(this, true);
|
||||
break;
|
||||
}
|
||||
auto seekable = memoryWidget->getSeekable();
|
||||
seekable->setSynchronization(synchronized);
|
||||
@ -1637,6 +1640,12 @@ void MainWindow::on_actionTabs_triggered()
|
||||
setTabLocation();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionBaseFind_triggered()
|
||||
{
|
||||
auto dialog = new BaseFindDialog(this);
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAbout_triggered()
|
||||
{
|
||||
AboutDialog *a = new AboutDialog(this);
|
||||
@ -1774,12 +1783,10 @@ void MainWindow::on_actionExport_as_code_triggered()
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
auto string = fromOwned(
|
||||
dialog.selectedNameFilter() != instructionsInComments
|
||||
? rz_lang_byte_array(buffer.data(), size, typMap[dialog.selectedNameFilter()])
|
||||
: rz_core_print_bytes_with_inst(rc, buffer.data(), 0, size));
|
||||
dialog.selectedNameFilter() != instructionsInComments
|
||||
? rz_lang_byte_array(buffer.data(), size, typMap[dialog.selectedNameFilter()])
|
||||
: rz_core_print_bytes_with_inst(rc, buffer.data(), 0, size));
|
||||
fileOut << string.get();
|
||||
}
|
||||
|
||||
|
@ -152,6 +152,7 @@ public slots:
|
||||
|
||||
void toggleOverview(bool visibility, GraphWidget *targetGraph);
|
||||
private slots:
|
||||
void on_actionBaseFind_triggered();
|
||||
void on_actionAbout_triggered();
|
||||
void on_actionIssue_triggered();
|
||||
void documentationClicked();
|
||||
|
@ -128,6 +128,12 @@
|
||||
<addaction name="actionSaveLayout"/>
|
||||
<addaction name="menuLayouts"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
<string>Tools</string>
|
||||
</property>
|
||||
<addaction name="actionBaseFind"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>Help</string>
|
||||
@ -184,6 +190,7 @@
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuWindows"/>
|
||||
<addaction name="menuDebug"/>
|
||||
<addaction name="menuTools"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="mainToolBar">
|
||||
@ -233,6 +240,11 @@
|
||||
<string>Zen mode</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBaseFind">
|
||||
<property name="text">
|
||||
<string>BaseFind</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="text">
|
||||
<string>About</string>
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "CommentsDialog.h"
|
||||
#include "ui_CommentsDialog.h"
|
||||
|
||||
#include <QErrorMessage>
|
||||
|
||||
#include "core/Cutter.h"
|
||||
|
||||
CommentsDialog::CommentsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CommentsDialog)
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "core/Cutter.h"
|
||||
#include "common/AnalysisTask.h"
|
||||
#include "CutterApplication.h"
|
||||
|
||||
InitialOptionsDialog::InitialOptionsDialog(MainWindow *main)
|
||||
: QDialog(nullptr), // parent must not be main
|
||||
@ -179,9 +180,56 @@ void InitialOptionsDialog::loadOptions(const InitialOptions &options)
|
||||
ui->entry_loadOffset->setText(RzAddressString(options.binLoadAddr));
|
||||
}
|
||||
|
||||
if (options.mapAddr != RVA_INVALID) {
|
||||
ui->entry_mapOffset->setText(RzAddressString(options.mapAddr));
|
||||
}
|
||||
|
||||
ui->vaCheckBox->setChecked(options.useVA);
|
||||
ui->writeCheckBox->setChecked(options.writeEnabled);
|
||||
|
||||
// TODO: all other options should also be applied to the ui
|
||||
if (!options.arch.isNull() && !options.arch.isEmpty()) {
|
||||
ui->archComboBox->setCurrentText(options.arch);
|
||||
}
|
||||
|
||||
if (!options.cpu.isNull() && !options.cpu.isEmpty()) {
|
||||
ui->cpuComboBox->setCurrentText(options.cpu);
|
||||
}
|
||||
|
||||
if (options.bits > 0) {
|
||||
ui->bitsComboBox->setCurrentText(QString::asprintf("%d", options.bits));
|
||||
}
|
||||
|
||||
if (!options.os.isNull() && !options.os.isEmpty()) {
|
||||
ui->kernelComboBox->setCurrentText(options.os);
|
||||
}
|
||||
|
||||
if (!options.forceBinPlugin.isNull() && !options.forceBinPlugin.isEmpty()) {
|
||||
ui->formatComboBox->setCurrentText(options.forceBinPlugin);
|
||||
}
|
||||
|
||||
if (!options.loadBinInfo) {
|
||||
ui->binCheckBox->setChecked(false);
|
||||
}
|
||||
|
||||
ui->writeCheckBox->setChecked(options.writeEnabled);
|
||||
|
||||
switch (options.endian) {
|
||||
case InitialOptions::Endianness::Little:
|
||||
ui->endiannessComboBox->setCurrentIndex(1);
|
||||
break;
|
||||
case InitialOptions::Endianness::Big:
|
||||
ui->endiannessComboBox->setCurrentIndex(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ui->demangleCheckBox->setChecked(options.demangle);
|
||||
|
||||
if (!options.pdbFile.isNull() && !options.pdbFile.isEmpty()) {
|
||||
ui->pdbCheckBox->setChecked(true);
|
||||
ui->pdbLineEdit->setText(options.pdbFile);
|
||||
}
|
||||
}
|
||||
|
||||
void InitialOptionsDialog::setTooltipWithConfigHelp(QWidget *w, const char *config)
|
||||
@ -246,7 +294,7 @@ QList<CommandDescription> InitialOptionsDialog::getSelectedAdvancedAnalCmds() co
|
||||
return advanced;
|
||||
}
|
||||
|
||||
void InitialOptionsDialog::setupAndStartAnalysis(/*int level, QList<QString> advanced*/)
|
||||
void InitialOptionsDialog::setupAndStartAnalysis()
|
||||
{
|
||||
InitialOptions options;
|
||||
|
||||
@ -322,6 +370,8 @@ void InitialOptionsDialog::setupAndStartAnalysis(/*int level, QList<QString> adv
|
||||
Core()->getAsyncTaskManager()->start(analysisTaskPtr);
|
||||
|
||||
done(0);
|
||||
|
||||
static_cast<CutterApplication *>(qApp)->setInitialOptions(options);
|
||||
}
|
||||
|
||||
void InitialOptionsDialog::on_okButton_clicked()
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
explicit InitialOptionsDialog(MainWindow *main);
|
||||
~InitialOptionsDialog();
|
||||
|
||||
void setupAndStartAnalysis(/*int level, QList<QString> advanced*/);
|
||||
void setupAndStartAnalysis();
|
||||
|
||||
private slots:
|
||||
void on_okButton_clicked();
|
||||
|
97
src/tools/basefind/BaseFindDialog.cpp
Normal file
97
src/tools/basefind/BaseFindDialog.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
#include "BaseFindDialog.h"
|
||||
#include "ui_BaseFindDialog.h"
|
||||
|
||||
#include "BaseFindSearchDialog.h"
|
||||
|
||||
#include <core/Cutter.h>
|
||||
#include <rz_th.h>
|
||||
|
||||
BaseFindDialog::BaseFindDialog(QWidget *parent) : QDialog(parent), ui(new Ui::BaseFindDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
|
||||
// Fill in N-thread Combo
|
||||
size_t n_cores = rz_th_physical_core_number();
|
||||
ui->nCoresCombo->clear();
|
||||
for (size_t i = n_cores; i > 0; i--) {
|
||||
if (n_cores == i) {
|
||||
ui->nCoresCombo->addItem("All Cores");
|
||||
continue;
|
||||
}
|
||||
ui->nCoresCombo->addItem(QString::number(i));
|
||||
}
|
||||
|
||||
ui->startAddressEdit->setText(Core()->getConfig("basefind.search.start"));
|
||||
ui->endAddressEdit->setText(Core()->getConfig("basefind.search.end"));
|
||||
ui->alignmentEdit->setText(Core()->getConfig("basefind.alignment"));
|
||||
ui->minStrLenEdit->setValue(Core()->getConfigut64("basefind.min.string"));
|
||||
ui->minScoreEdit->setValue(Core()->getConfigut64("basefind.min.score"));
|
||||
|
||||
size_t selected_n_cores = Core()->getConfigut64("basefind.max.threads");
|
||||
if (selected_n_cores < n_cores && selected_n_cores > 0) {
|
||||
ui->nCoresCombo->setCurrentIndex(n_cores - selected_n_cores);
|
||||
}
|
||||
}
|
||||
|
||||
BaseFindDialog::~BaseFindDialog() {}
|
||||
|
||||
size_t BaseFindDialog::getNCores() const
|
||||
{
|
||||
size_t n_cores = rz_th_physical_core_number();
|
||||
return n_cores - ui->nCoresCombo->currentIndex();
|
||||
}
|
||||
|
||||
ut32 BaseFindDialog::getPointerSize() const
|
||||
{
|
||||
auto index = ui->pointerSizeCombo->currentIndex();
|
||||
QString value = ui->pointerSizeCombo->itemText(index);
|
||||
return value.toULong(nullptr, 0);
|
||||
}
|
||||
|
||||
RVA BaseFindDialog::getStartAddress() const
|
||||
{
|
||||
QString value = ui->startAddressEdit->text();
|
||||
return value.toULongLong(nullptr, 0);
|
||||
}
|
||||
|
||||
RVA BaseFindDialog::getEndAddress() const
|
||||
{
|
||||
QString value = ui->endAddressEdit->text();
|
||||
return value.toULongLong(nullptr, 0);
|
||||
}
|
||||
|
||||
RVA BaseFindDialog::getAlignment() const
|
||||
{
|
||||
QString value = ui->alignmentEdit->text();
|
||||
return value.toULongLong(nullptr, 0);
|
||||
}
|
||||
|
||||
ut32 BaseFindDialog::getMinStrLen() const
|
||||
{
|
||||
return ui->minStrLenEdit->value();
|
||||
}
|
||||
|
||||
ut32 BaseFindDialog::getMinScore() const
|
||||
{
|
||||
return ui->minScoreEdit->value();
|
||||
}
|
||||
|
||||
void BaseFindDialog::on_buttonBox_accepted()
|
||||
{
|
||||
RzBaseFindOpt options = {};
|
||||
options.max_threads = getNCores();
|
||||
options.pointer_size = getPointerSize();
|
||||
options.start_address = getStartAddress();
|
||||
options.end_address = getEndAddress();
|
||||
options.alignment = getAlignment();
|
||||
options.min_score = getMinScore();
|
||||
options.min_string_len = getMinStrLen();
|
||||
options.callback = nullptr;
|
||||
options.user = nullptr;
|
||||
|
||||
BaseFindSearchDialog *bfs = new BaseFindSearchDialog(parentWidget());
|
||||
bfs->show(&options);
|
||||
}
|
||||
|
||||
void BaseFindDialog::on_buttonBox_rejected() {}
|
38
src/tools/basefind/BaseFindDialog.h
Normal file
38
src/tools/basefind/BaseFindDialog.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef BASEFIND_DIALOG_H
|
||||
#define BASEFIND_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QListWidgetItem>
|
||||
#include <memory>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
|
||||
namespace Ui {
|
||||
class BaseFindDialog;
|
||||
}
|
||||
|
||||
class BaseFindDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BaseFindDialog(QWidget *parent = nullptr);
|
||||
~BaseFindDialog();
|
||||
|
||||
size_t getNCores() const;
|
||||
ut32 getPointerSize() const;
|
||||
RVA getStartAddress() const;
|
||||
RVA getEndAddress() const;
|
||||
RVA getAlignment() const;
|
||||
ut32 getMinStrLen() const;
|
||||
ut32 getMinScore() const;
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::BaseFindDialog> ui;
|
||||
};
|
||||
|
||||
#endif // BASEFIND_DIALOG_H
|
246
src/tools/basefind/BaseFindDialog.ui
Normal file
246
src/tools/basefind/BaseFindDialog.ui
Normal file
@ -0,0 +1,246 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BaseFindDialog</class>
|
||||
<widget class="QDialog" name="BaseFindDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::NonModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>373</width>
|
||||
<height>348</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">BaseFind</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="0" column="0">
|
||||
<widget class="QLabel" name="nCoresLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cores:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="nCoresCombo"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="pointerSizeLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pointer Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="pointerSizeCombo">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>32</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>64</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="startAddressLabel">
|
||||
<property name="text">
|
||||
<string>Start Address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="startAddressEdit">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>382</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="endAddressLabel">
|
||||
<property name="text">
|
||||
<string>End Address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="endAddressEdit">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>382</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="alignmentLabel">
|
||||
<property name="text">
|
||||
<string>Alignment:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="alignmentEdit">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>382</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="minStrLenLabel">
|
||||
<property name="text">
|
||||
<string>Min String Length:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="minStrLenEdit">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>382</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="minScoreLabel">
|
||||
<property name="text">
|
||||
<string>Min Score:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="minScoreEdit">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>382</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</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>
|
||||
<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>accepted()</signal>
|
||||
<receiver>BaseFindDialog</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>BaseFindDialog</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>
|
161
src/tools/basefind/BaseFindResultsDialog.cpp
Normal file
161
src/tools/basefind/BaseFindResultsDialog.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
#include "BaseFindResultsDialog.h"
|
||||
#include "ui_BaseFindResultsDialog.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
#include <CutterApplication.h>
|
||||
|
||||
BaseFindResultsModel::BaseFindResultsModel(QList<BasefindResultDescription> *list, QObject *parent)
|
||||
: QAbstractListModel(parent), list(list)
|
||||
{
|
||||
}
|
||||
|
||||
int BaseFindResultsModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return list->count();
|
||||
}
|
||||
|
||||
int BaseFindResultsModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return BaseFindResultsModel::ColumnCount;
|
||||
}
|
||||
|
||||
QVariant BaseFindResultsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() >= list->count())
|
||||
return QVariant();
|
||||
|
||||
const BasefindResultDescription &entry = list->at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (index.column()) {
|
||||
case ScoreColumn:
|
||||
return QString::asprintf("%u", entry.score);
|
||||
case CandidateColumn:
|
||||
return QString::asprintf("%#010llx", entry.candidate);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole: {
|
||||
return QString::asprintf("%#010llx", entry.candidate);
|
||||
}
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant BaseFindResultsModel::headerData(int section, Qt::Orientation, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (section) {
|
||||
case ScoreColumn:
|
||||
return tr("Score");
|
||||
case CandidateColumn:
|
||||
return tr("Address");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
BaseFindResultsDialog::BaseFindResultsDialog(QList<BasefindResultDescription> results,
|
||||
QWidget *parent)
|
||||
: QDialog(parent), list(results), ui(new Ui::BaseFindResultsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
|
||||
model = new BaseFindResultsModel(&list, this);
|
||||
ui->tableView->setModel(model);
|
||||
ui->tableView->sortByColumn(BaseFindResultsModel::ScoreColumn, Qt::AscendingOrder);
|
||||
ui->tableView->verticalHeader()->hide();
|
||||
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
blockMenu = new QMenu(this);
|
||||
actionCopyCandidate = new QAction(tr("Copy %1"), this);
|
||||
actionSetLoadAddr = new QAction(tr("Reopen Cutter with base address as %1"), this);
|
||||
actionSetMapAddr = new QAction(tr("Reopen Cutter with map address as %1"), this);
|
||||
|
||||
connect(ui->tableView, &QWidget::customContextMenuRequested, this,
|
||||
&BaseFindResultsDialog::showItemContextMenu);
|
||||
connect(actionCopyCandidate, &QAction::triggered, this,
|
||||
&BaseFindResultsDialog::onActionCopyLine);
|
||||
connect(actionSetLoadAddr, &QAction::triggered, this,
|
||||
&BaseFindResultsDialog::onActionSetLoadAddr);
|
||||
connect(actionSetMapAddr, &QAction::triggered, this,
|
||||
&BaseFindResultsDialog::onActionSetMapAddr);
|
||||
|
||||
blockMenu->addAction(actionSetLoadAddr);
|
||||
blockMenu->addAction(actionSetMapAddr);
|
||||
blockMenu->addAction(actionCopyCandidate);
|
||||
addActions(blockMenu->actions());
|
||||
}
|
||||
|
||||
void BaseFindResultsDialog::showItemContextMenu(const QPoint &pt)
|
||||
{
|
||||
auto index = ui->tableView->currentIndex();
|
||||
if (index.isValid()) {
|
||||
const BasefindResultDescription &entry = list.at(index.row());
|
||||
candidate = entry.candidate;
|
||||
auto addr = QString::asprintf("%#010llx", candidate);
|
||||
actionCopyCandidate->setText(tr("Copy %1").arg(addr));
|
||||
actionSetLoadAddr->setText(tr("Reopen Cutter with base address as %1").arg(addr));
|
||||
actionSetMapAddr->setText(tr("Reopen Cutter with map address as %1").arg(addr));
|
||||
blockMenu->exec(this->mapToGlobal(pt));
|
||||
}
|
||||
}
|
||||
|
||||
void BaseFindResultsDialog::onActionCopyLine()
|
||||
{
|
||||
auto clipboard = QApplication::clipboard();
|
||||
clipboard->setText(QString::asprintf("%#010llx", candidate));
|
||||
}
|
||||
|
||||
void BaseFindResultsDialog::onActionSetLoadAddr()
|
||||
{
|
||||
auto cutter = static_cast<CutterApplication *>(qApp);
|
||||
auto options = cutter->getInitialOptions();
|
||||
auto oldValue = options.binLoadAddr;
|
||||
|
||||
// override options to generate correct args
|
||||
options.binLoadAddr = candidate;
|
||||
cutter->setInitialOptions(options);
|
||||
auto args = cutter->getArgs();
|
||||
|
||||
// revert back options
|
||||
options.binLoadAddr = oldValue;
|
||||
cutter->setInitialOptions(options);
|
||||
|
||||
cutter->launchNewInstance(args);
|
||||
}
|
||||
|
||||
void BaseFindResultsDialog::onActionSetMapAddr()
|
||||
{
|
||||
auto cutter = static_cast<CutterApplication *>(qApp);
|
||||
auto options = cutter->getInitialOptions();
|
||||
auto oldValue = options.mapAddr;
|
||||
|
||||
// override options to generate correct args
|
||||
options.mapAddr = candidate;
|
||||
cutter->setInitialOptions(options);
|
||||
auto args = cutter->getArgs();
|
||||
|
||||
// revert back options
|
||||
options.mapAddr = oldValue;
|
||||
cutter->setInitialOptions(options);
|
||||
|
||||
cutter->launchNewInstance(args);
|
||||
}
|
||||
|
||||
BaseFindResultsDialog::~BaseFindResultsDialog() {}
|
||||
|
||||
void BaseFindResultsDialog::on_buttonBox_rejected() {}
|
68
src/tools/basefind/BaseFindResultsDialog.h
Normal file
68
src/tools/basefind/BaseFindResultsDialog.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef BASEFIND_RESULTS_DIALOG_H
|
||||
#define BASEFIND_RESULTS_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAbstractListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <memory>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
|
||||
class BaseFindResultsDialog;
|
||||
|
||||
namespace Ui {
|
||||
class BaseFindResultsDialog;
|
||||
}
|
||||
|
||||
class BaseFindResultsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend BaseFindResultsDialog;
|
||||
|
||||
public:
|
||||
enum Column { ScoreColumn = 0, CandidateColumn, ColumnCount };
|
||||
|
||||
BaseFindResultsModel(QList<BasefindResultDescription> *list, QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
private:
|
||||
QList<BasefindResultDescription> *list;
|
||||
};
|
||||
|
||||
class BaseFindResultsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BaseFindResultsDialog(QList<BasefindResultDescription> results,
|
||||
QWidget *parent = nullptr);
|
||||
~BaseFindResultsDialog();
|
||||
|
||||
public slots:
|
||||
void showItemContextMenu(const QPoint &pt);
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
private:
|
||||
void onActionCopyLine();
|
||||
void onActionSetLoadAddr();
|
||||
void onActionSetMapAddr();
|
||||
|
||||
QList<BasefindResultDescription> list;
|
||||
std::unique_ptr<Ui::BaseFindResultsDialog> ui;
|
||||
BaseFindResultsModel *model;
|
||||
QMenu *blockMenu;
|
||||
QAction *actionCopyCandidate;
|
||||
QAction *actionSetLoadAddr;
|
||||
QAction *actionSetMapAddr;
|
||||
RVA candidate;
|
||||
};
|
||||
|
||||
#endif // BASEFIND_RESULTS_DIALOG_H
|
70
src/tools/basefind/BaseFindResultsDialog.ui
Normal file
70
src/tools/basefind/BaseFindResultsDialog.ui
Normal file
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BaseFindResultsDialog</class>
|
||||
<widget class="QDialog" name="BaseFindResultsDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::NonModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>582</width>
|
||||
<height>382</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">BaseFind Results</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="QTableView" name="tableView"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BaseFindResultsDialog</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>
|
66
src/tools/basefind/BaseFindSearchDialog.cpp
Normal file
66
src/tools/basefind/BaseFindSearchDialog.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "BaseFindSearchDialog.h"
|
||||
#include "ui_BaseFindSearchDialog.h"
|
||||
|
||||
#include "BaseFindResultsDialog.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QFormLayout>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
#include <rz_th.h>
|
||||
|
||||
BaseFindSearchDialog::BaseFindSearchDialog(QWidget *parent)
|
||||
: QDialog(parent), basefind(new Basefind(Core())), ui(new Ui::BaseFindSearchDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
}
|
||||
|
||||
BaseFindSearchDialog::~BaseFindSearchDialog() {}
|
||||
|
||||
void BaseFindSearchDialog::show(RzBaseFindOpt *opts)
|
||||
{
|
||||
size_t n_cores = rz_th_physical_core_number();
|
||||
if (opts->max_threads > n_cores || opts->max_threads < 1) {
|
||||
opts->max_threads = n_cores;
|
||||
}
|
||||
|
||||
QFormLayout *layout = new QFormLayout();
|
||||
ui->scrollAreaWidgetContents->setLayout(layout);
|
||||
for (ut32 i = 0; i < opts->max_threads; ++i) {
|
||||
QString label = QString::asprintf("Core %u", i);
|
||||
QProgressBar *pbar = new QProgressBar(nullptr);
|
||||
layout->addRow(label, pbar);
|
||||
pbar->setRange(0, 100);
|
||||
bars.push_back(pbar);
|
||||
}
|
||||
|
||||
if (!basefind->setOptions(opts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(this, &BaseFindSearchDialog::cancelSearch, basefind.get(), &Basefind::cancel);
|
||||
connect(basefind.get(), &Basefind::progress, this, &BaseFindSearchDialog::onProgress);
|
||||
connect(basefind.get(), &Basefind::complete, this, &BaseFindSearchDialog::onCompletion);
|
||||
|
||||
basefind->start();
|
||||
this->QDialog::show();
|
||||
}
|
||||
|
||||
void BaseFindSearchDialog::onProgress(BasefindCoreStatusDescription status)
|
||||
{
|
||||
bars[status.index]->setValue(status.percentage);
|
||||
}
|
||||
|
||||
void BaseFindSearchDialog::onCompletion()
|
||||
{
|
||||
auto results = basefind->results();
|
||||
BaseFindResultsDialog *table = new BaseFindResultsDialog(results, parentWidget());
|
||||
table->show();
|
||||
this->close();
|
||||
}
|
||||
|
||||
void BaseFindSearchDialog::on_buttonBox_rejected()
|
||||
{
|
||||
emit cancelSearch();
|
||||
}
|
41
src/tools/basefind/BaseFindSearchDialog.h
Normal file
41
src/tools/basefind/BaseFindSearchDialog.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef BASEFIND_SEARCH_DIALOG_H
|
||||
#define BASEFIND_SEARCH_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QListWidgetItem>
|
||||
#include <QProgressBar>
|
||||
#include <memory>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
|
||||
namespace Ui {
|
||||
class BaseFindSearchDialog;
|
||||
}
|
||||
|
||||
class BaseFindSearchDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BaseFindSearchDialog(QWidget *parent = nullptr);
|
||||
~BaseFindSearchDialog();
|
||||
|
||||
void show(RzBaseFindOpt *opts);
|
||||
|
||||
public slots:
|
||||
void onProgress(BasefindCoreStatusDescription status);
|
||||
void onCompletion();
|
||||
|
||||
signals:
|
||||
void cancelSearch();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
private:
|
||||
std::vector<QProgressBar *> bars;
|
||||
std::unique_ptr<Basefind> basefind;
|
||||
std::unique_ptr<Ui::BaseFindSearchDialog> ui;
|
||||
};
|
||||
|
||||
#endif // BASEFIND_SEARCH_DIALOG_H
|
112
src/tools/basefind/BaseFindSearchDialog.ui
Normal file
112
src/tools/basefind/BaseFindSearchDialog.ui
Normal file
@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BaseFindSearchDialog</class>
|
||||
<widget class="QDialog" name="BaseFindSearchDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::NonModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>582</width>
|
||||
<height>382</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">Searching for base address</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="QScrollArea" name="scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>564</width>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</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>BaseFindSearchDialog</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