Add new Projects Implementation (#12)

This commit is contained in:
Florian Märkl 2020-10-26 15:17:33 +01:00 committed by GitHub
parent 404d5b23f5
commit 4e18226c8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 5602 additions and 1805 deletions

View file

@ -36,6 +36,7 @@ OBJLIBS+=esil_sources.o esil_interrupt.o esil_cfg.o
OBJLIBS+=esil_stats.o esil_trace.o flirt.o labels.o
OBJLIBS+=esil2reil.o pin.o vtable.o rtti.o
OBJLIBS+=rtti_msvc.o rtti_itanium.o jmptbl.o function.o
OBJLIBS+=serialize_anal.o
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/xtensa-modules.o
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/xtensa-isa.o
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/elf32-xtensa.o

View file

@ -38,6 +38,7 @@ rz_anal_sources = [
'var.c',
'vtable.c',
'xrefs.c',
'serialize_anal.c',
'p/anal_6502.c',
'p/anal_6502_cs.c',
'p/anal_8051.c',

2079
librz/anal/serialize_anal.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -19,13 +19,13 @@ DLLS+=CSPMAN DCIMAN DDEML DESKCP16 DIBENG DISPDIB DISPLAY DSKMAINT
DLLS+=ENABLE3 FAXCODEC GDI INET16 IOSCLASS KERNEL KEYBOARD LZEXPAND
DLLS+=MAINCP16 MAPI MAPIU MAPIX MCIAVI MCICDA MCIMIDI MCIOLE
DLLS+=MCIWAVE MIDIMAP ML3XEC16 MMCI MMSYSTEM MODEM MODEMUI MOUSE
DLLS+=MSACM MSACMMAP MSDOS MSDOSD MSGSRV32 MSJSTICK MSMIXMGR MSPCIC
DLLS+=MSACM MSACMMAP MSDOS MSDOSD MSJSTICK MSMIXMGR MSPCIC
DLLS+=MSPRINT MSTCP MSVIDEO NETAPI NETCPL NETDI NETOS NETWARE
DLLS+=NW16 OLE2 OLE2CONV OLE2DISP OLE2NLS OLECLI OLESVR PIFMGR
DLLS+=PKPD PMSPL POWER RASAPI16 RNASETUP RSRC16 SB16SND SBFM
DLLS+=SETUP4 SETUPX SHELL SOUND SPOOLER STORAGE SYSCLASS SYSDETMG
DLLS+=SYSDM SYSEDIT SYSTEM SYSTHUNK TAPI TAPIADDR TAPIEXE
DLLS+=TAPIINI TOOLHELP TYPELIB UMDM16 USER VER WHLP16T WIN32S16
DLLS+=SYSDM SYSEDIT SYSTEM SYSTHUNK TAPI TAPIADDR
DLLS+=TOOLHELP TYPELIB UMDM16 USER VER WHLP16T WIN32S16
DLLS+=WIN87EM WINASPI WINNET16 WINOLDAP WINSOCK WINSPL16 WPSAPD WPSUNI
DLLS+=WPSUNIRE WSASRV
DLL_SDB=$(addsuffix .sdb,$(addprefix dll/,$(DLLS)))

View file

@ -89,7 +89,6 @@ sdb_files = [
'MSACMMAP',
'MSDOS',
'MSDOSD',
'MSGSRV32',
'MSJSTICK',
'MSMIXMGR',
'MSPCIC',
@ -131,8 +130,6 @@ sdb_files = [
'SYSTHUNK',
'TAPI',
'TAPIADDR',
'TAPIEXE',
'TAPIINI',
'TOOLHELP',
'TYPELIB',
'UMDM16',

View file

@ -2,6 +2,6 @@ include ../config.mk
NAME=rz_config
RZ_DEPS=rz_util
OBJS=config.o callback.o hold.o
OBJS=config.o callback.o hold.o serialize_config.o
include ../rules.mk

View file

@ -2,6 +2,7 @@ rz_config_sources = [
'callback.c',
'config.c',
'hold.c',
'serialize_config.c'
]
rz_config = library('rz_config', rz_config_sources,

View file

@ -0,0 +1,39 @@
/* radare - LGPL - Copyright 2019 - thestr4ng3r */
#include <rz_util/rz_serialize.h>
#include <rz_config.h>
/*
*
* RzConfig isn't completely serialized, only the values.
*
* SDB Format:
*
* /
* <name>=<value>
* ...
*
*/
RZ_API void rz_serialize_config_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config) {
RzListIter *iter;
RzConfigNode *node;
rz_list_foreach (config->nodes, iter, node) {
sdb_set (db, node->name, node->value, 0);
}
}
static bool load_config_cb(void *user, const char *k, const char *v) {
RzConfig *config = user;
RzConfigNode *node = rz_config_node_get (config, k);
if (!node) {
return 1;
}
rz_config_set (config, k, v);
return 1;
}
RZ_API bool rz_serialize_config_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config, RZ_NULLABLE RzSerializeResultInfo *res) {
sdb_foreach (db, load_config_cb, config);
return true;
}

View file

@ -11,7 +11,7 @@ OBJS+=fortune.o hack.o vasm.o patch.o cbin.o corelog.o rtr.o cmd_api.o
OBJS+=carg.o canal.o project.o gdiff.o casm.o disasm.o cplugin.o
OBJS+=vmenus.o vmenus_graph.o vmenus_zigns.o zdiff.o citem.o
OBJS+=task.o panels.o pseudo.o vmarks.o anal_tp.o anal_objc.o blaze.o cundo.o
OBJS+=cannotated_code.o
OBJS+=cannotated_code.o serialize_core.o
CFLAGS+=-I../../shlr/heap/include
CFLAGS+=-I../../shlr/tree-sitter/lib/include -I../../shlr/rizin-shell-parser/src/tree_parser

View file

@ -3221,12 +3221,7 @@ RZ_API int rz_core_config_init(RzCore *core) {
SETCB ("bin.verbose", "false", &cb_binverbose, "Show RzBin warnings when loading binaries");
/* prj */
SETPREF ("prj.name", "", "Name of current project");
SETBPREF ("prj.files", "false", "Save the target binary inside the project directory");
SETBPREF ("prj.git", "false", "Every project is a git repo and saving is committing");
SETBPREF ("prj.zip", "false", "Use ZIP format for project files");
SETBPREF ("prj.gpg", "false", "TODO: Encrypt project with GnuPGv2");
SETBPREF ("prj.simple", "false", "Use simple project saving style (functions, comments, options)");
SETPREF ("prj.file", "", "Path of the currently opened project");
/* cfg */
SETBPREF ("cfg.r2wars", "false", "Enable some tweaks for the r2wars game");

View file

@ -2117,7 +2117,6 @@ static struct autocomplete_flag_map_t {
{ "$flsp", "shows known flag-spaces hints", RZ_CORE_AUTOCMPLT_FLSP },
{ "$zign", "shows known zignatures hints", RZ_CORE_AUTOCMPLT_ZIGN },
{ "$eval", "shows known evals hints", RZ_CORE_AUTOCMPLT_EVAL },
{ "$prjt", "shows known projects hints", RZ_CORE_AUTOCMPLT_PRJT },
{ "$mins", NULL, RZ_CORE_AUTOCMPLT_MINS },
{ "$brkp", "shows known breakpoints hints", RZ_CORE_AUTOCMPLT_BRKP },
{ "$macro", NULL, RZ_CORE_AUTOCMPLT_MACR },
@ -7159,7 +7158,7 @@ RZ_API void rz_core_cmd_init(RzCore *core) {
{ "L", "manage dynamically loaded plugins", cmd_plugins, NULL, &L_help },
{ "o", "open or map file", cmd_open, cmd_open_init, &o_help },
{ "p", "print current block", cmd_print, cmd_print_init, &p_help },
{ "P", "project", cmd_project, cmd_project_init, &P_help },
{ "P", "project", NULL, cmd_project_init, NULL, &P_group_help, RZ_CMD_DESC_TYPE_GROUP},
{ "q", "exit program session", cmd_quit, cmd_quit_init, &q_help },
{ "Q", "alias for q!", cmd_Quit, NULL, &Q_help },
{ ":", "long commands starting with :", cmd_colon, NULL, &colon_help },

View file

@ -383,8 +383,18 @@ const RzCmdDescHelp p_help = {
.summary = "print commands",
};
const RzCmdDescHelp P_help = {
.summary = "project management utilities",
const RzCmdDescHelp P_group_help = {
.summary = "project management",
};
const RzCmdDescHelp Ps_help = {
.summary = "save a project",
.args_str = " [project.rzdb]"
};
const RzCmdDescHelp Po_help = {
.summary = "load a project",
.args_str = " [project.rzdb]"
};
const RzCmdDescHelp q_help = {

View file

@ -43,7 +43,9 @@ extern const RzCmdDescHelp L_help;
extern const RzCmdDescHelp m_help;
extern const RzCmdDescHelp o_help;
extern const RzCmdDescHelp p_help;
extern const RzCmdDescHelp P_help;
extern const RzCmdDescHelp P_group_help;
extern const RzCmdDescHelp Ps_help;
extern const RzCmdDescHelp Po_help;
extern const RzCmdDescHelp q_help;
extern const RzCmdDescHelp Q_help;
extern const RzCmdDescHelp colon_help;

View file

@ -1,244 +1,37 @@
/* radare - LGPL - Copyright 2009-2017 - pancake */
#include "rz_config.h"
#include "rz_core.h"
#include "rz_util.h"
#include <rz_project.h>
static const char *help_msg_P[] = {
"Usage:", "P[?osi] [file]", "Project management",
"P", "", "list all projects",
"Pc", " [file]", "show project script to console",
"Pd", " [file]", "delete project",
"Pi", " [file]", "show project information",
"Pn", "[j]", "show project notes (Pnj for json)",
"Pn", " [base64]", "set notes text",
"Pn", " -", "edit notes with cfg.editor",
"Po", " [file]", "open project",
"Ps", " [file]", "save project",
"PS", " [file]", "save script file",
"P-", " [file]", "delete project (alias for Pd)",
"NOTE:", "", "See 'e??prj.'",
"NOTE:", "", "project are stored in " RZ_JOIN_2_PATHS ("~", RZ_HOME_PROJECTS),
NULL
};
static RzCmdStatus Ps_handler(RzCore *core, int argc, const char **argv) {
if (argc != 2) {
return RZ_CMD_STATUS_WRONG_ARGS;
}
RzProjectErr err = rz_project_save_file (core, argv[1]);
if (err != RZ_PROJECT_ERR_SUCCESS) {
eprintf ("Failed to save project: %s\n", rz_project_err_message (err));
}
return RZ_CMD_STATUS_OK;
}
static const char *help_msg_Pn[] = {
"Usage:", "Pn[j-?] [...]", "Project Notes",
"Pn", "", "show project notes",
"Pn", " -", "edit notes with cfg.editor",
"Pn-", "", "delete notes",
"Pn-", "str", "delete lines matching /str/ in notes",
"Pn+", "str", "append one line to the notes",
"Pnj", "", "show notes in base64",
"Pnj", " [base64]", "set notes in base64",
"Pnx", "", "run project note commands",
NULL
};
static RzCmdStatus Po_handler(RzCore *core, int argc, const char **argv) {
if (argc != 2) {
return RZ_CMD_STATUS_WRONG_ARGS;
}
RzSerializeResultInfo *res = rz_serialize_result_info_new ();
RzProjectErr err = rz_project_load_file (core, argv[1], res);
if (err != RZ_PROJECT_ERR_SUCCESS) {
eprintf ("Failed to load project: %s\n", rz_project_err_message (err));
RzListIter *it;
char *s;
rz_list_foreach (res, it, s) {
eprintf (" %s\n", s);
}
}
rz_serialize_result_info_free (res);
return RZ_CMD_STATUS_OK;
}
static void cmd_project_init(RzCore *core, RzCmdDesc *parent) {
DEPRECATED_DEFINE_CMD_DESCRIPTOR (core, P);
DEPRECATED_DEFINE_CMD_DESCRIPTOR (core, Pn);
}
static int cmd_project(void *data, const char *input) {
RzCore *core = (RzCore *) data;
const char *file, *arg;
const char *fileproject = rz_config_get (core->config, "prj.name");
char *str = NULL;
if (!input) {
return false;
}
str = strdup (fileproject);
arg = strchr (input, ' ');
if (arg) {
arg++;
} else {
if (*input) {
arg = input + 1;
if (*arg == '&') {
arg++;
}
}
}
file = arg;
switch (input[0]) {
case 'c':
if (input[1] == ' ') {
rz_core_project_cat (core, input + 2);
} else {
eprintf ("Usage: Pc [prjname]\n");
}
break;
case 'o':
// if (rz_file_is_regular (file))
if (input[1] == '&') {
rz_core_cmdf (core, "& Po %s", file);
} else if (input[1]) {
rz_core_project_open (core, file, false);
} else {
if (file && *file) {
rz_cons_println (file);
}
}
break;
case 'd':
case '-':
rz_core_project_delete (core, file);
break;
case 's':
if (!file || !file[0]) { /* if no argument specified use current project */
file = str;
}
if (rz_core_project_save (core, file)) {
rz_cons_println (file);
}
break;
case 'S':
if (input[1] == ' ') {
rz_core_project_save_script (core, input + 2, RZ_CORE_PRJ_ALL);
} else {
eprintf ("Usage: PS [file]\n");
}
break;
case 'n': // "Pn"
if (input[1] == '?') {
rz_core_cmd_help (core, help_msg_Pn);
} else if (!fileproject || !*fileproject) {
eprintf ("No project\n");
} else {
switch (input[1]) {
case '-': // "Pn-"
/* remove lines containing specific words */
{
FILE *fd = rz_sandbox_fopen (str, "w");
if (!fd) {
eprintf ("Cannot open %s\n", str);
} else {
char *str = rz_core_project_notes_file (core, fileproject);
char *data = rz_file_slurp (str, NULL);
int del = 0;
if (data) {
char *ptr, *nl;
for (ptr = data; ptr; ptr = nl) {
nl = strchr (ptr, '\n');
if (nl) {
*nl++ = 0;
if (strstr (ptr, input + 2)) {
del++;
} else {
fprintf (fd, "%s\n", ptr);
}
}
}
free (data);
}
if (del > 0) {
eprintf ("Deleted %d lines\n", del);
}
free (str);
fclose (fd);
}
}
break;
case ' ': // "Pn "
if (input[2] == '-') {
char *str = rz_core_project_notes_file (core, fileproject);
// edit with cfg.editor
const char *editor = rz_config_get (core->config, "cfg.editor");
if (str && *str && editor && *editor) {
rz_sys_cmdf ("%s %s", editor, str);
} else {
eprintf ("No cfg.editor configured\n");
}
free (str);
} else {
// char *str = rz_core_project_notes_file (core, fileproject);
// append line to project notes
char *str = rz_core_project_notes_file (core, fileproject);
char *data = rz_file_slurp (str, NULL);
FILE *fd = rz_sandbox_fopen (str, "a");
if (fd) {
fprintf (fd, "%s\n", input + 2);
fclose (fd);
}
free (str);
free (data);
}
break;
case '+': // "Pn+"
{
char *str = rz_core_project_notes_file (core, fileproject);
char *data = rz_file_slurp (str, NULL);
data = rz_str_append (data, input + 2);
data = rz_str_append (data, "\n");
rz_file_dump (str, (const ut8*)data, strlen (data), false);
free (data);
free (str);
}
break;
case 'j': // "Pnj"
if (!input[2]) {
size_t len = 0;
/* get base64 string */
char *str = rz_core_project_notes_file (core, fileproject);
if (str) {
char *data = rz_file_slurp (str, &len);
char *res = rz_base64_encode_dyn (data, (int)len);
if (res) {
rz_cons_println (res);
free (res);
}
free (data);
free (str);
}
} else if (input[2] == ' ') {
/* set base64 string */
ut8 *data = rz_base64_decode_dyn (input + 3, -1);
if (data) {
char *str = rz_core_project_notes_file (core, fileproject);
if (str) {
rz_file_dump (str, data, strlen ((const char *) data), 0);
free (str);
}
free (data);
}
} else {
eprintf ("Usage: `Pnj` or `Pnj ...`\n");
}
break;
case 'x': // "Pnx"
rz_core_project_execute_cmds (core, fileproject);
break;
case 0: // "Pn"
{
char *str = rz_core_project_notes_file (core, fileproject);
char *data = rz_file_slurp (str, NULL);
if (data) {
rz_cons_println (data);
free (data);
}
free (str);
}
break;
}
}
break;
case 'i':
if (file && *file) {
char *prjName = rz_core_project_info (core, file);
rz_cons_println (prjName);
free (prjName);
}
break;
case 0:
case 'j':
rz_core_project_list (core, input[0]);
break;
default:
rz_core_cmd_help (core, help_msg_P);
break;
}
free (str);
return true;
DEFINE_CMD_ARGV_DESC (core, Ps, parent);
DEFINE_CMD_ARGV_DESC (core, Po, parent);
}

View file

@ -1216,25 +1216,6 @@ static void autocomplete_evals(RzCore *core, RLineCompletion *completion, const
}
}
static void autocomplete_project(RzCore *core, RLineCompletion *completion, const char* str) {
rz_return_if_fail (str);
char *foo, *projects_path = rz_file_abspath (rz_config_get (core->config, "dir.projects"));
RzList *list = rz_sys_dir (projects_path);
RzListIter *iter;
int n = strlen (str);
if (projects_path) {
rz_list_foreach (list, iter, foo) {
if (rz_core_is_project (core, foo)) {
if (!strncmp (foo, str, n)) {
rz_line_completion_push (completion, foo);
}
}
}
free (projects_path);
rz_list_free (list);
}
}
static void autocomplete_minus(RzCore *core, RLineCompletion *completion, const char *str) {
rz_return_if_fail (str);
int count;
@ -1547,9 +1528,6 @@ static bool find_autocomplete(RzCore *core, RLineCompletion *completion, RLineBu
case RZ_CORE_AUTOCMPLT_EVAL:
autocomplete_evals (core, completion, p);
break;
case RZ_CORE_AUTOCMPLT_PRJT:
autocomplete_project (core, completion, p);
break;
case RZ_CORE_AUTOCMPLT_MINS:
autocomplete_minus (core, completion, p);
break;
@ -2257,10 +2235,7 @@ static void __init_autocomplete_default (RzCore* core) {
"idp", "idpi", "L", "obf", "o+", "oc", "rz", "rz_bin", "rz_asm", "rz_hash", "rz_ax",
"rz_find", "cd", "ls", "on", "op", "wf", "rm", "wF", "wp", "Sd", "Sl", "to", "pm",
"/m", "zos", "zfd", "zfs", "zfz", "cat", "wta", "wtf", "wxf", "dml", "vi",
"less", "head", "tail", NULL
};
const char *projs[] = {
"Pc", "Pd", "Pi", "Po", "Ps", "P-", NULL
"less", "head", "tail", "Ps", "Pl", NULL
};
__foreach (core, flags, RZ_CORE_AUTOCMPLT_FLAG);
__foreach (core, seeks, RZ_CORE_AUTOCMPLT_SEEK);
@ -2268,7 +2243,6 @@ static void __init_autocomplete_default (RzCore* core) {
__foreach (core, evals, RZ_CORE_AUTOCMPLT_EVAL);
__foreach (core, breaks, RZ_CORE_AUTOCMPLT_BRKP);
__foreach (core, files, RZ_CORE_AUTOCMPLT_FILE);
__foreach (core, projs, RZ_CORE_AUTOCMPLT_PRJT);
rz_core_autocomplete_add (core->autocomplete, "-", RZ_CORE_AUTOCMPLT_MINS, true);
rz_core_autocomplete_add (core->autocomplete, "zs", RZ_CORE_AUTOCMPLT_ZIGN, true);

View file

@ -65,15 +65,16 @@ rz_core_sources = [
'yank.c',
'p/core_a2f.c',
'p/core_java.c',
'cannotated_code.c'
'cannotated_code.c',
'serialize_core.c'
]
rz_core_inc = []
if host_machine.system() != 'windows'
rz_core_inc += ['../../shlr/heap/include']
else
rz_core_sources += 'windows_heap.c'
rz_core_inc += ['../../shlr/heap/include/rz_windows']
rz_core_sources += 'windows_heap.c'
rz_core_inc += ['../../shlr/heap/include/rz_windows']
endif
rz_core_inc = [platform_inc, include_directories(rz_core_inc)]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,64 @@
/* radare - LGPL - Copyright 2019 - thestr4ng3r */
#include <rz_util/rz_serialize.h>
#include <rz_core.h>
#include "../util/serialize_helper.h"
/*
* SDB Format:
*
* /
* /config => see config.c
* /flags => see flag.c
* /anal => see anal.c
* offset=<offset>
* blocksize=<blocksize>
*/
RZ_API void rz_serialize_core_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core) {
rz_serialize_config_save (sdb_ns (db, "config", true), core->config);
rz_serialize_flag_save (sdb_ns (db, "flags", true), core->flags);
rz_serialize_anal_save (sdb_ns (db, "anal", true), core->anal);
char buf[0x20];
if (snprintf (buf, sizeof (buf), "0x%"PFMT64x, core->offset) < 0) {
return;
}
sdb_set (db, "offset", buf, 0);
if (snprintf (buf, sizeof (buf), "0x%"PFMT32x, core->blocksize) < 0) {
return;
}
sdb_set (db, "blocksize", buf, 0);
}
RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE RzSerializeResultInfo *res) {
Sdb *subdb;
#define SUB(ns, call) SUB_DO(ns, call, return false;)
SUB ("config", rz_serialize_config_load (subdb, core->config, res));
SUB ("flags", rz_serialize_flag_load (subdb, core->flags, res));
SUB ("anal", rz_serialize_anal_load (subdb, core->anal, res));
const char *str = sdb_get (db, "offset", 0);
if (!str || !*str) {
SERIALIZE_ERR ("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");
return false;
}
ut64 bs = strtoull (str, NULL, 0);
rz_core_block_size (core, (int)bs);
// handled by config already:
// cfglog, cmdrepeat, cmdtimes
return true;
}

View file

@ -395,7 +395,7 @@ static void serialize_checkpoints(Sdb *db, RzVector *checkpoints) {
* "data":"<base64>", "perm":<int>, "user":<int>, "shared":<bool>}
*
* Notes:
* - This mostly follows r2db-style serialization and uses sdb_json as the parser.
* - This mostly follows rz-db-style serialization and uses sdb_json as the parser.
*/
RZ_API void rz_debug_session_serialize(RzDebugSession *session, Sdb *db) {
sdb_num_set (db, "maxcnum", session->maxcnum, 0);

View file

@ -2,6 +2,6 @@ include ../config.mk
NAME=rz_flag
RZ_DEPS=rz_util
OBJS=flag.o zones.o tags.o
OBJS=flag.o zones.o tags.o serialize_flag.o
include ../rules.mk

View file

@ -1,7 +1,8 @@
rz_flag_sources = [
'flag.c',
'tags.c',
'zones.c'
'zones.c',
'serialize_flag.c'
]
rz_flag = library('rz_flag', rz_flag_sources,

329
librz/flag/serialize_flag.c Normal file
View file

@ -0,0 +1,329 @@
/* radare - LGPL - Copyright 2019 - thestr4ng3r */
#include <rz_util/rz_serialize.h>
#include <rz_flag.h>
#include "../util/serialize_helper.h"
#if R_FLAG_ZONE_USE_SDB
#error "R_FLAG_ZONE_USE_SDB not supported by rz_serialize"
#endif
/*
* SDB Format:
*
* /
* base=<base>
* realnames=<realnames?"1":"0">
* /spaces
* see spaces.c
* /tags
* like RzFlag.tags
* /zones
* <zone name>={"from":<from>,"to":<to>}
* /flags
* <flag name>={"realname":<str>,"demangled":<bool>,"offset":<uint>,"size":<uint>,"space":<str>,"color":<str>,"comment":<str>,"alias":<str>}
*
*/
RZ_API void rz_serialize_flag_zones_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzList/*<RzFlagZoneItem *>*/ *zones) {
RzListIter *it;
RzFlagZoneItem *item;
rz_list_foreach (zones, it, item) {
PJ *j = pj_new ();
if (!j) {
return;
}
pj_o (j);
pj_kn (j, "from", item->from);
pj_kn (j, "to", item->to);
pj_end (j);
sdb_set (db, item->name, pj_string (j), 0);
pj_free (j);
}
}
static bool zone_load_cb(void *user, const char *k, const char *v) {
RzList *list = user;
char *json_str = strdup (v);
if (!json_str) {
return true;
}
RJson *json = rz_json_parse (json_str);
if (!json) {
free (json_str);
return true;
}
if (json->type != RZ_JSON_OBJECT) {
goto beach;
}
const RJson *child;
RzFlagZoneItem *item = RZ_NEW0 (RzFlagZoneItem);
if (!item) {
goto beach;
}
item->name = strdup (k);
if (!item->name) {
free (item);
goto beach;
}
for (child = json->children.first; child; child = child->next) {
if (child->type != RZ_JSON_INTEGER) {
continue;
}
if (strcmp (child->key, "from") == 0) {
item->from = child->num.u_value;
} else if (strcmp (child->key, "to") == 0) {
item->to = child->num.u_value;
}
}
rz_list_append (list, item);
beach:
rz_json_free (json);
free (json_str);
return true;
}
RZ_API bool rz_serialize_flag_zones_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzList/*<RzFlagZoneItem *>*/ *zones, RZ_NULLABLE RzSerializeResultInfo *res) {
rz_return_val_if_fail (zones, false);
rz_list_purge (zones);
bool r = sdb_foreach (db, zone_load_cb, zones);
if (!r) {
SERIALIZE_ERR ("failed to parse a flag zone json");
}
return r;
}
static bool flag_save_cb(RzFlagItem *flag, void *user) {
Sdb *db = user;
PJ *j = pj_new ();
if (!j) {
return false;
}
pj_o (j);
if (flag->realname) {
pj_ks (j, "realname", flag->realname);
}
pj_kb (j, "demangled", flag->demangled);
pj_kn (j, "offset", flag->offset);
pj_kn (j, "size", flag->size);
if (flag->space) {
pj_ks (j, "space", flag->space->name);
}
if (flag->color) {
pj_ks (j, "color", flag->color);
}
if (flag->comment) {
pj_ks (j, "comment", flag->comment);
}
if (flag->alias) {
pj_ks (j, "alias", flag->alias);
}
pj_end (j);
sdb_set (db, flag->name, pj_string (j), 0);
pj_free (j);
return true;
}
RZ_API void rz_serialize_flag_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag) {
rz_serialize_spaces_save (sdb_ns (db, "spaces", true), &flag->spaces);
char buf[32];
if (snprintf (buf, sizeof (buf), "%"PFMT64d, flag->base) < 0) {
return;
}
sdb_set (db, "base", buf, 0);
sdb_set (db, "realnames", flag->realnames ? "1" : "0", 0);
sdb_copy (flag->tags, sdb_ns (db, "tags", true));
rz_serialize_flag_zones_save (sdb_ns (db, "zones", true), flag->zones);
rz_flag_foreach (flag, flag_save_cb, sdb_ns (db, "flags", true));
}
typedef enum {
FLAG_FIELD_REALNAME,
FLAG_FIELD_DEMANGLED,
FLAG_FIELD_OFFSET,
FLAG_FIELD_SIZE,
FLAG_FIELD_SPACE,
FLAG_FIELD_COLOR,
FLAG_FIELD_COMMENT,
FLAG_FIELD_ALIAS
} FlagField;
typedef struct {
RzFlag *flag;
KeyParser *parser;
} FlagLoadCtx;
static bool flag_load_cb(void *user, const char *k, const char *v) {
FlagLoadCtx *ctx = user;
char *json_str = strdup (v);
if (!json_str) {
return true;
}
RJson *json = rz_json_parse (json_str);
if (!json || json->type != RZ_JSON_OBJECT) {
free (json_str);
return false;
}
RzFlagItem proto = { 0 };
bool offset_set = false;
bool size_set = false;
KEY_PARSER_JSON (ctx->parser, json, child, {
case FLAG_FIELD_REALNAME:
if (child->type != RZ_JSON_STRING) {
break;
}
proto.realname = (char *)child->str_value;
break;
case FLAG_FIELD_DEMANGLED:
if (child->type != RZ_JSON_BOOLEAN) {
break;
}
proto.demangled = child->num.u_value != 0;
break;
case FLAG_FIELD_OFFSET:
if (child->type != RZ_JSON_INTEGER) {
break;
}
proto.offset = child->num.u_value;
offset_set = true;
break;
case FLAG_FIELD_SIZE:
if (child->type != RZ_JSON_INTEGER) {
break;
}
proto.size = child->num.u_value;
size_set = true;
break;
case FLAG_FIELD_SPACE:
if (child->type != RZ_JSON_STRING) {
break;
}
proto.space = rz_flag_space_get (ctx->flag, child->str_value);
break;
case FLAG_FIELD_COLOR:
if (child->type != RZ_JSON_STRING) {
break;
}
proto.color = (char *)child->str_value;
break;
case FLAG_FIELD_COMMENT:
if (child->type != RZ_JSON_STRING) {
break;
}
proto.comment = (char *)child->str_value;
break;
case FLAG_FIELD_ALIAS:
if (child->type != RZ_JSON_STRING) {
break;
}
proto.alias = (char *)child->str_value;
break;
default:
break;
});
bool res = true;
if (!offset_set || !size_set) {
res = false;
goto beach;
}
RzFlagItem *item = rz_flag_set (ctx->flag, k, proto.offset - ctx->flag->base, proto.size);
if (proto.realname) {
rz_flag_item_set_realname (item, proto.realname);
}
item->demangled = proto.demangled;
item->space = proto.space;
if (proto.color) {
rz_flag_item_set_color (item, proto.color);
}
if (proto.comment) {
rz_flag_item_set_comment (item, proto.comment);
}
if(proto.alias) {
rz_flag_item_set_alias (item, proto.alias);
}
beach:
rz_json_free (json);
free (json_str);
return res;
}
static bool load_flags(RZ_NONNULL Sdb *flags_db, RZ_NONNULL RzFlag *flag) {
FlagLoadCtx ctx = { flag, 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);
bool r = sdb_foreach (flags_db, flag_load_cb, &ctx);
key_parser_free (ctx.parser);
return r;
}
RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag, RZ_NULLABLE RzSerializeResultInfo *res) {
rz_flag_unset_all (flag);
const char *str = sdb_const_get (db, "base", NULL);
if (!str) {
SERIALIZE_ERR ("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");
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");
return false;
}
if (!rz_serialize_spaces_load (spaces_db, &flag->spaces, false, res)) {
return false;
}
Sdb *tags_db = sdb_ns (db, "tags", false);
if (!tags_db) {
SERIALIZE_ERR ("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");
return false;
}
rz_flag_zone_reset (flag);
if (!rz_serialize_flag_zones_load (zones_db, flag->zones, res)) {
return false;
}
Sdb *flags_db = sdb_ns (db, "flags", false);
if (!flags_db) {
SERIALIZE_ERR ("missing flags sub-namespace");
return false;
}
if (!load_flags (flags_db, flag)) {
SERIALIZE_ERR ("failed to parse a flag json");
return false;
}
return true;
}

View file

@ -2122,6 +2122,54 @@ RZ_API void rz_anal_base_type_free(RzAnalBaseType *type);
RZ_API RzAnalBaseType *rz_anal_base_type_new(RzAnalBaseTypeKind kind);
RZ_API void rz_anal_dwarf_process_info(const RzAnal *anal, RzAnalDwarfContext *ctx);
RZ_API void rz_anal_dwarf_integrate_functions(RzAnal *anal, RzFlag *flags, Sdb *dwarf_sdb);
/* serialize */
RZ_API void rz_serialize_anal_case_op_save(RZ_NONNULL PJ *j, RZ_NONNULL RzAnalCaseOp *op);
RZ_API void rz_serialize_anal_switch_op_save(RZ_NONNULL PJ *j, RZ_NONNULL RzAnalSwitchOp *op);
RZ_API RzAnalSwitchOp *rz_serialize_anal_switch_op_load(RZ_NONNULL const RJson *json);
typedef void *RSerializeAnalDiffParser;
RZ_API RSerializeAnalDiffParser rz_serialize_anal_diff_parser_new(void);
RZ_API void rz_serialize_anal_diff_parser_free(RSerializeAnalDiffParser parser);
RZ_API RZ_NULLABLE RzAnalDiff *rz_serialize_anal_diff_load(RZ_NONNULL RSerializeAnalDiffParser parser, RZ_NONNULL const RJson *json);
RZ_API void rz_serialize_anal_diff_save(RZ_NONNULL PJ *j, RZ_NONNULL RzAnalDiff *diff);
RZ_API void rz_serialize_anal_blocks_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
/**
* RzAnal must not contain any blocks when calling this function!
* All loaded blocks will have a ref of 1 after this function and should be unrefd once after loading functions.
*/
RZ_API bool rz_serialize_anal_blocks_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RSerializeAnalDiffParser diff_parser, RZ_NULLABLE RzSerializeResultInfo *res);
typedef void *RSerializeAnalVarParser;
RZ_API RSerializeAnalVarParser rz_serialize_anal_var_parser_new(void);
RZ_API void rz_serialize_anal_var_parser_free(RSerializeAnalVarParser parser);
RZ_API RZ_NULLABLE RzAnalVar *rz_serialize_anal_var_load(RZ_NONNULL RzAnalFunction *fcn, RZ_NONNULL RSerializeAnalVarParser parser, RZ_NONNULL const RJson *json);
RZ_API void rz_serialize_anal_functions_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_functions_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RSerializeAnalDiffParser diff_parser, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_xrefs_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_xrefs_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_meta_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_meta_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_hints_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_hints_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_classes_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_classes_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_types_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_types_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_sign_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_sign_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_imports_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_imports_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_pin_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_pin_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_cc_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_cc_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_anal_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal);
RZ_API bool rz_serialize_anal_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnal *anal, RZ_NULLABLE RzSerializeResultInfo *res);
/* plugin pointers */
extern RzAnalPlugin rz_anal_plugin_null;
extern RzAnalPlugin rz_anal_plugin_6502;

View file

@ -3,6 +3,7 @@
#include "rz_types.h"
#include "rz_util.h"
#include "rz_util/rz_serialize.h"
#ifdef __cplusplus
extern "C" {
@ -113,6 +114,11 @@ static inline bool rz_config_node_is_ro(RzConfigNode *node) {
static inline bool rz_config_node_is_str(RzConfigNode *node) {
return node->flags & CN_STR;
}
/* serialize */
RZ_API void rz_serialize_config_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config);
RZ_API bool rz_serialize_config_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config, RZ_NULLABLE RzSerializeResultInfo *res);
#endif
#ifdef __cplusplus

View file

@ -162,7 +162,6 @@ typedef enum rz_core_autocomplete_types_t {
RZ_CORE_AUTOCMPLT_FCN,
RZ_CORE_AUTOCMPLT_ZIGN,
RZ_CORE_AUTOCMPLT_EVAL,
RZ_CORE_AUTOCMPLT_PRJT,
RZ_CORE_AUTOCMPLT_MINS,
RZ_CORE_AUTOCMPLT_BRKP,
RZ_CORE_AUTOCMPLT_MACR,
@ -522,11 +521,6 @@ RZ_API void rz_core_fortune_list_types(void);
RZ_API void rz_core_fortune_list(RzCore *core);
RZ_API void rz_core_fortune_print_random(RzCore *core);
/* project */
RZ_API bool rz_core_project_load(RzCore *core, const char *prjfile, const char *rcfile);
RZ_API RzThread *rz_core_project_load_bg(RzCore *core, const char *prjfile, const char *rcfile);
RZ_API void rz_core_project_execute_cmds(RzCore *core, const char *prjfile);
#define RZ_CORE_FOREIGN_ADDR -1
RZ_API int rz_core_yank(RzCore *core, ut64 addr, int len);
RZ_API int rz_core_yank_string(RzCore *core, ut64 addr, int maxlen);
@ -674,15 +668,6 @@ RZ_API int rz_core_zdiff(RzCore *c, RzCore *c2);
RZ_API int rz_core_gdiff(RzCore *core1, RzCore *core2);
RZ_API int rz_core_gdiff_fcn(RzCore *c, ut64 addr, ut64 addr2);
RZ_API bool rz_core_project_open(RzCore *core, const char *file, bool thready);
RZ_API int rz_core_project_cat(RzCore *core, const char *name);
RZ_API int rz_core_project_delete(RzCore *core, const char *prjfile);
RZ_API int rz_core_project_list(RzCore *core, int mode);
RZ_API bool rz_core_project_save_script(RzCore *core, const char *file, int opts);
RZ_API bool rz_core_project_save(RzCore *core, const char *file);
RZ_API char *rz_core_project_info(RzCore *core, const char *file);
RZ_API char *rz_core_project_notes_file (RzCore *core, const char *file);
RZ_API char *rz_core_sysenv_begin(RzCore *core, const char *cmd);
RZ_API void rz_core_sysenv_end(RzCore *core, const char *cmd);
@ -959,6 +944,11 @@ RZ_API void rz_core_annotated_code_print(RAnnotatedCode *code, RzVector *line_of
*/
RZ_API void rz_core_annotated_code_print_comment_cmds(RAnnotatedCode *code);
/* serialize */
RZ_API void rz_serialize_core_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core);
RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE RzSerializeResultInfo *res);
#endif
#ifdef __cplusplus

View file

@ -5,6 +5,7 @@
#include <rz_util.h>
#include <rz_list.h>
#include <rz_skiplist.h>
#include <rz_util/rz_serialize.h>
#ifdef __cplusplus
extern "C" {
@ -196,6 +197,13 @@ RZ_API bool rz_flag_zone_list(RzFlag *fz, int mode);
RZ_API bool rz_flag_zone_reset(RzFlag *f);
RZ_API RzList *rz_flag_zone_barlist(RzFlag *f, ut64 from, ut64 bsize, int rows);
/* serialize */
RZ_API void rz_serialize_flag_zones_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzList/*<RzFlagZoneItem *>*/ *zones);
RZ_API bool rz_serialize_flag_zones_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzList/*<RzFlagZoneItem *>*/ *zones, RZ_NULLABLE RzSerializeResultInfo *res);
RZ_API void rz_serialize_flag_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag);
RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag, RZ_NULLABLE RzSerializeResultInfo *res);
#endif
#ifdef __cplusplus

