Skip to content

Commit

Permalink
introduced and am using the concept of a plaform specific NOP fill byte
Browse files Browse the repository at this point in the history
instead of hard coded to 0x90
  • Loading branch information
eteran committed Apr 25, 2019
1 parent 68504da commit 4a3c4b0
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 110 deletions.
1 change: 1 addition & 0 deletions include/IDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class IDebugger {
virtual QMap<qlonglong, QString> exceptions() const = 0;
virtual QString exceptionName(qlonglong value) = 0;
virtual qlonglong exceptionValue(const QString &name) = 0;
virtual uint8_t nopFillByte() const = 0;

public:
// important register names
Expand Down
214 changes: 106 additions & 108 deletions plugins/Assembler/DialogAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,136 +116,134 @@ void DialogAssembler::set_address(edb::address_t address) {
//------------------------------------------------------------------------------
void DialogAssembler::on_buttonBox_accepted() {

const QString nasm_syntax = ui.assembly->currentText().trimmed();

const auto asm_root=getAssemblerDescription().documentElement();
if(!asm_root.isNull()) {
QDomElement asm_executable = asm_root.firstChildElement("executable");
QDomElement asm_template = asm_root.firstChildElement("template");
#ifdef EDB_ARM32
const auto mode = edb::v1::debugger_core->cpu_mode();
while(mode == IDebugger::CPUMode::ARM32 && asm_template.attribute("mode") != "arm" ||
mode == IDebugger::CPUMode::Thumb && asm_template.attribute("mode") != "thumb") {

asm_template = asm_template.nextSiblingElement("template");
if(asm_template.isNull()) {
QMessageBox::critical(
this,
tr("Error running assembler"),
tr("Failed to locate source file template for current CPU mode"));
if(IDebugger *core = edb::v1::debugger_core) {
const QString nasm_syntax = ui.assembly->currentText().trimmed();

const auto asm_root = getAssemblerDescription().documentElement();
if(!asm_root.isNull()) {
QDomElement asm_executable = asm_root.firstChildElement("executable");
QDomElement asm_template = asm_root.firstChildElement("template");
#ifdef EDB_ARM32
const auto mode = core->cpu_mode();
while(mode == IDebugger::CPUMode::ARM32 && asm_template.attribute("mode") != "arm" ||
mode == IDebugger::CPUMode::Thumb && asm_template.attribute("mode") != "thumb") {

asm_template = asm_template.nextSiblingElement("template");
if(asm_template.isNull()) {
QMessageBox::critical(
this,
tr("Error running assembler"),
tr("Failed to locate source file template for current CPU mode"));
return;
}
}
#endif

const QString asm_name = asm_root.attribute("name");
const QString asm_cmd = asm_executable.attribute("command_line");
const QString asm_ext = asm_executable.attribute("extension");
Q_UNUSED(asm_name)

QString asm_code = asm_template.text();

QStringList command_line = edb::v1::parse_command_line(asm_cmd);
if(command_line.isEmpty()) {
QMessageBox::warning(this, tr("Couldn't Find Assembler"), tr("Failed to locate your assembler."));
return;
}
}
#endif

const QString asm_name = asm_root.attribute("name");
const QString asm_cmd = asm_executable.attribute("command_line");
const QString asm_ext = asm_executable.attribute("extension");
Q_UNUSED(asm_name)

QString asm_code = asm_template.text();

QStringList command_line = edb::v1::parse_command_line(asm_cmd);
if(command_line.isEmpty()) {
QMessageBox::warning(this, tr("Couldn't Find Assembler"), tr("Failed to locate your assembler."));
return;
}

QTemporaryFile source_file(QString("%1/edb_asm_temp_%2_XXXXXX.%3").arg(QDir::tempPath()).arg(QCoreApplication::applicationPid()).arg(asm_ext));
if(!source_file.open()) {
QMessageBox::critical(this, tr("Error Creating File"), tr("Failed to create temporary source file."));
return;
}

QTemporaryFile source_file(QString("%1/edb_asm_temp_%2_XXXXXX.%3").arg(QDir::tempPath()).arg(QCoreApplication::applicationPid()).arg(asm_ext));
if(!source_file.open()) {
QMessageBox::critical(this, tr("Error Creating File"), tr("Failed to create temporary source file."));
return;
}
QTemporaryFile output_file(QString("%1/edb_asm_temp_%2_XXXXXX.bin").arg(QDir::tempPath()).arg(QCoreApplication::applicationPid()));
if(!output_file.open()) {
QMessageBox::critical(this, tr("Error Creating File"), tr("Failed to create temporary object file."));
return;
}

QTemporaryFile output_file(QString("%1/edb_asm_temp_%2_XXXXXX.bin").arg(QDir::tempPath()).arg(QCoreApplication::applicationPid()));
if(!output_file.open()) {
QMessageBox::critical(this, tr("Error Creating File"), tr("Failed to create temporary object file."));
return;
}
const QString bitsStr = std::to_string(core->pointer_size()*8).c_str();
const QString addrStr = edb::v1::format_pointer(address_);

const QString bitsStr=std::to_string(edb::v1::debugger_core->pointer_size()*8).c_str();
const QString addrStr=edb::v1::format_pointer(address_);
static const auto bitsTag="%BITS%";
static const auto addrTag="%ADDRESS%";
static const auto insnTag="%INSTRUCTION%";
asm_code.replace(bitsTag, bitsStr);
asm_code.replace(addrTag, addrStr);
asm_code.replace(insnTag, nasm_syntax);

source_file.write(asm_code.toLatin1());
source_file.close();

QProcess process;
QString program(command_line[0]);

command_line.pop_front();

QStringList arguments = command_line;
for(auto &arg : arguments) {
arg.replace("%OUT%", output_file.fileName());
arg.replace("%IN%", source_file.fileName());
arg.replace(bitsTag, bitsStr);
arg.replace(addrTag, addrStr);
arg.replace(insnTag, nasm_syntax);
}
static const char *bitsTag = "%BITS%";
static const char *addrTag = "%ADDRESS%";
static const char *insnTag = "%INSTRUCTION%";

qDebug() << "RUNNING ASM TOOL: " << program << arguments;
asm_code.replace(bitsTag, bitsStr);
asm_code.replace(addrTag, addrStr);
asm_code.replace(insnTag, nasm_syntax);

process.start(program, arguments);
source_file.write(asm_code.toLatin1());
source_file.close();

if(process.waitForFinished()) {
QProcess process;
QString program(command_line[0]);

const int exit_code = process.exitCode();
command_line.pop_front();

if(exit_code != 0) {
QMessageBox::warning(this, tr("Error In Code"), process.readAllStandardError());
} else {
QByteArray bytes = output_file.readAll();
const size_t replacement_size = bytes.size();
QStringList arguments = command_line;
for(auto &arg : arguments) {
arg.replace("%OUT%", output_file.fileName());
arg.replace("%IN%", source_file.fileName());
arg.replace(bitsTag, bitsStr);
arg.replace(addrTag, addrStr);
arg.replace(insnTag, nasm_syntax);
}

if(replacement_size != 0 && replacement_size <= instruction_size_) {
if(ui.fillWithNOPs->isChecked()) {
// TODO(eteran): get system independent nop-code
if(!edb::v1::modify_bytes(address_, instruction_size_, bytes, 0x90)) {
return;
}
} else {
if(!edb::v1::modify_bytes(address_, instruction_size_, bytes, 0x00)) {
return;
}
}
} else if(replacement_size==0) {
const auto stdError = process.readAllStandardError();
QMessageBox::warning(this, tr("Error In Code"), tr("Got zero bytes from the assembler")+
(stdError.isEmpty()?"":tr(", here's what it has to say:\n\n")+stdError));
return;
qDebug() << "RUNNING ASM TOOL: " << program << arguments;

process.start(program, arguments);

if(process.waitForFinished()) {

const int exit_code = process.exitCode();

if(exit_code != 0) {
QMessageBox::warning(this, tr("Error In Code"), process.readAllStandardError());
} else {
if(ui.keepSize->isChecked()) {
QMessageBox::warning(this, tr("Error In Code"), tr("New instruction is too big to fit."));
QByteArray bytes = output_file.readAll();
const size_t replacement_size = bytes.size();

if(replacement_size != 0 && replacement_size <= instruction_size_) {
if(ui.fillWithNOPs->isChecked()) {
if(!edb::v1::modify_bytes(address_, instruction_size_, bytes, core->nopFillByte())) {
return;
}
} else {
if(!edb::v1::modify_bytes(address_, instruction_size_, bytes, 0x00)) {
return;
}
}
} else if(replacement_size==0) {
const auto stdError = process.readAllStandardError();
QMessageBox::warning(this, tr("Error In Code"), tr("Got zero bytes from the assembler") +
(stdError.isEmpty() ? "" : tr(", here's what it has to say:\n\n") + stdError));
return;
} else {
if(!edb::v1::modify_bytes(address_, replacement_size, bytes, 0x00)) {
if(ui.keepSize->isChecked()) {
QMessageBox::warning(this, tr("Error In Code"), tr("New instruction is too big to fit."));
return;
} else {
if(!edb::v1::modify_bytes(address_, replacement_size, bytes, 0x00)) {
return;
}
}
}
}

const edb::address_t new_address = address_ + replacement_size;
set_address(new_address);
edb::v1::set_cpu_selected_address(new_address);
const edb::address_t new_address = address_ + replacement_size;
set_address(new_address);
edb::v1::set_cpu_selected_address(new_address);
}
ui.assembly->setFocus(Qt::OtherFocusReason);
ui.assembly->lineEdit()->selectAll();
} else if(process.error()==QProcess::FailedToStart) {
QMessageBox::warning(this, tr("Couldn't Launch Assembler"), tr("Failed to start your assembler."));
return;
}
ui.assembly->setFocus(Qt::OtherFocusReason);
ui.assembly->lineEdit()->selectAll();
}
else if(process.error()==QProcess::FailedToStart)
{
QMessageBox::warning(this, tr("Couldn't Launch Assembler"), tr("Failed to start your assembler."));
return;
}



}
}

Expand Down
11 changes: 11 additions & 0 deletions plugins/DebuggerCore/unix/linux/DebuggerCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1163,4 +1163,15 @@ qlonglong DebuggerCore::exceptionValue(const QString &name) {
return Unix::exceptionValue(name);
}

uint8_t DebuggerCore::nopFillByte() const {
#if defined EDB_X86 || defined EDB_X86_64
return 0x90;
#elif defined EDB_ARM32 || defined EDB_ARM64
// TODO(eteran): does this concept even make sense for a multi-byte instruction encoding?
return 0x00;
#else
#error "Unsupported Architecture"
#endif
}

}
1 change: 1 addition & 0 deletions plugins/DebuggerCore/unix/linux/DebuggerCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class DebuggerCore final : public DebuggerCoreBase {
Status open(const QString &path, const QString &cwd, const QList<QByteArray> &args, const QString &tty) override;
MeansOfCapture last_means_of_capture() const override;
void set_ignored_exceptions(const QList<qlonglong> &exceptions) override;
uint8_t nopFillByte() const override;

public:
QMap<qlonglong, QString> exceptions() const override;
Expand Down
5 changes: 3 additions & 2 deletions src/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2053,8 +2053,9 @@ void Debugger::mnuCPUFillZero() {
// Desc:
//------------------------------------------------------------------------------
void Debugger::mnuCPUFillNop() {
// TODO: get system independent nop-code
cpu_fill(0x90);
if(IDebugger *core = edb::v1::debugger_core) {
cpu_fill(core->nopFillByte());
}
}

//------------------------------------------------------------------------------
Expand Down

0 comments on commit 4a3c4b0

Please sign in to comment.