#include "Mainwindow.hxx"
#include "qt.hxx"
+#include "bindings/Guile.hxx"
#include "disassembler/llvm/LLVMDisassembler.hxx"
#include "core/Function.hxx"
#include "core/BasicBlock.hxx"
#include "core/InformationManager.hxx"
+#include "core/events/RenameFunctionEvent.hxx"
+#include "core/events/NewFunctionEvent.hxx"
+
+#include "widgets/FridaDock.hxx"
+#include "widgets/LogDock.hxx"
#include "widgets/ScriptingDock.hxx"
#include "widgets/CFGScene.hxx"
#include "widgets/FunctionWidget.hxx"
#include <sstream>
-namespace {
- BasicBlockWidget *
- local__add_basic_block(BasicBlock * block,
- Mainwindow * mainwindow, InformationManager * manager,
- std::map<uint64_t, BasicBlockWidget*>& known_blocks,
- CFGScene * scene, uint64_t starty, uint64_t startx);
-}
-
Mainwindow::Mainwindow(InformationManager* mgr)
: manager(mgr)
- , logger(log4cxx::Logger::getLogger("Mainwindow")) {
+ , logger(log4cxx::Logger::getLogger("gui.Mainwindow")) {
openAction = new QAction(tr("&Open"), this);
+ loadAction = new QAction(tr("&Load"), 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()));
+ connect(openAction, &QAction::triggered,
+ this, &Mainwindow::open);
+ connect(loadAction, &QAction::triggered,
+ this, &Mainwindow::load);
+ connect(saveAction, &QAction::triggered,
+ this, &Mainwindow::save);
+ connect(exitAction, &QAction::triggered,
+ qApp, &QApplication::quit);
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
+ fileMenu->addAction(loadAction);
fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
- scripting = new ScriptingDock(tr("Scripting"), this);
- scripting->setAllowedAreas(Qt::BottomDockWidgetArea);
- addDockWidget(Qt::BottomDockWidgetArea, scripting);
+ QMenu* interpretermenu = menuBar()->addMenu(tr("&Interpreter"));
+
+ fdock = new FridaDock(tr("Frida Dock"), this);
+
+ fdock->addTab(new LogDock(fdock), "Log");
+
+ fdock->addTab(new ScriptingDock(manager->getInterpreter("GUILE"), fdock), "guile");
+ fdock->setAllowedAreas(Qt::BottomDockWidgetArea);
+ addDockWidget(Qt::BottomDockWidgetArea, fdock);
+ QAction* guileLoad = new QAction(tr("&GUILE"), this);
+ interpretermenu->addAction(guileLoad);
+ connect(guileLoad, &QAction::triggered,
+ [&]() {
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open Script"), "",
+ tr("Binaries") + " (*." +
+ manager->getInterpreter("GUILE")->fileExtension().c_str() + ")");
+ std::stringstream a, b;
+ std::string c;
+ manager->getInterpreter("GUILE")->loadFile(fileName.toStdString(), a, b, c);
+ });
listWidget = new QTreeWidget();
listWidget->setColumnCount(1);
+ listWidget->setDragDropMode(QAbstractItemView::InternalMove);
listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
connect(listWidget, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(showListContextMenu(const QPoint&)));
QTreeWidgetItem * external = new QTreeWidgetItem(listWidget, QStringList("External Functions"));
external->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
external->setBackground(0, QBrush(QColor(0xff, 0xdd, 0xdd)));
- mgr->connect_new_function_signal([&] (Function* fun) {addFunction(fun);});
- mgr->connect_new_dyn_symbol_signal([=] (const std::string& name) {
- auto item = new QTreeWidgetItem(external, QStringList(name.c_str()));
- item->setBackground(0, QBrush(QColor(0xff, 0xdd, 0xdd)));
+ mgr->registerNewFunctionEvent([=] (NewFunctionEvent* event) {
+ std::string name = event->function->getName();
+ if (event->function->isDynamic()) {
+ auto item = new QTreeWidgetItem(external, QStringList(name.c_str()));
+ item->setBackground(0, QBrush(QColor(0xff, 0xdd, 0xdd)));
+ } else {
+ addFunction(event->function);
+ }
+ });
+ mgr->registerRenameFunctionEvent([&](RenameFunctionEvent* event) {
+ if (objects_list_by_address.find(event->address) == objects_list_by_address.end())
+ return;
+ auto item = objects_list_by_address[event->address];
+ if (item) item->setText(0, event->new_name.c_str());
});
setGlobalHotkeys();
}
}
void Mainwindow::open() {
- QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
- tr("Binaries (*)"));
+ QFileDialog dialog(this, tr("Open bianry"), "", tr("Binaries (*)"));
+
+ if (dialog.exec()) {
+ QStringList files = dialog.selectedFiles();
+ if(1 != files.size()) {
+ LOG4CXX_ERROR(logger, "Needs exactly one file name")
+ } else {
+ manager->reset(files[0].toStdString());
+ }
+ }
+}
+
+void Mainwindow::load() {
+ QFileDialog dialog(this, tr("Open saved FrIDa file"), "", tr("Frida Archives (*.frida)"));
- manager->reset(fileName.toStdString());
+ if (dialog.exec()) {
+ QStringList files = dialog.selectedFiles();
+ if(1 != files.size()) {
+ LOG4CXX_ERROR(logger, "Needs exactly one file name")
+ } else {
+ manager->load(files[0].toStdString());
+ }
+ }
}
void Mainwindow::save() {
QString filename = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("Frida Archives (*.frida)"));
- manager->save(filename);
+ manager->save(filename.toStdString());
}
void Mainwindow::switchMainPlaneToAddress(uint64_t address) {
connect(act, &QAction::triggered, this, &Mainwindow::requestNewGroup);
if (item) {
- act = menu.addAction("Rename Function");
- connect(act, &QAction::triggered, [=]() {this->renameFunction(objects_list[item]->getFunction());});
+ if (objects_list.find(item) != objects_list.end()) {
+ act = menu.addAction("Rename Function");
+ connect(act, &QAction::triggered, [=]() {this->renameFunction(objects_list[item]->getFunction());});
+ } else {
+ act = menu.addAction("Rename Group");
+ connect(act, &QAction::triggered, [=]() {renameGroup(item);});
+ }
+
QMenu* submenu = menu.addMenu("Move to group");
LOG4CXX_DEBUG(logger, "renaming Function " << function->getName()
<< " to " << dialog.result().toStdString());
function->setName(dialog.result().toStdString());
- objects_list_by_address[function->getStartAddress()]->setText(0, dialog.result());
+ } else {
+ LOG4CXX_DEBUG(logger, "renameFunction aborted");
+ }
+}
+
+void Mainwindow::renameGroup(QTreeWidgetItem* item) {
+ SimpleStringDialog dialog("New name");
+ int result = dialog.exec();
+ if (QDialog::Accepted == result) {
+ LOG4CXX_DEBUG(logger, "renaming group " << item->text(0).toStdString()
+ << " to " << dialog.result().toStdString());
+ item->setText(0, dialog.result());
} else {
LOG4CXX_DEBUG(logger, "renameFunction aborted");
}
functions.insert(std::make_pair(fun->getStartAddress(), fun));
- FunctionWidget * w = new FunctionWidget(fun);
-
- // CFG
- CFGScene * scene = new CFGScene;
-
- BasicBlock * block = manager->getBasicBlock(fun->getStartAddress());
-
- uint64_t start_address(std::numeric_limits<uint64_t>::max());
- for (auto b : fun->blocks()) {
- if (b.first < start_address)
- start_address = b.first;
- }
-
- local__add_basic_block(block, this,
- manager, blocks, scene, start_address, 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");
+ FunctionWidget * w = new FunctionWidget(fun, this);
QTreeWidgetItem * item = new QTreeWidgetItem(listWidget, QStringList(fun->getName().c_str()));
stackedWidget->addWidget(w);
<< fun->getStartAddress());
objects_list_by_address.insert(std::make_pair(fun->getStartAddress(), item));
}
-
-namespace {
- BasicBlockWidget *
- local__add_basic_block(BasicBlock * block,
- Mainwindow * mainwindow, InformationManager * manager,
- std::map<uint64_t, BasicBlockWidget*>& 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())
- return old->second;
-
- std::stringstream s;
- s << "BLOCK_" << std::hex << block->getStartAddress()
- << "_" << block->getEndAddress();
- BasicBlockWidget * widget = new BasicBlockWidget(s.str().c_str(),
- block, mainwindow);
-
- known_blocks.insert(std::make_pair(block->getStartAddress(), widget));
-
- scene->addItem(widget);
- widget->setFlag(QGraphicsItem::ItemIsMovable, true);
- widget->moveBy(100*startx, block->getStartAddress() - starty);
-
- manager->getDisassembler()
- ->printEachInstruction(block->getStartAddress(),
- block->getEndAddress(),
- [&](uint8_t* bytes,
- size_t byte_count,
- const std::string& line,
- const std::string& ref) {
- widget->addItem(bytes, byte_count,
- line.c_str() + 1, // remove \t
- ref.c_str());
- });
-
- BasicBlockWidget *tmp, *nextl(NULL), *nextr(NULL);
- BasicBlock * tmpblock;
- if (block->getNextBlock(0) != 0) {
- int xshift = 0;
- if (block->getNextBlock(1) != 0)
- xshift = 1;
- tmpblock = manager->getBasicBlock(block->getNextBlock(0));
- tmp = local__add_basic_block(tmpblock, mainwindow, manager,
- known_blocks,
- scene, starty, startx+xshift);
- nextl = tmp;
- tmp->addPrevious(widget);
- }
- if (block->getNextBlock(1) != 0) {
- tmpblock = manager->getBasicBlock(block->getNextBlock(1));
- tmp = local__add_basic_block(tmpblock, mainwindow, manager,
- known_blocks,
- scene, starty, startx-1);
- nextr = tmp;
- tmp->addPrevious(widget);
- }
- widget->addNext(nextl, nextr);
- return widget;
- }
-}