From a2f149e5d151dcd937351f6e54229e508123c3ad Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 24 Mar 2017 19:47:25 +0100
Subject: Built tooltips from all kinds of operands.

---
 ChangeLog                    |  19 +++++++
 src/analysis/routine.c       |   2 +-
 src/arch/immediate.c         | 130 +++++++++++++++++++++++++++++++++++++++----
 src/arch/operand-int.h       |   4 ++
 src/arch/operand.c           |  30 ++++++++++
 src/arch/operand.h           |   7 +++
 src/arch/target.c            |  81 +++++++++++++++++++++++++++
 src/gtkext/gtkblockdisplay.c |  50 +++--------------
 8 files changed, 270 insertions(+), 53 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 086aab9..af5e121 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 17-03-24  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/analysis/routine.c:
+	Typo.
+
+	* src/arch/immediate.c:
+	Build tooltips for immediate operands.
+
+	* src/arch/operand-int.h:
+	* src/arch/operand.c:
+	* src/arch/operand.h:
+	Build tooltips from all kinds of operands.
+
+	* src/arch/target.c:
+	Build tooltips for routines and strings.
+
+	* src/gtkext/gtkblockdisplay.c:
+	Clean code.
+
+17-03-24  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/analysis/db/collection.c:
 	* src/analysis/db/items/comment.c:
 	* src/analysis/db/items/move.c:
