summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-05-06 00:07:18 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-05-06 00:07:18 (GMT)
commitd76e89e102aacfe945b44eb3150cb9f4bbf7b613 (patch)
tree7dda55fabeddcd0dbd1813d9ceef4b905a056c7f /src
parent2c6e4f3f3f15d1568e9dae407e32a217d8f7ab19 (diff)
Displayed a tooltip for strings or code symbols in buffer views.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@530 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src')
-rw-r--r--src/analysis/binary.c2
-rw-r--r--src/arch/vmpa.c43
-rw-r--r--src/arch/vmpa.h3
-rw-r--r--src/dialogs/gotox.c2
-rw-r--r--src/format/format.c46
-rw-r--r--src/format/format.h3
-rw-r--r--src/glibext/gcodebuffer.c109
-rw-r--r--src/glibext/gcodebuffer.h8
-rw-r--r--src/gtkext/gtkbufferview.c150
9 files changed, 353 insertions, 13 deletions
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index cf01e16..b0712fd 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -850,7 +850,7 @@ static void on_binary_bookmarks_change(GDbCollection *collec, DBAction action, G
addr = g_db_bookmark_get_address(bookmark);
- line = g_code_buffer_find_line_by_addr(binary->disass_buffer, addr);
+ line = g_code_buffer_find_line_by_addr(binary->disass_buffer, addr, BLF_HAS_CODE, NULL);
if (line != NULL)
{
diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c
index 67be9a9..ad4c078 100644
--- a/src/arch/vmpa.c
+++ b/src/arch/vmpa.c
@@ -842,6 +842,49 @@ bool mrange_contains_addr(const mrange_t *range, const vmpa2t *addr)
/******************************************************************************
* *
* Paramètres : range = zone mémoire à consulter. *
+* addr = localisation mémoire à analyser. *
+* *
+* Description : Indique si une localisation est incluse dans une zone ou non.*
+* *
+* Retour : Bilan de la consultation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool mrange_contains_addr_inclusive(const mrange_t *range, const vmpa2t *addr)
+{
+ bool result; /* Bilan à retourner */
+ int ret; /* Bilan d'une comparaison */
+ phys_t diff; /* Espace entre deux adresses */
+
+ ret = cmp_vmpa(&range->addr, addr);
+
+ if (ret <= -1)
+ {
+ diff = compute_vmpa_diff(&range->addr, addr);
+
+ if (diff != VMPA_NO_PHYSICAL)
+ result = (diff <= range->length);
+ else
+ result = false;
+
+ }
+
+ else if (ret == 0)
+ result = true;
+
+ else
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = zone mémoire à consulter. *
* addr = localisation mémoire à déterminer. *
* *
* Description : Calcule la position extérieure final d'une couverture. *
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index 675d5cb..3e0d35c 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -187,6 +187,9 @@ bool mrange_contains_mrange(const mrange_t *, const mrange_t *);
/* Indique si une localisation est incluse dans une zone ou non. */
bool mrange_contains_addr(const mrange_t *, const vmpa2t *);
+/* Indique si une localisation est incluse dans une zone ou non. */
+bool mrange_contains_addr_inclusive(const mrange_t *, const vmpa2t *);
+
/* Calcule la position extérieure final d'une couverture. */
void compute_mrange_end_addr(const mrange_t *, vmpa2t *);
diff --git a/src/dialogs/gotox.c b/src/dialogs/gotox.c
index fdf5e2a..00c4fd0 100644
--- a/src/dialogs/gotox.c
+++ b/src/dialogs/gotox.c
@@ -344,7 +344,7 @@ static void add_new_location_to_list(GtkTreeStore *store, GLoadedBinary *binary,
/* Adresse en mémoire virtuelle */
buffer = g_loaded_binary_get_disassembled_buffer(binary);
- line = g_code_buffer_find_line_by_addr(buffer, addr);
+ line = g_code_buffer_find_line_by_addr(buffer, addr, BLF_HAS_CODE, NULL);
if (line != NULL)
virtual = g_buffer_line_get_text(line, BLC_VIRTUAL, BLC_VIRTUAL + 1, true);
diff --git a/src/format/format.c b/src/format/format.c
index 2256160..c1877d2 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -482,6 +482,8 @@ bool g_binary_format_find_symbol_at(const GBinFormat *format, const vmpa2t *addr
result = false;
+ *symbol = NULL; /* TODO : vérifier les doublons côtés appelants */
+
for (i = 0; i < format->symbols_count && !result; i++)
{
range = g_binary_symbol_get_range(format->symbols[i]);
@@ -507,6 +509,50 @@ bool g_binary_format_find_symbol_at(const GBinFormat *format, const vmpa2t *addr
* Paramètres : format = informations chargées à consulter. *
* addr = adresse à cibler lors des recherches. *
* symbol = éventuel symbole trouvé à déréfenrencer. [OUT] *
+* *
+* Description : Recherche le symbole suivant celui lié à une adresse. *
+* *
+* Retour : true si l'opération a été un succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_format_find_next_symbol_at(const GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ const mrange_t *range; /* Espace mémoire parcouru */
+
+ result = false;
+
+ *symbol = NULL;
+
+ for (i = 0; i < format->symbols_count && !result; i++)
+ {
+ range = g_binary_symbol_get_range(format->symbols[i]);
+
+ if (cmp_vmpa(get_mrange_addr(range), addr) == 0 && (i + 1) < format->symbols_count)
+ {
+ *symbol = format->symbols[i + 1];
+ g_object_ref(G_OBJECT(*symbol));
+
+ result = true;
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* addr = adresse à cibler lors des recherches. *
+* symbol = éventuel symbole trouvé à déréfenrencer. [OUT] *
* diff = décallage entre l'adresse et le symbole. [OUT] *
* *
* Description : Recherche le symbole correspondant à une adresse. *
diff --git a/src/format/format.h b/src/format/format.h
index 66f014b..807e328 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -82,6 +82,9 @@ bool g_binary_format_find_symbol_by_label(const GBinFormat *, const char *, GBin
/* Recherche le symbole correspondant à une adresse. */
bool g_binary_format_find_symbol_at(const GBinFormat *, const vmpa2t *, GBinSymbol **);
+/* Recherche le symbole suivant celui lié à une adresse. */
+bool g_binary_format_find_next_symbol_at(const GBinFormat *, const vmpa2t *, GBinSymbol **);
+
/* Recherche le symbole correspondant à une adresse. */
bool g_binary_format_resolve_symbol(const GBinFormat *, const vmpa2t *, GBinSymbol **, phys_t *);
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 8633461..c9abf4e 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -145,8 +145,8 @@ struct _GBufferView
GCodeBuffer *buffer; /* Tampon de code visualisé */
vmpa2t *start; /* Première ligne intégrée */
vmpa2t *end; /* Dernière ligne intégrée */
- size_t first_index; /* Indice de la première ligne */
- size_t last_index; /* Indice de la dernière ligne */
+ size_t first_index; /* Indice de la première ligne */ /* FIXME : utiliser partout ? */
+ size_t last_index; /* Indice de la dernière ligne */ /* FIXME : idem */
gint line_height; /* Hauteur maximale des lignes */
gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */
@@ -744,6 +744,8 @@ GBufferLine *g_code_buffer_insert_after(GCodeBuffer *buffer, GBufferLine *line)
* *
* Paramètres : buffer = composant GTK à mettre à jour. *
* addr = adresse où retrouver la ligne recherchée. *
+* flags = propriétés à vérifier en tout ou partie. *
+* idx = indice de la ligne trouvée ou NULL. [OUT] *
* *
* Description : Retrouve une ligne au sein d'un tampon avec une adresse. *
* *
@@ -753,7 +755,7 @@ GBufferLine *g_code_buffer_insert_after(GCodeBuffer *buffer, GBufferLine *line)
* *
******************************************************************************/
-GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vmpa2t *addr)
+GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vmpa2t *addr, BufferLineFlags flags, size_t *idx)
{
GBufferLine *result; /* Instance à retourner */
size_t index; /* Indice de la ligne visée */
@@ -765,18 +767,24 @@ GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vm
else
{
+ if (idx != NULL)
+ *idx = index;
+
result = buffer->lines[index];
- while ((g_buffer_line_get_flags(result) & BLF_HAS_CODE) == 0)
- {
- if ((index + 1) == buffer->used) break;
+ if (flags != BLF_NONE)
+ while ((g_buffer_line_get_flags(result) & flags) == 0)
+ {
+ if ((index + 1) == buffer->used) break;
- /* FIXME : vérifier que l'adresse est toujours celle recherchée ! */
- /* TODO : passer la recherche de code en option via argument ? */
+ /* FIXME : vérifier que l'adresse est toujours celle recherchée ! */
- result = buffer->lines[++index];
+ if (idx != NULL)
+ (*idx)++;
- }
+ result = buffer->lines[++index];
+
+ }
g_object_ref(G_OBJECT(result));
@@ -1943,6 +1951,87 @@ void g_buffer_view_export(const GBufferView *view, buffer_export_context *ctx, B
/******************************************************************************
* *
+* Paramètres : view = visualisation à consulter. *
+* addr = adresse où retrouver la ligne recherchée. *
+* flags = propriétés à vérifier en tout ou partie. *
+* idx = indice de la ligne trouvée ou NULL. [OUT] *
+* *
+* Description : Retrouve une ligne au sein d'un tampon avec une adresse. *
+* *
+* Retour : Line retrouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *view, const vmpa2t *addr, BufferLineFlags flags, size_t *idx)
+{
+ GBufferLine *result; /* Ligne trouvée à retourner */
+ phys_t length; /* Taille de la vue */
+ mrange_t vrange; /* Couverture de la vue */
+ bool allowed; /* Rechercher validée ? */
+
+ /* Vérification des bornes */
+
+ if (view->start != NULL/* && view->end != NULL*/)
+ {
+ length = compute_vmpa_diff(view->start, view->end);
+
+ init_mrange(&vrange, view->start, length);
+
+ allowed = mrange_contains_addr_inclusive(&vrange, addr);
+
+ }
+ else allowed = true;
+
+ /* Lancement des recherches ? */
+
+ if (allowed)
+ result = g_code_buffer_find_line_by_addr(view->buffer, addr, flags, idx);
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = visualisation à consulter. *
+* index = indice de la ligne recherchée. *
+* *
+* Description : Retrouve une ligne au sein d'un tampon avec un indice. *
+* *
+* Retour : Line retrouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *view, size_t index)
+{
+ GBufferLine *result; /* Ligne trouvée à retourner */
+ bool allowed; /* Rechercher validée ? */
+
+ /* Vérification des bornes */
+
+ allowed = (view->first_index <= index && index < view->last_index);
+
+ /* Lancement des recherches ? */
+
+ if (allowed)
+ result = view->buffer->lines[index];
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : view = visualisation à consulter. *
* y = ordonnée comprise dans la ligne recherchée. *
* idx = indice de la ligne trouvée ou NULL. [OUT] *
diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h
index a248df3..652ea23 100644
--- a/src/glibext/gcodebuffer.h
+++ b/src/glibext/gcodebuffer.h
@@ -70,7 +70,7 @@ GBufferLine *g_code_buffer_insert_at(GCodeBuffer *, vmpa_t, bool);
GBufferLine *g_code_buffer_insert_after(GCodeBuffer *, GBufferLine *);
/* Retrouve une ligne au sein d'un tampon avec une adresse. */
-GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, const vmpa2t *);
+GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, const vmpa2t *, BufferLineFlags, size_t *);
/* Augmente l'indentation des prochaines lignes. */
void g_code_buffer_inc_indentation(GCodeBuffer *);
@@ -152,6 +152,12 @@ void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, gint, const cairo_
/* Exporte le contenu du tampon de code désassemblé. */
void g_buffer_view_export(const GBufferView *, buffer_export_context *, BufferExportType, const bool *);
+/* Retrouve une ligne au sein d'un tampon avec une adresse. */
+GBufferLine *g_buffer_view_find_line_by_addr(const GBufferView *, const vmpa2t *, BufferLineFlags, size_t *);
+
+/* Retrouve une ligne au sein d'un tampon avec un indice. */
+GBufferLine *g_buffer_view_find_line_by_index(const GBufferView *, size_t );
+
/* Fournit la ligne présente à une ordonnée donnée. */
GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *) __attribute__ ((deprecated));
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index 86a738a..8e4ffd4 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -27,6 +27,8 @@
#include <gdk/gdkkeysyms.h>
+#include "../arch/target.h"
+#include "../common/extstr.h"
#include "../core/params.h"
#include "../glibext/chrysamarshal.h"
@@ -59,6 +61,9 @@ static gboolean gtk_buffer_view_draw(GtkWidget *, cairo_t *);
/* Prend en compte une frappe de touche sur le composant. */
static gboolean gtk_buffer_view_key_press(GtkWidget *, GdkEventKey *);
+/* Prépare l'affichage d'une astuce. */
+static gboolean gtk_buffer_view_query_tooltip(GtkWidget *, gint, gint, gboolean, GtkTooltip *);
+
/* Indique les dimensions de travail du composant d'affichage. */
static void gtk_buffer_view_compute_requested_size(GtkBufferView *, gint *, gint *);
@@ -135,6 +140,7 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
widget_class->button_press_event = gtk_buffer_view_button_press;
widget_class->draw = gtk_buffer_view_draw;
widget_class->key_press_event = gtk_buffer_view_key_press;
+ widget_class->query_tooltip = gtk_buffer_view_query_tooltip;
panel_class->compute_size = (compute_requested_size_fc)gtk_buffer_view_compute_requested_size;
panel_class->compute_inc = (compute_scroll_inc_fc)gtk_buffer_view_compute_scroll_inc;
@@ -176,6 +182,12 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
static void gtk_buffer_view_init(GtkBufferView *view)
{
+ GObject *object; /* Autre version de l'instance */
+
+ object = G_OBJECT(view);
+
+ g_object_set(object, "has-tooltip", TRUE, NULL);
+
view->caret.x = 10;
view->caret.y = 10;
view->caret.width = 100;
@@ -484,7 +496,145 @@ static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event)
}
+/******************************************************************************
+* *
+* Paramètres : widget = composant GTK visé par l'opération. *
+* x = abscisse de la position du message. *
+* y = ordonnée de la position du message. *
+* keyboard = indique une demande suite à obtiention du focus. *
+* tooltip = astuce à compléter. [OUT] *
+* *
+* Description : Prépare l'affichage d'une astuce. *
+* *
+* Retour : TRUE pour un affichage validé, FALSE sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_buffer_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard, GtkTooltip *tooltip)
+{
+ GtkBufferView *view; /* Autre version du composant */
+ gint real_x; /* Abscisse absolue réelle */
+ gint real_y; /* Ordonnée absolue réelle */
+ GBufferLine *line; /* Ligne en cours de survol */
+ GBufferSegment *segment; /* Segment actif s'il existe */
+ GObject *creator; /* Créateur à l'orgine du seg. */
+ virt_t virt; /* Adresse virtuelle */
+ vmpa2t addr; /* Adresse de destination */
+ GBinFormat *format; /* Format du fichier binaire */
+ GBinSymbol *target_sym; /* Symbole présent à l'adresse */
+ GBinSymbol *next_sym; /* Symbole suivant l'adresse */
+ const vmpa2t *stop_addr; /* Adresse associée, pour fin */
+ const mrange_t *lrange; /* Couverture d'une ligne */
+ size_t count; /* Nbre de lignes max à traiter*/
+ char *markup; /* Description à construire */
+ size_t i; /* Boucle de parcours */
+ size_t index; /* Indice d'une ligne imprimée */
+ char *text; /* Contenu à ajouter */
+
+ if (keyboard) return FALSE;
+
+ view = GTK_BUFFER_VIEW(widget);
+
+ /* Récupération de la destination pointée */
+
+ real_x = x;
+ real_y = y;
+ gtk_view_panel_compute_real_coord(GTK_VIEW_PANEL(view), &real_x, &real_y);
+
+
+ line = g_buffer_view_find_line_and_segment_at(view->buffer_view,
+ &real_x, real_y, NULL,
+ GTK_VIEW_PANEL(view)->display, &segment);
+
+ if (line == NULL || segment == NULL) goto no_tooltip;
+
+ creator = g_buffer_segment_get_creator(segment);
+ if (creator == NULL) goto no_tooltip;
+
+ /**
+ * On fait le pari de reposer uniquement sur des adresses virtuelles !
+ * A changer dans un futur ?
+ */
+
+ virt = VMPA_NO_VIRTUAL;
+
+ if (G_IS_TARGET_OPERAND(creator))
+ virt = g_target_operand_get_addr(G_TARGET_OPERAND(creator));
+
+ else if (G_IS_IMM_OPERAND(creator))
+ {
+ if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(creator), &virt))
+ virt = VMPA_NO_VIRTUAL;
+ }
+
+ if (virt == VMPA_NO_VIRTUAL) goto no_tooltip;
+
+ init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
+
+ /* Construction du contenu textuel */
+
+ format = G_BIN_FORMAT(g_loaded_binary_get_format(GTK_VIEW_PANEL(view)->binary));
+
+ if (!g_binary_format_find_symbol_at(format, &addr, &target_sym))
+ goto no_tooltip;
+
+ g_object_unref(G_OBJECT(target_sym));
+
+ /* Construction du contenu textuel */
+
+ if (g_binary_format_find_next_symbol_at(format, &addr, &next_sym))
+ stop_addr = get_mrange_addr(g_binary_symbol_get_range(next_sym));
+
+ count = 4;
+
+ markup = NULL;
+
+ for (i = 0, line = g_buffer_view_find_line_by_addr(view->buffer_view, &addr, BLF_NONE, &index);
+ i < count && line != NULL;
+ i++, line = g_buffer_view_find_line_by_index(view->buffer_view, index + i))
+ {
+
+ /* Si on commence à marcher sur les plates-bandes du symbole suivant... */
+ if (next_sym != NULL)
+ {
+ lrange = g_buffer_line_get_range(line);
+
+ if (mrange_contains_addr(lrange, stop_addr))
+ break;
+
+ }
+
+ text = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true);
+
+ if (markup != NULL)
+ markup = stradd(markup, "\n");
+
+ if (text != NULL)
+ markup = stradd(markup, text);
+
+ free(text);
+
+ }
+
+ if (next_sym != NULL)
+ g_object_unref(G_OBJECT(next_sym));
+
+ if (markup == NULL) goto no_tooltip;
+ /* Impression finale */
+
+ gtk_tooltip_set_markup(tooltip, markup);
+ free(markup);
+
+ return TRUE;
+
+ no_tooltip:
+
+ return FALSE;
+
+}
/******************************************************************************