Move Serialization Helpers to Global API (#522)

This commit is contained in:
Florian Märkl 2021-02-06 12:10:43 +01:00 committed by GitHub
parent 9ea2984174
commit d93d3f3770
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 225 additions and 196 deletions

View file

@ -3,8 +3,6 @@
#include <rz_util/rz_serialize.h>
#include <rz_analysis.h>
#include "../util/serialize_helper.h"
#include <errno.h>
/*
@ -96,20 +94,20 @@ enum {
};
RZ_API RzSerializeAnalDiffParser rz_serialize_analysis_diff_parser_new(void) {
RzSerializeAnalDiffParser parser = key_parser_new();
RzSerializeAnalDiffParser parser = rz_key_parser_new();
if (!parser) {
return NULL;
}
key_parser_add(parser, "type", DIFF_FIELD_TYPE);
key_parser_add(parser, "addr", DIFF_FIELD_ADDR);
key_parser_add(parser, "dist", DIFF_FIELD_DIST);
key_parser_add(parser, "name", DIFF_FIELD_NAME);
key_parser_add(parser, "size", DIFF_FIELD_SIZE);
rz_key_parser_add(parser, "type", DIFF_FIELD_TYPE);
rz_key_parser_add(parser, "addr", DIFF_FIELD_ADDR);
rz_key_parser_add(parser, "dist", DIFF_FIELD_DIST);
rz_key_parser_add(parser, "name", DIFF_FIELD_NAME);
rz_key_parser_add(parser, "size", DIFF_FIELD_SIZE);
return parser;
}
RZ_API void rz_serialize_analysis_diff_parser_free(RzSerializeAnalDiffParser parser) {
key_parser_free(parser);
rz_key_parser_free(parser);
}
RZ_API RZ_NULLABLE RzAnalysisDiff *rz_serialize_analysis_diff_load(RZ_NONNULL RzSerializeAnalDiffParser parser, RZ_NONNULL const RJson *json) {
@ -120,7 +118,7 @@ RZ_API RZ_NULLABLE RzAnalysisDiff *rz_serialize_analysis_diff_load(RZ_NONNULL Rz
if (!diff) {
return NULL;
}
KEY_PARSER_JSON(parser, json, child, {
RZ_KEY_PARSER_JSON(parser, json, child, {
case DIFF_FIELD_TYPE:
if (child->type != RZ_JSON_STRING) {
break;
@ -340,7 +338,7 @@ enum {
typedef struct {
RzAnalysis *analysis;
KeyParser *parser;
RzKeyParser *parser;
RzSerializeAnalDiffParser diff_parser;
} BlockLoadCtx;
@ -364,7 +362,7 @@ static bool block_load_cb(void *user, const char *k, const char *v) {
proto.parent_stackptr = INT_MAX;
proto.cmpval = UT64_MAX;
size_t fingerprint_size = SIZE_MAX;
KEY_PARSER_JSON(ctx->parser, json, child, {
RZ_KEY_PARSER_JSON(ctx->parser, json, child, {
case BLOCK_FIELD_SIZE:
if (child->type != RZ_JSON_INTEGER) {
break;
@ -529,29 +527,29 @@ error:
}
RZ_API bool rz_serialize_analysis_blocks_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RzSerializeAnalDiffParser diff_parser, RZ_NULLABLE RzSerializeResultInfo *res) {
BlockLoadCtx ctx = { analysis, key_parser_new(), diff_parser };
BlockLoadCtx ctx = { analysis, rz_key_parser_new(), diff_parser };
if (!ctx.parser) {
SERIALIZE_ERR("parser init failed");
RZ_SERIALIZE_ERR(res, "parser init failed");
return false;
}
key_parser_add(ctx.parser, "size", BLOCK_FIELD_SIZE);
key_parser_add(ctx.parser, "jump", BLOCK_FIELD_JUMP);
key_parser_add(ctx.parser, "fail", BLOCK_FIELD_FAIL);
key_parser_add(ctx.parser, "traced", BLOCK_FIELD_TRACED);
key_parser_add(ctx.parser, "colorize", BLOCK_FIELD_COLORIZE);
key_parser_add(ctx.parser, "fingerprint", BLOCK_FIELD_FINGERPRINT);
key_parser_add(ctx.parser, "diff", BLOCK_FIELD_DIFF);
key_parser_add(ctx.parser, "switch_op", BLOCK_FIELD_SWITCH_OP);
key_parser_add(ctx.parser, "ninstr", BLOCK_FIELD_NINSTR);
key_parser_add(ctx.parser, "op_pos", BLOCK_FIELD_OP_POS);
key_parser_add(ctx.parser, "stackptr", BLOCK_FIELD_STACKPTR);
key_parser_add(ctx.parser, "parent_stackptr", BLOCK_FIELD_PARENT_STACKPTR);
key_parser_add(ctx.parser, "cmpval", BLOCK_FIELD_CMPVAL);
key_parser_add(ctx.parser, "cmpreg", BLOCK_FIELD_CMPREG);
rz_key_parser_add(ctx.parser, "size", BLOCK_FIELD_SIZE);
rz_key_parser_add(ctx.parser, "jump", BLOCK_FIELD_JUMP);
rz_key_parser_add(ctx.parser, "fail", BLOCK_FIELD_FAIL);
rz_key_parser_add(ctx.parser, "traced", BLOCK_FIELD_TRACED);
rz_key_parser_add(ctx.parser, "colorize", BLOCK_FIELD_COLORIZE);
rz_key_parser_add(ctx.parser, "fingerprint", BLOCK_FIELD_FINGERPRINT);
rz_key_parser_add(ctx.parser, "diff", BLOCK_FIELD_DIFF);
rz_key_parser_add(ctx.parser, "switch_op", BLOCK_FIELD_SWITCH_OP);
rz_key_parser_add(ctx.parser, "ninstr", BLOCK_FIELD_NINSTR);
rz_key_parser_add(ctx.parser, "op_pos", BLOCK_FIELD_OP_POS);
rz_key_parser_add(ctx.parser, "stackptr", BLOCK_FIELD_STACKPTR);
rz_key_parser_add(ctx.parser, "parent_stackptr", BLOCK_FIELD_PARENT_STACKPTR);
rz_key_parser_add(ctx.parser, "cmpval", BLOCK_FIELD_CMPVAL);
rz_key_parser_add(ctx.parser, "cmpreg", BLOCK_FIELD_CMPREG);
bool ret = sdb_foreach(db, block_load_cb, &ctx);
key_parser_free(ctx.parser);
rz_key_parser_free(ctx.parser);
if (!ret) {
SERIALIZE_ERR("basic blocks parsing failed");
RZ_SERIALIZE_ERR(res, "basic blocks parsing failed");
}
return ret;
}
@ -637,24 +635,24 @@ enum {
};
RZ_API RzSerializeAnalVarParser rz_serialize_analysis_var_parser_new(void) {
RzSerializeAnalDiffParser parser = key_parser_new();
RzSerializeAnalDiffParser parser = rz_key_parser_new();
if (!parser) {
return NULL;
}
key_parser_add(parser, "name", VAR_FIELD_NAME);
key_parser_add(parser, "type", VAR_FIELD_TYPE);
key_parser_add(parser, "kind", VAR_FIELD_KIND);
key_parser_add(parser, "arg", VAR_FIELD_ARG);
key_parser_add(parser, "delta", VAR_FIELD_DELTA);
key_parser_add(parser, "reg", VAR_FIELD_REG);
key_parser_add(parser, "cmt", VAR_FIELD_COMMENT);
key_parser_add(parser, "accs", VAR_FIELD_ACCS);
key_parser_add(parser, "constrs", VAR_FIELD_CONSTRS);
rz_key_parser_add(parser, "name", VAR_FIELD_NAME);
rz_key_parser_add(parser, "type", VAR_FIELD_TYPE);
rz_key_parser_add(parser, "kind", VAR_FIELD_KIND);
rz_key_parser_add(parser, "arg", VAR_FIELD_ARG);
rz_key_parser_add(parser, "delta", VAR_FIELD_DELTA);
rz_key_parser_add(parser, "reg", VAR_FIELD_REG);
rz_key_parser_add(parser, "cmt", VAR_FIELD_COMMENT);
rz_key_parser_add(parser, "accs", VAR_FIELD_ACCS);
rz_key_parser_add(parser, "constrs", VAR_FIELD_CONSTRS);
return parser;
}
RZ_API void rz_serialize_analysis_var_parser_free(RzSerializeAnalVarParser parser) {
key_parser_free(parser);
rz_key_parser_free(parser);
}
RZ_API RZ_NULLABLE RzAnalysisVar *rz_serialize_analysis_var_load(RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzSerializeAnalVarParser parser, RZ_NONNULL const RJson *json) {
@ -675,7 +673,7 @@ RZ_API RZ_NULLABLE RzAnalysisVar *rz_serialize_analysis_var_load(RZ_NONNULL RzAn
RzAnalysisVar *ret = NULL;
KEY_PARSER_JSON(parser, json, child, {
RZ_KEY_PARSER_JSON(parser, json, child, {
case VAR_FIELD_NAME:
if (child->type != RZ_JSON_STRING) {
break;
@ -968,7 +966,7 @@ enum {
typedef struct {
RzAnalysis *analysis;
KeyParser *parser;
RzKeyParser *parser;
RzSerializeAnalDiffParser diff_parser;
RzSerializeAnalVarParser var_parser;
} FunctionLoadCtx;
@ -992,7 +990,7 @@ static bool function_load_cb(void *user, const char *k, const char *v) {
function->bp_off = 0; // 0 if not specified
bool noreturn = false;
RJson *vars_json = NULL;
KEY_PARSER_JSON(ctx->parser, json, child, {
RZ_KEY_PARSER_JSON(ctx->parser, json, child, {
case FUNCTION_FIELD_NAME:
if (child->type != RZ_JSON_STRING) {
break;
@ -1190,39 +1188,39 @@ beach:
RZ_API bool rz_serialize_analysis_functions_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RzSerializeAnalDiffParser diff_parser, RZ_NULLABLE RzSerializeResultInfo *res) {
FunctionLoadCtx ctx = {
.analysis = analysis,
.parser = key_parser_new(),
.parser = rz_key_parser_new(),
.diff_parser = diff_parser,
.var_parser = rz_serialize_analysis_var_parser_new()
};
bool ret;
if (!ctx.parser || !ctx.var_parser) {
SERIALIZE_ERR("parser init failed");
RZ_SERIALIZE_ERR(res, "parser init failed");
ret = false;
goto beach;
}
key_parser_add(ctx.parser, "name", FUNCTION_FIELD_NAME);
key_parser_add(ctx.parser, "bits", FUNCTION_FIELD_BITS);
key_parser_add(ctx.parser, "type", FUNCTION_FIELD_TYPE);
key_parser_add(ctx.parser, "cc", FUNCTION_FIELD_CC);
key_parser_add(ctx.parser, "stack", FUNCTION_FIELD_STACK);
key_parser_add(ctx.parser, "maxstack", FUNCTION_FIELD_MAXSTACK);
key_parser_add(ctx.parser, "ninstr", FUNCTION_FIELD_NINSTR);
key_parser_add(ctx.parser, "pure", FUNCTION_FIELD_PURE);
key_parser_add(ctx.parser, "bp_frame", FUNCTION_FIELD_BP_FRAME);
key_parser_add(ctx.parser, "bp_off", FUNCTION_FIELD_BP_OFF);
key_parser_add(ctx.parser, "noreturn", FUNCTION_FIELD_NORETURN);
key_parser_add(ctx.parser, "fingerprint", FUNCTION_FIELD_FINGERPRINT);
key_parser_add(ctx.parser, "diff", FUNCTION_FIELD_DIFF);
key_parser_add(ctx.parser, "bbs", FUNCTION_FIELD_BBS);
key_parser_add(ctx.parser, "imports", FUNCTION_FIELD_IMPORTS);
key_parser_add(ctx.parser, "vars", FUNCTION_FIELD_VARS);
key_parser_add(ctx.parser, "labels", FUNCTION_FIELD_LABELS);
rz_key_parser_add(ctx.parser, "name", FUNCTION_FIELD_NAME);
rz_key_parser_add(ctx.parser, "bits", FUNCTION_FIELD_BITS);
rz_key_parser_add(ctx.parser, "type", FUNCTION_FIELD_TYPE);
rz_key_parser_add(ctx.parser, "cc", FUNCTION_FIELD_CC);
rz_key_parser_add(ctx.parser, "stack", FUNCTION_FIELD_STACK);
rz_key_parser_add(ctx.parser, "maxstack", FUNCTION_FIELD_MAXSTACK);
rz_key_parser_add(ctx.parser, "ninstr", FUNCTION_FIELD_NINSTR);
rz_key_parser_add(ctx.parser, "pure", FUNCTION_FIELD_PURE);
rz_key_parser_add(ctx.parser, "bp_frame", FUNCTION_FIELD_BP_FRAME);
rz_key_parser_add(ctx.parser, "bp_off", FUNCTION_FIELD_BP_OFF);
rz_key_parser_add(ctx.parser, "noreturn", FUNCTION_FIELD_NORETURN);
rz_key_parser_add(ctx.parser, "fingerprint", FUNCTION_FIELD_FINGERPRINT);
rz_key_parser_add(ctx.parser, "diff", FUNCTION_FIELD_DIFF);
rz_key_parser_add(ctx.parser, "bbs", FUNCTION_FIELD_BBS);
rz_key_parser_add(ctx.parser, "imports", FUNCTION_FIELD_IMPORTS);
rz_key_parser_add(ctx.parser, "vars", FUNCTION_FIELD_VARS);
rz_key_parser_add(ctx.parser, "labels", FUNCTION_FIELD_LABELS);
ret = sdb_foreach(db, function_load_cb, &ctx);
if (!ret) {
SERIALIZE_ERR("functions parsing failed");
RZ_SERIALIZE_ERR(res, "functions parsing failed");
}
beach:
key_parser_free(ctx.parser);
rz_key_parser_free(ctx.parser);
rz_serialize_analysis_var_parser_free(ctx.var_parser);
return ret;
}
@ -1326,7 +1324,7 @@ error:
RZ_API bool rz_serialize_analysis_xrefs_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res) {
bool ret = sdb_foreach(db, xrefs_load_cb, analysis);
if (!ret) {
SERIALIZE_ERR("xrefs parsing failed");
RZ_SERIALIZE_ERR(res, "xrefs parsing failed");
}
return ret;
}
@ -1556,7 +1554,7 @@ error:
RZ_API bool rz_serialize_analysis_meta_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res) {
Sdb *spaces_db = sdb_ns(db, "spaces", false);
if (!spaces_db) {
SERIALIZE_ERR("missing meta spaces namespace");
RZ_SERIALIZE_ERR(res, "missing meta spaces namespace");
return false;
}
if (!rz_serialize_spaces_load(spaces_db, &analysis->meta_spaces, false, res)) {
@ -1564,7 +1562,7 @@ RZ_API bool rz_serialize_analysis_meta_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAna
}
bool ret = sdb_foreach(db, meta_load_cb, analysis);
if (!ret) {
SERIALIZE_ERR("meta parsing failed");
RZ_SERIALIZE_ERR(res, "meta parsing failed");
}
return ret;
}
@ -1739,7 +1737,7 @@ enum {
typedef struct {
RzAnalysis *analysis;
KeyParser *parser;
RzKeyParser *parser;
} HintsLoadCtx;
static bool hints_load_cb(void *user, const char *k, const char *v) {
@ -1762,7 +1760,7 @@ static bool hints_load_cb(void *user, const char *k, const char *v) {
return false;
}
KEY_PARSER_JSON(ctx->parser, json, child, {
RZ_KEY_PARSER_JSON(ctx->parser, json, child, {
case HINTS_FIELD_ARCH:
rz_analysis_hint_set_arch(analysis, addr, child->type == RZ_JSON_STRING ? child->str_value : NULL);
break;
@ -1878,38 +1876,38 @@ static bool hints_load_cb(void *user, const char *k, const char *v) {
RZ_API bool rz_serialize_analysis_hints_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res) {
HintsLoadCtx ctx = {
.analysis = analysis,
.parser = key_parser_new(),
.parser = rz_key_parser_new(),
};
bool ret;
if (!ctx.parser) {
SERIALIZE_ERR("parser init failed");
RZ_SERIALIZE_ERR(res, "parser init failed");
ret = false;
goto beach;
}
key_parser_add(ctx.parser, "arch", HINTS_FIELD_ARCH);
key_parser_add(ctx.parser, "bits", HINTS_FIELD_BITS);
key_parser_add(ctx.parser, "immbase", HINTS_FIELD_IMMBASE);
key_parser_add(ctx.parser, "jump", HINTS_FIELD_JUMP);
key_parser_add(ctx.parser, "fail", HINTS_FIELD_FAIL);
key_parser_add(ctx.parser, "frame", HINTS_FIELD_STACKFRAME);
key_parser_add(ctx.parser, "ptr", HINTS_FIELD_PTR);
key_parser_add(ctx.parser, "nword", HINTS_FIELD_NWORD);
key_parser_add(ctx.parser, "ret", HINTS_FIELD_RET);
key_parser_add(ctx.parser, "newbits", HINTS_FIELD_NEW_BITS);
key_parser_add(ctx.parser, "size", HINTS_FIELD_SIZE);
key_parser_add(ctx.parser, "syntax", HINTS_FIELD_SYNTAX);
key_parser_add(ctx.parser, "optype", HINTS_FIELD_OPTYPE);
key_parser_add(ctx.parser, "opcode", HINTS_FIELD_OPCODE);
key_parser_add(ctx.parser, "toff", HINTS_FIELD_TYPE_OFFSET);
key_parser_add(ctx.parser, "esil", HINTS_FIELD_ESIL);
key_parser_add(ctx.parser, "high", HINTS_FIELD_HIGH);
key_parser_add(ctx.parser, "val", HINTS_FIELD_VAL);
rz_key_parser_add(ctx.parser, "arch", HINTS_FIELD_ARCH);
rz_key_parser_add(ctx.parser, "bits", HINTS_FIELD_BITS);
rz_key_parser_add(ctx.parser, "immbase", HINTS_FIELD_IMMBASE);
rz_key_parser_add(ctx.parser, "jump", HINTS_FIELD_JUMP);
rz_key_parser_add(ctx.parser, "fail", HINTS_FIELD_FAIL);
rz_key_parser_add(ctx.parser, "frame", HINTS_FIELD_STACKFRAME);
rz_key_parser_add(ctx.parser, "ptr", HINTS_FIELD_PTR);
rz_key_parser_add(ctx.parser, "nword", HINTS_FIELD_NWORD);
rz_key_parser_add(ctx.parser, "ret", HINTS_FIELD_RET);
rz_key_parser_add(ctx.parser, "newbits", HINTS_FIELD_NEW_BITS);
rz_key_parser_add(ctx.parser, "size", HINTS_FIELD_SIZE);
rz_key_parser_add(ctx.parser, "syntax", HINTS_FIELD_SYNTAX);
rz_key_parser_add(ctx.parser, "optype", HINTS_FIELD_OPTYPE);
rz_key_parser_add(ctx.parser, "opcode", HINTS_FIELD_OPCODE);
rz_key_parser_add(ctx.parser, "toff", HINTS_FIELD_TYPE_OFFSET);
rz_key_parser_add(ctx.parser, "esil", HINTS_FIELD_ESIL);
rz_key_parser_add(ctx.parser, "high", HINTS_FIELD_HIGH);
rz_key_parser_add(ctx.parser, "val", HINTS_FIELD_VAL);
ret = sdb_foreach(db, hints_load_cb, &ctx);
if (!ret) {
SERIALIZE_ERR("hints parsing failed");
RZ_SERIALIZE_ERR(res, "hints parsing failed");
}
beach:
key_parser_free(ctx.parser);
rz_key_parser_free(ctx.parser);
return ret;
}
@ -1919,7 +1917,7 @@ RZ_API void rz_serialize_analysis_classes_save(RZ_NONNULL Sdb *db, RZ_NONNULL Rz
RZ_API bool rz_serialize_analysis_classes_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res) {
if (!sdb_ns(db, "attrs", false)) {
SERIALIZE_ERR("missing attrs namespace");
RZ_SERIALIZE_ERR(res, "missing attrs namespace");
return false;
}
sdb_reset(analysis->sdb_classes);
@ -1948,7 +1946,7 @@ RZ_API bool rz_serialize_analysis_sign_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAna
sdb_copy(db, analysis->sdb_zigns);
Sdb *spaces_db = sdb_ns(db, "spaces", false);
if (!spaces_db) {
SERIALIZE_ERR("missing spaces namespace");
RZ_SERIALIZE_ERR(res, "missing spaces namespace");
return false;
}
if (!rz_serialize_spaces_load(spaces_db, &analysis->zign_spaces, false, res)) {
@ -2016,7 +2014,7 @@ RZ_API bool rz_serialize_analysis_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis
rz_analysis_purge(analysis);
Sdb *subdb;
#define SUB(ns, call) SUB_DO(ns, call, goto beach;)
#define SUB(ns, call) RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, goto beach;)
SUB("xrefs", rz_serialize_analysis_xrefs_load(subdb, analysis, res));
SUB("blocks", rz_serialize_analysis_blocks_load(subdb, analysis, diff_parser, res));

View file

@ -2,8 +2,6 @@
#include <rz_project.h>
#include "../util/serialize_helper.h"
#define RZ_DB_KEY_TYPE "type"
#define RZ_DB_KEY_VERSION "version"
@ -75,7 +73,7 @@ RZ_API RzProjectErr rz_project_load(RzCore *core, RzProject *prj, bool load_bin_
Sdb *core_db = sdb_ns(prj, "core", false);
if (!core_db) {
SERIALIZE_ERR("missing core namespace");
RZ_SERIALIZE_ERR(res, "missing core namespace");
return RZ_PROJECT_ERR_INVALID_CONTENTS;
}
if (!rz_serialize_core_load(core_db, core, load_bin_io, file, res)) {
@ -93,7 +91,7 @@ RZ_API RzProjectErr rz_project_load_file(RzCore *core, const char *file, bool lo
return RZ_PROJECT_ERR_UNKNOWN;
}
if (!sdb_text_load(prj, file)) {
SERIALIZE_ERR("failed to read database file");
RZ_SERIALIZE_ERR(res, "failed to read database file");
return RZ_PROJECT_ERR_FILE;
}
RzProjectErr ret = rz_project_load(core, prj, load_bin_io, file, res);

View file

@ -3,8 +3,6 @@
#include <rz_util/rz_serialize.h>
#include <rz_core.h>
#include "../util/serialize_helper.h"
/*
* SDB Format:
*
@ -49,7 +47,7 @@ RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core,
RZ_NULLABLE const char *prj_file, RZ_NULLABLE RzSerializeResultInfo *res) {
Sdb *subdb;
#define SUB(ns, call) SUB_DO(ns, call, return false;)
#define SUB(ns, call) RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, return false;)
if (load_bin_io) {
SUB("file", file_load(subdb, core, prj_file, res));
@ -60,14 +58,14 @@ RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core,
const char *str = sdb_get(db, "offset", 0);
if (!str || !*str) {
SERIALIZE_ERR("missing offset in core");
RZ_SERIALIZE_ERR(res, "missing offset in core");
return false;
}
core->offset = strtoull(str, NULL, 0);
str = sdb_get(db, "blocksize", 0);
if (!str || !*str) {
SERIALIZE_ERR("missing blocksize in core");
RZ_SERIALIZE_ERR(res, "missing blocksize in core");
return false;
}
ut64 bs = strtoull(str, NULL, 0);
@ -182,7 +180,7 @@ static FileRet try_load_file(RZ_NONNULL RzCore *core, const char *file, RZ_NULLA
RzCoreFile *fh = rz_core_file_open(core, file, RZ_PERM_RX, 0);
if (!fh) {
SERIALIZE_ERR("failed re-open file \"%s\" referenced by project", file);
RZ_SERIALIZE_ERR(res, "failed re-open file \"%s\" referenced by project", file);
return FILE_LOAD_FAIL;
}
rz_core_bin_load(core, file, UT64_MAX);
@ -229,6 +227,6 @@ static bool file_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE c
return r == FILE_SUCCESS;
}
SERIALIZE_ERR("failed to re-locate file referenced by project");
RZ_SERIALIZE_ERR(res, "failed to re-locate file referenced by project");
return false;
}

View file

@ -3,8 +3,6 @@
#include <rz_util/rz_serialize.h>
#include <rz_flag.h>
#include "../util/serialize_helper.h"
#if RZ_FLAG_ZONE_USE_SDB
#error "RZ_FLAG_ZONE_USE_SDB not supported by rz_serialize"
#endif
@ -89,7 +87,7 @@ RZ_API bool rz_serialize_flag_zones_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzList /
rz_list_purge(zones);
bool r = sdb_foreach(db, zone_load_cb, zones);
if (!r) {
SERIALIZE_ERR("failed to parse a flag zone json");
RZ_SERIALIZE_ERR(res, "failed to parse a flag zone json");
}
return r;
}
@ -151,7 +149,7 @@ typedef enum {
typedef struct {
RzFlag *flag;
KeyParser *parser;
RzKeyParser *parser;
} FlagLoadCtx;
static bool flag_load_cb(void *user, const char *k, const char *v) {
@ -171,7 +169,7 @@ static bool flag_load_cb(void *user, const char *k, const char *v) {
bool offset_set = false;
bool size_set = false;
KEY_PARSER_JSON(ctx->parser, json, child, {
RZ_KEY_PARSER_JSON(ctx->parser, json, child, {
case FLAG_FIELD_REALNAME:
if (child->type != RZ_JSON_STRING) {
break;
@ -255,20 +253,20 @@ beach:
}
static bool load_flags(RZ_NONNULL Sdb *flags_db, RZ_NONNULL RzFlag *flag) {
FlagLoadCtx ctx = { flag, key_parser_new() };
FlagLoadCtx ctx = { flag, rz_key_parser_new() };
if (!ctx.parser) {
return false;
}
key_parser_add(ctx.parser, "realname", FLAG_FIELD_REALNAME);
key_parser_add(ctx.parser, "demangled", FLAG_FIELD_DEMANGLED);
key_parser_add(ctx.parser, "offset", FLAG_FIELD_OFFSET);
key_parser_add(ctx.parser, "size", FLAG_FIELD_SIZE);
key_parser_add(ctx.parser, "space", FLAG_FIELD_SPACE);
key_parser_add(ctx.parser, "color", FLAG_FIELD_COLOR);
key_parser_add(ctx.parser, "comment", FLAG_FIELD_COMMENT);
key_parser_add(ctx.parser, "alias", FLAG_FIELD_ALIAS);
rz_key_parser_add(ctx.parser, "realname", FLAG_FIELD_REALNAME);
rz_key_parser_add(ctx.parser, "demangled", FLAG_FIELD_DEMANGLED);
rz_key_parser_add(ctx.parser, "offset", FLAG_FIELD_OFFSET);
rz_key_parser_add(ctx.parser, "size", FLAG_FIELD_SIZE);
rz_key_parser_add(ctx.parser, "space", FLAG_FIELD_SPACE);
rz_key_parser_add(ctx.parser, "color", FLAG_FIELD_COLOR);
rz_key_parser_add(ctx.parser, "comment", FLAG_FIELD_COMMENT);
rz_key_parser_add(ctx.parser, "alias", FLAG_FIELD_ALIAS);
bool r = sdb_foreach(flags_db, flag_load_cb, &ctx);
key_parser_free(ctx.parser);
rz_key_parser_free(ctx.parser);
return r;
}
@ -277,21 +275,21 @@ RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag,
const char *str = sdb_const_get(db, "base", NULL);
if (!str) {
SERIALIZE_ERR("flag base key is missing");
RZ_SERIALIZE_ERR(res, "flag base key is missing");
return false;
}
flag->base = strtoll(str, NULL, 0);
str = sdb_const_get(db, "realnames", 0);
if (!str) {
SERIALIZE_ERR("flag realnames key is missing");
RZ_SERIALIZE_ERR(res, "flag realnames key is missing");
return false;
}
flag->realnames = strtoul(str, NULL, 0) ? true : false;
Sdb *spaces_db = sdb_ns(db, "spaces", false);
if (!spaces_db) {
SERIALIZE_ERR("missing spaces namespace");
RZ_SERIALIZE_ERR(res, "missing spaces namespace");
return false;
}
if (!rz_serialize_spaces_load(spaces_db, &flag->spaces, false, res)) {
@ -300,14 +298,14 @@ RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag,
Sdb *tags_db = sdb_ns(db, "tags", false);
if (!tags_db) {
SERIALIZE_ERR("missing tags namespace");
RZ_SERIALIZE_ERR(res, "missing tags namespace");
return false;
}
sdb_copy(tags_db, flag->tags);
Sdb *zones_db = sdb_ns(db, "zones", false);
if (!zones_db) {
SERIALIZE_ERR("missing zones namespace");
RZ_SERIALIZE_ERR(res, "missing zones namespace");
return false;
}
rz_flag_zone_reset(flag);
@ -317,11 +315,11 @@ RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag,
Sdb *flags_db = sdb_ns(db, "flags", false);
if (!flags_db) {
SERIALIZE_ERR("missing flags sub-namespace");
RZ_SERIALIZE_ERR(res, "missing flags sub-namespace");
return false;
}
if (!load_flags(flags_db, flag)) {
SERIALIZE_ERR("failed to parse a flag json");
RZ_SERIALIZE_ERR(res, "failed to parse a flag json");
return false;
}

View file

@ -1,4 +1,4 @@
/* rizin - LGPL - Copyright 2020 - thestr4ng3r */
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef RZ_SERIALIZE_H
#define RZ_SERIALIZE_H
@ -6,12 +6,109 @@
#include <rz_util/rz_json.h>
#include <rz_list.h>
/**
* \brief Detailed info about a (de)serialization result
*
* This is currently just a list of strings which may be warnings
* or detailed error messages.
*/
typedef RzList RzSerializeResultInfo;
static inline RzSerializeResultInfo *rz_serialize_result_info_new(void) {
return rz_list_newf(free);
}
static inline void rz_serialize_result_info_free(RzSerializeResultInfo *info) {
rz_list_free(info);
}
// Common helpers for writing (de)serialization code
/**
* \brief Push an error to the local RzSerializeResultInfo
* \res RzSerializeInfoResult *
* \param ... printf-style arguments to be pushed as the error to res
*/
#define RZ_SERIALIZE_ERR(res, ...) \
do { \
if (res) { \
rz_list_push(res, rz_str_newf(__VA_ARGS__)); \
} \
} while (0)
/**
* \brief Hashtable-based key parser to prevent strcmp chains
*
* This enables string values to be used in a switch/case-like
* fashion.
*/
typedef HtPP RzKeyParser;
static inline RzKeyParser *rz_key_parser_new(void) {
return ht_pp_new0();
}
static inline void rz_key_parser_free(RzKeyParser *parser) {
ht_pp_free(parser);
}
static inline void rz_key_parser_add(RzKeyParser *parser, const char *key, int val) {
ht_pp_insert(parser, key, (void *)(size_t)val);
}
#define RZ_KEY_PARSER_UNKNOWN -1
/**
* \brief switch-like macro over RzKeyParser values
* \param parser RzKeyParser *
* \param key const char *
*/
#define RZ_KEY_PARSER_SWITCH(parser, key) \
bool key_parser_found = false; \
int key_parser_v = (int)(size_t)ht_pp_find(parser, key, &key_parser_found); \
if (!key_parser_found) { \
key_parser_v = RZ_KEY_PARSER_UNKNOWN; \
} \
switch (key_parser_v)
/**
* \brief Iterate over all keys in a json object and call RZ_KEY_PARSER_SWITCH on each
* \param parser RzKeyParser *
* \param json RzJson *
* \param child var name for the `RzJson *child`
* \param body code block with cases
*/
#define RZ_KEY_PARSER_JSON(parser, json, child, body) \
if (json->type == RZ_JSON_OBJECT) { \
for (RJson *child = json->children.first; child; child = child->next) { \
RZ_KEY_PARSER_SWITCH(parser, child->key) { body } \
} \
}
/**
* \brief Get an sdb sub-namespace and evaluate `call` or fail
* \param db Sdb * the Sdb from which to take the sub-namespace
* \param subdb Sdb * where to put the sub-namespace
* \param res RzSerializeResult * where to push an error on failure
* \param ns const char *
* \param call function call
* \param rip code to execute if the function failed
*
* Example:
*
* Sdb *subdb;
* RZ_SERIALIZE_SUB_DO(db, subdb, res, "files",
* rz_serialize_io_files_load(subdb, io, res), return false;)
*
*/
#define RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, rip) \
subdb = sdb_ns(db, ns, false); \
if (!subdb) { \
RZ_SERIALIZE_ERR(res, "missing " ns " namespace"); \
rip \
} \
if (!(call)) { \
rip \
}
#endif //RZ_SERIALIZE_H

View file

@ -3,8 +3,6 @@
#include <rz_util/rz_serialize.h>
#include <rz_io.h>
#include "../util/serialize_helper.h"
#include <errno.h>
/*
@ -103,7 +101,7 @@ RZ_API bool rz_serialize_io_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzIO *io, RZ_NUL
// TODO: purge RzIO?
bool ret = false;
Sdb *subdb;
#define SUB(ns, call) SUB_DO(ns, call, goto beach;)
#define SUB(ns, call) RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, goto beach;)
SUB("files", rz_serialize_io_files_load(subdb, io, res));
#undef SUB
ret = true;

View file

@ -1,56 +0,0 @@
#ifndef RZ_SERIALIZE_UTIL_H
#define RZ_SERIALIZE_UTIL_H
#include <rz_util/rz_str.h>
#define SERIALIZE_ERR(...) \
do { \
if (res) { \
rz_list_push(res, rz_str_newf(__VA_ARGS__)); \
} \
} while (0)
// Hashtable-based key parser to prevent strcmp chains
typedef HtPP KeyParser;
static inline KeyParser *key_parser_new(void) {
return ht_pp_new0();
}
static inline void key_parser_free(KeyParser *parser) {
ht_pp_free(parser);
}
static inline void key_parser_add(KeyParser *parser, const char *key, int val) {
ht_pp_insert(parser, key, (void *)(size_t)val);
}
#define KEY_PARSER_UNKNOWN -1
#define KEY_PARSER_SWITCH(parser, key) \
bool key_parser_found = false; \
int key_parser_v = (int)(size_t)ht_pp_find(parser, key, &key_parser_found); \
if (!key_parser_found) { \
key_parser_v = KEY_PARSER_UNKNOWN; \
} \
switch (key_parser_v)
#define KEY_PARSER_JSON(parser, json, child, body) \
if (json->type == RZ_JSON_OBJECT) { \
for (RJson *child = json->children.first; child; child = child->next) { \
KEY_PARSER_SWITCH(parser, child->key) { body } \
} \
}
#define SUB_DO(ns, call, rip) \
subdb = sdb_ns(db, ns, false); \
if (!subdb) { \
SERIALIZE_ERR("missing " ns " namespace"); \
rip \
} \
if (!(call)) { \
rip \
}
#endif //RZ_SERIALIZE_UTIL_H

View file

@ -2,8 +2,6 @@
#include <rz_util/rz_serialize.h>
#include <rz_util/rz_spaces.h>
#include "../util/serialize_helper.h"
/*
* SDB Format:
*
@ -57,7 +55,7 @@ RZ_API bool rz_serialize_spaces_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzSpaces *sp
spaces->name = sdb_get(db, KEY_NAME, NULL);
if (!spaces->name) {
spaces->name = old_name;
SERIALIZE_ERR("failed to get spaces name from db");
RZ_SERIALIZE_ERR(res, "failed to get spaces name from db");
return false;
}
free(old_name);
@ -67,33 +65,33 @@ RZ_API bool rz_serialize_spaces_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzSpaces *sp
Sdb *db_spaces = sdb_ns(db, KEY_SPACES, false);
if (!db_spaces) {
SERIALIZE_ERR("failed to get spaces sub-namespace");
RZ_SERIALIZE_ERR(res, "failed to get spaces sub-namespace");
return false;
}
sdb_foreach(db_spaces, foreach_space_cb, spaces);
char *stack_json_str = sdb_get(db, KEY_SPACESTACK, NULL);
if (!stack_json_str) {
SERIALIZE_ERR("spacestack is missing");
RZ_SERIALIZE_ERR(res, "spacestack is missing");
return false;
}
bool ret = true;
RJson *stack_json = rz_json_parse(stack_json_str);
if (!stack_json) {
SERIALIZE_ERR("failed to parse stackspace json");
RZ_SERIALIZE_ERR(res, "failed to parse stackspace json");
ret = false;
goto beach;
}
if (stack_json->type != RZ_JSON_ARRAY) {
SERIALIZE_ERR("stackspace json is not an array");
RZ_SERIALIZE_ERR(res, "stackspace json is not an array");
ret = false;
goto beach;
}
RJson *stack_element;
for (stack_element = stack_json->children.first; stack_element; stack_element = stack_element->next) {
if (stack_element->type != RZ_JSON_STRING) {
SERIALIZE_ERR("stackspace element is not a string");
RZ_SERIALIZE_ERR(res, "stackspace element is not a string");
ret = false;
goto beach;
}