From 231dae075375e7d57982f5107b86294fbe726b33 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Tue, 6 Jan 2015 22:23:25 +0100 Subject: [PATCH] Add in an Information Manager 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 | 5 +- src/core/InformationManager.cxx | 9 ++ src/core/InformationManager.hxx | 43 ++++++ src/disassembler/Disassembler.hxx | 11 +- src/disassembler/llvm/LLVMDisassembler.cxx | 9 +- src/disassembler/llvm/LLVMDisassembler.hxx | 71 ++++----- src/gui/Mainwindow.cxx | 163 +++++++++++---------- src/gui/Mainwindow.hxx | 37 ++--- src/main.cxx | 8 +- 9 files changed, 215 insertions(+), 141 deletions(-) create mode 100644 src/core/InformationManager.cxx create mode 100644 src/core/InformationManager.hxx diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a6433f..ab55827 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 index 0000000..6e91572 --- /dev/null +++ b/src/core/InformationManager.cxx @@ -0,0 +1,9 @@ +#include "InformationManager.hxx" +#include "disassembler/llvm/LLVMDisassembler.hxx" + +#include + +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 index 0000000..5d2ef64 --- /dev/null +++ b/src/core/InformationManager.hxx @@ -0,0 +1,43 @@ +#ifndef INCLUDE__InformationManager_hxx +#define INCLUDE__InformationManager_hxx + +#include +#include + +class Disassembler; +class Function; + +class InformationManager { +public: + boost::signals2::connection + connect_new_function_signal(std::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 f) { + return reset_signal.connect(f); + } + + // boost::signals2::connection + // connect_information_added_signal(uint64_t begin, uint64_t end, + // std::function) { + + // } + + Disassembler* getDisassembler() { + return disassembler.get(); + } + + void reset(const std::string& filename); +private: + boost::signals2::signal reset_signal; + boost::signals2::signal new_function_signal; + std::unique_ptr disassembler; +}; + +#endif /* INCLUDE__InformationManager_hxx */ diff --git a/src/disassembler/Disassembler.hxx b/src/disassembler/Disassembler.hxx index a618ae5..c88bfd5 100644 --- a/src/disassembler/Disassembler.hxx +++ b/src/disassembler/Disassembler.hxx @@ -1,4 +1,4 @@ -#ifndef INCLUDE__Disassembler_hxx + #ifndef INCLUDE__Disassembler_hxx #define INCLUDE__Disassembler_hxx #include @@ -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 callback) = 0; diff --git a/src/disassembler/llvm/LLVMDisassembler.cxx b/src/disassembler/llvm/LLVMDisassembler.cxx index 6b3402e..7f87b80 100644 --- a/src/disassembler/llvm/LLVMDisassembler.cxx +++ b/src/disassembler/llvm/LLVMDisassembler.cxx @@ -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 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() { diff --git a/src/disassembler/llvm/LLVMDisassembler.hxx b/src/disassembler/llvm/LLVMDisassembler.hxx index f2baecb..d26bb12 100644 --- a/src/disassembler/llvm/LLVMDisassembler.hxx +++ b/src/disassembler/llvm/LLVMDisassembler.hxx @@ -15,13 +15,14 @@ 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 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 blocks; std::map functions; - 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; - std::unique_ptr RelInfo; - std::unique_ptr Symzer; - - std::map sections; - std::map symbols; + 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; + std::unique_ptr RelInfo; + std::unique_ptr Symzer; + + std::map sections; + std::map symbols; + InformationManager * manager; }; #endif diff --git a/src/gui/Mainwindow.cxx b/src/gui/Mainwindow.cxx index f98cd60..7b207fa 100644 --- a/src/gui/Mainwindow.cxx +++ b/src/gui/Mainwindow.cxx @@ -1,6 +1,7 @@ #include "Mainwindow.hxx" #include "qt.hxx" #include "disassembler/llvm/LLVMDisassembler.hxx" + #include "widgets/CFGScene.hxx" #include @@ -9,75 +10,105 @@ #include -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& 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& known_blocks, - CFGScene * scene, uint64_t starty, uint64_t startx) { + std::map& 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); -} diff --git a/src/gui/Mainwindow.hxx b/src/gui/Mainwindow.hxx index 7f6d63e..40fa81d 100644 --- a/src/gui/Mainwindow.hxx +++ b/src/gui/Mainwindow.hxx @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -12,34 +13,34 @@ #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; std::map blocks; + std::set functions; + InformationManager* manager; private Q_SLOTS: - void quit(); - void open(); + void quit(); + void open(); }; #endif /* INCLUDE__Mainwindow_hxx_ */ diff --git a/src/main.cxx b/src/main.cxx index c33d6c4..290657d 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -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(); } -- 2.39.2