]> git.siccegge.de Git - frida/frida.git/blob - src/gui/Mainwindow.cxx
Fix layout if functions include blocks before entry
[frida/frida.git] / src / gui / Mainwindow.cxx
1 #include "Mainwindow.hxx"
2 #include "qt.hxx"
3 #include "disassembler/llvm/LLVMDisassembler.hxx"
4
5 #include "widgets/CFGScene.hxx"
6
7 #include <iostream>
8 #include <sstream>
9 #include <map>
10
11 #include <QtGui>
12
13 namespace {
14 BasicBlockWidget *
15 local__add_basic_block(BasicBlock * block, Disassembler * dis,
16 std::map<uint64_t, BasicBlockWidget*>& known_blocks,
17 CFGScene * scene, uint64_t starty, uint64_t startx);
18 }
19
20 Mainwindow::Mainwindow(InformationManager* mgr)
21 : manager(mgr) {
22 openAction = new QAction(tr("&Open"), this);
23 // saveAction = new QAction(tr("&Save"), this);
24 exitAction = new QAction(tr("E&xit"), this);
25
26 connect(openAction, SIGNAL(triggered()),
27 this, SLOT(open()));
28 // connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
29 connect(exitAction, SIGNAL(triggered()),
30 qApp, SLOT(quit()));
31
32 fileMenu = menuBar()->addMenu(tr("&File"));
33 fileMenu->addAction(openAction);
34 // fileMenu->addAction(saveAction);
35 fileMenu->addSeparator();
36 fileMenu->addAction(exitAction);
37
38 scripting = new ScriptingDock(tr("Scripting"), this);
39 scripting->setAllowedAreas(Qt::BottomDockWidgetArea);
40 addDockWidget(Qt::BottomDockWidgetArea, scripting);
41
42 listWidget = new QListWidget();
43 stackedWidget = new QStackedWidget();
44 dockWidget = new QDockWidget(tr("Functions"), this);
45 dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea |
46 Qt::RightDockWidgetArea);
47 dockWidget->setWidget(listWidget);
48 addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
49 setCentralWidget(stackedWidget);
50
51 connect(listWidget, SIGNAL(currentRowChanged(int)),
52 stackedWidget, SLOT(setCurrentIndex(int)));
53
54 setWindowTitle(tr("FRIDA"));
55
56 mgr->connect_new_function_signal([&] (Function* fun) {addFunction(fun);});
57 }
58
59 void Mainwindow::quit()
60 {
61 QMessageBox messageBox;
62 messageBox.setWindowTitle(tr("Notepad"));
63 messageBox.setText(tr("Do you really want to quit?"));
64 messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
65 messageBox.setDefaultButton(QMessageBox::No);
66 if (messageBox.exec() == QMessageBox::Yes)
67 qApp->quit();
68 }
69
70 void Mainwindow::open() {
71 QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
72 tr("Binaries (*)"));
73
74 manager->reset(fileName.toStdString());
75 }
76
77 void Mainwindow::addFunction(Function* fun) {
78 if (functions.find(fun) != functions.end())
79 return;
80
81 functions.insert(fun);
82
83 QTabWidget * w = new QTabWidget();
84
85 // CFG
86 CFGScene * scene = new CFGScene;
87
88 Disassembler * dis = manager->getDisassembler();
89 BasicBlock * block = dis->getBasicBlock(fun->getStartAddress());
90
91 uint64_t start_address(std::numeric_limits<uint64_t>::max());
92 for (auto b : fun->blocks()) {
93 if (b.first < start_address)
94 start_address = b.first;
95 }
96
97 local__add_basic_block(block, manager->getDisassembler(), blocks, scene,
98 start_address, 100);
99
100 QGraphicsView * view = new QGraphicsView(scene);
101 w->addTab(view, "CFG");
102
103 // Listing
104 QTableWidget * t = new QTableWidget();
105 t->setColumnCount(3);
106 t->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
107
108 w->addTab(t, "Listing");
109
110 listWidget->addItem(fun->getName().c_str());
111 stackedWidget->addWidget(w);
112 }
113
114 namespace {
115 BasicBlockWidget *
116 local__add_basic_block(BasicBlock * block, Disassembler * dis,
117 std::map<uint64_t, BasicBlockWidget*>& known_blocks,
118 CFGScene * scene, uint64_t starty, uint64_t startx) {
119
120 decltype(known_blocks.begin()) old;
121 if ((old = known_blocks.find(block->getStartAddress())) != known_blocks.end())
122 return old->second;
123
124 std::stringstream s;
125 s << "BLOCK_" << std::hex << block->getStartAddress()
126 << "_" << block->getEndAddress();
127 BasicBlockWidget * widget = new BasicBlockWidget(s.str().c_str(), block);
128
129 known_blocks.insert(std::make_pair(block->getStartAddress(), widget));
130
131 scene->addItem(widget);
132 widget->setFlag(QGraphicsItem::ItemIsMovable, true);
133 widget->moveBy(100*startx, block->getStartAddress() - starty);
134
135 dis->printEachInstruction(block->getStartAddress(),
136 block->getEndAddress(),
137 [&](uint8_t* bytes,
138 size_t byte_count,
139 const std::string& line) {
140 widget->addItem(bytes, byte_count, line.c_str() + 1);
141 });
142
143 BasicBlockWidget *tmp, *nextl(NULL), *nextr(NULL);
144 BasicBlock * tmpblock;
145 if (block->getNextBlock(0) != 0) {
146 int xshift = 0;
147 if (block->getNextBlock(1) != 0)
148 xshift = 1;
149 tmpblock = dis->getBasicBlock(block->getNextBlock(0));
150 tmp = local__add_basic_block(tmpblock, dis,
151 known_blocks,
152 scene, starty, startx+xshift);
153 nextl = tmp;
154 tmp->addPrevious(widget);
155 }
156 if (block->getNextBlock(1) != 0) {
157 tmpblock = dis->getBasicBlock(block->getNextBlock(1));
158 tmp = local__add_basic_block(tmpblock, dis,
159 known_blocks,
160 scene, starty, startx-1);
161 nextr = tmp;
162 tmp->addPrevious(widget);
163 }
164 widget->addNext(nextl, nextr);
165 return widget;
166 }
167 }