Implement loading of flat binary files
MODIFY
src/assembler.cpp
src/assembler.cpp
@@ -812,8 +812,8 @@ const QByteArray& Assembler::assemble(const QTextDocument& doc) {
const Program Assembler::getProgram() {
Program p;
- p.text = {ProcessorHandler::get()->getSetup().segmentPtrs.at(ProgramSegment::Text), &m_textSegment};
- p.others.push_back({ProcessorHandler::get()->getSetup().segmentPtrs.at(ProgramSegment::Data), &m_dataSegment});
+ p.text = {ProcessorHandler::get()->getSetup().segmentPtrs.at(ProgramSegment::Text), m_textSegment};
+ p.others.push_back({ProcessorHandler::get()->getSetup().segmentPtrs.at(ProgramSegment::Data), m_dataSegment});
return p;
}
} // namespace Ripes

MODIFY
src/edittab.cpp
src/edittab.cpp
@@ -16,7 +16,7 @@ namespace Ripes {
EditTab::EditTab(QToolBar* toolbar, QWidget* parent) : RipesTab(toolbar, parent), m_ui(new Ui::EditTab) {
m_ui->setupUi(this);
- connect(m_ui->enableEditor, &QPushButton::clicked, this, &EditTab::enableEditor);
+ connect(m_ui->enableEditor, &QPushButton::clicked, this, &EditTab::enableAssemblyInput);
// Only add syntax highlighter for code edit view - not for translated code. This is assumed to be correct after a
// translation is complete
@@ -39,17 +39,33 @@ EditTab::EditTab(QToolBar* toolbar, QWidget* parent) : RipesTab(toolbar, parent)
}
void EditTab::loadFile(const LoadFileParams& fileParams) {
+ QFile file(fileParams.filepath);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QMessageBox::warning(this, "Error", "Error: Could not open file " + fileParams.filepath);
+ return;
+ }
+
+ bool success = true;
+ Program loadedProgram;
switch (fileParams.type) {
case FileType::Assembly:
- loadAssemblyFile(fileParams);
+ success &= loadAssemblyFile(loadedProgram, file);
break;
case FileType::FlatBinary:
- loadFlatBinaryFile(fileParams);
+ success &= loadFlatBinaryFile(loadedProgram, file, fileParams.binaryEntryPoint, fileParams.binaryLoadAt);
break;
case FileType::Executable:
- loadElfFile(fileParams);
+ success &= loadElfFile(loadedProgram, file);
break;
}
+
+ if (success) {
+ m_loadedFile = fileParams;
+ m_activeProgram = loadedProgram;
+ emitProgramChanged();
+ } else {
+ QMessageBox::warning(this, "Error", "Error: Could not load file " + fileParams.filepath);
+ }
}
QString EditTab::getAssemblyText() {
@@ -60,20 +76,21 @@ const QByteArray& EditTab::getBinaryData() {
return m_assembler->getTextSegment();
}
-void EditTab::clear() {
+void EditTab::clearAssemblyEditor() {
m_ui->assemblyedit->reset();
m_assembler->clear();
}
void EditTab::emitProgramChanged() {
- emit programChanged(m_assembler->getProgram());
setDisassemblerText();
+ emit programChanged(&m_activeProgram);
}
void EditTab::assemble() {
if (m_ui->assemblyedit->syntaxAccepted()) {
- const QByteArray& ret = m_assembler->assemble(*m_ui->assemblyedit->document());
+ m_assembler->assemble(*m_ui->assemblyedit->document());
if (!m_assembler->hasError()) {
+ m_activeProgram = m_assembler->getProgram();
emitProgramChanged();
} else {
QMessageBox err;
@@ -97,47 +114,67 @@ void EditTab::setAssemblyText(const QString& text) {
m_ui->assemblyedit->setPlainText(text);
}
+void EditTab::enableAssemblyInput() {
+ // Clear currently loaded binary/ELF program
+ m_activeProgram = Program();
+ m_ui->binaryedit->clear();
+ enableEditor();
+}
+
void EditTab::setDisassemblerText() {
- const QString& text = m_ui->disassembledViewButton->isChecked()
- ? Parser::getParser()->disassemble(m_assembler->getTextSegment())
- : Parser::getParser()->binarize(m_assembler->getTextSegment());
+ auto text = m_ui->disassembledViewButton->isChecked()
+ ? Parser::getParser()->disassemble(m_activeProgram.text.second)
+ : Parser::getParser()->binarize(m_activeProgram.text.second);
m_ui->binaryedit->setPlainText(text);
}
void EditTab::enableEditor() {
+ connect(m_ui->assemblyedit, &CodeEditor::textChanged, this, &EditTab::assemble);
m_ui->editorStackedWidget->setCurrentIndex(0);
+ clearAssemblyEditor();
}
void EditTab::disableEditor() {
+ disconnect(m_ui->assemblyedit, &CodeEditor::textChanged, this, &EditTab::assemble);
m_ui->editorStackedWidget->setCurrentIndex(1);
+ clearAssemblyEditor();
}
void EditTab::on_disassembledViewButton_toggled() {
setDisassemblerText();
}
-void EditTab::loadFlatBinaryFile(const LoadFileParams& params) {
+bool EditTab::loadFlatBinaryFile(Program& program, QFile& file, uint32_t entryPoint, uint32_t loadAt) {
+ QByteArray text;
+ text = file.readAll();
+
+ program.text.first = loadAt;
+ program.text.second = text;
+
m_ui->curInputSrcLabel->setText("Flat binary");
disableEditor();
+ return true;
}
-void EditTab::loadAssemblyFile(const LoadFileParams& params) {
- // ... load file
- QFile file(params.filepath);
- clear();
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+bool EditTab::loadAssemblyFile(Program& program, QFile& file) {
+ enableEditor();
+ // Loading text to editor will trigger the assembler
setAssemblyText(file.readAll());
file.close();
+ return true;
}
- setDisassemblerText();
- enableEditor();
- emit programChanged(m_assembler->getProgram());
-}
-
-void EditTab::loadElfFile(const LoadFileParams& params) {
+bool EditTab::loadElfFile(Program& program, QFile& file) {
+ bool success = true;
m_ui->curInputSrcLabel->setText("Executable (ELF)");
+ clearAssemblyEditor();
+
+ if (success) {
disableEditor();
+ return true;
+ } else {
+ return false;
+ }
}
} // namespace Ripes

MODIFY
src/edittab.h
src/edittab.h
@@ -29,26 +29,32 @@ public:
void setDisassemblerText();
QString getAssemblyText();
void newProgram();
- void clear();
+ void clearAssemblyEditor();
const QByteArray& getBinaryData();
void loadFile(const LoadFileParams&);
signals:
- void programChanged(const Program& program);
+ void programChanged(const Program* program);
public slots:
void emitProgramChanged();
+ /**
+ * @brief enableAssemblyInput
+ * Called whenever the user wants to switch from binary/ELF file input to typed assembly input
+ */
+ void enableAssemblyInput();
+
private slots:
void assemble();
void on_disassembledViewButton_toggled();
private:
- void loadFlatBinaryFile(const LoadFileParams&);
- void loadAssemblyFile(const LoadFileParams&);
- void loadElfFile(const LoadFileParams&);
+ bool loadFlatBinaryFile(Program& program, QFile& file, uint32_t entryPoint, uint32_t loadAt);
+ bool loadAssemblyFile(Program& program, QFile& file);
+ bool loadElfFile(Program& program, QFile& file);
void setupActions();
void enableEditor();
@@ -56,5 +62,8 @@ private:
Ui::EditTab* m_ui;
Assembler* m_assembler = nullptr;
+
+ LoadFileParams m_loadedFile;
+ Program m_activeProgram;
};
} // namespace Ripes

MODIFY
src/instructionmodel.cpp
src/instructionmodel.cpp
@@ -23,8 +23,7 @@ int InstructionModel::columnCount(const QModelIndex&) const {
}
int InstructionModel::rowCount(const QModelIndex&) const {
- // Each instruction is 4 bytes and each row represents an instruction within the .text segment
- return ProcessorHandler::get()->getCurrentProgramSize();
+ return ProcessorHandler::get()->getCurrentProgramSize() / ProcessorHandler::get()->currentISA()->bytes();
}
void InstructionModel::processorWasClocked() {

MODIFY
src/processorhandler.cpp
src/processorhandler.cpp
@@ -13,19 +13,19 @@ ProcessorHandler::ProcessorHandler() {
selectProcessor(m_currentSetup);
}
-void ProcessorHandler::loadProgram(const Program& p) {
+void ProcessorHandler::loadProgram(const Program* p) {
auto& mem = m_currentProcessor->getMemory();
m_program = p;
// Memory initializations
mem.clearInitializationMemories();
- mem.addInitializationMemory(p.text.first, p.text.second->data(), p.text.second->length());
- for (const auto& seg : p.others) {
- mem.addInitializationMemory(seg.first, seg.second->data(), seg.second->length());
+ mem.addInitializationMemory(p->text.first, p->text.second.data(), p->text.second.length());
+ for (const auto& seg : p->others) {
+ mem.addInitializationMemory(seg.first, seg.second.data(), seg.second.length());
}
// Set the valid execution range to be contained within the .text segment.
- m_validExecutionRange = {p.text.first, p.text.first + p.text.second->length()};
+ m_validExecutionRange = {p->text.first, p->text.first + p->text.second.length()};
// Update breakpoints to stay within the loaded program range
std::vector<uint32_t> bpsToRemove;
@@ -130,8 +130,8 @@ void ProcessorHandler::selectProcessor(const ProcessorSetup& setup) {
}
int ProcessorHandler::getCurrentProgramSize() const {
- if (m_program.text.second)
- return m_program.text.second->size();
+ if (m_program)
+ return m_program->text.second.size();
return 0;
}

MODIFY
src/processorhandler.h
src/processorhandler.h
@@ -120,7 +120,7 @@ signals:
void hitBreakpoint(uint32_t address);
public slots:
- void loadProgram(const Program& p);
+ void loadProgram(const Program* p);
private slots:
void handleSysCall();
@@ -140,6 +140,6 @@ private:
*/
std::pair<uint32_t, uint32_t> m_validExecutionRange;
std::set<uint32_t> m_breakpoints;
- Program m_program;
+ const Program* m_program = nullptr;
};
} // namespace Ripes

MODIFY
src/program.h
src/program.h
@@ -21,7 +21,7 @@ struct LoadFileParams {
* program. Others section may contain all other program sections (.bss, .data, ...)
*/
struct Program {
- using Section = std::pair<uint32_t, QByteArray*>;
+ using Section = std::pair<uint32_t, QByteArray>;
Section text;
std::vector<Section> others;
};

Implement loading of flat binary files