Skip to content

Commit

Permalink
Improve jmptbl edges, second try (#10662)
Browse files Browse the repository at this point in the history
* Improve jmptbl edge positioning

* Merged edges with the same origin/destination

* Fix callgraph
  • Loading branch information
cyanpencil authored and radare committed Jul 8, 2018
1 parent ee2f848 commit e209b91
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 21 deletions.
1 change: 0 additions & 1 deletion libr/core/cconfig.c
Expand Up @@ -2828,7 +2828,6 @@ R_API int r_core_config_init(RCore *core) {
SETCB ("graph.extension", "gif", &cb_graphformat, "Graph extension when using 'w' format (png, jpg, pdf, ps, svg, json)");
SETPREF ("graph.refs", "false", "Graph references in callgraphs (.agc*;aggi)");
SETI ("graph.edges", 2, "0=no edges, 1=simple edges, 2=avoid collisions");
SETPREF ("graph.altedgepos", "false", "Switch to alternative (very experimental) positioning of edges");
SETI ("graph.layout", 0, "Graph layout (0=vertical, 1=horizontal)");
SETI ("graph.linemode", 1, "Graph edges (0=diagonal, 1=square)");
SETPREF ("graph.font", "Courier", "Font for dot graphs");
Expand Down
61 changes: 47 additions & 14 deletions libr/core/graph.c
Expand Up @@ -2641,6 +2641,24 @@ static void agraph_print_edges_simple(RAGraph *g) {
}
}

static int first_x_cmp (RGraphNode *ga, RGraphNode *gb) {
RANode *a = (RANode*) ga->data;
RANode *b = (RANode*) gb->data;
if (b->y < a->y) {
return -1;
}
if (b->y > a->y) {
return 1;
}
if (a->x < b->x) {
return 1;
} else if (a->x > b->x) {
return -1;
} else {
return 0;
}
}

static void agraph_print_edges(RAGraph *g) {
if (!g->edgemode) {
return;
Expand All @@ -2649,7 +2667,7 @@ static void agraph_print_edges(RAGraph *g) {
agraph_print_edges_simple (g);
return;
}
int out_nth, in_nth;
int out_nth, in_nth, bendpoint;
RListIter *itn, *itm, *ito;
RCanvasLineStyle style = {0};
const RList *nodes = r_graph_get_nodes (g->graph);
Expand Down Expand Up @@ -2706,13 +2724,27 @@ static void agraph_print_edges(RAGraph *g) {
}
}


bool many = r_list_length (neighbours) > 2;

if (many && !g->is_callgraph) {
ga->out_nodes->sorted = false;
r_list_sort (neighbours, first_x_cmp);
}

graph_foreach_anode (neighbours, itn, gb, b) {
out_nth = get_edge_number (g, a, b, true);
in_nth = get_edge_number (g, a, b, false);

if (many) {
bool parent_many = false;
if (a->is_dummy) {
RANode *in = (RANode *) (((RGraphNode *)r_list_first (ga->in_nodes))->data);
while (in && in->is_dummy) {
in = (RANode *) (((RGraphNode *)r_list_first ((in->gnode)->in_nodes))->data);
}
parent_many = r_list_length ((in->gnode)->out_nodes) > 2;
}

if (many || parent_many) {
style.color = LINE_UNCJMP;
} else {
switch (out_nth) {
Expand All @@ -2739,35 +2771,37 @@ static void agraph_print_edges(RAGraph *g) {
a_x_inc = R_EDGES_X_INC + 2 * (out_nth + 1);
b_x_inc = R_EDGES_X_INC + 2 * (in_nth + 1);

if (g->altedgepos) {
ax = a->is_dummy ? a->x : (a->x + a->w - a_x_inc);
bx = b->is_dummy ? b->x : (b->x + b_x_inc);
bx = b->is_dummy ? b->x : (b->x + b_x_inc);
ay = a->y + a->h;
by = b->y - 1;

if (many && !g->is_callgraph) {
int t = R_EDGES_X_INC + 2 * (neighbours->length + 1);
ax = a->is_dummy ? a->x : (a->x + a->w/2 + (t/2 - a_x_inc));
bendpoint = bx < ax ? neighbours->length - out_nth : out_nth;
} else {
ax = a->is_dummy ? a->x : (a->x + a_x_inc);
bx = b->is_dummy ? b->x : (b->x + a_x_inc);
bendpoint = tm->edgectr;
}

ay = a->y + a->h;
by = b->y - 1;

if (!a->is_dummy && itn == neighbours->head && out_nth == 0 && bx > ax) {
a_x_inc += 4;
ax += g->altedgepos ? -4 : 4;
ax += (many && !g->is_callgraph) ? 0 : 4;
}
if (a->h < a->layer_height) {
r_cons_canvas_line (g->can, ax, ay, ax, ay + a->layer_height - a->h, &style);
ay = a->y + a->layer_height;
style.symbol = LINE_NOSYM_VERT;
}
if (by >= ay) {
r_cons_canvas_line_square_defined (g->can, ax, ay, bx, by, &style, tm->edgectr, true);
r_cons_canvas_line_square_defined (g->can, ax, ay, bx, by, &style, bendpoint, true);
} else {
struct tmpbackedgeinfo *tmp = calloc (1, sizeof (struct tmpbackedgeinfo));
tmp->ax = ax;
tmp->bx = bx;
tmp->ay = ay;
tmp->by = by;
tmp->edgectr = tm->edgectr;
tmp->edgectr = bendpoint;
tmp->fromlayer = a->layer;
tmp->tolayer = b->layer;
tmp->style = style;
Expand Down Expand Up @@ -3731,7 +3765,6 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int
g->on_curnode_change = (RANodeCallback) seek_to_node;
g->on_curnode_change_data = core;
g->edgemode = r_config_get_i (core->config, "graph.edges");
g->altedgepos = r_config_get_i (core->config, "graph.altedgepos");
g->is_interactive = is_interactive;
bool asm_comments = r_config_get_i (core->config, "asm.comments");
r_config_set (core->config, "asm.comments",
Expand Down
1 change: 0 additions & 1 deletion libr/include/r_cons.h
Expand Up @@ -906,7 +906,6 @@ typedef struct r_ascii_graph_t {
bool is_tiny;
bool is_dis;
int edgemode;
bool altedgepos;
int mode;
bool is_callgraph;
bool is_interactive;
Expand Down
12 changes: 7 additions & 5 deletions libr/util/graph.c
Expand Up @@ -182,11 +182,13 @@ R_API void r_graph_add_edge (RGraph *t, RGraphNode *from, RGraphNode *to) {

R_API void r_graph_add_edge_at (RGraph *t, RGraphNode *from, RGraphNode *to, int nth) {
if (from && to) {
r_list_insert (from->out_nodes, nth, to);
r_list_append (from->all_neighbours, to);
r_list_append (to->in_nodes, from);
r_list_append (to->all_neighbours, from);
t->n_edges++;
if (!r_list_contains (from->out_nodes, to)) {
r_list_insert (from->out_nodes, nth, to);
r_list_append (from->all_neighbours, to);
r_list_append (to->in_nodes, from);
r_list_append (to->all_neighbours, from);
t->n_edges++;
}
}
}

Expand Down

0 comments on commit e209b91

Please sign in to comment.