X-Git-Url: https://git.siccegge.de//index.cgi?p=frida%2Ffrida.git;a=blobdiff_plain;f=src%2Fcore%2FInformationManager.cxx;h=604425e617499fa5155e3db8d84f40af49448824;hp=1234ac96aa64845775af2069a0bf73c901634d80;hb=HEAD;hpb=d5084161ca261d7fc0bd284621569440b6503eac diff --git a/src/core/InformationManager.cxx b/src/core/InformationManager.cxx index 1234ac9..604425e 100644 --- a/src/core/InformationManager.cxx +++ b/src/core/InformationManager.cxx @@ -1,33 +1,134 @@ #include "InformationManager.hxx" +#include "bindings/Interpreter.hxx" #include "disassembler/llvm/LLVMDisassembler.hxx" #include "core/Function.hxx" #include "core/BasicBlock.hxx" +#include "core/Comment.hxx" +#include "core/events/ChangeCommentEvent.hxx" -#include "gui/qt.hxx" +#include "qt.hxx" #include #include +#include + +InformationManager* current_information_manager; + +InformationManager::InformationManager() + : logger(log4cxx::Logger::getLogger("core.InformationManager")) +{ + current_information_manager = this; + qRegisterMetaType("NewFunctionEvent"); + + QPluginLoader* loader = new QPluginLoader("libguilePlugin", NULL); + if (!loader->load()) + LOG4CXX_ERROR(logger, "Loading plugin failed: " << loader->errorString().toStdString()); + interpreters["GUILE"] = qobject_cast(loader->instance()); + plugins.push_back(loader); +} + InformationManager::~InformationManager() { - for (BasicBlock * b : blocks) - delete b; + disassemblerThread.quit(); + for (auto b : blocks) + delete b.second; - for (Function * f : functions) - delete f; + for (auto f : functions) + delete f.second; + + for (auto i : plugins) + delete i; + disassemblerThread.wait(); } void InformationManager::reset(const std::string& filename) { + this->filename = filename; disassembler.reset(createLLVMDisassembler(filename, this)); - if (disassembler.get() != NULL) + if (disassembler.get() != NULL) { + emit resetEvent(); +#ifndef CONFIG_TEST + disassembler.get()->moveToThread(&disassemblerThread); + connect(&disassemblerThread, &QThread::started, + disassembler.get(), &Disassembler::start); + disassemblerThread.start(); +#else disassembler.get()->start(); +#endif + } +} + +void InformationManager::load(const std::string& filename) { + QuaZip zip(filename.c_str()); + QuaZipFile file(&zip); + QuaZipFileInfo info; + + if (!zip.open(QuaZip::mdUnzip)) { + LOG4CXX_ERROR(logger, "Failed to open archive " << filename); + return; + } + tmpfile.reset(new QTemporaryFile()); + + { + LOG4CXX_INFO(logger, "Loading binary from archive"); + zip.setCurrentFile("binary"); + tmpfile->open(); + file.open(QIODevice::ReadOnly); + QByteArray buffer; + while (!file.atEnd()) { + buffer = file.read(4096); + tmpfile->write(buffer); + } + tmpfile->flush(); + file.close(); + disassembler.reset(createLLVMDisassembler(tmpfile->fileName().toStdString(), this)); + } + + for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) { + zip.getCurrentFileInfo(&info); + file.open(QIODevice::ReadOnly); + + if(info.name != "binary") { + if (info.name.startsWith("comment:")) { + QXmlStreamReader reader(&file); + auto starttoken = reader.readNext(); + auto elementtoken = reader.readNext(); + assert(QXmlStreamReader::StartDocument == starttoken); + assert(QXmlStreamReader::StartElement == elementtoken); + Comment::deserialize(reader, this); + } else { + QXmlStreamReader reader(&file); + auto starttoken = reader.readNext(); + auto elementtoken = reader.readNext(); + assert(QXmlStreamReader::StartDocument == starttoken); + assert(QXmlStreamReader::StartElement == elementtoken); + Function::deserialize(reader, this); + } + } + file.close(); + } } -void InformationManager::save(const QString& filename) { - QuaZip zip(filename); +void InformationManager::save(const std::string& filename) { + QuaZip zip(filename.c_str()); zip.open(QuaZip::mdCreate); zip.setComment("FRIDA 0.0"); QuaZipFile outZipFile(&zip); - for (Function* fun : functions) { + { + QFile binary(this->filename.c_str()); + binary.open(QIODevice::ReadOnly); + QuaZipNewInfo zipinfo("binary"); + zipinfo.setPermissions(static_cast(0x6444)); + outZipFile.open(QIODevice::WriteOnly, zipinfo); + QByteArray buffer; + while (!binary.atEnd()) { + buffer = binary.read(4096); + outZipFile.write(buffer); + } + outZipFile.close(); + } + + for (auto funpair : functions) { + Function* fun = funpair.second; QuaZipNewInfo zipinfo(fun->getName().c_str()); zipinfo.setPermissions(static_cast(0x6444)); outZipFile.open(QIODevice::WriteOnly, zipinfo); @@ -35,33 +136,180 @@ void InformationManager::save(const QString& filename) { 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" + fun->serialize(stream); + stream.writeEndDocument(); outZipFile.close(); } + for (auto commentpair : comments) { + Comment* comment = commentpair.second; + if (!comment->isLocal()) { + QuaZipNewInfo zipinfo(QString("comment:%1").arg(comment->getAddress(), 0, 16)); + zipinfo.setPermissions(static_cast(0x6444)); + outZipFile.open(QIODevice::WriteOnly, zipinfo); + QXmlStreamWriter stream(&outZipFile); + stream.setAutoFormatting(true); + stream.setAutoFormattingIndent(-1); + stream.writeStartDocument(); + + comment->serialize(stream); + + stream.writeEndDocument(); + outZipFile.close(); + } + } zip.close(); } -void InformationManager::signal_new_function(Function* fun) { - functions.insert(fun); - for (auto b : fun->blocks()) - blocks.insert(b.second); - new_function_signal(fun); + +/* ******************************* + * Accessors for the Functions map + */ + +Function* InformationManager::getFunction(uint64_t address) { + auto it = functions.find(address); + if (it != functions.end()) + return it->second; + else + return NULL; +} + +std::map::const_iterator InformationManager::beginFunctions() { + return functions.begin(); +} +std::map::const_iterator InformationManager::endFunctions() { + return functions.end(); +} + + +/* ********************************* + * Accessors for the BasicBlocks map + */ + +BasicBlock* InformationManager::getBasicBlock(uint64_t address) { + auto it = blocks.find(address); + if (it != blocks.end()) + return it->second; + else + return NULL; +} + +std::map::const_iterator InformationManager::beginBasicBlocks() { + return blocks.begin(); +} +std::map::const_iterator InformationManager::endBasicBlocks() { + return blocks.end(); +} + +/* ********************************* + * Accessors for the Comments map + */ +std::pair< + std::multimap::const_iterator, + std::multimap::const_iterator> +InformationManager::getComments(uint64_t address) { + return comments.equal_range(address); +} + +std::multimap::const_iterator InformationManager::beginComments() { + return comments.begin(); +} +std::multimap::const_iterator InformationManager::endComments() { + return comments.end(); +} + +/* ********************************* + * Accessors for the Interpreter map + */ + +Interpreter* InformationManager::getInterpreter(const std::string& name) { + auto it = interpreters.find(name); + if (it != interpreters.end()) + return it->second; + else + return NULL; +} + +std::map::const_iterator InformationManager::beginInterpreters() { + return interpreters.begin(); +} +std::map::const_iterator InformationManager::endInterpreters() { + return interpreters.end(); +} + + +/* ******************************** + * Factory methods for data classes + */ + +Function* InformationManager::newFunction(uint64_t address) { + Function* fun = new Function(address, false, this); + functions.insert(std::make_pair(address, fun)); + return fun; +} + +Function* InformationManager::newDynamicFunction(uint64_t address) { + Function* fun = new Function(address, true, this); + functions.insert(std::make_pair(address, fun)); + return fun; +} + +BasicBlock* InformationManager::newBasicBlock(uint64_t address) { + BasicBlock* block = new BasicBlock(address, this); + blocks.insert(std::make_pair(address, block)); + return block; +} + +Comment* InformationManager::newGlobalComment(uint64_t address) { + Comment* comment = new Comment(address, this); + comments.insert(std::make_pair(address, comment)); + return comment; +} + +Comment* InformationManager::newLocalComment(uint64_t address, Function* f) { + Comment* comment = new Comment(address, f, this); + comments.insert(std::make_pair(address, comment)); + return comment; +} + +void InformationManager::finishFunction(Function* fun) { + LOG4CXX_DEBUG(logger, "Finishing function " << fun->getName()); + for (auto b : fun->blocks()) { + BasicBlock* bl = b.second; + blocks.insert(std::make_pair(bl->getStartAddress(), bl)); + } + NewFunctionEvent event(fun->getStartAddress(), fun); + emit newFunctionEvent(event); +} + +void InformationManager::finishBasicBlock(BasicBlock*) { +} + +void InformationManager::finishComment(Comment* c) { + LOG4CXX_DEBUG(logger, "Finishing comment " << c->getAddress()); + ChangeCommentEvent event(c->getAddress(), c->getLocation(), c); + emit changeCommentEvent(&event); +} + +void InformationManager::deleteFunction(Function* f) { + functions.erase(f->getStartAddress()); + delete f; +} + +void InformationManager::deleteBasicBlock(BasicBlock* b) { + blocks.erase(b->getStartAddress()); + delete b; +} + +void InformationManager::deleteComment(Comment* c) { + auto range = comments.equal_range(c->getAddress()); + for (auto it = range.first; it != range.second; ++it) { + if (it->second == c) { + comments.erase(it); + break; + } + } + delete c; }