manager->finishBasicBlock(block);
return block;
}
+
+std::list<Instruction> BasicBlock::getInstructions() const {
+ return manager->getDisassembler()->getInstructions(this);
+}
#include <cassert>
#include <string>
#include <sstream>
+#include <list>
+class Instruction;
class Disassembler;
class InformationManager;
class QXmlStreamWriter;
class BasicBlock {
public:
- uint64_t getStartAddress() const {
- return start_address;
- }
-
- uint64_t getEndAddress() const {
- return end_address;
- }
+ InformationManager* getManager() const {return manager;}
+ uint64_t getStartAddress() const {return start_address;}
+ uint64_t getEndAddress() const {return end_address;}
+ void setStartAddress(uint64_t address) {start_address = address;}
+ void setEndAddress(uint64_t address) {end_address = address;}
uint64_t getNextBlock(size_t index) const {
assert(index < 2);
next_blocks[index] = address;
}
- void setStartAddress(uint64_t address) {
- start_address = address;
- }
-
- void setEndAddress(uint64_t address) {
- end_address = address;
- }
-
std::string getName() const {
std::stringstream s;
s << "BLOCK_" << std::hex << start_address << '_' << end_address;
return s.str();
}
- InformationManager* getManager() const {
- return manager;
- }
-
+ std::list<Instruction> getInstructions() const;
void serialize(QXmlStreamWriter& stream);
static BasicBlock* deserialize(QXmlStreamReader& stream, InformationManager* manager);
#include <string>
#include <functional>
+#include <list>
+
+#include "Instruction.hxx"
class Function;
class BasicBlock;
std::function<void (uint8_t*, size_t, const std::string&,
const std::string&)> fun) = 0;
virtual Function * disassembleFunctionAt(uint64_t address, const std::string& name = "") = 0;
+ virtual std::list<Instruction> getInstructions(const BasicBlock* block) = 0;
};
#endif
--- /dev/null
+#ifndef INCLUDE__Instruction_hxx_
+#define INCLUDE__Instruction_hxx_
+
+#include <vector>
+#include <cstdint>
+#include <string>
+
+class Instruction {
+public:
+ Instruction(uint64_t address, const std::string& text, const std::vector<uint8_t>& bytes, const std::string& reference)
+ : address(address), text(text), bytes(bytes), reference(reference) {}
+ uint64_t getAddress() const {return address;}
+ const std::string& getText() const {return text;}
+ const std::vector<uint8_t>& getBytes() const {return bytes;}
+ const std::string& getReference() const {return reference;}
+private:
+ uint64_t address;
+ std::string text;
+ std::vector<uint8_t> bytes;
+ std::string reference;
+};
+
+#endif /* INCLUDE__Instruction_hxx_ */
+#include "disassembler/Instruction.hxx"
#include "disassembler/llvm/LLVMDisassembler.hxx"
#include "core/InformationManager.hxx"
#include "core/Function.hxx"
// // });
// }
+template <typename ELFT>
+std::list<Instruction> LLVMDisassembler<ELFT>::getInstructions(const BasicBlock *block) {
+ std::list<Instruction> result;
+ SectionRef text_section = getTextSection();
+ uint64_t base_address;
+ text_section.getAddress(base_address);
+ uint64_t current_address = block->getStartAddress() - base_address;
+ uint64_t end_position = block->getEndAddress() - base_address;
+
+ StringRef bytes;
+ text_section.getContents(bytes);
+ StringRefMemoryObject ref(bytes);
+
+ while (current_address < end_position) {
+ uint64_t inst_size;
+ MCInst inst;
+ std::string buf;
+ llvm::raw_string_ostream s(buf);
+
+ if(llvm::MCDisassembler::Success ==
+ DisAsm->getInstruction(inst, inst_size, ref, current_address, nulls(), nulls())) {
+
+ uint8_t bytes[inst_size+2];
+ ref.readBytes(current_address, inst_size, bytes);
+
+ uint64_t jmptarget;
+ std::string ref("");
+ IP->printInst(&inst, s, "");
+ if (MIA->evaluateBranch(inst, current_address, inst_size, jmptarget)) {
+ std::stringstream stream;
+ if (MIA->isCall(inst))
+ stream << "function:";
+ else
+ stream << "block:";
+
+ stream << std::hex << (base_address + jmptarget);
+ ref = stream.str();
+ }
+ result.push_back(Instruction(current_address + base_address, s.str(),
+ std::vector<uint8_t>(bytes, bytes+inst_size), ref));
+ } else {
+ LOG4CXX_WARN(logger, "Invalid byte at" << std::hex << current_address + base_address);
+ uint8_t bytes[1];
+ ref.readBytes(current_address, 1, bytes);
+ result.push_back(Instruction(current_address + base_address, "Invalid Instruction",
+ std::vector<uint8_t>(bytes, bytes+1), ""));
+ inst_size = 1;
+ }
+
+ current_address += inst_size;
+ }
+ return result;
+}
+
template <typename ELFT>
void LLVMDisassembler<ELFT>::printEachInstruction(uint64_t start, uint64_t end,
std::function<void (uint8_t*, size_t,
const std::string&)> fun);
Function * disassembleFunctionAt(uint64_t address, const std::string& name = "");
+ std::list<Instruction> getInstructions(const BasicBlock* block);
private:
// http://llvm.org/docs/doxygen/html/MCObjectDisassembler_8cpp_source.html +197
mainwindow->switchMainPlaneToAddress(address.toInt(NULL, 16));
}
});
+ instructions = block->getInstructions();
+ populateWidget();
}
void BasicBlockWidget::updateFunctionName(RenameFunctionEvent *event) {
}
}
-void BasicBlockWidget::addItem(uint8_t* bytes, size_t num_bytes,
- QString line, const QString& href) {
- QString bytestring;
+void BasicBlockWidget::populateWidget() {
int row;
-
- if (_table) {
- row = _table->rows();
- _table->appendRows(1);
- } else {
- row = 0;
- QTextTableFormat format;
- format.setBorderStyle(QTextFrameFormat::BorderStyle_None);
- format.setBorder(0);
- _table = _widget->textCursor().insertTable(1, 3, format);
- }
-
- for (size_t i(0); i < num_bytes; ++i) {
- const char * hexdigits = "0123456789ABCDEF";
- bytestring += hexdigits[(bytes[i] >> 4) & 0xF];
- bytestring += hexdigits[bytes[i] & 0xF];
- bytestring += ' ';
- }
-
- _table->cellAt(row, 0).firstCursorPosition().insertText(bytestring);
-
- line = line.replace('\t', ' ').toHtmlEscaped();
- if (href != "") {
- QStringList list = href.split(":");
- if (list[0] == "function") {
- uint64_t address = href.split(":")[1].toLongLong(NULL, 16);
- Function* fun = block->getManager()->getFunction(address);
-
- if (fun) {
- line = line.split(" ")[0] + " " + QString(fun->getName().c_str()).toHtmlEscaped();
- LOG4CXX_DEBUG(logger, "Naming function at " << address << " " << fun->getName());
+ QTextTableFormat format;
+ format.setBorderStyle(QTextFrameFormat::BorderStyle_None);
+ format.setBorder(0);
+
+ for (Instruction& inst : instructions) {
+ if (_table) {
+ row = _table->rows();
+ _table->appendRows(1);
+ } else {
+ row = 0;
+ _table = _widget->textCursor().insertTable(1, 3, format);
+ }
+ QString bytestring;
+ for (uint8_t byte : inst.getBytes()) {
+ const char * hexdigits = "0123456789ABCDEF";
+ bytestring += hexdigits[(byte >> 4) & 0xF];
+ bytestring += hexdigits[byte & 0xF];
+ bytestring += ' ';
+ }
+ _table->cellAt(row, 0).firstCursorPosition().insertText(bytestring);
+
+ QString line = inst.getText().c_str();
+ line = line.replace('\t', ' ').toHtmlEscaped();
+ if (inst.getReference() != "") {
+ QString href = inst.getReference().c_str();
+ QStringList list = href.split(":");
+ if (list[0] == "function") {
+ uint64_t address = href.split(":")[1].toLongLong(NULL, 16);
+ Function* fun = block->getManager()->getFunction(address);
+
+ if (fun) {
+ line = line.split(" ")[0] + " " + QString(fun->getName().c_str()).toHtmlEscaped();
+ LOG4CXX_DEBUG(logger, "Naming function at " << address << " " << fun->getName());
+ }
}
+ line = "<a href=\"" + href + "\">" + line + "</a>";
}
- line = "<a href=\"" + href + "\">" + line + "</a>";
- }
- _table->cellAt(row, 1).firstCursorPosition().insertHtml(line);
+ _table->cellAt(row, 1).firstCursorPosition().insertHtml(line);
+ }
}
void BasicBlockWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem*,
#include <array>
#include <memory>
#include <log4cxx/logger.h>
+#include <list>
+
+#include "disassembler/Instruction.hxx"
class Mainwindow;
class CustomQGraphicsTextItem;
public:
BasicBlockWidget(const QString& name, BasicBlock * block, Mainwindow * mainwindow);
- void addItem(uint8_t* bytes, size_t num_bytes, QString line, const QString& href);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
QRectF boundingRect() const;
{ return name; }
private:
void updateFunctionName(RenameFunctionEvent* event);
+ void populateWidget();
uint32_t width, height;
QString name;
std::unique_ptr<QGraphicsTextItem> _widget;
QTextTable* _table;
BasicBlock* block;
+ std::list<Instruction> instructions;
Mainwindow* mainwindow;
std::vector<BasicBlockWidget*> previous;
BasicBlockWidget* next[2];
widget->setFlag(QGraphicsItem::ItemIsMovable, true);
widget->moveBy(100*startx, block->getStartAddress() - starty);
- manager->getDisassembler()
- ->printEachInstruction(block->getStartAddress(),
- block->getEndAddress(),
- [&](uint8_t* bytes,
- size_t byte_count,
- const std::string& line,
- const std::string& ref) {
- widget->addItem(bytes, byte_count,
- line.c_str() + 1, // remove \t
- ref.c_str());
- });
-
BasicBlockWidget *tmp, *nextl(NULL), *nextr(NULL);
BasicBlock * tmpblock;
if (block->getNextBlock(0) != 0) {