Remove JSDec as decompiler and use rizin C api

This commit is contained in:
wargio 2024-02-24 19:47:29 +08:00 committed by Giovanni
parent c20d2c61d6
commit 2106551d00
8 changed files with 21 additions and 156 deletions

View File

@ -120,10 +120,6 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
Config()->setOutputRedirectionEnabled(clOptions.outputRedirectionEnabled);
if (JSDecDecompiler::isAvailable()) {
Core()->registerDecompiler(new JSDecDecompiler(Core()));
}
#if CUTTER_RZGHIDRA_STATIC
Core()->registerDecompiler(new RzGhidraDecompiler(Core()));
#endif

View File

@ -10,107 +10,8 @@ Decompiler::Decompiler(const QString &id, const QString &name, QObject *parent)
{
}
static char *jsonToStrdup(const CutterJson &str)
{
const RzJson *j = str.lowLevelValue();
if (!j || j->type != RZ_JSON_STRING) {
return NULL;
}
return rz_str_dup(j->str_value);
}
static RzAnnotatedCode *parseJsonCode(CutterJson &json)
{
char *raw_code = jsonToStrdup(json["code"]);
if (!raw_code) {
return NULL;
}
RzAnnotatedCode *code = rz_annotated_code_new(raw_code);
if (!code) {
return NULL;
}
for (const auto &jsonAnnotation : json["annotations"]) {
RzCodeAnnotation annotation = {};
annotation.start = jsonAnnotation["start"].toUt64();
annotation.end = jsonAnnotation["end"].toUt64();
QString type = jsonAnnotation["type"].toString();
if (type == "offset") {
annotation.type = RZ_CODE_ANNOTATION_TYPE_OFFSET;
annotation.offset.offset = jsonAnnotation["offset"].toString().toULongLong();
} else if (type == "function_name") {
annotation.type = RZ_CODE_ANNOTATION_TYPE_FUNCTION_NAME;
annotation.reference.name = jsonToStrdup(jsonAnnotation["name"]);
annotation.reference.offset = jsonAnnotation["offset"].toString().toULongLong();
} else if (type == "global_variable") {
annotation.type = RZ_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE;
annotation.reference.offset = jsonAnnotation["offset"].toString().toULongLong();
} else if (type == "constant_variable") {
annotation.type = RZ_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE;
annotation.reference.offset = jsonAnnotation["offset"].toString().toULongLong();
} else if (type == "local_variable") {
annotation.type = RZ_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE;
annotation.variable.name = jsonToStrdup(jsonAnnotation["name"]);
} else if (type == "function_parameter") {
annotation.type = RZ_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER;
annotation.variable.name = jsonToStrdup(jsonAnnotation["name"]);
} else if (type == "syntax_highlight") {
annotation.type = RZ_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT;
QString highlightType = jsonAnnotation["syntax_highlight"].toString();
if (highlightType == "keyword") {
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_KEYWORD;
} else if (highlightType == "comment") {
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_COMMENT;
} else if (highlightType == "datatype") {
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_DATATYPE;
} else if (highlightType == "function_name") {
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_NAME;
} else if (highlightType == "function_parameter") {
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_PARAMETER;
} else if (highlightType == "local_variable") {
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_LOCAL_VARIABLE;
} else if (highlightType == "constant_variable") {
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_CONSTANT_VARIABLE;
} else if (highlightType == "global_variable") {
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_GLOBAL_VARIABLE;
}
}
rz_annotated_code_add_annotation(code, &annotation);
}
return code;
}
RzAnnotatedCode *Decompiler::makeWarning(QString warningMessage)
{
std::string temporary = warningMessage.toStdString();
return rz_annotated_code_new(strdup(temporary.c_str()));
}
JSDecDecompiler::JSDecDecompiler(QObject *parent) : Decompiler("jsdec", "jsdec", parent)
{
task = nullptr;
}
bool JSDecDecompiler::isAvailable()
{
return Core()->getConfigVariableSpaces().contains("jsdec");
}
void JSDecDecompiler::decompileAt(RVA addr)
{
if (task) {
return;
}
task = new RizinCmdTask("pddA @ " + QString::number(addr));
connect(task, &RizinCmdTask::finished, this, [this]() {
CutterJson json = task->getResultJson();
delete task;
task = nullptr;
if (!json.size()) {
emit finished(Decompiler::makeWarning(tr("Failed to parse JSON from jsdec")));
return;
}
RzAnnotatedCode *code = parseJsonCode(json);
emit finished(code);
});
task->startTask();
}