View file

@ -0,0 +1,35 @@
#ifndef R2_PROJECT_H
#define R2_PROJECT_H
#include <rz_util/rz_serialize.h>
#include <rz_core.h>
#include <sdb.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef Sdb RzProject;
typedef enum rz_project_err {
RZ_PROJECT_ERR_SUCCESS,
RZ_PROJECT_ERR_FILE,
RZ_PROJECT_ERR_INVALID_TYPE,
RZ_PROJECT_ERR_INVALID_VERSION,
RZ_PROJECT_ERR_NEWER_VERSION,
RZ_PROJECT_ERR_INVALID_CONTENTS,
RZ_PROJECT_ERR_UNKNOWN
} RzProjectErr;
RZ_API RZ_NONNULL const char *rz_project_err_message(RzProjectErr err);
RZ_API RzProjectErr rz_project_save(RzCore *core, RzProject *prj);
RZ_API RzProjectErr rz_project_save_file(RzCore *core, const char *file);
RZ_API RzProjectErr rz_project_load(RzCore *core, RzProject *prj, RZ_NULLABLE const char *file, RzSerializeResultInfo *res);
RZ_API RzProjectErr rz_project_load_file(RzCore *core, const char *file, RzSerializeResultInfo *res);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,13 @@
/* rizin - LGPL - Copyright 2020 - thestr4ng3r */
#ifndef RZ_SERIALIZE_H
#define RZ_SERIALIZE_H
#include <rz_util/rz_json.h>
#include <rz_list.h>
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); }
#endif //RZ_SERIALIZE_H

