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