View File

@ -37,20 +37,4 @@ signals:
void finished(RzAnnotatedCode *codeDecompiled);
};
class JSDecDecompiler : public Decompiler
{
Q_OBJECT
private:
RizinCmdTask *task;
public:
explicit JSDecDecompiler(QObject *parent = nullptr);
void decompileAt(RVA addr) override;
bool isRunning() override { return task != nullptr; }
static bool isAvailable();
};
#endif // DECOMPILER_H

View File

@ -62,7 +62,7 @@ CutterJson RizinCmdTask::getResultJson()
}
char *copy = static_cast<char *>(rz_mem_alloc(strlen(res) + 1));
strcpy(copy, res);
return Core()->parseJson(copy, nullptr);
return Core()->parseJson("task", copy, nullptr);
}
const char *RizinCmdTask::getResultRaw()

View File

@ -273,6 +273,7 @@ void CutterCore::loadCutterRC()
}
qInfo() << tr("Loading initialization file from ") << cutterRCFilePath;
rz_core_cmd_file(core, cutterRCFilePath.toUtf8().constData());
rz_cons_flush();
}
}
@ -286,6 +287,7 @@ void CutterCore::loadDefaultCutterRC()
}
qInfo() << tr("Loading initialization file from ") << cutterRCFilePath;
rz_core_cmd_file(core, cutterRCFilePath.toUtf8().constData());
rz_cons_flush();
}
QList<QString> CutterCore::sdbList(QString path)
@ -473,19 +475,7 @@ QString CutterCore::cmdRaw(const char *cmd)
{
QString res;
CORE_LOCK();
rz_cons_push();
// rz_core_cmd does not return the output of the command
rz_core_cmd(core, cmd, 0);
// we grab the output straight from rz_cons
res = rz_cons_get_buffer();
// cleaning up
rz_cons_pop();
rz_cons_echo(NULL);
return res;
return rz_core_cmd_str(core, cmd);
}
CutterJson CutterCore::cmdj(const char *str)
@ -496,7 +486,7 @@ CutterJson CutterCore::cmdj(const char *str)
res = rz_core_cmd_str(core, str);
}
return parseJson(res, str);
return parseJson("cmdj", res, str);
}
QString CutterCore::cmdTask(const QString &str)
@ -507,9 +497,9 @@ QString CutterCore::cmdTask(const QString &str)
return task.getResult();
}
CutterJson CutterCore::parseJson(char *res, const char *cmd)
CutterJson CutterCore::parseJson(const char *name, char *res, const char *cmd)
{
if (!res) {
if (RZ_STR_ISEMPTY(res)) {
return CutterJson();
}
@ -517,18 +507,11 @@ CutterJson CutterCore::parseJson(char *res, const char *cmd)
if (!doc) {
if (cmd) {
eprintf("Failed to parse JSON for command \"%s\"\n", cmd);
RZ_LOG_ERROR("%s: Failed to parse JSON for command \"%s\"\n%s\n", name, cmd, res);
} else {
eprintf("Failed to parse JSON\n");
}
const int MAX_JSON_DUMP_SIZE = 8 * 1024;
size_t originalSize = strlen(res);
if (originalSize > MAX_JSON_DUMP_SIZE) {
res[MAX_JSON_DUMP_SIZE] = 0;
eprintf("%zu bytes total: %s ...\n", originalSize, res);
} else {
eprintf("%s\n", res);
RZ_LOG_ERROR("%s: Failed to parse JSON %s\n", name, res);
}
RZ_LOG_ERROR("%s: %s\n", name, res);
}
return CutterJson(doc, QSharedPointer<CutterJsonOwner>::create(doc, res));
@ -602,8 +585,6 @@ bool CutterCore::loadFile(QString path, ut64 baddr, ut64 mapaddr, int perms, int
rz_bin_select_idx(core->bin, NULL, idx);
}
#endif
} else {
// Not loading RzBin info coz va = false
}
auto iod = core->io ? core->io->desc : NULL;
@ -611,7 +592,8 @@ bool CutterCore::loadFile(QString path, ut64 baddr, ut64 mapaddr, int perms, int
core->file && iod && (core->file->fd == iod->fd) && iod->plugin && iod->plugin->isdbg;
if (!debug && rz_flag_get(core->flags, "entry0")) {
rz_core_cmd0(core, "s entry0");
ut64 addr = rz_num_math(core->num, "entry0");
rz_core_seek_and_save(core, addr, true);
}
if (perms & RZ_PERM_W) {
@ -621,6 +603,7 @@ bool CutterCore::loadFile(QString path, ut64 baddr, ut64 mapaddr, int perms, int
}
}
rz_cons_flush();
fflush(stdout);
return true;
}
@ -1390,7 +1373,7 @@ CutterJson CutterCore::getSignatureInfo()
if (!signature) {
return {};
}
return parseJson(signature, nullptr);
return parseJson("signature", signature, nullptr);
}
bool CutterCore::existsFileInfo()
@ -4333,6 +4316,7 @@ void CutterCore::loadScript(const QString &scriptname)
{
CORE_LOCK();
rz_core_cmd_file(core, scriptname.toUtf8().constData());
rz_cons_flush();
}
triggerRefreshAll();
}

