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