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
Add "save to file" to ag*w commands + colorize comments like ";arg1" #10860
Changes from 7 commits
d1ec2dc
44d3770
ab2e3d6
be22d20
b37fd7a
280184c
106ae2e
5ac4f6b
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 |
---|---|---|
|
@@ -386,31 +386,31 @@ static const char *help_msg_afvs[] = { | |
static const char *help_msg_ag[] = { | ||
"Usage:", "ag<graphtype><format> [addr]", "", | ||
"Graph commands:", "", "", | ||
"agc", "[format] [fcn addr]", "Function callgraph", | ||
"agf", "[format] [fcn addr]", "Basic blocks function graph", | ||
"agx", "[format] [addr]", "Cross references graph", | ||
"agr", "[format] [fcn addr]", "References graph", | ||
"aga", "[format] [fcn addr]", "Data references graph", | ||
"aga", "[format] [@ fcn addr]", "Data references graph", | ||
"agA", "[format]", "Global data references graph", | ||
"agc", "[format] [@ fcn addr]", "Function callgraph", | ||
"agC", "[format]", "Global callgraph", | ||
"agd", "[format] [fcn addr]", "Diff graph", | ||
"agf", "[format] [@ fcn addr]", "Basic blocks function graph", | ||
"agi", "[format]", "Imports graph", | ||
"agC", "[format]", "Global callgraph", | ||
"agr", "[format] [@ fcn addr]", "References graph", | ||
"agR", "[format]", "Global references graph", | ||
"agA", "[format]", "Global data references graph", | ||
"agx", "[format] [@ addr]", "Cross references graph", | ||
"agg", "[format]", "Custom graph", | ||
"ag-", "", "Clear the custom graph", | ||
"agn", "[?] title body", "Add a node to the custom graph", | ||
"age", "[?] title1 title2", "Add an edge to the custom graph", | ||
"","","", | ||
"Output formats:", "", "", | ||
"<blank>", "", "Ascii art", | ||
"v", "", "Interactive ascii art", | ||
"t", "", "Tiny ascii art", | ||
"*", "", "r2 commands", | ||
"d", "", "Graphviz dot", | ||
"j", "", "json ('J' for formatted disassembly)", | ||
"g", "", "Graph Modelling Language (gml)", | ||
"j", "", "json ('J' for formatted disassembly)", | ||
"k", "", "SDB key-value", | ||
"*", "", "r2 commands", | ||
"w", "", "Web/image (see graph.extension and graph.web)", | ||
"t", "", "Tiny ascii art", | ||
"v", "", "Interactive ascii art", | ||
"w", " [path]", "Write to path or display graph image (see graph.gv.format and graph.web)", | ||
NULL | ||
}; | ||
|
||
|
@@ -5740,6 +5740,53 @@ static void agraph_print_node(RANode *n, void *user) { | |
free (encbody); | ||
} | ||
|
||
static char *getViewerPath() { | ||
int i; | ||
const char *viewers[] = { | ||
"open", | ||
"geeqie", | ||
"gqview", | ||
"eog", | ||
"xdg-open", | ||
NULL | ||
}; | ||
for (i = 0; viewers[i]; i++) { | ||
char *dotPath = r_file_path (viewers[i]); | ||
if (dotPath && strcmp (dotPath, viewers[i])) { | ||
return dotPath; | ||
} | ||
free (dotPath); | ||
} | ||
return NULL; | ||
} | ||
|
||
static char* graph_cmd(RCore *core, char *r2_cmd, const char *save_path) { | ||
char *cmd = NULL; | ||
const char *ext = r_config_get (core->config, "graph.gv.format"); | ||
char *dotPath = r_file_path ("dot"); | ||
if (!r_file_exists (dotPath)) { | ||
free (dotPath); | ||
dotPath = r_file_path ("xdot"); | ||
} | ||
if (r_file_exists (dotPath)) { | ||
if (save_path && *save_path) { | ||
cmd = r_str_newf ("%s > a.dot;!%s -T%s -o%s a.dot;", r2_cmd, dotPath, ext, save_path); | ||
} else { | ||
char *viewer = getViewerPath(); | ||
if (viewer) { | ||
cmd = r_str_newf ("%s > a.dot;!%s -T%s -oa.%s a.dot;!%s a.%s", r2_cmd, dotPath, ext, ext, viewer, ext); | ||
free (viewer); | ||
} else { | ||
eprintf ("Cannot find a valid picture viewer"); | ||
} | ||
} | ||
} else { | ||
cmd = r_str_new ("agf"); | ||
} | ||
free (dotPath); | ||
return cmd; | ||
} | ||
|
||
static void agraph_print_edge_dot(RANode *from, RANode *to, void *user) { | ||
r_cons_printf ("\"%s\" -> \"%s\"\n", from->title, to->title); | ||
} | ||
|
@@ -5895,14 +5942,16 @@ static void cmd_agraph_print(RCore *core, const char *input) { | |
} | ||
break; | ||
} | ||
case 'd': // "aggd" - dot format | ||
case 'd': { // "aggd" - dot format | ||
const char *font = r_config_get (core->config, "graph.font"); | ||
r_cons_printf ("digraph code {\ngraph [bgcolor=white];\n" | ||
"node [color=lightgray, style=filled shape=box " | ||
"fontname=\"Courier\" fontsize=\"8\"];\n"); | ||
"fontname=\"%s\" fontsize=\"8\"];\n", font); | ||
r_agraph_foreach (core->graph, agraph_print_node_dot, NULL); | ||
r_agraph_foreach_edge (core->graph, agraph_print_edge_dot, NULL); | ||
r_cons_printf ("}\n"); | ||
break; | ||
} | ||
case '*': // "agg*" - | ||
r_agraph_foreach (core->graph, agraph_print_node, NULL); | ||
r_agraph_foreach_edge (core->graph, agraph_print_edge, NULL); | ||
|
@@ -5923,8 +5972,12 @@ static void cmd_agraph_print(RCore *core, const char *input) { | |
if (r_config_get_i (core->config, "graph.web")) { | ||
r_core_cmd0 (core, "=H /graph/"); | ||
} else { | ||
char *cmd = r_core_graph_cmd (core, "aggd"); | ||
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. in https://github.com/radare/radare2/pull/10860/files#diff-9a7bcc9d9f9b6439c4d8b9301f1d46ccR5947 honor graph.font eval var |
||
char *cmd = graph_cmd (core, "aggd", input + 1); | ||
if (cmd && *cmd) { | ||
if (input[1]) { | ||
r_cons_printf ("Saving to file %s ...\n", input + 1); | ||
r_cons_flush (); | ||
} | ||
r_core_cmd0 (core, cmd); | ||
} | ||
free (cmd); | ||
|
@@ -5944,15 +5997,13 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
r_core_visual_graph (core, NULL, NULL, false); | ||
break; | ||
case ' ':{ // "agf " | ||
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); | ||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); | ||
r_core_visual_graph (core, NULL, fcn, false); | ||
break; | ||
} | ||
case 'v': // "agfv" | ||
eprintf ("\rRendering graph..."); | ||
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); | ||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); | ||
if (fcn) { | ||
r_core_visual_graph (core, NULL, fcn, 1); | ||
} | ||
|
@@ -5962,8 +6013,7 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
case 't': { // "agft" - tiny graph | ||
int e = r_config_get_i (core->config, "graph.edges"); | ||
r_config_set_i (core->config, "graph.edges", 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); | ||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 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. why drop the use of specifying the offset as argument? 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. I think it makes more sense to have a consistent api that uses |
||
r_core_visual_graph (core, NULL, fcn, 2); | ||
r_config_set_i (core->config, "graph.edges", e); | ||
break; | ||
|
@@ -5985,29 +6035,30 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
R_CORE_ANAL_JSON | R_CORE_ANAL_JSON_FORMAT_DISASM); | ||
break; | ||
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); | ||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); | ||
r_core_print_bb_gml (core, fcn); | ||
break; | ||
} | ||
case 'k':{ // "agfk" | ||
ut64 addr = (*(input + 2)) ? r_num_math (core->num, input + 2) : core->offset; | ||
r_core_cmdf (core, "ag-; .agf* %"PFMT64u"; aggk", addr); | ||
r_core_cmdf (core, "ag-; .agf* @ %"PFMT64u"; aggk", core->offset); | ||
break; | ||
} | ||
case '*':{// "agf*" | ||
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); | ||
RAnalFunction *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 { | ||
char *cmdargs = r_str_newf ("agfd %"PFMT64u, r_num_math (core->num, input + 2)); | ||
char *cmd = r_core_graph_cmd (core, cmdargs); | ||
char *cmdargs = r_str_newf ("agfd @ 0x%"PFMT64x, core->offset); | ||
char *cmd = graph_cmd (core, cmdargs, input + 2); | ||
if (cmd && *cmd) { | ||
if (*(input + 2)) { | ||
r_cons_printf ("Saving to file %s ...\n", input + 2); | ||
r_cons_flush (); | ||
} | ||
r_core_cmd0 (core, cmd); | ||
} | ||
free (cmd); | ||
|
@@ -6043,7 +6094,7 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
case ' ': | ||
case 0: { | ||
core->graph->is_callgraph = true; | ||
r_core_cmdf (core, "ag-; .agC*; agg%c;", input[1]); | ||
r_core_cmdf (core, "ag-; .agC*; agg%s;", input + 1); | ||
core->graph->is_callgraph = false; | ||
break; | ||
} | ||
|
@@ -6077,14 +6128,12 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
case 'w': | ||
case ' ': { | ||
core->graph->is_callgraph = true; | ||
ut64 addr = input[2] ? r_num_math (core->num, input + 2) : core->offset; | ||
r_core_cmdf (core, "ag-; .agr* %"PFMT64u"; agg%c;", addr, input[1]); | ||
r_core_cmdf (core, "ag-; .agr* @ %"PFMT64u"; agg%s;", core->offset, input + 1); | ||
core->graph->is_callgraph = false; | ||
break; | ||
} | ||
case '*': { | ||
ut64 addr = input[2] ? r_num_math (core->num, input + 2) : core->offset; | ||
r_core_anal_coderefs (core, addr); | ||
r_core_anal_coderefs (core, core->offset); | ||
} | ||
break; | ||
case 0: | ||
|
@@ -6108,7 +6157,7 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
case ' ': | ||
case 0: { | ||
core->graph->is_callgraph = true; | ||
r_core_cmdf (core, "ag-; .agR*; agg%c;", input[1]); | ||
r_core_cmdf (core, "ag-; .agR*; agg%s;", input + 1); | ||
core->graph->is_callgraph = false; | ||
break; | ||
} | ||
|
@@ -6140,13 +6189,11 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
case 'k': | ||
case 'w': | ||
case ' ': { | ||
ut64 addr = input[2] ? r_num_math (core->num, input + 2) : core->offset; | ||
r_core_cmdf (core, "ag-; .agx* %"PFMT64u"; agg%c;", addr, input[1]); | ||
r_core_cmdf (core, "ag-; .agx* @ %"PFMT64u"; agg%s;", core->offset, input + 1); | ||
break; | ||
} | ||
case '*': { | ||
ut64 addr = input[2] ? r_num_math (core->num, input + 2) : core->offset; | ||
r_core_anal_codexrefs (core, addr); | ||
r_core_anal_codexrefs (core, core->offset); | ||
} | ||
break; | ||
case 0: | ||
|
@@ -6169,7 +6216,7 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
case 'w': | ||
case ' ': | ||
case 0: | ||
r_core_cmdf (core, "ag-; .agi*; agg%c;", input[1]); | ||
r_core_cmdf (core, "ag-; .agi*; agg%s;", input + 1); | ||
break; | ||
case '*': | ||
r_core_anal_importxrefs (core); | ||
|
@@ -6187,8 +6234,7 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
case 'w': | ||
case ' ': { | ||
core->graph->is_callgraph = true; | ||
ut64 addr = input[2] ? r_num_math (core->num, input + 2) : core->offset; | ||
r_core_cmdf (core, "ag-; .agc* %"PFMT64u"; agg%c;", addr, input[1]); | ||
r_core_cmdf (core, "ag-; .agc* @ %"PFMT64u"; agg%s;", core->offset, input + 1); | ||
core->graph->is_callgraph = false; | ||
break; | ||
} | ||
|
@@ -6198,24 +6244,20 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
core->graph->is_callgraph = false; | ||
break; | ||
case 'g': { | ||
ut64 addr = input[2] ? r_num_math (core->num, input + 2): core->offset; | ||
r_core_anal_callgraph (core, addr, R_GRAPH_FORMAT_GMLFCN); | ||
r_core_anal_callgraph (core, core->offset, R_GRAPH_FORMAT_GMLFCN); | ||
break; | ||
} | ||
case 'd': { | ||
ut64 addr = input[2] ? r_num_math (core->num, input + 2): core->offset; | ||
r_core_anal_callgraph (core, addr, R_GRAPH_FORMAT_DOT); | ||
r_core_anal_callgraph (core, core->offset, R_GRAPH_FORMAT_DOT); | ||
break; | ||
} | ||
case 'J': | ||
case 'j': { | ||
ut64 addr = input[2]? r_num_math (core->num, input + 2): core->offset; | ||
r_core_anal_callgraph (core, addr, R_GRAPH_FORMAT_JSON); | ||
r_core_anal_callgraph (core, core->offset, R_GRAPH_FORMAT_JSON); | ||
break; | ||
} | ||
case '*': { | ||
ut64 addr = input[2]? r_num_math (core->num, input + 2): core->offset; | ||
r_core_anal_callgraph (core, addr, R_GRAPH_FORMAT_CMD); | ||
r_core_anal_callgraph (core, core->offset, R_GRAPH_FORMAT_CMD); | ||
break; | ||
} | ||
default: | ||
|
@@ -6246,16 +6288,14 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
case 'J': | ||
case 'd': | ||
case ' ': { | ||
ut64 addr = input[2] ? r_num_math (core->num, input + 2): core->offset; | ||
r_core_cmdf (core, "ag-; .aga* %"PFMT64u"; agg%c;", addr, input[1]); | ||
r_core_cmdf (core, "ag-; .aga* @ %"PFMT64u"; agg%s;", core->offset, input + 1); | ||
break; | ||
} | ||
case 0: | ||
r_core_cmd0 (core, "ag-; .aga* $$; agg;"); | ||
break; | ||
case '*': { | ||
ut64 addr = input[2]? r_num_math (core->num, input + 2): core->offset; | ||
r_core_anal_datarefs (core, addr); | ||
r_core_anal_datarefs (core, core->offset); | ||
break; | ||
} | ||
default: | ||
|
@@ -6315,9 +6355,8 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
break; | ||
} | ||
case 'w': { | ||
char *cmdargs = r_str_newf ("agdd %"PFMT64u, | ||
input[2] ? r_num_math (core->num, input + 2) : core->offset); | ||
char *cmd = r_core_graph_cmd (core, cmdargs); | ||
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); | ||
} | ||
|
@@ -6334,9 +6373,13 @@ static void cmd_anal_graph(RCore *core, const char *input) { | |
if (r_config_get_i (core->config, "graph.web")) { | ||
r_core_cmd0 (core, "=H /graph/"); | ||
} else { | ||
char *cmdargs = r_str_newf ("agfd %"PFMT64u, r_num_math (core->num, input + 1)); | ||
char *cmd = r_core_graph_cmd (core, cmdargs); | ||
char *cmdargs = r_str_newf ("agfd @ 0x%"PFMT64x, core->offset); | ||
char *cmd = graph_cmd (core, cmdargs, input + 1); | ||
if (cmd && *cmd) { | ||
if (input[1]) { | ||
r_cons_printf ("Saving to file %s ...\n", input + 1); | ||
r_cons_flush (); | ||
} | ||
r_core_cmd0 (core, cmd); | ||
} | ||
free (cmd); | ||
|
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.
Where are my changes? :(
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.
Wait, maybe I fucked up the merge of the conflicts, let me check
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.
I copied the old getViewerPath and left the new one in cconfig.c :(
Sorry, my bad, will fix it