Added ev and evj command

This commit is contained in:
yetmorecode 2017-02-22 23:39:09 +01:00 committed by radare
parent 5398cc78f8
commit ca56112550
4 changed files with 156 additions and 34 deletions

View File

@ -16,6 +16,7 @@ R_API RConfigNode* r_config_node_new(const char *name, const char *value) {
node->value = strdup (value? value: "");
node->flags = CN_RW | CN_STR;
node->i_value = r_num_get (NULL, value);
node->options = r_list_new ();
return node;
}
@ -30,6 +31,7 @@ R_API RConfigNode* r_config_node_clone(RConfigNode *n) {
cn->i_value = n->i_value;
cn->flags = n->flags;
cn->setter = n->setter;
cn->options = r_list_clone (n->options);
return cn;
}
@ -41,15 +43,108 @@ R_API void r_config_node_free(void *n) {
free (node->name);
free (node->desc);
free (node->value);
r_list_free (node->options);
free (node);
}
static void config_print_value_json(RConfig *cfg, RConfigNode *node) {
const char *val = node->value;
if (node->flags & CN_BOOL || node->flags & CN_INT || node->flags & CN_OFFT) {
if (!val) {
val = "0";
}
if (!strncmp (val, "0x", 2)) {
ut64 n = r_num_get (NULL, val);
cfg->cb_printf ("%"PFMT64d, n);
} else if (r_str_isnumber (val) || !strcmp (val, "true") || !strcmp (val, "false")) {
cfg->cb_printf ("%s", val);
} else {
char *sval = r_str_escape (val);
cfg->cb_printf ("\"%s\"", sval);
free (sval);
}
} else {
cfg->cb_printf ("\"%s\"", val);
}
}
static void config_print_node(RConfig *cfg, RConfigNode *node, const char *pfx, const char *sfx, bool verbose, bool json) {
char *option;
bool is_first;
RListIter *iter;
char *es = NULL;
if (json) {
if (verbose) {
cfg->cb_printf ("{");
cfg->cb_printf ("\"name\":\"%s\",", node->name);
cfg->cb_printf ("\"value\":");
config_print_value_json (cfg, node);
cfg->cb_printf (",\"type\":\"%s\",", r_config_node_type (node));
es = r_str_escape (node->desc);
if (es) {
cfg->cb_printf ("\"desc\":\"%s\",", es);
free (es);
}
cfg->cb_printf ("\"ro\":%s", node->flags & CN_RO ? "true" : "false");
if (!r_list_empty (node->options)) {
is_first = true;
cfg->cb_printf (",\"options\":[");
r_list_foreach (node->options, iter, option) {
es = r_str_escape (option);
if (es) {
if (is_first) {
is_first = false;
} else {
cfg->cb_printf (",");
}
cfg->cb_printf ("\"%s\"", es);
free (es);
}
}
cfg->cb_printf ("]");
}
cfg->cb_printf ("}");
} else {
cfg->cb_printf ("\"%s\":", node->name);
config_print_value_json (cfg, node);
}
} else {
if (verbose) {
cfg->cb_printf ("%s%s = %s%s %s; %s", pfx,
node->name, node->value, sfx,
node->flags & CN_RO ? "(ro)" : "",
node->desc);
if (!r_list_empty (node->options)) {
is_first = true;
cfg->cb_printf(" [");
r_list_foreach (node->options, iter, option) {
if (is_first) {
is_first = false;
} else {
cfg->cb_printf(", ");
}
cfg->cb_printf("%s", option);
}
cfg->cb_printf("]");
}
cfg->cb_printf ("\n");
} else {
cfg->cb_printf ("%s%s = %s%s\n", pfx,
node->name, node->value, sfx);
}
}
}
R_API void r_config_list(RConfig *cfg, const char *str, int rad) {
RConfigNode *node;
RListIter *iter;
const char *sfx = "";
const char *pfx = "";
int len = 0;
bool verbose = false;
bool json = false;
bool json_is_first = false;
if (!STRNULL (str)) {
str = r_str_chop_ro (str);
@ -60,11 +155,12 @@ R_API void r_config_list(RConfig *cfg, const char *str, int rad) {
pfx = "\"e ";
sfx = "\"";
/* fallthrou */
case 'v':
verbose = true;
case 0:
r_list_foreach (cfg->nodes, iter, node) {
if (!str || (str && (!strncmp (str, node->name, len)))) {
cfg->cb_printf ("%s%s = %s%s\n", pfx,
node->name, node->value, sfx);
config_print_node (cfg, node, pfx, sfx, verbose, json);
}
}
break;
@ -83,39 +179,33 @@ R_API void r_config_list(RConfig *cfg, const char *str, int rad) {
cfg->cb_printf ("%s\n", node->name);
}
break;
case 'J':
verbose = true;
case 'j':
cfg->cb_printf ("{");
json = true;
json_is_first = true;
if (verbose) {
cfg->cb_printf ("[");
} else {
cfg->cb_printf ("{");
}
r_list_foreach (cfg->nodes, iter, node) {
if (!str || (str && (!strncmp (str, node->name, len)))) {
if (!str || !strncmp (str, node->name, len)) {
const char *val = node->value;
if (node->flags & CN_BOOL || node->flags & CN_INT || node->flags & CN_OFFT) {
if (!val) {
val = "0";
}
if (!strncmp (val, "0x", 2)) {
ut64 n = r_num_get (NULL, val);
cfg->cb_printf ("\"%s\":%"PFMT64d,
node->name, n);
} else if (r_str_isnumber (val) || !strcmp (val, "true") || !strcmp (val, "false")) {
cfg->cb_printf ("\"%s\":%s",
node->name, val);
} else {
char *sval = r_str_escape (val);
cfg->cb_printf ("\"%s\":\"%s\"", node->name, sval);
free (sval);
}
} else {
cfg->cb_printf ("\"%s\":\"%s\"",
node->name, val);
}
if (iter->n) {
if (!json_is_first) {
cfg->cb_printf (",");
} else {
json_is_first = false;
}
config_print_node (cfg, node, pfx, sfx, verbose, json);
}
}
}
cfg->cb_printf ("}\n");
if (verbose) {
cfg->cb_printf ("]\n");
} else {
cfg->cb_printf ("}\n");
}
break;
}
}

View File

@ -2,10 +2,14 @@
#include <r_core.h>
#define SETI(x,y,z) r_config_node_desc(r_config_set_i(cfg,x,y), z);
#define SETICB(w,x,y,z) r_config_node_desc(r_config_set_i_cb(cfg,w,x,y), z);
#define SETPREF(x,y,z) r_config_node_desc(r_config_set(cfg,x,y), z);
#define SETCB(w,x,y,z) r_config_node_desc(r_config_set_cb(cfg,w,x,y), z);
#define NODECB(w,x,y) r_config_set_cb(cfg,w,x,y)
#define NODEICB(w,x,y) r_config_set_i_cb(cfg,w,x,y)
#define SETDESC(x,y) r_config_node_desc(x,y)
#define SETOPTION(x,y) r_list_append((x)->options,strdup(y))
#define SETI(x,y,z) SETDESC(r_config_set_i(cfg,x,y), z);
#define SETICB(w,x,y,z) SETDESC(NODEICB(w,x,y), z);
#define SETPREF(x,y,z) SETDESC(r_config_set(cfg,x,y), z);
#define SETCB(w,x,y,z) SETDESC(NODECB(w,x,y), z);
/* TODO: use loop here */
/*------------------------------------------------------------------------------------------*/
@ -788,7 +792,11 @@ static int cb_dbg_btalgo(void *user, void *data) {
RCore *core = (RCore*) user;
RConfigNode *node = (RConfigNode*) data;
if (*node->value == '?') {
r_cons_printf ("default\nfuzzy\nanal\n");
RListIter *iter;
char *option;
r_list_foreach (node->options, iter, option) {
r_cons_printf ("%s\n", option);
}
return false;
}
free (core->dbg->btalgo);
@ -1733,6 +1741,7 @@ static char *getViewerPath() {
R_API int r_core_config_init(RCore *core) {
int i;
char buf[128], *p, *tmpdir;
RConfigNode *n;
RConfig *cfg = core->config = r_config_new (core);
if (!cfg) {
return 0;
@ -1998,7 +2007,11 @@ R_API int r_core_config_init(RCore *core) {
SETPREF("dbg.bpinmaps", "true", "Force breakpoints to be inside a valid map");
SETCB("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
SETCB("dbg.btalgo", "fuzzy", &cb_dbg_btalgo, "Select backtrace algorithm");
n = NODECB("dbg.btalgo", "fuzzy", &cb_dbg_btalgo);
SETDESC(n, "Select backtrace algorithm");
SETOPTION(n, "default");
SETOPTION(n, "fuzzy");
SETOPTION(n, "anal");
SETCB("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");
SETCB("dbg.clone", "false", &cb_dbg_clone, "Stop execution if new thread is created");
SETCB("dbg.aftersyscall", "true", &cb_dbg_aftersc, "Stop execution before the syscall is executed (see dcs)");

View File

@ -214,6 +214,24 @@ static int cmd_eval(void *data, const char *input) {
case 'j': // json
r_config_list (core->config, NULL, 'j');
break;
case 'v': // verbose
switch (input[1]) {
default:
if (strlen (input) > 2) {
r_config_list (core->config, input + 2, 'v');
} else {
r_config_list (core->config, NULL, 'v');
}
break;
case 'j':
if (strlen (input) > 3) {
r_config_list (core->config, input + 3, 'J');
} else {
r_config_list (core->config, NULL, 'J');
}
break;
}
break;
case 'q': // quiet list of eval keys
r_config_list (core->config, NULL, 'q');
break;
@ -351,7 +369,6 @@ static int cmd_eval(void *data, const char *input) {
r_core_config_init (core);
//eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
break;
case 'v': eprintf ("Invalid command '%s'. Use 'e?'\n", input); break;
case '*': r_config_list (core->config, NULL, 1); break;
case '?':
switch (input[1]) {
@ -362,7 +379,7 @@ static int cmd_eval(void *data, const char *input) {
"Usage:", "e [var[=value]]", "Evaluable vars",
"e","?asm.bytes", "show description",
"e", "??", "list config vars with description",
"e", "", "list config vars",
"e|ej", "", "list config vars (in JSON)",
"e-", "", "reset config vars",
"e*", "", "dump config vars in r commands",
"e!", "a", "invert the boolean value of 'a' var",
@ -370,6 +387,7 @@ static int cmd_eval(void *data, const char *input) {
"er", " [key]", "set config key as readonly. no way back",
"ec", " [k] [color]", "set color for given key (prompt, offset, ...)",
"et", " [key]", "show type of given config variable",
"ev|evj", " [key]", "list config vars in verbose format (in JSON)",
"e", " a", "get value of var 'a'",
"e", " a=b", "set var 'a' the 'b' value",
"e var=?", "", "print all valid values of var",

View File

@ -30,6 +30,7 @@ typedef struct r_config_node_t {
RConfigCallback getter;
RConfigCallback setter;
char *desc;
RList *options;
} RConfigNode;
R_API const char *r_config_node_type(RConfigNode *node);