summaryrefslogtreecommitdiff
path: root/src/gtkext/graph
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2013-01-05 13:30:19 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2013-01-05 13:30:19 (GMT)
commitd626276398a3cdd3cd6432e073a8866aa91418ce (patch)
tree15e4b325ebb0636b26058cd39fda3e1e87b534cc /src/gtkext/graph
parentbfd81d1f289913f4d6e09cd8d99f4aaeed98436b (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.c120
-rw-r--r--src/gtkext/graph/layout.h2
-rw-r--r--src/gtkext/graph/node.c78
-rw-r--r--src/gtkext/graph/node.h13
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, &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;
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 *);