mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 10:58:51 +00:00
Use AsyncTaskDialog for initial Analysis
This commit is contained in:
parent
896925736f
commit
3e8b76138c
@ -6,10 +6,8 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
|
||||||
AnalTask::AnalTask(OptionsDialog *parent) :
|
AnalTask::AnalTask(QObject *parent) :
|
||||||
AsyncTask(parent),
|
AsyncTask(parent)
|
||||||
level(2),
|
|
||||||
main(nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,13 +15,6 @@ AnalTask::~AnalTask()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalTask::setSettings(MainWindow *main, int level, QList<QString> advanced)
|
|
||||||
{
|
|
||||||
this->main = main;
|
|
||||||
this->level = level;
|
|
||||||
this->advanced = advanced;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalTask::interrupt()
|
void AnalTask::interrupt()
|
||||||
{
|
{
|
||||||
AsyncTask::interrupt();
|
AsyncTask::interrupt();
|
||||||
@ -39,42 +30,27 @@ void AnalTask::interruptAndWait()
|
|||||||
|
|
||||||
void AnalTask::runTask()
|
void AnalTask::runTask()
|
||||||
{
|
{
|
||||||
const auto optionsDialog = dynamic_cast<OptionsDialog *>(parent());
|
|
||||||
const auto &ui = optionsDialog->ui;
|
|
||||||
bool va = ui->vaCheckBox->isChecked();
|
|
||||||
ut64 binLoadAddr = UT64_MAX; // Where the bin header is located in the file (-B)
|
|
||||||
if (ui->entry_loadOffset->text().length() > 0)
|
|
||||||
binLoadAddr = Core()->math(ui->entry_loadOffset->text());
|
|
||||||
ut64 mapAddr = Core()->math(ui->entry_mapOffset->text()); // Where to map the file once loaded (-m)
|
|
||||||
|
|
||||||
log(tr("Loading Binary...\n"));
|
log(tr("Loading Binary...\n"));
|
||||||
|
|
||||||
// Set the CPU details (handle auto)
|
Core()->setCPU(options.arch, options.cpu, options.bits);
|
||||||
Core()->setCPU(optionsDialog->getSelectedArch(), optionsDialog->getSelectedCPU(),
|
|
||||||
optionsDialog->getSelectedBits());
|
|
||||||
|
|
||||||
// Binary opening permissions (read/write/execute)
|
|
||||||
int perms = R_IO_READ | R_IO_EXEC;
|
int perms = R_IO_READ | R_IO_EXEC;
|
||||||
if (ui->writeCheckBox->isChecked())
|
if (options.writeEnabled)
|
||||||
perms |= R_IO_WRITE;
|
perms |= R_IO_WRITE;
|
||||||
|
|
||||||
// Check if we must load and parse binary header (ELF, PE, ...)
|
|
||||||
bool loadBinInfo = !ui->binCheckBox->isChecked();
|
|
||||||
QString forceBinPlugin = nullptr;
|
|
||||||
QVariant forceBinPluginData = ui->formatComboBox->currentData();
|
|
||||||
if (!forceBinPluginData.isNull()) {
|
|
||||||
RBinPluginDescription pluginDesc = forceBinPluginData.value<RBinPluginDescription>();
|
|
||||||
forceBinPlugin = pluginDesc.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Demangle (must be before file Core()->loadFile)
|
// Demangle (must be before file Core()->loadFile)
|
||||||
Core()->setConfig("bin.demangle", ui->demangleCheckBox->isChecked());
|
Core()->setConfig("bin.demangle", options.demangle);
|
||||||
|
|
||||||
// Do not reload the file if already loaded
|
// Do not reload the file if already loaded
|
||||||
QJsonArray openedFiles = Core()->getOpenedFiles();
|
QJsonArray openedFiles = Core()->getOpenedFiles();
|
||||||
if (!openedFiles.size()) {
|
if (!openedFiles.size()) {
|
||||||
bool fileLoaded = Core()->loadFile(main->getFilename(), binLoadAddr, mapAddr, perms, va, loadBinInfo,
|
bool fileLoaded = Core()->loadFile(options.filename,
|
||||||
forceBinPlugin);
|
options.binLoadAddr,
|
||||||
|
options.mapAddr,
|
||||||
|
perms,
|
||||||
|
options.useVA,
|
||||||
|
options.loadBinInfo,
|
||||||
|
options.forceBinPlugin);
|
||||||
if (!fileLoaded) {
|
if (!fileLoaded) {
|
||||||
// Something wrong happened, fallback to open dialog
|
// Something wrong happened, fallback to open dialog
|
||||||
emit openFileFailed();
|
emit openFileFailed();
|
||||||
@ -83,32 +59,32 @@ void AnalTask::runTask()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set asm OS configuration
|
if (!options.os.isNull()) {
|
||||||
QString os = optionsDialog->getSelectedOS();
|
Core()->cmd("e asm.os=" + options.os);
|
||||||
if (!os.isNull()) {
|
|
||||||
Core()->cmd("e asm.os=" + os);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load PDB and/or scripts
|
// Load PDB and/or scripts
|
||||||
if (ui->pdbCheckBox->isChecked()) {
|
if (!options.pdbFile.isNull()) {
|
||||||
Core()->loadPDB(ui->pdbLineEdit->text());
|
Core()->loadPDB(options.pdbFile);
|
||||||
}
|
|
||||||
if (ui->scriptCheckBox->isChecked()) {
|
|
||||||
Core()->loadScript(ui->scriptLineEdit->text());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set various options
|
if (!options.script.isNull()) {
|
||||||
if (optionsDialog->getSelectedEndianness() != OptionsDialog::Endianness::Auto) {
|
Core()->loadScript(options.script);
|
||||||
Core()->setEndianness(optionsDialog->getSelectedEndianness() == OptionsDialog::Endianness::Big);
|
|
||||||
}
|
}
|
||||||
Core()->setBBSize(optionsDialog->getSelectedBBSize());
|
|
||||||
|
if (options.endian != InitialOptions::Endianness::Auto) {
|
||||||
|
Core()->setEndianness(options.endian == InitialOptions::Endianness::Big);
|
||||||
|
}
|
||||||
|
|
||||||
|
Core()->setBBSize(options.bbsize);
|
||||||
|
|
||||||
// Use prj.simple as default as long as regular projects are broken
|
// Use prj.simple as default as long as regular projects are broken
|
||||||
Core()->setConfig("prj.simple", true);
|
Core()->setConfig("prj.simple", true);
|
||||||
|
|
||||||
// Start analysis
|
// Start analysis
|
||||||
log(tr("Analysis in progress...\n"));
|
log(tr("Analysis in progress...\n"));
|
||||||
|
|
||||||
Core()->analyze(this->level, this->advanced);
|
Core()->analyze(options.analLevel, options.analAdvanced);
|
||||||
|
|
||||||
log(tr("Analysis complete!"));
|
log(tr("Analysis complete!"));
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,56 @@
|
|||||||
#define ANALTHREAD_H
|
#define ANALTHREAD_H
|
||||||
|
|
||||||
#include "utils/AsyncTask.h"
|
#include "utils/AsyncTask.h"
|
||||||
|
#include "Cutter.h"
|
||||||
|
|
||||||
class CutterCore;
|
class CutterCore;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class OptionsDialog;
|
class OptionsDialog;
|
||||||
|
|
||||||
|
struct InitialOptions
|
||||||
|
{
|
||||||
|
enum class Endianness { Auto, Little, Big };
|
||||||
|
|
||||||
|
QString filename;
|
||||||
|
|
||||||
|
bool useVA = true;
|
||||||
|
RVA binLoadAddr = RVA_INVALID;
|
||||||
|
RVA mapAddr = RVA_INVALID;
|
||||||
|
|
||||||
|
QString arch;
|
||||||
|
QString cpu;
|
||||||
|
int bits = 0;
|
||||||
|
QString os;
|
||||||
|
|
||||||
|
Endianness endian;
|
||||||
|
|
||||||
|
bool writeEnabled = false;
|
||||||
|
bool loadBinInfo = true;
|
||||||
|
QString forceBinPlugin;
|
||||||
|
|
||||||
|
bool demangle = true;
|
||||||
|
|
||||||
|
QString pdbFile;
|
||||||
|
QString script;
|
||||||
|
|
||||||
|
int bbsize = 0;
|
||||||
|
|
||||||
|
int analLevel = 1;
|
||||||
|
QList<QString> analAdvanced;
|
||||||
|
};
|
||||||
|
|
||||||
class AnalTask : public AsyncTask
|
class AnalTask : public AsyncTask
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AnalTask(OptionsDialog *parent = nullptr);
|
explicit AnalTask(QObject *parent = nullptr);
|
||||||
~AnalTask();
|
~AnalTask();
|
||||||
|
|
||||||
void setSettings(MainWindow *main, int level, QList<QString> advanced);
|
QString getTitle() override { return tr("Initial Analysis"); }
|
||||||
|
|
||||||
|
void setOptions(const InitialOptions &options) { this->options = options; }
|
||||||
|
|
||||||
void interrupt() override;
|
void interrupt() override;
|
||||||
void interruptAndWait();
|
void interruptAndWait();
|
||||||
|
|
||||||
@ -26,9 +62,7 @@ signals:
|
|||||||
void openFileFailed();
|
void openFileFailed();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int level;
|
InitialOptions options;
|
||||||
QList<QString> advanced;
|
|
||||||
MainWindow *main;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ANALTHREAD_H
|
#endif // ANALTHREAD_H
|
||||||
|
@ -71,7 +71,6 @@ public:
|
|||||||
void openProject(const QString &project_name);
|
void openProject(const QString &project_name);
|
||||||
|
|
||||||
void initUI();
|
void initUI();
|
||||||
void finalizeOpen();
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @param quit whether to show destructive button in dialog
|
* @param quit whether to show destructive button in dialog
|
||||||
@ -99,6 +98,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void finalizeOpen();
|
||||||
|
|
||||||
void refreshAll();
|
void refreshAll();
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ AsyncTaskDialog::AsyncTaskDialog(AsyncTask *task, QWidget *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect(task, &AsyncTask::logChanged, this, &AsyncTaskDialog::updateLog);
|
connect(task, &AsyncTask::logChanged, this, &AsyncTaskDialog::updateLog);
|
||||||
|
connect(task, &AsyncTask::finished, this, &QWidget::close);
|
||||||
|
|
||||||
updateLog();
|
updateLog();
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
OptionsDialog::OptionsDialog(MainWindow *main):
|
OptionsDialog::OptionsDialog(MainWindow *main):
|
||||||
QDialog(0), // parent may not be main
|
QDialog(0), // parent may not be main
|
||||||
analTask(this),
|
|
||||||
main(main),
|
main(main),
|
||||||
core(Core()),
|
core(Core()),
|
||||||
defaultAnalLevel(1),
|
defaultAnalLevel(1),
|
||||||
@ -62,7 +61,7 @@ OptionsDialog::OptionsDialog(MainWindow *main):
|
|||||||
// Add this so the dialog resizes when widgets are shown/hidden
|
// Add this so the dialog resizes when widgets are shown/hidden
|
||||||
//this->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
//this->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||||
|
|
||||||
connect(&analTask, SIGNAL(finished()), this, SLOT(analysisFinished()));
|
//connect(&analTask, SIGNAL(finished()), this, SLOT(analysisFinished()));
|
||||||
connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||||
|
|
||||||
ui->programLineEdit->setText(main->getFilename());
|
ui->programLineEdit->setText(main->getFilename());
|
||||||
@ -128,15 +127,15 @@ int OptionsDialog::getSelectedBBSize()
|
|||||||
return 1024;
|
return 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionsDialog::Endianness OptionsDialog::getSelectedEndianness()
|
InitialOptions::Endianness OptionsDialog::getSelectedEndianness()
|
||||||
{
|
{
|
||||||
switch (ui->endiannessComboBox->currentIndex()) {
|
switch (ui->endiannessComboBox->currentIndex()) {
|
||||||
case 1:
|
case 1:
|
||||||
return Endianness::Little;
|
return InitialOptions::Endianness::Little;
|
||||||
case 2:
|
case 2:
|
||||||
return Endianness::Big;
|
return InitialOptions::Endianness::Big;
|
||||||
default:
|
default:
|
||||||
return Endianness::Auto;
|
return InitialOptions::Endianness::Auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,12 +160,50 @@ void OptionsDialog::setupAndStartAnalysis(int level, QList<QString> advanced)
|
|||||||
|
|
||||||
main->initUI();
|
main->initUI();
|
||||||
|
|
||||||
connect(&analTask, &AnalTask::openFileFailed, main, &MainWindow::openNewFileFailed);
|
InitialOptions options;
|
||||||
analTask.setSettings(main, level, advanced);
|
|
||||||
Core()->getAsyncTaskManager()->start(&analTask);
|
|
||||||
|
|
||||||
AsyncTaskDialog *taskDialog = new AsyncTaskDialog(&analTask, main);
|
options.filename = main->getFilename();
|
||||||
|
|
||||||
|
// Where the bin header is located in the file (-B)
|
||||||
|
if (ui->entry_loadOffset->text().length() > 0) {
|
||||||
|
options.binLoadAddr = Core()->math(ui->entry_loadOffset->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
options.mapAddr = Core()->math(ui->entry_mapOffset->text()); // Where to map the file once loaded (-m)
|
||||||
|
options.arch = getSelectedArch();
|
||||||
|
options.cpu = getSelectedCPU();
|
||||||
|
options.bits = getSelectedBits();
|
||||||
|
options.os = getSelectedOS();
|
||||||
|
options.writeEnabled = ui->writeCheckBox->isChecked();
|
||||||
|
options.loadBinInfo = !ui->binCheckBox->isChecked();
|
||||||
|
QVariant forceBinPluginData = ui->formatComboBox->currentData();
|
||||||
|
if (!forceBinPluginData.isNull()) {
|
||||||
|
RBinPluginDescription pluginDesc = forceBinPluginData.value<RBinPluginDescription>();
|
||||||
|
options.forceBinPlugin = pluginDesc.name;
|
||||||
|
}
|
||||||
|
options.demangle = ui->demangleCheckBox->isChecked();
|
||||||
|
if (ui->pdbCheckBox->isChecked()) {
|
||||||
|
options.pdbFile = ui->pdbLineEdit->text();
|
||||||
|
}
|
||||||
|
if (ui->scriptCheckBox->isChecked()) {
|
||||||
|
options.script = ui->scriptLineEdit->text();
|
||||||
|
}
|
||||||
|
options.endian = getSelectedEndianness();
|
||||||
|
options.bbsize = getSelectedBBSize();
|
||||||
|
|
||||||
|
AnalTask *analTask = new AnalTask(main);
|
||||||
|
analTask->setOptions(options);
|
||||||
|
|
||||||
|
connect(analTask, &AnalTask::openFileFailed, main, &MainWindow::openNewFileFailed);
|
||||||
|
connect(analTask, &AsyncTask::finished, main, &MainWindow::finalizeOpen);
|
||||||
|
|
||||||
|
Core()->getAsyncTaskManager()->start(analTask);
|
||||||
|
|
||||||
|
AsyncTaskDialog *taskDialog = new AsyncTaskDialog(analTask);
|
||||||
|
taskDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
taskDialog->show();
|
taskDialog->show();
|
||||||
|
|
||||||
|
done(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -225,11 +262,11 @@ void OptionsDialog::on_okButton_clicked()
|
|||||||
|
|
||||||
void OptionsDialog::analysisFinished()
|
void OptionsDialog::analysisFinished()
|
||||||
{
|
{
|
||||||
if (analTask.isInterrupted()) {
|
//if (analTask.isInterrupted()) {
|
||||||
updateProgress(tr("Analysis aborted."));
|
// updateProgress(tr("Analysis aborted."));
|
||||||
done(1);
|
// done(1);
|
||||||
return;
|
// return;
|
||||||
}
|
//}
|
||||||
|
|
||||||
updateProgress(tr("Loading interface..."));
|
updateProgress(tr("Loading interface..."));
|
||||||
main->addOutput(tr(" > Analysis finished"));
|
main->addOutput(tr(" > Analysis finished"));
|
||||||
@ -240,9 +277,9 @@ void OptionsDialog::analysisFinished()
|
|||||||
|
|
||||||
void OptionsDialog::closeEvent(QCloseEvent *event)
|
void OptionsDialog::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
if (analTask.isRunning()) {
|
//if (analTask.isRunning()) {
|
||||||
analTask.interruptAndWait();
|
// analTask.interruptAndWait();
|
||||||
}
|
//}
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ protected:
|
|||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AnalTask analTask;
|
|
||||||
MainWindow *main;
|
MainWindow *main;
|
||||||
CutterCore *core;
|
CutterCore *core;
|
||||||
int defaultAnalLevel;
|
int defaultAnalLevel;
|
||||||
@ -56,15 +55,13 @@ private:
|
|||||||
void setInteractionEnabled(bool enabled);
|
void setInteractionEnabled(bool enabled);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Endianness { Auto, Little, Big };
|
|
||||||
|
|
||||||
std::unique_ptr<Ui::OptionsDialog> ui;
|
std::unique_ptr<Ui::OptionsDialog> ui;
|
||||||
|
|
||||||
QString getSelectedArch();
|
QString getSelectedArch();
|
||||||
QString getSelectedCPU();
|
QString getSelectedCPU();
|
||||||
int getSelectedBits();
|
int getSelectedBits();
|
||||||
int getSelectedBBSize();
|
int getSelectedBBSize();
|
||||||
Endianness getSelectedEndianness();
|
InitialOptions::Endianness getSelectedEndianness();
|
||||||
QString getSelectedOS();
|
QString getSelectedOS();
|
||||||
|
|
||||||
void reject() override;
|
void reject() override;
|
||||||
|
@ -5,7 +5,7 @@ AsyncTask::AsyncTask(QObject *parent)
|
|||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
QRunnable()
|
QRunnable()
|
||||||
{
|
{
|
||||||
setAutoDelete(false);
|
setAutoDelete(true);
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user