Add in an Information Manager
authorChristoph Egger <christoph@christoph-egger.org>
Tue, 6 Jan 2015 21:23:25 +0000 (22:23 +0100)
committerChristoph Egger <christoph@christoph-egger.org>
Wed, 7 Jan 2015 10:06:46 +0000 (11:06 +0100)
Now individual functions are added to the GUI via signals. This is the
way it was alwasys supposed to work. Now Information flow is cleaner,
we can add support to save things and we can properly tag things as
functions and rerun the disassembler.

Also includes some whitespace cleanup for technical reasons

CMakeLists.txt
src/core/InformationManager.cxx [new file with mode: 0644]
src/core/InformationManager.hxx [new file with mode: 0644]
src/disassembler/Disassembler.hxx
src/disassembler/llvm/LLVMDisassembler.cxx
src/disassembler/llvm/LLVMDisassembler.hxx
src/gui/Mainwindow.cxx
src/gui/Mainwindow.hxx
src/main.cxx

index 8a6433f916c0f3d5a30280c7c96329ebb92595f5..ab55827c77f948cf760ea42a8eb0c85ef7a1c792 100644 (file)
@@ -27,7 +27,8 @@ execute_process(COMMAND ${LLVM_CONFIG} --ldflags     OUTPUT_VARIABLE LLVM_LDFLAG
 execute_process(COMMAND ${LLVM_CONFIG} --libs        OUTPUT_VARIABLE LLVM_LIBS        OUTPUT_STRIP_TRAILING_WHITESPACE)
 execute_process(COMMAND ${LLVM_CONFIG} --system-libs OUTPUT_VARIABLE LLVM_SYSTEM_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE)
 
-string(REPLACE -O2 '' LLVM_CFLAGS ${LLVM_CFLAGS})
+string(REPLACE -O2 "" LLVM_CFLAGS ${LLVM_CFLAGS})
+string(REPLACE -fno-exceptions "" LLVM_CFLAGS ${LLVM_CFLAGS})
 
 separate_arguments(LLVM_CFLAGS)
 add_definitions(${LLVM_CFLAGS})
@@ -41,6 +42,7 @@ set(CMAKE_CXX_COMPILER "clang++")
 
 SET(frida_SOURCES
   src/main.cxx
+  src/core/InformationManager.cxx
   src/gui/Mainwindow.cxx
   src/gui/widgets/BasicBlockWidget.cxx
   src/gui/widgets/CFGScene.cxx
@@ -50,6 +52,7 @@ SET(frida_SOURCES
   )
 SET(frida_HEADERS
   src/include_llvm.hxx
+  src/core/InformationManager.hxx
   src/gui/qt.hxx
   src/gui/Mainwindow.hxx
   src/gui/widgets/BasicBlockWidget.hxx
diff --git a/src/core/InformationManager.cxx b/src/core/InformationManager.cxx
new file mode 100644 (file)
index 0000000..6e91572
--- /dev/null
@@ -0,0 +1,9 @@
+#include "InformationManager.hxx"
+#include "disassembler/llvm/LLVMDisassembler.hxx"
+
+#include <iostream>
+
+void InformationManager::reset(const std::string& filename) {
+       disassembler.reset(new LLVMDisassembler(filename, this));
+       disassembler.get()->start();
+}
diff --git a/src/core/InformationManager.hxx b/src/core/InformationManager.hxx
new file mode 100644 (file)
index 0000000..5d2ef64
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef INCLUDE__InformationManager_hxx
+#define INCLUDE__InformationManager_hxx
+
+#include <boost/signals2.hpp>
+#include <functional>
+
+class Disassembler;
+class Function;
+
+class InformationManager {
+public:
+       boost::signals2::connection
+       connect_new_function_signal(std::function<void(Function*)> f) {
+               return new_function_signal.connect(f);
+       }
+
+       void signal_new_function(Function* f) {
+               new_function_signal(f);
+       }
+
+       boost::signals2::connection
+       connect_reset_signal(std::function<void ()> f) {
+               return reset_signal.connect(f);
+       }
+
+       // boost::signals2::connection
+       // connect_information_added_signal(uint64_t begin, uint64_t end,
+       //                                  std::function<void (uint64_t)>) {
+
+       // }
+
+       Disassembler* getDisassembler() {
+               return disassembler.get();
+       }
+
+       void reset(const std::string& filename);
+private:
+       boost::signals2::signal<void ()> reset_signal;
+       boost::signals2::signal<void (Function*)> new_function_signal;
+       std::unique_ptr<Disassembler> disassembler;
+};
+
+#endif /* INCLUDE__InformationManager_hxx */
index a618ae587e020575b5c6b246194f5d60def4046e..c88bfd5f1408933e3d1ccc9bbd055b5a097b2532 100644 (file)
@@ -1,4 +1,4 @@
-#ifndef INCLUDE__Disassembler_hxx
+  #ifndef INCLUDE__Disassembler_hxx
 #define INCLUDE__Disassembler_hxx
 
 #include <string>
@@ -6,15 +6,16 @@
 
 #include "disassembler/BasicBlock.hxx"
 #include "disassembler/Function.hxx"
-
+#include "core/InformationManager.hxx"
 
 class Disassembler {
 public:
-       Disassembler(const std::string& filename) {}
+       Disassembler(const std::string& filename, InformationManager* manager) {}
     virtual ~Disassembler() {}
 
-       void getSymbols();
-       uint64_t entryAddress();
+       virtual void start() = 0;
+       virtual void getSymbols() = 0;
+       virtual uint64_t entryAddress() = 0;
        virtual BasicBlock * getBasicBlock(uint64_t address) = 0;
 
        virtual void forEachFunction(std::function<void (uint64_t, Function*)> callback) = 0;
index 6b3402eb0b2414d56c4b415f7467e3c29d7e33cd..7f87b80116068fc6c6d88cafae059b2839c14400 100644 (file)
@@ -14,10 +14,12 @@ using std::error_code;
  * ist sondern z.B. einfach nur Instruktionen oder ein Bootsektor oder
  * foo
  */
-LLVMDisassembler::LLVMDisassembler(const std::string& filename)
-    : Disassembler(filename)
+LLVMDisassembler::LLVMDisassembler(const std::string& filename,
+                                   InformationManager* manager)
+       : Disassembler(filename, manager)
     , logger(log4cxx::Logger::getLogger("LLVMDisassembler"))
     , triple("unknown-unknown-unknown")
+    , manager(manager)
 {
     LOG4CXX_DEBUG(logger, "Handling file" << filename);
     auto result = createBinary(filename);
@@ -111,7 +113,9 @@ LLVMDisassembler::LLVMDisassembler(const std::string& filename)
     std::unique_ptr<MCObjectDisassembler> OD(
         new MCObjectDisassembler(*o, *DisAsm, *MIA));
     Mod.reset(OD->buildModule(false));
+}
 
+void LLVMDisassembler::start() {
     readSymbols();
     readSections();
     disassemble();
@@ -231,6 +235,7 @@ void LLVMDisassembler::disassembleFunction(LLVMFunction* function) {
         }
     }
     LOG4CXX_DEBUG(logger, "Finished function " << function->getName());
+    manager->signal_new_function(function);
 }
 
 void LLVMDisassembler::disassemble() {
index f2baecb33a2e44904322f298d429ef05852a2654..d26bb126f8dee24fc592afc058a5cfd6410c7c62 100644 (file)
 
 
 class LLVMDisassembler
-    : public Disassembler {
+       : public Disassembler {
 public:
-    LLVMDisassembler(const std::string& filename);
-    virtual ~LLVMDisassembler();
+       LLVMDisassembler(const std::string& filename, InformationManager* manager);
+       virtual ~LLVMDisassembler();
 
-       void getSymbols();
-       uint64_t entryAddress();
+       void start();
+       void getSymbols() {}
+       uint64_t entryAddress() {}
 
        void forEachFunction(std::function<void (uint64_t, Function*)> callback);
        void printEachInstruction(uint64_t start, uint64_t end,
@@ -31,47 +32,47 @@ public:
                return blocks[address];
        }
 
-    Function * disassembleFunctionAt(uint64_t address, const std::string& name = "");
+       Function * disassembleFunctionAt(uint64_t address, const std::string& name = "");
 
 protected:
-    bool isFunctionCall(uint64_t address) {return false;}
-    bool isJump(uint64_t address) {return false;}
+       bool isFunctionCall(uint64_t address) {return false;}
+       bool isJump(uint64_t address) {return false;}
 
 private:
-    // http://llvm.org/docs/doxygen/html/MCObjectDisassembler_8cpp_source.html +197
-    void disassembleFunction(LLVMFunction* function);
-    void splitBlocks();
-    void disassemble();
+       // http://llvm.org/docs/doxygen/html/MCObjectDisassembler_8cpp_source.html +197
+       void disassembleFunction(LLVMFunction* function);
+       void splitBlocks();
+       void disassemble();
 
        void readSymbols();
        void readSections();
 
-    log4cxx::LoggerPtr logger;
+       log4cxx::LoggerPtr logger;
        std::map<uint64_t, LLVMBasicBlock*> blocks;
        std::map<uint64_t, LLVMFunction*> functions;
 
-    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;
-    std::unique_ptr<llvm::MCRelocationInfo> RelInfo;
-    std::unique_ptr<llvm::MCSymbolizer> Symzer;
-
-    std::map<std::string, llvm::object::SectionRef> sections;
-    std::map<std::string, llvm::object::SymbolRef> symbols;
+       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;
+       std::unique_ptr<llvm::MCRelocationInfo> RelInfo;
+       std::unique_ptr<llvm::MCSymbolizer> Symzer;
+
+       std::map<std::string, llvm::object::SectionRef> sections;
+       std::map<std::string, llvm::object::SymbolRef> symbols;
+       InformationManager * manager;
 };
 
 #endif
index f98cd60a226888da2f780af6c3dc924cdde6a45b..7b207faf9504281dfa3e9b7ff2ef663ed4ddfbd6 100644 (file)
@@ -1,6 +1,7 @@
 #include "Mainwindow.hxx"
 #include "qt.hxx"
 #include "disassembler/llvm/LLVMDisassembler.hxx"
+
 #include "widgets/CFGScene.hxx"
 
 #include <iostream>
 
 #include <QtGui>
 
-Mainwindow::Mainwindow(const std::string& filename)
-{
-    openAction = new QAction(tr("&Open"), this);
-    // saveAction = new QAction(tr("&Save"), this);
-    exitAction = new QAction(tr("E&xit"), this);
-
-    connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
-    // connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
-    connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
-
-    fileMenu = menuBar()->addMenu(tr("&File"));
-    fileMenu->addAction(openAction);
-    // fileMenu->addAction(saveAction);
-    fileMenu->addSeparator();
-    fileMenu->addAction(exitAction);
-
-    scripting = new ScriptingDock(tr("Scripting"), this);
-    scripting->setAllowedAreas(Qt::BottomDockWidgetArea);
-    addDockWidget(Qt::BottomDockWidgetArea, scripting);
-
-    listWidget = new QListWidget();
-    stackedWidget = new QStackedWidget();
-    dockWidget = new QDockWidget(tr("Functions"), this);
-    dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea |
-                                Qt::RightDockWidgetArea);
-    dockWidget->setWidget(listWidget);
-    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
-    setCentralWidget(stackedWidget);
-
-    connect(listWidget, SIGNAL(currentRowChanged(int)),
-            stackedWidget, SLOT(setCurrentIndex(int)));
-
-    setWindowTitle(tr("FRIDA"));
-
-       openBinary(filename);
+namespace {
+       BasicBlockWidget *
+       local__add_basic_block(BasicBlock * block, Disassembler * dis,
+                              std::map<uint64_t, BasicBlockWidget*>& known_blocks,
+                              CFGScene * scene, uint64_t starty, uint64_t startx);
+}
+
+Mainwindow::Mainwindow(InformationManager* mgr)
+       : manager(mgr) {
+       openAction = new QAction(tr("&Open"), this);
+       // saveAction = new QAction(tr("&Save"), this);
+       exitAction = new QAction(tr("E&xit"), this);
+
+       connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
+       // connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
+       connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+
+       fileMenu = menuBar()->addMenu(tr("&File"));
+       fileMenu->addAction(openAction);
+       // fileMenu->addAction(saveAction);
+       fileMenu->addSeparator();
+       fileMenu->addAction(exitAction);
+
+       scripting = new ScriptingDock(tr("Scripting"), this);
+       scripting->setAllowedAreas(Qt::BottomDockWidgetArea);
+       addDockWidget(Qt::BottomDockWidgetArea, scripting);
+
+       listWidget = new QListWidget();
+       stackedWidget = new QStackedWidget();
+       dockWidget = new QDockWidget(tr("Functions"), this);
+       dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea |
+                                   Qt::RightDockWidgetArea);
+       dockWidget->setWidget(listWidget);
+       addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
+       setCentralWidget(stackedWidget);
+
+       connect(listWidget, SIGNAL(currentRowChanged(int)),
+               stackedWidget, SLOT(setCurrentIndex(int)));
+
+       setWindowTitle(tr("FRIDA"));
+
+       mgr->connect_new_function_signal([&] (Function* fun) {addFunction(fun);});
 }
 
 void Mainwindow::quit()
 {
-    QMessageBox messageBox;
-    messageBox.setWindowTitle(tr("Notepad"));
-    messageBox.setText(tr("Do you really want to quit?"));
-    messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
-    messageBox.setDefaultButton(QMessageBox::No);
-    if (messageBox.exec() == QMessageBox::Yes)
-        qApp->quit();
+       QMessageBox messageBox;
+       messageBox.setWindowTitle(tr("Notepad"));
+       messageBox.setText(tr("Do you really want to quit?"));
+       messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+       messageBox.setDefaultButton(QMessageBox::No);
+       if (messageBox.exec() == QMessageBox::Yes)
+               qApp->quit();
 }
 
 void Mainwindow::open() {
-    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
-                                                    tr("Binaries (*)"));
+       QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
+                                                       tr("Binaries (*)"));
 
-       openBinary(fileName.toStdString());
+       manager->reset(fileName.toStdString());
 }
 
-void Mainwindow::openBinary(const std::string& filename) {
-    if (filename != "") {
-        disassembler.reset(new LLVMDisassembler(filename));
-               disassembler->forEachFunction([&](uint64_t address, Function* fun) {
-                               populateSymbolInformation(fun);
-                       });
-    }
+void Mainwindow::addFunction(Function* fun) {
+       if (functions.find(fun) != functions.end())
+               return;
+
+       functions.insert(fun);
+
+       QTabWidget * w = new QTabWidget();
+
+       // CFG
+       CFGScene * scene = new CFGScene;
+
+       Disassembler * dis = manager->getDisassembler();
+       std::cerr << dis << std::endl;
+
+       BasicBlock * block = dis->getBasicBlock(fun->getStartAddress());
+
+       local__add_basic_block(block, manager->getDisassembler(), blocks, scene, block->getStartAddress(), 100);
+
+       QGraphicsView * view = new QGraphicsView(scene);
+       w->addTab(view, "CFG");
+
+       // Listing
+       QTableWidget * t = new QTableWidget();
+       t->setColumnCount(3);
+       t->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
+
+       w->addTab(t, "Listing");
+
+       listWidget->addItem(fun->getName().c_str());
+       stackedWidget->addWidget(w);
 }
 
 namespace {
        BasicBlockWidget *
        local__add_basic_block(BasicBlock * block, Disassembler * dis,
-                                                  std::map<uint64_t, BasicBlockWidget*>& known_blocks,
-                                                  CFGScene * scene, uint64_t starty, uint64_t startx) {
+                              std::map<uint64_t, BasicBlockWidget*>& known_blocks,
+                              CFGScene * scene, uint64_t starty, uint64_t startx) {
 
                decltype(known_blocks.begin()) old;
                if ((old = known_blocks.find(block->getStartAddress())) != known_blocks.end())
@@ -124,27 +155,3 @@ namespace {
                return widget;
        }
 }
-
-void Mainwindow::populateSymbolInformation(Function* fun) {
-    QTabWidget * w = new QTabWidget();
-
-    // CFG
-    CFGScene * scene = new CFGScene;
-
-       BasicBlock * block = disassembler->getBasicBlock(fun->getStartAddress());
-
-       local__add_basic_block(block, disassembler.get(), blocks, scene, block->getStartAddress(), 100);
-
-    QGraphicsView * view = new QGraphicsView(scene);
-    w->addTab(view, "CFG");
-
-    // Listing
-    QTableWidget * t = new QTableWidget();
-    t->setColumnCount(3);
-    t->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
-
-    w->addTab(t, "Listing");
-
-    listWidget->addItem(fun->getName().c_str());
-    stackedWidget->addWidget(w);
-}
index 7f6d63e5c04d2d7e80f596eed4a26ca62d3aa025..40fa81d5f50de269927da297be9bbf6c37de8943 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <memory>
 #include <map>
+#include <set>
 #include <QTextEdit>
 #include <QPushButton>
 #include <QMainWindow>
 #include "disassembler/Disassembler.hxx"
 #include "widgets/BasicBlockWidget.hxx"
 #include "widgets/ScriptingDock.hxx"
+#include "core/InformationManager.hxx"
 
 class Mainwindow : public QMainWindow {
-    Q_OBJECT
+       Q_OBJECT
 public:
-    Mainwindow(const std::string& filename = "");
+       Mainwindow(InformationManager* mgr);
 private:
-       void openBinary(const std::string& filename);
+       void addFunction(Function* fun);
 
-    void populateSymbolInformation(Function * fun);
+       QTextEdit *textEdit;
+       QPushButton *quitButton;
+       QMenu *fileMenu;
 
-    QTextEdit *textEdit;
-    QPushButton *quitButton;
-    QMenu *fileMenu;
+       QTabWidget * tabwidget;
+       QListWidget * listWidget;
+       QStackedWidget * stackedWidget;
+       QDockWidget * dockWidget;
+       ScriptingDock * scripting;
 
-    QTabWidget * tabwidget;
-    QListWidget * listWidget;
-    QStackedWidget * stackedWidget;
-    QDockWidget * dockWidget;
-    ScriptingDock * scripting;
+       QAction *exitAction;
+       QAction *openAction;
 
-    QAction *exitAction;
-    QAction *openAction;
-
-    std::shared_ptr<Disassembler> disassembler;
        std::map<uint64_t, BasicBlockWidget*> blocks;
+       std::set<Function*> functions;
+       InformationManager* manager;
 private Q_SLOTS:
-    void quit();
-    void open();
+       void quit();
+       void open();
 };
 
 #endif /* INCLUDE__Mainwindow_hxx_ */
index c33d6c419fa750bd034b54bfeefd03ee98f1731d..290657d52004b6f9529575658cca7b6ee356f03a 100644 (file)
@@ -17,6 +17,8 @@
 #include "log4cxx/basicconfigurator.h"
 
 #include "gui/Mainwindow.hxx"
+#include "core/InformationManager.hxx"
+#include "disassembler/llvm/LLVMDisassembler.hxx"
 
 using std::cout;
 using std::cin;
@@ -39,10 +41,11 @@ int main(int argc, char** argv)
        parser.addVersionOption();
        parser.addPositionalArgument("filename", QCoreApplication::translate("main", "File to disassemble."));
 
-
        parser.process(app);
 #endif
 
+       InformationManager iman;
+
     LOG4CXX_DEBUG(_logger, "Initializing LLVM");
     llvm::InitializeAllTargetInfos();
     llvm::InitializeAllTargetMCs();
@@ -58,7 +61,8 @@ int main(int argc, char** argv)
        }
 #endif
 
-       Mainwindow m(filename);
+       Mainwindow m(&iman);
        m.show();
+       iman.reset(filename);
        return app.exec();
 }