SET(frida_SOURCES
src/core/InformationManager.cxx
src/core/BasicBlock.cxx
+ src/core/Comment.cxx
src/core/Function.cxx
src/gui/Mainwindow.cxx
src/gui/widgets/BasicBlockWidget.cxx
%include <stdint.i>
%include <std_string.i>
%include <std_map.i>
+%include <stl.i>
+
+ // noone knows how to get these working
+%ignore beginFunctions();
+%ignore endFunctions();
+%ignore beginBasicBlocks();
+%ignore endBasicBlocks();
%{
#include "core/Function.hxx"
%}
namespace std {
- %template(map_uint64t_BasicBlock) map<unsigned long long, BasicBlock*>;
+ %template(BasicBlockMap) map<unsigned long, BasicBlock*>;
+ %template(FunctionMap) map<unsigned long, Function*>;
+ %template(InterpreterMap) map<std::string, Interpreter*>;
}
%inline %{
#include <string>
class Function;
+class InformationManager;
class Comment {
public:
bool isLocal() const {return location == NULL;}
+ void setText(const std::string& text);
+ uint64_t getAddress();
private:
- Comment(uint64_t address);
- Comment(uint64_t address, Function* location);
+ Comment(uint64_t address, InformationManager* manager);
+ Comment(uint64_t address, Function* location, InformationManager* manager);
uint64_t address;
Function* location;
+ InformationManager* manager;
std::string text;
+
+ friend class InformationManager;
};
#endif /* INCLUDE__Comment_hxx */
#include "InformationManager.hxx"
#include "gui/qt.hxx"
-Function::Function(uint64_t start_address, InformationManager* manager)
+Function::Function(uint64_t start_address, bool dynamic, InformationManager* manager)
: start_address(start_address)
+ , dynamic(dynamic)
, manager(manager) {}
class Function {
public:
- uint64_t getStartAddress() const {
- return start_address;
- }
+ uint64_t getStartAddress() const { return start_address; }
- std::string getName() const
- { return name; }
+ std::string getName() const { return name; }
void setName(const std::string& new_name);
- InformationManager* getManager() const {
- return manager;
- }
+ InformationManager* getManager() const { return manager; }
+
+ bool isDynamic() const { return dynamic; }
void addBasicBlock(BasicBlock* block) {
_blocks.insert(std::make_pair(block->getStartAddress(), block));
static Function* deserialize(QXmlStreamReader& stream, InformationManager* manager);
private:
- Function(uint64_t start_address, InformationManager* manager);
+ Function(uint64_t start_address, bool dynamic, InformationManager* manager);
std::string name;
uint64_t start_address;
+ bool dynamic;
InformationManager * manager;
std::map<uint64_t, BasicBlock*> _blocks;
#include "core/Function.hxx"
#include "core/BasicBlock.hxx"
#include "core/Comment.hxx"
+#include "core/events/NewFunctionEvent.hxx"
#include "gui/qt.hxx"
#include <quazip/quazip.h>
zip.close();
}
-void InformationManager::signal_new_function(Function* fun) {
-}
-
-
/* *******************************
* Accessors for the Functions map
*/
Function* InformationManager::newFunction(uint64_t address) {
- Function* fun = new Function(address, this);
+ 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;
}
}
Comment* InformationManager::newGlobalComment(uint64_t address) {
- return NULL;
+ Comment* comment = new Comment(address, this);
+ comments.insert(std::make_pair(address, comment));
+ return comment;
}
Comment* InformationManager::newLocalComment(uint64_t address, Function* f) {
- return NULL;
+ Comment* comment = new Comment(address, this);
+ comments.insert(std::make_pair(address, comment));
+ return comment;
}
void InformationManager::finishFunction(Function* fun) {
BasicBlock* bl = b.second;
blocks.insert(std::make_pair(bl->getStartAddress(), bl));
}
- new_function_signal(fun);
+ NewFunctionEvent event(fun->getStartAddress(), fun);
+ dispatch(&event);
}
-void InformationManager::finishBasicBlock(BasicBlock* b) {
+void InformationManager::finishBasicBlock(BasicBlock*) {
}
void InformationManager::finnishComment(Comment* c) {
}
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;
}
class Comment;
class RenameFunctionEvent;
+class NewFunctionEvent;
+class ChangeCommentEvent;
class QString;
class QTemporaryFile;
class QPluginLoader;
+using boost::signals2::connection;
+
class InformationManager {
public:
InformationManager();
void load(const std::string& filename);
void save(const std::string& filename);
- void signal_new_function(Function* f);
- void signal_new_dyn_symbol(const std::string& f)
- { new_dyn_symbol_signal(f); }
-
- boost::signals2::connection
- connect_new_function_signal(std::function<void(Function*)> f)
- { return new_function_signal.connect(f); }
-
- boost::signals2::connection
- connect_new_dyn_symbol_signal(std::function<void(const std::string& name)> f)
- { return new_dyn_symbol_signal.connect(f); }
-
- boost::signals2::connection
- connect_reset_signal(std::function<void ()> f)
- { return reset_signal.connect(f); }
-
- boost::signals2::connection
- connect_rename_function_signal(std::function<void (RenameFunctionEvent*)> f)
- { return rename_function_signal.connect(f); }
-
Disassembler* getDisassembler()
{ return disassembler.get(); }
+ // Rename Function
+ typedef std::function<void (RenameFunctionEvent*)> RenameFunctionHandler;
+ connection registerRenameFunctionEvent(RenameFunctionHandler h)
+ { return renameFunctionSignal.connect(h); }
void dispatch(RenameFunctionEvent* event)
- { rename_function_signal(event); }
-
+ { renameFunctionSignal(event); }
+
+ // New Function
+ typedef std::function<void (NewFunctionEvent*)> NewFunctionHandler;
+ connection registerNewFunctionEvent(NewFunctionHandler h)
+ { return newFunctionSignal.connect(h); }
+ void dispatch(NewFunctionEvent* event)
+ { newFunctionSignal(event); }
+
+ // Change Comment
+ typedef std::function<void (ChangeCommentEvent*)> ChangeCommentHandler;
+ connection registerChangeCommentEvent(ChangeCommentHandler h)
+ { return changeCommentSignal.connect(h); }
+ void dispatch(ChangeCommentEvent* event)
+ { changeCommentSignal(event); }
+
+ connection connect_reset_signal(std::function<void ()> f)
+ { return reset_signal.connect(f); }
Function* getFunction(uint64_t address);
bool hasFunctions() const {return functions.size() != 0;}
std::map<uint64_t, BasicBlock*>::const_iterator beginBasicBlocks();
std::map<uint64_t, BasicBlock*>::const_iterator endBasicBlocks();
-
Interpreter* getInterpreter(const std::string& name);
bool hasInterpreters() const {return interpreters.size() != 0;}
std::map<std::string, Interpreter*>::const_iterator beginInterpreters();
* thingsmay happen.
*/
Function* newFunction(uint64_t address);
+ Function* newDynamicFunction(uint64_t address);
BasicBlock* newBasicBlock(uint64_t address);
Comment* newGlobalComment(uint64_t address);
Comment* newLocalComment(uint64_t address, Function* f);
void deleteComment(Comment* c);
private:
+ boost::signals2::signal<void (RenameFunctionEvent*)> renameFunctionSignal;
+ boost::signals2::signal<void (NewFunctionEvent*)> newFunctionSignal;
+ boost::signals2::signal<void (ChangeCommentEvent*)> changeCommentSignal;
+
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;
- boost::signals2::signal<void (RenameFunctionEvent*)> rename_function_signal;
+
std::unique_ptr<Disassembler> disassembler;
+
std::map<std::string, Interpreter*> interpreters;
std::map<uint64_t, Function*> functions;
std::map<uint64_t, BasicBlock*> blocks;
+ std::multimap<uint64_t, Comment*> comments;
+
std::string filename;
std::unique_ptr<QTemporaryFile> tmpfile;
std::vector<QPluginLoader*> plugins;
// TODO: Error handling
std::string symbolname = *(elffile->getSymbolName(it));
std::string symbolversion = *(elffile->getSymbolVersion(nullptr, &*it, is_default));
- manager->signal_new_dyn_symbol(symbolname + (is_default? "@@" : "@") + symbolversion);
+ // TODO: actually get the symbol address from relocations
+ Function* f = manager->newDynamicFunction(0);
+ f->setName(symbolname + (is_default? "@@" : "@") + symbolversion);
+ manager->finishFunction(f);
+
LOG4CXX_DEBUG(logger, "Adding dynamic Symbol " << symbolname << (is_default? "@@" : "@") << symbolversion);
}
}
#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"
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->connect_rename_function_signal([&](RenameFunctionEvent* event) {
+ 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];
, logger(log4cxx::Logger::getLogger("gui.BasicBlockWidget." + name.toStdString())) {
next[0] = NULL; next[1] = NULL;
- block->getManager()->connect_rename_function_signal([=](RenameFunctionEvent* event) {updateFunctionName(event);});
+ block->getManager()->registerRenameFunctionEvent([=](RenameFunctionEvent* event) {updateFunctionName(event);});
_widget.reset(new CustomQGraphicsTextItem("", this));
_widget->setPos(5, 20);