summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-09-28 21:43:18 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-09-28 21:43:18 (GMT)
commit7b99c255f7b5a6cd82196d8ae396b5cf991f9784 (patch)
treec0ae708dc13910832cb3577400926062c2bd6157
parent34db987b49ae8135f4ad41ec0012c86ede0c9f4c (diff)
Updated and improved the symbols panel.
-rw-r--r--ChangeLog5
-rw-r--r--src/gui/panels/symbols.c236
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 <nocbos@gmail.com>
+
+ * src/gui/panels/symbols.c:
+ Update and improve the symbols panel.
+
16-09-27 Cyrille Bagard <nocbos@gmail.com>
* 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, "<", "&lt;");
+ }
+
+ /* 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, "<", "&lt;");
+ }
+ else
+ result = NULL;
+
+ result = stradd(result, "<b>");
+
+ valid = strndup(&raw[selection.rm_so], selection.rm_eo - selection.rm_so);
+ valid = strrpl(valid, "<", "&lt;");
+
+ result = stradd(result, valid);
+
+ free(valid);
+
+ result = stradd(result, "</b>");
+
+ valid = strdup(&raw[selection.rm_eo]);
+ valid = strrpl(valid, "<", "&lt;");
+
+ result = stradd(result, valid);
+
+ free(valid);
+
+ }
+
+ return result;
+
+}