diff options
Diffstat (limited to 'src/gtkext/graph/layout.c')
-rw-r--r-- | src/gtkext/graph/layout.c | 120 |
1 files changed, 105 insertions, 15 deletions
diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c index 45e3a82..2cf4a36 100644 --- a/src/gtkext/graph/layout.c +++ b/src/gtkext/graph/layout.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * layout.c - mise en place de graphique * - * Copyright (C) 2009-2012 Cyrille Bagard + * Copyright (C) 2009-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -33,14 +33,33 @@ #include "node.h" #include "../gtkbufferview.h" #include "../../analysis/binary.h" +#include "../../analysis/blocks/flow.h" #include "../../common/extstr.h" +/* Taille maximale des introductions aux clusters */ +#define CLUSTER_DESC_LEN 128 + /* Taille maximale des descriptions de liens */ #define LINKS_DESC_LEN 128 +/* Paramètres de construction des commandes */ +typedef struct _visitor_dot_params +{ + GGraphNode **nodes; /* Intermédiaires en place */ + size_t count; /* Quantité de noeuds en place */ + + unsigned int level; /* Profondeur de la visite */ + char *cmds; /* Description à envoyer à dot */ + +} visitor_dot_params; + + +/* Construit les commandes pour dot en parcourant les noeuds. */ +static bool register_graph_nodes(GInstrBlock *, BlockVisitOrder, visitor_dot_params *); + /* Etablit tous les liens entre les différents morceaux de code. */ static char *complete_graph_links(const GtkGraphView *, GtkViewPanel **, size_t, char *); @@ -60,47 +79,118 @@ static char *complete_graph_links(const GtkGraphView *, GtkViewPanel **, size_t, * * ******************************************************************************/ -bool build_graph_view(GtkGraphView *view, GtkViewPanel **views, size_t count) +bool build_graph_view(GtkGraphView *view, GInstrBlock *blocks, GtkViewPanel **views, size_t count) { - GGraphNode **nodes; /* Intermédiaires en place */ + visitor_dot_params params; /* Paramètres de construction */ size_t i; /* Boucle de parcours */ - char *cmds; /* Description à envoyer à dot */ graph_layout *layout; /* Graphique construit */ GtkLinkRenderer **links; /* Liens graphiques construits */ size_t links_count; /* Quantité de ces liens */ /* Création de la glue */ - nodes = (GGraphNode **)calloc(count, sizeof(GGraphNode *)); + params.nodes = (GGraphNode **)calloc(count, sizeof(GGraphNode *)); + params.count = count; for (i = 0; i < count; i++) - nodes[i] = g_graph_node_new(GTK_WIDGET(views[i])); + params.nodes[i] = g_graph_node_new(GTK_WIDGET(views[i])); /* Définition du graphique */ - cmds = strdup("digraph G {\n overlap=false;\n splines=ortho;\n compound=true;\n"); + params.level = 1; + params.cmds = strdup("digraph G {\n overlap=false;\n splines=ortho;\n compound=true;\n"); - for (i = 0; i < count; i++) - cmds = g_graph_node_register_for_dot(nodes[i], cmds); + g_instr_block_visit(blocks, (instr_block_visitor_cb)register_graph_nodes, ¶ms); - cmds = complete_graph_links(view, views, count, cmds); + params.cmds = complete_graph_links(view, views, count, params.cmds); - cmds = stradd(cmds, "}"); + params.cmds = stradd(params.cmds, "}"); - layout = create_graph_layout(cmds); + layout = create_graph_layout(params.cmds); /* Affichage du graphique */ - place_nodes_of_graph_layout(layout, view, nodes, count); + place_nodes_of_graph_layout(layout, view, params.nodes, count); - links = create_links_from_graph_layout(layout, &links_count, nodes, count); + links = create_links_from_graph_layout(layout, &links_count, params.nodes, count); gtk_graph_view_attach_links(view, links, links_count); gtk_widget_queue_draw(GTK_WIDGET(view)); delete_graph_layout(layout); - /* TODO : free nodes */ + for (i = 0; i < count; i++) + g_object_unref(params.nodes[i]); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : block = bloc d'instructions concerné par la visite. * +* order = position dans la visite. * +* params = informations à mettre à jour pour dot. * +* * +* Description : Construit les commandes pour dot en parcourant les noeuds. * +* * +* Retour : true si le parcours a été jusqu'à son terme, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool register_graph_nodes(GInstrBlock *block, BlockVisitOrder order, visitor_dot_params *params) +{ + char *cmds; /* Raccourci d'usage pratique */ + vmpa_t start; /* Adresse de départ d'un bloc */ + GGraphNode *node; /* Noeud rattaché */ + unsigned int i; /* Boucle de parcours */ + char buffer[CLUSTER_DESC_LEN]; /* Tampon pour les commandes */ + + cmds = params->cmds; + + if (G_IS_FLOW_BLOCK(block)) + { + g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(block), &start, NULL); + node = find_graph_node_by_start_address(params->nodes, params->count, start); + + cmds = g_graph_node_register_for_dot(node, cmds, params->level); + + } + else + { + if (order == BVO_IN) + { + for (i = 0; i < params->level; i++) + cmds = stradd(cmds, DOT_IDENT); + + snprintf(buffer, CLUSTER_DESC_LEN, "subgraph cluster_v%p {\n", block); + cmds = stradd(cmds, buffer); + + params->level++; + + for (i = 0; i < params->level; i++) + cmds = stradd(cmds, DOT_IDENT); + + cmds = stradd(cmds, "style=invisible;\n"); + + } + else if (order == BVO_OUT) + { + params->level--; + + for (i = 0; i < params->level; i++) + cmds = stradd(cmds, DOT_IDENT); + + cmds = stradd(cmds, "}\n"); + + } + + } + + params->cmds = cmds; return true; |