From 5dcd05f19ac62f6ff922176cd0ae6f8839910f2e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 1 Jul 2012 11:52:52 +0000
Subject: Built the graph view when defining a target address.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@247 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                          | 21 ++++++++++
 src/analysis/binary.c              | 20 ++--------
 src/analysis/disass/disassembler.c |  5 ++-
 src/analysis/disass/disassembler.h |  4 +-
 src/format/dex/method.c            |  2 +-
 src/glibext/gcodebuffer.c          | 12 +++---
 src/graph/node.c                   | 13 ++-----
 src/gtkext/gtkgraphview.c          | 78 ++++++++++++++++++++++++++++++++++++--
 src/gtkext/gtkviewpanel-int.h      |  4 ++
 src/gtkext/gtkviewpanel.c          |  6 +--
 10 files changed, 122 insertions(+), 43 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6968d8a..09f90ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+12-07-01  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/binary.c:
+	* src/analysis/disass/disassembler.c:
+	* src/analysis/disass/disassembler.h:
+	Provide disassembled instructions when done with disassembling.
+
+	* src/format/dex/method.c:
+	Set the method size.
+
+	* src/glibext/gcodebuffer.c:
+	Draw the restricted part of the buffer correctly.
+
+	* src/graph/node.c:
+	Typo.
+
+	* src/gtkext/gtkgraphview.c:
+	* src/gtkext/gtkviewpanel.c:
+	* src/gtkext/gtkviewpanel-int.h:
+	Build the graph view when defining a target address.
+
 12-06-30  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/glibext/gcodebuffer.c:
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 53da917..45e6d31 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -96,6 +96,7 @@ struct _GOpenidaBinary
     GRenderingLine *lines;                  /* Lignes de rendu en place    */
     GRenderingOptions *options;             /* Options de désassemblage    */
 
+    GArchInstruction *instrs;               /* Instructions d'assemblage   */
     GCodeBuffer *disass_buffer;             /* Instructions lisibles       */
     GCodeBuffer **dec_buffers;              /* Sources sous forme de texte */
     size_t decbuf_count;                    /* Taille des tableaux         */
@@ -834,7 +835,7 @@ void g_openida_binary_analyse(GOpenidaBinary *binary)
         }
     }
 
-    binary->disass_buffer = disassemble_binary(binary, parts, parts_count);
+    binary->disass_buffer = disassemble_binary(binary, parts, parts_count, &binary->instrs);
 
     /* TODO : remme ! */
     ack_completed_disassembly(NULL, binary);
@@ -993,22 +994,7 @@ GRenderingLine *g_openida_binary_get_lines(const GOpenidaBinary *binary)
 
 GArchInstruction *g_openida_binary_get_instructions(const GOpenidaBinary *binary)
 {
-    GArchInstruction *result;               /* Liste à renvoyer            */
-    GRenderingLine *iter;                   /* Boucle de parcours          */
-
-    result = NULL;
-
-    for (iter = binary->lines;
-         iter != NULL;
-         iter = g_rendering_line_get_next_iter(binary->lines, iter, NULL))
-    {
-        if (G_IS_CODE_LINE(iter)) break;
-    }
-
-    if (iter != NULL)
-        result = g_code_line_get_instruction(G_CODE_LINE(iter));
-
-    return result;
+    return binary->instrs;
 
 }
 
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index c270389..5a866c0 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -368,6 +368,7 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
 *  Paramètres  : binary = représentation de binaire chargé.                   *
 *                parts  = parties binaires à désassembler.                    *
 *                count  = nombre de parties à traiter.                        *
+*                instrs = liste des instructions chargées. [OUT]              *
 *                                                                             *
 *  Description : Procède au désassemblage d'un contenu binaire donné.         *
 *                                                                             *
@@ -377,7 +378,7 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
 *                                                                             *
 ******************************************************************************/
 
