mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-03 12:12:06 +00:00
Add agfm command to print cfg graphs using mermaid syntax ##analysis
This commit is contained in:
parent
f59b7dfb56
commit
eccee9beb7
@ -9703,6 +9703,62 @@ R_API void cmd_agfb2(RCore *core, const char *s) {
|
||||
free (pix);
|
||||
}
|
||||
|
||||
static bool cmd_graph_mermaid(RCore *core) {
|
||||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
||||
if (!fcn || !fcn->bbs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
|
||||
// for info on mermaid syntax: https://mermaid-js.github.io/mermaid/#/stateDiagram
|
||||
RStrBuf *nodes = r_strbuf_new ("stateDiagram-v2\n");
|
||||
RStrBuf *edges = r_strbuf_new ("");
|
||||
|
||||
// TODO: add themeing to nodes buff here -> https://mermaid-js.github.io/mermaid/#/theming
|
||||
|
||||
RAnalBlock *b;
|
||||
RListIter *iter;
|
||||
|
||||
r_list_sort (fcn->bbs, bb_cmp);
|
||||
r_list_foreach (fcn->bbs, iter, b) {
|
||||
// node names start with _0x b/c 0x makes mermaids mad somehow
|
||||
if (b->addr != fcn->addr) {
|
||||
ret &= r_strbuf_appendf (nodes, "\tstate \"0x%" PFMT64x "\" as _0x%" PFMT64x "\n", b->addr, b->addr);
|
||||
} else {
|
||||
ret &= r_strbuf_appendf (nodes, "\tstate \"ENTRY: 0x%" PFMT64x "\" as _0x%" PFMT64x "\n", b->addr, b->addr);
|
||||
}
|
||||
// TODO: make body contain assembly, this needs to be done with some care so characters are not misinterpreted
|
||||
if (b->jump != UT64_MAX) {
|
||||
if (b->fail != UT64_MAX) {
|
||||
ret &= r_strbuf_appendf (edges, "\t_0x%" PFMT64x " --> _0x%" PFMT64x ": true\n", b->addr, b->jump);
|
||||
ret &= r_strbuf_appendf (edges, "\t_0x%" PFMT64x " --> _0x%" PFMT64x ": false\n", b->addr, b->fail);
|
||||
} else {
|
||||
ret &= r_strbuf_appendf (edges, "\t_0x%" PFMT64x " --> _0x%" PFMT64x "\n", b->addr, b->jump);
|
||||
}
|
||||
} else if (b->fail != UT64_MAX) {
|
||||
ret &= r_strbuf_appendf (edges, "\t_0x%" PFMT64x " --> _0x%" PFMT64x "\n", b->addr, b->fail);
|
||||
}
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
char *n = r_strbuf_drain_nofree (nodes);
|
||||
char *e = r_strbuf_drain_nofree (edges);
|
||||
if (n && e) {
|
||||
r_cons_print (n);
|
||||
r_cons_print (e);
|
||||
}
|
||||
free (n);
|
||||
free (e);
|
||||
}
|
||||
r_strbuf_free (nodes);
|
||||
r_strbuf_free (edges);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cmd_anal_graph(RCore *core, const char *input) {
|
||||
core->graph->show_node_titles = r_config_get_i (core->config, "graph.ntitles");
|
||||
r_cons_enable_highlight (false);
|
||||
@ -9715,6 +9771,9 @@ static void cmd_anal_graph(RCore *core, const char *input) {
|
||||
case 'b': // "agfb" // braile
|
||||
cmd_agfb (core);
|
||||
break;
|
||||
case 'm': /// "agfm" // mermaid
|
||||
cmd_graph_mermaid (core);
|
||||
break;
|
||||
case ' ': { // "agf "
|
||||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
||||
r_core_visual_graph (core, NULL, fcn, false);
|
||||
|
@ -61,3 +61,50 @@ digraph code {
|
||||
}
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=agfm basic mermaid output
|
||||
FILE=bins/elf/ls
|
||||
CMDS=<<EOF
|
||||
s sym._obstack_newchunk
|
||||
af
|
||||
agfm
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
stateDiagram-v2
|
||||
state "ENTRY: 0x15cc0" as _0x15cc0
|
||||
state "0x15d06" as _0x15d06
|
||||
state "0x15d12" as _0x15d12
|
||||
state "0x15d29" as _0x15d29
|
||||
state "0x15d67" as _0x15d67
|
||||
state "0x15d7e" as _0x15d7e
|
||||
state "0x15da0" as _0x15da0
|
||||
state "0x15db5" as _0x15db5
|
||||
state "0x15dc9" as _0x15dc9
|
||||
state "0x15dd0" as _0x15dd0
|
||||
state "0x15dd5" as _0x15dd5
|
||||
state "0x15dda" as _0x15dda
|
||||
state "0x15de3" as _0x15de3
|
||||
state "0x15df0" as _0x15df0
|
||||
state "0x15df6" as _0x15df6
|
||||
_0x15cc0 --> _0x15db5: true
|
||||
_0x15cc0 --> _0x15d06: false
|
||||
_0x15d06 --> _0x15db5: true
|
||||
_0x15d06 --> _0x15d12: false
|
||||
_0x15d12 --> _0x15db5: true
|
||||
_0x15d12 --> _0x15d29: false
|
||||
_0x15d29 --> _0x15d7e: true
|
||||
_0x15d29 --> _0x15d67: false
|
||||
_0x15d67 --> _0x15da0: true
|
||||
_0x15d67 --> _0x15d7e: false
|
||||
_0x15da0 --> _0x15d7e
|
||||
_0x15db5 --> _0x15df6: true
|
||||
_0x15db5 --> _0x15dc9: false
|
||||
_0x15dc9 --> _0x15dd0
|
||||
_0x15dd0 --> _0x15dda: true
|
||||
_0x15dd0 --> _0x15dd5: false
|
||||
_0x15dd5 --> _0x15df0: true
|
||||
_0x15dd5 --> _0x15dda: false
|
||||
_0x15dda --> _0x15dd0: true
|
||||
_0x15dda --> _0x15de3: false
|
||||
EOF
|
||||
RUN
|
||||
|
Loading…
x
Reference in New Issue
Block a user