mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-27 15:10:53 +00:00
Implement agd*
based commands (#14809)
* ag* commands fully functional * Indent and r_return usage * All agd* commands functional now * Graphs are pretty now * Refactoring the code * Fixed assertion error * Fixed broken agf
This commit is contained in:
parent
a7bf98bca7
commit
a0354d4cfd
@ -72,6 +72,11 @@ static struct {
|
||||
{ "graph.current", r_offsetof (RConsPrintablePalette, graph_current), r_offsetof (RConsPalette, graph_current) },
|
||||
{ "graph.traced", r_offsetof (RConsPrintablePalette, graph_traced), r_offsetof (RConsPalette, graph_traced) },
|
||||
|
||||
{ "graph.diff.unknown", r_offsetof (RConsPrintablePalette, graph_diff_unknown), r_offsetof (RConsPalette, graph_diff_unknown) },
|
||||
{ "graph.diff.new", r_offsetof (RConsPrintablePalette, graph_diff_new), r_offsetof (RConsPalette, graph_diff_new) },
|
||||
{ "graph.diff.match", r_offsetof (RConsPrintablePalette, graph_diff_match), r_offsetof (RConsPalette, graph_diff_match) },
|
||||
{ "graph.diff.unmatch", r_offsetof (RConsPrintablePalette, graph_diff_unmatch), r_offsetof (RConsPalette, graph_diff_unmatch) },
|
||||
|
||||
{ "gui.cflow", r_offsetof (RConsPrintablePalette, gui_cflow), r_offsetof (RConsPalette, gui_cflow) },
|
||||
{ "gui.dataoffset", r_offsetof (RConsPrintablePalette, gui_dataoffset), r_offsetof (RConsPalette, gui_dataoffset) },
|
||||
{ "gui.background", r_offsetof (RConsPrintablePalette, gui_background), r_offsetof (RConsPalette, gui_background) },
|
||||
@ -227,6 +232,11 @@ R_API void r_cons_pal_init(RConsContext *ctx) {
|
||||
ctx->cpal.graph_trufae = (RColor) RColor_BLUE; // single jump
|
||||
ctx->cpal.graph_traced = (RColor) RColor_YELLOW;
|
||||
ctx->cpal.graph_current = (RColor) RColor_BLUE;
|
||||
ctx->cpal.graph_diff_unknown = (RColor) RColor_MAGENTA;
|
||||
ctx->cpal.graph_diff_new = (RColor) RColor_RED;
|
||||
ctx->cpal.graph_diff_match = (RColor) RColor_GRAY;
|
||||
ctx->cpal.graph_diff_unmatch = (RColor) RColor_YELLOW;
|
||||
|
||||
|
||||
r_cons_pal_free (ctx);
|
||||
ctx->pal.reset = Color_RESET; // reset is not user accessible, const char* is ok
|
||||
|
@ -317,6 +317,16 @@ static void tiny_RANode_print(const RAGraph *g, const RANode *n, int cur) {
|
||||
}
|
||||
}
|
||||
|
||||
static char *get_node_color (int color, int cur) {
|
||||
RCons *cons = r_cons_singleton ();
|
||||
if (color == -1) {
|
||||
return cur ? cons->context->pal.graph_box2 : cons->context->pal.graph_box;
|
||||
}
|
||||
return color ? (\
|
||||
color==R_ANAL_DIFF_TYPE_MATCH ? cons->context->pal.graph_diff_match:
|
||||
color==R_ANAL_DIFF_TYPE_UNMATCH? cons->context->pal.graph_diff_unmatch : cons->context->pal.graph_diff_new): cons->context->pal.graph_diff_unknown;
|
||||
}
|
||||
|
||||
static void normal_RANode_print(const RAGraph *g, const RANode *n, int cur) {
|
||||
ut32 center_x = 0, center_y = 0;
|
||||
ut32 delta_x = 0, delta_txt_x = 0;
|
||||
@ -324,6 +334,7 @@ static void normal_RANode_print(const RAGraph *g, const RANode *n, int cur) {
|
||||
char title[TITLE_LEN];
|
||||
char *body;
|
||||
int x, y;
|
||||
int color = n->difftype;
|
||||
const bool showTitle = g->show_node_titles;
|
||||
const bool showBody = g->show_node_body;
|
||||
|
||||
@ -401,18 +412,17 @@ static void normal_RANode_print(const RAGraph *g, const RANode *n, int cur) {
|
||||
|
||||
// TODO: check if node is traced or not and show proper color
|
||||
// This info must be stored inside RANode* from RCore*
|
||||
RCons *cons = r_cons_singleton ();
|
||||
if (g->show_node_bubble) {
|
||||
if (cur) {
|
||||
r_cons_canvas_circle (g->can, n->x, n->y, n->w, n->h, cons->context->pal.graph_box2);
|
||||
r_cons_canvas_circle (g->can, n->x, n->y, n->w, n->h, get_node_color(color, cur));
|
||||
} else {
|
||||
r_cons_canvas_circle(g->can, n->x, n->y, n->w, n->h, cons->context->pal.graph_box);
|
||||
r_cons_canvas_circle(g->can, n->x, n->y, n->w, n->h, get_node_color(color, cur));
|
||||
}
|
||||
} else {
|
||||
if (cur) {
|
||||
r_cons_canvas_box (g->can, n->x, n->y, n->w, n->h, cons->context->pal.graph_box2);
|
||||
r_cons_canvas_box (g->can, n->x, n->y, n->w, n->h, get_node_color(color, cur));
|
||||
} else {
|
||||
r_cons_canvas_box (g->can, n->x, n->y, n->w, n->h, cons->context->pal.graph_box);
|
||||
r_cons_canvas_box (g->can, n->x, n->y, n->w, n->h, get_node_color(color, cur));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3673,42 +3683,47 @@ R_API void r_agraph_set_title(RAGraph *g, const char *title) {
|
||||
sdb_set (g->db, "agraph.title", g->title, 0);
|
||||
}
|
||||
|
||||
R_API RANode *r_agraph_add_node(const RAGraph *g, const char *title, const char *body) {
|
||||
RANode *res = r_agraph_get_node (g, title);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
res = R_NEW0 (RANode);
|
||||
if (!res) {
|
||||
return NULL;
|
||||
}
|
||||
R_API RANode *r_agraph_add_node_with_color(const RAGraph *g, const char *title, const char *body, int color) {
|
||||
RANode *res = r_agraph_get_node (g, title);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
res = R_NEW0 (RANode);
|
||||
if (!res) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res->title = title? r_str_trunc_ellipsis (title, 255) : strdup ("");
|
||||
res->body = body? strdup (body): strdup ("");
|
||||
res->layer = -1;
|
||||
res->pos_in_layer = -1;
|
||||
res->is_dummy = false;
|
||||
res->is_reversed = false;
|
||||
res->klass = -1;
|
||||
res->gnode = r_graph_add_node (g->graph, res);
|
||||
sdb_num_set (g->nodes, res->title, (ut64) (size_t) res, 0);
|
||||
if (res->title) {
|
||||
char *s, *estr, *b;
|
||||
size_t len;
|
||||
sdb_array_add (g->db, "agraph.nodes", res->title, 0);
|
||||
b = strdup (res->body);
|
||||
len = strlen (b);
|
||||
if (len > 0 && b[len - 1] == '\n') {
|
||||
b[len - 1] = '\0';
|
||||
}
|
||||
estr = sdb_encode ((const void *) b, -1);
|
||||
//s = sdb_fmt ("base64:%s", estr);
|
||||
s = r_str_newf ("base64:%s", estr);
|
||||
free (estr);
|
||||
free (b);
|
||||
sdb_set (g->db, sdb_fmt ("agraph.nodes.%s.body", res->title), s, 0);
|
||||
}
|
||||
return res;
|
||||
res->title = title? r_str_trunc_ellipsis (title, 255) : strdup ("");
|
||||
res->body = body? strdup (body): strdup ("");
|
||||
res->layer = -1;
|
||||
res->pos_in_layer = -1;
|
||||
res->is_dummy = false;
|
||||
res->is_reversed = false;
|
||||
res->klass = -1;
|
||||
res->difftype = color;
|
||||
res->gnode = r_graph_add_node (g->graph, res);
|
||||
sdb_num_set (g->nodes, res->title, (ut64) (size_t) res, 0);
|
||||
if (res->title) {
|
||||
char *s, *estr, *b;
|
||||
size_t len;
|
||||
sdb_array_add (g->db, "agraph.nodes", res->title, 0);
|
||||
b = strdup (res->body);
|
||||
len = strlen (b);
|
||||
if (len > 0 && b[len - 1] == '\n') {
|
||||
b[len - 1] = '\0';
|
||||
}
|
||||
estr = sdb_encode ((const void *) b, -1);
|
||||
//s = sdb_fmt ("base64:%s", estr);
|
||||
s = r_str_newf ("base64:%s", estr);
|
||||
free (estr);
|
||||
free (b);
|
||||
sdb_set (g->db, sdb_fmt ("agraph.nodes.%s.body", res->title), s, 0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
R_API RANode *r_agraph_add_node(const RAGraph *g, const char *title, const char *body) {
|
||||
return r_agraph_add_node_with_color(g, title, body, -1);
|
||||
}
|
||||
|
||||
R_API bool r_agraph_del_node(const RAGraph *g, const char *title) {
|
||||
|
@ -970,6 +970,10 @@ error:
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *get_title(ut64 addr) {
|
||||
return r_str_newf ("0x%"PFMT64x, addr);
|
||||
}
|
||||
|
||||
/* decode and return the RAnalOp at the address addr */
|
||||
R_API RAnalOp* r_core_anal_op(RCore *core, ut64 addr, int mask) {
|
||||
int len;
|
||||
@ -1235,6 +1239,9 @@ static char *core_anal_graph_label(RCore *core, RAnalBlock *bb, int opts) {
|
||||
}
|
||||
oline = line;
|
||||
}
|
||||
} else if (opts & R_CORE_ANAL_STAR) {
|
||||
snprintf (cmd, sizeof (cmd), "pdb %d @ 0x%08" PFMT64x, bb->size, bb->addr);
|
||||
str = r_core_cmd_str (core, cmd);
|
||||
} else if (opts & R_CORE_ANAL_GRAPHBODY) {
|
||||
const bool scrColor = r_config_get (core->config, "scr.color");
|
||||
const bool scrUtf8 = r_config_get (core->config, "scr.utf8");
|
||||
@ -1244,10 +1251,10 @@ static char *core_anal_graph_label(RCore *core, RAnalBlock *bb, int opts) {
|
||||
cmdstr = r_core_cmd_str (core, cmd);
|
||||
r_config_set_i (core->config, "scr.color", scrColor);
|
||||
r_config_set_i (core->config, "scr.utf8", scrUtf8);
|
||||
}
|
||||
if (cmdstr) {
|
||||
str = r_str_escape_dot (cmdstr);
|
||||
free (cmdstr);
|
||||
if (cmdstr) {
|
||||
str = r_str_escape_dot (cmdstr);
|
||||
free (cmdstr);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@ -1272,18 +1279,347 @@ static void core_anal_color_curr_node(RCore *core, RAnalBlock *bbi) {
|
||||
free (pal_curr);
|
||||
}
|
||||
|
||||
static int core_anal_graph_construct_edges (RCore *core, RAnalFunction *fcn, int opts, PJ *pj, Sdb *DB) {
|
||||
RAnalBlock *bbi;
|
||||
RListIter *iter;
|
||||
int is_keva = opts & R_CORE_ANAL_KEYVALUE;
|
||||
int is_star = opts & R_CORE_ANAL_STAR;
|
||||
int is_json = opts & R_CORE_ANAL_JSON;
|
||||
int is_html = r_cons_singleton ()->is_html;
|
||||
char *pal_jump = palColorFor ("graph.true");
|
||||
char *pal_fail = palColorFor ("graph.false");
|
||||
char *pal_trfa = palColorFor ("graph.trufae");
|
||||
int nodes = 0;
|
||||
r_list_foreach (fcn->bbs, iter, bbi) {
|
||||
if (bbi->jump != UT64_MAX) {
|
||||
nodes++;
|
||||
if (is_keva) {
|
||||
char key[128];
|
||||
char val[128];
|
||||
snprintf (key, sizeof (key), "bb.0x%08"PFMT64x".to", bbi->addr);
|
||||
if (bbi->fail != UT64_MAX) {
|
||||
snprintf (val, sizeof (val), "0x%08"PFMT64x, bbi->jump);
|
||||
} else {
|
||||
snprintf (val, sizeof (val), "0x%08"PFMT64x ",0x%08"PFMT64x,
|
||||
bbi->jump, bbi->fail);
|
||||
}
|
||||
// bb.<addr>.to=<jump>,<fail>
|
||||
sdb_set (DB, key, val, 0);
|
||||
} else if (is_html) {
|
||||
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
|
||||
" <img class=\"connector-end\" src=\"img/arrow.gif\" /></div>\n",
|
||||
bbi->addr, bbi->jump);
|
||||
} else if (!is_json && !is_keva) {
|
||||
if (is_star) {
|
||||
char *from = get_title (bbi->addr);
|
||||
char *to = get_title (bbi->jump);
|
||||
r_cons_printf ("age %s %s\n", from, to);
|
||||
} else {
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"\" "
|
||||
"[color=\"%s\"];\n", bbi->addr, bbi->jump,
|
||||
bbi->fail != -1 ? pal_jump : pal_trfa);
|
||||
core_anal_color_curr_node (core, bbi);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bbi->fail != -1) {
|
||||
nodes++;
|
||||
if (is_html) {
|
||||
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
|
||||
" <img class=\"connector-end\" src=\"img/arrow.gif\"/></div>\n",
|
||||
bbi->addr, bbi->fail);
|
||||
} else if (!is_keva && !is_json) {
|
||||
if (is_star) {
|
||||
char *from = get_title (bbi->addr);
|
||||
char *to = get_title (bbi->fail);
|
||||
r_cons_printf ("age %s %s\n", from, to);
|
||||
} else {
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"\" "
|
||||
"[color=\"%s\"];\n", bbi->addr, bbi->fail, pal_fail);
|
||||
core_anal_color_curr_node (core, bbi);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bbi->switch_op) {
|
||||
RAnalCaseOp *caseop;
|
||||
RListIter *iter;
|
||||
|
||||
if (bbi->fail != UT64_MAX) {
|
||||
if (is_html) {
|
||||
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
|
||||
" <img class=\"connector-end\" src=\"img/arrow.gif\"/></div>\n",
|
||||
bbi->addr, bbi->fail);
|
||||
} else if (!is_keva && !is_json) {
|
||||
if (is_star) {
|
||||
char *from = get_title (bbi->addr);
|
||||
char *to = get_title (bbi->fail);
|
||||
r_cons_printf ("%age %s %s\n", from, to);
|
||||
} else {
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"\" "
|
||||
"[color=\"%s\"];\n", bbi->addr, bbi->fail, pal_fail);
|
||||
core_anal_color_curr_node (core, bbi);
|
||||
}
|
||||
}
|
||||
}
|
||||
r_list_foreach (bbi->switch_op->cases, iter, caseop) {
|
||||
nodes++;
|
||||
if (is_keva) {
|
||||
char key[128];
|
||||
snprintf (key, sizeof (key),
|
||||
"bb.0x%08"PFMT64x".switch.%"PFMT64d,
|
||||
bbi->addr, caseop->value);
|
||||
sdb_num_set (DB, key, caseop->jump, 0);
|
||||
snprintf (key, sizeof (key),
|
||||
"bb.0x%08"PFMT64x".switch", bbi->addr);
|
||||
sdb_array_add_num (DB, key, caseop->value, 0);
|
||||
} else if (is_html) {
|
||||
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
|
||||
" <img class=\"connector-end\" src=\"img/arrow.gif\"/></div>\n",
|
||||
caseop->addr, caseop->jump);
|
||||
} else if (!is_json && !is_keva){
|
||||
if (is_star) {
|
||||
char *from = get_title (caseop->addr);
|
||||
char *to = get_title (caseop->jump);
|
||||
r_cons_printf ("age %s %s\n", from ,to);
|
||||
} else {
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"\" " \
|
||||
"[color2=\"%s\"];\n", caseop->addr, caseop->jump, pal_fail);
|
||||
core_anal_color_curr_node (core, bbi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
static int core_anal_graph_construct_nodes (RCore *core, RAnalFunction *fcn, int opts, PJ *pj, Sdb *DB) {
|
||||
RAnalBlock *bbi;
|
||||
RListIter *iter;
|
||||
int is_keva = opts & R_CORE_ANAL_KEYVALUE;
|
||||
int is_star = opts & R_CORE_ANAL_STAR;
|
||||
int is_json = opts & R_CORE_ANAL_JSON;
|
||||
int is_html = r_cons_singleton ()->is_html;
|
||||
int left = 300;
|
||||
int top = 0;
|
||||
|
||||
int is_json_format_disasm = opts & R_CORE_ANAL_JSON_FORMAT_DISASM;
|
||||
char *pal_curr = palColorFor ("graph.current");
|
||||
char *pal_traced = palColorFor ("graph.traced");
|
||||
char *pal_box4 = palColorFor ("graph.box4");
|
||||
const char *font = r_config_get (core->config, "graph.font");
|
||||
bool color_current = r_config_get_i (core->config, "graph.gv.current");
|
||||
char *str;
|
||||
int nodes = 0;
|
||||
r_list_foreach (fcn->bbs, iter, bbi) {
|
||||
if (is_keva) {
|
||||
char key[128];
|
||||
sdb_array_push_num (DB, "bbs", bbi->addr, 0);
|
||||
snprintf (key, sizeof (key), "bb.0x%08"PFMT64x".size", bbi->addr);
|
||||
sdb_num_set (DB, key, bbi->size, 0); // bb.<addr>.size=<num>
|
||||
} else if (is_json) {
|
||||
RDebugTracepoint *t = r_debug_trace_get (core->dbg, bbi->addr);
|
||||
ut8 *buf = malloc (bbi->size);
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "offset", bbi->addr);
|
||||
pj_kn (pj, "size", bbi->size);
|
||||
if (bbi->jump != UT64_MAX) {
|
||||
pj_kn (pj, "jump", bbi->jump);
|
||||
}
|
||||
if (bbi->fail != -1) {
|
||||
pj_kn (pj, "fail", bbi->fail);
|
||||
}
|
||||
if (bbi->switch_op) {
|
||||
RAnalSwitchOp *op = bbi->switch_op;
|
||||
pj_k (pj, "switchop");
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "offset", op->addr);
|
||||
pj_kn (pj, "defval", op->def_val);
|
||||
pj_kn (pj, "maxval", op->max_val);
|
||||
pj_kn (pj, "minval", op->min_val);
|
||||
pj_k (pj, "cases");
|
||||
pj_a (pj);
|
||||
RAnalCaseOp *case_op;
|
||||
RListIter *case_iter;
|
||||
r_list_foreach (op->cases, case_iter, case_op) {
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "offset", case_op->addr);
|
||||
pj_kn (pj, "value", case_op->value);
|
||||
pj_kn (pj, "jump", case_op->jump);
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
}
|
||||
if (t) {
|
||||
pj_k (pj, "trace");
|
||||
pj_o (pj);
|
||||
pj_ki (pj, "count", t->count);
|
||||
pj_ki (pj, "times", t->times);
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_kn (pj, "colorize", bbi->colorize);
|
||||
pj_k (pj, "ops");
|
||||
pj_a (pj);
|
||||
if (buf) {
|
||||
r_io_read_at (core->io, bbi->addr, buf, bbi->size);
|
||||
if (is_json_format_disasm) {
|
||||
r_core_print_disasm (core->print, core, bbi->addr, buf, bbi->size, bbi->size, 0, 1, true, pj, NULL);
|
||||
} else {
|
||||
r_core_print_disasm_json (core, bbi->addr, buf, bbi->size, 0, pj);
|
||||
}
|
||||
free (buf);
|
||||
} else {
|
||||
eprintf ("cannot allocate %d byte(s)\n", bbi->size);
|
||||
}
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
continue;
|
||||
}
|
||||
if ((str = core_anal_graph_label (core, bbi, opts))) {
|
||||
if (opts & R_CORE_ANAL_GRAPHDIFF) {
|
||||
const char *difftype = bbi->diff? (\
|
||||
bbi->diff->type==R_ANAL_DIFF_TYPE_MATCH? "lightgray":
|
||||
bbi->diff->type==R_ANAL_DIFF_TYPE_UNMATCH? "yellow": "red"): "orange";
|
||||
const char *diffname = bbi->diff? (\
|
||||
bbi->diff->type==R_ANAL_DIFF_TYPE_MATCH? "match":
|
||||
bbi->diff->type==R_ANAL_DIFF_TYPE_UNMATCH? "unmatch": "new"): "unk";
|
||||
if (is_keva) {
|
||||
sdb_set (DB, "diff", diffname, 0);
|
||||
sdb_set (DB, "label", str, 0);
|
||||
} else if (!is_json) {
|
||||
nodes++;
|
||||
RConfigHold *hc = r_config_hold_new (core->config);
|
||||
r_config_hold_i (hc, "scr.color", "scr.utf8", "asm.offset", "asm.lines",
|
||||
"asm.cmt.right", "asm.lines.fcn", "asm.bytes", NULL);
|
||||
RDiff *d = r_diff_new ();
|
||||
r_config_set_i (core->config, "scr.color", 0);
|
||||
r_config_set_i (core->config, "scr.utf8", 0);
|
||||
r_config_set_i (core->config, "asm.offset", 0);
|
||||
r_config_set_i (core->config, "asm.lines", 0);
|
||||
r_config_set_i (core->config, "asm.cmt.right", 0);
|
||||
r_config_set_i (core->config, "asm.lines.fcn", 0);
|
||||
r_config_set_i (core->config, "asm.bytes", 0);
|
||||
|
||||
if (bbi->diff && bbi->diff->type != R_ANAL_DIFF_TYPE_MATCH && core->c2) {
|
||||
RCore *c = core->c2;
|
||||
RConfig *oc = c->config;
|
||||
char *str = r_core_cmd_strf (core, "pdb @ 0x%08"PFMT64x, bbi->addr);
|
||||
c->config = core->config;
|
||||
// XXX. the bbi->addr doesnt needs to be in the same address in core2
|
||||
char *str2 = r_core_cmd_strf (c, "pdb @ 0x%08"PFMT64x, bbi->diff->addr);
|
||||
char *diffstr = r_diff_buffers_to_string (d,
|
||||
(const ut8*)str, strlen (str),
|
||||
(const ut8*)str2, strlen(str2));
|
||||
|
||||
if (diffstr) {
|
||||
char *nl = strchr (diffstr, '\n');
|
||||
if (nl) {
|
||||
nl = strchr (nl + 1, '\n');
|
||||
if (nl) {
|
||||
nl = strchr (nl + 1, '\n');
|
||||
if (nl) {
|
||||
r_str_cpy (diffstr, nl + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
diffstr = r_str_replace (diffstr, "\n", "\\l", 1);
|
||||
diffstr = r_str_replace (diffstr, "\"", "'", 1);
|
||||
if (is_star) {
|
||||
char *title = get_title (bbi->addr);
|
||||
char *body_b64 = r_base64_encode_dyn (diffstr, -1);
|
||||
|
||||
if (!title || !body_b64) {
|
||||
free (body_b64);
|
||||
free (title);
|
||||
return false;
|
||||
}
|
||||
body_b64 = r_str_prepend (body_b64, "base64:");
|
||||
r_cons_printf ("agn %s %s %d\n", title, body_b64, bbi->diff->type);
|
||||
} else {
|
||||
r_cons_printf(" \"0x%08"PFMT64x"\" [fillcolor=\"%s\","
|
||||
"color=\"black\", fontname=\"Courier\","
|
||||
" label=\"%s\", URL=\"%s/0x%08"PFMT64x"\"]\n",
|
||||
bbi->addr, difftype, diffstr, fcn->name,
|
||||
bbi->addr);
|
||||
}
|
||||
free (diffstr);
|
||||
c->config = oc;
|
||||
} else {
|
||||
if (is_star) {
|
||||
char *title = get_title (bbi->addr);
|
||||
char *body_b64 = r_base64_encode_dyn (str, -1);
|
||||
|
||||
if (!title || !body_b64) {
|
||||
free (body_b64);
|
||||
free (title);
|
||||
return false;
|
||||
}
|
||||
body_b64 = r_str_prepend (body_b64, "base64:");
|
||||
r_cons_printf ("agn %s %s %d\n", title, body_b64, bbi->diff->type);
|
||||
} else {
|
||||
r_cons_printf(" \"0x%08"PFMT64x"\" [fillcolor=\"%s\","
|
||||
"color=\"black\", fontname=\"Courier\","
|
||||
" label=\"%s\", URL=\"%s/0x%08"PFMT64x"\"]\n",
|
||||
bbi->addr, difftype, str, fcn->name, bbi->addr);
|
||||
}
|
||||
}
|
||||
r_diff_free (d);
|
||||
r_config_set_i (core->config, "scr.color", 1);
|
||||
r_config_hold_free (hc);
|
||||
}
|
||||
} else {
|
||||
if (is_html) {
|
||||
nodes++;
|
||||
r_cons_printf ("<p class=\"block draggable\" style=\""
|
||||
"top: %dpx; left: %dpx; width: 400px;\" id=\""
|
||||
"_0x%08"PFMT64x"\">\n%s</p>\n",
|
||||
top, left, bbi->addr, str);
|
||||
left = left? 0: 600;
|
||||
if (!left) {
|
||||
top += 250;
|
||||
}
|
||||
} else if (!is_json && !is_keva) {
|
||||
bool current = r_anal_bb_is_in_offset (bbi, core->offset);
|
||||
const char *label_color = bbi->traced
|
||||
? pal_traced
|
||||
: (current && color_current)
|
||||
? pal_curr
|
||||
: pal_box4;
|
||||
const char *fill_color = (current || label_color == pal_traced)? pal_traced: "white";
|
||||
nodes++;
|
||||
if (is_star) {
|
||||
char *title = get_title (bbi->addr);
|
||||
char *body_b64 = r_base64_encode_dyn (str, -1);
|
||||
|
||||
if (!title || !body_b64) {
|
||||
free (body_b64);
|
||||
free (title);
|
||||
return false;
|
||||
}
|
||||
body_b64 = r_str_prepend (body_b64, "base64:");
|
||||
r_cons_printf ("agn %s %s %d\n", title, body_b64, bbi->diff->type);
|
||||
} else {
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" ["
|
||||
"URL=\"%s/0x%08"PFMT64x"\", fillcolor=\"%s\","
|
||||
"color=\"%s\", fontname=\"%s\","
|
||||
"label=\"%s\"]\n",
|
||||
bbi->addr, fcn->name, bbi->addr,
|
||||
fill_color, label_color, font, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
free (str);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
static int core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts, PJ *pj) {
|
||||
int is_html = r_cons_singleton ()->is_html;
|
||||
int is_json = opts & R_CORE_ANAL_JSON;
|
||||
int is_json_format_disasm = opts & R_CORE_ANAL_JSON_FORMAT_DISASM;
|
||||
int is_keva = opts & R_CORE_ANAL_KEYVALUE;
|
||||
RAnalBlock *bbi;
|
||||
RListIter *iter;
|
||||
int left = 300;
|
||||
int count = 0;
|
||||
int nodes = 0;
|
||||
int top = 0;
|
||||
char *str;
|
||||
Sdb *DB = NULL;
|
||||
char *pal_jump = palColorFor ("graph.true");
|
||||
char *pal_fail = palColorFor ("graph.false");
|
||||
@ -1291,8 +1627,6 @@ static int core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts, PJ *
|
||||
char *pal_curr = palColorFor ("graph.current");
|
||||
char *pal_traced = palColorFor ("graph.traced");
|
||||
char *pal_box4 = palColorFor ("graph.box4");
|
||||
const char *font = r_config_get (core->config, "graph.font");
|
||||
bool color_current = r_config_get_i (core->config, "graph.gv.current");
|
||||
if (!fcn || !fcn->bbs) {
|
||||
eprintf ("No fcn\n");
|
||||
return -1;
|
||||
@ -1338,266 +1672,14 @@ static int core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts, PJ *
|
||||
pj_kn (pj, "size", r_anal_fcn_size (fcn));
|
||||
pj_ki (pj, "stack", fcn->maxstack);
|
||||
pj_ks (pj, "type", r_anal_fcn_type_tostring (fcn->type));
|
||||
//pj_ki (pj, "cc", fcn->call) // TODO: calling convention
|
||||
if (fcn->dsc) {
|
||||
pj_ks (pj, "signature", fcn->dsc);
|
||||
}
|
||||
pj_k (pj, "blocks");
|
||||
pj_a (pj);
|
||||
}
|
||||
r_list_foreach (fcn->bbs, iter, bbi) {
|
||||
count ++;
|
||||
if (is_keva) {
|
||||
char key[128];
|
||||
sdb_array_push_num (DB, "bbs", bbi->addr, 0);
|
||||
snprintf (key, sizeof (key), "bb.0x%08"PFMT64x".size", bbi->addr);
|
||||
sdb_num_set (DB, key, bbi->size, 0); // bb.<addr>.size=<num>
|
||||
} else if (is_json) {
|
||||
RDebugTracepoint *t = r_debug_trace_get (core->dbg, bbi->addr);
|
||||
ut8 *buf = malloc (bbi->size);
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "offset", bbi->addr);
|
||||
pj_kn (pj, "size", bbi->size);
|
||||
if (bbi->jump != UT64_MAX) {
|
||||
pj_kn (pj, "jump", bbi->jump);
|
||||
}
|
||||
if (bbi->fail != -1) {
|
||||
pj_kn (pj, "fail", bbi->fail);
|
||||
}
|
||||
if (bbi->switch_op) {
|
||||
RAnalSwitchOp *op = bbi->switch_op;
|
||||
pj_k (pj, "switchop");
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "offset", op->addr);
|
||||
pj_kn (pj, "defval", op->def_val);
|
||||
pj_kn (pj, "maxval", op->max_val);
|
||||
pj_kn (pj, "minval", op->min_val);
|
||||
pj_k (pj, "cases");
|
||||
pj_a (pj);
|
||||
RAnalCaseOp *case_op;
|
||||
RListIter *case_iter;
|
||||
r_list_foreach (op->cases, case_iter, case_op) {
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "offset", case_op->addr);
|
||||
pj_kn (pj, "value", case_op->value);
|
||||
pj_kn (pj, "jump", case_op->jump);
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
}
|
||||
if (t) {
|
||||
pj_k (pj, "trace");
|
||||
pj_o (pj);
|
||||
pj_ki (pj, "count", t->count);
|
||||
pj_ki (pj, "times", t->times);
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_kn (pj, "colorize", bbi->colorize);
|
||||
pj_k (pj, "ops");
|
||||
pj_a (pj);
|
||||
if (buf) {
|
||||
r_io_read_at (core->io, bbi->addr, buf, bbi->size);
|
||||
if (is_json_format_disasm) {
|
||||
r_core_print_disasm (core->print, core, bbi->addr, buf, bbi->size, bbi->size, 0, 1, true, pj, NULL);
|
||||
} else {
|
||||
r_core_print_disasm_json (core, bbi->addr, buf, bbi->size, 0, pj);
|
||||
}
|
||||
free (buf);
|
||||
} else {
|
||||
eprintf ("cannot allocate %d byte(s)\n", bbi->size);
|
||||
}
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
continue;
|
||||
}
|
||||
if (bbi->jump != UT64_MAX) {
|
||||
nodes++;
|
||||
if (is_keva) {
|
||||
char key[128];
|
||||
char val[128];
|
||||
snprintf (key, sizeof (key), "bb.0x%08"PFMT64x".to", bbi->addr);
|
||||
if (bbi->fail != UT64_MAX) {
|
||||
snprintf (val, sizeof (val), "0x%08"PFMT64x, bbi->jump);
|
||||
} else {
|
||||
snprintf (val, sizeof (val), "0x%08"PFMT64x ",0x%08"PFMT64x,
|
||||
bbi->jump, bbi->fail);
|
||||
}
|
||||
// bb.<addr>.to=<jump>,<fail>
|
||||
sdb_set (DB, key, val, 0);
|
||||
} else if (is_html) {
|
||||
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
|
||||
" <img class=\"connector-end\" src=\"img/arrow.gif\" /></div>\n",
|
||||
bbi->addr, bbi->jump);
|
||||
} else if (!is_json) {
|
||||
//r_cons_printf ("\t\"0x%08"PFMT64x"_0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"_0x%08"PFMT64x"\" "
|
||||
// "[color=\"%s\"];\n", fcn->addr, bbi->addr, fcn->addr, bbi->jump,
|
||||
// bbi->fail != -1 ? "green" : "blue");
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"\" "
|
||||
"[color=\"%s\"];\n", bbi->addr, bbi->jump,
|
||||
bbi->fail != -1 ? pal_jump : pal_trfa);
|
||||
core_anal_color_curr_node (core, bbi);
|
||||
}
|
||||
}
|
||||
if (bbi->fail != -1) {
|
||||
nodes++;
|
||||
if (is_html) {
|
||||
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
|
||||
" <img class=\"connector-end\" src=\"img/arrow.gif\"/></div>\n",
|
||||
bbi->addr, bbi->fail);
|
||||
} else if (!is_keva) {
|
||||
//r_cons_printf ("\t\"0x%08"PFMT64x"_0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"_0x%08"PFMT64x"\" "
|
||||
// "[color=\"red\"];\n", fcn->addr, bbi->addr, fcn->addr, bbi->fail);
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"\" "
|
||||
"[color=\"%s\"];\n", bbi->addr, bbi->fail, pal_fail);
|
||||
core_anal_color_curr_node (core, bbi);
|
||||
}
|
||||
}
|
||||
if (bbi->switch_op) {
|
||||
RAnalCaseOp *caseop;
|
||||
RListIter *iter;
|
||||
|
||||
if (is_html) {
|
||||
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
|
||||
" <img class=\"connector-end\" src=\"img/arrow.gif\"/></div>\n",
|
||||
bbi->addr, bbi->fail);
|
||||
} else if (!is_keva) {
|
||||
//r_cons_printf ("\t\"0x%08"PFMT64x"_0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"_0x%08"PFMT64x"\" "
|
||||
// "[color=\"red\"];\n", fcn->addr, bbi->addr, fcn->addr, bbi->fail);
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"\" "
|
||||
"[color=\"%s\"];\n", bbi->addr, bbi->fail, pal_fail);
|
||||
core_anal_color_curr_node (core, bbi);
|
||||
}
|
||||
|
||||
r_list_foreach (bbi->switch_op->cases, iter, caseop) {
|
||||
nodes++;
|
||||
if (is_keva) {
|
||||
char key[128];
|
||||
snprintf (key, sizeof (key),
|
||||
"bb.0x%08"PFMT64x".switch.%"PFMT64d,
|
||||
bbi->addr, caseop->value);
|
||||
sdb_num_set (DB, key, caseop->jump, 0);
|
||||
snprintf (key, sizeof (key),
|
||||
"bb.0x%08"PFMT64x".switch", bbi->addr);
|
||||
sdb_array_add_num (DB, key, caseop->value, 0);
|
||||
} else if (is_html) {
|
||||
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
|
||||
" <img class=\"connector-end\" src=\"img/arrow.gif\"/></div>\n",
|
||||
caseop->addr, caseop->jump);
|
||||
} else {
|
||||
//r_cons_printf ("\t\"0x%08"PFMT64x"_0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"_0x%08"PFMT64x"\" "
|
||||
// "[color=\"red\"];\n", fcn->addr, caseop->addr, fcn->addr, caseop->jump);
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"\" "
|
||||
"[color2=\"%s\"];\n", caseop->addr, caseop->jump, pal_fail);
|
||||
core_anal_color_curr_node (core, bbi);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((str = core_anal_graph_label (core, bbi, opts))) {
|
||||
if (opts & R_CORE_ANAL_GRAPHDIFF) {
|
||||
const char *difftype = bbi->diff? (\
|
||||
bbi->diff->type==R_ANAL_DIFF_TYPE_MATCH? "lightgray":
|
||||
bbi->diff->type==R_ANAL_DIFF_TYPE_UNMATCH? "yellow": "red"): "orange";
|
||||
const char *diffname = bbi->diff? (\
|
||||
bbi->diff->type==R_ANAL_DIFF_TYPE_MATCH? "match":
|
||||
bbi->diff->type==R_ANAL_DIFF_TYPE_UNMATCH? "unmatch": "new"): "unk";
|
||||
if (is_keva) {
|
||||
sdb_set (DB, "diff", diffname, 0);
|
||||
sdb_set (DB, "label", str, 0);
|
||||
} else if (!is_json) {
|
||||
nodes++;
|
||||
//r_cons_printf (" \"0x%08"PFMT64x"_0x%08"PFMT64x"\" [color=\"%s\","
|
||||
// " label=\"%s\", URL=\"%s/0x%08"PFMT64x"\"]\n",
|
||||
// fcn->addr, bbi->addr, difftype, str, fcn->name, bbi->addr);
|
||||
RConfigHold *hc = r_config_hold_new (core->config);
|
||||
r_config_hold_i (hc, "scr.color", "scr.utf8", "asm.offset", "asm.lines",
|
||||
"asm.cmt.right", "asm.lines.fcn", "asm.bytes", NULL);
|
||||
RDiff *d = r_diff_new ();
|
||||
r_config_set_i (core->config, "scr.color", 0);
|
||||
r_config_set_i (core->config, "scr.utf8", 0);
|
||||
r_config_set_i (core->config, "asm.offset", 0);
|
||||
r_config_set_i (core->config, "asm.lines", 0);
|
||||
r_config_set_i (core->config, "asm.cmt.right", 0);
|
||||
r_config_set_i (core->config, "asm.lines.fcn", 0);
|
||||
r_config_set_i (core->config, "asm.bytes", 0);
|
||||
|
||||
if (bbi->diff && bbi->diff->type != R_ANAL_DIFF_TYPE_MATCH && core->c2) {
|
||||
RCore *c = core->c2;
|
||||
RConfig *oc = c->config;
|
||||
char *str = r_core_cmd_strf (core, "pdb @ 0x%08"PFMT64x, bbi->addr);
|
||||
c->config = core->config;
|
||||
// XXX. the bbi->addr doesnt needs to be in the same address in core2
|
||||
char *str2 = r_core_cmd_strf (c, "pdb @ 0x%08"PFMT64x, bbi->diff->addr);
|
||||
char *diffstr = r_diff_buffers_to_string (d,
|
||||
(const ut8*)str, strlen (str),
|
||||
(const ut8*)str2, strlen(str2));
|
||||
if (diffstr) {
|
||||
char *nl = strchr (diffstr, '\n');
|
||||
if (nl) {
|
||||
nl = strchr (nl + 1, '\n');
|
||||
if (nl) {
|
||||
nl = strchr (nl + 1, '\n');
|
||||
if (nl) {
|
||||
r_str_cpy (diffstr, nl + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
diffstr = r_str_replace (diffstr, "\n", "\\l", 1);
|
||||
diffstr = r_str_replace (diffstr, "\"", "'", 1);
|
||||
// eprintf ("%s\n", diffstr? diffstr: "");
|
||||
r_cons_printf (" \"0x%08"PFMT64x"\" [fillcolor=\"%s\","
|
||||
"color=\"black\", fontname=\"Courier\","
|
||||
" label=\"%s\", URL=\"%s/0x%08"PFMT64x"\"]\n",
|
||||
bbi->addr, difftype, diffstr, fcn->name, bbi->addr);
|
||||
free (diffstr);
|
||||
c->config = oc;
|
||||
} else {
|
||||
r_cons_printf (" \"0x%08"PFMT64x"\" [fillcolor=\"%s\","
|
||||
"color=\"black\", fontname=\"Courier\","
|
||||
" label=\"%s\", URL=\"%s/0x%08"PFMT64x"\"]\n",
|
||||
bbi->addr, difftype, str, fcn->name, bbi->addr);
|
||||
}
|
||||
r_diff_free (d);
|
||||
r_config_set_i (core->config, "scr.color", 1);
|
||||
r_config_hold_free (hc);
|
||||
}
|
||||
} else {
|
||||
if (is_html) {
|
||||
nodes++;
|
||||
r_cons_printf ("<p class=\"block draggable\" style=\""
|
||||
"top: %dpx; left: %dpx; width: 400px;\" id=\""
|
||||
"_0x%08"PFMT64x"\">\n%s</p>\n",
|
||||
top, left, bbi->addr, str);
|
||||
left = left? 0: 600;
|
||||
if (!left) {
|
||||
top += 250;
|
||||
}
|
||||
} else if (!is_json && !is_keva) {
|
||||
bool current = r_anal_bb_is_in_offset (bbi, core->offset);
|
||||
const char *label_color = bbi->traced
|
||||
? pal_traced
|
||||
: (current && color_current)
|
||||
? pal_curr
|
||||
: pal_box4;
|
||||
const char *fill_color = (current || label_color == pal_traced)? pal_traced: "white";
|
||||
nodes++;
|
||||
//r_cons_printf (" \"0x%08"PFMT64x"_0x%08"PFMT64x"\" ["
|
||||
// "URL=\"%s/0x%08"PFMT64x"\", color=\"%s\", label=\"%s\"]\n",
|
||||
// fcn->addr, bbi->addr,
|
||||
// fcn->name, bbi->addr,
|
||||
// bbi->traced?"yellow":"lightgray", str);
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" ["
|
||||
"URL=\"%s/0x%08"PFMT64x"\", fillcolor=\"%s\","
|
||||
"color=\"%s\", fontname=\"%s\","
|
||||
"label=\"%s\"]\n",
|
||||
bbi->addr, fcn->name, bbi->addr,
|
||||
fill_color, label_color, font, str);
|
||||
}
|
||||
}
|
||||
free (str);
|
||||
}
|
||||
}
|
||||
nodes += core_anal_graph_construct_nodes (core, fcn, opts, pj, DB);
|
||||
nodes += core_anal_graph_construct_edges (core, fcn, opts, pj, DB);
|
||||
if (is_json) {
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
@ -1855,10 +1937,6 @@ R_API int r_core_anal_fcn_clean(RCore *core, ut64 addr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *get_title(ut64 addr) {
|
||||
return r_str_newf ("0x%"PFMT64x, addr);
|
||||
}
|
||||
|
||||
R_API int r_core_print_bb_custom(RCore *core, RAnalFunction *fcn) {
|
||||
RAnalBlock *bb;
|
||||
RListIter *iter;
|
||||
@ -1886,7 +1964,6 @@ R_API int r_core_print_bb_custom(RCore *core, RAnalFunction *fcn) {
|
||||
char *title = get_title (bb->addr);
|
||||
char *body = r_core_cmd_strf (core, "pdb @ 0x%08"PFMT64x, bb->addr);
|
||||
char *body_b64 = r_base64_encode_dyn (body, -1);
|
||||
|
||||
if (!title || !body || !body_b64) {
|
||||
free (body_b64);
|
||||
free (body);
|
||||
@ -3338,6 +3415,7 @@ R_API int r_core_anal_graph(RCore *core, ut64 addr, int opts) {
|
||||
int is_json = opts & R_CORE_ANAL_JSON;
|
||||
int is_json_format_disasm = opts & R_CORE_ANAL_JSON_FORMAT_DISASM;
|
||||
int is_keva = opts & R_CORE_ANAL_KEYVALUE;
|
||||
int is_star = opts & R_CORE_ANAL_STAR;
|
||||
RConfigHold *hc;
|
||||
RAnalFunction *fcni;
|
||||
RListIter *iter;
|
||||
@ -3363,7 +3441,7 @@ R_API int r_core_anal_graph(RCore *core, ut64 addr, int opts) {
|
||||
r_config_hold_i (hc, "asm.bytes", NULL);
|
||||
r_config_set_i (core->config, "asm.bytes", 0);
|
||||
}
|
||||
if (!is_html && !is_json && !is_keva) {
|
||||
if (!is_html && !is_json && !is_keva && !is_star) {
|
||||
const char * gv_edge = r_config_get (core->config, "graph.gv.edge");
|
||||
const char * gv_node = r_config_get (core->config, "graph.gv.node");
|
||||
const char * gv_spline = r_config_get (core->config, "graph.gv.spline");
|
||||
@ -3406,10 +3484,15 @@ R_API int r_core_anal_graph(RCore *core, ut64 addr, int opts) {
|
||||
if (!nodes) {
|
||||
if (!is_html && !is_json && !is_keva) {
|
||||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, 0);
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\";\n", fcn? fcn->addr: addr);
|
||||
if (is_star) {
|
||||
char *name = get_title(fcn ? fcn->addr: addr);
|
||||
r_cons_printf ("agn %s;", name);
|
||||
}else {
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\";\n", fcn? fcn->addr: addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_keva && !is_html && !is_json) {
|
||||
if (!is_keva && !is_html && !is_json && !is_star) {
|
||||
r_cons_printf ("}\n");
|
||||
}
|
||||
if (is_json) {
|
||||
|
@ -7160,9 +7160,10 @@ static void cmd_agraph_node(RCore *core, const char *input) {
|
||||
char *newbody = NULL;
|
||||
char **args, *body;
|
||||
int n_args, B_LEN = strlen ("base64:");
|
||||
int color = -1;
|
||||
input++;
|
||||
args = r_str_argv (input, &n_args);
|
||||
if (n_args < 1 || n_args > 2) {
|
||||
if (n_args < 1 || n_args > 3) {
|
||||
r_cons_printf ("Wrong arguments\n");
|
||||
r_str_argv_free (args);
|
||||
break;
|
||||
@ -7182,10 +7183,13 @@ static void cmd_agraph_node(RCore *core, const char *input) {
|
||||
body = newbody;
|
||||
}
|
||||
body = r_str_append (body, "\n");
|
||||
if (n_args > 2) {
|
||||
color = atoi(args[2]);
|
||||
}
|
||||
} else {
|
||||
body = strdup ("");
|
||||
}
|
||||
r_agraph_add_node (core->graph, args[0], body);
|
||||
r_agraph_add_node_with_color (core->graph, args[0], body, color);
|
||||
r_str_argv_free (args);
|
||||
free (body);
|
||||
//free newbody it's not necessary since r_str_append reallocate the space
|
||||
@ -7717,37 +7721,56 @@ static void cmd_anal_graph(RCore *core, const char *input) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'd': // "agd"
|
||||
switch (input[1]) {
|
||||
case 'v':
|
||||
case 't':
|
||||
case 'j':
|
||||
case 'J':
|
||||
case 'g':
|
||||
case 'k':
|
||||
case '*':
|
||||
case ' ':
|
||||
case 0:
|
||||
eprintf ("Currently the only supported formats for the diff graph are 'agdd' and 'agdw'\n");
|
||||
break;
|
||||
case 'd': {
|
||||
ut64 addr = input[2]? r_num_math (core->num, input + 2): core->offset;
|
||||
r_core_gdiff_fcn (core, addr, core->offset);
|
||||
r_core_anal_graph (core, addr, R_CORE_ANAL_GRAPHBODY | R_CORE_ANAL_GRAPHDIFF);
|
||||
break;
|
||||
}
|
||||
case 'w': {
|
||||
char *cmdargs = r_str_newf ("agdd 0x%"PFMT64x, core->offset);
|
||||
char *cmd = graph_cmd (core, cmdargs, input + 2);
|
||||
if (cmd && *cmd) {
|
||||
r_core_cmd0 (core, cmd);
|
||||
}
|
||||
free (cmd);
|
||||
free (cmdargs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'd': {// "agd"
|
||||
int diff_opt = R_CORE_ANAL_GRAPHBODY | R_CORE_ANAL_GRAPHDIFF;
|
||||
switch (input[1]) {
|
||||
case 'j': {
|
||||
ut64 addr = input[2] ? r_num_math(core->num, input + 2) : core->offset;
|
||||
r_core_gdiff_fcn(core, addr, core->offset);
|
||||
r_core_anal_graph(core, addr, diff_opt | R_CORE_ANAL_JSON);
|
||||
break;
|
||||
}
|
||||
case 'J': {
|
||||
ut64 addr = input[2] ? r_num_math(core->num, input + 2) : core->offset;
|
||||
r_core_gdiff_fcn(core, addr, core->offset);
|
||||
r_core_anal_graph(core, addr, diff_opt | R_CORE_ANAL_JSON | R_CORE_ANAL_JSON_FORMAT_DISASM);
|
||||
break;
|
||||
}
|
||||
case '*': {
|
||||
ut64 addr = input[2] ? r_num_math(core->num, input + 2) : core->offset;
|
||||
r_core_gdiff_fcn(core, addr, core->offset);
|
||||
r_core_anal_graph(core, addr, diff_opt | R_CORE_ANAL_STAR);
|
||||
break;
|
||||
}
|
||||
case ' ':
|
||||
case 0:
|
||||
case 't':
|
||||
case 'k':
|
||||
case 'v':
|
||||
case 'g': {
|
||||
ut64 addr = input[2] ? r_num_math(core->num, input + 2) : core->offset;
|
||||
r_core_cmdf (core, "ag-; .agd* @ %"PFMT64u"; agg%s;", addr, input + 1);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
ut64 addr = input[2] ? r_num_math(core->num, input + 2) : core->offset;
|
||||
r_core_gdiff_fcn(core, addr, core->offset);
|
||||
r_core_anal_graph(core, addr, diff_opt);
|
||||
break;
|
||||
}
|
||||
case 'w': {
|
||||
char *cmdargs = r_str_newf("agdd 0x%"PFMT64x, core->offset);
|
||||
char *cmd = graph_cmd(core, cmdargs, input + 2);
|
||||
if (cmd && *cmd) {
|
||||
r_core_cmd0(core, cmd);
|
||||
}
|
||||
free(cmd);
|
||||
free(cmdargs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'v': // "agv" alias for "agfv"
|
||||
r_core_cmdf (core, "agfv%s", input + 1);
|
||||
break;
|
||||
|
@ -22,6 +22,7 @@ typedef struct r_ascii_node_t {
|
||||
int is_dummy;
|
||||
int is_reversed;
|
||||
int klass;
|
||||
int difftype;
|
||||
bool is_mini;
|
||||
} RANode;
|
||||
|
||||
@ -90,6 +91,7 @@ R_API void r_agraph_set_title(RAGraph *g, const char *title);
|
||||
R_API RANode *r_agraph_get_first_node(const RAGraph *g);
|
||||
R_API RANode *r_agraph_get_node(const RAGraph *g, const char *title);
|
||||
R_API RANode *r_agraph_add_node(const RAGraph *g, const char *title, const char *body);
|
||||
R_API RANode *r_agraph_add_node_with_color(const RAGraph *g, const char *title, const char *body, int color);
|
||||
R_API bool r_agraph_del_node(const RAGraph *g, const char *title);
|
||||
R_API void r_agraph_add_edge(const RAGraph *g, RANode *a, RANode *b);
|
||||
R_API void r_agraph_add_edge_at(const RAGraph *g, RANode *a, RANode *b, int nth);
|
||||
|
@ -254,6 +254,10 @@ typedef struct r_cons_palette_t {
|
||||
RColor graph_trufae;
|
||||
RColor graph_traced;
|
||||
RColor graph_current;
|
||||
RColor graph_diff_match;
|
||||
RColor graph_diff_unmatch;
|
||||
RColor graph_diff_unknown;
|
||||
RColor graph_diff_new;
|
||||
} RConsPalette;
|
||||
|
||||
typedef struct r_cons_printable_palette_t {
|
||||
@ -321,6 +325,10 @@ typedef struct r_cons_printable_palette_t {
|
||||
char *graph_box2;
|
||||
char *graph_box3;
|
||||
char *graph_box4;
|
||||
char *graph_diff_match;
|
||||
char *graph_diff_unmatch;
|
||||
char *graph_diff_unknown;
|
||||
char *graph_diff_new;
|
||||
char *graph_true;
|
||||
char *graph_false;
|
||||
char *graph_trufae;
|
||||
|
@ -46,6 +46,7 @@ R_LIB_VERSION_HEADER(r_core);
|
||||
#define R_CORE_ANAL_JSON 8
|
||||
#define R_CORE_ANAL_KEYVALUE 16
|
||||
#define R_CORE_ANAL_JSON_FORMAT_DISASM 32
|
||||
#define R_CORE_ANAL_STAR 64
|
||||
|
||||
#define R_FLAGS_FS_CLASSES "classes"
|
||||
#define R_FLAGS_FS_FUNCTIONS "functions"
|
||||
|
Loading…
Reference in New Issue
Block a user