View file

@ -4,6 +4,7 @@
#define RZ_SPACES_MAX 512
#include "rz_util.h"
#include "rz_serialize.h"
#ifdef __cplusplus
extern "C" {
@ -103,6 +104,14 @@ typedef RBIter RSpaceIter;
#define rz_spaces_foreach(sp, it, s) \
rz_rbtree_foreach ((sp)->spaces, (it), (s), RSpace, rb)
/* serialize */
RZ_API void rz_serialize_spaces_save(RZ_NONNULL Sdb *db, RZ_NONNULL RSpaces *spaces);
/**
* @param load_name whether to overwrite the name in spaces with the value from db
*/
RZ_API bool rz_serialize_spaces_load(RZ_NONNULL Sdb *db, RZ_NONNULL RSpaces *spaces, bool load_name, RZ_NULLABLE RzSerializeResultInfo *res);
#ifdef __cplusplus
}
#endif

View file

@ -8,7 +8,7 @@ RZ_DEPS+=rz_cons
RZ_DEPS+=rz_crypto
STATIC_OBJS=$(subst ..,p/..,$(subst io_,p/io_,$(STATIC_OBJ)))
OBJS=${STATIC_OBJS}
OBJS+=io.o io_plugin.o io_map.o io_desc.o io_cache.o p_cache.o undo.o ioutils.o io_fd.o
OBJS+=io.o io_plugin.o io_map.o io_desc.o io_cache.o p_cache.o undo.o ioutils.o io_fd.o serialize_io.o
CFLAGS+=-Wall -DRZ_PLUGIN_INCORE

