summaryrefslogtreecommitdiff
path: root/src/gtkext/graph/layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkext/graph/layout.c')
-rw-r--r--src/gtkext/graph/layout.c120
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, &params);
- 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;