diff --git a/src/analysis/routine.c b/src/analysis/routine.c
index 089d287..9ec17c1 100644
--- a/src/analysis/routine.c
+++ b/src/analysis/routine.c
@@ -1142,7 +1142,7 @@ void g_binary_routine_print_code(const GBinRoutine *routine, GLangOutput *lang,
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : routine = routine à mettre à jour.                           *
+*  Paramètres  : routine = routine à consulter.                               *
 *                binary  = informations relatives au binaire chargé.          *
 *                                                                             *
 *  Description : Construit un petit résumé concis de la routine.              *
diff --git a/src/arch/immediate.c b/src/arch/immediate.c
index 5df1f42..5970f06 100644
--- a/src/arch/immediate.c
+++ b/src/arch/immediate.c
@@ -25,6 +25,7 @@
 
 
 #include <assert.h>
+#include <ctype.h>
 #include <inttypes.h>
 #include <malloc.h>
 #include <stdarg.h>
@@ -32,6 +33,9 @@
 #include <string.h>
 
 
+#include <i18n.h>
+
+
 #include "operand-int.h"
 #include "../common/asm.h"
 #include "../common/extstr.h"
@@ -79,9 +83,15 @@ static void g_imm_operand_dispose(GImmOperand *);
 /* Procède à la libération totale de la mémoire. */
 static void g_imm_operand_finalize(GImmOperand *);
 
+/* Construit la chaîne de caractères correspondant à l'opérande. */
+static size_t _g_imm_operand_to_string(const GImmOperand *, AsmSyntax, ImmOperandDisplay, char [IMM_MAX_SIZE]);
+
 /* Traduit un opérande en version humainement lisible. */
 static void g_imm_operand_print(const GImmOperand *, GBufferLine *, AsmSyntax);
 
+/* Construit un petit résumé concis de l'opérande. */
+static char *g_imm_operand_build_tooltip(const GImmOperand *, const GLoadedBinary *);
+
 
 
 /* Indique le type défini pour un opérande de valeur numérique. */
@@ -113,6 +123,7 @@ static void g_imm_operand_class_init(GImmOperandClass *klass)
     object->finalize = (GObjectFinalizeFunc)g_imm_operand_finalize;
 
     operand->print = (operand_print_fc)g_imm_operand_print;
+    operand->build_tooltip = (operand_build_tooltip_fc)g_imm_operand_build_tooltip;
 
     g_signal_new("value-changed",
                  G_TYPE_IMM_OPERAND,
@@ -662,6 +673,7 @@ bool g_imm_operand_is_null(const GImmOperand *operand)
 *                                                                             *
 *  Paramètres  : operand = opérande à transcrire.                             *
 *                syntax  = type de représentation demandée.                   *
+*                display = type d'affichage demandé.                          *
 *                value   = valeur portée par l'opérande transcrite. [OUT]     *
 *                                                                             *
 *  Description : Construit la chaîne de caractères correspondant à l'opérande.*
@@ -672,7 +684,7 @@ bool g_imm_operand_is_null(const GImmOperand *operand)
 *                                                                             *
 ******************************************************************************/
 
-size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, char value[IMM_MAX_SIZE])
+static size_t _g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, ImmOperandDisplay display, char value[IMM_MAX_SIZE])
 {
     size_t result;                          /* Longueur à retourner        */
     unsigned int range;                     /* Catégorie de la taille      */
@@ -685,7 +697,7 @@ size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, cha
     const char *conv;                       /* Opérateur de conversion     */
     char binval[65];                        /* Conversion intégrée         */
     unsigned int max;                       /* Indice du plus fort bit     */
-    unsigned int i;                         /* Boucle de parcours #1       */
+    unsigned int i;                         /* Boucle de parcours          */
     char format[16 + 65];                   /* Format d'impression final   */
 
     static const char *zpad_defs[] = { "", "02", "04", "08", "016" };
@@ -698,7 +710,7 @@ size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, cha
     range = MDS_RANGE(operand->size);
 
     /* Encadrement pour les caractères */
-    if (operand->display == IOD_CHAR)
+    if (display == IOD_CHAR)
     {
         prefix = (syntax == ASX_ATT ? "$'" : "'");
         suffix = "'";
@@ -710,7 +722,7 @@ size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, cha
     }
 
     /* Préfix de forme '0x', 'b' ou '0' */
-    switch (operand->display)
+    switch (display)
     {
         case IOD_BIN:
             alternate = "b";
@@ -727,13 +739,13 @@ size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, cha
     }
 
     /* Va-t-on réellement avoir besoin d'un formatage ? */
-    if (operand->display != IOD_BIN)
+    if (display != IOD_BIN)
         intro = "%";
     else
         intro = "";
 
     /* Drapeau de remplissage ? */
-    switch (operand->display)
+    switch (display)
     {
         case IOD_BIN:
         case IOD_CHAR:
@@ -751,12 +763,12 @@ size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, cha
 
     /* Spécification de la conversion */
 
-    if (operand->display != IOD_BIN)
+    if (display != IOD_BIN)
     {
         if (MDS_IS_SIGNED(operand->size))
-            conv = conv_si_defs[operand->display];
+            conv = conv_si_defs[display];
         else
-            conv = conv_us_defs[operand->display];
+            conv = conv_us_defs[display];
 
     }
     else
@@ -779,7 +791,7 @@ size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, cha
             conv = binval;
 
             for (i = max; i > 0; i--)
-                binval[max - i] = (operand->raw & (1 << (i - 1)) ? '1' : '0');
+                binval[max - i] = (operand->raw & (1llu << (i - 1)) ? '1' : '0');
 
             binval[max] = '\0';
 
@@ -852,6 +864,31 @@ size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, cha
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : operand = opérande à transcrire.                             *
+*                syntax  = type de représentation demandée.                   *
+*                value   = valeur portée par l'opérande transcrite. [OUT]     *
+*                                                                             *
+*  Description : Construit la chaîne de caractères correspondant à l'opérande.*
+*                                                                             *
+*  Retour      : Nombre de caractères utilisés.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax syntax, char value[IMM_MAX_SIZE])
+{
+    size_t result;                          /* Longueur à retourner        */
+
+    result = _g_imm_operand_to_string(operand, syntax, operand->display, value);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : operand = opérande à traiter.                                *
 *                line    = ligne tampon où imprimer l'opérande donné.         *
 *                syntax  = type de représentation demandée.                   *
@@ -878,6 +915,79 @@ static void g_imm_operand_print(const GImmOperand *operand, GBufferLine *line, A
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : operand = opérande à consulter.                              *
+*                binary  = informations relatives au binaire chargé.          *
+*                                                                             *
+*  Description : Construit un petit résumé concis de l'opérande.              *
+*                                                                             *
+*  Retour      : Chaîne de caractères à libérer après usage ou NULL.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_imm_operand_build_tooltip(const GImmOperand *operand, const GLoadedBinary *binary)
+{
+    char *result;                           /* Description à retourner     */
+    char value[IMM_MAX_SIZE];               /* Conversion artificielle     */
+    char *conv;                             /* Affichage de la Conversion  */
+
+    if (isprint(operand->raw))
+        asprintf(&result, _("Character: '%c'"), (char)operand->raw);
+    else
+        asprintf(&result, _("Character: &lt;not printable&gt;"));
+
+    /* Binaire */
+
+    _g_imm_operand_to_string(operand, ASX_INTEL, IOD_BIN, value);
+
+    asprintf(&conv, _("Binary: %s"), value);
+
+    result = stradd(result, "\n");
+    result = stradd(result, conv);
+
+    free(conv);
+
+    /* Octal */
+
+    _g_imm_operand_to_string(operand, ASX_INTEL, IOD_OCT, value);
+
+    asprintf(&conv, _("Octal: %s"), value);
+
+    result = stradd(result, "\n");
+    result = stradd(result, conv);
+
+    free(conv);
+
+    /* Décimal */
+
+    _g_imm_operand_to_string(operand, ASX_INTEL, IOD_DEC, value);
+
+    asprintf(&conv, _("Decimal: %s"), value);
+
+    result = stradd(result, "\n");
+    result = stradd(result, conv);
+
+    free(conv);
+
+    /* Hexadécimal */
+
+    _g_imm_operand_to_string(operand, ASX_INTEL, IOD_HEX, value);
+
+    asprintf(&conv, _("Hexadecimal: %s"), value);
+
+    result = stradd(result, "\n");
+    result = stradd(result, conv);
+
+    free(conv);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : operand = opérande à traiter.                                *
 *                pos     = valeur résultante. [OUT]                           *
 *                                                                             *
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h
index eb1a1d7..8335614 100644
--- a/src/arch/operand-int.h
+++ b/src/arch/operand-int.h
@@ -36,6 +36,9 @@ typedef int (* operand_compare_fc) (const GArchOperand * const *, const GArchOpe
 /* Traduit un opérande en version humainement lisible. */
 typedef void (* operand_print_fc) (const GArchOperand *, GBufferLine *, AsmSyntax);
 
+/* Construit un petit résumé concis de l'opérande. */
+typedef char * (* operand_build_tooltip_fc) (const GArchOperand *, const GLoadedBinary *);
+
 
 /* Adjonction de rendu alternatif */
 typedef struct _alt_rendering
@@ -67,6 +70,7 @@ struct _GArchOperandClass
 
     operand_compare_fc compare;             /* Comparaison d'opérandes     */
     operand_print_fc print;                 /* Texte humain équivalent     */
+    operand_build_tooltip_fc build_tooltip; /* Construction de description */
 
 };
 
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 731c757..dd28238 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -388,3 +388,33 @@ void g_arch_operand_print(const GArchOperand *operand, GBufferLine *line, AsmSyn
         G_ARCH_OPERAND_GET_CLASS(operand)->print(operand, line, syntax);
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = opérande à consulter.                              *
+*                binary  = informations relatives au binaire chargé.          *
+*                                                                             *
+*  Description : Construit un petit résumé concis de l'opérande.              *
+*                                                                             *
+*  Retour      : Chaîne de caractères à libérer après usage ou NULL.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBinary *binary)
+{
+    char *result;                           /* Description à retourner     */
+    GArchOperandClass *class;               /* Classe associée à l'objet   */
+
+    class = G_ARCH_OPERAND_GET_CLASS(operand);
+
+    if (class->build_tooltip != NULL)
+        result = class->build_tooltip(operand, binary);
+    else
+        result = NULL;
+
+    return result;
+
+}
diff --git a/src/arch/operand.h b/src/arch/operand.h
index ca9f3c8..36fc231 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -32,6 +32,10 @@
 
 
 
+/* Depuis "../analysis/binary.h" : description de fichier binaire */
+typedef struct _GLoadedBinary GLoadedBinary;
+
+
 #define G_TYPE_ARCH_OPERAND                 g_arch_operand_get_type()
 #define G_ARCH_OPERAND(obj)                 (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_operand_get_type(), GArchOperand))
 #define G_IS_ARCH_OPERAND(obj)              (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_operand_get_type()))
@@ -59,6 +63,9 @@ void g_arch_operand_set_alt_text(GArchOperand *, const char *, RenderingTagType)
 /* Traduit un opérande en version humainement lisible. */
 void g_arch_operand_print(const GArchOperand *, GBufferLine *, AsmSyntax);
 
+/* Construit un petit résumé concis de l'opérande. */
+char *g_arch_operand_build_tooltip(const GArchOperand *, const GLoadedBinary *);
+
 
 
 #endif  /* _ARCH_OPERAND_H */
diff --git a/src/arch/target.c b/src/arch/target.c
index 3632b76..bce00a7 100644
--- a/src/arch/target.c
+++ b/src/arch/target.c
@@ -75,6 +75,9 @@ static void g_target_operand_finalize(GTargetOperand *);
 /* Traduit un opérande en version humainement lisible. */
 static void g_target_operand_print(const GTargetOperand *, GBufferLine *, AsmSyntax);
 
+/* Construit un petit résumé concis de l'opérande. */
+static char *g_target_operand_build_tooltip(const GTargetOperand *, const GLoadedBinary *);
+
 
 
 /* Indique le type défini pour un opérande de valeur numérique. */
@@ -106,6 +109,7 @@ static void g_target_operand_class_init(GTargetOperandClass *klass)
     object->finalize = (GObjectFinalizeFunc)g_target_operand_finalize;
 
     operand->print = (operand_print_fc)g_target_operand_print;
+    operand->build_tooltip = (operand_build_tooltip_fc)g_target_operand_build_tooltip;
 
 }
 
@@ -252,6 +256,83 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : operand = opérande à consulter.                              *
+*                binary  = informations relatives au binaire chargé.          *
+*                                                                             *
+*  Description : Construit un petit résumé concis de l'opérande.              *
+*                                                                             *
+*  Retour      : Chaîne de caractères à libérer après usage ou NULL.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_target_operand_build_tooltip(const GTargetOperand *operand, const GLoadedBinary *binary)
+{
+    char *result;                           /* Description à retourner     */
+    SymbolType stype;                       /* Type de symbole identifié   */
+    GBinRoutine *routine;                   /* Routine à manipuler         */
+    const mrange_t *srange;                 /* Emplacement du symbole      */
+    GBufferCache *cache;                    /* Tampon de désassemblage     */
+    size_t index;                           /* Indice de ligne à traiter   */
+    GBufferLine *line;                      /* Ligne présente à l'adresse  */
+
+    result = NULL;
+
+    if (operand->symbol != NULL && operand->diff == 0)
+    {
+        stype = g_binary_symbol_get_target_type(operand->symbol);
+
+        switch (stype)
+        {
+            case STP_ROUTINE:
+            case STP_ENTRY_POINT:
+
+                routine = g_binary_symbol_get_routine(operand->symbol);
+
+                result = g_binary_routine_build_tooltip(routine, binary);
+
+                //g_object_unref(G_OBJECT(routine)); // TODO
+
+                break;
+
+            case STP_STRING:
+            case STP_RO_STRING:
+
+                srange = g_binary_symbol_get_range(operand->symbol);
+
+                cache = g_loaded_binary_get_disassembled_cache(binary);
+
+                index = g_buffer_cache_find_index_by_addr(cache, get_mrange_addr(srange), true);
+
+                index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE);
+
+                line = g_buffer_cache_find_line_by_index(cache, index);
+
+                if (line != NULL)
+                {
+                    result = g_buffer_line_get_text(line, BLC_ASSEMBLY, BLC_COUNT, true);
+                    g_object_unref(G_OBJECT(line));
+                }
+
+                g_object_unref(G_OBJECT(cache));
+
+                break;
+
+            default:
+                break;
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : operand = structure dont le contenu est à consulter.         *
 *                                                                             *
 *  Description : Renseigne la taille de la valeur indiquée à la construction. *
diff --git a/src/gtkext/gtkblockdisplay.c b/src/gtkext/gtkblockdisplay.c
index 9698ee5..b39b561 100644
--- a/src/gtkext/gtkblockdisplay.c
+++ b/src/gtkext/gtkblockdisplay.c
@@ -25,7 +25,7 @@
 
 
 #include "gtkbufferdisplay-int.h"
-#include "../arch/target.h"
+#include "../arch/operand.h"
 
 
 
@@ -287,11 +287,6 @@ static gboolean gtk_block_display_query_tooltip(GtkWidget *widget, gint x, gint
     gint real_x;                            /* Abscisse absolue réelle     */
     gint real_y;                            /* Ordonnée absolue réelle     */
     GObject *creator;                       /* Origine du segment pointé   */
-    GBinSymbol *symbol;                     /* Eventuel symbole survolé    */
-    GTargetOperand *operand;                /* Operande associé            */
-    phys_t diff;                            /* Différence avec la base     */
-    SymbolType stype;                       /* Type de symbole identifié   */
-    GBinRoutine *routine;                   /* Routine à manipuler         */
     char *info;                             /* Information à faire paraître*/
 
     if (keyboard) return FALSE;
@@ -309,49 +304,20 @@ static gboolean gtk_block_display_query_tooltip(GtkWidget *widget, gint x, gint
 
     if (creator != NULL)
     {
-        symbol = NULL;
+        if (G_IS_ARCH_OPERAND(creator))
+            info = g_arch_operand_build_tooltip(G_ARCH_OPERAND(creator), panel->binary);
 
-        if (!G_IS_TARGET_OPERAND(creator))
-            goto gbdqt_done;
+        else
+            info = NULL;
 
-        operand = G_TARGET_OPERAND(creator);
-
-        symbol = g_target_operand_get_symbol(operand, &diff);
-
-        if (symbol == NULL || diff != 0)
-            goto gbdqt_done;
-
-        stype = g_binary_symbol_get_target_type(symbol);
-
-        switch (stype)
-        {
-            case STP_ROUTINE:
-            case STP_ENTRY_POINT:
-
-                routine = g_binary_symbol_get_routine(symbol);
-
-                info = g_binary_routine_build_tooltip(routine, panel->binary);
-
-                //g_object_unref(G_OBJECT(routine));
-
-                result = (info != NULL);
-                break;
-
-            default:
-                break;
-
-        }
-
-        if (result)
+        if (info != NULL)
         {
             gtk_tooltip_set_markup(tooltip, info);
             free(info);
-        }
 
- gbdqt_done:
+            result = TRUE;
 
-        if (symbol != NULL)
-            g_object_unref(G_OBJECT(symbol));
+        }
 
         g_object_unref(creator);
 
-- 
cgit v0.11.2-87-g4458