diff options
Diffstat (limited to 'src/gui/panels/bintree.c')
-rw-r--r-- | src/gui/panels/bintree.c | 922 |
1 files changed, 741 insertions, 181 deletions
diff --git a/src/gui/panels/bintree.c b/src/gui/panels/bintree.c index c2caef7..642a71c 100644 --- a/src/gui/panels/bintree.c +++ b/src/gui/panels/bintree.c @@ -25,6 +25,7 @@ #include "bintree.h" +#include <assert.h> #include <malloc.h> #include <regex.h> @@ -33,11 +34,15 @@ #include "panel-int.h" +#include "updating-int.h" #include "../core/global.h" +#include "../../core/queue.h" #include "../../gtkext/tmgt.h" +/* -------------------------- PARTIE PRINCIPALE DU PANNEAU -------------------------- */ + /* Origine de la dernière ouverture/fermeture reproductible */ typedef enum _UserActionType { @@ -47,18 +52,16 @@ typedef enum _UserActionType } UserActionType; - /* Panneau de présentation des portions (instance) */ struct _GBintreePanel { GPanelItem parent; /* A laisser en premier */ GLoadedBinary *binary; /* Binaire représenté */ - regex_t *filter; /* Filtre appliqué ou NULL */ UserActionType last; /* Dernière action */ - GtkTreeIter *top; /* Transfert de racine */ + size_t count; /* Quantité de portions utiles */ }; @@ -73,6 +76,8 @@ struct _GBintreePanelClass /* Colonnes de la liste des messages */ typedef enum _BinaryTreeColumn { + BTC_PORTION, /* Elément interne représenté */ + BTC_ICON, /* Image de représentation */ BTC_CAPTION, /* Désignation de l'élément */ BTC_START, /* Position de départ */ @@ -80,45 +85,122 @@ typedef enum _BinaryTreeColumn BTC_RIGHTS, /* Droits d'accès */ BTC_MATCHED, /* Correspondance établie ? */ - BTC_PORTION /* Elément interne représenté */ + BTC_MATCH_POINTS, /* Nombre de demandeurs */ + + BTC_COUNT /* Nombre de colonnes */ } BinaryTreeColumn; +/* Données utiles à la mise à jour */ +typedef struct _bintree_update_data bintree_update_data; + + /* Initialise la classe des panneaux d'affichage des portions. */ static void g_bintree_panel_class_init(GBintreePanelClass *); /* Initialise une instance de panneau d'affichage des portions. */ static void g_bintree_panel_init(GBintreePanel *); +/* Procède à l'initialisation de l'interface de mise à jour. */ +static void g_bintree_panel_updatable_interface_init(GUpdatablePanelInterface *); + /* Supprime toutes les références externes. */ static void g_bintree_panel_dispose(GBintreePanel *); /* Procède à la libération totale de la mémoire. */ static void g_bintree_panel_finalize(GBintreePanel *); +/* Modifie la profondeur affichée des portions présentes. */ +static void on_depth_spin_value_changed(GtkSpinButton *, const GBintreePanel *); + +/* Réagit au changement de sélection des portions. */ +static void on_bintree_selection_changed(GtkTreeSelection *, gpointer); + +/* Réagit à un changement d'affichage principal de contenu. */ +static void change_bintree_panel_current_binary(GBintreePanel *, GLoadedBinary *); + + + +/* -------------------------- AFFICHAGE SOUS FORME D'ARBRE -------------------------- */ + + /* Parcourt un ensemble de portions. */ -static bool populate_tree_with_portion(GBinPortion *, GBinPortion *, BinaryPortionVisit, GBintreePanel *); +static bool populate_tree_with_portion(GBinPortion *, GBinPortion *, BinaryPortionVisit, bintree_update_data *); /* Réagit à un changement d'affichage principal de contenu. */ -static void update_panel_with_binary_portions(GBintreePanel *, GLoadedBinary *); +static void reload_portions_for_new_tree_view(const GBintreePanel *, GtkStatusStack *, activity_id_t, bintree_update_data *); + +/* Met en surbrillance les éléments recherchés dans les noms. */ +static void update_bintree_column_in_tree_view(GtkTreeStore *, GtkTreeIter *, GBinPortion *, gint, const regmatch_t *); + + + +/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */ -/* Modifie la profondeur affichée des portions présentes. */ -static void on_depth_spin_value_changed(GtkSpinButton *, GtkTreeView *); /* Prend note du changement de filtre sur les portions. */ static void on_search_entry_changed(GtkSearchEntry *, GBintreePanel *); -/* Parcourt un arbre en place et retire les branches filtrées. */ -static void apply_filter_on_portions(GtkTreeStore *); +/* Détermine si un noeud de l'arborescence doit être filtré. */ +static bool update_bintree_node(const bintree_update_data *, GtkTreeStore *, GtkTreeIter *, GBinPortion *); + +/* Exécute un nouveau filtrage des symboles affichés. */ +static void do_filtering_on_portions(const GBintreePanel *, GtkStatusStack *, activity_id_t, bintree_update_data *); -/* Réagit au changement de sélection des portions. */ -static void on_bintree_selection_changed(GtkTreeSelection *, gpointer); +/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */ + + +/* Données utiles à la mise à jour */ +struct _bintree_update_data +{ + size_t count; /* Qté d'inscriptions réalisées*/ + + regex_t *filter; /* Filtre appliqué ou NULL */ + + char **expanded; /* Chemins des noeuds ouverts */ + size_t ecount; /* Nombre de ces chemins */ + size_t eallocated; /* Espace alloué effectivement */ + + const GBintreePanel *panel; /* Transfert de panneau */ + GtkTreeIter *top; /* Transfert de racine */ + +}; + + +#define EXPAND_ALLOC_RANGE 10 + + +/* Détermine si une valeur de portion doit être filtrée ou non. */ +static bool is_bintree_column_matching(const bintree_update_data *, GBinPortion *, gint, regmatch_t *); + +/* Prépare une opération de mise à jour de panneau. */ +static const char *g_bintree_panel_setup(const GBintreePanel *, unsigned int, size_t *, bintree_update_data **); + +/* Bascule l'affichage d'un panneau avant mise à jour. */ +static void g_bintree_panel_introduce(const GBintreePanel *, unsigned int, bintree_update_data *); + +/* Réalise une opération de mise à jour de panneau. */ +static void g_bintree_panel_process(const GBintreePanel *, unsigned int, GtkStatusStack *, activity_id_t, bintree_update_data *); + +/* Bascule l'affichage d'un panneau après mise à jour. */ +static void g_bintree_panel_conclude(GBintreePanel *, unsigned int, bintree_update_data *); + +/* Supprime les données dynamiques utilisées à la mise à jour. */ +static void g_bintree_panel_clean_data(GUpdatablePanel *, unsigned int, bintree_update_data *); + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTIE PRINCIPALE DU PANNEAU */ +/* ---------------------------------------------------------------------------------- */ + /* Indique le type défini pour un panneau d'affichage des portions. */ -G_DEFINE_TYPE(GBintreePanel, g_bintree_panel, G_TYPE_PANEL_ITEM); +G_DEFINE_TYPE_WITH_CODE(GBintreePanel, g_bintree_panel, G_TYPE_PANEL_ITEM, + G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_bintree_panel_updatable_interface_init)); /****************************************************************************** @@ -137,6 +219,7 @@ static void g_bintree_panel_class_init(GBintreePanelClass *klass) { GObjectClass *object; /* Autre version de la classe */ GEditorItemClass *editem; /* Encore une autre vision... */ + GPanelItemClass *panel; /* Version parente de la classe*/ object = G_OBJECT_CLASS(klass); @@ -145,7 +228,11 @@ static void g_bintree_panel_class_init(GBintreePanelClass *klass) editem = G_EDITOR_ITEM_CLASS(klass); - editem->update_binary = (update_item_binary_fc)update_panel_with_binary_portions; + editem->update_binary = (update_item_binary_fc)change_bintree_panel_current_binary; + + panel = G_PANEL_ITEM_CLASS(klass); + + panel->gid = setup_tiny_global_work_group(1); } @@ -187,7 +274,6 @@ static void g_bintree_panel_init(GBintreePanel *panel) /* Compléments propres */ panel->binary = NULL; - panel->filter = NULL; panel->last = UAT_EXPAND; @@ -251,6 +337,30 @@ static void g_bintree_panel_init(GBintreePanel *panel) /****************************************************************************** * * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de mise à jour. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_bintree_panel_updatable_interface_init(GUpdatablePanelInterface *iface) +{ + iface->setup = (setup_updatable_cb)g_bintree_panel_setup; + iface->get_group = (get_updatable_group_cb)g_panel_item_get_group; + iface->introduce = (introduce_updatable_cb)g_bintree_panel_introduce; + iface->process = (process_updatable_cb)g_bintree_panel_process; + iface->conclude = (conclude_updatable_cb)g_bintree_panel_conclude; + iface->clean = (clean_updatable_data_cb)g_bintree_panel_clean_data; + +} + + +/****************************************************************************** +* * * Paramètres : panel = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * @@ -285,12 +395,6 @@ static void g_bintree_panel_dispose(GBintreePanel *panel) static void g_bintree_panel_finalize(GBintreePanel *panel) { - if (panel->filter != NULL) - { - regfree(panel->filter); - free(panel->filter); - } - G_OBJECT_CLASS(g_bintree_panel_parent_class)->finalize(G_OBJECT(panel)); } @@ -321,122 +425,216 @@ GPanelItem *g_bintree_panel_new(void) /****************************************************************************** * * -* Paramètres : panel = portion de binaire à traiter. * -* parent = portion parent de la portion visitée. * -* visit = indication sur le sens de la visite. * -* panel = lien vers toutes les autres informations utiles. * +* Paramètres : button = bouton de réglage de l'affichage. * +* treeview = arborescence dont l'affichage est à moduler. * * * -* Description : Parcourt un ensemble de portions. * +* Description : Modifie la profondeur affichée des portions présentes. * * * -* Retour : true pour continuer la visite. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, GBintreePanel *panel) +static void on_depth_spin_value_changed(GtkSpinButton *button, const GBintreePanel *panel) { - const char *desc; /* Description d'origine */ - bool fmatched; /* Correspondance rencontrée ? */ - regmatch_t match; /* Position d'un filtre */ - char *node_caption; /* Etiquette de nouveau noeud */ - const mrange_t *range; /* Espace de portion à traiter */ - VMPA_BUFFER(offset); /* Décalage physique */ - char *node_start; /* Position pour nouveau noeud */ - vmpa2t end; /* Zone de construction temp. */ - char *node_end; /* Bordure pour nouveau noeud */ - PortionAccessRights rights; /* Droits d'accès à analyser */ - char hrights[4]; /* Version humainement lisible */ - char *node_rights; /* Droits pour nouveau noeud */ - cairo_surface_t *icon; /* Miniature de décoration */ + gint max_depth; /* Profondeur maximale */ GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeView *treeview; /* Arborescence constituée */ GtkTreeStore *store; /* Modèle de gestion */ - GtkTreeIter iter; /* Point d'insertion */ - GtkTreeIter *save; /* Sauvegarde d'une position */ - if (parent == NULL) - return true; + max_depth = gtk_spin_button_get_value_as_int(button); - /* Insertion de la portion courante */ + gboolean apply_max_depth(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused) + { + gint depth; /* Profondeur du point courant */ - if (visit == BPV_ENTER || visit == BPV_SHOW) + depth = gtk_tree_store_iter_depth(GTK_TREE_STORE(model), iter); + + if (depth < max_depth) + gtk_tree_view_expand_to_path(treeview, path); + + return FALSE; + + } + + builder = G_PANEL_ITEM(panel)->builder; + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + + gtk_tree_view_collapse_all(treeview); + + store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store")); + + gtk_tree_model_foreach(GTK_TREE_MODEL(store), (GtkTreeModelForeachFunc)apply_max_depth, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : selection = sélection modifiée. * +* unused = adresse non utilisée ici. * +* * +* Description : Réagit au changement de sélection des portions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_bintree_selection_changed(GtkTreeSelection *selection, gpointer unused) +{ + GtkTreeIter iter; /* Point de sélection */ + GtkTreeModel *model; /* Modèle de gestion */ + GBinPortion *portion; /* Portion à traiter */ + const mrange_t *range; /* Couverture dudit symbole */ + GLoadedPanel *panel; /* Afficheur effectif de code */ + + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - /* Etiquette */ + gtk_tree_model_get(model, &iter, BTC_PORTION, &portion, -1); + + if (portion != NULL) + { + range = g_binary_portion_get_range(portion); + + panel = get_current_view(); + + if (GTK_IS_DISPLAY_PANEL(panel)) + gtk_display_panel_request_move(GTK_DISPLAY_PANEL(panel), get_mrange_addr(range)); + + g_object_unref(G_OBJECT(panel)); + + g_object_unref(G_OBJECT(portion)); + + } + + } + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau à mettre à jour. * +* binary = nouvelle instance de binaire analysé. * +* * +* Description : Réagit à un changement d'affichage principal de contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void change_bintree_panel_current_binary(GBintreePanel *panel, GLoadedBinary *binary) +{ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeStore *store; /* Modèle de gestion */ + + /* Basculement du binaire utilisé */ + + if (panel->binary != NULL) + g_object_unref(G_OBJECT(panel->binary)); + + panel->binary = binary; + + if (panel->binary != NULL) + g_object_ref(G_OBJECT(panel->binary)); - desc = g_binary_portion_get_desc(portion); + /* Réinitialisation */ - fmatched = is_content_matching(panel->filter, desc, &match); - node_caption = build_highlighted_name(desc, &match, 0); + builder = G_PANEL_ITEM(panel)->builder; - /* Point de départ */ + store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store")); - range = g_binary_portion_get_range(portion); + gtk_tree_store_clear(store); - vmpa2_phys_to_string(get_mrange_addr(range), MDS_UNDEFINED, offset, NULL); + /* Si le panneau actif représente un binaire, actualisation de l'affichage */ - fmatched |= is_content_matching(panel->filter, offset, &match); - node_start = build_highlighted_name(offset, &match, 0); + if (binary != NULL) + run_panel_update(G_UPDATABLE_PANEL(panel), PUI_0); - /* Point d'arrivée */ +} - compute_mrange_end_addr(range, &end); - vmpa2_phys_to_string(&end, MDS_UNDEFINED, offset, NULL); - fmatched |= is_content_matching(panel->filter, offset, &match); - node_end = build_highlighted_name(offset, &match, 0); +/* ---------------------------------------------------------------------------------- */ +/* AFFICHAGE SOUS FORME D'ARBRE */ +/* ---------------------------------------------------------------------------------- */ - /* Droits nominaux */ - rights = g_binary_portion_get_rights(portion); +/****************************************************************************** +* * +* Paramètres : panel = portion de binaire à traiter. * +* parent = portion parent de la portion visitée. * +* visit = indication sur le sens de la visite. * +* panel = lien vers toutes les autres informations utiles. * +* * +* Description : Parcourt un ensemble de portions. * +* * +* Retour : true pour continuer la visite. * +* * +* Remarques : - * +* * +******************************************************************************/ - hrights[0] = (rights & PAC_READ ? 'r' : '-'); - hrights[1] = (rights & PAC_WRITE ? 'w' : '-'); - hrights[2] = (rights & PAC_EXEC ? 'x' : '-'); - hrights[3] = '\0'; +static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, bintree_update_data *data) +{ + const GBintreePanel *panel; /* Panneau à compléter */ + cairo_surface_t *icon; /* Miniature de décoration */ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeStore *store; /* Modèle de gestion */ + GtkTreeIter iter; /* Point d'insertion */ + GtkTreeIter *save; /* Sauvegarde d'une position */ - fmatched |= is_content_matching(panel->filter, hrights, &match); - node_rights = build_highlighted_name(hrights, &match, 0); + if (parent == NULL) + return true; + + panel = data->panel; - /* Intégration */ + /* Insertion de la portion courante */ + if (visit == BPV_ENTER || visit == BPV_SHOW) + { icon = NULL; builder = G_PANEL_ITEM(panel)->builder; store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store")); - gtk_tree_store_append(store, &iter, panel->top); + gtk_tree_store_append(store, &iter, data->top); gtk_tree_store_set(store, &iter, - BTC_ICON, icon, - BTC_CAPTION, node_caption, - BTC_START, node_start, - BTC_END, node_end, - BTC_RIGHTS, node_rights, - BTC_MATCHED, fmatched, BTC_PORTION, portion, + BTC_ICON, icon, + BTC_CAPTION, NULL, + BTC_START, NULL, + BTC_END, NULL, + BTC_RIGHTS, NULL, + BTC_MATCHED, false, + BTC_MATCH_POINTS, 0, -1); - free(node_caption); - free(node_start); - free(node_end); - free(node_rights); - if (icon != NULL) cairo_surface_destroy(icon); + update_bintree_node(data, store, &iter, portion); + + } /* Définition de la hiérarchie */ if (visit == BPV_ENTER) { - save = gtk_tree_iter_copy(panel->top); + save = gtk_tree_iter_copy(data->top); g_object_set_data_full(G_OBJECT(portion), "_save", save, (GDestroyNotify)gtk_tree_iter_free); - *panel->top = iter; + *data->top = iter; } @@ -444,7 +642,7 @@ static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent { save = g_object_get_data(G_OBJECT(portion), "_save"); - *panel->top = *save; + *data->top = *save; g_object_set_data(G_OBJECT(portion), "_save", NULL); @@ -458,7 +656,9 @@ static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent /****************************************************************************** * * * Paramètres : panel = panneau à mettre à jour. * -* binary = nouvelle instance de binaire analysé. * +* status = barre de statut à tenir informée. * +* id = identifiant pour le suivi de la progression. * +* data = données complémentaire à manipuler. * * * * Description : Réagit à un changement d'affichage principal de contenu. * * * @@ -468,7 +668,7 @@ static bool populate_tree_with_portion(GBinPortion *portion, GBinPortion *parent * * ******************************************************************************/ -static void update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinary *binary) +static void reload_portions_for_new_tree_view(const GBintreePanel *panel, GtkStatusStack *status, activity_id_t id, bintree_update_data *data) { GtkBuilder *builder; /* Constructeur utilisé */ GtkTreeStore *store; /* Modèle de gestion */ @@ -479,44 +679,31 @@ static void update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinar GtkSpinButton *depth_spin; /* Bouton de variation */ GtkTreeView *treeview; /* Arborescence constituée */ - /* Réinitialisation */ - - if (panel->binary != NULL) - g_object_unref(G_OBJECT(panel->binary)); - - panel->binary = binary; - builder = G_PANEL_ITEM(panel)->builder; store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store")); - gtk_tree_store_clear(store); + /* Constitution de l'arborescence */ - /* Chargement */ + format = g_loaded_binary_get_format(panel->binary); - if (binary != NULL) - { - g_object_ref(G_OBJECT(binary)); - - format = g_loaded_binary_get_format(binary); - - portions = g_exe_format_get_portions(format); + portions = g_exe_format_get_portions(format); - gtk_tree_store_append(store, &top, NULL); + gtk_tree_store_append(store, &top, NULL); - gtk_tree_store_set(store, &top, - BTC_ICON, NULL, - BTC_CAPTION, g_loaded_binary_get_name(binary, false), - -1); + gtk_tree_store_set(store, &top, + BTC_ICON, NULL, + BTC_CAPTION, g_loaded_binary_get_name(panel->binary, false), + -1); - panel->top = ⊤ - g_binary_portion_visit(portions, (visit_portion_fc)populate_tree_with_portion, panel); + data->panel = panel; + data->top = ⊤ - g_object_unref(G_OBJECT(portions)); + g_binary_portion_visit(portions, (visit_portion_fc)populate_tree_with_portion, data); - g_object_unref(G_OBJECT(format)); + g_object_unref(G_OBJECT(portions)); - } + g_object_unref(G_OBJECT(format)); /* Détermination de la profondeur maximale */ @@ -556,23 +743,23 @@ static void update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinar break; case UAT_DEPTH: - on_depth_spin_value_changed(depth_spin, treeview); + on_depth_spin_value_changed(depth_spin, panel); break; } - if (panel->filter != NULL) - apply_filter_on_portions(store); - } /****************************************************************************** * * -* Paramètres : button = bouton de réglage de l'affichage. * -* treeview = arborescence dont l'affichage est à moduler. * +* Paramètres : store = gestionnaire de l'ensemble des données. * +* iter = localisation des données à analyser. * +* portion = portion de binaire concernée par l'analyse. * +* column = colonne visée par l'analyse. * +* match = portion de texte à mettre en évidence. * * * -* Description : Modifie la profondeur affichée des portions présentes. * +* Description : Met en surbrillance les éléments recherchés dans les noms. * * * * Retour : - * * * @@ -580,35 +767,61 @@ static void update_panel_with_binary_portions(GBintreePanel *panel, GLoadedBinar * * ******************************************************************************/ -static void on_depth_spin_value_changed(GtkSpinButton *button, GtkTreeView *treeview) +static void update_bintree_column_in_tree_view(GtkTreeStore *store, GtkTreeIter *iter, GBinPortion *portion, gint column, const regmatch_t *match) { - gint max_depth; /* Profondeur maximale */ - GtkTreeModel *model; /* Modèle de gestion */ - - max_depth = gtk_spin_button_get_value_as_int(button); + const char *content; /* Contenu brut d'origine */ + const mrange_t *range; /* Espace de portion à traiter */ + VMPA_BUFFER(offset); /* Localisation quelconque */ + vmpa2t end; /* Zone de construction temp. */ + PortionAccessRights rights; /* Droits d'accès à analyser */ + char hrights[4]; /* Version humainement lisible */ + char *value; /* Etiquette mise en relief */ - gboolean apply_max_depth(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused) + switch (column) { - gint depth; /* Profondeur du point courant */ + case BTC_CAPTION: + content = g_binary_portion_get_desc(portion); + break; - depth = gtk_tree_store_iter_depth(GTK_TREE_STORE(model), iter); + case BTC_START: + range = g_binary_portion_get_range(portion); + vmpa2_phys_to_string(get_mrange_addr(range), MDS_UNDEFINED, offset, NULL); + content = offset; + break; - if (depth < max_depth) - gtk_tree_view_expand_to_path(treeview, path); + case BTC_END: + range = g_binary_portion_get_range(portion); + compute_mrange_end_addr(range, &end); + vmpa2_phys_to_string(&end, MDS_UNDEFINED, offset, NULL); + content = offset; + break; - return FALSE; + case BTC_RIGHTS: + rights = g_binary_portion_get_rights(portion); + hrights[0] = (rights & PAC_READ ? 'r' : '-'); + hrights[1] = (rights & PAC_WRITE ? 'w' : '-'); + hrights[2] = (rights & PAC_EXEC ? 'x' : '-'); + hrights[3] = '\0'; + content = hrights; + break; } - gtk_tree_view_collapse_all(treeview); + value = build_highlighted_name(content, match, 0); - model = gtk_tree_view_get_model(treeview); + gtk_tree_store_set(store, iter, column, value, -1); - gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc)apply_max_depth, NULL); + free(value); } + +/* ---------------------------------------------------------------------------------- */ +/* FILTRAGE DES SYMBOLES PRESENTS */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : entry = zone de texte avec un nouveau filtre d'affichage. * @@ -624,71 +837,74 @@ static void on_depth_spin_value_changed(GtkSpinButton *button, GtkTreeView *tree static void on_search_entry_changed(GtkSearchEntry *entry, GBintreePanel *panel) { - update_regex_on_search_entry_changed(entry, &panel->filter); + update_regex_on_search_entry_changed(entry, &G_PANEL_ITEM(panel)->filter); - if (panel->binary != NULL) - { - g_object_ref(G_OBJECT(panel->binary)); - update_panel_with_binary_portions(panel, panel->binary); - g_object_unref(G_OBJECT(panel->binary)); - } + run_panel_update(G_UPDATABLE_PANEL(panel), PUI_1); } /****************************************************************************** * * -* Paramètres : store = gestionnaire de contenu d'une arborescence donnée. * +* Paramètres : data = données complémentaire à manipuler. * +* store = gestionnaire de l'ensemble des données. * +* iter = localisation des données à analyser. * +* portion = portion binaire présente à la position courante. * * * -* Description : Parcourt un arbre en place et retire les branches filtrées. * +* Description : Détermine si un noeud de l'arborescence doit être filtré. * * * -* Retour : - * +* Retour : Bilan du filtrage. * * * * Remarques : - * * * ******************************************************************************/ -static void apply_filter_on_portions(GtkTreeStore *store) +static bool update_bintree_node(const bintree_update_data *data, GtkTreeStore *store, GtkTreeIter *iter, GBinPortion *portion) { - GtkTreeIter root; /* Racine de l'arboresence */ + bool result; /* Bilan à retourner */ + regmatch_t match; /* Récupération des trouvailles*/ + bool caption_matched; /* Correspondance de sélection */ + bool start_matched; /* Correspondance de sélection */ + bool end_matched; /* Correspondance de sélection */ + bool rights_matched; /* Correspondance de sélection */ - void check_portion_iter(GtkTreeIter *iter) - { - GtkTreeModel *model; /* Version alternative */ - gint children_count; /* Nombre d'enfants présents */ - gint i; /* Boucle de parcours */ - GtkTreeIter child; /* Pointeur vers la descendance*/ - gboolean fmatched; /* Correspondance immédiate ? */ + caption_matched = is_bintree_column_matching(data, portion, BTC_CAPTION, &match); - model = GTK_TREE_MODEL(store); + if (caption_matched) + update_bintree_column_in_tree_view(store, iter, portion, BTC_CAPTION, &match); - children_count = gtk_tree_model_iter_n_children(model, iter); + start_matched = is_bintree_column_matching(data, portion, BTC_START, &match); - for (i = children_count; i > 0; i--) - if (gtk_tree_model_iter_nth_child(model, &child, iter, i - 1)) - check_portion_iter(&child); + if (start_matched) + update_bintree_column_in_tree_view(store, iter, portion, BTC_START, &match); - children_count = gtk_tree_model_iter_n_children(model, iter); + end_matched = is_bintree_column_matching(data, portion, BTC_END, &match); - gtk_tree_model_get(model, iter, BTC_MATCHED, &fmatched, -1); + if (end_matched) + update_bintree_column_in_tree_view(store, iter, portion, BTC_END, &match); - if (!fmatched && children_count == 0) - gtk_tree_store_remove(store, iter); + rights_matched = is_bintree_column_matching(data, portion, BTC_RIGHTS, &match); - } + if (rights_matched) + update_bintree_column_in_tree_view(store, iter, portion, BTC_RIGHTS, &match); - if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &root)) - check_portion_iter(&root); + result = (caption_matched || start_matched || end_matched || rights_matched); + + gtk_tree_store_set(store, iter, BTC_MATCHED, result, -1); + + return result; } /****************************************************************************** * * -* Paramètres : selection = sélection modifiée. * -* unused = adresse non utilisée ici. * +* Paramètres : panel = panneau assurant l'affichage des symboles. * +* status = barre de statut à tenir informée. * +* id = identifiant pour le suivi de la progression. * +* data = données complémentaire à manipuler. * * * -* Description : Réagit au changement de sélection des portions. * +* Description : Exécute un nouveau filtrage des symboles affichés. * * * * Retour : - * * * @@ -696,33 +912,377 @@ static void apply_filter_on_portions(GtkTreeStore *store) * * ******************************************************************************/ -static void on_bintree_selection_changed(GtkTreeSelection *selection, gpointer unused) +static void do_filtering_on_portions(const GBintreePanel *panel, GtkStatusStack *status, activity_id_t id, bintree_update_data *data) { - GtkTreeIter iter; /* Point de sélection */ - GtkTreeModel *model; /* Modèle de gestion */ - GBinPortion *portion; /* Portion à traiter */ - const mrange_t *range; /* Couverture dudit symbole */ - GLoadedPanel *panel; /* Afficheur effectif de code */ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeStore *store; /* Modèle de gestion */ - if (gtk_tree_selection_get_selected(selection, &model, &iter)) + + gboolean filter_portion_panel_iter(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused) { - gtk_tree_model_get(model, &iter, BTC_PORTION, &portion, -1); + GBinPortion *portion; /* Portion à traiter */ + bool matched; /* Correspondance de sélection */ + gboolean shown; /* Visibilité actuelle */ + + gtk_tree_model_get(model, iter, BTC_PORTION, &portion, -1); if (portion != NULL) { - range = g_binary_portion_get_range(portion); + matched = update_bintree_node(data, store, iter, portion); - panel = get_current_view(); + gtk_tree_model_get(model, iter, BTC_MATCHED, &shown, -1); - if (GTK_IS_DISPLAY_PANEL(panel)) - gtk_display_panel_request_move(GTK_DISPLAY_PANEL(panel), get_mrange_addr(range)); + if (!matched) + { + if (shown) + update_node_visibility(store, iter, BTC_MATCHED, false); + } - g_object_unref(G_OBJECT(panel)); + else + { + if (!shown) + update_node_visibility(store, iter, BTC_MATCHED, true); + } g_object_unref(G_OBJECT(portion)); + gtk_status_stack_update_activity_value(status, id, 1); + + } + + return FALSE; + + } + + + builder = G_PANEL_ITEM(panel)->builder; + + store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store")); + + gtk_tree_model_foreach(GTK_TREE_MODEL(store), (GtkTreeModelForeachFunc)filter_portion_panel_iter, NULL); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE MISE A JOUR DE PANNEAU */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : data = données complémentaire à manipuler. * +* portion = portion de binaire concernée par l'analyse. * +* column = colonne visée par l'analyse. * +* match = récupération des trouvailles. [OUT] * +* * +* Description : Détermine si une valeur de portion doit être filtrée ou non. * +* * +* Retour : true si le symbol ne doit pas être affiché, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_bintree_column_matching(const bintree_update_data *data, GBinPortion *portion, gint column, regmatch_t *match) +{ + bool result; /* Bilan à retourner */ + const char *content; /* Contenu à analyser */ + const mrange_t *range; /* Espace de portion à traiter */ + VMPA_BUFFER(offset); /* Localisation quelconque */ + vmpa2t end; /* Zone de construction temp. */ + PortionAccessRights rights; /* Droits d'accès à analyser */ + char hrights[4]; /* Version humainement lisible */ + + switch (column) + { + case BTC_CAPTION: + content = g_binary_portion_get_desc(portion); + break; + + case BTC_START: + range = g_binary_portion_get_range(portion); + vmpa2_phys_to_string(get_mrange_addr(range), MDS_UNDEFINED, offset, NULL); + content = offset; + break; + + case BTC_END: + range = g_binary_portion_get_range(portion); + compute_mrange_end_addr(range, &end); + vmpa2_phys_to_string(&end, MDS_UNDEFINED, offset, NULL); + content = offset; + break; + + case BTC_RIGHTS: + rights = g_binary_portion_get_rights(portion); + hrights[0] = (rights & PAC_READ ? 'r' : '-'); + hrights[1] = (rights & PAC_WRITE ? 'w' : '-'); + hrights[2] = (rights & PAC_EXEC ? 'x' : '-'); + hrights[3] = '\0'; + content = hrights; + break; + + } + + result = is_content_matching(data->filter, content, match); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau ciblé par une mise à jour. * +* uid = identifiant de la phase de traitement. * +* count = nombre d'étapes à prévoir dans le traitement. [OUT] * +* data = données sur lesquelles s'appuyer ensuite. [OUT] * +* * +* Description : Prépare une opération de mise à jour de panneau. * +* * +* Retour : Description du message d'information. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *g_bintree_panel_setup(const GBintreePanel *panel, unsigned int uid, size_t *count, bintree_update_data **data) +{ + const char *result; /* Message à retourner */ + int ret; /* Bilan de mise en place */ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeView *treeview; /* Arborescence graphique */ + + *data = malloc(sizeof(bintree_update_data)); + + switch (uid) + { + case PUI_0: + + *count = 1; + (*data)->count = 0; + + result = _("Loading portions contained in the binary format..."); + + break; + + case PUI_1: + + *count = panel->count; + (*data)->count = panel->count; + + result = _("Filtering portions contained in the binary format..."); + + break; + + default: /* Pour GCC... */ + assert(false); + result = ""; + break; + + } + + if (G_PANEL_ITEM(panel)->filter != NULL) + { + (*data)->filter = (regex_t *)malloc(sizeof(regex_t)); + + ret = regcomp((*data)->filter, G_PANEL_ITEM(panel)->filter, REG_EXTENDED | REG_ICASE); + assert(ret == 0); + + } + + else + (*data)->filter = NULL; + + /* Mémorisation de tous les noeuds ouverts */ + + builder = G_PANEL_ITEM(panel)->builder; + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + + void keep_track_of_expanded(GtkTreeView *tv, GtkTreePath *path, bintree_update_data *sud) + { + if (sud->ecount == sud->eallocated) + { + sud->eallocated += EXPAND_ALLOC_RANGE; + sud->expanded = (char **)realloc(sud->expanded, sud->eallocated * sizeof(char *)); } + sud->expanded[sud->ecount] = gtk_tree_path_to_string(path); + + sud->ecount++; + + } + + (*data)->expanded = NULL; + (*data)->ecount = 0; + (*data)->eallocated = 0; + + gtk_tree_view_map_expanded_rows(treeview, (GtkTreeViewMappingFunc)keep_track_of_expanded, *data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau ciblé par une mise à jour. * +* uid = identifiant de la phase de traitement. * +* data = données préparées par l'appelant. * +* * +* Description : Bascule l'affichage d'un panneau avant mise à jour. * +* * +* Retour : - * +* * +* Remarques : Cette fonction est appelée depuis le contexte principal. * +* * +******************************************************************************/ + +static void g_bintree_panel_introduce(const GBintreePanel *panel, unsigned int uid, bintree_update_data *data) +{ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeView *treeview; /* Arborescence graphique */ + GtkTreeModel *model; /* Source de données associée */ + + /* Basculement de l'affichage hors ligne */ + + g_panel_item_switch_to_updating_mask(G_PANEL_ITEM(panel)); + + builder = G_PANEL_ITEM(panel)->builder; + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + + model = gtk_tree_view_get_model(treeview); + + if (model != NULL) + { + g_object_ref(G_OBJECT(model)); + gtk_tree_view_set_model(treeview, NULL); + } + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau ciblé par une mise à jour. * +* uid = identifiant de la phase de traitement. * +* status = barre de statut à tenir informée. * +* id = identifiant pour le suivi de la progression. * +* data = données préparées par l'appelant. * +* * +* Description : Réalise une opération de mise à jour de panneau. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_bintree_panel_process(const GBintreePanel *panel, unsigned int uid, GtkStatusStack *status, activity_id_t id, bintree_update_data *data) +{ + switch (uid) + { + case PUI_0: + reload_portions_for_new_tree_view(panel, status, id, data); + break; + + case PUI_1: + do_filtering_on_portions(panel, status, id, data); + break; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau ciblé par une mise à jour. * +* uid = identifiant de la phase de traitement. * +* data = données préparées par l'appelant. * +* * +* Description : Bascule l'affichage d'un panneau après mise à jour. * +* * +* Retour : - * +* * +* Remarques : Cette fonction est appelée depuis le contexte principal. * +* * +******************************************************************************/ + +static void g_bintree_panel_conclude(GBintreePanel *panel, unsigned int uid, bintree_update_data *data) +{ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeView *treeview; /* Arborescence graphique */ + GtkTreeModel *model; /* Source de données associée */ + size_t i; /* Boucle de parcours */ + GtkTreePath *path; /* Chemin d'accès à un noeud */ + + if (g_atomic_int_get(&G_PANEL_ITEM(panel)->switched) > 1) + goto skip_this_step; + + /* Mise à jour des compteurs */ + + panel->count = data->count; + + /* Basculement de l'affichage en ligne */ + + builder = G_PANEL_ITEM(panel)->builder; + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + + model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "filter")); + + g_object_ref(G_OBJECT(model)); + gtk_tree_view_set_model(treeview, model); + + for (i = 0; i < data->ecount; i++) + { + path = gtk_tree_path_new_from_string(data->expanded[i]); + + gtk_tree_view_expand_to_path(treeview, path); + + gtk_tree_path_free(path); + } + skip_this_step: + + g_panel_item_switch_to_updated_content(G_PANEL_ITEM(panel)); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau ciblé par une mise à jour. * +* uid = identifiant de la phase de traitement. * +* data = données en place à nettoyer avant suppression. * +* * +* Description : Supprime les données dynamiques utilisées à la mise à jour. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_bintree_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, bintree_update_data *data) +{ + size_t i; /* Boucle de parcours */ + + if (data->filter != NULL) + { + regfree(data->filter); + free(data->filter); + } + + for (i = 0; i < data->ecount; i++) + g_free(data->expanded[i]); + + if (data->expanded != NULL) + free(data->expanded); + } |