6179f5f1ff2d83c5287ed07f629674907da15139
[frida/frida.git] / src / core / InformationManager.cxx
1 #include "InformationManager.hxx"
2 #include "bindings/Interpreter.hxx"
3 #include "disassembler/llvm/LLVMDisassembler.hxx"
4 #include "core/Function.hxx"
5 #include "core/BasicBlock.hxx"
6 #include "core/Comment.hxx"
7 #include "core/events/NewFunctionEvent.hxx"
8 #include "core/events/ChangeCommentEvent.hxx"
9
10 #include "gui/qt.hxx"
11 #include <quazip/quazip.h>
12 #include <quazip/quazipfile.h>
13
14 #include <QTemporaryFile>
15
16 InformationManager* current_information_manager;
17
18 InformationManager::InformationManager()
19 : logger(log4cxx::Logger::getLogger("core.InformationManager"))
20 {
21 current_information_manager = this;
22
23 QPluginLoader* loader = new QPluginLoader("libguilePlugin", NULL);
24 if (!loader->load())
25 LOG4CXX_ERROR(logger, "Loading plugin failed: " << loader->errorString().toStdString());
26 interpreters["GUILE"] = qobject_cast<Interpreter*>(loader->instance());
27 plugins.push_back(loader);
28 }
29
30 InformationManager::~InformationManager() {
31 for (auto b : blocks)
32 delete b.second;
33
34 for (auto f : functions)
35 delete f.second;
36
37 for (auto i : plugins)
38 delete i;
39 }
40
41 void InformationManager::reset(const std::string& filename) {
42 this->filename = filename;
43 disassembler.reset(createLLVMDisassembler(filename, this));
44 if (disassembler.get() != NULL)
45 disassembler.get()->start();
46 }
47
48 void InformationManager::load(const std::string& filename) {
49 QuaZip zip(filename.c_str());
50 QuaZipFile file(&zip);
51 QuaZipFileInfo info;
52
53 zip.open(QuaZip::mdUnzip);
54 tmpfile.reset(new QTemporaryFile());
55
56 {
57 LOG4CXX_INFO(logger, "Loading binary from archive");
58 zip.setCurrentFile("binary");
59 tmpfile->open();
60 file.open(QIODevice::ReadOnly);
61 QByteArray buffer;
62 while (!file.atEnd()) {
63 buffer = file.read(4096);
64 tmpfile->write(buffer);
65 }
66 tmpfile->flush();
67 file.close();
68 disassembler.reset(createLLVMDisassembler(tmpfile->fileName().toStdString(), this));
69 }
70
71 for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) {
72 zip.getCurrentFileInfo(&info);
73 file.open(QIODevice::ReadOnly);
74
75 if(info.name != "binary") {
76 QXmlStreamReader reader(&file);
77 assert(QXmlStreamReader::StartDocument == reader.readNext());
78 assert(QXmlStreamReader::StartElement == reader.readNext());
79 Function::deserialize(reader, this);
80 }
81 file.close();
82 }
83 }
84
85 void InformationManager::save(const std::string& filename) {
86 QuaZip zip(filename.c_str());
87 zip.open(QuaZip::mdCreate);
88 zip.setComment("FRIDA 0.0");
89 QuaZipFile outZipFile(&zip);
90
91 {
92 QFile binary(this->filename.c_str());
93 binary.open(QIODevice::ReadOnly);
94 QuaZipNewInfo zipinfo("binary");
95 zipinfo.setPermissions(static_cast<QFile::Permissions>(0x6444));
96 outZipFile.open(QIODevice::WriteOnly, zipinfo);
97 QByteArray buffer;
98 while (!binary.atEnd()) {
99 buffer = binary.read(4096);
100 outZipFile.write(buffer);
101 }
102 outZipFile.close();
103 }
104
105 for (auto funpair : functions) {
106 Function* fun = funpair.second;
107 QuaZipNewInfo zipinfo(fun->getName().c_str());
108 zipinfo.setPermissions(static_cast<QFile::Permissions>(0x6444));
109 outZipFile.open(QIODevice::WriteOnly, zipinfo);
110 QXmlStreamWriter stream(&outZipFile);
111 stream.setAutoFormatting(true);
112 stream.setAutoFormattingIndent(-1);
113 stream.writeStartDocument();
114
115 fun->serialize(stream);
116
117 stream.writeEndDocument();
118 outZipFile.close();
119 }
120
121 zip.close();
122 }
123
124
125 /* *******************************
126 * Accessors for the Functions map
127 */
128
129 Function* InformationManager::getFunction(uint64_t address) {
130 auto it = functions.find(address);
131 if (it != functions.end())
132 return it->second;
133 else
134 return NULL;
135 }
136
137 std::map<uint64_t, Function*>::const_iterator InformationManager::beginFunctions() {
138 return functions.begin();
139 }
140 std::map<uint64_t, Function*>::const_iterator InformationManager::endFunctions() {
141 return functions.end();
142 }
143
144
145 /* *********************************
146 * Accessors for the BasicBlocks map
147 */
148
149 BasicBlock* InformationManager::getBasicBlock(uint64_t address) {
150 auto it = blocks.find(address);
151 if (it != blocks.end())
152 return it->second;
153 else
154 return NULL;
155 }
156
157 std::map<uint64_t, BasicBlock*>::const_iterator InformationManager::beginBasicBlocks() {
158 return blocks.begin();
159 }
160 std::map<uint64_t, BasicBlock*>::const_iterator InformationManager::endBasicBlocks() {
161 return blocks.end();
162 }
163
164 /* *********************************
165 * Accessors for the Comments map
166 */
167 std::pair<
168 std::multimap<uint64_t, Comment*>::const_iterator,
169 std::multimap<uint64_t, Comment*>::const_iterator>
170 InformationManager::getComments(uint64_t address) {
171 return comments.equal_range(address);
172 }
173
174 std::multimap<uint64_t, Comment*>::const_iterator InformationManager::beginComments() {
175 return comments.begin();
176 }
177 std::multimap<uint64_t, Comment*>::const_iterator InformationManager::endComments() {
178 return comments.end();
179 }
180
181 /* *********************************
182 * Accessors for the Interpreter map
183 */
184
185 Interpreter* InformationManager::getInterpreter(const std::string& name) {
186 auto it = interpreters.find(name);
187 if (it != interpreters.end())
188 return it->second;
189 else
190 return NULL;
191 }
192
193 std::map<std::string, Interpreter*>::const_iterator InformationManager::beginInterpreters() {
194 return interpreters.begin();
195 }
196 std::map<std::string, Interpreter*>::const_iterator InformationManager::endInterpreters() {
197 return interpreters.end();
198 }
199
200
201 /* ********************************
202 * Factory methods for data classes
203 */
204
205 Function* InformationManager::newFunction(uint64_t address) {
206 Function* fun = new Function(address, false, this);
207 functions.insert(std::make_pair(address, fun));
208 return fun;
209 }
210
211 Function* InformationManager::newDynamicFunction(uint64_t address) {
212 Function* fun = new Function(address, true, this);
213 functions.insert(std::make_pair(address, fun));
214 return fun;
215 }
216
217 BasicBlock* InformationManager::newBasicBlock(uint64_t address) {
218 BasicBlock* block = new BasicBlock(address, this);
219 blocks.insert(std::make_pair(address, block));
220 return block;
221 }
222
223 Comment* InformationManager::newGlobalComment(uint64_t address) {
224 Comment* comment = new Comment(address, this);
225 comments.insert(std::make_pair(address, comment));
226 return comment;
227 }
228
229 Comment* InformationManager::newLocalComment(uint64_t address, Function* f) {
230 Comment* comment = new Comment(address, f, this);
231 comments.insert(std::make_pair(address, comment));
232 return comment;
233 }
234
235 void InformationManager::finishFunction(Function* fun) {
236 LOG4CXX_DEBUG(logger, "Finishing function " << fun->getName());
237 for (auto b : fun->blocks()) {
238 BasicBlock* bl = b.second;
239 blocks.insert(std::make_pair(bl->getStartAddress(), bl));
240 }
241 NewFunctionEvent event(fun->getStartAddress(), fun);
242 dispatch(&event);
243 }
244
245 void InformationManager::finishBasicBlock(BasicBlock*) {
246 }
247
248 void InformationManager::finishComment(Comment* c) {
249 LOG4CXX_DEBUG(logger, "Finishing comment " << c->getAddress());
250 ChangeCommentEvent event(c->getAddress(), c->getLocation(), c);
251 dispatch(&event);
252 }
253
254 void InformationManager::deleteFunction(Function* f) {
255 functions.erase(f->getStartAddress());
256 delete f;
257 }
258
259 void InformationManager::deleteBasicBlock(BasicBlock* b) {
260 blocks.erase(b->getStartAddress());
261 delete b;
262 }
263
264 void InformationManager::deleteComment(Comment* c) {
265 auto range = comments.equal_range(c->getAddress());
266 for (auto it = range.first; it != range.second; ++it) {
267 if (it->second == c) {
268 comments.erase(it);
269 break;
270 }
271 }
272 delete c;
273 }