diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2016-12-30 10:38:52 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2016-12-30 10:38:52 (GMT) |
commit | 932ea7c83c07d3982fee605c6dd9895fd2753874 (patch) | |
tree | 766ad53bab9e3e3005334c30e823493de8e84168 /src/gtkext/gtkgraphview.c | |
parent | 1b5d39bfbc48c33a0ea0924b60e48448c8b45dd4 (diff) |
Rewritten the line buffers using generators and on-demand building to save memory.
Diffstat (limited to 'src/gtkext/gtkgraphview.c')
-rw-r--r-- | src/gtkext/gtkgraphview.c | 1371 |
1 files changed, 0 insertions, 1371 deletions
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c deleted file mode 100644 index 57bbec0..0000000 --- a/src/gtkext/gtkgraphview.c +++ /dev/null @@ -1,1371 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gtkgraphview.c - affichage de morceaux de code sous forme graphique - * - * Copyright (C) 2009-2014 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "gtkgraphview.h" - - -#include <assert.h> - - -#include "gtkblockview.h" -#include "gtkbufferview.h" -#include "gtkdisplaypanel-int.h" -#include "graph/cluster.h" -#include "../analysis/blocks/flow.h" -#include "../format/format.h" -#include "../gui/editem.h" - - - -/* Composant d'affichage sous forme graphique (instance) */ -struct _GtkGraphView -{ - GtkDisplayPanel parent; /* A laisser en premier */ - GtkWidget *support; /* Support des vues en bloc */ - GtkWidget *extender; /* Force la taille du support */ - - GBinRoutine *routine; /* Routine en cours d'affichage*/ - - segcnt_list *highlighted; /* Segments mis en évidence */ - GtkBufferView **children; /* Liste des sous-blocs */ - GtkAllocation *allocs; /* Emplacements prévisibles */ - size_t children_count; /* Taille de cette liste */ - - //GGraphLayout *layout; /* Disposition en graphique */ - GGraphCluster *cluster; /* Disposition en graphique */ - - GGraphEdge **edges; /* Liens entre les noeuds */ - size_t edges_count; /* Quantité de ces liens */ - - gdouble start_x; /* Abscisse du point de souris */ - gdouble start_y; /* Ordonnée du point de souris */ - bool big_enough; /* Capacités de déplacement ? */ - gdouble ref_h; /* Position horizontale de ref.*/ - gdouble ref_v; /* Position verticale de ref. */ - -}; - -/* Composant d'affichage sous forme graphique (classe) */ -struct _GtkGraphViewClass -{ - GtkDisplayPanelClass parent; /* A laisser en premier */ - -}; - - -/* Profondeur de l'ombre */ -#define SHADOW_SIZE 4 - - -/* Initialise la classe générique des graphiques de code. */ -static void gtk_graph_view_class_init(GtkGraphViewClass *); - -/* Initialise une instance d'afficheur de code en graphique. */ -static void gtk_graph_view_init(GtkGraphView *); - -/* Supprime toutes les références externes. */ -static void gtk_graph_view_dispose(GtkGraphView *); - -/* Procède à la libération totale de la mémoire. */ -static void gtk_graph_view_finalize(GtkGraphView *); - -/* S'adapte à la surface concédée par le composant parent. */ -static void gtk_graph_view_size_allocate(GtkWidget *, GtkAllocation *); - -/* Centre si possible le contenu du panneau d'affichage. */ -static void gtk_graph_view_update_support_margins(GtkGraphView *, const GtkAllocation *); - -/* Indique les dimensions de travail du composant d'affichage. */ -static void gtk_graph_view_compute_requested_size(GtkGraphView *, gint *, gint *); - -/* Réagit à un défilement chez une barre associée au composant. */ -static void gtk_graph_view_adjust_scroll_value(GtkGraphView *, GtkAdjustment *, GtkOrientation); - -/* Met à jour l'affichage de la vue sous forme graphique. */ -static gboolean gtk_graph_view_draw(GtkWidget *, cairo_t *, GtkGraphView *); - -/* Assure la gestion des clics de souris sur le composant. */ -static gboolean gtk_graph_view_button_press(GtkWidget *, GdkEventButton *, GtkGraphView *); - -/* Assure la gestion des clics de souris sur le composant. */ -static gboolean gtk_graph_view_button_release(GtkWidget *, GdkEventButton *, GtkGraphView *); - -/* Assure la suivi des déplacements de souris sur le composant. */ -static gboolean gtk_graph_view_motion_notify(GtkWidget *, GdkEventMotion *, GtkGraphView *); - -/* Actualise les besoins internes avant un redimensionnement. */ -static void gtk_graph_view_prepare_resize(GtkGraphView *); - -/* Réagit à la sélection externe d'une adresse. */ -static void gtk_graph_view_define_main_address(GtkGraphView *, const vmpa2t *); - -/* Indique la position courante du curseur. */ -static const vmpa2t *gtk_graph_view_get_caret_location(const GtkGraphView *); - -/* Indique la position d'affichage d'une adresse donnée. */ -static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak); - -/* Déplace le curseur à un emplacement défini. */ -static bool gtk_graph_view_move_caret_to(GtkGraphView *, gint, gint); - -/* Place en cache un rendu destiné à l'aperçu graphique rapide. */ -static void gtk_graph_view_cache_glance(GtkGraphView *, cairo_t *, const GtkAllocation *, double); - -/* Supprime tout contenu de l'afficheur de code en graphique. */ -static void gtk_graph_view_reset(GtkGraphView *); - -/* Définit la liste complète des éléments du futur graphique. */ -static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *, GLoadedBinary *, const GBinRoutine *); - -/* Notifie un changement de surbrillance au sein d'un noeud. */ -static void gtk_graph_view_changed_highlights(GtkBlockView *, GtkGraphView *); - -/* Notifie une incapacité de déplacement au sein d'un noeud. */ -static void gtk_graph_view_reach_caret_limit(GtkBufferView *, GdkScrollDirection, GtkGraphView *); - - - -/* Détermine le type du composant d'affichage en graphique. */ -G_DEFINE_TYPE(GtkGraphView, gtk_graph_view, GTK_TYPE_DISPLAY_PANEL) - - -/****************************************************************************** -* * -* Paramètres : class = classe GTK à initialiser. * -* * -* Description : Initialise la classe générique des graphiques de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_class_init(GtkGraphViewClass *class) -{ - GObjectClass *object; /* Autre version de la classe */ - GtkWidgetClass *widget_class; /* Classe de haut niveau */ - GtkDisplayPanelClass *panel_class; /* Classe parente */ - - object = G_OBJECT_CLASS(class); - - object->dispose = (GObjectFinalizeFunc/* ! */)gtk_graph_view_dispose; - object->finalize = (GObjectFinalizeFunc)gtk_graph_view_finalize; - - widget_class = GTK_WIDGET_CLASS(class); - - widget_class->size_allocate = gtk_graph_view_size_allocate; - - panel_class = GTK_DISPLAY_PANEL_CLASS(class); - - panel_class->compute_size = (compute_requested_size_fc)gtk_graph_view_compute_requested_size; - panel_class->adjust = (adjust_scroll_value_fc)gtk_graph_view_adjust_scroll_value; - panel_class->define = (define_address_fc)gtk_graph_view_define_main_address; - - panel_class->get_caret_loc = (get_caret_location_fc)gtk_graph_view_get_caret_location; - panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates; - panel_class->move_caret_to = (move_caret_to_fc)gtk_graph_view_move_caret_to; - panel_class->cache_glance = (cache_glance_fc)gtk_graph_view_cache_glance; - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance GTK à initialiser. * -* * -* Description : Initialise une instance d'afficheur de code en graphique. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_init(GtkGraphView *view) -{ - GtkDisplayPanel *panel; /* Instance parente #1 */ - //GtkBinView *binview; /* Instance parente #2 */ - - panel = GTK_DISPLAY_PANEL(view); - - panel->resize = (prepare_resize_fc)gtk_graph_view_prepare_resize; - ////////viewpanel->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates; - - //binview = GTK_BIN_VIEW(view); - - //binview->set_lines = (set_rendering_lines_fc)gtk_graph_view_set_rendering_lines; - //binview->define_address = (define_main_address_fc)gtk_graph_view_define_main_address; - //binview->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates; - - view->support = gtk_fixed_new(); - gtk_widget_set_has_window(view->support, TRUE); - gtk_widget_set_can_focus(view->support, TRUE); - - g_signal_connect(G_OBJECT(view->support), "draw", - G_CALLBACK(gtk_graph_view_draw), view); - - g_signal_connect(G_OBJECT(view->support), "button-press-event", - G_CALLBACK(gtk_graph_view_button_press), view); - g_signal_connect(G_OBJECT(view->support), "button-release-event", - G_CALLBACK(gtk_graph_view_button_release), view); - g_signal_connect(G_OBJECT(view->support), "motion-notify-event", - G_CALLBACK(gtk_graph_view_motion_notify), view); - - gtk_widget_add_events(view->support, - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); - - gtk_widget_show(view->support); - - gtk_fixed_put(GTK_FIXED(view), view->support, 0, 0); - - //view->mutex = g_mutex_new(); - //view->cond = g_cond_new(); - - - view->extender = gtk_fixed_new(); - - gtk_widget_set_margin_end(view->extender, 1); - gtk_widget_set_margin_top(view->extender, 1); - - gtk_widget_show(view->extender); - - - view->cluster = NULL; - - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_dispose(GtkGraphView *view) -{ - g_object_unref(G_OBJECT(view->extender)); - - if (view->cluster != NULL) - { - g_object_unref(G_OBJECT(view->cluster)); - view->cluster = NULL; - } - - G_OBJECT_CLASS(gtk_graph_view_parent_class)->dispose(G_OBJECT(view)); - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_finalize(GtkGraphView *view) -{ - G_OBJECT_CLASS(gtk_graph_view_parent_class)->finalize(G_OBJECT(view)); - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK à mettre à jour. * -* allocation = étendue accordée à la vue. * -* * -* Description : S'adapte à la surface concédée par le composant parent. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - GtkGraphView *view; /* Autre version du composant */ - - GTK_WIDGET_CLASS(gtk_graph_view_parent_class)->size_allocate(widget, allocation); - - view = GTK_GRAPH_VIEW(widget); - - gtk_graph_view_update_support_margins(view, allocation); - -} - -/****************************************************************************** -* * -* Paramètres : view = panneau dont le contenu est à déplacer. * -* allocation = étendue accordée à la vue. * -* * -* Description : Centre si possible le contenu du panneau d'affichage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_update_support_margins(GtkGraphView *view, const GtkAllocation *allocation) -{ - gint width; /* Largeur totale du support */ - gint height; /* Hauteur totale du support */ - gint start; /* Bordure horizontale */ - gint top; /* Bordure verticale */ - - gtk_graph_view_compute_requested_size(view, &width, &height); - - if (width > allocation->width) - start = 0; - else - start = (allocation->width - width) / 2; - - if (height > allocation->height) - top = 0; - else - top = (allocation->height - height) / 2; - - gtk_widget_set_margin_start(view->support, start); - gtk_widget_set_margin_top(view->support, top); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* width = largeur requise à renseigner ou NULL. [OUT] * -* height = hauteur requise à renseigner ou NULL. [OUT] * -* * -* Description : Indique les dimensions de travail du composant d'affichage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_compute_requested_size(GtkGraphView *view, gint *width, gint *height) -{ - GtkAllocation needed; /* Taille requise */ - gint rwidth; /* Largeur demandée */ - gint rheight; /* Hauteur demandée */ - - if (view->cluster != NULL) - { - g_graph_cluster_compute_needed_alloc(view->cluster, &needed); - assert(needed.x == 0 && needed.y == 0); - - /* TODO : marges ou centrage */ - - } - else - { - needed.width = 0; - needed.height = 0; - } - - if (width != NULL) *width = needed.width + SHADOW_SIZE; - if (height != NULL) *height = needed.height + SHADOW_SIZE; - -} - - -/****************************************************************************** -* * -* Paramètres : view = panneau d'affichage concerné. * -* adj = défilement dont une valeur a changé. * -* orientation = indication sur le défilement à traiter. * -* * -* Description : Réagit à un défilement chez une barre associée au composant. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_adjust_scroll_value(GtkGraphView *view, GtkAdjustment *adj, GtkOrientation orientation) -{ - gint fake_x; /* Abscisse virtuelle */ - gint fake_y; /* Ordonnée virtuelle */ - - fake_x = 0; - fake_y = 0; - gtk_display_panel_compute_fake_coord(GTK_DISPLAY_PANEL(view), &fake_x, &fake_y); - - gtk_fixed_move(GTK_FIXED(view), view->support, fake_x, -fake_y); - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK à redessiner. * -* cr = contexte graphique associé à l'événement. * -* view = support maître à consulter. * -* * -* Description : Met à jour l'affichage de la vue sous forme graphique. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_graph_view_draw(GtkWidget *widget, cairo_t *cr, GtkGraphView *view) -{ - size_t i; /* Boucle de parcours */ - - void draw_shadow(GtkWidget *child, gpointer unused) - { - GtkAllocation alloc; /* Emplacement de l'enfant */ - gint j; /* Boucle de parcours */ - cairo_pattern_t *pattern; /* Zones d'application */ - - gtk_widget_get_allocation(child, &alloc); - - for (j = 1; j < SHADOW_SIZE; j++) - { - cairo_push_group(cr); - - gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x + j, alloc.y + j); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); - cairo_fill(cr); - - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - - gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x, alloc.y); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); - cairo_fill(cr); - - pattern = cairo_pop_group(cr); - - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.3); - cairo_mask(cr, pattern); - cairo_fill(cr); - - cairo_pattern_destroy(pattern); - - } - - } - - gtk_container_foreach(GTK_CONTAINER(view->support), (GtkCallback)draw_shadow, NULL); - - - for (i = 0; i < view->edges_count; i++) - g_graph_edge_draw(view->edges[i], cr, true); - - - /* - if (view->layout != NULL) - g_graph_layout_draw(view->layout, cr, true); - */ - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* view = support maître à consulter. * -* * -* Description : Assure la gestion des clics de souris sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_graph_view_button_press(GtkWidget *widget, GdkEventButton *event, GtkGraphView *view) -{ - gboolean result; /* Poursuite à faire suivre */ - GtkScrolledWindow *support; /* Support défilant associé */ - GtkAdjustment *hadj; /* Gestionnaire du défilement */ - GtkAdjustment *vadj; /* Gestionnaire du défilement */ - GdkCursor *cursor; /* Pointeur pour la surface */ - - result = FALSE; - - if (event->button == 1) - { - support = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(view))); - - hadj = gtk_scrolled_window_get_hadjustment(support); - vadj = gtk_scrolled_window_get_vadjustment(support); - - view->big_enough = (gtk_adjustment_get_upper(hadj) > gtk_adjustment_get_page_size(hadj) - || gtk_adjustment_get_upper(vadj) > gtk_adjustment_get_page_size(vadj)); - - if (view->big_enough) - { - view->start_x = event->x_root; - view->start_y = event->y_root; - - view->ref_h = gtk_adjustment_get_value(hadj); - view->ref_v = gtk_adjustment_get_value(vadj); - - cursor = gdk_cursor_new(GDK_FLEUR); - gdk_window_set_cursor(gtk_widget_get_window(widget), cursor); - g_object_unref(G_OBJECT(cursor)); - - result = TRUE; - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* view = support maître à consulter. * -* * -* Description : Assure la gestion des clics de souris sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_graph_view_button_release(GtkWidget *widget, GdkEventButton *event, GtkGraphView *view) -{ - if (event->button == 1 && view->big_enough) - gdk_window_set_cursor(gtk_widget_get_window(widget), NULL); - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK visé par l'opération. * -* event = informations liées à l'événement. * -* view = support maître à consulter. * -* * -* Description : Assure la suivi des déplacements de souris sur le composant. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_graph_view_motion_notify(GtkWidget *widget, GdkEventMotion *event, GtkGraphView *view) -{ - gdouble diff_x; /* Evolution sur les abscisses */ - gdouble diff_y; /* Evolution sur les ordonnées */ - GtkScrolledWindow *support; /* Support défilant associé */ - GtkAdjustment *hadj; /* Gestionnaire du défilement */ - GtkAdjustment *vadj; /* Gestionnaire du défilement */ - gdouble value; /* Nouvelle valeur bornée */ - - if (event->state & GDK_BUTTON1_MASK && view->big_enough) - { - diff_x = view->start_x - event->x_root; - diff_y = view->start_y - event->y_root; - - support = GTK_SCROLLED_WINDOW(gtk_widget_get_parent(GTK_WIDGET(view))); - - hadj = gtk_scrolled_window_get_hadjustment(support); - vadj = gtk_scrolled_window_get_vadjustment(support); - - value = CLAMP(view->ref_h + diff_x, gtk_adjustment_get_lower(hadj), - gtk_adjustment_get_upper(hadj) - gtk_adjustment_get_page_size(hadj)); - gtk_adjustment_set_value(hadj, value); - - value = CLAMP(view->ref_v + diff_y, gtk_adjustment_get_lower(vadj), - gtk_adjustment_get_upper(vadj) - gtk_adjustment_get_page_size(vadj)); - gtk_adjustment_set_value(vadj, value); - - } - - return FALSE; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* * -* Description : Actualise les besoins internes avant un redimensionnement. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_prepare_resize(GtkGraphView *view) -{ - size_t i; /* Boucle de parcours */ - - if (view->children_count > 0) - { - for (i = 0; i < view->children_count; i++) - gtk_widget_queue_resize(GTK_WIDGET(view->children[i])); - - /* - g_graph_layout_refresh(view->layout); - g_graph_layout_place(view->layout, view); - */ - - change_editor_items_current_view_content(GTK_DISPLAY_PANEL(view)); - - } - -} - - -/****************************************************************************** -* * -* 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, const vmpa2t *addr) -{ - bool need_update; /* Mise à jour du contenu ? */ - const mrange_t *range; /* Couverture courante */ - 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 */ - gint right; /* Abscisse du coin droit */ - gint bottom; /* Ordonnée du coin inférieur */ - GtkAllocation allocation; /* Espace alloué au panneau */ - - if (view->routine == NULL) - need_update = true; - else - { - range = g_binary_routine_get_range(view->routine); - need_update = !mrange_contains_addr(range, addr); - } - - if (need_update) - { - gtk_graph_view_reset(view); - - format = g_loaded_binary_get_format(GTK_DISPLAY_PANEL(view)->binary); - routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count); - - for (i = 0; i < routines_count; i++) - { - range = g_binary_routine_get_range(routines[i]); - - if (mrange_contains_addr(range, addr)) - { - view->routine = routines[i]; - g_object_ref(G_OBJECT(view->routine)); - - view->highlighted = init_segment_content_list(); - - /* - view->children = gtk_graph_view_load_nodes(view, GTK_DISPLAY_PANEL(view)->binary, - routines[i]); - - view->allocs = (GtkAllocation *)calloc(view->children_count, - sizeof(GtkAllocation)); - - view->layout = g_graph_layout_new(g_binary_routine_get_basic_blocks(view->routine), - view->children, view->children_count); - - g_graph_layout_place(view->layout, view); - */ - - do - { - - GBlockList *list; - - list = g_binary_routine_get_basic_blocks(routines[i]); - -#if 0 - view->cluster = g_graph_cluster_new(GTK_DISPLAY_PANEL(view)->binary, - list, 0/* FIXME */, view->highlighted); -#endif - - - view->cluster = bootstrap_graph_cluster(GTK_DISPLAY_PANEL(view)->binary, - list, view->highlighted); - - - - g_graph_cluster_place(view->cluster, view); - - /** - * Comme la taille du support ne peut pas être forcée et - * étendue pour comprendre les ombres, on place un composant - * minuscule à l'extrémité de ce support. - */ - - gtk_graph_view_compute_requested_size(view, &right, &bottom); - - g_object_ref(G_OBJECT(view->extender)); - gtk_fixed_put(GTK_FIXED(view->support), view->extender, right, bottom); - - /** - * Si possible, on centre le contenu obtenu. - */ - - gtk_widget_get_allocation(GTK_WIDGET(view), &allocation); - - gtk_graph_view_update_support_margins(view, &allocation); - - - - } - while (0); - - - - break; - - } - - } - - change_editor_items_current_view_content(GTK_DISPLAY_PANEL(view)); - - g_object_unref(G_OBJECT(format)); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* * -* Description : Indique la position courante du curseur. * -* * -* Retour : Emplacement courant du curseur ou NULL si aucun. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const vmpa2t *gtk_graph_view_get_caret_location(const GtkGraphView *view) -{ - return NULL; /* FIXME */ - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* addr = adresse à présenter à l'écran. * -* x = position horizontale au sein du composant. [OUT] * -* y = position verticale au sein du composant. [OUT] * -* tweak = adaptation finale à effectuer. * -* * -* Description : Indique la position d'affichage d'une adresse donnée. * -* * -* Retour : true si l'adresse fait partie du composant, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, const vmpa2t *addr, gint *x, gint *y, ScrollPositionTweak tweak) -{ - /* TODO */ - - return false; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* x = abscisse proposée pour le nouvel emplacement. * -* y = ordonnée proposée pour le nouvel emplacement. * -* * -* Description : Déplace le curseur à un emplacement défini. * -* * -* Retour : true si un traitement a été effectué, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gtk_graph_view_move_caret_to(GtkGraphView *view, gint x, gint y) -{ - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - GtkDisplayPanel *panel; /* Autre vision d'enfance */ - gint sub_x; /* Abscisse relative à l'enfant*/ - gint sub_y; /* Ordonnée relative à l'enfant*/ - - result = false; - - for (i = 0; i < view->children_count; i++) - { - if (x < view->allocs[i].x || x >= (view->allocs[i].x + view->allocs[i].width)) continue; - if (y < view->allocs[i].y || y >= (view->allocs[i].y + view->allocs[i].height)) continue; - - panel = GTK_DISPLAY_PANEL(view->children[i]); - - sub_x = x - view->allocs[i].x; - sub_y = y - view->allocs[i].y; - - result = GTK_DISPLAY_PANEL_GET_CLASS(panel)->move_caret_to(panel, sub_x, sub_y); - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à manipuler. * -* cairo = assistant pour la création de rendus. * -* area = taille de la surface réduite à disposition. * -* scale = échelle vis à vis de la taille réelle. * -* * -* Description : Place en cache un rendu destiné à l'aperçu graphique rapide. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_cache_glance(GtkGraphView *view, cairo_t *cairo, const GtkAllocation *area, double scale) -{ - size_t i; /* Boucle de parcours */ - GtkAllocation sub_area; /* Emplacement réservé */ - - for (i = 0; i < view->children_count; i++) - { - sub_area.x = view->allocs[i].x * scale; - sub_area.y = view->allocs[i].y * scale; - sub_area.width = view->allocs[i].width * scale + 1; - sub_area.height = view->allocs[i].height * scale + 1; - - gtk_display_panel_cache_glance(GTK_DISPLAY_PANEL(view->children[i]), cairo, &sub_area, scale); - - } - - cairo_scale(cairo, scale, scale); - - /* - if (view->layout != NULL) - g_graph_layout_draw(view->layout, cairo, false); - */ - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée un nouveau composant pour l'affichage en graphique. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -GtkWidget *gtk_graph_view_new(void) -{ - return g_object_new(GTK_TYPE_GRAPH_VIEW, NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* widget = composant GTK à insérer. * -* x = abscisse du point d'insertion. * -* y = ordonnée du point d'insertion. * -* * -* Description : Place une vue sous forme de bloc dans le graphique. * -* * -* Retour : Plutôt que de redéfinir *toutes* les méthodes de * -* GtkContainer, on étend ! * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_graph_view_put(GtkGraphView *view, GtkWidget *widget, const GtkAllocation *alloc) -{ - size_t i; /* Boucle de parcours */ - GtkWidget *parent; /* Parent en cas de réajustemt.*/ - - /* - for (i = 0; i < view->children_count; i++) - if (GTK_WIDGET(view->children[i]) == widget) - { - view->allocs[i] = *alloc; - break; - } - - parent = gtk_widget_get_parent(widget); - - if (parent != NULL) - { - g_object_ref(G_OBJECT(widget)); - gtk_container_remove(GTK_CONTAINER(parent), widget); - } - */ - - gtk_fixed_put(GTK_FIXED(view->support), widget, alloc->x, alloc->y); - - /* - if (parent != NULL) - g_object_unref(G_OBJECT(widget)); - */ - -} - - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* edge = lien entre noeuds à conserver. * -* * -* Description : Intègre un lien entre blocs graphiques dans l'afficheur. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_graph_view_add_edge(GtkGraphView *view, GGraphEdge *edge) -{ - view->edges = (GGraphEdge **)realloc(view->edges, - ++view->edges_count * sizeof(GGraphEdge *)); - - view->edges[view->edges_count - 1] = edge; - -} - - -/****************************************************************************** -* * -* Paramètres : view = instance GTK à réinitialiser. * -* * -* Description : Supprime tout contenu de l'afficheur de code en graphique. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_reset(GtkGraphView *view) -{ - size_t i; /* Boucle de parcours */ - - - void detach_all_blocks(GtkWidget *widget, GtkContainer *container) - { - - - - gtk_container_remove(container, widget); - - - } - - - gtk_container_foreach(GTK_CONTAINER(view->support), (GtkCallback)detach_all_blocks, view->support); - - - if (view->cluster != NULL) - { - g_object_unref(G_OBJECT(view->cluster)); - view->cluster = NULL; - } - - for (i = 0; i < view->edges_count; i++) - g_object_unref(G_OBJECT(view->edges[i])); - - if (view->edges_count > 0) - { - free(view->edges); - view->edges = NULL; - - view->edges_count = 0; - - } - - - /* - for (i = 0; i < view->links_count; i++) - gtk_object_destroy(GTK_OBJECT(view->links[i])); - - if (view->links_count > 0) - { - free(view->links); - view->links = NULL; - - view->links_count = 0; - - } - */ - - if (view->highlighted) - exit_segment_content_list(view->highlighted); - - for (i = 0; i < view->children_count; i++) - { - g_signal_handlers_disconnect_by_func(view->children[i], gtk_graph_view_reach_caret_limit, view); - gtk_widget_destroy(GTK_WIDGET(view->children[i])); - } - - if (view->children_count > 0) - { - free(view->children); - view->children = NULL; - free(view->allocs); - view->allocs = NULL; - - view->children_count = 0; - - } - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant d'affichage GTK à mettre à jour. * -* routine = routine à présenter via ledit composant. * -* * -* Description : Définit la liste complète des éléments du futur graphique. * -* * -* Retour : Liste d'éléments du graphique à placer. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GtkBufferView **gtk_graph_view_load_nodes(GtkGraphView *view, GLoadedBinary *binary, const GBinRoutine *routine) -{ - GtkBufferView **result; /* Liste à retourner */ - GCodeBuffer *buffer; /* Tampon brut à découper */ - size_t *count; /* Nombre d'éléments créés. */ - GInstrBlock *main_block; /* Premier bloc rattaché */ - GInstrBlock **blocks; /* Liste des blocs basiques */ - size_t i; /* Boucle de parcours */ - vmpa2t first; /* Début d'un groupe de lignes */ - vmpa2t last; /* Fin d'un groupe de lignes */ - GBufferView *subview; /* Partie affichée du tampon */ - - buffer = g_loaded_binary_get_disassembled_buffer(binary); - - count = &view->children_count; - - main_block = g_binary_routine_get_basic_blocks(routine); - - blocks = NULL; - *count = 0; - g_instr_block_list_all_blocks(main_block, &blocks, count); - - result = (GtkBufferView **)calloc(*count, sizeof(GtkBufferView *)); - - for (i = 0; i < *count; i++) - { - result[i] = GTK_BUFFER_VIEW(gtk_block_view_new()); - g_signal_connect(result[i], "reach-limit", G_CALLBACK(gtk_graph_view_reach_caret_limit), view); - g_signal_connect(result[i], "highlight-changed", G_CALLBACK(gtk_graph_view_changed_highlights), view); - - gtk_widget_show(GTK_WIDGET(result[i])); - gtk_display_panel_attach_binary(GTK_DISPLAY_PANEL(result[i]), binary, BVW_GRAPH); - - gtk_display_panel_show_border(GTK_DISPLAY_PANEL(result[i]), true); - - g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blocks[i]), &first, &last); - - subview = g_buffer_view_new(buffer, view->highlighted); - g_buffer_view_restrict(subview, &first, &last); - gtk_buffer_view_attach_buffer(result[i], subview); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : node = composant d'affichage GTK impliqué dans la procédure. * -* view = support graphique de tous les noeuds. * -* * -* Description : Notifie un changement de surbrillance au sein d'un noeud. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_changed_highlights(GtkBlockView *node, GtkGraphView *view) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < view->children_count; i++) - { - if (view->children[i] == GTK_BUFFER_VIEW(node)) - continue; - - gtk_widget_queue_draw(GTK_WIDGET(view->children[i])); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : node = composant d'affichage GTK impliqué dans la procédure. * -* dir = direction du déplacement souhaité et impossible. * -* view = support graphique de tous les noeuds. * -* * -* Description : Notifie une incapacité de déplacement au sein d'un noeud. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_graph_view_reach_caret_limit(GtkBufferView *node, GdkScrollDirection dir, GtkGraphView *view) -{ - GBufferView *bview; /* Vue d'un tampon global */ - vmpa2t first; /* Début d'un groupe de lignes */ - vmpa2t last; /* Fin d'un groupe de lignes */ - const mrange_t *range; /* Couverture courante */ - GArchProcessor *proc; /* Processeur pour instructions*/ - vmpa2t iaddr; /* Adresse du prochain saut */ - instr_iter_t *iter; /* Boucle de parcours */ - GArchInstruction *instr; /* Instruction à venir visiter */ -#ifndef NDEBUG - bool is_return; /* Est-ce une instruc. finale ?*/ -#endif - size_t i; /* Boucle de parcours */ - bool updated; /* Besoin d'une mise à jour ? */ - - /* Détermination de l'instruction à cibler */ - - bview = gtk_buffer_view_get_buffer(node); - g_buffer_view_get_restrictions(bview, &first, &last); - - range = g_binary_routine_get_range(view->routine); - - proc = g_loaded_binary_get_processor(GTK_DISPLAY_PANEL(view)->binary); - - init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); - -#ifndef NDEBUG - is_return = false; -#endif - - switch (dir) - { - case GDK_SCROLL_LEFT: - case GDK_SCROLL_UP: - - if (cmp_vmpa(get_mrange_addr(range), &first) != 0) - { - iter = g_arch_processor_get_iter_from_address(proc, &first); - - if (iter != NULL) - { - instr = get_instruction_iterator_prev(iter); - - if (instr != NULL) - { - /* TODO : boucler si !HAS_CODE */ - - if (mrange_contains_addr(range, &iaddr)) - copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr))); - - g_object_unref(G_OBJECT(instr)); - - } - - delete_instruction_iterator(iter); - - } - - } - - break; - - case GDK_SCROLL_RIGHT: - case GDK_SCROLL_DOWN: - - iter = g_arch_processor_get_iter_from_address(proc, &last); - - if (iter != NULL) - { -#ifndef NDEBUG - instr = get_instruction_iterator_current(iter); - if (instr != NULL) - { - is_return = (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT); - g_object_unref(G_OBJECT(instr)); - } -#endif - - instr = get_instruction_iterator_next(iter); - - if (instr != NULL) - { - /* TODO : boucler si !HAS_CODE */ - - copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr))); - - if (!mrange_contains_addr(range, &iaddr)) - init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); - - g_object_unref(G_OBJECT(instr)); - - } - - delete_instruction_iterator(iter); - - } - - break; - - case GDK_SCROLL_SMOOTH: - assert(0); /* Argument jamais généré */ - break; - - } - - g_object_unref(G_OBJECT(proc)); - - /* Recherche du bloc parent */ - - /* FIXME : valid ! */ - if (iaddr.physical == VMPA_NO_PHYSICAL && iaddr.virtual == VMPA_NO_VIRTUAL) - return; - - for (i = 0; i < view->children_count; i++) - { - bview = gtk_buffer_view_get_buffer(view->children[i]); - g_buffer_view_get_restrictions(bview, &first, &last); - - if (cmp_vmpa(&first, &iaddr) <= 0 && cmp_vmpa(&iaddr, &last) <= 0) - { - assert(node != view->children[i]); - break; - } - - } - - assert(i < view->children_count || is_return); - - /* Affichage du nouveau curseur */ - - /** - * Il se peut qu'aucune adresse suivante ne soit disponible : c'est typiquement - * le cas sous ARM, avec les valeurs brutes référencées dans le code. Ces valeurs - * sont incluses dans la surface couverte par la routine concernée, mais ne sont - * pas intégrées dans les blocs basiques associés. - */ - - if (i == view->children_count) - return; - - gtk_widget_grab_focus(GTK_WIDGET(view->children[i])); - - switch (dir) - { - case GDK_SCROLL_LEFT: - updated = gtk_buffer_view_move_caret_to(view->children[i], false, NULL); - break; - - case GDK_SCROLL_UP: - break; - - case GDK_SCROLL_RIGHT: - updated = gtk_buffer_view_move_caret_to(view->children[i], true, NULL); - break; - - case GDK_SCROLL_DOWN: - break; - - case GDK_SCROLL_SMOOTH: - assert(0); /* Argument jamais généré */ - break; - - } - - /* TODO : scrolling... */ - -} |