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 )
--- /dev/null
+
+
+class BasicBlock {
+public:
+
+private:
+
+};
--- /dev/null
+#include "Disassembler.hxx"
+
+using namespace llvm;
+using namespace llvm::object;
+
+Disassembler::Disassembler(const std::string& filename)
+ : _binary(createBinary(filename).get())
+ , _target(_binary)
+{
+
+}
+
--- /dev/null
+#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
--- /dev/null
+
+
+class Instruction {
+public:
+private:
+};
--- /dev/null
+#include "InstructionReader.hxx"
+
+InstructionReader::InstructionReader(const Target& target)
+ : _logger(log4cxx::Logger::getLogger("disassembler.Target"))
+ , _target(target)
+{
+ DisAsm.reset(_target.getTarget().createMCDisassembler(_target.getSubTargetInfo()));
+ if (!DisAsm) {
+ LOG4CXX_ERROR(_logger, "error: no disassembler for target " << _target.getTripleName())
+ return;
+ }
+}
+
+void InstructionReader::readInstruction(std::string& data, size_t& offset, Instruction& inst) {
+ llvm::MCInst instr;
+ llvm::StringRefMemoryObject memoryObject(data);
+ uint64_t size;
+
+ if (DisAsm->getInstruction(instr, size, memoryObject, offset,
+ llvm::nulls(), llvm::nulls())) {
+
+ } else {
+ LOG4CXX_WARN(_logger, "warning: invalid instruction encoding");
+ if (size == 0)
+ size = 1; // skip illegible bytes
+ }
+}
--- /dev/null
+#include "include_llvm.hxx"
+#include "Instruction.hxx"
+#include "Target.hxx"
+
+#include <string>
+
+#include <log4cxx/logger.h>
+
+
+class InstructionReader {
+public:
+ InstructionReader(const Target& target);
+ void readInstruction(std::string& data, size_t& offset, Instruction& inst);
+private:
+ log4cxx::LoggerPtr _logger;
+ const Target& _target;
+ llvm::OwningPtr<llvm::MCDisassembler> DisAsm;
+};
--- /dev/null
+#include "Target.hxx"
+
+#include <string>
+
+Target::Target(llvm::object::Binary* binary)
+ : _logger(log4cxx::Logger::getLogger("disassembler.Target"))
+ , triple("unknown-unknown-unknown")
+{
+ std::string error;
+ llvm::object::ObjectFile * o = llvm::dyn_cast<llvm::object::ObjectFile>(binary);
+
+ triple.setArch(llvm::Triple::ArchType(o->getArch()));
+ std::string tripleName(triple.getTriple());
+ LOG4CXX_INFO(_logger, "Detected triple " << tripleName);
+
+ target = llvm::TargetRegistry::lookupTarget("", triple, error);
+ if (!target) {
+ LOG4CXX_ERROR(_logger, "Couldn't create Target: " << error);
+ return;
+ }
+ LOG4CXX_INFO(_logger, "Target: " << target->getName());
+
+ STI.reset(target->createMCSubtargetInfo(tripleName, "", ""));
+ if (!STI) {
+ LOG4CXX_ERROR(_logger, "No subtarget for target " << tripleName);
+ return;
+ }
+}
--- /dev/null
+#ifndef INCLUDE__Target_hxx
+#define INCLUDE__Target_hxx
+
+#include <log4cxx/logger.h>
+
+#include "include_llvm.hxx"
+
+class Target {
+public:
+ Target(llvm::object::Binary* binary);
+
+ const llvm::Target& getTarget() const {
+ return *target;
+ }
+
+ const llvm::MCSubtargetInfo& getSubTargetInfo() const {
+ return *STI;
+ }
+
+ std::string getTripleName() const {
+ return triple.getTriple();
+ }
+private:
+ log4cxx::LoggerPtr _logger;
+ llvm::Triple triple;
+
+ const llvm::Target * target;
+ llvm::OwningPtr<const llvm::MCSubtargetInfo> STI;
+};
+
+#endif
+++ /dev/null
-
-
-class BasicBlock {
-public:
-
-private:
-
-};
-#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)
-{
-
-}
#ifndef INCLUDE__Disassembler_hxx
#define INCLUDE__Disassembler_hxx
-#include "Target.hxx"
-#include "include_llvm.hxx"
+#include <string>
+#include <functional>
+
+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<void (long, std::string, std::string)> 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
+++ /dev/null
-
-
-class Instruction {
-public:
-private:
-};
+++ /dev/null
-#include "InstructionReader.hxx"
-
-InstructionReader::InstructionReader(const Target& target)
- : _logger(log4cxx::Logger::getLogger("disassembler.Target"))
- , _target(target)
-{
- DisAsm.reset(_target.getTarget().createMCDisassembler(_target.getSubTargetInfo()));
- if (!DisAsm) {
- LOG4CXX_ERROR(_logger, "error: no disassembler for target " << _target.getTripleName())
- return;
- }
-}
-
-void InstructionReader::readInstruction(std::string& data, size_t& offset, Instruction& inst) {
- llvm::MCInst instr;
- llvm::StringRefMemoryObject memoryObject(data);
- uint64_t size;
-
- if (DisAsm->getInstruction(instr, size, memoryObject, offset,
- llvm::nulls(), llvm::nulls())) {
-
- } else {
- LOG4CXX_WARN(_logger, "warning: invalid instruction encoding");
- if (size == 0)
- size = 1; // skip illegible bytes
- }
-}
+++ /dev/null
-#include "include_llvm.hxx"
-#include "Instruction.hxx"
-#include "Target.hxx"
-
-#include <string>
-
-#include <log4cxx/logger.h>
-
-
-class InstructionReader {
-public:
- InstructionReader(const Target& target);
- void readInstruction(std::string& data, size_t& offset, Instruction& inst);
-private:
- log4cxx::LoggerPtr _logger;
- const Target& _target;
- llvm::OwningPtr<llvm::MCDisassembler> DisAsm;
-};
+++ /dev/null
-#include "Target.hxx"
-
-#include <string>
-
-Target::Target(llvm::object::Binary* binary)
- : _logger(log4cxx::Logger::getLogger("disassembler.Target"))
- , triple("unknown-unknown-unknown")
-{
- std::string error;
- llvm::object::ObjectFile * o = llvm::dyn_cast<llvm::object::ObjectFile>(binary);
-
- triple.setArch(llvm::Triple::ArchType(o->getArch()));
- std::string tripleName(triple.getTriple());
- LOG4CXX_INFO(_logger, "Detected triple " << tripleName);
-
- target = llvm::TargetRegistry::lookupTarget("", triple, error);
- if (!target) {
- LOG4CXX_ERROR(_logger, "Couldn't create Target: " << error);
- return;
- }
- LOG4CXX_INFO(_logger, "Target: " << target->getName());
-
- STI.reset(target->createMCSubtargetInfo(tripleName, "", ""));
- if (!STI) {
- LOG4CXX_ERROR(_logger, "No subtarget for target " << tripleName);
- return;
- }
-}
+++ /dev/null
-#ifndef INCLUDE__Target_hxx
-#define INCLUDE__Target_hxx
-
-#include <log4cxx/logger.h>
-
-#include "include_llvm.hxx"
-
-class Target {
-public:
- Target(llvm::object::Binary* binary);
-
- const llvm::Target& getTarget() const {
- return *target;
- }
-
- const llvm::MCSubtargetInfo& getSubTargetInfo() const {
- return *STI;
- }
-
- std::string getTripleName() const {
- return triple.getTriple();
- }
-private:
- log4cxx::LoggerPtr _logger;
- llvm::Triple triple;
-
- const llvm::Target * target;
- llvm::OwningPtr<const llvm::MCSubtargetInfo> STI;
-};
-
-#endif
--- /dev/null
+#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<ObjectFile>(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<MCObjectDisassembler> OD(
+ new MCObjectDisassembler(*o, *DisAsm, *MIA));
+ Mod.reset(OD->buildModule(false));
+}
--- /dev/null
+#ifndef INCLUDE__LLVMDisassembler_hxx
+#define INCLUDE__LLVMDisassembler_hxx
+
+#include <memory>
+#include <log4cxx/logger.h>
+
+#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<void (long, std::string, std::string)> 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<llvm::object::Binary> binary;
+
+
+ const llvm::Target * target;
+ llvm::object::ObjectFile * o;
+
+ std::unique_ptr<const llvm::MCRegisterInfo> MRI;
+ std::unique_ptr<const llvm::MCAsmInfo> AsmInfo;
+ std::unique_ptr<llvm::MCModule> Mod;
+ std::unique_ptr<llvm::MCInstPrinter> IP;
+ std::unique_ptr<llvm::MCDisassembler> DisAsm;
+ std::unique_ptr<const llvm::MCObjectFileInfo> MOFI;
+ std::unique_ptr<llvm::MCContext> Ctx;
+ std::unique_ptr<const llvm::MCInstrAnalysis> MIA;
+ std::unique_ptr<const llvm::MCSubtargetInfo> STI;
+ std::unique_ptr<const llvm::MCInstrInfo> MII;
+ llvm::OwningPtr<llvm::MCRelocationInfo> RelInfo;
+ llvm::OwningPtr<llvm::MCSymbolizer> Symzer;
+
+ std::map<std::string, llvm::object::SectionRef> sections;
+ std::map<std::string, llvm::object::SymbolRef> symbols;
+};
+
+#endif
-#include "Mainwindow.hxx"
+ #include "Mainwindow.hxx"
#include "widgets/BasicBlockWidget.hxx"
#include "qt.hxx"
+#include "disassembler/llvm/LLVMDisassembler.hxx"
#include <iostream>
#include <sstream>
tr("Binaries (*)"));
if (fileName != "") {
- curBin = new qtlldb::Binary(fileName.toStdString());
-
- std::vector<std::string> 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<std::string> symbols = curBin->getSymbols();
+ // if (0 == symbols.size())
+ // populateSymbolInformation(".text");
+ // for (auto it = symbols.begin(); it != symbols.end(); ++it) {
+ // populateSymbolInformation(*it);
+ // }
}
}
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
+#include <memory>
#include <QTextEdit>
#include <QPushButton>
#include <QMainWindow>
#include <QListWidget>
#include <QStackedWidget>
-#include "Binary.hxx"
+#include "disassembler/Disassembler.hxx"
class Mainwindow : public QMainWindow {
Q_OBJECT
QAction *exitAction;
QAction *openAction;
- qtlldb::Binary * curBin;
+ std::shared_ptr<Disassembler> disassembler;
private slots:
void quit();
void open();