diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-06-04 00:27:13 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-06-04 00:27:13 (GMT) |
commit | a7f73441a0d466824798a421f369628db0184030 (patch) | |
tree | 762b100af90b94f71597436fbd6d2349dcde7b42 /src/gui/panels/strings.c | |
parent | 0d10ebabd650128271650ca03d6e0b0ac9facc5c (diff) |
Loaded the biggest panel contents using threads.
Diffstat (limited to 'src/gui/panels/strings.c')
-rw-r--r-- | src/gui/panels/strings.c | 1015 |
1 files changed, 760 insertions, 255 deletions
diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c index 7420ffe..4828038 100644 --- a/src/gui/panels/strings.c +++ b/src/gui/panels/strings.c @@ -25,19 +25,23 @@ #include "strings.h" +#include <assert.h> #include <string.h> #include <inttypes.h> #include "panel-int.h" +#include "updating-int.h" #include "../core/global.h" #include "../dialogs/gotox.h" #include "../../common/extstr.h" #include "../../core/params.h" +#include "../../core/queue.h" #include "../../format/format.h" #include "../../format/symiter.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/gtkdockable-int.h" +#include "../../gtkext/tmgt.h" @@ -49,16 +53,14 @@ struct _GStringsPanel { GPanelItem parent; /* A laisser en premier */ - GtkTreeView *treeview; /* Composant d'affichage */ - const regex_t *filter; /* Filtre appliqué ou NULL */ + GLoadedBinary *binary; /* Binaire en cours d'analyse */ GtkMenu *menu; /* Menu contextuel pour param. */ - GLoadedBinary *binary; /* Binaire en cours d'analyse */ + size_t count; /* Quantité de symboles utiles */ }; - /* Panneau d'aperçu de graphiques (classe) */ struct _GStringsPanelClass { @@ -70,27 +72,34 @@ struct _GStringsPanelClass /* Colonnes de la liste des symboles */ typedef enum _StringsColumn { - STC_STRING, /* Elément GLib représenté */ + STC_SYMBOL, /* Symbole représenté */ STC_PHYSICAL, /* Adresse phyisque */ STC_VIRTUAL, /* Adresse virtuelle */ STC_AREA, /* Zone de localisation */ STC_NAME, /* Désignation humaine */ STC_VALUE, /* Chaîne de caractères */ + STC_ORIGINAL, /* Version brute d'origine */ + + STC_MATCHED, /* Correspondance établie ? */ STC_COUNT /* Nombre de colonnes */ } StringsColumn; +/* Données utiles à la mise à jour */ +typedef struct _strings_update_data strings_update_data; + + /* Initialise la classe des panneaux d'affichage de chaînes. */ static void g_strings_panel_class_init(GStringsPanelClass *); /* Initialise une instance de panneau d'affichage des chaînes. */ static void g_strings_panel_init(GStringsPanel *); -/* Procède à l'initialisation de l'interface de rassemblement. */ -static void g_strings_panel_dockable_interface_init(GtkDockableInterface *); +/* Procède à l'initialisation de l'interface de mise à jour. */ +static void g_strings_panel_updatable_interface_init(GUpdatablePanelInterface *); /* Supprime toutes les références externes. */ static void g_strings_panel_dispose(GStringsPanel *); @@ -98,14 +107,6 @@ static void g_strings_panel_dispose(GStringsPanel *); /* Procède à la libération totale de la mémoire. */ static void g_strings_panel_finalize(GStringsPanel *); - - -/* ------------------------- AFFICHAGE A L'AIDE D'UNE LISTE ------------------------- */ - - -/* Réagit à un changement d'affichage principal de contenu. */ -static void change_strings_panel_current_binary(GStringsPanel *, GLoadedBinary *); - /* Réagit au changement de sélection des chaînes textuelles. */ static void on_strings_selection_change(GtkTreeSelection *, gpointer); @@ -116,18 +117,38 @@ static gint compare_strings_list_columns(GtkTreeModel *, GtkTreeIter *, GtkTreeI static gboolean on_key_pressed_over_strings(GtkTreeView *, GdkEventKey *, GStringsPanel *); /* Réagit à une édition de l'étiquette d'une chaîne textuelle. */ -static void on_string_value_edited(GtkCellRendererText *, gchar *, gchar *, GtkTreeStore *); +static void on_string_name_edited(GtkCellRendererText *, gchar *, gchar *, GtkTreeModel *); +/* Réagit à un changement d'affichage principal de contenu. */ +static void change_strings_panel_current_binary(GStringsPanel *, GLoadedBinary *); -/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */ + +/* ------------------------- AFFICHAGE A L'AIDE D'UNE LISTE ------------------------- */ + + +/* Réagit à un changement d'affichage principal de contenu. */ +static void reload_strings_for_new_list_view(const GStringsPanel *, GtkStatusStack *, activity_id_t, strings_update_data *); + +/* Met en surbrillance les éléments recherchés dans les noms. */ +static void update_string_label_in_list_view(GtkListStore *, GtkTreeIter *, const regmatch_t *); + +/* Met en surbrillance les éléments recherchés dans les valeurs. */ +static void update_string_value_in_list_view(GtkListStore *, GtkTreeIter *, const regmatch_t *); + + + +/* ------------------------- FILTRAGE DES CHAINES PRESENTES ------------------------- */ /* Démarre l'actualisation du filtrage des chaînes. */ -static void update_filtered_strings(GStringsPanel *, const regex_t *); +static void update_filtered_strings(GStringsPanel *); + +/* Détermine si un noeud de l'arborescence doit être filtré. */ +static void update_string_node(const strings_update_data *, GtkListStore *, GtkTreeIter *); -/* Détermine si une chaîne textuelle doit être filtrée ou non. */ -static bool is_string_filtered(GStringsPanel *, const char *, const char *); +/* Exécute un nouveau filtrage des chaînes affichées. */ +static void do_filtering_on_strings(const GStringsPanel *, GtkStatusStack *, activity_id_t, strings_update_data *); @@ -141,7 +162,7 @@ static gboolean on_button_event_over_strings(GtkWidget *, GdkEventButton *, GStr static GtkMenu *build_strings_panel_menu(GStringsPanel *); /* Fournit le signet sélectionné dans la liste. */ -static GBinSymbol *get_selected_panel_symbol(GtkTreeView *, GtkTreeIter *); +static GBinSymbol *get_selected_panel_symbol(GStringsPanel *, GtkTreeIter *); /* Réagit avec le menu "Editer le nom". */ static void mcb_strings_panel_edit(GtkMenuItem *, GStringsPanel *); @@ -156,6 +177,41 @@ static void mcb_strings_panel_find_refs(GtkMenuItem *, GStringsPanel *); static void mcb_strings_panel_filter(GtkMenuItem *, GStringsPanel *); +/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */ + + +/* Données utiles à la mise à jour */ +struct _strings_update_data +{ + size_t count; /* Qté d'inscriptions réalisées*/ + + regex_t *filter; /* Filtre appliqué ou NULL */ + +}; + + +/* Détermine si un nom de symbole doit être filtré ou non. */ +static bool is_string_name_matching(const strings_update_data *, GtkTreeModel *, GtkTreeIter *, regmatch_t *); + +/* Détermine si une valeur de symbole doit être filtrée ou non. */ +static bool is_string_value_matching(const strings_update_data *, GtkTreeModel *, GtkTreeIter *, regmatch_t *); + +/* Prépare une opération de mise à jour de panneau. */ +static const char *g_strings_panel_setup(const GStringsPanel *, unsigned int, size_t *, strings_update_data **); + +/* Bascule l'affichage d'un panneau avant mise à jour. */ +static void g_strings_panel_introduce(const GStringsPanel *, unsigned int, strings_update_data *); + +/* Réalise une opération de mise à jour de panneau. */ +static void g_strings_panel_process(const GStringsPanel *, unsigned int, GtkStatusStack *, activity_id_t, strings_update_data *); + +/* Bascule l'affichage d'un panneau après mise à jour. */ +static void g_strings_panel_conclude(GStringsPanel *, unsigned int, strings_update_data *); + +/* Supprime les données dynamiques utilisées à la mise à jour. */ +static void g_strings_panel_clean_data(GUpdatablePanel *, unsigned int, strings_update_data *); + + /* ---------------------------------------------------------------------------------- */ /* PARTIE PRINCIPALE DU PANNEAU */ @@ -164,7 +220,7 @@ static void mcb_strings_panel_filter(GtkMenuItem *, GStringsPanel *); /* Indique le type définit pour un panneau d'affichage des chaînes. */ G_DEFINE_TYPE_WITH_CODE(GStringsPanel, g_strings_panel, G_TYPE_PANEL_ITEM, - G_IMPLEMENT_INTERFACE(GTK_TYPE_DOCKABLE, g_strings_panel_dockable_interface_init)); + G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_strings_panel_updatable_interface_init)); /****************************************************************************** @@ -199,6 +255,13 @@ static void g_strings_panel_class_init(GStringsPanelClass *klass) panel->unique = true; panel->bindings = "<Shift>F12"; + panel->can_search = true; + panel->can_be_closed = true; + + panel->update_filtered = (update_filtered_fc)update_filtered_strings; + + panel->gid = setup_tiny_global_work_group(1); + } @@ -218,14 +281,13 @@ static void g_strings_panel_init(GStringsPanel *panel) { GEditorItem *base; /* Version basique d'instance */ GPanelItem *pitem; /* Version parente du panneau */ - GObject *ref; /* Espace de référencement */ - GtkTreeStore *store; /* Modèle de gestion */ - GtkWidget *treeview; /* Affichage de la liste */ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeModelFilter *filter; /* Filtre pour l'arborescence */ + GtkTreeView *treeview; /* Affichage de la liste */ GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ GtkTreeViewColumn *column; /* Colonne de la liste */ + GtkTreeModel *model; /* Modèle de gestion de liste */ GtkTreeSortable *sortable; /* Autre vision de la liste */ - GtkTreeSelection *select; /* Sélection dans la liste */ - bool display; /* Affichage si sélection ? */ /* Eléments de base */ @@ -242,37 +304,15 @@ static void g_strings_panel_init(GStringsPanel *panel) /* Représentation graphique */ - base->widget = gtk_scrolled_window_new(NULL, NULL); - gtk_widget_show(base->widget); - - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(base->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(base->widget), GTK_SHADOW_IN); - - ref = G_OBJECT(base->widget); - g_object_set_data(ref, "panel", panel); - - /* Partie chaînes */ - - store = gtk_tree_store_new(STC_COUNT, G_TYPE_OBJECT, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - - treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - panel->treeview = GTK_TREE_VIEW(treeview); - - g_signal_connect(G_OBJECT(treeview), "button-press-event", - G_CALLBACK(on_button_event_over_strings), panel); - g_signal_connect(G_OBJECT(treeview), "button-release-event", - G_CALLBACK(on_button_event_over_strings), panel); - g_signal_connect(G_OBJECT(treeview), "key-press-event", - G_CALLBACK(on_key_pressed_over_strings), panel); + builder = g_panel_item_build(pitem, "strings"); - gtk_widget_show(treeview); - gtk_container_add(GTK_CONTAINER(base->widget), treeview); - - g_object_unref(G_OBJECT(store)); + filter = GTK_TREE_MODEL_FILTER(gtk_builder_get_object(builder, "filter")); + gtk_tree_model_filter_set_visible_column(filter, STC_MATCHED); /* Cellules d'affichage */ + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(_("Physical address"), renderer, "text", STC_PHYSICAL, @@ -295,9 +335,11 @@ static void g_strings_panel_init(GStringsPanel *panel) gtk_tree_view_column_set_sort_column_id(column, STC_AREA); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "store")); + renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL); - g_signal_connect(renderer, "edited", G_CALLBACK(on_string_value_edited), store); + g_signal_connect(renderer, "edited", G_CALLBACK(on_string_name_edited), model); column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, "text", STC_NAME, NULL); @@ -313,7 +355,7 @@ static void g_strings_panel_init(GStringsPanel *panel) /* Tri de la liste */ - sortable = GTK_TREE_SORTABLE(store); + sortable = GTK_TREE_SORTABLE(gtk_builder_get_object(builder, "store")); gtk_tree_sortable_set_sort_func(sortable, STC_PHYSICAL, compare_strings_list_columns, GINT_TO_POINTER(STC_PHYSICAL), NULL); @@ -332,15 +374,15 @@ static void g_strings_panel_init(GStringsPanel *panel) gtk_tree_sortable_set_sort_column_id(sortable, STC_VIRTUAL, GTK_SORT_ASCENDING); - /* Prise en compte de la sélection */ + /* Connexion des signaux */ - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); + gtk_builder_add_callback_symbols(builder, + "on_button_event_over_strings", G_CALLBACK(on_button_event_over_strings), + "on_key_pressed_over_strings", G_CALLBACK(on_key_pressed_over_strings), + "on_strings_selection_change", G_CALLBACK(on_strings_selection_change), + NULL); - g_generic_config_get_value(get_main_configuration(), MPK_DISPLAY_ON_SEL, &display); - - if (display) - g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(on_strings_selection_change), NULL); + gtk_builder_connect_signals(builder, panel); /* Préparation du menu contextuel */ @@ -351,9 +393,9 @@ static void g_strings_panel_init(GStringsPanel *panel) /****************************************************************************** * * -* Paramètres : iface = interface GTK à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de rassemblement. * +* Description : Procède à l'initialisation de l'interface de mise à jour. * * * * Retour : - * * * @@ -361,19 +403,14 @@ static void g_strings_panel_init(GStringsPanel *panel) * * ******************************************************************************/ -static void g_strings_panel_dockable_interface_init(GtkDockableInterface *iface) +static void g_strings_panel_updatable_interface_init(GUpdatablePanelInterface *iface) { - GtkDockableInterface *parent_iface; /* Définition précédente */ - - parent_iface = (GtkDockableInterface *)g_type_interface_peek_parent(iface); - - iface->can_search = true; - iface->can_be_closed = true; - - iface->get_name = parent_iface->get_name; - iface->get_desc = parent_iface->get_desc; - iface->get_widget = parent_iface->get_widget; - iface->update_filtered = (update_filtered_data_fc)update_filtered_strings; + iface->setup = (setup_updatable_cb)g_strings_panel_setup; + iface->get_group = (get_updatable_group_cb)g_panel_item_get_group; + iface->introduce = (introduce_updatable_cb)g_strings_panel_introduce; + iface->process = (process_updatable_cb)g_strings_panel_process; + iface->conclude = (conclude_updatable_cb)g_strings_panel_conclude; + iface->clean = (clean_updatable_data_cb)g_strings_panel_clean_data; } @@ -442,143 +479,6 @@ GPanelItem *g_strings_panel_new(void) } - -/* ---------------------------------------------------------------------------------- */ -/* AFFICHAGE A L'AIDE D'UNE LISTE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* 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_strings_panel_current_binary(GStringsPanel *panel, GLoadedBinary *binary) -{ - GtkTreeStore *store; /* Modèle de gestion */ - GArchProcessor *proc; /* Architecture du binaire */ - MemoryDataSize msize; /* Taille par défaut */ - GExeFormat *format; /* Format de travail */ - GBinPortion *portions; /* Couche première de portions */ - GBinContent *content; /* Contenu binaire en mémoire */ - sym_iter_t *siter; /* Parcours des symboles */ - GBinSymbol *symbol; /* Symbole manipulé */ - const mrange_t *range; /* Couverture mémoire */ - const vmpa2t *addr; /* Adressse liée à la chaîne */ - VMPA_BUFFER(phys); /* Position physique */ - VMPA_BUFFER(virt); /* Adresse virtuelle */ - GBinPortion *portion; /* Zone mémoire d'appartenance */ - const char *area; /* Description de la zone */ - const char *label; /* Etiquette liée au symbole */ - vmpa2t pos; /* Tête de lecture modifiable */ - char *text; /* Version imprimable du texte */ - GtkTreeIter iter; /* Point d'insertion */ - - /* 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)); - - store = GTK_TREE_STORE(gtk_tree_view_get_model(panel->treeview)); - gtk_tree_store_clear(store); - - /* Si le panneau actif ne représente pas un binaire... */ - - if (binary == NULL) return; - - /* Actualisation de l'affichage */ - - proc = g_loaded_binary_get_processor(binary); - msize = g_arch_processor_get_memory_size(proc); - g_object_unref(G_OBJECT(proc)); - - format = g_loaded_binary_get_format(binary); - portions = g_exe_format_get_portions(format); - content = g_binary_format_get_content(G_BIN_FORMAT(format)); - - siter = create_symbol_iterator(G_BIN_FORMAT(format), 0); - - for (symbol = get_symbol_iterator_current(siter); - symbol != NULL; - symbol = get_symbol_iterator_next(siter)) - { - if (g_binary_symbol_get_target_type(symbol) != STP_RO_STRING) - goto cspcb_next; - - range = g_binary_symbol_get_range(symbol); - addr = get_mrange_addr(range); - - vmpa2_phys_to_string(addr, msize, phys, NULL); - vmpa2_virt_to_string(addr, msize, virt, NULL); - - portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { }); - area = g_binary_portion_get_desc(portion); - g_object_unref(G_OBJECT(portion)); - - label = g_binary_symbol_get_label(symbol); - - text = (char *)calloc(get_mrange_length(range) + 1, sizeof(char)); - - copy_vmpa(&pos, addr); - - if (!g_binary_content_read_raw(content, &pos, get_mrange_length(range), (uint8_t *)text)) - { - free(text); - goto cspcb_next; - } - - if (is_string_filtered(panel, label, text)) - { - free(text); - goto cspcb_next; - } - - text = strrpl(text, "&", "&"); - text = strrpl(text, "<", "<"); - text = strrpl(text, ">", ">"); - text = strrpl(text, "\r", "<b>\\r</b>"); - text = strrpl(text, "\n", "<b>\\n</b>"); - - gtk_tree_store_append(store, &iter, NULL); - gtk_tree_store_set(store, &iter, - STC_STRING, symbol, - STC_PHYSICAL, phys, - STC_VIRTUAL, virt, - STC_AREA, area, - STC_NAME, label, - STC_VALUE, text, - -1); - - free(text); - - cspcb_next: - - g_object_unref(G_OBJECT(symbol)); - - } - - delete_symbol_iterator(siter); - - g_object_unref(G_OBJECT(content)); - g_object_unref(G_OBJECT(portions)); - g_object_unref(G_OBJECT(format)); - -} - - /****************************************************************************** * * * Paramètres : selection = sélection modifiée. * @@ -602,7 +502,7 @@ static void on_strings_selection_change(GtkTreeSelection *selection, gpointer un if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - gtk_tree_model_get(model, &iter, STC_STRING, &symbol, -1); + gtk_tree_model_get(model, &iter, STC_SYMBOL, &symbol, -1); addr = get_mrange_addr(g_binary_symbol_get_range(symbol)); @@ -703,7 +603,7 @@ static gboolean on_key_pressed_over_strings(GtkTreeView *treeview, GdkEventKey * * Paramètres : renderer = moteur de rendu pour la cellule. * * path = chemin d'accès vers la cellule éditée. * * new = nouvelle valeur sous forme de texte à valider. * -* store = gestionnaire des données de la liste affichée. * +* model = gestionnaire des données de la liste affichée. * * * * Description : Réagit à une édition de l'étiquette d'une chaîne textuelle. * * * @@ -713,7 +613,7 @@ static gboolean on_key_pressed_over_strings(GtkTreeView *treeview, GdkEventKey * * * ******************************************************************************/ -static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, gchar *new, GtkTreeStore *store) +static void on_string_name_edited(GtkCellRendererText *renderer, gchar *path, gchar *new, GtkTreeModel *model) { GtkTreePath *tree_path; /* Chemin d'accès natif */ GtkTreeIter iter; /* Point de la modification */ @@ -722,10 +622,10 @@ static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, g tree_path = gtk_tree_path_new_from_string(path); if (tree_path == NULL) return; - if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, tree_path)) + if (!gtk_tree_model_get_iter(model, &iter, tree_path)) goto opve_bad_iter; - gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, STC_STRING, &symbol, -1); + gtk_tree_model_get(model, &iter, STC_SYMBOL, &symbol, -1); g_binary_symbol_set_alt_label(symbol, new); @@ -738,18 +638,64 @@ static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, g } +/****************************************************************************** +* * +* 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_strings_panel_current_binary(GStringsPanel *panel, GLoadedBinary *binary) +{ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkListStore *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)); + + /* Réinitialisation */ + + builder = G_PANEL_ITEM(panel)->builder; + + store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store")); + + gtk_list_store_clear(store); + + /* Si le panneau actif représente un binaire, actualisation de l'affichage */ + + if (binary != NULL) + run_panel_update(G_UPDATABLE_PANEL(panel), PUI_0); + +} + + /* ---------------------------------------------------------------------------------- */ -/* FILTRAGE DES SYMBOLES PRESENTS */ +/* AFFICHAGE A L'AIDE D'UNE LISTE */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : panel = panneau assurant l'affichage des paramètres. * -* preg = expression régulière compilée à utiliser. * +* Paramètres : panel = panneau à mettre à jour. * +* status = barre de statut à tenir informée. * +* id = identifiant pour le suivi de la progression. * +* data = données complémentaire à manipuler. * * * -* Description : Démarre l'actualisation du filtrage des chaînes. * +* Description : Réagit à un changement d'affichage principal de contenu. * * * * Retour : - * * * @@ -757,50 +703,289 @@ static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, g * * ******************************************************************************/ -static void update_filtered_strings(GStringsPanel *panel, const regex_t *preg) +static void reload_strings_for_new_list_view(const GStringsPanel *panel, GtkStatusStack *status, activity_id_t id, strings_update_data *data) { - panel->filter = preg; + GtkBuilder *builder; /* Constructeur utilisé */ + GtkListStore *store; /* Modèle de gestion */ + GArchProcessor *proc; /* Architecture utilisée */ + MemoryDataSize size; /* Taille des localisations */ + GExeFormat *format; /* Format associé au binaire */ + GBinPortion *portions; /* Couche première de portions */ + GBinContent *content; /* Contenu binaire en mémoire */ + sym_iter_t *siter; /* Parcours des symboles */ + GBinSymbol *symbol; /* Symbole manipulé */ + const mrange_t *range; /* Couverture mémoire */ + const vmpa2t *addr; /* Adressse liée à la chaîne */ + VMPA_BUFFER(phys); /* Position physique */ + VMPA_BUFFER(virt); /* Adresse virtuelle */ + GBinPortion *portion; /* Zone mémoire d'appartenance */ + const char *area; /* Description de la zone */ + char *text; /* Texte original référencé */ + vmpa2t pos; /* Tête de lecture modifiable */ + GtkTreeIter iter; /* Point d'insertion */ + + builder = G_PANEL_ITEM(panel)->builder; + + store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store")); + + proc = g_loaded_binary_get_processor(panel->binary); + size = g_arch_processor_get_memory_size(proc); + g_object_unref(G_OBJECT(proc)); + + format = g_loaded_binary_get_format(panel->binary); + portions = g_exe_format_get_portions(format); + content = g_binary_format_get_content(G_BIN_FORMAT(format)); + + siter = create_symbol_iterator(G_BIN_FORMAT(format), 0); + + for (symbol = get_symbol_iterator_current(siter); + symbol != NULL; + symbol = get_symbol_iterator_next(siter)) + { + if (g_binary_symbol_get_target_type(symbol) != STP_RO_STRING) + goto rsfnlv_next; + + range = g_binary_symbol_get_range(symbol); + addr = get_mrange_addr(range); + + vmpa2_phys_to_string(addr, size, phys, NULL); + vmpa2_virt_to_string(addr, size, virt, NULL); + + portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { }); + area = g_binary_portion_get_desc(portion); + g_object_unref(G_OBJECT(portion)); + + text = (char *)calloc(get_mrange_length(range) + 1, sizeof(char)); + + copy_vmpa(&pos, addr); + + if (!g_binary_content_read_raw(content, &pos, get_mrange_length(range), (uint8_t *)text)) + { + free(text); + goto rsfnlv_next; + } + + addr = get_mrange_addr(g_binary_symbol_get_range(symbol)); + vmpa2_virt_to_string(addr, size, virt, NULL); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + STC_SYMBOL, symbol, + STC_PHYSICAL, phys, + STC_VIRTUAL, virt, + STC_AREA, area, + STC_NAME, NULL, + STC_VALUE, NULL, + STC_ORIGINAL, text, + STC_MATCHED, false, + -1); + + update_string_node(data, store, &iter); + + data->count++; + + free(text); - change_strings_panel_current_binary(panel, panel->binary); + rsfnlv_next: + + g_object_unref(G_OBJECT(symbol)); + + gtk_status_stack_update_activity_value(status, id, 1); + + } + + delete_symbol_iterator(siter); + + g_object_unref(G_OBJECT(content)); + g_object_unref(G_OBJECT(portions)); + g_object_unref(G_OBJECT(format)); } /****************************************************************************** * * -* Paramètres : panel = panneau assurant l'affichage des paramètres. * -* label = étiquette liée au symbole à traiter. * -* value = chaîne de caractères représentée par le symbole. * +* Paramètres : store = gestionnaire de données pour une arborescence. * +* iter = position des données traitées. * +* match = correspondance avec un objet recherché. * * * -* Description : Détermine si une chaîne textuelle doit être filtrée ou non. * +* Description : Met en surbrillance les éléments recherchés dans les noms. * * * -* Retour : true si le symbole ne doit pas être affiché, false sinon. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool is_string_filtered(GStringsPanel *panel, const char *label, const char *value) +static void update_string_label_in_list_view(GtkListStore *store, GtkTreeIter *iter, const regmatch_t *match) { - bool result; /* Bilan à retourner */ + GtkTreeModel *model; /* Autre vision du gestionnaire*/ + char *original; /* Etiquette brute d'origine */ + char *value; /* Etiquette mise en relief */ + + model = GTK_TREE_MODEL(store); + + gtk_tree_model_get(model, iter, STC_ORIGINAL, &original, -1); + + original = strrpl(original, "&", "&"); + original = strrpl(original, "<", "<"); + original = strrpl(original, ">", ">"); + original = strrpl(original, "\r", "<b>\\r</b>"); + original = strrpl(original, "\n", "<b>\\n</b>"); + + value = build_highlighted_name(original, match, 0); + + gtk_list_store_set(store, iter, STC_VALUE, value, -1); + + free(original); + free(value); + +} + + +/****************************************************************************** +* * +* Paramètres : store = gestionnaire de données pour une arborescence. * +* iter = position des données traitées. * +* match = correspondance avec un objet recherché. * +* * +* Description : Met en surbrillance les éléments recherchés dans les valeurs.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_string_value_in_list_view(GtkListStore *store, GtkTreeIter *iter, const regmatch_t *match) +{ + GtkTreeModel *model; /* Autre vision du gestionnaire*/ + char *original; /* Etiquette brute d'origine */ + char *value; /* Etiquette mise en relief */ + + model = GTK_TREE_MODEL(store); + + gtk_tree_model_get(model, iter, STC_ORIGINAL, &original, -1); + + original = strrpl(original, "&", "&"); + original = strrpl(original, "<", "<"); + original = strrpl(original, ">", ">"); + original = strrpl(original, "\r", "<b>\\r</b>"); + original = strrpl(original, "\n", "<b>\\n</b>"); + + value = build_highlighted_name(original, match, 0); + + gtk_list_store_set(store, iter, STC_VALUE, value, -1); + + free(original); + free(value); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* FILTRAGE DES CHAINES PRESENTES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : panel = panneau assurant l'affichage des chaînes. * +* * +* Description : Démarre l'actualisation du filtrage des chaînes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_filtered_strings(GStringsPanel *panel) +{ + run_panel_update(G_UPDATABLE_PANEL(panel), PUI_1); + +} + + +/****************************************************************************** +* * +* Paramètres : data = données complémentaire à manipuler. * +* store = gestionnaire de l'ensemble des données. * +* iter = localisation des données à analyser. * +* * +* Description : Détermine si un noeud de l'arborescence doit être filtré. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_string_node(const strings_update_data *data, GtkListStore *store, GtkTreeIter *iter) +{ + GtkTreeModel *model; /* Autre vision du gestionnaire*/ regmatch_t match; /* Récupération des trouvailles*/ - int ret; /* Bilan du filtrage */ + bool name_matched; /* Correspondance de sélection */ + bool value_matched; /* Correspondance de sélection */ + + model = GTK_TREE_MODEL(store); + + name_matched = is_string_name_matching(data, model, iter, &match); + + if (name_matched) + update_string_label_in_list_view(store, iter, &match); + + value_matched = is_string_value_matching(data, model, iter, &match); + + if (value_matched) + update_string_value_in_list_view(store, iter, &match); + + if (name_matched || value_matched) + gtk_list_store_set(GTK_LIST_STORE(model), iter, STC_MATCHED, true, -1); + else + gtk_list_store_set(GTK_LIST_STORE(model), iter, STC_MATCHED, false, -1); + +} + - if (panel->filter == NULL) - return false; +/****************************************************************************** +* * +* Paramètres : panel = panneau assurant l'affichage des chaînes. * +* status = barre de statut à tenir informée. * +* id = identifiant pour le suivi de la progression. * +* data = données complémentaire à manipuler. * +* * +* Description : Exécute un nouveau filtrage des chaînes affichées. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void do_filtering_on_strings(const GStringsPanel *panel, GtkStatusStack *status, activity_id_t id, strings_update_data *data) +{ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkListStore *store; /* Modèle de gestion */ - result = true; - if (label != NULL) + gboolean filter_string_panel_iter(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer unused) { - ret = regexec(panel->filter, label, 1, &match, 0); - result &= (ret == REG_NOMATCH); + update_string_node(data, store, iter); + + gtk_status_stack_update_activity_value(status, id, 1); + + return FALSE; + } - ret = regexec(panel->filter, value, 1, &match, 0); - result &= (ret == REG_NOMATCH); - return result; + builder = G_PANEL_ITEM(panel)->builder; + + store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store")); + + gtk_tree_model_foreach(GTK_TREE_MODEL(store), (GtkTreeModelForeachFunc)filter_string_panel_iter, NULL); } @@ -845,7 +1030,7 @@ static gboolean on_button_event_over_strings(GtkWidget *widget, GdkEventButton * if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - gtk_tree_model_get(model, &iter, STC_STRING, &symbol, -1); + gtk_tree_model_get(model, &iter, STC_SYMBOL, &symbol, -1); addr = get_mrange_addr(g_binary_symbol_get_range(symbol)); @@ -918,8 +1103,8 @@ static GtkMenu *build_strings_panel_menu(GStringsPanel *panel) /****************************************************************************** * * -* Paramètres : treeview = liste d'affichage à consulter. * -* save = zone de conservation du point de trouvaille. [OUT]* +* Paramètres : panel = panneau concerné par l'opération. * +* save = zone de conservation du point de trouvaille. [OUT] * * * * Description : Fournit le signet sélectionné dans la liste. * * * @@ -929,19 +1114,25 @@ static GtkMenu *build_strings_panel_menu(GStringsPanel *panel) * * ******************************************************************************/ -static GBinSymbol *get_selected_panel_symbol(GtkTreeView *treeview, GtkTreeIter *save) +static GBinSymbol *get_selected_panel_symbol(GStringsPanel *panel, GtkTreeIter *save) { GBinSymbol *result; /* Chaîne textuelle à renvoyer */ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeView *treeview; /* Arborescence graphique */ GtkTreeSelection *selection; /* Représentation de sélection */ GtkTreeModel *model; /* Gestionnaire des données */ GtkTreeIter iter; /* Point de la sélection */ result = NULL; + builder = G_PANEL_ITEM(panel)->builder; + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + selection = gtk_tree_view_get_selection(treeview); if (gtk_tree_selection_get_selected(selection, &model, &iter)) - gtk_tree_model_get(model, &iter, STC_STRING, &result, -1); + gtk_tree_model_get(model, &iter, STC_SYMBOL, &result, -1); if (save != NULL) *save = iter; @@ -968,17 +1159,23 @@ static void mcb_strings_panel_edit(GtkMenuItem *menuitem, GStringsPanel *panel) { GtkTreeIter iter; /* Point de la sélection */ GBinSymbol *symbol; /* Symbole sélectionné */ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeView *treeview; /* Arborescence graphique */ GtkTreeModel *model; /* Gestionnaire de données */ GtkTreePath *path; /* Chemin d'accès à ce point */ - symbol = get_selected_panel_symbol(panel->treeview, &iter); + symbol = get_selected_panel_symbol(panel, &iter); if (symbol == NULL) return; - model = gtk_tree_view_get_model(panel->treeview); + builder = G_PANEL_ITEM(panel)->builder; + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + + model = gtk_tree_view_get_model(treeview); path = gtk_tree_model_get_path(model, &iter); - gtk_tree_view_set_cursor(panel->treeview, path, - gtk_tree_view_get_column(panel->treeview, STC_NAME - STC_PHYSICAL), + gtk_tree_view_set_cursor(treeview, path, + gtk_tree_view_get_column(treeview, STC_NAME - STC_PHYSICAL), TRUE); gtk_tree_path_free(path); @@ -1003,13 +1200,19 @@ static void mcb_strings_panel_edit(GtkMenuItem *menuitem, GStringsPanel *panel) static void mcb_strings_panel_copy(GtkMenuItem *menuitem, GStringsPanel *panel) { + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeView *treeview; /* Arborescence graphique */ GtkTreeSelection *selection; /* Sélection de l'arbre */ GtkTreeIter iter; /* Point de sélection */ GtkTreeModel *model; /* Modèle de gestion */ gchar *string; /* Chaîne sélectionnée */ GtkClipboard *clipboard; /* Presse-papiers d'arrivée */ - selection = gtk_tree_view_get_selection(panel->treeview); + builder = G_PANEL_ITEM(panel)->builder; + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + + selection = gtk_tree_view_get_selection(treeview); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { @@ -1055,7 +1258,7 @@ static void mcb_strings_panel_find_refs(GtkMenuItem *menuitem, GStringsPanel *pa vmpa2t *addr; /* Adresse de destination */ GLoadedPanel *display; /* Afficheur effectif de code */ - symbol = get_selected_panel_symbol(panel->treeview, NULL); + symbol = get_selected_panel_symbol(panel, NULL); if (symbol == NULL) return; range = g_binary_symbol_get_range(symbol); @@ -1119,7 +1322,7 @@ static void mcb_strings_panel_filter(GtkMenuItem *menuitem, GStringsPanel *panel #if 0 GCfgParam *param; /* Paramètre sélectionné */ - param = get_selected_panel_symbol(panel->treeview, NULL); + param = get_selected_panel_symbol(panel, NULL); if (param == NULL) return; g_config_param_make_empty(param); @@ -1127,3 +1330,305 @@ static void mcb_strings_panel_filter(GtkMenuItem *menuitem, GStringsPanel *panel g_object_unref(G_OBJECT(param)); #endif } + + + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE MISE A JOUR DE PANNEAU */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : data = données complémentaire à manipuler. * +* model = gestionnaire de l'ensemble des données. * +* iter = localisation des données à analyser. * +* match = récupération des trouvailles. [OUT] * +* * +* Description : Détermine si un nom de symbole doit être filtré ou non. * +* * +* Retour : true si le symbol ne doit pas être affiché, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_string_name_matching(const strings_update_data *data, GtkTreeModel *model, GtkTreeIter *iter, regmatch_t *match) +{ + bool result; /* Bilan à retourner */ + GBinSymbol *symbol; /* Symbole manipulé */ +#ifndef NDEBUG + SymbolType type; /* Type associé au symbole */ +#endif + const char *label; /* Etiquette à analyser */ + + gtk_tree_model_get(model, iter, STC_SYMBOL, &symbol, -1); + assert(symbol != NULL); + +#ifndef NDEBUG + + type = g_binary_symbol_get_target_type(symbol); + + assert(type == STP_RO_STRING); + +#endif + + label = g_binary_symbol_get_label(symbol); + + if (label == NULL) + result = false; + else + result = is_content_matching(data->filter, label, match); + + g_object_unref(G_OBJECT(symbol)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = données complémentaire à manipuler. * +* model = gestionnaire de l'ensemble des données. * +* iter = localisation des données à analyser. * +* match = récupération des trouvailles. [OUT] * +* * +* Description : Détermine si une valeur de symbole doit être filtrée ou non. * +* * +* Retour : true si le symbol ne doit pas être affiché, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_string_value_matching(const strings_update_data *data, GtkTreeModel *model, GtkTreeIter *iter, regmatch_t *match) +{ + bool result; /* Bilan à retourner */ + char *original; /* Etiquette brute d'origine */ + + gtk_tree_model_get(model, iter, STC_ORIGINAL, &original, -1); + + result = is_content_matching(data->filter, original, match); + + free(original); + + 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_strings_panel_setup(const GStringsPanel *panel, unsigned int uid, size_t *count, strings_update_data **data) +{ + const char *result; /* Message à retourner */ + GBinFormat *format; /* Format du binaire */ + int ret; /* Bilan de mise en place */ + + *data = malloc(sizeof(strings_update_data)); + + switch (uid) + { + case PUI_0: + + format = G_BIN_FORMAT(g_loaded_binary_get_format(panel->binary)); + + g_binary_format_lock_symbols_rd(format); + *count = g_binary_format_count_symbols(format); + g_binary_format_unlock_symbols_rd(format); + + g_object_unref(G_OBJECT(format)); + + (*data)->count = 0; + + result = _("Loading strings available in the binary format..."); + + break; + + case PUI_1: + + *count = panel->count; + (*data)->count = panel->count; + + result = _("Filtering strings available 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; + + 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_strings_panel_introduce(const GStringsPanel *panel, unsigned int uid, strings_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_strings_panel_process(const GStringsPanel *panel, unsigned int uid, GtkStatusStack *status, activity_id_t id, strings_update_data *data) +{ + switch (uid) + { + case PUI_0: + reload_strings_for_new_list_view(panel, status, id, data); + break; + + case PUI_1: + do_filtering_on_strings(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_strings_panel_conclude(GStringsPanel *panel, unsigned int uid, strings_update_data *data) +{ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeView *treeview; /* Arborescence graphique */ + GtkTreeModel *model; /* Source de données associée */ + + 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); + + 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_strings_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, strings_update_data *data) +{ + if (data->filter != NULL) + { + regfree(data->filter); + free(data->filter); + } + +} |