From 0f91922e40640e00f1208aee5d8c968a698c5d31 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Tue, 20 May 2014 14:23:33 +0200 Subject: [PATCH] Factor out llvm disassembler --- CMakeLists.txt | 15 +-- .../BasicBlock.hxx | 0 src/disassembler.old/Disassembler.cxx | 12 +++ src/disassembler.old/Disassembler.hxx | 15 +++ .../Instruction.hxx | 0 .../InstructionReader.cxx | 0 .../InstructionReader.hxx | 0 .../Target.cxx | 0 .../Target.hxx | 0 src/disassembler/Disassembler.cxx | 11 +- src/disassembler/Disassembler.hxx | 25 +++-- src/disassembler/llvm/LLVMDisassembler.cxx | 100 ++++++++++++++++++ src/disassembler/llvm/LLVMDisassembler.hxx | 57 ++++++++++ src/gui/Mainwindow.cxx | 44 ++++---- src/gui/Mainwindow.hxx | 5 +- 15 files changed, 238 insertions(+), 46 deletions(-) rename src/{disassembler => disassembler.old}/BasicBlock.hxx (100%) create mode 100644 src/disassembler.old/Disassembler.cxx create mode 100644 src/disassembler.old/Disassembler.hxx rename src/{disassembler => disassembler.old}/Instruction.hxx (100%) rename src/{disassembler => disassembler.old}/InstructionReader.cxx (100%) rename src/{disassembler => disassembler.old}/InstructionReader.hxx (100%) rename src/{disassembler => disassembler.old}/Target.cxx (100%) rename src/{disassembler => disassembler.old}/Target.hxx (100%) create mode 100644 src/disassembler/llvm/LLVMDisassembler.cxx create mode 100644 src/disassembler/llvm/LLVMDisassembler.hxx diff --git a/CMakeLists.txt b/CMakeLists.txt index fe8e1a3..2d9ccbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,19 +28,20 @@ separate_arguments(LLVM_LIBS) set(CMAKE_CXX_COMPILER "clang++") SET(frida_SOURCES - src/Binary.cxx src/main.cxx src/gui/Mainwindow.cxx src/gui/widgets/BasicBlockWidget.cxx - src/disassembler/InstructionReader.cxx - src/disassembler/Target.cxx - src/disassembler/Disassembler.cxx) + src/disassembler/Disassembler.cxx + src/disassembler/llvm/LLVMDisassembler.cxx + ) SET(frida_HEADERS - src/Binary.hxx src/include_llvm.hxx - src/Section.hxx + src/gui/qt.hxx src/gui/Mainwindow.hxx - src/gui/widgets/BasicBlockWidget.hxx) + src/gui/widgets/BasicBlockWidget.hxx + src/disassembler/llvm/LLVMDisassembler.hxx + src/disassembler/Disassembler.hxx + ) ADD_EXECUTABLE(frida ${frida_SOURCES} ${frida_HEADERS_MOC}) #ADD_LIBRARY(llvm SHARED ) diff --git a/src/disassembler/BasicBlock.hxx b/src/disassembler.old/BasicBlock.hxx similarity index 100% rename from src/disassembler/BasicBlock.hxx rename to src/disassembler.old/BasicBlock.hxx diff --git a/src/disassembler.old/Disassembler.cxx b/src/disassembler.old/Disassembler.cxx new file mode 100644 index 0000000..7422df5 --- /dev/null +++ b/src/disassembler.old/Disassembler.cxx @@ -0,0 +1,12 @@ +#include "Disassembler.hxx" + +using namespace llvm; +using namespace llvm::object; + +Disassembler::Disassembler(const std::string& filename) + : _binary(createBinary(filename).get()) + , _target(_binary) +{ + +} + diff --git a/src/disassembler.old/Disassembler.hxx b/src/disassembler.old/Disassembler.hxx new file mode 100644 index 0000000..3effa25 --- /dev/null +++ b/src/disassembler.old/Disassembler.hxx @@ -0,0 +1,15 @@ +#ifndef INCLUDE__Disassembler_hxx +#define INCLUDE__Disassembler_hxx + +#include "Target.hxx" +#include "include_llvm.hxx" + +class Disassembler { +public: + Disassembler(const std::string& filename); +private: + llvm::object::Binary* _binary; + Target _target; +}; + +#endif diff --git a/src/disassembler/Instruction.hxx b/src/disassembler.old/Instruction.hxx similarity index 100% rename from src/disassembler/Instruction.hxx rename to src/disassembler.old/Instruction.hxx diff --git a/src/disassembler/InstructionReader.cxx b/src/disassembler.old/InstructionReader.cxx similarity index 100% rename from src/disassembler/InstructionReader.cxx rename to src/disassembler.old/InstructionReader.cxx diff --git a/src/disassembler/InstructionReader.hxx b/src/disassembler.old/InstructionReader.hxx similarity index 100% rename from src/disassembler/InstructionReader.hxx rename to src/disassembler.old/InstructionReader.hxx diff --git a/src/disassembler/Target.cxx b/src/disassembler.old/Target.cxx similarity index 100% rename from src/disassembler/Target.cxx rename to src/disassembler.old/Target.cxx diff --git a/src/disassembler/Target.hxx b/src/disassembler.old/Target.hxx similarity index 100% rename from src/disassembler/Target.hxx rename to src/disassembler.old/Target.hxx diff --git a/src/disassembler/Disassembler.cxx b/src/disassembler/Disassembler.cxx index 7422df5..968ebe2 100644 --- a/src/disassembler/Disassembler.cxx +++ b/src/disassembler/Disassembler.cxx @@ -1,12 +1,3 @@ -#include "Disassembler.hxx" +#include "disassembler/Disassembler.hxx" -using namespace llvm; -using namespace llvm::object; - -Disassembler::Disassembler(const std::string& filename) - : _binary(createBinary(filename).get()) - , _target(_binary) -{ - -} diff --git a/src/disassembler/Disassembler.hxx b/src/disassembler/Disassembler.hxx index 3effa25..9986ac8 100644 --- a/src/disassembler/Disassembler.hxx +++ b/src/disassembler/Disassembler.hxx @@ -1,15 +1,28 @@ #ifndef INCLUDE__Disassembler_hxx #define INCLUDE__Disassembler_hxx -#include "Target.hxx" -#include "include_llvm.hxx" +#include +#include + +class BasicBlock {}; class Disassembler { public: - Disassembler(const std::string& filename); -private: - llvm::object::Binary* _binary; - Target _target; + Disassembler(const std::string& filename) {} + virtual ~Disassembler() {} + + void getSymbols(); + uint64_t entryAddress(); + + virtual void forEachInstruction(const std::string& name, std::function callback) = 0; + + // http://llvm.org/docs/doxygen/html/MCObjectDisassembler_8cpp_source.html +197 + BasicBlock * generateControlFlowGraph(const std::string& name); + BasicBlock * generateControlFlowGraph(uint64_t address); + +protected: + virtual bool isFunctionCall(uint64_t address) = 0; + virtual bool isJump(uint64_t address) = 0; }; #endif diff --git a/src/disassembler/llvm/LLVMDisassembler.cxx b/src/disassembler/llvm/LLVMDisassembler.cxx new file mode 100644 index 0000000..881c662 --- /dev/null +++ b/src/disassembler/llvm/LLVMDisassembler.cxx @@ -0,0 +1,100 @@ +#include "disassembler/llvm/LLVMDisassembler.hxx" + +using namespace llvm; +using namespace llvm::object; + +/* + * TODO: fallback code falls die Datei kein ELF/PE/COFF/MacO/.. binary + * ist sondern z.B. einfach nur Instruktionen oder ein Bootsektor oder + * foo + */ + +LLVMDisassembler::LLVMDisassembler(const std::string& filename) + : Disassembler(filename) + , logger(log4cxx::Logger::getLogger("LLVMDisassembler")) + , triple("unknown-unknown-unknown") +{ + LOG4CXX_DEBUG(logger, "Handling file" << filename); + auto result = createBinary(filename); + + error_code ec; + if ((ec = result.getError())) { + LOG4CXX_ERROR(logger, "Failed to load Binary" << ec.message()); + binary = NULL; + return; + } + + binary.reset(result.get()); + + o = dyn_cast(binary.get()); + + triple.setArch(Triple::ArchType(o->getArch())); + std::string tripleName(triple.getTriple()); + + LOG4CXX_INFO(logger, "Architecture " << tripleName); + + + std::string es; + target = TargetRegistry::lookupTarget("", triple, es); + if (!target) { + LOG4CXX_ERROR(logger, es); + return; + } + + LOG4CXX_INFO(logger, "Target " << target->getName()); + + MRI.reset(target->createMCRegInfo(tripleName)); + if (!MRI) { + LOG4CXX_ERROR(logger, "no register info for target " << tripleName); + return; + } + + // Set up disassembler. + AsmInfo.reset(target->createMCAsmInfo(*MRI, tripleName)); + if (!AsmInfo) { + LOG4CXX_ERROR(logger, "no assembly info for target " << tripleName); + return; + } + + STI.reset(target->createMCSubtargetInfo(tripleName, "", "")); + if (!STI) { + LOG4CXX_ERROR(logger, "no subtarget info for target " << tripleName); + return; + } + + MII.reset(target->createMCInstrInfo()); + if (!MII) { + LOG4CXX_ERROR(logger, "no instruction info for target " << tripleName); + return; + } + + DisAsm.reset(target->createMCDisassembler(*STI)); + if (!DisAsm) { + LOG4CXX_ERROR(logger, "no disassembler for target " << tripleName); + return; + } + + MOFI.reset(new MCObjectFileInfo); + Ctx.reset(new MCContext(AsmInfo.get(), MRI.get(), MOFI.get())); + RelInfo.reset( + target->createMCRelocationInfo(tripleName, *Ctx.get())); + if (RelInfo) { + Symzer.reset( + MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(), RelInfo, o)); + if (Symzer) + DisAsm->setSymbolizer(Symzer); + } + + MIA.reset(target->createMCInstrAnalysis(MII.get())); + + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + IP.reset(target->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); + if (!IP) { + LOG4CXX_ERROR(logger, "no instruction printer for target " << tripleName); + return; + } + + OwningPtr OD( + new MCObjectDisassembler(*o, *DisAsm, *MIA)); + Mod.reset(OD->buildModule(false)); +} diff --git a/src/disassembler/llvm/LLVMDisassembler.hxx b/src/disassembler/llvm/LLVMDisassembler.hxx new file mode 100644 index 0000000..ff81be5 --- /dev/null +++ b/src/disassembler/llvm/LLVMDisassembler.hxx @@ -0,0 +1,57 @@ +#ifndef INCLUDE__LLVMDisassembler_hxx +#define INCLUDE__LLVMDisassembler_hxx + +#include +#include + +#include "include_llvm.hxx" + +#include "disassembler/Disassembler.hxx" + + +class LLVMDisassembler + : public Disassembler { +public: + LLVMDisassembler(const std::string& filename); + virtual ~LLVMDisassembler() {}; + + void getSymbols(); + uint64_t entryAddress(); + + void forEachInstruction(const std::string& name, std::function callback) {} + + BasicBlock * generateControlFlowGraph(const std::string& name); + BasicBlock * generateControlFlowGraph(uint64_t address); + +protected: + bool isFunctionCall(uint64_t address) {return false;} + bool isJump(uint64_t address) {return false;} + +private: + log4cxx::LoggerPtr logger; + + llvm::Triple triple; + std::shared_ptr binary; + + + const llvm::Target * target; + llvm::object::ObjectFile * o; + + std::unique_ptr MRI; + std::unique_ptr AsmInfo; + std::unique_ptr Mod; + std::unique_ptr IP; + std::unique_ptr DisAsm; + std::unique_ptr MOFI; + std::unique_ptr Ctx; + std::unique_ptr MIA; + std::unique_ptr STI; + std::unique_ptr MII; + llvm::OwningPtr RelInfo; + llvm::OwningPtr Symzer; + + std::map sections; + std::map symbols; +}; + +#endif diff --git a/src/gui/Mainwindow.cxx b/src/gui/Mainwindow.cxx index be86cac..061734a 100644 --- a/src/gui/Mainwindow.cxx +++ b/src/gui/Mainwindow.cxx @@ -1,6 +1,7 @@ -#include "Mainwindow.hxx" + #include "Mainwindow.hxx" #include "widgets/BasicBlockWidget.hxx" #include "qt.hxx" +#include "disassembler/llvm/LLVMDisassembler.hxx" #include #include @@ -54,14 +55,15 @@ void Mainwindow::open() { tr("Binaries (*)")); if (fileName != "") { - curBin = new qtlldb::Binary(fileName.toStdString()); - - std::vector symbols = curBin->getSymbols(); - if (0 == symbols.size()) - populateSymbolInformation(".text"); - for (auto it = symbols.begin(); it != symbols.end(); ++it) { - populateSymbolInformation(*it); - } + disassembler.reset(new LLVMDisassembler(fileName.toStdString())); + // curBin = new Binary(fileName.toStdString()); + + // std::vector symbols = curBin->getSymbols(); + // if (0 == symbols.size()) + // populateSymbolInformation(".text"); + // for (auto it = symbols.begin(); it != symbols.end(); ++it) { + // populateSymbolInformation(*it); + // } } } @@ -72,18 +74,18 @@ void Mainwindow::populateSymbolInformation(const std::string& sym) { QTableWidget * t = new QTableWidget(); t->setColumnCount(3); t->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - curBin->for_each_instruction(sym, [&t](long add, std::string bytes, std::string mnemonic) { - int row = t->rowCount(); - std::stringstream s; - t->setRowCount(t->rowCount() + 1); - s << std::hex << add; - t->setItem(row,0,new QTableWidgetItem(s.str().c_str())); - s.str(""); - s << std::hex; - for_each(bytes.begin(), bytes.end(), [&s](char c){s << (unsigned int)((unsigned char)c) << ' ';}); - t->setItem(row,1,new QTableWidgetItem(s.str().c_str())); - t->setItem(row,2,new QTableWidgetItem(mnemonic.c_str() + 1)); - }); + // curBin->for_each_instruction(sym, [&t](long add, std::string bytes, std::string mnemonic) { + // int row = t->rowCount(); + // std::stringstream s; + // t->setRowCount(t->rowCount() + 1); + // s << std::hex << add; + // t->setItem(row,0,new QTableWidgetItem(s.str().c_str())); + // s.str(""); + // s << std::hex; + // for_each(bytes.begin(), bytes.end(), [&s](char c){s << (unsigned int)((unsigned char)c) << ' ';}); + // t->setItem(row,1,new QTableWidgetItem(s.str().c_str())); + // t->setItem(row,2,new QTableWidgetItem(mnemonic.c_str() + 1)); + // }); w->addTab(t, "Listing"); // CFG diff --git a/src/gui/Mainwindow.hxx b/src/gui/Mainwindow.hxx index 34abc3a..adfe71e 100644 --- a/src/gui/Mainwindow.hxx +++ b/src/gui/Mainwindow.hxx @@ -1,10 +1,11 @@ +#include #include #include #include #include #include -#include "Binary.hxx" +#include "disassembler/Disassembler.hxx" class Mainwindow : public QMainWindow { Q_OBJECT @@ -25,7 +26,7 @@ private: QAction *exitAction; QAction *openAction; - qtlldb::Binary * curBin; + std::shared_ptr disassembler; private slots: void quit(); void open(); -- 2.39.2