From: Christoph Egger Date: Thu, 19 Mar 2015 16:56:49 +0000 (+0100) Subject: Rework API for getting at instructions X-Git-Tag: v0.1~30 X-Git-Url: https://git.siccegge.de//index.cgi?p=frida%2Ffrida.git;a=commitdiff_plain;h=4443ad3e38327c776dcc68538591456d37c9ed6f;ds=sidebyside Rework API for getting at instructions Now we don't hand a callback to the Disassembler, instead we just get a list of Instruction objects and use that --- diff --git a/src/core/BasicBlock.cxx b/src/core/BasicBlock.cxx index 5e2efd7..7af6bd8 100644 --- a/src/core/BasicBlock.cxx +++ b/src/core/BasicBlock.cxx @@ -89,3 +89,7 @@ BasicBlock* BasicBlock::deserialize(QXmlStreamReader& stream, InformationManager manager->finishBasicBlock(block); return block; } + +std::list BasicBlock::getInstructions() const { + return manager->getDisassembler()->getInstructions(this); +} diff --git a/src/core/BasicBlock.hxx b/src/core/BasicBlock.hxx index 0df07b2..3f87787 100644 --- a/src/core/BasicBlock.hxx +++ b/src/core/BasicBlock.hxx @@ -4,7 +4,9 @@ #include #include #include +#include +class Instruction; class Disassembler; class InformationManager; class QXmlStreamWriter; @@ -12,13 +14,11 @@ class QXmlStreamReader; 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); @@ -30,24 +30,13 @@ public: 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 getInstructions() const; void serialize(QXmlStreamWriter& stream); static BasicBlock* deserialize(QXmlStreamReader& stream, InformationManager* manager); diff --git a/src/disassembler/Disassembler.hxx b/src/disassembler/Disassembler.hxx index fe240a9..78c67c6 100644 --- a/src/disassembler/Disassembler.hxx +++ b/src/disassembler/Disassembler.hxx @@ -3,6 +3,9 @@ #include #include +#include + +#include "Instruction.hxx" class Function; class BasicBlock; @@ -21,6 +24,7 @@ public: std::function fun) = 0; virtual Function * disassembleFunctionAt(uint64_t address, const std::string& name = "") = 0; + virtual std::list getInstructions(const BasicBlock* block) = 0; }; #endif diff --git a/src/disassembler/Instruction.hxx b/src/disassembler/Instruction.hxx new file mode 100644 index 0000000..e79b24f --- /dev/null +++ b/src/disassembler/Instruction.hxx @@ -0,0 +1,23 @@ +#ifndef INCLUDE__Instruction_hxx_ +#define INCLUDE__Instruction_hxx_ + +#include +#include +#include + +class Instruction { +public: + Instruction(uint64_t address, const std::string& text, const std::vector& 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& getBytes() const {return bytes;} + const std::string& getReference() const {return reference;} +private: + uint64_t address; + std::string text; + std::vector bytes; + std::string reference; +}; + +#endif /* INCLUDE__Instruction_hxx_ */ diff --git a/src/disassembler/llvm/LLVMDisassembler.cxx b/src/disassembler/llvm/LLVMDisassembler.cxx index 58d122a..3023f93 100644 --- a/src/disassembler/llvm/LLVMDisassembler.cxx +++ b/src/disassembler/llvm/LLVMDisassembler.cxx @@ -1,3 +1,4 @@ +#include "disassembler/Instruction.hxx" #include "disassembler/llvm/LLVMDisassembler.hxx" #include "core/InformationManager.hxx" #include "core/Function.hxx" @@ -524,6 +525,60 @@ void LLVMDisassembler::readSections() { // // }); // } +template +std::list LLVMDisassembler::getInstructions(const BasicBlock *block) { + std::list 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(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(bytes, bytes+1), "")); + inst_size = 1; + } + + current_address += inst_size; + } + return result; +} + template void LLVMDisassembler::printEachInstruction(uint64_t start, uint64_t end, std::function fun); Function * disassembleFunctionAt(uint64_t address, const std::string& name = ""); + std::list getInstructions(const BasicBlock* block); private: // http://llvm.org/docs/doxygen/html/MCObjectDisassembler_8cpp_source.html +197 diff --git a/src/gui/widgets/BasicBlockWidget.cxx b/src/gui/widgets/BasicBlockWidget.cxx index 128b9fb..3781401 100644 --- a/src/gui/widgets/BasicBlockWidget.cxx +++ b/src/gui/widgets/BasicBlockWidget.cxx @@ -84,6 +84,8 @@ BasicBlockWidget::BasicBlockWidget(const QString& name, BasicBlock * block, mainwindow->switchMainPlaneToAddress(address.toInt(NULL, 16)); } }); + instructions = block->getInstructions(); + populateWidget(); } void BasicBlockWidget::updateFunctionName(RenameFunctionEvent *event) { @@ -111,47 +113,48 @@ 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 = "" + line + ""; } - line = "" + line + ""; - } - _table->cellAt(row, 1).firstCursorPosition().insertHtml(line); + _table->cellAt(row, 1).firstCursorPosition().insertHtml(line); + } } void BasicBlockWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem*, diff --git a/src/gui/widgets/BasicBlockWidget.hxx b/src/gui/widgets/BasicBlockWidget.hxx index 8cf709c..22bc220 100644 --- a/src/gui/widgets/BasicBlockWidget.hxx +++ b/src/gui/widgets/BasicBlockWidget.hxx @@ -8,6 +8,9 @@ #include #include #include +#include + +#include "disassembler/Instruction.hxx" class Mainwindow; class CustomQGraphicsTextItem; @@ -23,7 +26,6 @@ class BasicBlockWidget : public QObject, public QGraphicsItem 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; @@ -48,12 +50,14 @@ public: { return name; } private: void updateFunctionName(RenameFunctionEvent* event); + void populateWidget(); uint32_t width, height; QString name; std::unique_ptr _widget; QTextTable* _table; BasicBlock* block; + std::list instructions; Mainwindow* mainwindow; std::vector previous; BasicBlockWidget* next[2]; diff --git a/src/gui/widgets/FunctionWidget.cxx b/src/gui/widgets/FunctionWidget.cxx index ba96e5d..576e848 100644 --- a/src/gui/widgets/FunctionWidget.cxx +++ b/src/gui/widgets/FunctionWidget.cxx @@ -77,18 +77,6 @@ namespace { 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) {