Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support all output formats for the refs graph (agr) #10078

Merged
merged 1 commit into from May 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 23 additions & 11 deletions libr/core/canal.c
Expand Up @@ -1708,14 +1708,13 @@ R_API int r_core_print_bb_gml(RCore *core, RAnalFunction *fcn) {
return true;
}

R_API void r_core_anal_codexrefs(RCore *core, ut64 addr, int fmt) {
R_API void r_core_anal_coderefs(RCore *core, ut64 addr) {
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, -1);
if (fcn) {
const char *me = fcn->name;
RListIter *iter;
RAnalRef *ref;
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
r_cons_printf ("e graph.layout=1\n");
r_cons_printf ("ag-\n");
r_cons_printf ("agn %s\n", me);
r_list_foreach (refs, iter, ref) {
Expand All @@ -1725,21 +1724,34 @@ R_API void r_core_anal_codexrefs(RCore *core, ut64 addr, int fmt) {
r_cons_printf ("age %s %s\n", me, dst);
}
r_list_free (refs);
RList *list = r_anal_xrefs_get (core->anal, addr);
r_list_foreach (list, iter, ref) {
RFlagItem *item = r_flag_get_i (core->flags, ref->addr);
const char *src = item? item->name: sdb_fmt ("0x%08"PFMT64x, ref->addr);
r_cons_printf ("agn %s\n", src);
r_cons_printf ("age %s %s\n", src, me);
}
r_list_free (list);
} else {
eprintf("Not in a function. Use 'df' to define it.\n");
}
}

R_API void r_core_anal_codexrefs(RCore *core, ut64 addr) {
RFlagItem *f = r_flag_get_at (core->flags, addr, false);
char *me = (f && f->offset == addr)
? r_str_new (f->name) : r_str_newf ("0x%"PFMT64x, addr);
r_cons_printf ("ag-\n");
r_cons_printf ("agn %s\n", me);
RListIter *iter;
RAnalRef *ref;
RList *list = r_anal_xrefs_get (core->anal, addr);
r_list_foreach (list, iter, ref) {
RFlagItem *item = r_flag_get_i (core->flags, ref->addr);
const char *src = item? item->name: sdb_fmt ("0x%08"PFMT64x, ref->addr);
r_cons_printf ("agn %s\n", src);
r_cons_printf ("age %s %s\n", src, me);
}
r_list_free (list);
free (me);
}

#define FMT_NO 0
#define FMT_GV 1
#define FMT_JS 2
R_API void r_core_anal_coderefs(RCore *core, ut64 addr, int fmt) {
R_API void r_core_anal_callgraph(RCore *core, ut64 addr, int fmt) {
RAnalFunction fakefr = R_EMPTY;
const char *font = r_config_get (core->config, "graph.font");
const char *format = r_config_get (core->config, "graph.format");
Expand Down
55 changes: 28 additions & 27 deletions libr/core/cmd_anal.c
Expand Up @@ -5558,21 +5558,6 @@ static void cmd_anal_hint(RCore *core, const char *input) {
}
}

static void agraph_print_node_json(RANode *n, void *user) {
char *label = strdup (n->body);
r_cons_printf ("%s{\"id\":%d,\"title\":\"%s\",\"body\":\"%s\",\"out_nodes\":[",
n->gnode->idx > 0 ? "," : "", n->gnode->idx, n->title, label);
RListIter *it = NULL;
RGraphNode *node = NULL;
RList *nodes = n->gnode->out_nodes;
r_list_foreach (nodes, it, node) {
r_cons_printf ("%s%d", it == nodes->head ? "" : ",", node->idx);
}
r_cons_printf ("]}");
free (label);
}


static void agraph_print_node_gml(RANode *n, void *user) {
r_cons_printf (" node [\n"
" id %d\n"
Expand Down Expand Up @@ -5780,7 +5765,7 @@ static void cmd_agraph_print(RCore *core, const char *input) {
case 'J':
case 'j':
r_cons_printf ("{\"nodes\":[");
r_agraph_foreach (core->graph, agraph_print_node_json, NULL);
r_agraph_print_json (core->graph);
r_cons_printf ("]}\n");
break;
case 'g':
Expand Down Expand Up @@ -5903,34 +5888,50 @@ static void cmd_anal_graph(RCore *core, const char *input) {
}
break;
case 'C': // "agC"
r_core_anal_coderefs (core, UT64_MAX, input[1] == 'j'? 2: 1);
r_core_anal_callgraph (core, UT64_MAX, input[1] == 'j'? 2 : 1);
break;
case 'r': // "refs"
switch (input[1]) {
case '*':
case 'v':
case 't':
case 'd':
case 'J':
case 'j':
case ' ':
case 0:
{
ut64 addr = input[2]? r_num_math (core->num, input + 2): core->offset;
r_core_anal_codexrefs (core, addr, '*');
case 'g':
case 'k':
case 'w':
case ' ': {
char *cmd = r_str_newf ("ag-; .agr* %lld; agg%c;",
input[2] ? r_num_math (core->num, input + 2) : core->offset, input[1]);
if (cmd && *cmd) {
r_core_cmd0 (core, cmd);
}
free (cmd);
break;
}
case '*': {
ut64 addr = input[2] ? r_num_math (core->num, input + 2) : core->offset;
r_core_anal_coderefs (core, addr);
}
break;
case 0:
r_core_cmd0 (core, "ag-; .agr* $$; agg;");
break;
default:
eprintf ("|ERROR| Usage: agr[*j]\n");
eprintf ("Usage: see ag?\n");
break;
}
break;
case 'c': // "agc"
if (input[1] == '*') {
ut64 addr = input[2]? r_num_math (core->num, input + 2): UT64_MAX;
r_core_anal_coderefs (core, addr, '*');
r_core_anal_callgraph (core, addr, '*');
} else if (input[1] == 'j') {
ut64 addr = input[2]? r_num_math (core->num, input + 2): UT64_MAX;
r_core_anal_coderefs (core, addr, 2);
r_core_anal_callgraph (core, addr, 2);
} else if (input[1] == ' ') {
ut64 addr = input[2]? r_num_math (core->num, input + 1): UT64_MAX;
r_core_anal_coderefs (core, addr, 1);
r_core_anal_callgraph (core, addr, 1);
} else {
eprintf ("|ERROR| Usage: agc[j*] ([addr])\n");
}
Expand Down
22 changes: 20 additions & 2 deletions libr/core/graph.c
Expand Up @@ -3268,6 +3268,24 @@ R_API void r_agraph_print(RAGraph *g) {
}
}

R_API void r_agraph_print_json(RAGraph *g) {
RList *nodes = g->graph->nodes, *neighbours = NULL;
RListIter *it, *itt;
RGraphNode *node = NULL, *neighbour = NULL;
r_list_foreach (nodes, it, node) {
RANode *anode = (RANode *) node->data;
char *label = strdup (anode->body);
r_cons_printf ("%s{\"id\":%d,\"title\":\"%s\",\"body\":\"%s\",\"out_nodes\":[",
it == nodes->head ? "" : ",", anode->gnode->idx, anode->title, label);
neighbours = anode->gnode->out_nodes;
r_list_foreach (neighbours, itt, neighbour) {
r_cons_printf ("%s%d", itt == neighbours->head ? "" : ",", neighbour->idx);
}
r_cons_printf ("]}");
free (label);
}
}

R_API void r_agraph_set_title(RAGraph *g, const char *title) {
free (g->title);
g->title = title? strdup (title): NULL;
Expand Down Expand Up @@ -3767,8 +3785,8 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int
}
r_config_set_i (core->config, "graph.layout", e);
g->layout = r_config_get_i (core->config, "graph.layout");
g->need_reload_nodes = true;
get_bbupdate (g, core, fcn);
g->need_update_dim = true;
g->need_set_layout = true;
}
break;
case 'e':
Expand Down
1 change: 1 addition & 0 deletions libr/include/r_cons.h
Expand Up @@ -928,6 +928,7 @@ 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);
R_API void r_agraph_del_edge(const RAGraph *g, RANode *a, RANode *b);
R_API void r_agraph_print(RAGraph *g);
R_API void r_agraph_print_json(RAGraph *g);
R_API Sdb *r_agraph_get_sdb(RAGraph *g);
R_API void r_agraph_foreach(RAGraph *g, RANodeCallback cb, void *user);
R_API void r_agraph_foreach_edge(RAGraph *g, RAEdgeCallback cb, void *user);
Expand Down
5 changes: 3 additions & 2 deletions libr/include/r_core.h
Expand Up @@ -404,8 +404,9 @@ R_API void r_core_anal_hint_list (RAnal *a, int mode);
R_API int r_core_anal_search(RCore *core, ut64 from, ut64 to, ut64 ref, int mode);
R_API int r_core_anal_search_xrefs(RCore *core, ut64 from, ut64 to, int rad);
R_API int r_core_anal_data (RCore *core, ut64 addr, int count, int depth, int wordsize);
R_API void r_core_anal_coderefs(RCore *core, ut64 addr, int gv);
R_API void r_core_anal_codexrefs(RCore *core, ut64 addr, int fmt);
R_API void r_core_anal_coderefs(RCore *core, ut64 addr);
R_API void r_core_anal_codexrefs(RCore *core, ut64 addr);
R_API void r_core_anal_callgraph(RCore *core, ut64 addr, int fmt);
R_API int r_core_anal_refs(RCore *core, const char *input);
R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr, ut64 *prev_addr);
R_API bool r_core_esil_cmd(RAnalEsil *esil, const char *cmd, ut64 a1, ut64 a2);
Expand Down