From 4e55fa26b9562c661872ab20c9ab872c7e7e8548 Mon Sep 17 00:00:00 2001 From: cyanpencil Date: Mon, 7 May 2018 00:43:23 +0200 Subject: [PATCH 1/3] output formats support --- libr/core/canal.c | 124 ++++++++++++++++++++++++++++++++++++++++++ libr/core/cmd_anal.c | 68 ++++++++++++++++++++++- libr/include/r_core.h | 2 + 3 files changed, 191 insertions(+), 3 deletions(-) diff --git a/libr/core/canal.c b/libr/core/canal.c index 24c81b2cedc33..9e81ab3e71c0b 100644 --- a/libr/core/canal.c +++ b/libr/core/canal.c @@ -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); + + 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); + } + 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"); + + 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) { diff --git a/libr/core/cmd_anal.c b/libr/core/cmd_anal.c index c4ab59460da27..a1b1e41b89b95 100644 --- a/libr/core/cmd_anal.c +++ b/libr/core/cmd_anal.c @@ -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); + } + 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 + } + 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); + } + 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); + } + 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; diff --git a/libr/include/r_core.h b/libr/include/r_core.h index 6b344c75bdc81..40eca5d309e1e 100644 --- a/libr/include/r_core.h +++ b/libr/include/r_core.h @@ -417,6 +417,8 @@ R_API int r_core_anal_fcn_list(RCore *core, const char *input, const char *rad); R_API int r_core_anal_fcn_list_size(RCore *core); R_API void r_core_anal_fcn_labels(RCore *core, RAnalFunction *fcn, int rad); R_API int r_core_anal_fcn_clean(RCore *core, ut64 addr); +R_API int r_core_print_bb_custom(RCore *core, RAnalFunction *fcn); +R_API int r_core_print_bb_gml(RCore *core, RAnalFunction *fcn); R_API int r_core_anal_graph(RCore *core, ut64 addr, int opts); R_API int r_core_anal_graph_fcn(RCore *core, char *input, int opts); R_API RList* r_core_anal_graph_to(RCore *core, ut64 addr, int n); From 37795fcd9e87436a1e61cef7e6953f43487180f4 Mon Sep 17 00:00:00 2001 From: cyanpencil Date: Mon, 7 May 2018 17:04:04 +0200 Subject: [PATCH 2/3] various fixes --- libr/core/canal.c | 18 +++++++++++------- libr/core/cmd_anal.c | 26 +++++--------------------- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/libr/core/canal.c b/libr/core/canal.c index 9e81ab3e71c0b..eeef11662daea 100644 --- a/libr/core/canal.c +++ b/libr/core/canal.c @@ -1610,10 +1610,14 @@ 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, strlen(body)); - body_b64 = r_str_prefix (body_b64, "base64:"); + char *body_b64 = r_base64_encode_dyn (body, -1); + + if (!title || !body || !body_b64) { + return false; + } - r_cons_printf ("agn \"%s\" \"%s\"\n", title, body_b64); + body_b64 = r_str_prefix (body_b64, "base64:"); + r_cons_printf ("agn %s %s\n", title, body_b64); free (body); free (body_b64); @@ -1631,18 +1635,18 @@ R_API int r_core_print_bb_custom(RCore *core, RAnalFunction *fcn) { 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); + r_cons_printf ("age %s %s\n", u, v); } if (bb->fail != UT64_MAX) { v = get_title (bb->fail); - r_cons_printf ("age \"%s\" \"%s\"\n", u, v); + 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); + r_cons_printf ("age %s %s\n", u, v); } } free (u); @@ -1658,7 +1662,7 @@ R_API int r_core_print_bb_gml(RCore *core, RAnalFunction *fcn) { return false; } - r_cons_printf ("graph\n[\n" "hierarchic\t1\n" "label\t\"\"\n" "directed\t1\n"); + r_cons_printf ("graph\n[\n" "hierarchic 1\n" "label \"\"\n" "directed 1\n"); r_list_foreach (fcn->bbs, iter, bb) { RFlagItem *flag = r_flag_get_i (core->flags, bb->addr); diff --git a/libr/core/cmd_anal.c b/libr/core/cmd_anal.c index a1b1e41b89b95..10f9e12ff8e35 100644 --- a/libr/core/cmd_anal.c +++ b/libr/core/cmd_anal.c @@ -5791,8 +5791,7 @@ static void cmd_anal_graph(RCore *core, const char *input) { if (input[2] == 'm') { r_core_anal_graph (core, r_num_math (core->num, input + 2), R_CORE_ANAL_GRAPHLINES); - } - else { + } else { r_core_anal_graph (core, r_num_math (core->num, input + 1), R_CORE_ANAL_GRAPHBODY); } @@ -5804,31 +5803,16 @@ static void cmd_anal_graph(RCore *core, const char *input) { 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 - } - 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); - } - else { - fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); - } + ut64 off_fcn = (*(input + 2)) ? r_num_math (core->num, input + 2) : core->offset; + RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off_fcn, 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); - } - else { - fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); - } + ut64 off_fcn = (*(input + 2)) ? r_num_math (core->num, input + 2) : core->offset; + RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off_fcn, 0); r_core_print_bb_custom (core, fcn); break; } From ee945581d18b999e61758435faacd81b7ea490c5 Mon Sep 17 00:00:00 2001 From: cyanpencil Date: Mon, 7 May 2018 17:34:57 +0200 Subject: [PATCH 3/3] fix travis error --- libr/core/cmd_anal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libr/core/cmd_anal.c b/libr/core/cmd_anal.c index 10f9e12ff8e35..b3d155321263b 100644 --- a/libr/core/cmd_anal.c +++ b/libr/core/cmd_anal.c @@ -5802,11 +5802,12 @@ static void cmd_anal_graph(RCore *core, const char *input) { 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" + case 'g':{// "agfg" ut64 off_fcn = (*(input + 2)) ? r_num_math (core->num, input + 2) : core->offset; RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off_fcn, 0); r_core_print_bb_gml (core, fcn); break; + } case 'k':// "agfk" r_core_cmd0 (core, "ag-; .agf*; aggk"); break;