View file

@ -8,6 +8,7 @@ rz_io_sources = [
'ioutils.c',
'undo.c',
'p_cache.c',
'serialize_io.c',
'p/io_ar.c',
'p/io_fd.c',
'p/io_bfdbg.c',

113
librz/io/serialize_io.c Normal file
View file

@ -0,0 +1,113 @@
/* rizin - LGPL - Copyright 2020 - thestr4ng3r */
#include <rz_util/rz_serialize.h>
#include <rz_io.h>
#include "../util/serialize_helper.h"
#include <errno.h>
/*
*
* SDB Format:
*
* /
* /files
* <fd>={perm:<int>, uri:<str>, name:<str>, referer?:<str>}
* /pcache
* <fd>.<ut64>={cached:<ut64>, data:<base64>}
*/
typedef struct {
int fd;
int perm;
char *uri;
char *name;
char *referer;
HtUP *cache;
void *data;
struct rz_io_plugin_t *plugin;
RzIO *io;
} RzIODescasd;
typedef struct {
int fd;
Sdb *db;
} PCacheSaveCtx;
static bool pcache_save_cb(void *user, const ut64 k, const void *v) {
PCacheSaveCtx *ctx = user;
const RzIODescCache *cache = v;
char key[0x30];
if (snprintf (key, sizeof (key), "%d.0x%"PFMT64x, ctx->fd, k) < 0) {
return false;
}
char val[RZ_IO_DESC_CACHE_SIZE * 4 + 1];
rz_base64_encode (val, cache->cdata, RZ_IO_DESC_CACHE_SIZE);
return true;
}
static bool file_save_cb(void *user, void *data, ut32 id) {
Sdb *db = user;
RzIODesc *desc = (RzIODesc *)data;
char key[0x20];
if (snprintf (key, sizeof (key), "%d", desc->fd) < 0) {
return false;
}
PJ *j = pj_new ();
if (!j) {
return false;
}
pj_o (j);
pj_ki (j, "perm", desc->perm);
// obsz is irrelevant (never written, always 0)
pj_ks (j, "uri", desc->uri);
pj_ks (j, "name", desc->name);
if (desc->referer) {
pj_ks (j, "referer", desc->referer);
}
// TODO: plugin
pj_end (j);
sdb_set (db, key, pj_string (j), 0);
pj_free (j);
if (desc->cache->count) {
PCacheSaveCtx ctx = {
.fd = desc->fd,
.db = sdb_ns (db, "pcache", true)
};
ht_up_foreach (desc->cache, pcache_save_cb, &ctx);
}
return true;
}
RZ_API void rz_serialize_io_files_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzIO *io) {
sdb_ns (db, "pcache", true);
rz_id_storage_foreach (io->files, file_save_cb, db);
}
RZ_API bool rz_serialize_io_files_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzIO *io, RZ_NULLABLE RzSerializeResultInfo *res) {
// TODO
return true;
}
RZ_API void rz_serialize_io_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzIO *io) {
rz_serialize_io_files_save (sdb_ns (db, "files", true), io);
}
RZ_API bool rz_serialize_io_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzIO *io, RZ_NULLABLE RzSerializeResultInfo *res) {
// TODO: purge RzIO?
bool ret = false;
Sdb *subdb;
#define SUB(ns, call) SUB_DO(ns, call, goto beach;)
SUB ("files", rz_serialize_io_files_load (subdb, io, res));
#undef SUB
ret = true;
beach:
return ret;
}

View file

