diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2013-01-05 13:30:19 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2013-01-05 13:30:19 (GMT) |
commit | d626276398a3cdd3cd6432e073a8866aa91418ce (patch) | |
tree | 15e4b325ebb0636b26058cd39fda3e1e87b534cc /src/gtkext/graph | |
parent | bfd81d1f289913f4d6e09cd8d99f4aaeed98436b (diff) |
Refined the definition of basic blocks and used them to build extra clusters for dot.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@317 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/gtkext/graph')
-rw-r--r-- | src/gtkext/graph/layout.c | 120 | ||||
-rw-r--r-- | src/gtkext/graph/layout.h | 2 | ||||
-rw-r--r-- | src/gtkext/graph/node.c | 78 | ||||
-rw-r--r-- | src/gtkext/graph/node.h | 13 |
4 files changed, 184 insertions, 29 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; diff --git a/src/gtkext/graph/layout.h b/src/gtkext/graph/layout.h index ffb227f..7a3bf1e 100644 --- a/src/gtkext/graph/layout.h +++ b/src/gtkext/graph/layout.h @@ -34,7 +34,7 @@ /* Dispose une série de morceaux d'affichage en graphique. */ -bool build_graph_view(GtkGraphView *, GtkViewPanel **, size_t); +bool build_graph_view(GtkGraphView *, GInstrBlock *, GtkViewPanel **, size_t); diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c index 0d746e2..d9b0eca 100644 --- a/src/gtkext/graph/node.c +++ b/src/gtkext/graph/node.c @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * node.c - éléments de graphiques chez dot * - * Copyright (C) 2009-2012 Cyrille Bagard + * Copyright (C) 2009-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -29,6 +29,7 @@ #include <string.h> +#include "../gtkbufferview.h" #include "../../common/extstr.h" @@ -60,6 +61,10 @@ struct _GGraphNodeClass }; +/* Taille maximale des lignes de description de noeud */ +#define NODE_DESC_LEN 128 + + /* Initialise la classe des intermédiaires avec les noeuds dot. */ static void g_graph_node_class_init(GGraphNodeClass *); @@ -184,8 +189,9 @@ GGraphNode *g_graph_node_new(GtkWidget *view) /****************************************************************************** * * -* Paramètres : node = intermédiaire à consulter. * -* cmds = description pour dot à compléter. * +* Paramètres : node = intermédiaire à consulter. * +* cmds = description pour dot à compléter. * +* level = profondeur du noeud pour l'indentation. * * * * Description : Déclare l'intermédiaire en tant que noeud pour dot. * * * @@ -195,33 +201,45 @@ GGraphNode *g_graph_node_new(GtkWidget *view) * * ******************************************************************************/ -char *g_graph_node_register_for_dot(const GGraphNode *node, char *cmds) +char *g_graph_node_register_for_dot(const GGraphNode *node, char *cmds, unsigned int level) { GtkRequisition requisition; /* Taille à l'écran requise */ - char buffer[128]; + unsigned int i; /* Boucle de parcours */ + char buffer[NODE_DESC_LEN]; /* Tampon pour les commandes */ gtk_widget_size_request(node->view, &requisition); - snprintf(buffer, 128, " subgraph cluster%s {\n", node->name); + for (i = 0; i < level; i++) + cmds = stradd(cmds, DOT_IDENT); + + snprintf(buffer, NODE_DESC_LEN, "subgraph cluster%s {\n", node->name); cmds = stradd(cmds, buffer); - cmds = stradd(cmds, " style=invisible;\n"); + for (i = 0; i < (level + 1); i++) + cmds = stradd(cmds, DOT_IDENT); + + cmds = stradd(cmds, "style=invisible;\n"); + + for (i = 0; i < (level + 1); i++) + cmds = stradd(cmds, DOT_IDENT); - cmds = stradd(cmds, " "); cmds = stradd(cmds, node->name); cmds = stradd(cmds, " [shape=box, fixedsize "); - snprintf(buffer, 128, ", width=\"%g\"", + snprintf(buffer, NODE_DESC_LEN, ", width=\"%g\"", requisition.width / G_GRAPH_NODE_GET_CLASS(node)->dpi_x); cmds = stradd(cmds, buffer); - snprintf(buffer, 128, ", height=\"%g\"", + snprintf(buffer, NODE_DESC_LEN, ", height=\"%g\"", requisition.height / G_GRAPH_NODE_GET_CLASS(node)->dpi_y); cmds = stradd(cmds, buffer); cmds = stradd(cmds, "];\n"); - cmds = stradd(cmds, " }\n"); + for (i = 0; i < level; i++) + cmds = stradd(cmds, DOT_IDENT); + + cmds = stradd(cmds, "}\n"); return cmds; @@ -327,6 +345,44 @@ void g_graph_node_connect(const GGraphNode *node, gint x, gint y, GdkPoint **poi /****************************************************************************** * * +* Paramètres : nodes = liste de noeuds à parcourir. * +* count = taille de la liste. * +* addrt = adresse de début du noeud recherché. * +* * +* Description : Recherche un noeud donné dans une série de noeuds. * +* * +* Retour : Noeud trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGraphNode *find_graph_node_by_start_address(GGraphNode **nodes, size_t count, vmpa_t addr) +{ + GGraphNode *result; /* Trouvaille à remonter */ + size_t i; /* Boucle de parcours */ + GBufferView *buffer; /* Tampon d'une partie de code */ + vmpa_t start; /* Adresse de départ du tampon */ + + result = NULL; + + for (i = 0; i < count && result == NULL; i++) + { + buffer = gtk_buffer_view_get_buffer(GTK_BUFFER_VIEW(nodes[i]->view)); + g_buffer_view_get_restrictions(buffer, &start, NULL); + + if (start == addr) + result = nodes[i]; + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : nodes = liste de noeuds à parcourir. * * count = taille de la liste. * * target = nom du noeud recherché. * diff --git a/src/gtkext/graph/node.h b/src/gtkext/graph/node.h index 515c92b..57d0932 100644 --- a/src/gtkext/graph/node.h +++ b/src/gtkext/graph/node.h @@ -2,7 +2,7 @@ /* OpenIDA - Outil d'analyse de fichiers binaires * node.h - prototypes pour les éléments de graphiques chez dot * - * Copyright (C) 2009-2012 Cyrille Bagard + * Copyright (C) 2009-2013 Cyrille Bagard * * This file is part of OpenIDA. * @@ -26,6 +26,12 @@ #include "../gtkgraphview.h" +#include "../../arch/archbase.h" + + + +/* Indentation pour l'édition des commandes */ +#define DOT_IDENT " " @@ -53,7 +59,7 @@ GType g_graph_node_get_type(void); GGraphNode *g_graph_node_new(GtkWidget *); /* Déclare l'intermédiaire en tant que noeud pour dot. */ -char *g_graph_node_register_for_dot(const GGraphNode *, char *); +char *g_graph_node_register_for_dot(const GGraphNode *, char *, unsigned int); /* Place le morceau de code de l'intermédiaire à l'écran. */ void g_graph_node_place(GGraphNode *, GtkGraphView *, gint , gint); @@ -67,6 +73,9 @@ void g_graph_node_connect(const GGraphNode *, gint, gint, GdkPoint **, size_t *) /* Recherche un noeud donné dans une série de noeuds. */ +GGraphNode *find_graph_node_by_start_address(GGraphNode **, size_t, vmpa_t); + +/* Recherche un noeud donné dans une série de noeuds. */ GGraphNode *find_graph_node_by_name(GGraphNode **, size_t, const char *); |