From e7ba901892df20045ff3a541b4fa34e36bd05bfb Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 8 Mar 2015 21:31:56 +0000 Subject: Listed all idenfied read only strings in a dedicated panel. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@483 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 16 ++ src/analysis/disass/area.c | 1 + src/format/symbol.c | 4 + src/format/symbol.h | 5 +- src/gui/panels/bookmarks.c | 30 +- src/gui/panels/regedit.c | 4 +- src/gui/panels/strings.c | 702 ++++++++++++++++++++++++++++++++++++++++----- 7 files changed, 666 insertions(+), 96 deletions(-) diff --git a/ChangeLog b/ChangeLog index d832495..46ccde4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 15-03-08 Cyrille Bagard + * src/analysis/disass/area.c: + * src/format/symbol.c: + * src/format/symbol.h: + Introduce a new symbol type called 'STP_RO_STRING'. + + * src/gui/panels/bookmarks.c: + Update code. + + * src/gui/panels/regedit.c: + Typo. + + * src/gui/panels/strings.c: + List all idenfied read only strings in a dedicated panel. + +15-03-08 Cyrille Bagard + * src/analysis/disass/disassembler.c: Update code. diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index f47e74c..bd99402 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -847,6 +847,7 @@ static GArchInstruction *get_instructions_from_mem_area(const mem_area *area) switch (g_binary_symbol_get_target_type(area->symbol)) { case STP_DATA: + case STP_RO_STRING: result = g_binary_symbol_get_instruction(area->symbol); g_object_ref(G_OBJECT(result)); break; diff --git a/src/format/symbol.c b/src/format/symbol.c index 8ab76b6..37dc45e 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -222,6 +222,7 @@ SymbolType g_binary_symbol_get_target_type(const GBinSymbol *symbol) const char *g_binary_symbol_to_string(const GBinSymbol *symbol) { + return "AAAA"; const char *result; /* Désignation à retourner */ switch (symbol->type) @@ -328,6 +329,7 @@ void g_binary_symbol_fix_range(GBinSymbol *symbol, const vmpa2t *full) switch (symbol->type) { case STP_DATA: + case STP_RO_STRING: instr = g_binary_symbol_get_instruction(symbol); @@ -385,6 +387,7 @@ const mrange_t *g_binary_symbol_get_range(const GBinSymbol *symbol) switch (symbol->type) { case STP_DATA: + case STP_RO_STRING: result = g_arch_instruction_get_range(symbol->extra.instr); break; @@ -460,6 +463,7 @@ void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine) void g_binary_symbol_attach_instruction(GBinSymbol *symbol, GArchInstruction *instr) { + if (symbol->type != STP_RO_STRING) symbol->type = STP_DATA; symbol->extra.instr = instr; diff --git a/src/format/symbol.h b/src/format/symbol.h index c3e53cc..fafc55f 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -42,7 +42,8 @@ typedef enum _SymbolType STP_OBJECT, /* Objet quelconque */ STP_FUNCTION, /* Simple morceau de code */ STP_ENTRY_POINT, /* Morceau de code en entrée */ - STP_STRING /* Chaîne de caractères */ + STP_STRING, /* Chaîne de caractères */ + STP_RO_STRING /* Chaîne de caractères */ } SymbolType; @@ -142,7 +143,7 @@ GDbComment *g_binary_symbol_get_comment(const GBinSymbol *); #define ADD_STR_AS_SYM(_fmt, _sym, _ins) \ do \ { \ - _sym = g_binary_symbol_new(STP_DATA, NULL, 0); \ + _sym = g_binary_symbol_new(STP_RO_STRING, NULL, 0); \ g_binary_symbol_attach_instruction(_sym, _ins); \ g_binary_format_add_symbol(G_BIN_FORMAT(_fmt), _sym); \ } \ diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c index e9ab0d1..60daf67 100644 --- a/src/gui/panels/bookmarks.c +++ b/src/gui/panels/bookmarks.c @@ -38,9 +38,9 @@ #include "panel-int.h" #include "../../analysis/db/items/bookmark.h" -#include "../../core/params.h" #include "../../common/cpp.h" #include "../../common/extstr.h" +#include "../../core/params.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/support.h" @@ -141,7 +141,7 @@ static void on_param_value_edited(GtkCellRendererText *, gchar *, gchar *, GtkTr /* Démarre l'actualisation du filtrage des paramètres. */ static void on_param_search_changed(GtkSearchEntry *, GBookmarksPanel *); -/*Détermine si un paramètre doit être filtré ou non. */ +/* Détermine si un paramètre doit être filtré ou non. */ static bool is_param_filtered(GBookmarksPanel *, const char *); @@ -153,7 +153,7 @@ static bool is_param_filtered(GBookmarksPanel *, const char *); static gboolean on_button_press_over_bookmarks(GtkWidget *, GdkEventButton *, GBookmarksPanel *); /* Construit le menu contextuel pour les signets. */ -GtkMenu *build_bookmarks_panel_menu(GBookmarksPanel *); +static GtkMenu *build_bookmarks_panel_menu(GBookmarksPanel *); /* Fournit le signet sélectionné dans la liste. */ static GDbBookmark *get_selected_panel_bookmark(GtkTreeView *, GtkTreeIter *); @@ -807,7 +807,7 @@ static gint compare_bookmarks_list_columns(GtkTreeModel *model, GtkTreeIter *a, result = (value_a == NULL ? -1 : 1); } else - result = g_utf8_collate(value_a,value_b); + result = g_utf8_collate(value_a, value_b); g_free(value_a); g_free(value_b); @@ -836,9 +836,6 @@ static gboolean on_key_pressed_over_params(GtkTreeView *treeview, GdkEventKey *e const gchar *accelerator; /* Combinaison de raccourci */ guint accel_key; /* Touche de raccourci */ GdkModifierType accel_mod; /* Modifiateurs attendus aussi */ - GtkTreeIter iter; /* Point de la sélection */ - GtkTreeModel *model; /* Gestionnaire de données */ - GtkTreePath *path; /* Chemin d'accès à ce point */ if (!g_generic_config_get_value(get_main_configuration(), MPK_KEYBINDINGS_EDIT, &accelerator)) return FALSE; @@ -849,22 +846,7 @@ static gboolean on_key_pressed_over_params(GtkTreeView *treeview, GdkEventKey *e gtk_accelerator_parse(accelerator, &accel_key, &accel_mod); if (event->keyval == accel_key && event->state == accel_mod) - { - /* FIXME : unref(result) */ - if (get_selected_panel_bookmark(treeview, &iter) != NULL) - { - model = gtk_tree_view_get_model(treeview); - path = gtk_tree_model_get_path(model, &iter); - - gtk_tree_view_set_cursor(treeview, path, - gtk_tree_view_get_column(treeview, BMC_COMMENT - BMC_PHYSICAL), - TRUE); - - gtk_tree_path_free(path); - - } - - } + mcb_bookmarks_panel_edit(NULL, panel); return FALSE; @@ -1112,7 +1094,7 @@ static gboolean on_button_press_over_bookmarks(GtkWidget *widget, GdkEventButton * * ******************************************************************************/ -GtkMenu *build_bookmarks_panel_menu(GBookmarksPanel *panel) +static GtkMenu *build_bookmarks_panel_menu(GBookmarksPanel *panel) { GtkWidget *result; /* Support à retourner */ GtkWidget *submenuitem; /* Sous-élément de menu */ diff --git a/src/gui/panels/regedit.c b/src/gui/panels/regedit.c index 3145385..a187a2d 100644 --- a/src/gui/panels/regedit.c +++ b/src/gui/panels/regedit.c @@ -127,7 +127,7 @@ static void on_param_value_edited(GtkCellRendererText *, gchar *, gchar *, GtkTr /* Démarre l'actualisation du filtrage des paramètres. */ static void on_param_search_changed(GtkSearchEntry *, GRegeditPanel *); -/*Détermine si un paramètre doit être filtré ou non. */ +/* Détermine si un paramètre doit être filtré ou non. */ static bool is_param_filtered(GRegeditPanel *, const char *); @@ -650,7 +650,7 @@ static gint compare_config_list_columns(GtkTreeModel *model, GtkTreeIter *a, Gtk result = (value_a == NULL ? -1 : 1); } else - result = g_utf8_collate(value_a,value_b); + result = g_utf8_collate(value_a, value_b); g_free(value_a); g_free(value_b); diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c index b68a0e8..f1397a8 100644 --- a/src/gui/panels/strings.c +++ b/src/gui/panels/strings.c @@ -26,10 +26,12 @@ #include +#include #include "panel-int.h" #include "../../common/extstr.h" +#include "../../core/params.h" #include "../../gtkext/easygtk.h" @@ -43,11 +45,11 @@ struct _GStringsPanel GPanelItem parent; /* A laisser en premier */ GtkTreeView *treeview; /* Composant d'affichage */ - GtkTreeStore *store; /* Modèle de gestion */ + regex_t *filter; /* Filtre appliqué ou NULL */ - GLoadedBinary *binary; /* Binaire à prendre en compte */ + GtkMenu *menu; /* Menu contextuel pour param. */ - GtkWidget *menubar; /* Support pour l'édition */ + GLoadedBinary *binary; /* Binaire en cours d'analyse */ }; @@ -63,9 +65,12 @@ struct _GStringsPanelClass /* Colonnes de la liste des symboles */ typedef enum _StringsColumn { - STC_ADDRESS, /* Adresse mémoire du symbole */ - STC_STRING, /* Désignation humaine */ - STC_RAW, /* Données non retouchées */ + STC_STRING, /* Elément GLib représenté */ + + STC_PHYSICAL, /* Adresse phyisque */ + STC_VIRTUAL, /* Adresse virtuelle */ + STC_NAME, /* Désignation humaine */ + STC_VALUE, /* Chaîne de caractères */ STC_COUNT /* Nombre de colonnes */ @@ -89,14 +94,57 @@ static void change_strings_panel_current_binary(GStringsPanel *, GLoadedBinary * -/* ------------------------- GESTIONS DES MENUS CONTEXTUELS ------------------------- */ -/* Affiche le menu d'édition propre aux chaînes trouvées. */ -static gboolean on_strings_button_press_event(GtkTreeView *, GdkEventButton *, GStringsPanel *); +/* ------------------------- AFFICHAGE A L'AIDE D'UNE LISTE ------------------------- */ + + +/* Réagit au changement de sélection des chaînes textuelles. */ +static void on_strings_selection_change(GtkTreeSelection *, GStringsPanel *); + +/* Etablit une comparaison entre deux chaînes de caractères. */ +static gint compare_strings_list_columns(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *, gpointer); + +/* Réagit à une pression sur et simule l'édition. */ +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 *); + + + +/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */ + + +/* Démarre l'actualisation du filtrage des paramètres. */ +static void on_string_search_changed(GtkSearchEntry *, GStringsPanel *); + +/* Détermine si une chaîne textuelle doit être filtrée ou non. */ +static bool is_string_filtered(GStringsPanel *, const char *, const char *); + + + +/* ------------------------ ATTRIBUTION D'UN MENU CONTEXTUEL ------------------------ */ + + +/* Assure la gestion des clics de souris sur les signets. */ +static gboolean on_button_press_over_strings(GtkWidget *, GdkEventButton *, GStringsPanel *); + +/* Construit le menu contextuel pour les signets. */ +static GtkMenu *build_strings_panel_menu(GStringsPanel *); + +/* Fournit le signet sélectionné dans la liste. */ +static GBinSymbol *get_selected_panel_symbol(GtkTreeView *, GtkTreeIter *); + +/* Réagit avec le menu "Editer le nom". */ +static void mcb_strings_panel_edit(GtkMenuItem *, GStringsPanel *); + +/* Réagit avec le menu "Copier dans le presse-papiers". */ +static void mcb_strings_panel_copy(GtkMenuItem *, GStringsPanel *); + +/* Réagit avec le menu "Filtrer...". */ +static void mcb_strings_panel_filter(GtkMenuItem *, GStringsPanel *); -/* Réagit avec le menu "--- -> Copier". */ -static void mcb_strings_copy(GtkMenuItem *, GtkTreeView *); @@ -154,67 +202,123 @@ static void g_strings_panel_init(GStringsPanel *panel) { GEditorItem *base; /* Version basique d'instance */ GObject *ref; /* Espace de référencement */ - GtkWidget *scrollwnd; /* Support défilant */ + GtkWidget *label; /* Etiquette à utiliser */ + GtkWidget *search; /* Zone de recherche */ + GtkWidget *scrolled; /* Fenêtre défilante */ GtkTreeStore *store; /* Modèle de gestion */ GtkWidget *treeview; /* Affichage de la liste */ GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ GtkTreeViewColumn *column; /* Colonne de la liste */ - GtkWidget *submenuitem; /* Sous-élément de menu */ + GtkTreeSortable *sortable; /* Autre vision de la liste */ + GtkTreeSelection *select; /* Sélection dans la liste */ base = G_EDITOR_ITEM(panel); - base->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + base->widget = gtk_grid_new(); gtk_widget_show(base->widget); + gtk_grid_set_row_spacing(GTK_GRID(base->widget), 8); + ref = G_OBJECT(base->widget); g_object_set_data(ref, "panel", panel); - /* Liste des chaînes */ + /* Partie recherche */ + + label = qck_create_label(NULL, NULL, _("Look for:")); + g_object_set(label, "margin", 8, NULL); + gtk_grid_attach(GTK_GRID(base->widget), label, 0, 0, 1, 1); + + search = gtk_search_entry_new(); + g_signal_connect(search, "search-changed", G_CALLBACK(on_string_search_changed), panel); + gtk_widget_show(search); + gtk_widget_set_hexpand(search, TRUE); + gtk_grid_attach_next_to(GTK_GRID(base->widget), search, label, GTK_POS_RIGHT, 1, 1); - scrollwnd = gtk_scrolled_window_new(NULL, NULL); - gtk_widget_show(scrollwnd); - gtk_box_pack_start(GTK_BOX(base->widget), scrollwnd, TRUE, TRUE, 0); + /* Partie paramètres */ - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN); + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrolled); + gtk_widget_set_vexpand(scrolled, TRUE); + gtk_grid_attach_next_to(GTK_GRID(base->widget), scrolled, label, GTK_POS_BOTTOM, 2, 1); - store = gtk_tree_store_new(STC_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - g_object_set_data(G_OBJECT(panel), "store", store); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); + + store = gtk_tree_store_new(STC_COUNT, G_TYPE_OBJECT, + 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_press_over_strings), panel); + g_signal_connect(G_OBJECT(treeview), "key-press-event", + G_CALLBACK(on_key_pressed_over_strings), panel); + gtk_widget_show(treeview); - gtk_container_add(GTK_CONTAINER(scrollwnd), treeview); + gtk_container_add(GTK_CONTAINER(scrolled), treeview); g_object_unref(G_OBJECT(store)); - column = gtk_tree_view_column_new(); + /* Cellules d'affichage */ + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Physical address"), renderer, + "text", STC_PHYSICAL, + NULL); + gtk_tree_view_column_set_sort_column_id(column, STC_PHYSICAL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column); renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("Address"), renderer, - "text", STC_ADDRESS, NULL); + column = gtk_tree_view_column_new_with_attributes(_("Virtual address"), renderer, + "text", STC_VIRTUAL, + NULL); + gtk_tree_view_column_set_sort_column_id(column, STC_VIRTUAL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("String"), renderer, - "markup", STC_STRING, NULL); + g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL); + g_signal_connect(renderer, "edited", G_CALLBACK(on_string_value_edited), store); + column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, + "text", STC_NAME, + NULL); + gtk_tree_view_column_set_sort_column_id(column, STC_NAME); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - /* Menu contextuel */ + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Value"), renderer, + "markup", STC_VALUE, + NULL); + gtk_tree_view_column_set_sort_column_id(column, STC_VALUE); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - panel->menubar = gtk_menu_new(); + /* Tri de la liste */ - submenuitem = qck_create_menu_item(NULL, NULL, _("_Copy"), - G_CALLBACK(mcb_strings_copy), treeview); - gtk_container_add(GTK_CONTAINER(panel->menubar), submenuitem); + sortable = GTK_TREE_SORTABLE(store); - submenuitem = qck_create_menu_item(NULL, NULL, _("_Find references..."), NULL, NULL); - gtk_container_add(GTK_CONTAINER(panel->menubar), submenuitem); + gtk_tree_sortable_set_sort_func(sortable, STC_PHYSICAL, compare_strings_list_columns, + GINT_TO_POINTER(STC_PHYSICAL), NULL); + + gtk_tree_sortable_set_sort_func(sortable, STC_VIRTUAL, compare_strings_list_columns, + GINT_TO_POINTER(STC_VIRTUAL), NULL); + + gtk_tree_sortable_set_sort_func(sortable, STC_NAME, compare_strings_list_columns, + GINT_TO_POINTER(STC_NAME), NULL); + + gtk_tree_sortable_set_sort_func(sortable, STC_VALUE, compare_strings_list_columns, + GINT_TO_POINTER(STC_VALUE), NULL); - g_signal_connect(G_OBJECT(treeview), "button_release_event", - G_CALLBACK(on_strings_button_press_event), panel); + gtk_tree_sortable_set_sort_column_id(sortable, STC_VIRTUAL, GTK_SORT_ASCENDING); + + /* Prise en compte de la sélection */ + + select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); + gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); + g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(on_strings_selection_change), panel); + + /* Préparation du menu contextuel */ + + panel->menu = build_strings_panel_menu(panel); } @@ -312,6 +416,12 @@ GPanelItem *create_strings_panel(GObject *ref) } + +/* ---------------------------------------------------------------------------------- */ +/* AFFICHAGE A L'AIDE D'UNE LISTE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : panel = panneau à mettre à jour. * @@ -328,12 +438,19 @@ GPanelItem *create_strings_panel(GObject *ref) 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 */ + GBinContent *content; /* Contenu binaire en mémoire */ size_t count; /* Nombre des chaînes */ GBinSymbol **symbols; /* Liste des chaînes trouvées */ size_t i; /* Boucle de parcours */ - char address[VMPA_MAX_SIZE]; /* Conversion de l'adresse */ - const char *raw; /* Texte brut trouvé */ + 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 */ + 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 */ @@ -347,23 +464,52 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin 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 */ - store = g_object_get_data(G_OBJECT(panel), "store"); + 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); + content = g_binary_format_get_conten_(G_BIN_FORMAT(format)); + symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &count); for (i = 0; i < count; i++) { - if (g_binary_symbol_get_target_type(symbols[i]) != STP_STRING) continue; + if (g_binary_symbol_get_target_type(symbols[i]) != STP_RO_STRING) continue; + + range = g_binary_symbol_get_range(symbols[i]); + addr = get_mrange_addr(range); + + vmpa2_phys_to_string(addr, msize, phys, NULL); + vmpa2_virt_to_string(addr, msize, virt, NULL); - /* FIXME : adresses autres que 32 bits */ - snprintf(address, VMPA_MAX_SIZE, "0x%08" PRIx64, g_binary_symbol_get_address(symbols[i])); + label = g_binary_symbol_get_label(symbols[i]); - raw = g_binary_symbol_to_string(symbols[i]); + text = (char *)calloc(get_mrange_length(range) + 1, sizeof(char)); + + copy_vmpa(&pos, addr); + + if (!g_binary_content_get_raw(content, &pos, get_mrange_length(range), (uint8_t *)text)) + { + free(text); + continue; + } + + if (is_string_filtered(panel, label, text)) + { + free(text); + continue; + } - text = strdup(raw); text = strrpl(text, "&", "&"); text = strrpl(text, "<", "<"); text = strrpl(text, ">", ">"); @@ -372,9 +518,11 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_set(store, &iter, - STC_ADDRESS, address, - STC_STRING, text, - STC_RAW, raw, + STC_STRING, symbols[i], + STC_PHYSICAL, phys, + STC_VIRTUAL, virt, + STC_NAME, label, + STC_VALUE, text, -1); free(text); @@ -384,19 +532,92 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin } +/****************************************************************************** +* * +* Paramètres : selection = sélection modifiée. * +* panel = structure contenant les informations maîtresses. * +* * +* Description : Réagit au changement de sélection des chaînes textuelles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_strings_selection_change(GtkTreeSelection *selection, GStringsPanel *panel) +{ + GtkTreeIter iter; /* Point de sélection */ + GtkTreeModel *model; /* Modèle de gestion */ + GBinSymbol *symbol; /* Symbole en cours d'étude */ + const vmpa2t *addr; /* Adressse associée au signet */ + GtkViewPanel *vpanel; /* Afficheur effectif de code */ -/* ---------------------------------------------------------------------------------- */ -/* GESTIONS DES MENUS CONTEXTUELS */ -/* ---------------------------------------------------------------------------------- */ + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_tree_model_get(model, &iter, STC_STRING, &symbol, -1); + + addr = get_mrange_addr(g_binary_symbol_get_range(symbol)); + + vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); + gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER); + + g_object_unref(G_OBJECT(symbol)); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : model = gestionnaire du tableau de données. * +* a = première ligne de données à traiter. * +* b = seconde ligne de données à traiter. * +* column = indice de la colonne à considérer, encodée. * +* * +* Description : Etablit une comparaison entre deux chaînes de caractères. * +* * +* Retour : Indication de tri entre les deux lignes fournies. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gint compare_strings_list_columns(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer column) +{ + gint result; /* Valeur calculée à retourner */ + gchar *value_a; /* Cellule de la ligne 'a' */ + gchar *value_b; /* Cellule de la ligne 'b' */ + + gtk_tree_model_get(model, a, GPOINTER_TO_INT(column), &value_a, -1); + gtk_tree_model_get(model, b, GPOINTER_TO_INT(column), &value_b, -1); + + if (value_a == NULL || value_b == NULL) + { + if (value_a == NULL && value_b == NULL) + result = 0; + else + result = (value_a == NULL ? -1 : 1); + } + else + result = g_utf8_collate(value_a, value_b); + + g_free(value_a); + g_free(value_b); + + return result; + +} /****************************************************************************** * * -* Paramètres : treeview = composant GTK visé par l'opération. * +* Paramètres : treeview = composant graphique présentant les paramètres. * * event = informations liées à l'événement. * -* data = référence vers le panneau contenant le menu. * +* panel = panneau d'affichage sur lequel s'appuyer. * * * -* Description : Affiche le menu d'édition propre aux chaînes trouvées. * +* Description : Réagit à une pression sur et simule l'édition. * * * * Retour : FALSE pour poursuivre la propagation de l'événement. * * * @@ -404,22 +625,302 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin * * ******************************************************************************/ -static gboolean on_strings_button_press_event(GtkTreeView *treeview, GdkEventButton *event, GStringsPanel *panel) +static gboolean on_key_pressed_over_strings(GtkTreeView *treeview, GdkEventKey *event, GStringsPanel *panel) +{ + const gchar *accelerator; /* Combinaison de raccourci */ + guint accel_key; /* Touche de raccourci */ + GdkModifierType accel_mod; /* Modifiateurs attendus aussi */ + + if (!g_generic_config_get_value(get_main_configuration(), MPK_KEYBINDINGS_EDIT, &accelerator)) + return FALSE; + + if (accelerator == NULL) + return FALSE; + + gtk_accelerator_parse(accelerator, &accel_key, &accel_mod); + + if (event->keyval == accel_key && event->state == accel_mod) + mcb_strings_panel_edit(NULL, panel); + + return FALSE; + +} + + +/****************************************************************************** +* * +* 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. * +* * +* Description : Réagit à une édition de l'étiquette d'une chaîne textuelle. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_string_value_edited(GtkCellRendererText *renderer, gchar *path, gchar *new, GtkTreeStore *store) +{ + GtkTreePath *tree_path; /* Chemin d'accès natif */ + GtkTreeIter iter; /* Point de la modification */ + GBinSymbol *symbol; /* Symbole à actualiser */ + + 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)) + goto opve_bad_iter; + + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, STC_STRING, &symbol, -1); + + g_binary_symbol_set_label(symbol, new); + + g_object_unref(G_OBJECT(symbol)); + + opve_bad_iter: + + gtk_tree_path_free(tree_path); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* FILTRAGE DES SYMBOLES PRESENTS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : entry = entrée de texte contenant le filtre brut. * +* panel = panneau assurant l'affichage des paramètres. * +* * +* Description : Démarre l'actualisation du filtrage des paramètres. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_string_search_changed(GtkSearchEntry *entry, GStringsPanel *panel) { - gboolean result; /* Bilan d'action à renvoyer */ + const gchar *text; /* Texte de l'utilisateur */ + int ret; /* Bilan de mise en place */ + GdkRGBA error; /* Couleur d'erreur */ + + if (panel->filter != NULL) + { + regfree(panel->filter); + free(panel->filter); + panel->filter = NULL; + } - result = FALSE; + text = gtk_entry_get_text(GTK_ENTRY(entry)); - if (event->type == GDK_BUTTON_RELEASE && event->button == 3) + if (strlen(text) > 0) { - gtk_menu_popup(GTK_MENU(panel->menubar), - NULL, NULL, NULL, NULL, - event->button, event->time); + panel->filter = (regex_t *)calloc(1, sizeof(regex_t)); + ret = regcomp(panel->filter, text, REG_EXTENDED); + + if (ret != 0) + { + free(panel->filter); + panel->filter = NULL; + + error.red = 1.0; + error.green = 0.0; + error.blue = 0.0; + error.alpha = 1.0; + gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error); + + return; + + } + + } + + gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL); + + change_strings_panel_current_binary(panel, panel->binary); + +} + + +/****************************************************************************** +* * +* 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. * +* * +* Description : Détermine si une chaîne textuelle doit être filtrée ou non. * +* * +* Retour : true si le symbole ne doit pas être affiché, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_string_filtered(GStringsPanel *panel, const char *label, const char *value) +{ + bool result; /* Bilan à retourner */ + regmatch_t match; /* Récupération des trouvailles*/ + int ret; /* Bilan du filtrage */ - result = TRUE; + if (panel->filter == NULL) + return false; + result = false; + + if (label != NULL) + { + ret = regexec(panel->filter, label, 1, &match, 0); + result |= (ret != REG_NOMATCH); } + ret = regexec(panel->filter, value, 1, &match, 0); + result |= (ret != REG_NOMATCH); + + return !result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* ATTRIBUTION D'UN MENU CONTEXTUEL */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK visé par l'opération. * +* event = informations liées à l'événement. * +* panel = informations liées au panneau associé. * +* * +* Description : Assure la gestion des clics de souris sur les signets. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean on_button_press_over_strings(GtkWidget *widget, GdkEventButton *event, GStringsPanel *panel) +{ + GtkTreeSelection *selection; /* Sélection courante */ + GtkTreeIter iter; /* Point de sélection */ + GtkTreeModel *model; /* Modèle de gestion */ + GBinSymbol *symbol; /* Symbole en cours d'étude */ + const vmpa2t *addr; /* Adressse associée au signet */ + GtkViewPanel *vpanel; /* Afficheur effectif de code */ + + switch (event->button) + { + case 1: + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_tree_model_get(model, &iter, STC_STRING, &symbol, -1); + + addr = get_mrange_addr(g_binary_symbol_get_range(symbol)); + + vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); + gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER); + + g_object_unref(G_OBJECT(symbol)); + + } + + break; + + case 3: + if (event->type == GDK_BUTTON_RELEASE) + gtk_menu_popup(panel->menu, NULL, NULL, NULL, NULL, event->button, event->time); + break; + + } + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau d'affichage des signets liés à un binaire. * +* * +* Description : Construit le menu contextuel pour les signets. * +* * +* Retour : Panneau de menus mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GtkMenu *build_strings_panel_menu(GStringsPanel *panel) +{ + GtkWidget *result; /* Support à retourner */ + GtkWidget *submenuitem; /* Sous-élément de menu */ + + result = gtk_menu_new(); + + submenuitem = qck_create_menu_item(NULL, NULL, _("_Edit name"), NULL, NULL); + gtk_container_add(GTK_CONTAINER(result), submenuitem); + + submenuitem = qck_create_menu_item(NULL, NULL, _("_Copy to clipboard"), + G_CALLBACK(mcb_strings_panel_copy), panel); + gtk_container_add(GTK_CONTAINER(result), submenuitem); + + submenuitem = qck_create_menu_item(NULL, NULL, _("_Find references..."), NULL, NULL); + gtk_container_add(GTK_CONTAINER(result), submenuitem); + + submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(result), submenuitem); + + submenuitem = qck_create_menu_item(NULL, NULL, _("Filter..."), G_CALLBACK(mcb_strings_panel_filter), panel); + gtk_container_add(GTK_CONTAINER(result), submenuitem); + + return GTK_MENU(result); + +} + + +/****************************************************************************** +* * +* Paramètres : treeview = liste d'affichage à consulter. * +* save = zone de conservation du point de trouvaille. [OUT]* +* * +* Description : Fournit le signet sélectionné dans la liste. * +* * +* Retour : Signet en cours d'édition ou NULL en cas de soucis. * +* * +* Remarques : Le résultat non nul est à déréférencer après usage. * +* * +******************************************************************************/ + +static GBinSymbol *get_selected_panel_symbol(GtkTreeView *treeview, GtkTreeIter *save) +{ + GBinSymbol *result; /* Chaîne textuelle à renvoyer */ + GtkTreeSelection *selection; /* Représentation de sélection */ + GtkTreeModel *model; /* Gestionnaire des données */ + GtkTreeIter iter; /* Point de la sélection */ + + result = NULL; + + 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); + + if (save != NULL) + *save = iter; + return result; } @@ -428,9 +929,46 @@ static gboolean on_strings_button_press_event(GtkTreeView *treeview, GdkEventBut /****************************************************************************** * * * Paramètres : menuitem = élément de menu sélectionné. * +* panel = panneau d'affichage des signets liés à un binaire.* +* * +* Description : Réagit avec le menu "Editer le nom". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_strings_panel_edit(GtkMenuItem *menuitem, GStringsPanel *panel) +{ + GtkTreeIter iter; /* Point de la sélection */ + GBinSymbol *symbol; /* Symbole sélectionné */ + GtkTreeModel *model; /* Gestionnaire de données */ + GtkTreePath *path; /* Chemin d'accès à ce point */ + + symbol = get_selected_panel_symbol(panel->treeview, &iter); + if (symbol == NULL) return; + + model = gtk_tree_view_get_model(panel->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), + TRUE); + + gtk_tree_path_free(path); + + g_object_unref(G_OBJECT(symbol)); + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * * treeview = arbre contenant la sélection à exporter. * * * -* Description : Réagit avec le menu "--- -> Copier". * +* Description : Réagit avec le menu "Copier dans le presse-papiers". * * * * Retour : - * * * @@ -438,7 +976,7 @@ static gboolean on_strings_button_press_event(GtkTreeView *treeview, GdkEventBut * * ******************************************************************************/ -static void mcb_strings_copy(GtkMenuItem *menuitem, GtkTreeView *treeview) +static void mcb_strings_panel_copy(GtkMenuItem *menuitem, GStringsPanel *panel) { GtkTreeSelection *selection; /* Sélection de l'arbre */ GtkTreeIter iter; /* Point de sélection */ @@ -446,11 +984,11 @@ static void mcb_strings_copy(GtkMenuItem *menuitem, GtkTreeView *treeview) gchar *string; /* Chaîne sélectionnée */ GtkClipboard *clipboard; /* Presse-papiers d'arrivée */ - selection = gtk_tree_view_get_selection(treeview); + selection = gtk_tree_view_get_selection(panel->treeview); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - gtk_tree_model_get(model, &iter, STC_RAW, &string, -1); + gtk_tree_model_get(model, &iter, STC_VALUE, &string, -1); if (string != NULL) { @@ -465,3 +1003,31 @@ static void mcb_strings_copy(GtkMenuItem *menuitem, GtkTreeView *treeview) } } + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* panel = panneau d'affichage des signets liés à un binaire.* +* * +* Description : Réagit avec le menu "Filtrer...". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +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); + if (param == NULL) return; + + g_config_param_make_empty(param); + + g_object_unref(G_OBJECT(param)); +#endif +} -- cgit v0.11.2-87-g4458