Add new Projects Implementation (#12)
This commit is contained in:
parent
404d5b23f5
commit
4e18226c8d
56 changed files with 5602 additions and 1805 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
2079
librz/anal/serialize_anal.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ rz_config_sources = [
|
|||
'callback.c',
|
||||
'config.c',
|
||||
'hold.c',
|
||||
'serialize_config.c'
|
||||
]
|
||||
|
||||
rz_config = library('rz_config', rz_config_sources,
|
||||
|
|
|
|||
39
librz/config/serialize_config.c
Normal file
39
librz/config/serialize_config.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
64
librz/core/serialize_core.c
Normal file
64
librz/core/serialize_core.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
329
librz/flag/serialize_flag.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
35
librz/include/rz_project.h
Normal file
35
librz/include/rz_project.h
Normal 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
|
||||
13
librz/include/rz_util/rz_serialize.h
Normal file
13
librz/include/rz_util/rz_serialize.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
113
librz/io/serialize_io.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
||||
|
|
|
|||
51
librz/util/serialize_helper.h
Normal file
51
librz/util/serialize_helper.h
Normal 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
|
||||
110
librz/util/serialize_spaces.c
Normal file
110
librz/util/serialize_spaces.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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'
|
||||
]
|
||||
|
||||
|
|
|
|||
2
shlr/sdb
2
shlr/sdb
|
|
@ -1 +1 @@
|
|||
Subproject commit f0902e0ad52c89468d0dfea1e99598a15aa023ad
|
||||
Subproject commit 807d74f0488cb010501e8e908938a747e1c8945d
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
115
test/db/cmd/project
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ if get_option('enable_tests')
|
|||
'queue',
|
||||
'rz_test',
|
||||
'rbtree',
|
||||
'serialize_anal',
|
||||
'serialize_config',
|
||||
'serialize_flag',
|
||||
'serialize_spaces',
|
||||
'sign',
|
||||
'skiplist',
|
||||
'spaces',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
1847
test/unit/test_serialize_anal.c
Normal file
1847
test/unit/test_serialize_anal.c
Normal file
File diff suppressed because it is too large
Load diff
61
test/unit/test_serialize_config.c
Normal file
61
test/unit/test_serialize_config.c
Normal 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();
|
||||
}
|
||||
241
test/unit/test_serialize_flag.c
Normal file
241
test/unit/test_serialize_flag.c
Normal 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();
|
||||
}
|
||||
155
test/unit/test_serialize_spaces.c
Normal file
155
test/unit/test_serialize_spaces.c
Normal 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();
|
||||
}
|
||||
Loading…
Reference in a new issue