-
Notifications
You must be signed in to change notification settings - Fork 96
/
Copy pathR2GhidraCmdDecompiler.cpp
83 lines (76 loc) · 2.52 KB
/
R2GhidraCmdDecompiler.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "R2GhidraCmdDecompiler.h"
#include "Iaito.h"
#include <QJsonObject>
#include <QJsonArray>
/*
RCodeMeta *Decompiler::makeWarning(QString warningMessage){
std::string temporary = warningMessage.toStdString();
return r_codemeta_new(temporary.c_str());
}
*/
R2GhidraCmdDecompiler::R2GhidraCmdDecompiler(QObject *parent)
: Decompiler("pdg", "pdg", parent)
{
task = nullptr;
this->cache = new QHash<QString, RCodeMeta*>();
}
bool R2GhidraCmdDecompiler::isAvailable()
{
return Core()->cmdList("e cmd.pdc=?").contains(QStringLiteral("pdg"));
}
void R2GhidraCmdDecompiler::decompileAt(RVA addr)
{
if (task) {
return;
}
QString k = QString::number(addr);
bool is_cached = this->cache->contains (k);
task = new R2Task(is_cached? "?e": "pdgj @ " + k);
connect(task, &R2Task::finished, this, [this, addr, k, is_cached]() {
if (is_cached) {
RCodeMeta *code = r_codemeta_clone (this->cache->value(k));
delete task;
emit finished(code);
return;
}
QJsonObject json = task->getResultJson().object();
delete task;
task = nullptr;
if (json.isEmpty()) {
emit finished(Decompiler::makeWarning(tr("Failed to parse JSON from r2ghidra")));
return;
}
RCodeMeta *code = r_codemeta_new (nullptr);
QString codeString = json["code"].toString();
QJsonArray linesArray = json["annotations"].toArray();
for (const QJsonValueRef line : linesArray) {
QJsonObject lineObject = line.toObject();
if (lineObject.isEmpty()) {
continue;
}
if (lineObject["type"].toString() != "offset") {
continue;
}
RCodeMetaItem *mi = r_codemeta_item_new ();
mi->start = lineObject["start"].toInt();
mi->end = lineObject["end"].toInt();
bool ok;
mi->type = R_CODEMETA_TYPE_OFFSET;
mi->offset.offset = lineObject["offset"].toVariant().toULongLong(&ok);
r_codemeta_add_item (code, mi);
}
for (const auto line : json["errors"].toArray()) {
if (!line.isString()) {
continue;
}
codeString.append(line.toString() + "\n");
}
std::string tmp = codeString.toStdString();
code->code = strdup(tmp.c_str());
if (!is_cached) {
this->cache->insert(k, r_codemeta_clone (code));
}
emit finished(code);
});
task->startTask();
}