From 7b99c255f7b5a6cd82196d8ae396b5cf991f9784 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 28 Sep 2016 23:43:18 +0200 Subject: Updated and improved the symbols panel. --- ChangeLog | 5 + src/gui/panels/symbols.c | 236 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 190 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 848a371..00d6f56 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +16-09-28 Cyrille Bagard + + * src/gui/panels/symbols.c: + Update and improve the symbols panel. + 16-09-27 Cyrille Bagard * src/gui/menus/binary.c: diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c index d1bca91..0cbb9eb 100644 --- a/src/gui/panels/symbols.c +++ b/src/gui/panels/symbols.c @@ -37,6 +37,7 @@ #include "panel-int.h" +#include "../../common/extstr.h" #include "../../format/format.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/support.h" @@ -79,6 +80,7 @@ typedef enum _SymbolsColumn SBC_PICTURE, /* Image de représentation */ SBC_NAME, /* Désignation humaine */ + SBC_ORIGINAL, /* Version brute d'origine */ SBC_ADDRESS, /* Adresse mémoire du symbole */ SBC_SECTION, /* Section d'appartenance */ @@ -124,11 +126,11 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *); /* S'assure qu'un noeud donné existe bien. */ -#if 0 -static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *, GtkTreeIter *, const char *); -#endif + +static GtkTreeIter ensure_symbol_node_exist(GSymbolsPanel *, GtkTreeIter *, const char *, const regmatch_t *, size_t); + /* Détermine le point d'insertion parent d'une routine. */ -static bool find_parent_for_symbol(GtkTreeStore *, const GBinSymbol *, GtkTreeIter *); +static bool find_parent_for_symbol(GSymbolsPanel *, const GBinSymbol *, GtkTreeIter *, const regmatch_t *, size_t *); /* Réagit à un changement d'affichage principal de contenu. */ static void reload_symbols_for_new_tree_view(GSymbolsPanel *); @@ -151,7 +153,10 @@ static void on_symbols_filter_changed(GtkSearchEntry *, GSymbolsPanel *); static void do_filtering_on_symbols(GSymbolsPanel *); /* Détermine si un nom de symbole doit être filtré ou non. */ -static bool is_symbol_filtered(GSymbolsPanel *, const GBinSymbol *); +static bool is_symbol_filtered(GSymbolsPanel *, const GBinSymbol *, regmatch_t *); + +/* Met en évidence le texte recherché en cas de correspondance. */ +static char *build_highlighted_name(const char *, const regmatch_t *, size_t); @@ -338,7 +343,7 @@ static void g_symbols_panel_init(GSymbolsPanel *panel) gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN); panel->store = gtk_tree_store_new(SBC_COUNT, G_TYPE_OBJECT, CAIRO_GOBJECT_TYPE_SURFACE, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(panel->store)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); @@ -353,17 +358,18 @@ static void g_symbols_panel_init(GSymbolsPanel *panel) /* Cellules d'affichage */ + column = gtk_tree_view_column_new(); + renderer = gtk_cell_renderer_pixbuf_new(); - column = gtk_tree_view_column_new_with_attributes("", renderer, - "surface", SBC_PICTURE, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + gtk_tree_view_column_pack_start(column, renderer, FALSE); + gtk_tree_view_column_add_attribute(column, renderer, "surface", SBC_PICTURE); renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, - "text", SBC_NAME, - NULL); + gtk_tree_view_column_pack_start(column, renderer, TRUE); + gtk_tree_view_column_add_attribute(column, renderer, "markup", SBC_NAME); gtk_tree_view_column_set_sort_column_id(column, SBC_NAME); + + gtk_tree_view_column_set_title(column, _("Name")); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); renderer = gtk_cell_renderer_text_new(); @@ -550,12 +556,16 @@ static void on_symbols_selection_change(GtkTreeSelection *selection, GSymbolsPan { gtk_tree_model_get(model, &iter, SBC_SYMBOL, &symbol, -1); - range = g_binary_symbol_get_range(symbol); + if (symbol != NULL) + { + range = g_binary_symbol_get_range(symbol); + + vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); + gtk_view_panel_request_move(vpanel, get_mrange_addr(range)); - vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); - gtk_view_panel_request_move(vpanel, get_mrange_addr(range)); + g_object_unref(G_OBJECT(symbol)); - g_object_unref(G_OBJECT(symbol)); + } } @@ -632,7 +642,10 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) GArchProcessor *proc; /* Architecture utilisée */ MemoryDataSize size; /* Taille des localisations */ size_t i; /* Boucle de parcours */ + regmatch_t match; /* Récupération des trouvailles*/ cairo_surface_t *icon; /* Image associée au symbole */ + const char *original; /* Etiquette brute d'origine */ + char *name; /* Etiquette mise en relief */ const vmpa2t *addr; /* Localisation d'un symbole */ char virt[VMPA_MAX_LEN]; /* Version humainement lisible */ GtkTreeIter iter; /* Point d'insertion */ @@ -647,7 +660,7 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) for (i = 0; i < sym_count; i++) { - if (is_symbol_filtered(panel, symbols[i])) + if (is_symbol_filtered(panel, symbols[i], &match)) continue; switch (g_binary_symbol_get_target_type(symbols[i])) @@ -664,6 +677,9 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) break; } + original = g_binary_symbol_get_label(symbols[i]); + name = build_highlighted_name(original, &match, 0); + addr = get_mrange_addr(g_binary_symbol_get_range(symbols[i])); vmpa2_virt_to_string(addr, size, virt, NULL); @@ -671,10 +687,13 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) gtk_tree_store_set(panel->store, &iter, SBC_SYMBOL, symbols[i], SBC_PICTURE, icon, - SBC_NAME, g_binary_symbol_get_label(symbols[i]), + SBC_NAME, name, + SBC_ORIGINAL, original, SBC_ADDRESS, virt, -1); + free(name); + } } @@ -688,9 +707,11 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) /****************************************************************************** * * -* Paramètres : store = gestion des différents éléments insérés. * +* Paramètres : panel = panneau en cours de mise à jour. * * parent = point d'insertion parent à retrouver. [OUT] * -* name = nom du noeud ciblé. * +* raw = nom du noeud ciblé. * +* match = portion de texte à mettre en évidence. * +* start = position du texte brute dans l'étiquette complète. * * * * Description : S'assure qu'un noeud donné existe bien. * * * @@ -699,21 +720,24 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) * Remarques : - * * * ******************************************************************************/ -#if 0 -static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *store, GtkTreeIter *parent, const char *name) + +static GtkTreeIter ensure_symbol_node_exist(GSymbolsPanel *panel, GtkTreeIter *parent, const char *raw, const regmatch_t *match, size_t start) { + GtkTreeStore *store; /* Gestionnaire de données */ bool found; /* Bilan des recherches */ GtkTreeIter iter; /* Boucle de parcours */ gchar *string; /* Chaîne sélectionnée */ - cairo_surface_t *icon; /* Image associée au symbole */ + char *name; /* Etiquette mise en relief */ + + store = panel->store; found = false; if (gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, parent)) do { - gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, SBC_NAME, &string, -1); - found = (strcmp(string, name) == 0); + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, SBC_ORIGINAL, &string, -1); + found = (strcmp(string, raw) == 0); g_free(string); if (found) break; @@ -723,23 +747,31 @@ static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *store, GtkTreeIter *pa if (!found) { + name = build_highlighted_name(raw, match, start); + gtk_tree_store_append(store, &iter, parent); gtk_tree_store_set(store, &iter, SBC_PICTURE, G_SYMBOLS_PANEL_GET_CLASS(panel)->package_img, SBC_NAME, name, + SBC_ORIGINAL, raw, -1); + + free(name); + } return iter; } -#endif + /****************************************************************************** * * -* Paramètres : store = gestion des différents éléments insérés. * +* Paramètres : panel = panneau en cours de mise à jour. * * symbol = routine ou objet à intégrer. * -* parent = point d'insertion parent à constituer. * +* parent = point d'insertion parent à constituer. [OUT] * +* match = portion de texte à mettre en évidence. * +* last = position du dernier élément du nom de symbole. [OUT]* * * * Description : Détermine le point d'insertion parent d'une routine. * * * @@ -749,33 +781,41 @@ static GtkTreeIter ensure_symbol_node_exist(GtkTreeStore *store, GtkTreeIter *pa * * ******************************************************************************/ -static bool find_parent_for_symbol(GtkTreeStore *store, const GBinSymbol *symbol, GtkTreeIter *parent) +static bool find_parent_for_symbol(GSymbolsPanel *panel, const GBinSymbol *symbol, GtkTreeIter *parent, const regmatch_t *match, size_t *last) { -#if 0 - GDataType *namespace; /* Espace d'appartenance */ - char *string; /* Conversion en chaîne */ - char *iter; /* Boucle de parcours */ + const char *label; /* Etiquette immuable */ + char *string; /* Etiquette modifiable */ + const char *sep; /* Délimitateur à utiliser */ + char *start; /* Début de boucle de parcours */ char *token; /* Partie de texte isolée */ char *saveptr; /* Ctx. interne de découpage */ + char *next; /* Prochaine partie à traiter */ + + *last = 0; - namespace = g_binary_routine_get_namespace(routine); - if (namespace == NULL) return false; + label = g_binary_symbol_get_label(symbol); + if (label == NULL) return false; - string = g_data_type_to_string(namespace); + string = strdup(label); - for (iter = string; ; iter = NULL) + sep = "."/*"::"*/; /* FIXME */ + + for (start = string, token = strtok_r(start, sep, &saveptr); ; start = NULL, token = next) { - token = strtok_r(iter, "::", &saveptr); - if (token == NULL) break; + next = strtok_r(NULL, sep, &saveptr); + if (next == NULL) + { + *last = (token - string); + break; + } - *parent = ensure_symbol_node_exist(store, (iter == string ? NULL : parent), token); + *parent = ensure_symbol_node_exist(panel, (start == string ? NULL : parent), token, match, token - string); } - return true; -#endif + free(string); - return false; + return true; } @@ -800,8 +840,12 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) GArchProcessor *proc; /* Architecture utilisée */ MemoryDataSize size; /* Taille des localisations */ size_t i; /* Boucle de parcours */ + regmatch_t match; /* Récupération des trouvailles*/ GtkTreeIter parent; /* Point d'insertion parent */ + size_t last; /* Position du dernier élément */ cairo_surface_t *icon; /* Image associée au symbole */ + const char *original; /* Etiquette brute d'origine */ + char *name; /* Etiquette mise en relief */ const vmpa2t *addr; /* Localisation d'un symbole */ char virt[VMPA_MAX_LEN]; /* Version humainement lisible */ GtkTreeIter iter; /* Point d'insertion */ @@ -816,10 +860,10 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) for (i = 0; i < sym_count; i++) { - if (is_symbol_filtered(panel, symbols[i])) + if (is_symbol_filtered(panel, symbols[i], &match)) continue; - if (find_parent_for_symbol(panel->store, symbols[i], &parent)) + if (find_parent_for_symbol(panel, symbols[i], &parent, &match, &last)) { gtk_tree_store_set(panel->store, &parent, SBC_PICTURE, G_SYMBOLS_PANEL_GET_CLASS(panel)->class_img, @@ -846,16 +890,22 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) break; } + original = g_binary_symbol_get_label(symbols[i]); + name = build_highlighted_name(original + last, &match, last); + addr = get_mrange_addr(g_binary_symbol_get_range(symbols[i])); vmpa2_virt_to_string(addr, size, virt, NULL); gtk_tree_store_set(panel->store, &iter, SBC_SYMBOL, symbols[i], SBC_PICTURE, icon, - SBC_NAME, g_binary_symbol_get_label(symbols[i]), + SBC_NAME, name, + SBC_ORIGINAL, original + last, SBC_ADDRESS, virt, -1); + free(name); + } } @@ -969,7 +1019,7 @@ static void on_symbols_filter_changed(GtkSearchEntry *entry, GSymbolsPanel *pane if (strlen(text) > 0) { panel->filter = (regex_t *)calloc(1, sizeof(regex_t)); - ret = regcomp(panel->filter, text, REG_EXTENDED); + ret = regcomp(panel->filter, text, REG_EXTENDED | REG_ICASE); if (ret != 0) { @@ -1020,6 +1070,7 @@ static void do_filtering_on_symbols(GSymbolsPanel *panel) * * * Paramètres : panel = panneau assurant l'affichage des symboles. * * symbol = symbole à traiter. * +* match = récupération des trouvailles. [OUT] * * * * Description : Détermine si un nom de symbole doit être filtré ou non. * * * @@ -1029,10 +1080,9 @@ static void do_filtering_on_symbols(GSymbolsPanel *panel) * * ******************************************************************************/ -static bool is_symbol_filtered(GSymbolsPanel *panel, const GBinSymbol *symbol) +static bool is_symbol_filtered(GSymbolsPanel *panel, const GBinSymbol *symbol, regmatch_t *match) { SymbolType type; /* Type associé au symbole */ - regmatch_t match; /* Récupération des trouvailles*/ int ret; /* Bilan du filtrage */ type = g_binary_symbol_get_target_type(symbol); @@ -1040,13 +1090,97 @@ static bool is_symbol_filtered(GSymbolsPanel *panel, const GBinSymbol *symbol) if (type != STP_ROUTINE && type != STP_ENTRY_POINT && type != STP_OBJECT) return true; + memset(match, 0, sizeof(regmatch_t)); + if (panel->filter == NULL) return false; - ret = regexec(panel->filter, g_binary_symbol_get_label(symbol), 1, &match, 0); + ret = regexec(panel->filter, g_binary_symbol_get_label(symbol), 1, match, 0); if (ret == REG_NOMATCH) return true; return false; } + + +/****************************************************************************** +* * +* Paramètres : raw = bribe de texte à traiter. * +* match = portion de texte à mettre en évidence. * +* start = position du texte brute dans l'étiquette complète. * +* * +* Description : Met en évidence le texte recherché en cas de correspondance. * +* * +* Retour : Texte final destiné à être inséré, à libérer après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *build_highlighted_name(const char *raw, const regmatch_t *match, size_t start) +{ + char *result; /* Construction à retourner */ + size_t len; /* Taille du texte d'entrée */ + regmatch_t selection; /* Sélection relative au texte */ + char *valid; /* Retouche partielle */ + + len = strlen(raw); + + /* Si aucune sélection ou texte hors champ... */ + + if ((match->rm_eo - match->rm_so) == 0 || (start + len) <= match->rm_so || match->rm_eo < start) + { + result = strdup(raw); + result = strrpl(result, "<", "<"); + } + + /* Sinon, il y a forcément correspondance quelque part ! */ + + else + { + /* Adaptations */ + + if (match->rm_so < start) + selection.rm_so = 0; + else + selection.rm_so = match->rm_so - start; + + selection.rm_eo = match->rm_eo - start; + + if (selection.rm_eo > len) + selection.rm_eo = len; + + /* Impressions */ + + if (selection.rm_so > 0) + { + result = strndup(raw, selection.rm_so); + result = strrpl(result, "<", "<"); + } + else + result = NULL; + + result = stradd(result, ""); + + valid = strndup(&raw[selection.rm_so], selection.rm_eo - selection.rm_so); + valid = strrpl(valid, "<", "<"); + + result = stradd(result, valid); + + free(valid); + + result = stradd(result, ""); + + valid = strdup(&raw[selection.rm_eo]); + valid = strrpl(valid, "<", "<"); + + result = stradd(result, valid); + + free(valid); + + } + + return result; + +} -- cgit v0.11.2-87-g4458