-GCodeBuffer *disassemble_binary(const GOpenidaBinary *binary, GBinPart **parts, size_t parts_count)
+GCodeBuffer *disassemble_binary(const GOpenidaBinary *binary, GBinPart **parts, size_t parts_count, GArchInstruction **instrs)
 {
     GCodeBuffer *result;                    /* Tampon constitué à renvoyer */
     const uint8_t *data;                    /* Données binaires brutes     */
@@ -397,6 +398,8 @@ GCodeBuffer *disassemble_binary(const GOpenidaBinary *binary, GBinPart **parts,
 
     g_delayed_work_wait_for_completion(G_DELAYED_WORK(disass));
 
+    *instrs = disass->instrs;
+
     g_object_unref(G_OBJECT(disass));
 
     return result;
diff --git a/src/analysis/disass/disassembler.h b/src/analysis/disass/disassembler.h
index 7cfdcc5..2a0f72a 100644
--- a/src/analysis/disass/disassembler.h
+++ b/src/analysis/disass/disassembler.h
@@ -2,7 +2,7 @@
 /* OpenIDA - Outil d'analyse de fichiers binaires
  * disassembler.h - prototypes pour l'encadrement des phases de désassemblage
  *
- * Copyright (C) 2010 Cyrille Bagard
+ * Copyright (C) 2010-2012 Cyrille Bagard
  *
  *  This file is part of OpenIDA.
  *
@@ -31,7 +31,7 @@
 
 
 /* Procède à la décompilation des routines d'un fichier donné. */
-GCodeBuffer *disassemble_binary(const GOpenidaBinary *, GBinPart **parts, size_t parts_count);
+GCodeBuffer *disassemble_binary(const GOpenidaBinary *, GBinPart **parts, size_t parts_count, GArchInstruction **);
 
 
 
diff --git a/src/format/dex/method.c b/src/format/dex/method.c
index 95f121a..cca03a7 100644
--- a/src/format/dex/method.c
+++ b/src/format/dex/method.c
@@ -161,7 +161,7 @@ GDexMethod *g_dex_method_new(const GDexFormat *format, const encoded_method *see
 
 
     g_binary_routine_set_address(routine, result->offset);
-
+    g_binary_routine_set_size(routine, item.insns_size * sizeof(uint16_t));
 
     result->routine = routine;
 
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index d5dbc8c..97d6505 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -731,7 +731,7 @@ void g_buffer_view_get_size(GBufferView *view, gint *width, gint *height, bool a
     first = g_code_buffer_get_index_from_address(view->buffer, view->start);
     last = g_code_buffer_get_index_from_address(view->buffer, view->end);
 
-    *height *= (last - first);
+    *height *= (last - first + 1);
 
 }
 
@@ -783,6 +783,7 @@ void g_buffer_view_draw(const GBufferView *view, const GdkEventExpose *event, Gd
     gint real_y;                            /* Ordonnée réelle pour tampon */
 
     size_t first;                           /* Première ligne visée        */
+    size_t end;                             /* Dernière ligne avant limite */
     size_t last;                            /* Dernière ligne visée + 1    */
     gint y;                                 /* Point de départ + décallage */
 
@@ -799,16 +800,17 @@ void g_buffer_view_draw(const GBufferView *view, const GdkEventExpose *event, Gd
 
 
 
-    first = (real_y / view->line_height);
+    first = g_code_buffer_get_index_from_address(view->buffer, view->start);
+    first += (real_y / view->line_height);
+
     last = first + (event->area.height / view->line_height);
     if (event->area.height % view->line_height > 0) last++;
 
-    last = MIN(last, view->buffer->used > 0 ? view->buffer->used - 1 : 0);
+    end = g_code_buffer_get_index_from_address(view->buffer, view->end);
+    last = MIN(last, end);
 
     y = event->area.y - (real_y % view->line_height);
 
-
-
     lines = view->buffer->lines;
 
     if (view->buffer->used > 0)
diff --git a/src/graph/node.c b/src/graph/node.c
index 3e6cc14..0d278f3 100644
--- a/src/graph/node.c
+++ b/src/graph/node.c
@@ -203,17 +203,12 @@ char *g_graph_node_register_for_dot(const GGraphNode *node, char *cmds)
     cmds = stradd(cmds, node->name);
     cmds = stradd(cmds, " [shape=box, fixedsize ");
 
-
-    printf(" req=(%d ; %d) -->> (%g ; %g)\n",
-           requisition.width,
-           requisition.height,
-           requisition.width / G_GRAPH_NODE_GET_CLASS(node)->dpi_x,
-           requisition.height / G_GRAPH_NODE_GET_CLASS(node)->dpi_y);
-
-    snprintf(buffer, 128, ", width=\"%g\"", requisition.width / G_GRAPH_NODE_GET_CLASS(node)->dpi_x);
+    snprintf(buffer, 128, ", width=\"%g\"",
+             requisition.width / G_GRAPH_NODE_GET_CLASS(node)->dpi_x);
     cmds = stradd(cmds, buffer);
 
-    snprintf(buffer, 128, ", height=\"%g\"", requisition.height / G_GRAPH_NODE_GET_CLASS(node)->dpi_y);
+    snprintf(buffer, 128, ", height=\"%g\"",
+             requisition.height / G_GRAPH_NODE_GET_CLASS(node)->dpi_y);
     cmds = stradd(cmds, buffer);
 
     cmds = stradd(cmds, "];\n");
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c
index 263ab7d..8366c1f 100644
--- a/src/gtkext/gtkgraphview.c
+++ b/src/gtkext/gtkgraphview.c
@@ -27,6 +27,7 @@
 #include "gtkblockview.h"
 #include "gtkbufferview.h"
 #include "gtkviewpanel-int.h"
+#include "../graph/layout.h"
 
 
 
@@ -41,7 +42,7 @@ struct _GtkGraphView
     vmpa_t start;                           /* Début de la portion vue     */
     vmpa_t end;                             /* Fin de la portion affichée  */
 
-    GtkBlockView **childs;                  /* Liste des sous-blocs        */
+    GtkViewPanel **childs;                  /* Liste des sous-blocs        */
     size_t childs_count;                    /* Taille de cette liste       */
 
     GtkLinkRenderer **links;                /* Liste des liens graphiques  */
@@ -73,6 +74,9 @@ static void gtk_graph_view_size_allocate(GtkWidget *, GtkAllocation *);
 /*  Met à jour l'affichage de la vue sous forme graphique. */
 static gboolean gtk_graph_view_expose(GtkWidget *, GdkEventExpose *, GtkGraphView *);
 
+/* Réagit à la sélection externe d'une adresse. */
+static void gtk_graph_view_define_main_address(GtkGraphView *, vmpa_t);
+
 /* Indique la position d'affichage d'une adresse donnée. */
 static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *, vmpa_t, gint *, gint *);
 
@@ -82,6 +86,9 @@ static void gtk_graph_view_scroll(GtkGraphView *);
 /* Supprime tout contenu de l'afficheur de code en graphique. */
 static void gtk_graph_view_reset(GtkGraphView *);
 
+/* Liste d'éléments du graphique à placer. */
+static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *, GOpenidaBinary *, vmpa_t, vmpa_t);
+
 
 
 /* Détermine le type du composant d'affichage en graphique. */
@@ -132,6 +139,7 @@ static void gtk_graph_view_init(GtkGraphView *view)
 
     viewpanel = GTK_VIEW_PANEL(view);
 
+    viewpanel->define = (define_address_fc)gtk_graph_view_define_main_address;
     viewpanel->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates;
     viewpanel->scroll = (scroll_fc)gtk_graph_view_scroll;
 
@@ -287,6 +295,61 @@ static gboolean gtk_graph_view_expose(GtkWidget *widget, GdkEventExpose *event,
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : view = composant GTK à mettre à jour.                        *
+*                addr = adresse sélectionnée de manière externe.              *
+*                                                                             *
+*  Description : Réagit à la sélection externe d'une adresse.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_graph_view_define_main_address(GtkGraphView *view, vmpa_t addr)
+{
+    GExeFormat *format;                     /* Type de fichier chargé      */
+    GBinRoutine **routines;                 /* Liste des routines trouvées */
+    size_t routines_count;                  /* Nombre de ces routines      */
+    size_t i;                               /* Boucle de parcours          */
+    vmpa_t start;                           /* Début d'une routine         */
+    vmpa_t end;                             /* Fin d'une routine           */
+
+    if (!(view->start <= addr && addr < view->end))
+    {
+        gtk_graph_view_reset(view);
+
+        format = g_openida_binary_get_format(GTK_VIEW_PANEL(view)->binary);
+        routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count);
+
+        for (i = 0; i < routines_count; i++)
+        {
+            start = g_binary_routine_get_address(routines[i]);
+            end = start + g_binary_routine_get_size(routines[i]);
+
+            if (start <= addr && addr < end)
+            {
+                view->start = start;
+                view->end = end;
+
+                view->childs = gtk_graph_view_load_nodes(view, GTK_VIEW_PANEL(view)->binary,
+                                                         start, end);
+
+                build_graph_view(view, view->childs, view->childs_count);
+
+                break;
+
+            }
+
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : view = composant GTK à consulter.                            *
 *                addr = adresse à présenter à l'écran.                        *
 *                x    = position horizontale au sein du composant. [OUT]      *
@@ -495,6 +558,7 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GOpenidaBina
     code = g_openida_binary_display_code_in_text(binary);
 
     first = start;
+    last = first;
 
     for (iter = g_arch_instruction_find_by_address(list, start, true);
          iter != NULL;
@@ -505,11 +569,13 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GOpenidaBina
             result = (GtkViewPanel **)realloc(result, ++(*count) * sizeof(GtkViewPanel *));
 
             result[*count - 1] = GTK_VIEW_PANEL(gtk_block_view_new());
+            gtk_widget_show(result[*count - 1]);
+            gtk_view_panel_attach_binary(result[*count - 1], binary, addr, code);
 
             gtk_view_panel_show_border(result[*count - 1], true);
 
             subview = g_buffer_view_new(buffer);
-            //g_buffer_view_restrict(subview, size_t first, size_t last);
+            g_buffer_view_restrict(subview, first, last);
             gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(result[*count - 1]),
                                           subview, addr, code);
 
@@ -525,11 +591,13 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GOpenidaBina
             result = (GtkViewPanel **)realloc(result, ++(*count) * sizeof(GtkViewPanel *));
 
             result[*count - 1] = GTK_VIEW_PANEL(gtk_block_view_new());
+            gtk_widget_show(result[*count - 1]);
+            gtk_view_panel_attach_binary(result[*count - 1], binary, addr, code);
 
             gtk_view_panel_show_border(result[*count - 1], true);
 
             subview = g_buffer_view_new(buffer);
-            //g_buffer_view_restrict(subview, size_t first, size_t last);
+            g_buffer_view_restrict(subview, first, last);
             gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(result[*count - 1]),
                                           subview, addr, code);
 
@@ -544,11 +612,13 @@ static GtkViewPanel **gtk_graph_view_load_nodes(GtkGraphView *view, GOpenidaBina
         result = (GtkViewPanel **)realloc(result, ++(*count) * sizeof(GtkViewPanel *));
 
         result[*count - 1] = GTK_VIEW_PANEL(gtk_block_view_new());
+        gtk_widget_show(result[*count - 1]);
+        gtk_view_panel_attach_binary(result[*count - 1], binary, addr, code);
 
         gtk_view_panel_show_border(result[*count - 1], true);
 
         subview = g_buffer_view_new(buffer);
-        //g_buffer_view_restrict(subview, size_t first, size_t last);
+        g_buffer_view_restrict(subview, first, last);
         gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(result[*count - 1]),
                                       subview, addr, code);
 
diff --git a/src/gtkext/gtkviewpanel-int.h b/src/gtkext/gtkviewpanel-int.h
index 446d182..a4edd06 100644
--- a/src/gtkext/gtkviewpanel-int.h
+++ b/src/gtkext/gtkviewpanel-int.h
@@ -36,6 +36,9 @@
 /* Prend acte de l'association d'un binaire chargé. */
 typedef void (* attach_binary_fc) (GtkViewPanel *, GOpenidaBinary *, bool *, bool *);
 
+/* Réagit à la sélection externe d'une adresse. */
+typedef void (* define_address_fc) (GtkViewPanel *, vmpa_t);
+
 /* Indique la position d'affichage d'une adresse donnée. */
 typedef bool (* get_addr_coordinates_fc) (const GtkViewPanel *, vmpa_t, gint *, gint *);
 
@@ -57,6 +60,7 @@ struct _GtkViewPanel
     GOpenidaBinary *binary;                 /* Binaire à visualiser        */
 
     attach_binary_fc attach;                /* Association avec un binaire */
+    define_address_fc define;               /* Centrage sur une partie     */
     get_addr_coordinates_fc get_coordinates;/* Conversion adresse <-> pos. */
     scroll_fc scroll;                       /* Défilement du contenu       */
 
diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c
index 2dac981..326e4d8 100644
--- a/src/gtkext/gtkviewpanel.c
+++ b/src/gtkext/gtkviewpanel.c
@@ -517,10 +517,8 @@ void gtk_view_panel_scroll_to_address(const GtkViewPanel *panel, vmpa_t addr)
     gint y;                                 /* Ordonnée à garantir         */
     GtkAdjustment *adj;                     /* Défilement à mettre à jour  */
 
-    /* TODO
-    if (panel->define_address != NULL)
-        panel->define_address(panel, addr);
-    */
+    if (panel->define != NULL)
+        panel->define(panel, addr);
 
     if (panel->get_coordinates(panel, addr, &x, &y))
     {
-- 
cgit v0.11.2-87-g4458