@ -10,6 +10,7 @@
#endif
#include <rz_core.h>
#include <rz_project.h>
static bool is_valid_gdb_file(RzCoreFile *fh) {
RzIODesc *d = fh && fh->core ? rz_io_desc_get (fh->core->io, fh->fd) : NULL;
@ -121,7 +122,7 @@ static int main_help(int line) {
" -q quiet mode (no prompt) and quit after -i\n"
" -qq quit after running all -c and -i\n"
" -Q quiet mode (no prompt) and quit faster (quickLeak=true)\n"
" -p [prj] use project, list if no arg, load if no file\n"
" -p [p.rzdb] load project file\n"
" -P [file] apply rapatch file and quit\n"
" -r [rz_run] specify rz_run profile to load (same as -e dbg.profile=X)\n"
" -R [rrz_testule] specify custom rz_run directive\n"
@ -337,7 +338,6 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
int zflag = 0;
bool do_connect = false;
bool fullfile = false;
int has_project;
bool zerosep = false;
int help = 0;
enum { LOAD_BIN_ALL, LOAD_BIN_NOTHING, LOAD_BIN_STRUCTURES_ONLY } load_bin = LOAD_BIN_ALL;
@ -422,12 +422,6 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
r->io->envprofile = envprofile;
rz_core_task_sync_begin (&r->tasks);
if (argc == 2 && !strcmp (argv[1], "-p")) {
rz_core_project_list (r, 0);
rz_cons_flush ();
LISTS_FREE ();
return 0;
}
// HACK TO PERMIT '#!/usr/bin/rz - -i' hashbangs
if (argc > 2 && !strcmp (argv[1], "-") && !strcmp (argv[2], "-i")) {
argv[1] = argv[0];
@ -578,13 +572,7 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
}
break;
case 'p':
if (!strcmp (opt.arg, "?")) {
rz_core_project_list (r, 0);
rz_cons_flush ();
LISTS_FREE ();
return 0;
}
rz_config_set (r->config, "prj.name", opt.arg);
prj = *opt.arg ? opt.arg : NULL;
break;
case 'P':
if (RZ_STR_ISEMPTY (opt.arg)) {
@ -804,10 +792,18 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
rz_bin_force_plugin (r->bin, forcebin);
prj = rz_config_get (r->config, "prj.name");
if (prj && *prj) {
rz_core_project_open (r, prj, false);
rz_config_set (r->config, "bin.strings", "false");
if (prj) {
RzSerializeResultInfo *res = rz_serialize_result_info_new ();
RzProjectErr err = rz_project_load_file (r, prj, res);
if (err != RZ_PROJECT_ERR_SUCCESS) {
eprintf ("Failed to load project: %s\n", rz_project_err_message (err));
RzListIter *it;
char *s;
rz_list_foreach (res, it, s) {
eprintf (" %s\n", s);
}
}
rz_serialize_result_info_free (res);
}
if (do_connect) {
@ -923,7 +919,7 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
LISTS_FREE ();
return 1;
}
} else if (strcmp (argv[opt.ind - 1], "--") && !(rz_config_get (r->config, "prj.name") && rz_config_get (r->config, "prj.name")[0]) ) {
} else if (strcmp (argv[opt.ind - 1], "--")) {
if (debug) {
if (asmbits) {
rz_config_set (r->config, "asm.bits", asmbits);
@ -1118,25 +1114,11 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
}
}
} else {
const char *prj = rz_config_get (r->config, "prj.name");
if (prj && *prj) {
pfile = rz_core_project_info (r, prj);
if (pfile) {
if (!fh) {
fh = rz_core_file_open (r, pfile, perms, mapaddr);
}
// load_bin = LOAD_BIN_NOTHING;
load_bin = LOAD_BIN_STRUCTURES_ONLY;
} else {
eprintf ("Cannot find project file\n");
}
} else {
if (fh) {
iod = r->io ? rz_io_desc_get (r->io, fh->fd) : NULL;
if (iod) {
perms = iod->perm;
rz_io_map_new (r->io, iod->fd, perms, 0LL, 0LL, rz_io_desc_size (iod));
}
if (fh) {
iod = r->io ? rz_io_desc_get (r->io, fh->fd) : NULL;
if (iod) {
perms = iod->perm;
rz_io_map_new (r->io, iod->fd, perms, 0LL, 0LL, rz_io_desc_size (iod));
}
}
}
@ -1280,11 +1262,7 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
if (iod && !strstr (iod->uri, "://")) {
const char *npath;
char *path = strdup (rz_config_get (r->config, "file.path"));
has_project = rz_core_project_open (r, rz_config_get (r->config, "prj.name"), false);
iod = r->io ? rz_io_desc_get (r->io, fh->fd) : NULL;
if (has_project) {
rz_config_set (r->config, "bin.strings", "false");
}
npath = rz_config_get (r->config, "file.path");
if (!quiet && path && *path && npath && strcmp (path, npath)) {
eprintf ("WARNING: file.path change: %s => %s\n", path, npath);
@ -1448,15 +1426,15 @@ RZ_API int rz_main_rizin(int argc, const char **argv) {
}
}
prj = rz_config_get (r->config, "prj.name");
prj = rz_config_get (r->config, "prj.file");
if (no_question_save) {
if (prj && *prj && y_save_project){
rz_core_project_save (r, prj);
rz_project_save_file (r, prj); // TODO: check error
}
} else {
question = rz_str_newf ("Do you want to save the '%s' project? (Y/n)", prj);
if (prj && *prj && rz_cons_yesno ('y', "%s", question)) {
rz_core_project_save (r, prj);
rz_project_save_file (r, prj); // TODO: check error
}
free (question);
}

View file

@ -345,6 +345,7 @@ include_files =[
'include/rz_magic.h',
'include/rz_parse.h',
'include/rz_pdb.h',
'include/rz_project.h',
'include/rz_qrcode.h',
'include/rz_regex.h',
'include/rz_reg.h',
@ -399,6 +400,7 @@ rz_util_files = [
'include/rz_util/rz_rbtree.h',
'include/rz_util/rz_intervaltree.h',
'include/rz_util/rz_sandbox.h',
'include/rz_util/rz_serialize.h',
'include/rz_util/rz_signal.h',
'include/rz_util/rz_spaces.h',
'include/rz_util/rz_stack.h',

View file

@ -23,7 +23,7 @@ OBJS+=udiff.o bdiff.o stack.o queue.o tree.o idpool.o assert.o
OBJS+=punycode.o pkcs7.o x509.o asn1.o astr.o json_parser.o json_indent.o skiplist.o
OBJS+=pj.o rbtree.o intervaltree.o qrcode.o vector.o str_constpool.o str_trim.o
OBJS+=ascii_table.o protobuf.o graph_drawable.o
OBJS+=annotated_code.o
OBJS+=annotated_code.o serialize_spaces.o
ifeq (${HAVE_LIB_GMP},1)
OBJS+=big-gmp.o

View file

@ -82,7 +82,8 @@ rz_util_sources = [
'regex/regcomp.c',
'regex/regexec.c',
'regex/regerror.c',
'annotated_code.c'
'annotated_code.c',
'serialize_spaces.c'
]
rz_util_deps = [ldl, mth, spp_dep, pth, utl, sdb_dep, zlib_dep, platform_deps]

View file

@ -28,6 +28,7 @@ SDB_OBJS+=num.o
SDB_OBJS+=util.o
SDB_OBJS+=journal.o
SDB_OBJS+=diff.o
SDB_OBJS+=text.o
SDBOBJS=$(addprefix ${SDBPATH},${SDB_OBJS})

View file

@ -0,0 +1,51 @@
#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

@ -0,0 +1,110 @@
#include <rz_util/rz_serialize.h>
#include <rz_util/rz_spaces.h>
#include "../util/serialize_helper.h"
/*
* SDB Format:
*
* /
* name=<spaces name>
* spacestack=[<space name>,<space name>,<space name>, <current>] (json)
* /spaces
* <space name>="s"
* ...
*/
#define KEY_NAME "name"
#define KEY_SPACESTACK "spacestack"
#define KEY_SPACES "spaces"
RZ_API void rz_serialize_spaces_save(RZ_NONNULL Sdb *db, RZ_NONNULL RSpaces *spaces) {
sdb_set (db, KEY_NAME, spaces->name, 0);
PJ *j = pj_new ();
if(!j) {
return;
}
pj_a (j);
RzListIter *iter;
char *spacename;
rz_list_foreach (spaces->spacestack, iter, spacename) {
pj_s (j, spacename);
}
pj_s (j, spaces->current ? spaces->current->name : "*"); // push current manually, will be popped on load
pj_end (j);
sdb_set (db, KEY_SPACESTACK, pj_string (j), 0);
pj_free (j);
Sdb *db_spaces = sdb_ns (db, KEY_SPACES, true);
RBIter rbiter;
RSpace *space;
rz_rbtree_foreach (spaces->spaces, rbiter, space, RSpace, rb) {
sdb_set (db_spaces, space->name, "s", 0);
}
}
static bool foreach_space_cb(void *user, const char *k, const char *v) {
RSpaces *spaces = user;
rz_spaces_add (spaces, k);
return true;
}
RZ_API bool rz_serialize_spaces_load(RZ_NONNULL Sdb *db, RZ_NONNULL RSpaces *spaces, bool load_name, RZ_NULLABLE RzSerializeResultInfo *res) {
if (load_name) {
char *old_name = (char *)spaces->name;
spaces->name = sdb_get (db, KEY_NAME, NULL);
if (!spaces->name) {
spaces->name = old_name;
SERIALIZE_ERR ("failed to get spaces name from db");
return false;
}
free (old_name);
}
rz_spaces_purge (spaces);
Sdb *db_spaces = sdb_ns (db, KEY_SPACES, false);
if (!db_spaces) {
SERIALIZE_ERR ("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");
return false;
}
bool ret = true;
RJson *stack_json = rz_json_parse (stack_json_str);
if (!stack_json) {
SERIALIZE_ERR ("failed to parse stackspace json");
ret = false;
goto beach;
}
if (stack_json->type != RZ_JSON_ARRAY) {
SERIALIZE_ERR ("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");
ret = false;
goto beach;
}
RSpace *space = rz_spaces_get (spaces, stack_element->str_value);
rz_list_append (spaces->spacestack, space ? space->name : "*");
}
rz_spaces_pop (spaces); // current is the top stack element, pop it
beach:
rz_json_free (stack_json);
free (stack_json_str);
return ret;
}

View file

@ -469,6 +469,7 @@ sdb_files = [
'shlr/sdb/src/query.c',
'shlr/sdb/src/sdb.c',
'shlr/sdb/src/sdbht.c',
'shlr/sdb/src/text.c',
'shlr/sdb/src/util.c'
]

@ -1 +1 @@
Subproject commit f0902e0ad52c89468d0dfea1e99598a15aa023ad
Subproject commit 807d74f0488cb010501e8e908938a747e1c8945d

View file

@ -1067,20 +1067,13 @@ e asm.bits=64
pd 1
Cf 1 x
pd 1
Ps temp_proj
Cf-
pd 1
Ps temp_proj
Po temp_proj
pd 1
EOF
EXPECT=<<EOF
0x00000000 57 push rdi
0x00000000 pf x # size=1
0x00000000 = 0x6c726f57
temp_proj
0x00000000 57 push rdi
temp_proj
0x00000000 57 push rdi
EOF
RUN

View file

@ -1,457 +0,0 @@
NAME=Import project
FILE=malloc://512
CMDS=<<EOF
e dir.projects = bins/other/projects
Po test > /dev/null
C*
EOF
EXPECT=<<EOF
CCu base64:U29tZSB0ZXN0 @ 0x00404890
EOF
RUN
NAME=Import project with overwriting
FILE=malloc://512
CMDS=<<EOF
e asm.bits=64
e asm.arch = x86
e anal.arch = x86
e dir.projects = ../bin/
CC Some test @ 0x00404890
Po import2 > /dev/null
CC*
EOF
EXPECT=<<EOF
CCu base64:U29tZSB0ZXN0 @ 0x00404890
EOF
RUN
NAME=Import project with overwriting
FILE=malloc://512
CMDS=<<EOF
t-*
e asm.arch = x86
e anal.arch = x86
e dir.projects = .tmp/
e asm.bits=64
wx 31ed4989d15e4889e24883e4f0505449c7c09024410048c7c12024410048c7c7a0284000e857dcfffff4
af test
afF @ test
pdf
Ps testw > /dev/null
Pc testw~afF
rm .tmp/testw
EOF
EXPECT=<<EOF
/ (fcn) test
\ 0x00000000 (42 byte folded function)
afF @ 0x00000000
EOF
RUN
NAME=Export project
FILE=malloc://512
CMDS=<<EOF
e dir.projects = .tmp/
CC "Some other test" @ 0x00404890
Ps testexp > /dev/null
cat .tmp/testexp/rc | grep base64
rmdir -p .tmp/testexp
EOF
EXPECT=<<EOF
"e bin.debase64 = false"
CCu base64:IlNvbWUgb3RoZXIgdGVzdCI= @ 0x00404890
EOF
RUN
NAME=Set, export, unset and import
FILE=malloc://512
CMDS=<<EOF
e dir.projects = .tmp/
t-*
CC "First comment" @ 0x00404890
CC "Second comment" @ 0x00404800
Ps testset > /dev/null
C- @ 0x00404890
C- @ 0x00404800
Po project.rz
cat .tmp/testset/rc | grep CC
rmdir -p .tmp/testset
EOF
EXPECT=<<EOF
CCu base64:IlNlY29uZCBjb21tZW50Ig== @ 0x00404800
CCu base64:IkZpcnN0IGNvbW1lbnQi @ 0x00404890
EOF
RUN
NAME=xrefs
FILE=malloc://512
CMDS=<<EOF
ax 1
e dir.projects = .tmp/
axq
Ps xrefs > /dev/null
axq
EOF
EXPECT=<<EOF
0x00000000 -> 0x00000001 UNKNOWN
0x00000000 -> 0x00000001 UNKNOWN
EOF
RUN
NAME=Import mapped project
FILE=malloc://512
CMDS=<<EOF
e dir.projects = bins/other/projects/
Po resetc64 > /dev/null
pu 3 @0xc000
EOF
EXPECT=<<EOF
%4c%e2%fc
EOF
RUN
NAME=asm.emu in project
FILE=bins/elf/analysis/simpleARM.elf
CMDS=<<EOF
e asm.flags = false
e asm.emu = true
e dir.projects = .tmp/
Ps emu > /dev/null
Po emu
CC-
om `o~[0]` 0
pd 1
rm .tmp/emu
EOF
EXPECT=<<EOF
0x08000060 0d20a0e3 mov r2, 0xd ; r2=0xd -> 0x2000000
EOF
RUN
NAME=Variables in project file
FILE=bins/efi/bootia32.efi
CMDS=<<EOF
e dir.projects = .tmp/
af
afvr edi blahblah typeR @ 0x10002d8d
afvb 8 ImageHandle blah @ 0x10002d8d
Ps var > /dev/null
Pc var~ImageHandle
Pc var~blahblah
rm .tmp/var
EOF
EXPECT=<<EOF
afvb 8 ImageHandle blah @ 0x10002d8d
afvr edi blahblah typeR @ 0x10002d8d
EOF
RUN
NAME=Types and link in project file
FILE=-
CMDS=<<EOF
e dir.projects = .tmp/
tk zoby = type
tl char @ 0x0
Ps types > /dev/null
Pc types~?link.,symlink,unlink
Pc types~?zoby
EOF
EXPECT=<<EOF
10
1
EOF
RUN
NAME=Breakpoints in project file
FILE=bins/elf/analysis/main
BROKEN=1
CMDS=<<EOF
e dbg.bpinmaps = false
e dir.projects = .tmp/
db 0x1234567
Ps breakpoints > /dev/null
Pc breakpoints~?0x1234567
EOF
EXPECT=<<EOF
1
EOF
RUN
NAME=Visual Marks in project file
FILE=bins/elf/analysis/main
CMDS=<<EOF
fV 49 0x400410
fV 50 0x400412
Ps vmarks > /dev/null
Pc vmarks~fV
Pd vmarks > /dev/null
EOF
EXPECT=<<EOF
fV 49 0x400410
fV 50 0x400412
EOF
RUN
NAME=Custom types in project file
BROKEN=1
FILE=bins/elf/analysis/main
CMDS=<<EOF
tk char **=type
tk type.char **=**z
tk type.char **.size=64
Ps custom_types > /dev/null
Pc custom_types~?char **
"td struct Foo { int bar; int x; int y; };"
Ps custom_types > /dev/null
Pc custom_types~?char **
Pc custom_types~?Foo
Pd custom_types > /dev/null
EOF
EXPECT=<<EOF
9
9
8
EOF
RUN
NAME=Export custom types and import again
FILE=bins/elf/analysis/main
BROKEN=1
CMDS=<<EOF
tk char **=type
tk type.char **=**z
tk type.char **.size=64
"td struct Foo { int bar; int x; int y; };"
Ps custom_types > /dev/null
t- char **
t- Foo
tk~?char **
tk~?Foo
Po custom_types > /dev/null
tk~?char **
tk~?Foo
Pd custom_types > /dev/null
EOF
EXPECT=<<EOF
5
0
7
5
EOF
RUN
NAME=Save project for a binary and checking opened files
FILE=bins/elf/analysis/main
BROKEN=1
CMDS=<<EOF
e dir.projects = .tmp/
Ps ulumulu > /dev/null
Po ulumulu > /dev/null
o*~?
EOF
EXPECT=<<EOF
1
EOF
RUN
NAME=Save project for a binary without saving its info
FILE=bins/elf/analysis/main
ARGS=-n
CMDS=<<EOF
e dir.projects = .tmp/
Ps blub > /dev/null
Po blub > /dev/null
i~format
EOF
EXPECT=<<EOF
EOF
RUN
NAME=Save project for a binary after analysis
FILE=bins/elf/analysis/main
CMDS=<<EOF
e dir.projects = .tmp/
aaa
Ps beer
# Following command hangs:
# Po beer
y
EOF
EXPECT=<<EOF
beer
EOF
RUN
NAME=Save project for a binary without saving its info at a specific map offset
FILE=bins/elf/analysis/main
ARGS=-n -m 0x1337
CMDS=<<EOF
e dir.projects = .tmp/
Ps hand > /dev/null
Po hand > /dev/null
om*~?
om*~[2]
EOF
EXPECT=<<EOF
1
0x00001337
EOF
RUN
NAME=Delete a saved project (with Pd)
FILE=bins/elf/analysis/main
ARGS=-n
CMDS=<<EOF
e dir.projects = .tmp/
Ps cannot > /dev/null
Pd cannot > /dev/null
Pl~cannot
EOF
EXPECT=<<EOF
EOF
RUN
NAME=Delete a saved project (with P-)
FILE=bins/elf/analysis/main
ARGS=-n
CMDS=<<EOF
e dir.projects = .tmp/
Ps erase > /dev/null
P- erase > /dev/null
Pl~erase
EOF
EXPECT=<<EOF
EOF
RUN
NAME=Delete a saved project and used directory (with Pd)
FILE=bins/elf/analysis/main
ARGS=-n
CMDS=<<EOF
e dir.projects = .tmp/
Ps anesthetize > /dev/null
Pd anesthetize > /dev/null
Pl~blah
ls -l `e dir.projects`~anesthetize
EOF
EXPECT=<<EOF
EOF
RUN
NAME=Delete a saved project and used directory (with P-)
FILE=bins/elf/analysis/main
ARGS=-n
BROKEN=1
CMDS=<<EOF
e dir.projects = .tmp/
Ps lightbulb > /dev/null
P- lightbulb > /dev/null
Pl~lightbulb
ls -l `e dir.projects`~lightbulb
EOF
EXPECT=<<EOF
-drwxr-xr-x 1 501:20 96 .tmp/lightbulb/
EOF
RUN
NAME=Save project for a file with asm.bits=32 and check the value after loading again
FILE=bins/src/hello.c
ARGS=
CMDS=<<EOF
e dir.projects = .tmp/
e asm.bits=16
Ps sun > /dev/null
Po sun > /dev/null
e asm.bits
EOF
EXPECT=<<EOF
16
EOF
RUN
NAME=prj.name saved in project
FILE=malloc://512
CMDS=<<EOF
e dir.projects = .tmp/
Ps named_prj > /dev/null
e prj.name=
Po named_prj > /dev/null
e prj.name
rm .tmp/named_prj
EOF
EXPECT=<<EOF
named_prj
EOF
RUN
NAME=Checking e prj.name after saving again
FILE=bins/elf/analysis/main
CMDS=<<EOF
e dir.projects = .tmp/
Ps stupid > /dev/null
Po stupid > /dev/null
Ps stupid > /dev/null
Po stupid > /dev/null
e prj.name
EOF
EXPECT=<<EOF
stupid
EOF
RUN
NAME=Restoring xrefs
FILE=malloc://512
CMDS=<<EOF
e asm.arch = x86
e anal.arch = x86
e asm.bits=32
e dir.projects = .tmp/
wx 5031c0e801000000c3b801000000c3
af
Ps dream > /dev/null
Po dream > /dev/null
axq
EOF
EXPECT=<<EOF
0x00000003 -> 0x00000009 CALL
EOF
RUN
NAME=Reopening projects bin info loading
FILE=bins/elf/analysis/main
BROKEN=1
CMDS=<<EOF
e dir.projects = .tmp/
Ps bininfo > /dev/null
Po bininfo
i~?
ie~?
ii~?
EOF
EXPECT=<<EOF
37
3
5
EOF
RUN
NAME=Reopening project with changes loading
FILE=bins/elf/analysis/main
CMDS=<<EOF
aaa > /dev/null
e dir.projects = .tmp/
s main > /dev/null
CC test
Ps lapa > /dev/null
Po lapa
pd 1 ~test
rm .tmp/
EOF
EXPECT=<<EOF
| 0x00400506 55 push rbp ; test
EOF
RUN

115
test/db/cmd/project Normal file
View file

@ -0,0 +1,115 @@
NAME=flags
FILE=bins/elf/crackme0x05
CMDS=<<EOF
e cfg.newshell=1
fr sym.main sym.renamedmain
f~?
f~main
Ps .tmp_flags.rzdb
?e --
o--
f
?e --
Po .tmp_flags.rzdb
rm .tmp_flags.rzdb
f~?
f~main
EOF
EXPECT=<<EOF
117
0x08048364 16 sym.imp.__libc_start_main
0x08048540 256 main
0x08048540 92 sym.renamedmain
0x0804a000 4 reloc.__libc_start_main
--
--
117
0x08048364 16 sym.imp.__libc_start_main
0x08048540 92 sym.renamedmain
0x08048540 256 main
0x0804a000 4 reloc.__libc_start_main
EOF
RUN
NAME=config
FILE=-
CMDS=<<EOF
e cfg.newshell=1
e asm.describe=1
e asm.describe
e asm.indentspace=8
e asm.indentspace
e anal.fcnprefix=myfunctions
e anal.fcnprefix
Ps .tmp_config.rzdb
?e --
e asm.describe=0
e asm.describe
e asm.indentspace=0
e asm.indentspace
e anal.fcnprefix=fcn
e anal.fcnprefix
?e --
Po .tmp_config.rzdb
rm .tmp_config.rzdb
e asm.describe
e asm.indentspace
e anal.fcnprefix
EOF
EXPECT=<<EOF
true
8
myfunctions
--
false
0
fcn
--
true
8
myfunctions
EOF
RUN
NAME=seek
FILE=-
CMDS=<<EOF
e cfg.newshell=1
s 0x1337
s
Ps .tmp_seek.rzdb
o--
s 0
Po .tmp_seek.rzdb
rm .tmp_seek.rzdb
s
EOF
EXPECT=<<EOF
0x1337
0x1337
EOF
RUN
NAME=anal
FILE=-
CMDS=<<EOF
e cfg.newshell=1
af+ 0x100 windowpane
afb+ windowpane 0x100 0x30
afl
Ps .tmp_anal.rzdb
?e --
o--
afl
?e --
Po .tmp_anal.rzdb
rm .tmp_anal.rzdb
afl
EOF
EXPECT=<<EOF
0x00000100 1 48 windowpane
--
--
0x00000100 1 48 windowpane
EOF
RUN

View file

@ -174,3 +174,20 @@ EXPECT_ERR=<<EOF
Cannot open empty rapatch path
EOF
RUN
NAME=rizin project with explicit file
FILE=-
CMDS=<<EOF
!rizin -escr.utf8=0 -escr.color=0 -escr.interactive=0 -N -Qc "f easy @ 0x080483fe; Ps .crackme.rzdb" bins/elf/ioli/crackme0x00
?e Same project, different file
!rizin -escr.utf8=0 -escr.color=0 -escr.interactive=0 -N -p .crackme.rzdb -Qc "pdi 3 @ easy" bins/elf/ioli/crackme0x01
!rm .crackme.rzdb
EOF
EXPECT=<<EOF
Same project, different file
0x080483fe easy:
0x080483fe 29c4 sub esp, eax
0x08048400 c7042428850408 mov dword [esp], str.IOLI_Crackme_Level_0x01
0x08048407 e810ffffff call sym.imp.printf
EOF
RUN

View file

@ -44,6 +44,10 @@ if get_option('enable_tests')
'queue',
'rz_test',
'rbtree',
'serialize_anal',
'serialize_config',
'serialize_flag',
'serialize_spaces',
'sign',
'skiplist',
'spaces',

View file

@ -17,17 +17,14 @@ static size_t blocks_count(RzAnal *anal) {
}
#define assert_invariants(anal) do { if (!check_invariants (anal)) { return false; } } while (0)
#define assert_leaks(anal) do { if (!check_leaks (anal)) { return false; } } while (0)
bool test_r_anal_block_create() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (blocks_count (anal), 0, "initial count");
RzAnalBlock *block = rz_anal_create_block (anal, 0x1337, 42);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert ("created block", block);
mu_assert_eq (block->addr, 0x1337, "created addr");
mu_assert_eq (block->size, 42, "created size");
@ -35,7 +32,7 @@ bool test_r_anal_block_create() {
mu_assert_eq (blocks_count (anal), 1, "count after create");
RzAnalBlock *block2 = rz_anal_create_block (anal, 0x133f, 100);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert ("created block (overlap)", block2);
mu_assert_eq (block2->addr, 0x133f, "created addr");
mu_assert_eq (block2->size, 100, "created size");
@ -43,14 +40,14 @@ bool test_r_anal_block_create() {
mu_assert_eq (blocks_count (anal), 2, "count after create");
RzAnalBlock *block3 = rz_anal_create_block (anal, 0x1337, 5);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert ("no double create on same start", !block3);
mu_assert_eq (blocks_count (anal), 2, "count after failed create");
rz_anal_block_unref (block);
rz_anal_block_unref (block2);
assert_leaks (anal);
assert_block_leaks (anal);
rz_anal_free (anal);
mu_end;
}
@ -69,10 +66,10 @@ bool test_r_anal_block_contains() {
bool test_r_anal_block_split() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalBlock *block = rz_anal_create_block (anal, 0x1337, 42);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (blocks_count (anal), 1, "count after create");
block->jump = 0xdeadbeef;
block->fail = 0xc0ffee;
@ -84,14 +81,14 @@ bool test_r_anal_block_split() {
rz_anal_bb_set_offset (block, 4, 30);
RzAnalBlock *second = rz_anal_block_split (block, 0x1337);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_ptreq (second, block, "nop split on first addr");
mu_assert_eq (blocks_count (anal), 1, "count after nop split");
mu_assert_eq (block->ref, 2, "ref after nop split");
rz_anal_block_unref (block);
second = rz_anal_block_split (block, 0x1339);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_ptrneq (second, block, "non-nop split");
mu_assert_eq (blocks_count (anal), 2, "count after non-nop split");
@ -117,27 +114,27 @@ bool test_r_anal_block_split() {
rz_anal_block_unref (block);
rz_anal_block_unref (second);
assert_leaks (anal);
assert_block_leaks (anal);
rz_anal_free (anal);
mu_end;
}
bool test_r_anal_block_split_in_function() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalFunction *fcn = rz_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalBlock *block = rz_anal_create_block (anal, 0x1337, 42);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (blocks_count (anal), 1, "count after create");
rz_anal_function_add_block (fcn, block);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->ref, 2, "block refs after adding to function");
RzAnalBlock *second = rz_anal_block_split (block, 0x1339);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_ptrneq (second, block, "non-nop split");
mu_assert_eq (blocks_count (anal), 2, "count after non-nop split");
mu_assert_eq (block->ref, 2, "first block refs after adding to function");
@ -151,18 +148,18 @@ bool test_r_anal_block_split_in_function() {
rz_anal_block_unref (block);
rz_anal_block_unref (second);
assert_leaks (anal);
assert_block_leaks (anal);
rz_anal_free (anal);
mu_end;
}
bool test_r_anal_block_merge() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalBlock *first = rz_anal_create_block (anal, 0x1337, 42);
RzAnalBlock *second = rz_anal_create_block (anal, 0x1337 + 42, 624);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (blocks_count (anal), 2, "count after create");
second->jump = 0xdeadbeef;
second->fail = 0xc0ffee;
@ -179,7 +176,7 @@ bool test_r_anal_block_merge() {
rz_anal_bb_set_offset (second, 3, 30);
bool success = rz_anal_block_merge (first, second);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert ("merge success", success);
mu_assert_eq (blocks_count (anal), 1, "count after merge");
mu_assert_eq (first->addr, 0x1337, "addr after merge");
@ -199,29 +196,29 @@ bool test_r_anal_block_merge() {
rz_anal_block_unref (first);
// second must be already freed by the merge!
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_free (anal);
mu_end;
}
bool test_r_anal_block_merge_in_function() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalFunction *fcn = rz_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
RzAnalBlock *first = rz_anal_create_block (anal, 0x1337, 42);
RzAnalBlock *second = rz_anal_create_block (anal, 0x1337 + 42, 624);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (blocks_count (anal), 2, "count after create");
rz_anal_function_add_block (fcn, first);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_function_add_block (fcn, second);
assert_invariants (anal);
assert_block_invariants (anal);
bool success = rz_anal_block_merge (first, second);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert ("merge success", success);
mu_assert_eq (blocks_count (anal), 1, "count after merge");
mu_assert_eq (rz_list_length (fcn->bbs), 1, "fcn bbs after merge");
@ -232,29 +229,29 @@ bool test_r_anal_block_merge_in_function() {
rz_anal_block_unref (first);
// second must be already freed by the merge!
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_free (anal);
mu_end;
}
bool test_r_anal_block_delete() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalFunction *fcn = rz_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
RzAnalBlock *block = rz_anal_create_block (anal, 0x1337, 42);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (blocks_count (anal), 1, "count after create");
rz_anal_function_add_block (fcn, block);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->ref, 2, "refs after adding");
mu_assert_eq (rz_list_length (fcn->bbs), 1, "fcn bbs after add");
mu_assert_eq (rz_list_length (block->fcns), 1, "bb fcns after add");
rz_anal_delete_block (block);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->ref, 1, "refs after delete");
mu_assert_eq (rz_list_length (fcn->bbs), 0, "fcn bbs after delete");
mu_assert_eq (rz_list_length (block->fcns), 0, "bb fcns after delete");
@ -267,38 +264,38 @@ bool test_r_anal_block_delete() {
bool test_r_anal_block_set_size() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalFunction *fcn = rz_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
RzAnalBlock *block = rz_anal_create_block (anal, 0x1337, 42);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_function_add_block (fcn, block);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_block_set_size (block, 300);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->size, 300, "size after set_size");
RzAnalBlock *second = rz_anal_create_block (anal, 0x1337+300, 100);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_function_add_block (fcn, block);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_block_set_size (second, 500);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (second->size, 500, "size after set_size");
rz_anal_block_set_size (block, 80);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->size, 80, "size after set_size");
rz_anal_block_unref (block);
rz_anal_block_unref (second);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_free (anal);
mu_end;
@ -306,64 +303,64 @@ bool test_r_anal_block_set_size() {
bool test_r_anal_block_relocate() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalFunction *fcn = rz_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
RzAnalBlock *block = rz_anal_create_block (anal, 0x1337, 42);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_function_add_block (fcn, block);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
assert_invariants (anal);
assert_block_invariants (anal);
bool success = rz_anal_block_relocate (block, 0x200, 0x100);
mu_assert ("relocate success", success);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->addr, 0x200, "addr after relocate");
mu_assert_eq (block->size, 0x100, "size after relocate");
RzAnalBlock *second = rz_anal_create_block (anal, 0x1337+300, 100);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_function_add_block (fcn, second);
assert_invariants (anal);
assert_block_invariants (anal);
success = rz_anal_block_relocate (second, 0x400, 0x123);
mu_assert ("relocate success", success);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (second->addr, 0x400, "addr after relocate");
mu_assert_eq (second->size, 0x123, "size after relocate");
rz_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
assert_invariants (anal);
assert_block_invariants (anal);
success = rz_anal_block_relocate (block, 0x400, 0x333);
mu_assert ("relocate fail on same addr", !success);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->addr, 0x200, "addr after failed relocate");
mu_assert_eq (block->size, 0x100, "size after failed relocate");
rz_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
assert_invariants (anal);
assert_block_invariants (anal);
// jump after the other block
success = rz_anal_block_relocate (block, 0x500, 0x333);
mu_assert ("relocate success", success);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->addr, 0x500, "addr after failed relocate");
mu_assert_eq (block->size, 0x333, "size after failed relocate");
rz_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
assert_invariants (anal);
assert_block_invariants (anal);
// jump before the other block
success = rz_anal_block_relocate (block, 0x10, 0x333);
mu_assert ("relocate success", success);
assert_invariants (anal);
assert_block_invariants (anal);
mu_assert_eq (block->addr, 0x10, "addr after failed relocate");
mu_assert_eq (block->size, 0x333, "size after failed relocate");
rz_anal_block_unref (block);
rz_anal_block_unref (second);
assert_invariants (anal);
assert_block_invariants (anal);
rz_anal_free (anal);
mu_end;
@ -371,7 +368,7 @@ bool test_r_anal_block_relocate() {
bool test_r_anal_block_query() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
#define N 200
#define MAXSIZE 0x300
@ -382,7 +379,7 @@ bool test_r_anal_block_query() {
size_t i;
for (i = 0; i < N; i++) {
blocks[i] = rz_anal_create_block (anal, rand () % SPACE, rand () % MAXSIZE); // may return null on duplicates
assert_invariants (anal);
assert_block_invariants (anal);
}
// --
@ -475,7 +472,7 @@ bool test_r_anal_block_query() {
rz_anal_block_unref (blocks[i]);
}
assert_leaks (anal);
assert_block_leaks (anal);
rz_anal_free (anal);
mu_end;
}
@ -488,7 +485,7 @@ bool addr_list_cb(ut64 addr, void *user) {
bool test_r_anal_block_successors() {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalBlock *blocks[10];
blocks[0] = rz_anal_create_block (anal, 0x10, 0x10);
@ -501,7 +498,7 @@ bool test_r_anal_block_successors() {
blocks[7] = rz_anal_create_block (anal, 0x140, 0x10);
blocks[8] = rz_anal_create_block (anal, 0xa0, 0x10);
blocks[9] = rz_anal_create_block (anal, 0xc0, 0x10);
assert_invariants (anal);
assert_block_invariants (anal);
blocks[0]->jump = 0x30;
blocks[0]->fail = 0x50;
@ -562,7 +559,7 @@ bool test_r_anal_block_successors() {
rz_anal_block_unref (blocks[i]);
}
assert_leaks (anal);
assert_block_leaks (anal);
rz_anal_free (anal);
mu_end;
}
@ -571,7 +568,7 @@ bool test_r_anal_block_automerge() {
size_t i;
for (i = 0; i < SAMPLES; i++) {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalBlock *a = rz_anal_create_block (anal, 0x100, 0x10);
@ -624,7 +621,7 @@ bool test_r_anal_block_automerge() {
rz_list_free (all_blocks);
rz_anal_block_automerge (shuffled_blocks);
assert_invariants (anal);
assert_block_invariants (anal);
//mu_assert_eq (rz_list_length (shuffled_blocks), 4, "length after automerge");
mu_assert ("remaining blocks a", rz_list_contains (shuffled_blocks, a));
mu_assert ("remaining blocks b", rz_list_contains (shuffled_blocks, b));
@ -638,8 +635,8 @@ bool test_r_anal_block_automerge() {
}
rz_list_free (shuffled_blocks);
assert_invariants (anal);
assert_leaks (anal);
assert_block_invariants (anal);
assert_block_leaks (anal);
rz_anal_free (anal);
}
mu_end;
@ -647,7 +644,7 @@ bool test_r_anal_block_automerge() {
bool test_r_anal_block_chop_noreturn(void) {
RzAnal *anal = rz_anal_new ();
assert_invariants (anal);
assert_block_invariants (anal);
RzAnalBlock *a = rz_anal_create_block (anal, 0x100, 0x10);
RzAnalBlock *b = rz_anal_create_block (anal, 0x110, 0x10);
@ -665,7 +662,7 @@ bool test_r_anal_block_chop_noreturn(void) {
rz_anal_block_chop_noreturn (b, 0x111);
assert_invariants (anal);
assert_block_invariants (anal);
mu_end;
}

View file

@ -68,3 +68,6 @@ static bool block_check_leaks(RzAnal *anal) {
}
return true;
}
#define assert_block_invariants(anal) do { if (!block_check_invariants (anal)) { return false; } } while (0)
#define assert_block_leaks(anal) do { if (!block_check_leaks (anal)) { return false; } } while (0)

View file

@ -1,6 +1,9 @@
#ifndef TEST_SDB_H
#define TEST_SDB_H
#define PERTURBATOR "\\,\";] [}{'"
#define PERTURBATOR_JSON "\\\\,\\\";] [}{'"
static void diff_cb(const SdbDiff *diff, void *user) {
char buf[2048];
if (sdb_diff_format (buf, sizeof (buf), diff) < 0) {
@ -17,4 +20,9 @@ static inline void print_sdb(Sdb *sdb) {
#define assert_sdb_eq(actual, expected, msg) mu_assert ((msg), sdb_diff (expected, actual, diff_cb, NULL));
#define assert_streq_null(actual, expected, message) do { \
mu_assert (message, (!(actual)) == (!(expected))); \
if (expected) { mu_assert_streq (actual, expected, message); } \
} while(0)
#endif //R2DB_TEST_UTILS_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,61 @@
#include <rz_config.h>
#include "minunit.h"
#include "test_sdb.h"
Sdb *ref_db() {
Sdb *db = sdb_new0 ();
sdb_set (db, "somestring", "somevalue", 0);
sdb_set (db, "someint", "42", 0);
sdb_set (db, "somebiggerint", "0x00001337", 0);
return db;
}
bool test_config_save() {
RzConfig *config = rz_config_new (NULL);
rz_config_set (config, "somestring", "somevalue");
rz_config_set_i (config, "someint", 42);
rz_config_set_i (config, "somebiggerint", 0x1337);
rz_config_lock (config, true);
Sdb *db = sdb_new0 ();
rz_serialize_config_save (db, config);
rz_config_free (config);
Sdb *expected = ref_db ();
assert_sdb_eq (db, expected, "config save");
sdb_free (db);
sdb_free (expected);
mu_end;
}
bool test_config_load() {
RzConfig *config = rz_config_new (NULL);
rz_config_set (config, "somestring", "someoldvalue");
rz_config_set_i (config, "someint", 0);
rz_config_set_i (config, "somebiggerint", 0);
rz_config_lock (config, true);
Sdb *db = ref_db ();
sdb_set (db, "sneaky", "not part of config", 0);
bool suck = rz_serialize_config_load (db, config, NULL);
sdb_free (db);
mu_assert ("load success", suck);
mu_assert_eq (rz_list_length (config->nodes), 3, "count after load");
mu_assert_streq (rz_config_get (config, "somestring"), "somevalue", "loaded config string");
mu_assert_eq_fmt (rz_config_get_i (config, "someint"), (ut64)42, "loaded config int", "%"PFMT64u);
mu_assert_eq_fmt (rz_config_get_i (config, "somebiggerint"), (ut64)0x1337, "loaded config bigger int", "0x%"PFMT64x);
rz_config_free (config);
mu_end;
}
int all_tests() {
mu_run_test (test_config_save);
mu_run_test (test_config_load);
return tests_passed != tests_run;
}
int main(int argc, char **argv) {
return all_tests();
}

View file

@ -0,0 +1,241 @@
#include <rz_flag.h>
#include "minunit.h"
#include "test_sdb.h"
Sdb *ref_0_db() {
Sdb *db = sdb_new0 ();
sdb_set (db, "base", "-1337", 0);
sdb_set (db, "realnames", "1", 0);
Sdb *spaces_db = sdb_ns (db, "spaces", true);
sdb_set (spaces_db, "name", "fs", 0);
sdb_set (spaces_db, "spacestack", "[\"reveries\"]", 0);
Sdb *spaces_spaces_db = sdb_ns (spaces_db, "spaces", true);
sdb_set (spaces_spaces_db, "ghost", "s", 0);
sdb_set (spaces_spaces_db, "reveries", "s", 0);
Sdb *tags_db = sdb_ns (db, "tags", true);
sdb_set (tags_db, "tag."PERTURBATOR, PERTURBATOR, 0);
sdb_set (tags_db, "tag.lotus", "eater", 0);
Sdb *zones_db = sdb_ns (db, "zones", true);
sdb_set (zones_db, "blackwater park", "{\"from\":12345,\"to\":12648243}", 0);
sdb_set (zones_db, PERTURBATOR, "{\"from\":3735928559,\"to\":18446744073709551614}", 0);
Sdb *flags_db = sdb_ns (db, "flags", true);
sdb_set (flags_db, "damnation", "{\"realname\":\"Damnation\",\"demangled\":true,\"offset\":3582,\"size\":16,\"space\":\"reveries\",\"color\":\"white\",\"comment\":\"windowpane\",\"alias\":\"d4mn4t10n\"}", 0);
sdb_set (flags_db, "d4mn4t10n", "{\"realname\":\"d4mn4t10n\",\"demangled\":false,\"offset\":3582,\"size\":1}", 0);
sdb_set (flags_db, "deliverance", "{\"realname\":\"deliverance\",\"demangled\":false,\"offset\":66,\"size\":19}", 0);
return db;
}
RzFlag *ref_0_flag() {
RzFlag *flag = rz_flag_new ();
flag->base = -1337;
flag->realnames = true;
rz_flag_set (flag, "deliverance", 0x42 + 1337, 0x13);
rz_flag_set (flag, "d4mn4t10n", 0x1337, 1);
rz_flag_space_set (flag, "ghost");
rz_flag_space_set (flag, "reveries");
RzFlagItem *damnation = rz_flag_set (flag, "damnation", 0x1337, 0x10);
damnation->demangled = true;
rz_flag_item_set_realname (damnation, "Damnation");
rz_flag_item_set_color (damnation, "white");
rz_flag_item_set_comment (damnation, "windowpane");
rz_flag_item_set_alias (damnation, "d4mn4t10n");
rz_flag_tags_set (flag, "lotus", "eater");
rz_flag_tags_set (flag, PERTURBATOR, PERTURBATOR);
rz_flag_zone_add (flag, PERTURBATOR, 0xdeadbeef);
rz_flag_zone_add (flag, PERTURBATOR, UT64_MAX - 1);
rz_flag_zone_add (flag, "blackwater park", 0xc0ff33);
rz_flag_zone_add (flag, "blackwater park", 12345);
return flag;
}
Sdb *ref_1_db() {
Sdb *db = sdb_new0 ();
sdb_set (db, "base", "0", 0);
sdb_set (db, "realnames", "0", 0);
Sdb *spaces_db = sdb_ns (db, "spaces", true);
sdb_set (spaces_db, "name", "fs", 0);
sdb_set (spaces_db, "spacestack", "[\"*\"]", 0);
sdb_ns (spaces_db, "spaces", true);
sdb_ns (db, "tags", true);
sdb_ns (db, "zones", true);
sdb_ns (db, "flags", true);
return db;
}
RzFlag *ref_1_flag() {
RzFlag *flag = rz_flag_new ();
flag->base = 0;
flag->realnames = false;
return flag;
}
static bool test_save(RzFlag *flag, Sdb *ref) {
Sdb *db = sdb_new0 ();
rz_serialize_flag_save (db, flag);
assert_sdb_eq (db, ref, "save");
sdb_free (db);
sdb_free (ref);
rz_flag_free (flag);
return true;
}
static bool space_eq(RSpace *actual, RSpace *expected) {
mu_assert ("space null", (!actual) == (!expected));
if (expected != NULL) {
mu_assert_streq (actual->name, expected->name, "space name");
}
return true;
}
static bool spaces_eq(RSpaces *actual, RSpaces *expected) {
assert_streq_null (actual->name, expected->name, "spaces name");
RBIter actual_iter = rz_rbtree_first (actual->spaces);
RBIter expected_iter = rz_rbtree_first (expected->spaces);
while (rz_rbtree_iter_has (&actual_iter) && rz_rbtree_iter_has (&expected_iter)) {
RSpace *actual_space = rz_rbtree_iter_get (&actual_iter, RSpace, rb);
RSpace *expected_space = rz_rbtree_iter_get (&expected_iter, RSpace, rb);
if (!space_eq (actual_space, expected_space)) {
return false;
}
rz_rbtree_iter_next (&actual_iter);
rz_rbtree_iter_next (&expected_iter);
}
mu_assert ("spaces count", !rz_rbtree_iter_has (&actual_iter) && !rz_rbtree_iter_has (&expected_iter));
if (!space_eq (actual->current, expected->current)) {
return false;
}
RzListIter *actual_stack_iter = rz_list_iterator (actual->spacestack);
RzListIter *expected_stack_iter = rz_list_iterator (expected->spacestack);
while (actual_stack_iter && expected_stack_iter) {
RSpace *actual_space = rz_list_iter_get (actual_stack_iter);
RSpace *expected_space = rz_list_iter_get (expected_stack_iter);
if (!space_eq (actual_space, expected_space)) {
return false;
}
}
mu_assert ("spacestack count", !actual_stack_iter && !expected_stack_iter);
return true;
}
typedef struct {
bool equal;
RzFlag *other;
} FlagCmpCtx;
static bool flag_cmp(RzFlagItem *actual, RzFlagItem *expected) {
mu_assert_notnull (expected, "flag");
assert_streq_null (actual->realname, expected->realname, "flag realname");
mu_assert_eq (actual->demangled, expected->demangled, "flag demangled");
mu_assert_eq_fmt (actual->offset, expected->offset, "flag offset", "0x%"PFMT64x);
mu_assert_eq_fmt (actual->size, expected->size, "flag size", "0x%"PFMT64x);
mu_assert_eq (!actual->space, !expected->space, "flag space null");
if (expected->space) {
mu_assert_streq (actual->space->name, expected->space->name, "flag space");
}
assert_streq_null (actual->color, expected->color, "flag color");
assert_streq_null (actual->comment, expected->comment, "flag comment");
assert_streq_null (actual->alias, expected->alias, "flag alias");
return true;
}
static bool flag_cmp_cb(RzFlagItem *fi, void *user) {
FlagCmpCtx *ctx = user;
RzFlagItem *fo = rz_flag_get (ctx->other, fi->name);
if(!flag_cmp (fi, fo)) {
ctx->equal = false;
return false;
}
return true;
}
static bool test_load(Sdb *db, RzFlag *ref) {
RzFlag *flag = rz_flag_new ();
bool suck = rz_serialize_flag_load (db, flag, NULL);
sdb_free (db);
mu_assert ("load success", suck);
if (!spaces_eq (&flag->spaces, &ref->spaces)) {
return false;
}
size_t zones_length_actual = flag->zones ? rz_list_length (flag->zones) : 0;
size_t zones_length_expect = ref->zones ? rz_list_length (ref->zones) : 0;
mu_assert_eq (zones_length_actual, zones_length_expect, "zones count");
RzListIter *actual_iter;
RzFlagZoneItem *actual_zone;
rz_list_foreach (flag->zones, actual_iter, actual_zone) {
RzListIter *expected_iter;
RzFlagZoneItem *expected_zone;
rz_list_foreach (ref->zones, expected_iter, expected_zone) {
if (strcmp (actual_zone->name, expected_zone->name) != 0) {
continue;
}
mu_assert_streq (actual_zone->name, expected_zone->name, "zone name");
mu_assert_eq_fmt (actual_zone->from, expected_zone->from, "zone from", "0x%"PFMT64x);
mu_assert_eq_fmt (actual_zone->to, expected_zone->to, "zone from", "0x%"PFMT64x);
goto kontinju;
}
mu_assert ("zone", false);
kontinju:
continue;
}
mu_assert_eq_fmt (flag->base, ref->base, "base", "0x%"PFMT64x);
mu_assert_eq (flag->realnames, ref->realnames, "realnames");
assert_sdb_eq (flag->tags, ref->tags, "tags");
mu_assert_eq (rz_flag_count (flag, NULL), rz_flag_count (ref, NULL), "flags count");
FlagCmpCtx cmp_ctx = { true, ref };
rz_flag_foreach (flag, flag_cmp_cb, &cmp_ctx);
rz_flag_free (flag);
rz_flag_free (ref);
return true;
}
#define TEST_CALL(name, call) \
bool name() { \
if (!(call)) { \
return false; \
} \
mu_end; \
}
TEST_CALL (test_flag_0_save, test_save(ref_0_flag (), ref_0_db ()));
TEST_CALL (test_flag_1_save, test_save(ref_1_flag (), ref_1_db ()));
TEST_CALL (test_flag_0_load, test_load(ref_0_db (), ref_0_flag ()));
TEST_CALL (test_flag_1_load, test_load(ref_1_db (), ref_1_flag ()));
int all_tests() {
mu_run_test (test_flag_0_save);
mu_run_test (test_flag_1_save);
mu_run_test (test_flag_0_load);
mu_run_test (test_flag_1_load);
return tests_passed != tests_run;
}
int main(int argc, char **argv) {
return all_tests();
}

View file

@ -0,0 +1,155 @@
#include <rz_util/rz_spaces.h>
#include "minunit.h"
#include "test_sdb.h"
bool test_spaces_save(void) {
RSpaces *spaces = rz_spaces_new ("myspaces");
rz_spaces_add (spaces, "a");
rz_spaces_add (spaces, "b");
rz_spaces_add (spaces, "c");
rz_spaces_add (spaces, PERTURBATOR);
Sdb *db = sdb_new0 ();
rz_serialize_spaces_save (db, spaces);
Sdb *expected = sdb_new0 ();
sdb_set (expected, "name", "myspaces", 0);
sdb_set (expected, "spacestack", "[\"*\"]", 0);
Sdb *expected_spaces = sdb_ns (expected, "spaces", true);
sdb_set (expected_spaces, "a", "s", 0);
sdb_set (expected_spaces, "b", "s", 0);
sdb_set (expected_spaces, "c", "s", 0);
sdb_set (expected_spaces, PERTURBATOR, "s", 0);
assert_sdb_eq (db, expected, "spaces save (no current, empty stack)");
sdb_free (db);
rz_spaces_set (spaces, PERTURBATOR);
db = sdb_new0 ();
rz_serialize_spaces_save (db, spaces);
sdb_set (expected, "spacestack", "[\""PERTURBATOR_JSON"\"]", 0);
assert_sdb_eq (db, expected, "spaces save (current, empty stack)");
sdb_free (db);
rz_spaces_push (spaces, "a");
rz_spaces_push (spaces, "b");
db = sdb_new0 ();
rz_serialize_spaces_save (db, spaces);
sdb_set (expected, "spacestack", "[\""PERTURBATOR_JSON"\",\"a\",\"b\"]", 0);
assert_sdb_eq (db, expected, "spaces save (current, stack)");
sdb_free (db);
sdb_free (expected);
rz_spaces_free (spaces);
mu_end;
}
bool test_spaces_load_noname_nostack(void) {
Sdb *db = sdb_new0 ();
sdb_set (db, "name", "myspaces", 0);
sdb_set (db, "spacestack", "[\"*\"]", 0);
Sdb *db_spaces = sdb_ns (db, "spaces", true);
sdb_set (db_spaces, "a", "s", 0);
sdb_set (db_spaces, "b", "s", 0);
sdb_set (db_spaces, "c", "s", 0);
sdb_set (db_spaces, PERTURBATOR, "s", 0);
RSpaces *spaces = rz_spaces_new ("fixed name");
bool suck = rz_serialize_spaces_load (db, spaces, false, NULL);
mu_assert ("load success", suck);
mu_assert_streq (spaces->name, "fixed name", "spaces load without name");
mu_assert_null (spaces->current, "spaces load no current");
mu_assert_eq (rz_list_length (spaces->spacestack), 0, "empty spacestack");
RBIter rbiter;
RSpace *space;
int i = 0;
rz_rbtree_foreach (spaces->spaces, rbiter, space, RSpace, rb) {
switch (i) {
case 0:
mu_assert_streq (space->name, PERTURBATOR, "loaded spaces");
break;
case 1:
mu_assert_streq (space->name, "a", "loaded spaces");
break;
case 2:
mu_assert_streq (space->name, "b", "loaded spaces");
break;
case 3:
mu_assert_streq (space->name, "c", "loaded spaces");
break;
default:
break;
}
i++;
}
mu_assert_eq (i, 4, "loaded spaces count");
rz_spaces_free (spaces);
sdb_free (db);
mu_end;
}
bool test_spaces_load_name_stack(void) {
Sdb *db = sdb_new0 ();
sdb_set (db, "name", "myspaces", 0);
sdb_set (db, "spacestack", "[\"a\",\"*\",\""PERTURBATOR_JSON"\",\"b\",\""PERTURBATOR_JSON"\"]", 0);
Sdb *db_spaces = sdb_ns (db, "spaces", true);
sdb_set (db_spaces, "a", "s", 0);
sdb_set (db_spaces, "b", "s", 0);
sdb_set (db_spaces, "c", "s", 0);
sdb_set (db_spaces, PERTURBATOR, "s", 0);
RSpaces *spaces = rz_spaces_new ("");
bool suck = rz_serialize_spaces_load (db, spaces, true, NULL);
mu_assert ("load success", suck);
mu_assert_streq (spaces->name, "myspaces", "loaded name");
mu_assert_notnull (spaces->current, "current non-null");
mu_assert_streq (spaces->current->name, PERTURBATOR, "current");
mu_assert_eq (rz_list_length (spaces->spacestack), 4, "spacestack size");
mu_assert_streq ((const char *)rz_list_get_n (spaces->spacestack, 0), "a", "spacestack");
mu_assert_streq ((const char *)rz_list_get_n (spaces->spacestack, 1), "*", "spacestack");
mu_assert_streq ((const char *)rz_list_get_n (spaces->spacestack, 2), PERTURBATOR, "spacestack");
mu_assert_streq ((const char *)rz_list_get_n (spaces->spacestack, 3), "b", "spacestack");
RBIter rbiter;
RSpace *space;
int i = 0;
rz_rbtree_foreach (spaces->spaces, rbiter, space, RSpace, rb) {
switch (i) {
case 0:
mu_assert_streq (space->name, PERTURBATOR, "loaded spaces");
break;
case 1:
mu_assert_streq (space->name, "a", "loaded spaces");
break;
case 2:
mu_assert_streq (space->name, "b", "loaded spaces");
break;
case 3:
mu_assert_streq (space->name, "c", "loaded spaces");
break;
default:
break;
}
i++;
}
mu_assert_eq (i, 4, "loaded spaces count");
rz_spaces_free (spaces);
sdb_free (db);
mu_end;
}
int all_tests() {
mu_run_test (test_spaces_save);
mu_run_test (test_spaces_load_noname_nostack);
mu_run_test (test_spaces_load_name_stack);
return tests_passed != tests_run;
}
int main(int argc, char **argv) {
return all_tests();
}