1
0
Fork 0

AssembleDialog : Changed the instruction validation when Keep Size is enabled to be checked with a ValidateExpressionThread

ValidateExpressionThread : Added a method to see the callback when expression has changed to make it more generic
This commit is contained in:
Herzeh 2015-12-10 21:19:08 +01:00
parent 4c08df508b
commit 736e99ff56
6 changed files with 154 additions and 67 deletions

View File

@ -10,14 +10,21 @@ AssembleDialog::AssembleDialog(QWidget *parent) :
{
ui->setupUi(this);
setModal(true);
setFixedSize(this->size()); //fixed size
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
setWindowFlags(Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint);
#endif
setFixedSize(this->size()); //fixed size
mSelectedInstrVa = 0;
bKeepSizeChecked = false;
bFillWithNopsChecked = false;
selectedInstrVa = 0;
mValidateThread = new ValidateExpressionThread(this);
mValidateThread->setOnExpressionChangedCallback(std::bind(&AssembleDialog::validateInstruction, this, std::placeholders::_1));
connect(ui->lineEdit, SIGNAL(textEdited(QString)), this, SLOT(textChangedSlot(QString)));
connect(mValidateThread, SIGNAL(instructionChanged(dsint,QString)), this, SLOT(instructionChangedSlot(dsint, QString)));
}
AssembleDialog::~AssembleDialog()
@ -54,84 +61,126 @@ void AssembleDialog::setFillWithNopsLabel(const QString &text)
void AssembleDialog::setSelectedInstrVa(const duint va)
{
this->selectedInstrVa = va;
this->mSelectedInstrVa = va;
}
void AssembleDialog::compareTypedInstructionToSelected()
{
char error[MAX_ERROR_SIZE] = "";
BASIC_INSTRUCTION_INFO basicInstrInfo;
int typedInstructionSize = 0, selectedInstructionSize = 0;
// Get selected instruction info (size here)
DbgDisasmFastAt(this->selectedInstrVa, &basicInstrInfo);
selectedInstructionSize = basicInstrInfo.size;
// Get typed in instruction size
if(!DbgFunctions()->Assemble(this->selectedInstrVa, NULL, &typedInstructionSize, editText.toUtf8().constData(), error) || selectedInstructionSize == 0)
{
this->setKeepSizeLabel("<font color='orange'><b>Instruction decoding error : " + QString(error) + "</b></font>");
return;
}
if(typedInstructionSize > selectedInstructionSize)
{
int sizeDifference = typedInstructionSize - selectedInstructionSize;
QString errorMessage = "<font color='red'><b>Instruction bigger by " + QString::number(sizeDifference);
(sizeDifference == 1) ? errorMessage += QString(" byte</b></font>") : errorMessage += QString(" bytes</b></font>");
this->setKeepSizeLabel(errorMessage);
this->setOkButtonEnabled(false);
}
else
{
int sizeDifference = selectedInstructionSize - typedInstructionSize;
QString message;
if(!sizeDifference)
message = "<font color='#00cc00'><b>Instruction is same size</b></font>";
else
{
message = "<font color='#00cc00'><b>Instruction smaller by " + QString::number(sizeDifference);
(sizeDifference == 1) ? message += QString(" byte</b></font>") : message += QString(" bytes</b></font>");
}
this->setKeepSizeLabel(message);
this->setOkButtonEnabled(true);
}
}
void AssembleDialog::setOkButtonEnabled(bool enabled)
{
ui->pushButtonOk->setEnabled(enabled);
}
void AssembleDialog::validateInstruction(QString expression)
{
//void instructionChanged(bool validInstruction, dsint sizeDifference, QString error)
dsint sizeDifference = 0;
int typedInstructionSize = 0;
int selectedInstructionSize = 0;
bool validInstruction = false;
QByteArray error(MAX_ERROR_SIZE, 0);
BASIC_INSTRUCTION_INFO basicInstrInfo;
// Get selected instruction info (size here)
DbgDisasmFastAt(mSelectedInstrVa, &basicInstrInfo);
selectedInstructionSize = basicInstrInfo.size;
// Get typed in instruction size
if(!DbgFunctions()->Assemble(this->mSelectedInstrVa, NULL, &typedInstructionSize, editText.toUtf8().constData(), error.data()) || selectedInstructionSize == 0)
{
emit mValidateThread->emitInstructionChanged(0, QString(error));
return;
}
// Valid instruction
validInstruction = true;
sizeDifference = typedInstructionSize - selectedInstructionSize;
emit mValidateThread->emitInstructionChanged(sizeDifference, "");
}
void AssembleDialog::hideEvent(QHideEvent *event)
{
Q_UNUSED(event);
mValidateThread->stop();
mValidateThread->wait();
}
void AssembleDialog::textChangedSlot(QString text)
{
if(ui->checkBoxKeepSize->isChecked())
mValidateThread->textChanged(text);
}
void AssembleDialog::instructionChangedSlot(dsint sizeDifference, QString error)
{
if(ui->checkBoxKeepSize->isChecked())
{
// If there was an error
if(error.length())
{
this->setKeepSizeLabel("<font color='orange'><b>Instruction decoding error : " + error + "</b></font>");
return;
}
// No error
else
{
// SizeDifference > 0 <=> Typed instruction is bigger
if(sizeDifference > 0)
{
QString message = "<font color='red'><b>Instruction bigger by " + QString::number(sizeDifference);
if(sizeDifference == 1)
message += QString(" byte</b></font>");
else
message += QString(" bytes</b></font>");
this->setKeepSizeLabel(message);
this->setOkButtonEnabled(false);
}
// SizeDifference < 0 <=> Typed instruction is smaller
else if(sizeDifference < 0)
{
QString message = "<font color='#00cc00'><b>Instruction smaller by " + QString::number(sizeDifference);
if(sizeDifference == -1)
message += QString(" byte</b></font>");
else
message += QString(" bytes</b></font>");
this->setKeepSizeLabel(message);
this->setOkButtonEnabled(true);
}
// SizeDifference == 0 <=> Both instruction have same size
else
{
QString message = "<font color='#00cc00'><b>Instruction is same size</b></font>";
this->setKeepSizeLabel(message);
this->setOkButtonEnabled(true);
}
}
}
}
void AssembleDialog::on_lineEdit_textChanged(const QString &arg1)
{
editText = arg1;
if(ui->checkBoxKeepSize->isChecked() && editText.size())
compareTypedInstructionToSelected();
mValidateThread->start(editText);
}
void AssembleDialog::on_checkBoxKeepSize_clicked(bool checked)
{
// If first time ticking this checkbox, warn user about possible short dialog freeze when typing invalid instruction
if(checked && !AssembleDialog::bWarningShowedOnce)
{
int answer = QMessageBox::question(this, "Possible dialog freeze", "Enabling this option may cause this dialog to freeze for a short amount of time when typing invalid instruction. Do you still want to enable this ?", QMessageBox::Yes | QMessageBox::No);
if(answer == QMessageBox::No)
{
ui->checkBoxKeepSize->setChecked(false);
return;
}
else
AssembleDialog::bWarningShowedOnce = true;
}
if(checked && editText.size())
compareTypedInstructionToSelected();
{
mValidateThread->start();
mValidateThread->textChanged(ui->lineEdit->text()); // Have to add this or textChanged isn't called inside start()
}
else
{
mValidateThread->stop();
mValidateThread->wait();
ui->labelKeepSize->setText("");
ui->pushButtonOk->setEnabled(true);
}

View File

@ -4,6 +4,7 @@
#include <QDialog>
#include <functional>
#include "Bridge.h"
#include "ValidateExpressionThread.h"
namespace Ui
{
@ -30,17 +31,22 @@ public:
void setFillWithNopsLabel(const QString & text);
void setSelectedInstrVa(const duint va);
void compareTypedInstructionToSelected();
void setOkButtonEnabled(bool enabled);
void validateInstruction(QString expression);
void hideEvent(QHideEvent *event);
private slots:
void textChangedSlot(QString text);
void instructionChangedSlot(dsint sizeDifference, QString error);
void on_lineEdit_textChanged(const QString &arg1);
void on_checkBoxKeepSize_clicked(bool checked);
void on_checkBoxFillWithNops_clicked(bool checked);
private:
Ui::AssembleDialog *ui;
duint selectedInstrVa;
duint mSelectedInstrVa;
ValidateExpressionThread *mValidateThread;
};

View File

@ -21,6 +21,8 @@ GotoDialog::GotoDialog(QWidget* parent) : QDialog(parent), ui(new Ui::GotoDialog
validRangeEnd = 0;
fileOffset = false;
mValidateThread = new ValidateExpressionThread(this);
mValidateThread->setOnExpressionChangedCallback(std::bind(&GotoDialog::validateExpression, this, std::placeholders::_1));
connect(mValidateThread, SIGNAL(expressionChanged(bool, bool, dsint)), this, SLOT(expressionChanged(bool, bool, dsint)));
connect(ui->editExpression, SIGNAL(textEdited(QString)), mValidateThread, SLOT(textChanged(QString)));
connect(this, SIGNAL(finished(int)), this, SLOT(finishedSlot(int)));
@ -44,6 +46,14 @@ void GotoDialog::hideEvent(QHideEvent* event)
mValidateThread->wait();
}
void GotoDialog::validateExpression(QString expression)
{
duint value;
bool validExpression = DbgFunctions()->ValFromString(expression.toUtf8().constData(), &value);
bool validPointer = validExpression && DbgMemIsValidReadPtr(value);
this->mValidateThread->emitExpressionChanged(validExpression, validPointer, value);
}
void GotoDialog::expressionChanged(bool validExpression, bool validPointer, dsint value)
{
QString expression = ui->editExpression->text();

View File

@ -24,6 +24,7 @@ public:
QString modName;
void showEvent(QShowEvent* event);
void hideEvent(QHideEvent* event);
void validateExpression(QString expression);
private slots:
void expressionChanged(bool validExpression, bool validPointer, dsint value);

View File

@ -2,6 +2,7 @@
ValidateExpressionThread::ValidateExpressionThread(QObject* parent) : QThread(parent), mExpressionChanged(false), mStopThread(false)
{
this->mOnExpressionChangedCallback = nullptr;
}
void ValidateExpressionThread::start(QString initialValue)
@ -16,6 +17,16 @@ void ValidateExpressionThread::stop()
mStopThread = true;
}
void ValidateExpressionThread::emitExpressionChanged(bool validExpression, bool validPointer, dsint value)
{
emit expressionChanged(validExpression, validPointer, value);
}
void ValidateExpressionThread::emitInstructionChanged(dsint sizeDifference, QString error)
{
emit instructionChanged(sizeDifference, error);
}
void ValidateExpressionThread::textChanged(QString text)
{
mExpressionMutex.lock();
@ -27,6 +38,11 @@ void ValidateExpressionThread::textChanged(QString text)
mExpressionMutex.unlock();
}
void ValidateExpressionThread::setOnExpressionChangedCallback(EXPRESSIONCHANGEDCB callback)
{
mOnExpressionChangedCallback = callback;
}
void ValidateExpressionThread::run()
{
while(!mStopThread)
@ -36,12 +52,9 @@ void ValidateExpressionThread::run()
bool changed = mExpressionChanged;
mExpressionChanged = false;
mExpressionMutex.unlock();
if(changed)
if(changed && mOnExpressionChangedCallback != nullptr)
{
duint value;
bool validExpression = DbgFunctions()->ValFromString(expression.toUtf8().constData(), &value);
bool validPointer = validExpression && DbgMemIsValidReadPtr(value);
emit expressionChanged(validExpression, validPointer, value);
mOnExpressionChangedCallback(expression);
}
Sleep(50);
}

View File

@ -3,8 +3,11 @@
#include <QThread>
#include <QMutex>
#include <functional>
#include "Imports.h"
typedef std::function<void(QString expression) > EXPRESSIONCHANGEDCB;
class ValidateExpressionThread : public QThread
{
Q_OBJECT
@ -12,18 +15,23 @@ public:
ValidateExpressionThread(QObject* parent = 0);
void start(QString initialValue = QString());
void stop();
void emitExpressionChanged(bool validExpression, bool validPointer, dsint value);
void emitInstructionChanged(dsint sizeDifference, QString error);
signals:
void expressionChanged(bool validExpression, bool validPointer, dsint value);
void instructionChanged(dsint sizeDifference, QString error);
public slots:
void textChanged(QString text);
void setOnExpressionChangedCallback(EXPRESSIONCHANGEDCB callback);
private:
QMutex mExpressionMutex;
QString mExpressionText;
bool mExpressionChanged;
volatile bool mStopThread;
EXPRESSIONCHANGEDCB mOnExpressionChangedCallback;
void run();
};