]> git.siccegge.de Git - frida/frida.git/commitdiff
Add CFGScene QGraphicsScene taking care of BasicBlock stuff
authorChristoph Egger <christoph@anonymous.siccegge.de>
Fri, 28 Nov 2014 21:52:02 +0000 (22:52 +0100)
committerChristoph Egger <christoph@anonymous.siccegge.de>
Fri, 28 Nov 2014 21:52:02 +0000 (22:52 +0100)
Rearranges BasicBlocks to look nicely and draws the arrows. There is
lots of stuff left here like backwards edges that are just ignored for
now.

CMakeLists.txt
src/gui/Mainwindow.cxx
src/gui/widgets/BasicBlockWidget.hxx
src/gui/widgets/CFGScene.cxx [new file with mode: 0644]
src/gui/widgets/CFGScene.hxx [new file with mode: 0644]

index 87bed5a2da49a9d56f7f790eeeee3e948cf1e62b..d5080b7489ffbd6eaddf306960f12ab84bf42ee6 100644 (file)
@@ -42,6 +42,7 @@ SET(frida_SOURCES
   src/main.cxx
   src/gui/Mainwindow.cxx
   src/gui/widgets/BasicBlockWidget.cxx
+  src/gui/widgets/CFGScene.cxx
   src/gui/widgets/ScriptingDock.cxx
   src/disassembler/Disassembler.cxx
   src/disassembler/llvm/LLVMDisassembler.cxx
@@ -51,6 +52,7 @@ SET(frida_HEADERS
   src/gui/qt.hxx
   src/gui/Mainwindow.hxx
   src/gui/widgets/BasicBlockWidget.hxx
+  src/gui/widgets/CFGScene.hxx
   src/gui/widgets/ScriptingDock.hxx
   src/disassembler/llvm/LLVMDisassembler.hxx
   src/disassembler/Disassembler.hxx
index c00c8f83637950f55cdf8009eb4c633a460b8999..9a8310c4e00bfbe500270330f37f9a02346d591d 100644 (file)
@@ -1,6 +1,7 @@
 #include "Mainwindow.hxx"
 #include "qt.hxx"
 #include "disassembler/llvm/LLVMDisassembler.hxx"
+#include "widgets/CFGScene.hxx"
 
 #include <iostream>
 #include <sstream>
@@ -76,7 +77,7 @@ namespace {
        BasicBlockWidget *
        local__add_basic_block(BasicBlock * block, Disassembler * dis,
                                                   std::map<uint64_t, BasicBlockWidget*>& known_blocks,
-                                                  QGraphicsScene * scene, uint64_t starty, uint64_t startx) {
+                                                  CFGScene * scene, uint64_t starty, uint64_t startx) {
 
                decltype(known_blocks.begin()) old;
                if ((old = known_blocks.find(block->getStartAddress())) != known_blocks.end())
@@ -91,7 +92,7 @@ namespace {
 
                scene->addItem(widget);
                widget->setFlag(QGraphicsItem::ItemIsMovable, true);
-               widget->moveBy(100*startx, 10*(block->getStartAddress() - starty));
+               widget->moveBy(100*startx, block->getStartAddress() - starty);
 
                dis->printEachInstruction(block->getStartAddress(), block->getEndAddress(),
                                                                  [&](uint8_t* bytes, size_t byte_count, const std::string& line) {
@@ -125,7 +126,7 @@ void Mainwindow::populateSymbolInformation(Function* fun) {
     QTabWidget * w = new QTabWidget();
 
     // CFG
-    QGraphicsScene * scene = new QGraphicsScene;
+    CFGScene * scene = new CFGScene;
 
        BasicBlock * block = disassembler->getBasicBlock(fun->getStartAddress());
 
index bc579a90efaf7670dd5bfdd77a144145ae42a836..dd2fa30208d8a347c1672aed7e94a85a80d421f2 100644 (file)
@@ -5,6 +5,7 @@
 #include "disassembler/BasicBlock.hxx"
 #include <vector>
 #include <cassert>
+#include <tuple>
 
 class BasicBlockWidget : public QGraphicsItem
 {
@@ -15,37 +16,26 @@ public:
 
     QRectF boundingRect() const  {
         qreal penWidth = 1;
-
-
-               if (next[0]) {
-                       if (next[1]) {
-                               result |= QRectF(QPointF(x + dx/3, y+dy),
-                                                                mapFromScene(next[0]->getEntry()));
-                       } else {
-                               result |= QRectF(QPointF(x + dx/2, y+dy),
-                                                                mapFromScene(next[0]->getEntry()));
-                       }
-               }
-               if (next[1])
-                       result |= QRectF(QPointF(x + 2*dx/3, y+dy),
-                                                        mapFromScene(next[1]->getEntry()));
-
                QRectF result(- penWidth / 2, - penWidth / 2,
                       width + penWidth, height + penWidth);
         return result;
     }
-       void mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+
+       void mouseMoveEvent(QGraphicsSceneMouseEvent * event) {
                QGraphicsItem::mouseMoveEvent(event);
-               std::for_each(previous.begin(), previous.end(),
-                                         [&] (BasicBlockWidget * item) {
-                                                 item->update(boundingRect() | item->boundingRect());
-                                         });
+        scene()->update();
        }
 
        QPointF getEntry() const {
                return mapToScene(QPointF(width/2, 0));
        }
 
+    std::tuple<QPointF, QPointF, QPointF> getExits() const {
+        return std::make_tuple(mapToScene(QPointF(  width/3, height)),
+                               mapToScene(QPointF(  width/2, height)),
+                               mapToScene(QPointF(2*width/3, height)));
+    }
+
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                QWidget *widget) {
         painter->fillRect(0, 0, width, height, QColor(0xcc, 0xcc, 0xff, 0xff));
@@ -53,24 +43,7 @@ public:
         painter->drawRect(0, 0, width, height);
         painter->drawText(5, 15, name);
                if (_widget.rowCount() != 0)
-                       _widget.render(painter);
-
-               if (next[0]) {
-                       if (next[1]) {
-                               painter->setPen(QColor(0x00, 0xff, 0x00, 0xff));
-                               painter->drawLine(QPointF(x + dx/3, y+dy),
-                                                                 mapFromScene(next[0]->getEntry()));
-                       } else {
-                               painter->setPen(QColor(0x00, 0x00, 0x00, 0xff));
-                               painter->drawLine(QPointF(x + dx/2, y+dy),
-                                                                 mapFromScene(next[0]->getEntry()));
-                       }
-               }
-               painter->setPen(QColor(0xff, 0x00, 0x00, 0xff));
-               if (next[1])
-                       painter->drawLine(QPointF(x + 2*dx/3, y+dy),
-                                                         mapFromScene(next[1]->getEntry()));
-
+                       _widget.render(painter, QPoint(5, 20));
     }
 
        void addPrevious(BasicBlockWidget * widget) {
@@ -82,6 +55,10 @@ public:
                next[1] = right;
        }
 
+    BasicBlockWidget ** getNext() {
+        return next;
+    }
+
 private:
     uint32_t width, height;
     QTableWidget _widget;
diff --git a/src/gui/widgets/CFGScene.cxx b/src/gui/widgets/CFGScene.cxx
new file mode 100644 (file)
index 0000000..7bed8f1
--- /dev/null
@@ -0,0 +1,62 @@
+#include "CFGScene.hxx"
+
+void CFGScene::drawBackground(QPainter* painter, const QRectF & rect) {
+    QGraphicsScene::drawBackground(painter, rect);
+
+    spaceWidgets();
+
+    for (BasicBlockWidget * widget : widgets) {
+        QPointF kopf = widget->getEntry();
+        painter->setPen(QColor(0x00, 0xff, 0x00, 0xff));
+        painter->drawLine(kopf, kopf - QPointF(0, 20));
+
+        auto tails = widget->getExits();
+        auto next = widget->getNext();
+        if (NULL != next[0]) {
+            if (NULL != next[1]) {
+                painter->setPen(QColor(0xff, 0x00, 0x00, 0xff));
+                painter->drawLine(std::get<0>(tails), std::get<0>(tails) + QPointF(0, 20));
+                drawLine(painter, std::get<0>(tails) + QPointF(0, 20), next[1]->getEntry() - QPointF(0, 20));
+                painter->setPen(QColor(0x00, 0xff, 0x00, 0xff));
+                painter->drawLine(std::get<2>(tails), std::get<2>(tails) + QPointF(0, 20));
+                drawLine(painter, std::get<2>(tails) + QPointF(0, 20), next[0]->getEntry() - QPointF(0, 20));
+            } else {
+                painter->setPen(QColor(0x00, 0x00, 0x00, 0xff));
+                painter->drawLine(std::get<1>(tails), std::get<1>(tails) + QPointF(0, 20));
+                drawLine(painter, std::get<1>(tails) + QPointF(0, 20), next[0]->getEntry() - QPointF(0, 20));
+            }
+        }
+    }
+}
+
+void CFGScene::drawLine(QPainter* painter, QPointF from, QPointF to, bool left) {
+    if ((to - from).y() > 0) {
+        QPointF angle1(from + QPointF(0, (to - from).y())), angle2(to - QPointF(0, (to - from).y() / 2));
+        painter->drawLine(from,   angle1);
+        painter->drawLine(angle1, to);
+    }
+}
+
+void CFGScene::spaceWidgets() {
+    bool changed = false;
+    do {
+        changed = false;
+        for (BasicBlockWidget * widget : widgets) {
+            QPointF out(std::get<0>(widget->getExits()));
+            BasicBlockWidget ** next = widget->getNext();
+
+            if (NULL != next[0]
+                && (next[0]->getEntry() - widget->getEntry()).y() > 0
+                && (next[0]->getEntry() - out).y() < 50) {
+                next[0]->moveBy(0, 1);
+                changed = true;
+            }
+            if (NULL != next[1]
+                && (next[1]->getEntry() - widget->getEntry()).y() > 0
+                && (next[1]->getEntry() - out).y() < 50) {
+                next[1]->moveBy(0, 1);
+                changed = true;
+            }
+        }
+    } while (changed);
+}
diff --git a/src/gui/widgets/CFGScene.hxx b/src/gui/widgets/CFGScene.hxx
new file mode 100644 (file)
index 0000000..6baa618
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef INCLUDE__CFGScene_hxx
+#define INCLUDE__CFGScene_hxx
+
+#include "gui/qt.hxx"
+#include "BasicBlockWidget.hxx"
+
+#include <vector>
+
+class CFGScene : public QGraphicsScene {
+public:
+    CFGScene(QWidget * parent = 0)
+        : QGraphicsScene(parent) {}
+
+    // Take special care when adding a BasicBlock to the scene as we
+    // need to draw arrows for it later on
+    void addItem(BasicBlockWidget* block) {
+        widgets.push_back(block);
+        QGraphicsScene::addItem(block);
+    }
+
+    virtual void drawBackground(QPainter* painter, const QRectF & rect);
+private:
+    std::vector<BasicBlockWidget*> widgets;
+
+    void drawLine(QPainter* painter, QPointF from, QPointF to, bool left = true);
+
+    void spaceWidgets();
+};
+
+#endif