mirror of
https://github.com/rizinorg/jsdec.git
synced 2026-11-07 06:45:57 -10:00
Create cutter native plugin (#52)
This commit is contained in:
1 parent
0f966e3c2c
commit
906664e1fd
12 files changed
+549
-12
No files matched your search
@@ -28,7 +28,7 @@ rm -rf "rizin-*"
|
||||
cd "$CI_JSDEC"
|
||||
|
||||
# build jsdec and install in the rizin dir.
|
||||
meson setup --buildtype=release -Dstandalone=false build
|
||||
meson setup --buildtype=release -Dbuild_type=rizin build
|
||||
sudo ninja -C build install
|
||||
|
||||
# check if it was installed correctly and try to run it.
|
||||
|
||||
@@ -46,3 +46,7 @@ License: BSD-3-Clause
|
||||
Files: .clang-format
|
||||
Copyright: 2021 Giovanni Dante Grazioli <[email protected]>
|
||||
License: BSD-3-Clause
|
||||
|
||||
Files: cutter-plugin/CMakeLists.txt
|
||||
Copyright: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
License: BSD-3-Clause
|
||||
@@ -0,0 +1,359 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rz_types.h>
|
||||
#include <rz_lib.h>
|
||||
#include <rz_cmd.h>
|
||||
#include <rz_core.h>
|
||||
#include <rz_cons.h>
|
||||
#include <rz_analysis.h>
|
||||
|
||||
#include "jsdec.h"
|
||||
#include "jsdec-cutter.h"
|
||||
|
||||
typedef struct rz_core_t RzCore;
|
||||
|
||||
typedef struct exec_context_t {
|
||||
RzCore *core;
|
||||
void *bed;
|
||||
RzStrBuf *anno;
|
||||
JSValue shared;
|
||||
} ExecContext;
|
||||
|
||||
static JSValue js_analysis_bytes(JSContext *ctx, RzCore *core, RzAnalysisBytes *ab) {
|
||||
RzAnalysisOp *aop = ab->op;
|
||||
JSValue op = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, op, "offset", JS_NewBigUint64(ctx, aop->addr));
|
||||
if (aop->ptr != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "ptr", JS_NewBigUint64(ctx, aop->ptr));
|
||||
}
|
||||
if (aop->val != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "val", JS_NewBigUint64(ctx, aop->val));
|
||||
}
|
||||
JS_SetPropertyStr(ctx, op, "opcode", JS_NewString(ctx, rz_str_get_null(ab->opcode)));
|
||||
JS_SetPropertyStr(ctx, op, "disasm", JS_NewString(ctx, rz_str_get_null(ab->disasm)));
|
||||
JS_SetPropertyStr(ctx, op, "type", JS_NewString(ctx, rz_analysis_optype_to_string(aop->type)));
|
||||
if (aop->jump != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "jump", JS_NewBigInt64(ctx, aop->jump));
|
||||
}
|
||||
if (aop->fail != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "fail", JS_NewBigUint64(ctx, aop->fail));
|
||||
}
|
||||
const char *comment = rz_meta_get_string(core->analysis, RZ_META_TYPE_COMMENT, aop->addr);
|
||||
if (RZ_STR_ISNOTEMPTY(comment)) {
|
||||
JS_SetPropertyStr(ctx, op, "comment", JS_NewString(ctx, comment));
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
static JSValue js_analysis_opcodes(JSContext *ctx, RzCore *core) {
|
||||
RzAnalysisBytes *ab;
|
||||
JSValue ops = JS_NewArray(ctx);
|
||||
st64 op_idx = 0;
|
||||
|
||||
RzIterator *iter = rz_core_analysis_bytes(core, core->offset, core->block, core->blocksize, 0);
|
||||
if (!iter) {
|
||||
return ops;
|
||||
}
|
||||
rz_iterator_foreach(iter, ab) {
|
||||
if (!ab || !ab->op || !strcmp(ab->opcode, "nop")) {
|
||||
continue;
|
||||
}
|
||||
JSValue op = js_analysis_bytes(ctx, core, ab);
|
||||
JS_SetPropertyInt64(ctx, ops, op_idx, op);
|
||||
op_idx++;
|
||||
}
|
||||
rz_iterator_free(iter);
|
||||
return ops;
|
||||
}
|
||||
|
||||
static JSValue js_function_bbs(JSContext *ctx, RzCore *core, RzAnalysisFunction *fcn) {
|
||||
JSValue bbs = JS_NewArray(ctx);
|
||||
RzAnalysisBlock *bbi;
|
||||
RzListIter *iter;
|
||||
st64 bbs_idx = 0;
|
||||
ut64 old_offset = core->offset;
|
||||
ut64 old_bsize = core->blocksize;
|
||||
rz_list_foreach (fcn->bbs, iter, bbi) {
|
||||
rz_core_block_size(core, bbi->size);
|
||||
rz_core_seek(core, bbi->addr, true);
|
||||
|
||||
JSValue bb = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, bb, "address", JS_NewBigUint64(ctx, bbi->addr));
|
||||
if (bbi->jump != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, bb, "jump", JS_NewBigUint64(ctx, bbi->jump));
|
||||
}
|
||||
if (bbi->fail != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, bb, "fail", JS_NewBigUint64(ctx, bbi->fail));
|
||||
}
|
||||
JSValue ops = js_analysis_opcodes(ctx, core);
|
||||
JS_SetPropertyStr(ctx, bb, "ops", ops);
|
||||
JS_SetPropertyInt64(ctx, bbs, bbs_idx, bb);
|
||||
bbs_idx++;
|
||||
}
|
||||
rz_core_block_size(core, old_bsize);
|
||||
rz_core_seek(core, old_offset, true);
|
||||
return bbs;
|
||||
}
|
||||
|
||||
static JSValue js_command(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
if (argc != 1) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
const char *command = JS_ToCString(ctx, argv[0]);
|
||||
if (!command) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
ExecContext *ectx = (ExecContext *)JS_GetContextOpaque(ctx);
|
||||
RzCore *core = ectx->core;
|
||||
rz_cons_sleep_end(ectx->bed);
|
||||
|
||||
char *output = rz_core_cmd_str(core, command);
|
||||
JS_FreeCString(ctx, command);
|
||||
JSValue result = JS_NewString(ctx, output ? output : "");
|
||||
free(output);
|
||||
|
||||
ectx->bed = rz_cons_sleep_begin();
|
||||
return result;
|
||||
}
|
||||
|
||||
static JSValue js_graph(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
if (argc != 0) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
ExecContext *ectx = (ExecContext *)JS_GetContextOpaque(ctx);
|
||||
RzCore *core = ectx->core;
|
||||
rz_cons_sleep_end(ectx->bed);
|
||||
|
||||
RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(core->analysis, core->offset, -1);
|
||||
if (!fcn) {
|
||||
ectx->bed = rz_cons_sleep_begin();
|
||||
return JS_ThrowInternalError(ctx, "Cannot find function at 0x%08" PFMT64x, core->offset);
|
||||
}
|
||||
|
||||
JSValue graph = JS_NewArray(ctx);
|
||||
JSValue object = JS_NewObject(ctx);
|
||||
JS_SetPropertyInt64(ctx, graph, 0, object);
|
||||
JS_SetPropertyStr(ctx, object, "name", JS_NewString(ctx, rz_str_get_null(fcn->name)));
|
||||
JSValue blocks = js_function_bbs(ctx, core, fcn);
|
||||
JS_SetPropertyStr(ctx, object, "blocks", blocks);
|
||||
ectx->bed = rz_cons_sleep_begin();
|
||||
return graph;
|
||||
}
|
||||
|
||||
static JSValue js_console_log(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
ExecContext *ectx = (ExecContext *)JS_GetContextOpaque(ctx);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (i != 0) {
|
||||
rz_strbuf_append_n(ectx->anno, " ", 1);
|
||||
}
|
||||
const char *str = JS_ToCString(ctx, argv[i]);
|
||||
if (!str) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
rz_strbuf_append(ectx->anno, str);
|
||||
JS_FreeCString(ctx, str);
|
||||
}
|
||||
rz_strbuf_append_n(ectx->anno, "\n", 1);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_get_global(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
ExecContext *ectx = (ExecContext *)JS_GetContextOpaque(ctx);
|
||||
return JS_GetPropertyStr(ctx, ectx->shared, "Shared");
|
||||
}
|
||||
|
||||
static jsdec_t *jsdec_create(ExecContext *ec) {
|
||||
jsdec_t *dec = jsdec_new();
|
||||
if (!dec) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSContext *ctx = jsdec_context(dec);
|
||||
JS_SetContextOpaque(ctx, ec);
|
||||
ec->shared = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, ec->shared, "Shared", JS_NewObject(ctx));
|
||||
|
||||
JSValue global = JS_GetGlobalObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "Global", JS_NewCFunction(ctx, js_get_global, "Global", 1));
|
||||
|
||||
JSValue console = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "console", console);
|
||||
JS_SetPropertyStr(ctx, console, "log", JS_NewCFunction(ctx, js_console_log, "log", 1));
|
||||
|
||||
JSValue rizin = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "rizin", rizin);
|
||||
JS_SetPropertyStr(ctx, rizin, "command", JS_NewCFunction(ctx, js_command, "command", 1));
|
||||
JS_SetPropertyStr(ctx, rizin, "graph", JS_NewCFunction(ctx, js_graph, "graph", 1));
|
||||
|
||||
JSValue process = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "process", process);
|
||||
JSValue args = JS_NewArray(ctx);
|
||||
JS_SetPropertyInt64(ctx, args, 0, JS_NewString(ctx, "--annotation"));
|
||||
JS_SetPropertyStr(ctx, process, "args", args);
|
||||
|
||||
JS_FreeValue(ctx, global);
|
||||
return dec;
|
||||
}
|
||||
|
||||
static void jsdec_destroy(jsdec_t *dec, ExecContext *ec) {
|
||||
JSContext *ctx = jsdec_context(dec);
|
||||
JS_FreeValue(ctx, ec->shared);
|
||||
jsdec_free(dec);
|
||||
}
|
||||
|
||||
static char *json_to_strdup(const RzJson *object, const char *key) {
|
||||
const RzJson *j = rz_json_get(object, key);
|
||||
if (!j || j->type != RZ_JSON_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
return rz_str_dup(j->str_value);
|
||||
}
|
||||
|
||||
static const char *json_as_string(const RzJson *object, const char *key) {
|
||||
const RzJson *j = rz_json_get(object, key);
|
||||
if (!j || j->type != RZ_JSON_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
return j->str_value;
|
||||
}
|
||||
|
||||
static ut64 json_as_ut64(const RzJson *object, const char *key) {
|
||||
const RzJson *j = rz_json_get(object, key);
|
||||
if (!j || (j->type != RZ_JSON_STRING && j->type != RZ_JSON_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
if (j->type == RZ_JSON_INTEGER) {
|
||||
return j->num.u_value;
|
||||
} else if (rz_num_is_valid_input(NULL, j->str_value)) {
|
||||
return rz_num_get_input_value(NULL, j->str_value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static RzAnnotatedCode *parse_json(RzStrBuf *sb) {
|
||||
char *text = rz_strbuf_drain(sb);
|
||||
if (RZ_STR_ISEMPTY(text)) {
|
||||
free(text);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// text is modified by rz_json_parse and
|
||||
// is freed by rz_json_free
|
||||
RzJson *json = rz_json_parse(text);
|
||||
if (!json) {
|
||||
RZ_LOG_ERROR("failed to parse from json string\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *raw_code = json_to_strdup(json, "code");
|
||||
if (!raw_code) {
|
||||
rz_json_free(json);
|
||||
RZ_LOG_ERROR("failed to dup code\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzAnnotatedCode *code = rz_annotated_code_new(raw_code);
|
||||
if (!code) {
|
||||
rz_json_free(json);
|
||||
RZ_LOG_ERROR("failed to create RzAnnotatedCode\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const RzJson *annotations = rz_json_get(json, "annotations");
|
||||
const RzJson *element = NULL;
|
||||
for (size_t idx = 0; annotations && (element = rz_json_item(annotations, idx)); idx++) {
|
||||
RzCodeAnnotation annotation = { 0 };
|
||||
annotation.start = json_as_ut64(element, "start");
|
||||
annotation.end = json_as_ut64(element, "end");
|
||||
const char *type = json_as_string(element, "type");
|
||||
if (!strcmp(type, "offset")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_OFFSET;
|
||||
annotation.offset.offset = json_as_ut64(element, "offset");
|
||||
} else if (!strcmp(type, "function_name")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_FUNCTION_NAME;
|
||||
annotation.reference.name = json_to_strdup(element, "name");
|
||||
annotation.reference.offset = json_as_ut64(element, "offset");
|
||||
} else if (!strcmp(type, "global_variable")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE;
|
||||
annotation.reference.offset = json_as_ut64(element, "offset");
|
||||
} else if (!strcmp(type, "constant_variable")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE;
|
||||
annotation.reference.offset = json_as_ut64(element, "offset");
|
||||
} else if (!strcmp(type, "local_variable")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE;
|
||||
annotation.variable.name = json_to_strdup(element, "name");
|
||||
} else if (!strcmp(type, "function_parameter")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER;
|
||||
annotation.variable.name = json_to_strdup(element, "name");
|
||||
} else if (!strcmp(type, "syntax_highlight")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT;
|
||||
const char *highlightType = json_as_string(element, "syntax_highlight");
|
||||
if (!strcmp(highlightType, "keyword")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_KEYWORD;
|
||||
} else if (!strcmp(highlightType, "comment")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_COMMENT;
|
||||
} else if (!strcmp(highlightType, "datatype")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_DATATYPE;
|
||||
} else if (!strcmp(highlightType, "function_name")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_NAME;
|
||||
} else if (!strcmp(highlightType, "function_parameter")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_PARAMETER;
|
||||
} else if (!strcmp(highlightType, "local_variable")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_LOCAL_VARIABLE;
|
||||
} else if (!strcmp(highlightType, "constant_variable")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_CONSTANT_VARIABLE;
|
||||
} else if (!strcmp(highlightType, "global_variable")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_GLOBAL_VARIABLE;
|
||||
}
|
||||
}
|
||||
rz_annotated_code_add_annotation(code, &annotation);
|
||||
}
|
||||
|
||||
rz_json_free(json);
|
||||
return code;
|
||||
}
|
||||
|
||||
RzAnnotatedCode *jsdec_as_annotation(RzCore *core, ut64 addr) {
|
||||
ExecContext ectx;
|
||||
ectx.core = core;
|
||||
ectx.anno = rz_strbuf_new("");
|
||||
if (!ectx.anno) {
|
||||
rz_strbuf_free(ectx.anno);
|
||||
RZ_LOG_ERROR("failed to create RzStrBuf\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsdec_t *dec = jsdec_create(&ectx);
|
||||
if (!dec) {
|
||||
rz_strbuf_free(ectx.anno);
|
||||
RZ_LOG_ERROR("failed to create jsdec_t\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ut64 offset = core->offset;
|
||||
if (offset != addr) {
|
||||
rz_core_seek(core, addr, true);
|
||||
}
|
||||
|
||||
ectx.bed = rz_cons_sleep_begin();
|
||||
bool ret = jsdec_run(dec);
|
||||
rz_cons_sleep_end(ectx.bed);
|
||||
|
||||
if (offset != addr) {
|
||||
rz_core_seek(core, offset, true);
|
||||
}
|
||||
|
||||
jsdec_destroy(dec, &ectx);
|
||||
if (!ret) {
|
||||
rz_strbuf_free(ectx.anno);
|
||||
RZ_LOG_ERROR("jsdec_run returned false\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return parse_json(ectx.anno);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#ifndef JSDEC_CUTTER_H
|
||||
#define JSDEC_CUTTER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rz_util/rz_annotated_code.h>
|
||||
|
||||
RzAnnotatedCode *jsdec_as_annotation(RzCore *core, ut64 addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JSDEC_CUTTER_H */
|
||||
@@ -0,0 +1,26 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(cutter-jsdec-plugin)
|
||||
|
||||
set(CUTTER_INSTALL_PLUGDIR "share/rizin/cutter/plugins/native" CACHE STRING "Directory to install Cutter plugin into")
|
||||
set(JSDEC_BUILD_DIR "../build" CACHE STRING "Directory where to find libjsdec.a")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_INSTALL_PREFIX}/lib/cmake/Cutter")
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
add_library(jsdec_cutter MODULE
|
||||
JSDecPlugin.h
|
||||
JSDecPlugin.cpp
|
||||
JSDecDecompiler.h
|
||||
JSDecDecompiler.cpp
|
||||
)
|
||||
|
||||
find_library(libjsdec NAMES jsdec PATHS "${JSDEC_BUILD_DIR}")
|
||||
include_directories("../c")
|
||||
|
||||
find_package(Cutter REQUIRED)
|
||||
|
||||
target_link_libraries(jsdec_cutter PRIVATE Cutter::Cutter "${libjsdec}")
|
||||
install(TARGETS jsdec_cutter DESTINATION "${CUTTER_INSTALL_PLUGDIR}")
|
||||
@@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "JSDecDecompiler.h"
|
||||
#include <Cutter.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "../c/jsdec-cutter.h"
|
||||
|
||||
JSDecDecompiler::JSDecDecompiler(QObject *parent)
|
||||
: Decompiler("jsdec", "jsdec", parent) {
|
||||
task = nullptr;
|
||||
}
|
||||
|
||||
void JSDecDecompiler::decompileAt(RVA addr) {
|
||||
if (task) {
|
||||
return;
|
||||
}
|
||||
|
||||
task = new RizinFunctionTask([addr](RzCore *core) {
|
||||
return jsdec_as_annotation(core, addr);
|
||||
});
|
||||
|
||||
connect(task, &RizinFunctionTask::finished, this, [this]() {
|
||||
auto res = reinterpret_cast<RzAnnotatedCode *>(task->getResult());
|
||||
delete task;
|
||||
task = nullptr;
|
||||
if (!res) {
|
||||
res = Decompiler::makeWarning(tr("Failed to parse JSON from jsdec"));
|
||||
}
|
||||
emit finished(res);
|
||||
});
|
||||
|
||||
task->startTask();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#ifndef JSDEC_DECOMPILER_H
|
||||
#define JSDEC_DECOMPILER_H
|
||||
|
||||
#include "Decompiler.h"
|
||||
#include "RizinTask.h"
|
||||
|
||||
class JSDecDecompiler: public Decompiler
|
||||
{
|
||||
private:
|
||||
RizinFunctionTask *task;
|
||||
|
||||
public:
|
||||
JSDecDecompiler(QObject *parent = nullptr);
|
||||
virtual void decompileAt(RVA addr) override;
|
||||
virtual bool isRunning() override { return task != nullptr; }
|
||||
};
|
||||
|
||||
#endif // JSDEC_DECOMPILER_H
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "JSDecDecompiler.h"
|
||||
#include "JSDecPlugin.h"
|
||||
|
||||
void JSDecPlugin::setupPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
void JSDecPlugin::setupInterface(MainWindow *)
|
||||
{
|
||||
}
|
||||
|
||||
void JSDecPlugin::registerDecompilers()
|
||||
{
|
||||
Core()->registerDecompiler(new JSDecDecompiler(Core()));
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#ifndef JSDEC_CUTTER_PLUGIN_H
|
||||
#define JSDEC_CUTTER_PLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtPlugin>
|
||||
#include <plugins/CutterPlugin.h>
|
||||
|
||||
class JSDecPlugin : public QObject, CutterPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "re.rizin.cutter.plugins.jsdec")
|
||||
Q_INTERFACES(CutterPlugin)
|
||||
|
||||
public:
|
||||
void setupPlugin() override;
|
||||
void setupInterface(MainWindow *main) override;
|
||||
void registerDecompilers() override;
|
||||
|
||||
QString getName() const override { return "JsDec Decompiler (jsdec)"; }
|
||||
QString getAuthor() const override { return "deroad"; }
|
||||
QString getDescription() const override { return "GUI Integration of jsdec."; }
|
||||
QString getVersion() const override { return "1.0"; }
|
||||
};
|
||||
|
||||
|
||||
#endif // JSDEC_CUTTER_PLUGIN_H
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
jsdec_plugin = 'jsdec-plugin.js'
|
||||
jsdec_testsuite = 'jsdec-testsuite.js'
|
||||
|
||||
if get_option('standalone')
|
||||
if get_option('build_type') == 'standalone'
|
||||
bytecode_h = custom_target(
|
||||
'bytecode.h',
|
||||
build_always_stale: true,
|
||||
|
||||
+32
-9
@@ -1,7 +1,7 @@
|
||||
# SPDX-FileCopyrightText: 2023 Giovanni Dante Grazioli <[email protected]>
|
||||
# SPDX-FileCopyrightText: 2023-2024 Giovanni Dante Grazioli <[email protected]>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
project('jsdec', 'c', meson_version: '>=0.55.0')
|
||||
project('jsdec', 'c', meson_version: '>=0.56.0')
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
@@ -16,7 +16,7 @@ jsdec_src = [
|
||||
'c' / 'base64.c',
|
||||
]
|
||||
jsdec_deps = [
|
||||
libquickjs_dep,
|
||||
libquickjs_dep.as_link_whole(),
|
||||
]
|
||||
|
||||
modjs_gen = executable('modjs_gen', 'tools' / 'modjs_gen.c',
|
||||
@@ -28,8 +28,8 @@ modjs_gen = executable('modjs_gen', 'tools' / 'modjs_gen.c',
|
||||
|
||||
subdir('js')
|
||||
|
||||
if get_option('standalone')
|
||||
|
||||
build_type = get_option('build_type')
|
||||
if build_type == 'standalone'
|
||||
jsdec_src += [
|
||||
bytecode_h,
|
||||
bytecode_mod_h,
|
||||
@@ -43,7 +43,31 @@ if get_option('standalone')
|
||||
implicit_include_directories: false,
|
||||
install: false,
|
||||
)
|
||||
else
|
||||
elif build_type == 'cutter'
|
||||
jsdec_deps += dependency('rz_core')
|
||||
jsdec_deps += dependency('rz_util')
|
||||
jsdec_deps += dependency('rz_cons')
|
||||
jsdec_deps += dependency('rz_config')
|
||||
jsdec_deps += dependency('rz_io')
|
||||
|
||||
jsdec_src += [
|
||||
bytecode_h,
|
||||
bytecode_mod_h,
|
||||
'c' / 'jsdec-cutter.c'
|
||||
]
|
||||
|
||||
libjsdec = static_library('jsdec', jsdec_src,
|
||||
c_args : jsdec_c_args,
|
||||
dependencies: jsdec_deps,
|
||||
include_directories: include_directories(jsdec_incs),
|
||||
implicit_include_directories: false,
|
||||
install: false,
|
||||
)
|
||||
libjsdec_dep = declare_dependency(
|
||||
link_with: libjsdec,
|
||||
include_directories: include_directories(jsdec_incs),
|
||||
)
|
||||
elif build_type == 'rizin'
|
||||
# build plugin for Rizin
|
||||
rz_core_dep = dependency('rz_core')
|
||||
jsdec_deps += rz_core_dep
|
||||
@@ -54,9 +78,6 @@ else
|
||||
rizin_plugdir = get_option('rizin_plugdir')
|
||||
if rizin_plugdir == ''
|
||||
rizin_plugdir = rz_core_dep.get_variable(pkgconfig: 'plugindir', cmake: 'rz_core_PLUGINDIR')
|
||||
plugin_jsdec_dir = join_paths(get_option('prefix'), rizin_plugdir, 'jsdec')
|
||||
else
|
||||
plugin_jsdec_dir = join_paths(rizin_plugdir, 'jsdec')
|
||||
endif
|
||||
|
||||
jsdec_src += [
|
||||
@@ -73,4 +94,6 @@ else
|
||||
install: true,
|
||||
install_dir: rizin_plugdir
|
||||
)
|
||||
else
|
||||
error('Invalid `build_type`.')
|
||||
endif
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
option('rizin_plugdir', type: 'string', value: '', description: 'rizin install directory')
|
||||
option('standalone', type: 'boolean', value: false, description: 'enables/disables building only the standalone executable for testing purposes')
|
||||
option('build_type', type: 'combo', choices: ['rizin', 'cutter', 'standalone'], value: 'rizin', description: 'build type; `standalone` for tests, `rizin` as rizin native plugin and `cutter` as cutter native plugin')
|
||||
Reference in new issue
Block a user