2017-10-01 19:09:42 +00:00
|
|
|
#include "OptionsDialog.h"
|
|
|
|
#include "ui_OptionsDialog.h"
|
|
|
|
#include "MainWindow.h"
|
2017-10-02 09:41:28 +00:00
|
|
|
#include "dialogs/NewFileDialog.h"
|
2017-10-01 19:09:42 +00:00
|
|
|
#include "utils/Helpers.h"
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
#include <QSettings>
|
2017-07-11 16:41:58 +00:00
|
|
|
#include <QFileInfo>
|
2017-09-27 20:23:18 +00:00
|
|
|
#include <QFileDialog>
|
2017-04-18 10:03:47 +00:00
|
|
|
|
2017-05-13 18:09:36 +00:00
|
|
|
OptionsDialog::OptionsDialog(MainWindow *main):
|
|
|
|
QDialog(0), // parent may not be main
|
2017-04-18 10:03:47 +00:00
|
|
|
analThread(this),
|
2017-10-09 18:08:35 +00:00
|
|
|
main(main),
|
2018-04-12 06:33:30 +00:00
|
|
|
core(Core()),
|
2017-10-24 08:18:16 +00:00
|
|
|
defaultAnalLevel(1),
|
2017-09-28 22:04:57 +00:00
|
|
|
ui(new Ui::OptionsDialog)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
2017-03-31 00:51:14 +00:00
|
|
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->progressBar->setVisible(0);
|
|
|
|
ui->statusLabel->setVisible(0);
|
2017-12-11 14:06:26 +00:00
|
|
|
ui->elapsedLabel->setVisible(0);
|
2018-02-12 12:22:53 +00:00
|
|
|
ui->logoSvgWidget->load(Config()->getLogoFile());
|
2017-04-10 12:22:18 +00:00
|
|
|
ui->analSlider->setValue(defaultAnalLevel);
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
// Fill the plugins combo
|
2017-10-09 18:08:35 +00:00
|
|
|
asm_plugins = core->getAsmPluginNames();
|
2017-05-03 09:09:57 +00:00
|
|
|
for (auto plugin : asm_plugins)
|
2017-09-27 20:23:18 +00:00
|
|
|
ui->archComboBox->addItem(plugin, plugin);
|
2017-10-09 18:08:35 +00:00
|
|
|
ui->archComboBox->setToolTip(core->cmd("e? asm.arch").trimmed());
|
2017-09-27 20:23:18 +00:00
|
|
|
|
|
|
|
// cpu combo box
|
|
|
|
ui->cpuComboBox->lineEdit()->setPlaceholderText(tr("Auto"));
|
2017-10-09 18:08:35 +00:00
|
|
|
ui->cpuComboBox->setToolTip(core->cmd("e? asm.cpu").trimmed());
|
2017-09-27 20:23:18 +00:00
|
|
|
updateCPUComboBox();
|
|
|
|
|
|
|
|
// os combo box
|
2017-10-09 18:08:35 +00:00
|
|
|
for (const auto &plugin : core->cmdList("e asm.os=?"))
|
2017-09-27 20:23:18 +00:00
|
|
|
ui->kernelComboBox->addItem(plugin, plugin);
|
2017-10-09 18:08:35 +00:00
|
|
|
ui->kernelComboBox->setToolTip(core->cmd("e? asm.os").trimmed());
|
2017-09-27 20:23:18 +00:00
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
ui->bitsComboBox->setToolTip(core->cmd("e? asm.bits").trimmed());
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2018-03-07 12:02:39 +00:00
|
|
|
ui->entry_analbb->setToolTip(core->cmd("e? anal.bb.maxsize").trimmed());
|
2018-03-21 20:32:32 +00:00
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
for (auto plugin : core->getRBinPluginDescriptions("bin"))
|
2017-09-29 11:32:53 +00:00
|
|
|
ui->formatComboBox->addItem(plugin.name, QVariant::fromValue(plugin));
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->hideFrame->setVisible(false);
|
2017-07-24 11:05:28 +00:00
|
|
|
ui->analoptionsFrame->setVisible(false);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-09-27 20:23:18 +00:00
|
|
|
updatePDBLayout();
|
|
|
|
|
|
|
|
connect(ui->pdbCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updatePDBLayout()));
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
// Add this so the dialog resizes when widgets are shown/hidden
|
|
|
|
//this->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
2017-03-31 22:47:37 +00:00
|
|
|
|
|
|
|
connect(&analThread, SIGNAL(finished()), this, SLOT(anal_finished()));
|
2017-12-06 12:32:35 +00:00
|
|
|
connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
2017-04-09 19:55:06 +00:00
|
|
|
|
2017-05-13 18:09:36 +00:00
|
|
|
ui->programLineEdit->setText(main->getFilename());
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-10-02 09:41:28 +00:00
|
|
|
OptionsDialog::~OptionsDialog() {}
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-09-27 20:23:18 +00:00
|
|
|
void OptionsDialog::updateCPUComboBox()
|
|
|
|
{
|
|
|
|
QString currentText = ui->cpuComboBox->lineEdit()->text();
|
|
|
|
ui->cpuComboBox->clear();
|
|
|
|
|
|
|
|
QString cmd = "e asm.cpu=?";
|
|
|
|
|
|
|
|
QString arch = getSelectedArch();
|
|
|
|
if (!arch.isNull())
|
|
|
|
cmd += " @a:" + arch;
|
|
|
|
|
|
|
|
ui->cpuComboBox->addItem("");
|
2017-10-09 18:08:35 +00:00
|
|
|
ui->cpuComboBox->addItems(core->cmdList(cmd));
|
2017-09-27 20:23:18 +00:00
|
|
|
|
|
|
|
ui->cpuComboBox->lineEdit()->setText(currentText);
|
|
|
|
}
|
|
|
|
|
2017-12-21 11:29:58 +00:00
|
|
|
void OptionsDialog::setInteractionEnabled(bool enabled)
|
|
|
|
{
|
|
|
|
ui->optionsWidget->setEnabled(enabled);
|
|
|
|
ui->okButton->setEnabled(enabled);
|
|
|
|
ui->cancelButton->setEnabled(enabled);
|
|
|
|
}
|
|
|
|
|
2017-09-27 20:23:18 +00:00
|
|
|
QString OptionsDialog::getSelectedArch()
|
|
|
|
{
|
|
|
|
QVariant archValue = ui->archComboBox->currentData();
|
|
|
|
return archValue.isValid() ? archValue.toString() : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString OptionsDialog::getSelectedCPU()
|
|
|
|
{
|
|
|
|
QString cpu = ui->cpuComboBox->currentText();
|
|
|
|
if (cpu.isNull() || cpu.isEmpty())
|
|
|
|
return nullptr;
|
|
|
|
return cpu;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OptionsDialog::getSelectedBits()
|
|
|
|
{
|
|
|
|
QString sel_bits = ui->bitsComboBox->currentText();
|
2018-03-21 20:32:32 +00:00
|
|
|
if (sel_bits != "Auto") {
|
2017-09-27 20:23:18 +00:00
|
|
|
return sel_bits.toInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-03-07 12:02:39 +00:00
|
|
|
int OptionsDialog::getSelectedBBSize()
|
|
|
|
{
|
|
|
|
QString sel_bbsize = ui->entry_analbb->text();
|
|
|
|
bool ok;
|
|
|
|
int bbsize = sel_bbsize.toInt(&ok);
|
|
|
|
if (ok)
|
|
|
|
return bbsize;
|
|
|
|
return 1024;
|
|
|
|
}
|
|
|
|
|
2018-01-20 10:35:31 +00:00
|
|
|
OptionsDialog::Endianness OptionsDialog::getSelectedEndianness()
|
|
|
|
{
|
2018-03-21 20:32:32 +00:00
|
|
|
switch (ui->endiannessComboBox->currentIndex()) {
|
2018-01-20 10:35:31 +00:00
|
|
|
case 1:
|
|
|
|
return Endianness::Little;
|
|
|
|
case 2:
|
|
|
|
return Endianness::Big;
|
|
|
|
default:
|
|
|
|
return Endianness::Auto;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-27 20:23:18 +00:00
|
|
|
QString OptionsDialog::getSelectedOS()
|
|
|
|
{
|
|
|
|
QVariant os = ui->kernelComboBox->currentData();
|
|
|
|
return os.isValid() ? os.toString() : nullptr;
|
|
|
|
}
|
|
|
|
|
2017-07-24 11:05:28 +00:00
|
|
|
void OptionsDialog::setupAndStartAnalysis(int level, QList<QString> advanced)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
2017-04-28 13:09:40 +00:00
|
|
|
ui->analSlider->setValue(level);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-12-21 11:29:58 +00:00
|
|
|
setInteractionEnabled(false);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// Show Progress Bar
|
2017-12-21 11:29:58 +00:00
|
|
|
ui->progressBar->setVisible(true);
|
|
|
|
ui->statusLabel->setVisible(true);
|
|
|
|
ui->elapsedLabel->setVisible(true);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-09-09 09:36:15 +00:00
|
|
|
ui->statusLabel->setText(tr("Starting analysis"));
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-05-13 18:09:36 +00:00
|
|
|
main->initUI();
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-12-11 14:06:26 +00:00
|
|
|
// Timer for showing elapsed analysis time.
|
|
|
|
analTimer.setInterval(1000);
|
|
|
|
analTimer.setSingleShot(false);
|
|
|
|
analTimer.start();
|
|
|
|
analElapsedTimer.start();
|
|
|
|
|
|
|
|
updateProgressTimer();
|
|
|
|
connect(&analTimer, SIGNAL(timeout()), this, SLOT(updateProgressTimer()));
|
|
|
|
|
2018-01-27 10:40:26 +00:00
|
|
|
// Threads stuff, connect signal/slot
|
2017-09-28 22:04:57 +00:00
|
|
|
connect(&analThread, &AnalThread::updateProgress, this, &OptionsDialog::updateProgress);
|
|
|
|
analThread.start(main, level, advanced);
|
|
|
|
}
|
|
|
|
|
2017-12-11 14:06:26 +00:00
|
|
|
void OptionsDialog::updateProgressTimer()
|
|
|
|
{
|
2018-03-21 20:32:32 +00:00
|
|
|
int secondsElapsed = (analElapsedTimer.elapsed() + 500) / 1000;
|
2017-12-11 14:06:26 +00:00
|
|
|
int minutesElapsed = secondsElapsed / 60;
|
|
|
|
int hoursElapsed = minutesElapsed / 60;
|
|
|
|
|
2017-12-14 12:26:49 +00:00
|
|
|
QString label = tr("Running for") + " ";
|
2018-03-21 20:32:32 +00:00
|
|
|
if (hoursElapsed) {
|
2017-12-11 14:06:26 +00:00
|
|
|
label += tr("%n hour", "%n hours", hoursElapsed);
|
|
|
|
label += " ";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (minutesElapsed) {
|
2017-12-11 14:06:26 +00:00
|
|
|
label += tr("%n minute", "%n minutes", minutesElapsed % 60);
|
|
|
|
label += " ";
|
|
|
|
}
|
|
|
|
label += tr("%n seconds", "%n second", secondsElapsed % 60);
|
|
|
|
ui->elapsedLabel->setText(label);
|
|
|
|
}
|
|
|
|
|
2017-09-28 22:04:57 +00:00
|
|
|
void OptionsDialog::updateProgress(const QString &status)
|
|
|
|
{
|
|
|
|
ui->statusLabel->setText(status);
|
2017-04-28 13:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OptionsDialog::on_okButton_clicked()
|
|
|
|
{
|
2017-07-24 11:05:28 +00:00
|
|
|
QList<QString> advanced = QList<QString>();
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->analSlider->value() == 3) {
|
|
|
|
if (ui->aa_symbols->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "aa";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->aar_references->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "aar";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->aac_calls->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "aac";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->aab_basicblocks->isChecked()) {
|
2017-12-04 21:36:02 +00:00
|
|
|
advanced << "aab";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->aan_rename->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "aan";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->aae_emulate->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "aae";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->aat_consecutive->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "aat";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->afta_typeargument->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "afta";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->aaT_aftertrap->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "aaT";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->aap_preludes->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "aap";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->jmptbl->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "e! anal.jmptbl";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->pushret->isChecked()) {
|
2017-07-24 11:05:28 +00:00
|
|
|
advanced << "e! anal.pushret";
|
|
|
|
}
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->hasnext->isChecked()) {
|
2017-12-04 21:36:02 +00:00
|
|
|
advanced << "e! anal.hasnext";
|
|
|
|
}
|
2017-07-24 11:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
setupAndStartAnalysis(ui->analSlider->value(), advanced);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OptionsDialog::anal_finished()
|
|
|
|
{
|
2018-03-21 20:32:32 +00:00
|
|
|
if (analThread.isInterrupted()) {
|
2018-03-09 12:57:57 +00:00
|
|
|
done(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-09 09:36:15 +00:00
|
|
|
ui->statusLabel->setText(tr("Loading interface"));
|
|
|
|
main->addOutput(tr(" > Analysis finished"));
|
2017-05-13 18:09:36 +00:00
|
|
|
|
|
|
|
main->finalizeOpen();
|
2017-12-06 13:46:10 +00:00
|
|
|
done(0);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2018-03-09 12:57:57 +00:00
|
|
|
void OptionsDialog::closeEvent(QCloseEvent *event)
|
|
|
|
{
|
2018-03-21 20:32:32 +00:00
|
|
|
if (analThread.isRunning()) {
|
2018-03-09 12:57:57 +00:00
|
|
|
analThread.interruptAndWait();
|
|
|
|
}
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
|
2017-04-10 12:22:18 +00:00
|
|
|
QString OptionsDialog::analysisDescription(int level)
|
|
|
|
{
|
|
|
|
//TODO: replace this with meaningful descriptions
|
2018-03-21 20:32:32 +00:00
|
|
|
switch (level) {
|
2017-04-10 12:22:18 +00:00
|
|
|
case 0:
|
2017-07-24 11:05:28 +00:00
|
|
|
return tr("No analysis");
|
2017-04-10 12:22:18 +00:00
|
|
|
case 1:
|
2017-07-24 11:05:28 +00:00
|
|
|
return tr("Auto-Analysis (aaa)");
|
2017-04-10 12:22:18 +00:00
|
|
|
case 2:
|
2017-07-24 11:05:28 +00:00
|
|
|
return tr("Auto-Analysis Experimental (aaaa)");
|
2017-04-10 12:22:18 +00:00
|
|
|
case 3:
|
2017-07-24 11:05:28 +00:00
|
|
|
return tr("Advanced");
|
2017-04-10 12:22:18 +00:00
|
|
|
default:
|
|
|
|
return tr("Unknown");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
void OptionsDialog::on_analSlider_valueChanged(int value)
|
|
|
|
{
|
2017-04-12 15:02:35 +00:00
|
|
|
ui->analDescription->setText(tr("Level") + QString(": %1").arg(analysisDescription(value)));
|
2018-03-21 20:32:32 +00:00
|
|
|
if (value == 0) {
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->analCheckBox->setChecked(false);
|
2017-09-09 09:36:15 +00:00
|
|
|
ui->analCheckBox->setText(tr("Analysis: Disabled"));
|
2018-03-21 20:32:32 +00:00
|
|
|
} else {
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->analCheckBox->setChecked(true);
|
2017-09-09 09:36:15 +00:00
|
|
|
ui->analCheckBox->setText(tr("Analysis: Enabled"));
|
2018-03-21 20:32:32 +00:00
|
|
|
if (value == 3) {
|
2017-07-24 11:05:28 +00:00
|
|
|
ui->analoptionsFrame->setVisible(true);
|
2018-03-21 20:32:32 +00:00
|
|
|
} else {
|
2017-07-24 11:05:28 +00:00
|
|
|
ui->analoptionsFrame->setVisible(false);
|
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OptionsDialog::on_AdvOptButton_clicked()
|
|
|
|
{
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->AdvOptButton->isChecked()) {
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->hideFrame->setVisible(true);
|
|
|
|
ui->AdvOptButton->setArrowType(Qt::DownArrow);
|
2018-03-21 20:32:32 +00:00
|
|
|
} else {
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->hideFrame->setVisible(false);
|
|
|
|
ui->AdvOptButton->setArrowType(Qt::RightArrow);
|
|
|
|
}
|
|
|
|
}
|
2017-04-10 12:22:18 +00:00
|
|
|
|
|
|
|
void OptionsDialog::on_analCheckBox_clicked(bool checked)
|
|
|
|
{
|
2017-04-13 15:51:58 +00:00
|
|
|
if (!checked)
|
2017-04-10 12:22:18 +00:00
|
|
|
defaultAnalLevel = ui->analSlider->value();
|
|
|
|
ui->analSlider->setValue(checked ? defaultAnalLevel : 0);
|
|
|
|
}
|
2017-09-27 20:23:18 +00:00
|
|
|
|
|
|
|
void OptionsDialog::on_archComboBox_currentIndexChanged(int)
|
|
|
|
{
|
|
|
|
updateCPUComboBox();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OptionsDialog::updatePDBLayout()
|
|
|
|
{
|
|
|
|
ui->pdbWidget->setEnabled(ui->pdbCheckBox->isChecked());
|
|
|
|
}
|
|
|
|
|
|
|
|
void OptionsDialog::on_pdbSelectButton_clicked()
|
|
|
|
{
|
|
|
|
QFileDialog dialog(this);
|
|
|
|
dialog.setWindowTitle(tr("Select PDB file"));
|
|
|
|
dialog.setNameFilters({ tr("PDB file (*.pdb)"), tr("All files (*)") });
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
if (!dialog.exec()) {
|
2017-09-27 20:23:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString fileName = dialog.selectedFiles().first();
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
if (!fileName.isEmpty()) {
|
2017-09-27 20:23:18 +00:00
|
|
|
ui->pdbLineEdit->setText(fileName);
|
|
|
|
}
|
|
|
|
}
|
2017-12-06 12:32:35 +00:00
|
|
|
|
|
|
|
void OptionsDialog::reject()
|
|
|
|
{
|
|
|
|
done(0);
|
|
|
|
NewFileDialog *n = new NewFileDialog(nullptr);
|
|
|
|
n->show();
|
|
|
|
}
|