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 every output format for the bb graph (agf) #10030
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1579,6 +1579,130 @@ 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; | ||
if (!fcn) { | ||
return false; | ||
} | ||
|
||
RConfigHold *hc = r_config_hold_new (core->config); | ||
r_config_save_num (hc, "scr.color", "scr.utf8", "asm.marks", "asm.offset", "asm.lines", | ||
"asm.cmt.right", "asm.cmt.col", "asm.fcnlines", "asm.bytes", NULL); | ||
/*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.marks", 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.cmt.col", 0); | ||
r_config_set_i (core->config, "asm.fcnlines", 0); | ||
r_config_set_i (core->config, "asm.bytes", 0); | ||
|
||
r_list_foreach (fcn->bbs, iter, bb) { | ||
if (bb->addr == UT64_MAX) { | ||
continue; | ||
} | ||
|
||
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, strlen(body)); | ||
body_b64 = r_str_prefix (body_b64, "base64:"); | ||
|
||
r_cons_printf ("agn \"%s\" \"%s\"\n", title, body_b64); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. quotes dont work like this in r2land |
||
|
||
free (body); | ||
free (body_b64); | ||
free (title); | ||
} | ||
|
||
r_config_restore (hc); | ||
r_config_hold_free (hc); | ||
|
||
r_list_foreach (fcn->bbs, iter, bb) { | ||
if (bb->addr == UT64_MAX) { | ||
continue; | ||
} | ||
|
||
char *u = get_title (bb->addr), *v = NULL; | ||
if (bb->jump != UT64_MAX) { | ||
v = get_title (bb->jump); | ||
r_cons_printf ("age \"%s\" \"%s\"\n", u, v); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. quotes dont work like this in r2land, remove them |
||
} | ||
if (bb->fail != UT64_MAX) { | ||
v = get_title (bb->fail); | ||
r_cons_printf ("age \"%s\" \"%s\"\n", u, v); | ||
} | ||
if (bb->switch_op) { | ||
RListIter *it; | ||
RAnalCaseOp *cop; | ||
r_list_foreach (bb->switch_op->cases, it, cop) { | ||
v = get_title (cop->addr); | ||
r_cons_printf ("age \"%s\" \"%s\"\n", u, v); | ||
} | ||
} | ||
free (u); | ||
free (v); | ||
} | ||
return true; | ||
} | ||
|
||
R_API int r_core_print_bb_gml(RCore *core, RAnalFunction *fcn) { | ||
RAnalBlock *bb; | ||
RListIter *iter; | ||
if (!fcn) { | ||
return false; | ||
} | ||
|
||
r_cons_printf ("graph\n[\n" "hierarchic\t1\n" "label\t\"\"\n" "directed\t1\n"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we use spaces intead of tabs here? or graphviz will not work? it is better to not print tabs to stdout in r2 commands to avoid problems in visual and such, even if its not suposed to be printed |
||
|
||
r_list_foreach (fcn->bbs, iter, bb) { | ||
RFlagItem *flag = r_flag_get_i (core->flags, bb->addr); | ||
char *msg = flag? strdup (flag->name): r_str_newf ("0x%08"PFMT64x, bb->addr); | ||
r_cons_printf ("\tnode [\n" | ||
"\t\tid\t%"PFMT64d"\n" | ||
"\t\tlabel\t\"%s\"\n" | ||
"\t]\n", bb->addr, msg); | ||
} | ||
|
||
r_list_foreach (fcn->bbs, iter, bb) { | ||
if (bb->addr == UT64_MAX) { | ||
continue; | ||
} | ||
|
||
if (bb->jump != UT64_MAX) { | ||
r_cons_printf ("\tedge [\n" | ||
"\t\tsource %"PFMT64d"\n" | ||
"\t\ttarget %"PFMT64d"\n" | ||
"\t]\n", bb->addr, bb->jump | ||
); | ||
} | ||
if (bb->fail != UT64_MAX) { | ||
r_cons_printf ("\tedge [\n" | ||
"\t\tsource %"PFMT64d"\n" | ||
"\t\ttarget %"PFMT64d"\n" | ||
"\t]\n", bb->addr, bb->fail | ||
); | ||
} | ||
if (bb->switch_op) { | ||
RListIter *it; | ||
RAnalCaseOp *cop; | ||
r_list_foreach (bb->switch_op->cases, it, cop) { | ||
r_cons_printf ("\tedge [\n" | ||
"\t\tsource %"PFMT64d"\n" | ||
"\t\ttarget %"PFMT64d"\n" | ||
"\t]\n", bb->addr, cop->addr | ||
); | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
R_API void r_core_anal_codexrefs(RCore *core, ut64 addr, int fmt) { | ||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, -1); | ||
if (fcn) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5776,14 +5776,76 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
switch (input[0]) { | ||
case 'f': // "agf" | ||
switch (input[1]) { | ||
case 0:// "agf" | ||
r_core_visual_graph (core, NULL, NULL, false); | ||
break; | ||
case 'v':// "agfv" | ||
eprintf ("\rRendering graph..."); | ||
r_core_visual_graph (core, NULL, NULL, 1); | ||
r_cons_show_cursor (true); | ||
break; | ||
case 't':// "agft" - tiny graph | ||
r_core_visual_graph (core, NULL, NULL, 2); | ||
break; | ||
case 0: | ||
r_core_visual_graph (core, NULL, NULL, false); | ||
case 'd':// "agfd" | ||
if (input[2] == 'm') { | ||
r_core_anal_graph (core, r_num_math (core->num, input + 2), | ||
R_CORE_ANAL_GRAPHLINES); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. else goes here , in the same line of the } |
||
else { | ||
r_core_anal_graph (core, r_num_math (core->num, input + 1), | ||
R_CORE_ANAL_GRAPHBODY); | ||
} | ||
break; | ||
case 'j':// "agfj" | ||
r_core_anal_graph (core, r_num_math (core->num, input + 1), R_CORE_ANAL_JSON); | ||
break; | ||
case 'J':// "agfJ" | ||
r_core_anal_graph (core, r_num_math (core->num, input + 1), | ||
R_CORE_ANAL_JSON | R_CORE_ANAL_JSON_FORMAT_DISASM); | ||
case 'g':// "agfg" | ||
if (input[2] == 'f') { | ||
//TODO | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. uh |
||
} | ||
RAnalFunction *fcn = NULL; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use ternary operator instead of assigning to null and such. also the only thing that changes is the off_fcn, so you dont need to copy the r_anal-get_fcn_in call twice |
||
if (*(input + 2)) { | ||
ut64 off_fcn = r_num_math (core->num, input + 2); | ||
fcn = r_anal_get_fcn_in (core->anal, off_fcn, 0); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as before (else in this line, use ternary operator and avoid dupped call when only 1 arg changes) |
||
else { | ||
fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); | ||
} | ||
r_core_print_bb_gml (core, fcn); | ||
break; | ||
case 'k':// "agfk" | ||
r_core_cmd0 (core, "ag-; .agf*; aggk"); | ||
break; | ||
case '*':{// "agf*" | ||
RAnalFunction *fcn = NULL; | ||
if (*(input + 2)) { | ||
ut64 off_fcn = r_num_math (core->num, input + 2); | ||
fcn = r_anal_get_fcn_in (core->anal, off_fcn, 0); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
else { | ||
fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); | ||
} | ||
r_core_print_bb_custom (core, fcn); | ||
break; | ||
} | ||
case 'w':// "agfw" | ||
if (r_config_get_i (core->config, "graph.web")) { | ||
r_core_cmd0 (core, "=H /graph/"); | ||
} else { | ||
const char *cmd = r_config_get (core->config, "cmd.graph"); | ||
if (cmd && *cmd) { | ||
r_core_cmd0 (core, cmd); | ||
} else { | ||
eprintf ("Command cmd.graph not valid\n"); | ||
} | ||
} | ||
break; | ||
default: | ||
eprintf ("Usage: agf or agft (for tiny)\n"); | ||
eprintf ("Usage: see ag?"); | ||
break; | ||
} | ||
break; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space before = and before (. if you use -1 in the length argument, the bsae64 api will do the strlen for you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if any of those variables are null, following lines will make it crash