View File

@ -183,10 +183,10 @@ public:
QString getRizinVersionReadable(const char *program = nullptr);
QString getVersionInformation();
CutterJson parseJson(char *res, const char *cmd = nullptr);
CutterJson parseJson(char *res, const QString &cmd = QString())
CutterJson parseJson(const char *name, char *res, const char *cmd = nullptr);
CutterJson parseJson(const char *name, char *res, const QString &cmd = QString())
{
return parseJson(res, cmd.isNull() ? nullptr : cmd.toLocal8Bit().constData());
return parseJson(name, res, cmd.isNull() ? nullptr : cmd.toLocal8Bit().constData());
}
QStringList autocomplete(const QString &cmd, RzLinePromptType promptType, size_t limit = 4096);

View File

@ -520,7 +520,7 @@ void DisassemblyContextMenu::aboutToShowSlot()
if (ab && ab->op) {
const char *opexstr = RZ_STRBUF_SAFEGET(&ab->op->opex);
CutterJson operands = Core()->parseJson(strdup(opexstr), nullptr);
CutterJson operands = Core()->parseJson("opex", strdup(opexstr), nullptr);
// Loop through both the operands of the instruction
for (const CutterJson operand : operands) {

View File

@ -193,11 +193,11 @@ void GraphvizLayout::CalculateLayout(std::unordered_map<ut64, GraphBlock> &block
if (it != edges.end()) {
auto e = it->second;
if (auto spl = ED_spl(e)) {
for (int i = 0; i < 1 && i < spl->size; i++) {
for (size_t i = 0; i < 1 && i < spl->size; i++) {
auto bz = spl->list[i];
edge.polyline.clear();
edge.polyline.reserve(bz.size + 1);
for (int j = 0; j < bz.size; j++) {
for (size_t j = 0; j < bz.size; j++) {
edge.polyline.push_back(QPointF(bz.list[j].x, bz.list[j].y));
}
QPointF last(0, 0);