]> git.siccegge.de Git - frida/frida.git/commitdiff
Name functions in BasicBlock view
authorChristoph Egger <Christoph.Egger@cs.fau.de>
Mon, 23 Feb 2015 15:36:31 +0000 (16:36 +0100)
committerChristoph Egger <Christoph.Egger@cs.fau.de>
Mon, 23 Feb 2015 15:37:14 +0000 (16:37 +0100)
Now call instructions have a symbolic name in the CFG view which is
updated upon function renaming

CMakeLists.txt
src/core/Function.cxx [new file with mode: 0644]
src/core/Function.hxx
src/core/InformationManager.cxx
src/core/InformationManager.hxx
src/core/events/RenameFunctionEvent.hxx [new file with mode: 0644]
src/gui/widgets/BasicBlockWidget.cxx
src/gui/widgets/BasicBlockWidget.hxx
src/gui/widgets/FunctionWidget.cxx [new file with mode: 0644]
src/gui/widgets/FunctionWidget.hxx [new file with mode: 0644]

index d948879d1cb61acb021154ff2bca54f2ae9fa614..0fe40fbae181dfdfbb05378dcb92b847ae77c4e6 100644 (file)
@@ -45,6 +45,7 @@ separate_arguments(LLVM_LIBS)
 SET(frida_SOURCES
   src/main.cxx
   src/core/InformationManager.cxx
+  src/core/Function.cxx
   src/gui/Mainwindow.cxx
   src/gui/widgets/BasicBlockWidget.cxx
   src/gui/widgets/CFGScene.cxx
diff --git a/src/core/Function.cxx b/src/core/Function.cxx
new file mode 100644 (file)
index 0000000..e9bb173
--- /dev/null
@@ -0,0 +1,20 @@
+#include "Function.hxx"
+#include "core/events/RenameFunctionEvent.hxx"
+#include "InformationManager.hxx"
+
+#include <iostream>
+
+Function::Function(const std::string& name, uint64_t start_address,
+                   InformationManager* manager)
+       : start_address(start_address)
+       , manager(manager) {
+       setName(name);
+}
+
+
+void Function::setName(const std::string& new_name) {
+       name = new_name;
+       RenameFunctionEvent event(new_name, start_address);
+       manager->dispatch(&event);
+}
+
index aebfe8f8591e2b1174551f4a69b9bf9ae8ab0ecc..b57dca2706edd31df2b31798c18d5ebedf301017 100644 (file)
@@ -8,11 +8,7 @@ class InformationManager;
 
 class Function {
 public:
-       Function(const std::string& name, uint64_t start_address,
-                InformationManager* manager)
-               : name(name)
-               , start_address(start_address)
-               ,manager(manager) {}
+       Function(const std::string& name, uint64_t start_address, InformationManager* manager);
 
        uint64_t getStartAddress() const {
                return start_address;
@@ -20,8 +16,7 @@ public:
 
        std::string getName() const
                { return name; }
-       void setName(const std::string& new_name)
-               { name = new_name; }
+       void setName(const std::string& new_name);
 
        InformationManager* getManager() const {
                return manager;
index 1234ac96aa64845775af2069a0bf73c901634d80..a274c418091e40efcab87f1f29821cb67ab3c5f9 100644 (file)
@@ -8,11 +8,11 @@
 #include <quazip/quazipfile.h>
 
 InformationManager::~InformationManager() {
-       for (BasicBlock * b : blocks)
-               delete b;
+       for (auto b : blocks)
+               delete b.second;
 
-       for (Function * f : functions)
-               delete f;
+       for (auto f : functions)
+               delete f.second;
 }
 
 void InformationManager::reset(const std::string& filename) {
@@ -27,7 +27,8 @@ void InformationManager::save(const QString& filename) {
        zip.setComment("FRIDA 0.0");
        QuaZipFile outZipFile(&zip);
 
-       for (Function* fun : functions) {
+       for (auto funpair : functions) {
+               Function* fun = funpair.second;
                QuaZipNewInfo zipinfo(fun->getName().c_str());
                zipinfo.setPermissions(static_cast<QFile::Permissions>(0x6444));
                outZipFile.open(QIODevice::WriteOnly, zipinfo);
@@ -60,8 +61,10 @@ void InformationManager::save(const QString& filename) {
 }
 
 void InformationManager::signal_new_function(Function* fun) {
-       functions.insert(fun);
-       for (auto b : fun->blocks())
-               blocks.insert(b.second);
+       functions.insert(std::make_pair(fun->getStartAddress(), fun));
+       for (auto b : fun->blocks()) {
+               BasicBlock* bl = b.second;
+               blocks.insert(std::make_pair(bl->getStartAddress(), bl));
+       }
        new_function_signal(fun);
 }
index a43b1181281cd1deea73b4d8cb595a1128bd108b..dc781285f049de01b2200f6a2e852ee3f21d9353 100644 (file)
@@ -4,7 +4,7 @@
 #include <boost/signals2.hpp>
 #include <functional>
 #include <string>
-#include <set>
+#include <map>
 
 class Disassembler;
 class Function;
@@ -12,6 +12,8 @@ class BasicBlock;
 
 class QString;
 
+class RenameFunctionEvent;
+
 class InformationManager {
 public:
        ~InformationManager();
@@ -20,33 +22,45 @@ public:
        void save(const QString& filename);
 
        void signal_new_function(Function* f);
+       void signal_new_dyn_symbol(const std::string& f)
+               { new_dyn_symbol_signal(f);     }
 
        boost::signals2::connection
        connect_new_function_signal(std::function<void(Function*)> f)
                { return new_function_signal.connect(f); }
 
-
-
        boost::signals2::connection
        connect_new_dyn_symbol_signal(std::function<void(const std::string& name)> f)
                { return new_dyn_symbol_signal.connect(f); }
 
-       void signal_new_dyn_symbol(const std::string& f)
-               { new_dyn_symbol_signal(f);     }
-
        boost::signals2::connection
        connect_reset_signal(std::function<void ()> f)
                { return reset_signal.connect(f); }
 
+       boost::signals2::connection
+       connect_rename_function_signal(std::function<void (RenameFunctionEvent*)> f)
+               { return rename_function_signal.connect(f); }
+
        Disassembler* getDisassembler()
                { return disassembler.get(); }
+
+       void dispatch(RenameFunctionEvent* event)
+               { rename_function_signal(event); }
+
+       Function* getFunction(uint64_t address)
+       { return functions[address]; }
+
+       BasicBlock* getBlock(uint64_t address)
+       { return blocks[address]; }
+
 private:
        boost::signals2::signal<void ()> reset_signal;
        boost::signals2::signal<void (Function*)> new_function_signal;
        boost::signals2::signal<void (const std::string& name)> new_dyn_symbol_signal;
+       boost::signals2::signal<void (RenameFunctionEvent*)> rename_function_signal;
        std::unique_ptr<Disassembler> disassembler;
-       std::set<Function*> functions;
-       std::set<BasicBlock*> blocks;
+       std::map<uint64_t, Function*> functions;
+       std::map<uint64_t, BasicBlock*> blocks;
 };
 
 #endif /* INCLUDE__InformationManager_hxx */
diff --git a/src/core/events/RenameFunctionEvent.hxx b/src/core/events/RenameFunctionEvent.hxx
new file mode 100644 (file)
index 0000000..a8c78d5
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef INCLUDE__RenameFunctionEvent_hxx_
+#define INCLUDE__RenameFunctionEvent_hxx_
+
+#include <string>
+
+class RenameFunctionEvent {
+public:
+       RenameFunctionEvent(const std::string& name, uint64_t address)
+               : new_name(name), address(address) {}
+
+       std::string new_name;
+       uint64_t address;
+};
+
+#endif /* INCLUDE__RenameFunctionEvent_hxx_ */
index 0036bda65180ea76cfa8e787332109a597cccfcb..f66a575167b83fb25d1cc12b4fd06d5975b583a0 100644 (file)
@@ -2,6 +2,10 @@
 #include "gui/Mainwindow.hxx"
 #include "gui/dialogs/SimpleStringDialog.hxx"
 #include "core/BasicBlock.hxx"
+#include "core/Function.hxx"
+#include "core/InformationManager.hxx"
+#include "core/events/RenameFunctionEvent.hxx"
+#include <iostream>
 
 class CustomQGraphicsTextItem : public QObject, public QGraphicsTextItem {
 public:
@@ -61,8 +65,11 @@ BasicBlockWidget::BasicBlockWidget(const QString& name, BasicBlock * block,
        : width(270), height(45), name(name)
        , _table(NULL)
        , block(block), mainwindow(mainwindow)
-       , logger(log4cxx::Logger::getLogger(name.toStdString() + "BasicBlock")) {
+       , logger(log4cxx::Logger::getLogger(name.toStdString() + " BasicBlockWidget")) {
        next[0] = NULL; next[1] = NULL;
+
+       block->getManager()->connect_rename_function_signal([=](RenameFunctionEvent* event) {updateFunctionName(event);});
+
        _widget.reset(new CustomQGraphicsTextItem("", this));
        _widget->setPos(5, 20);
        _widget->setTextInteractionFlags(Qt::TextSelectableByMouse|
@@ -78,6 +85,30 @@ BasicBlockWidget::BasicBlockWidget(const QString& name, BasicBlock * block,
                                 }
                         });
 }
+
+void BasicBlockWidget::updateFunctionName(RenameFunctionEvent *event) {
+       QString search = QString("function:") + QString::number(event->address, 16);
+       QTextDocument *document = _widget->document();
+       QTextBlock b = document->begin();
+       while (b.isValid()) {
+               for (QTextBlock::iterator i = b.begin(); !i.atEnd(); ++i) {
+                       QTextCharFormat format = i.fragment().charFormat();
+                       bool isLink = format.isAnchor();
+                       if (isLink)
+                       {
+                               if (search == format.anchorHref()) {
+                                       LOG4CXX_DEBUG(logger, i.fragment().text().toStdString() << " ---> " << format.anchorHref().toStdString());
+                                       QTextCursor c(b);
+                                       c.setPosition(i.fragment().position());
+                                       c.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, i.fragment().length());
+                                       c.movePosition(QTextCursor::Left,  QTextCursor::KeepAnchor, i.fragment().length());
+                                       c.movePosition(QTextCursor::WordRight,  QTextCursor::KeepAnchor);
+                                       c.insertText(event->new_name.c_str());
+                               }
+                       }
+               }
+               b = b.next();
+       }
 }
 
 void BasicBlockWidget::addItem(uint8_t* bytes, size_t num_bytes,
@@ -107,6 +138,16 @@ void BasicBlockWidget::addItem(uint8_t* bytes, size_t num_bytes,
 
        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] + " " + fun->getName().c_str();
+                               LOG4CXX_DEBUG(logger, "Naming function at " << address << " " << fun->getName());
+                       }
+               }
                line = "<a href=\"" + href + "\">" + line + "</a>";
        }
 
index ce1c833d09fbbb3b352ed244d6029ab2bc98cac5..8cf709c9f2f821449ac689c6af147ada50db34e8 100644 (file)
@@ -14,6 +14,8 @@ class CustomQGraphicsTextItem;
 
 class BasicBlock;
 
+class RenameFunctionEvent;
+
 class BasicBlockWidget : public QObject, public QGraphicsItem
 {
        Q_OBJECT
@@ -45,6 +47,8 @@ public:
        QString getName() const
                { return name; }
 private:
+       void updateFunctionName(RenameFunctionEvent* event);
+
        uint32_t width, height;
        QString name;
        std::unique_ptr<QGraphicsTextItem> _widget;
diff --git a/src/gui/widgets/FunctionWidget.cxx b/src/gui/widgets/FunctionWidget.cxx
new file mode 100644 (file)
index 0000000..e4c1c0b
--- /dev/null
@@ -0,0 +1 @@
+#include "FunctionWidget.hxx"
diff --git a/src/gui/widgets/FunctionWidget.hxx b/src/gui/widgets/FunctionWidget.hxx
new file mode 100644 (file)
index 0000000..fbd3638
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef INCLUDE__FunctionWidget_hxx_
+#define INCLUDE__FunctionWidget_hxx_
+
+#include "gui/qt.hxx"
+
+class Function;
+
+class FunctionWidget : public QTabWidget {
+       Q_OBJECT
+public:
+       FunctionWidget(Function* function)
+               : function(function) {}
+
+       virtual ~FunctionWidget() {}
+
+       Function* getFunction() const
+               { return function; }
+
+private:
+       Function * function;
+};
+
+#endif /* INCLUDE__FunctionWidget_hxx_ */