#include "InformationManager.hxx"
#include "disassembler/llvm/LLVMDisassembler.hxx"
+#include "gui/qt.hxx"
+#include "quazip/quazip.h"
+#include "quazip/quazipfile.h"
void InformationManager::reset(const std::string& filename) {
disassembler.reset(createLLVMDisassembler(filename, this));
if (disassembler.get() != NULL)
disassembler.get()->start();
}
+
+void InformationManager::save(const QString& filename) {
+ QuaZip zip(filename);
+ zip.open(QuaZip::mdCreate);
+ zip.setComment("FRIDA 0.0");
+ QuaZipFile outZipFile(&zip);
+
+ for (Function* fun : functions) {
+ QuaZipNewInfo zipinfo(fun->getName().c_str());
+ zipinfo.setPermissions(static_cast<QFile::Permissions>(0x6444));
+ outZipFile.open(QIODevice::WriteOnly, zipinfo);
+ QXmlStreamWriter stream(&outZipFile);
+ stream.setAutoFormatting(true);
+ stream.setAutoFormattingIndent(-1);
+ stream.writeStartDocument();
+ stream.writeStartElement("function");
+ stream.writeAttribute("name", fun->getName().c_str());
+ stream.writeAttribute("entry", QString::number(fun->getStartAddress(), 16));
+
+ for (auto& blockentry : fun->blocks()) {
+ stream.writeStartElement("block");
+ stream.writeAttribute("id", blockentry.second->getName().c_str());
+ stream.writeTextElement("start", QString::number(blockentry.second->getStartAddress(), 16));
+ stream.writeTextElement("end", QString::number(blockentry.second->getEndAddress(), 16));
+ if (0 != blockentry.second->getNextBlock(0))
+ stream.writeTextElement("next", QString::number(blockentry.second->getNextBlock(0), 16));
+ if (0 != blockentry.second->getNextBlock(1))
+ stream.writeTextElement("next", QString::number(blockentry.second->getNextBlock(1), 16));
+ stream.writeEndElement(); // "block"
+ }
+
+ stream.writeEndElement(); // "function"
+ stream.writeEndDocument();
+ outZipFile.close();
+ }
+
+ zip.close();
+}
#include <boost/signals2.hpp>
#include <functional>
#include <string>
+#include <set>
class Disassembler;
class Function;
+class QString;
+
class InformationManager {
public:
- boost::signals2::connection
- connect_new_function_signal(std::function<void(Function*)> f) {
- return new_function_signal.connect(f);
- }
-
- void signal_new_function(Function* f) {
- new_function_signal(f);
- }
+ void reset(const std::string& filename);
+ void save(const QString& filename);
boost::signals2::connection
- connect_new_dyn_symbol_signal(std::function<void(const std::string& name)> f) {
- return new_dyn_symbol_signal.connect(f);
- }
+ connect_new_function_signal(std::function<void(Function*)> f)
+ { return new_function_signal.connect(f); }
- void signal_new_dyn_symbol(const std::string& f) {
- new_dyn_symbol_signal(f);
- }
+ void signal_new_function(Function* f)
+ { functions.insert(f); new_function_signal(f); }
boost::signals2::connection
- connect_reset_signal(std::function<void ()> f) {
- return reset_signal.connect(f);
- }
+ connect_new_dyn_symbol_signal(std::function<void(const std::string& name)> f)
+ { return new_dyn_symbol_signal.connect(f); }
- // boost::signals2::connection
- // connect_information_added_signal(uint64_t begin, uint64_t end,
- // std::function<void (uint64_t)>) {
+ void signal_new_dyn_symbol(const std::string& f)
+ { new_dyn_symbol_signal(f); }
- // }
-
- Disassembler* getDisassembler() {
- return disassembler.get();
- }
+ boost::signals2::connection
+ connect_reset_signal(std::function<void ()> f)
+ { return reset_signal.connect(f); }
- void reset(const std::string& filename);
+ Disassembler* getDisassembler()
+ { return disassembler.get(); }
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;
std::unique_ptr<Disassembler> disassembler;
+ std::set<Function*> functions;
};
#endif /* INCLUDE__InformationManager_hxx */
#define INCLUDE__BasicBlock_hxx
#include <cassert>
+#include <string>
+#include <sstream>
class BasicBlock {
public:
end_address = address;
}
+ std::string getName() {
+ std::stringstream s;
+ s << "BLOCK_" << std::hex << start_address << '_' << end_address;
+ return s.str();
+ }
+
private:
uint64_t start_address;
uint64_t end_address;
: manager(mgr)
, logger(log4cxx::Logger::getLogger("Mainwindow")) {
openAction = new QAction(tr("&Open"), this);
- // saveAction = new QAction(tr("&Save"), 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(saveAction, SIGNAL(triggered()),
+ this, SLOT(save()));
connect(exitAction, SIGNAL(triggered()),
qApp, SLOT(quit()));
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
- // fileMenu->addAction(saveAction);
+ fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
manager->reset(fileName.toStdString());
}
+void Mainwindow::save() {
+ QString filename = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("Frida Archives (*.frida)"));
+ manager->save(filename);
+}
+
void Mainwindow::switchMainPlaneToAddress(uint64_t address) {
if (objects_list_by_address.find(address) != objects_list_by_address.end()) {
LOG4CXX_DEBUG(logger, "Switching to function " << std::hex << address);
QAction *exitAction;
QAction *openAction;
+ QAction *saveAction;
std::map<uint64_t, BasicBlockWidget*> blocks;
std::map<QListWidgetItem*, QWidget*> objects_list;
private Q_SLOTS:
void quit();
void open();
+ void save();
void switchMainPlane(int);
void showListContextMenu(const QPoint&);
void requestNewFunction();
#include <QtGui>
#include <QMenu>
#include <QShortcut>
+#include <QXmlStreamWriter>
+#include <QXmlStreamReader>
#endif /* INCLUDE__qt_hxx_ */