From d450f573d94f795d83d09526546d63c81fde2e1d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 18 Feb 2015 19:31:36 +0000
Subject: Fixed a bug by properly reloading a reallocated list of binary areas.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@475 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                  |   9 +++
 src/analysis/disass/area.c | 137 ++++++++++++++++++++++-----------------------
 src/analysis/disass/area.h |   6 +-
 src/arch/target.c          |   2 +-
 4 files changed, 81 insertions(+), 73 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ad647ec..5949c37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+15-02-18  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	* src/analysis/disass/area.h:
+	Fix a bug by properly reloading a reallocated list of binary areas.
+
+	* src/arch/target.c:
+	Avoid to crash when there is no label linked to a symbol.
+
 15-02-17  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/binary.c:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 974a223..f47e74c 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -89,7 +89,7 @@ static GArchInstruction *get_instructions_from_mem_area(const mem_area *);
 
 
 /* Insère un symbole dans un découpage en aires. */
-static bool insert_extra_symbol_into_mem_areas(mem_area **, size_t *, size_t *, GBinSymbol *);
+static bool insert_extra_symbol_into_mem_areas(mem_area **, size_t *, GBinSymbol *, size_t);
 
 
 
@@ -390,15 +390,15 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, phys_t start, ph
 *                                                                             *
 *  Description : Procède au désassemblage d'un contenu binaire exécutable.    *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Recalcul de rafraîchissement de l'aire de travail requis ?   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, const GLoadedBinary *binary, GProcContext *ctx, const vmpa2t *start, status_blob_info *info)
+bool load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, const GLoadedBinary *binary, GProcContext *ctx, const vmpa2t *start, status_blob_info *info)
 {
-
+    bool result;                            /* Besoin à retourner          */
     mem_area *area;                         /* Zone de désassemblage       */
 
 
@@ -428,14 +428,14 @@ void load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons
     bool has_new_sym;                       /* Statut d'un dépilement      */
 
     GBinSymbol *symbol;                     /* Symbole créé en parallèle   */
-    size_t new_index;                       /* Nouvelle position déterminée*/
-
+    bool refresh;                           /* Besoin de rafraîchissement  */
 
+    result = false;
 
     /* On cherche à obtenir l'assurance que le traitement n'a jamais été fait */
 
     init_mrange(&range, start, 1);
-    if (!is_range_blank_in_mem_areas(*list, *count, &range)) return;
+    if (!is_range_blank_in_mem_areas(*list, *count, &range)) return false;
 
     /* Récupération des informations de base */
 
@@ -507,39 +507,19 @@ void load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons
              has_new_sym;
              has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr))
         {
-            printf("depop :: %x / %x\n", (unsigned int)sym_addr.physical, (unsigned int)sym_addr.virtual);
-            //continue;
-
-            //if (sym_addr.physical != 0x5bc && sym_addr.physical != 0x5c0) continue;
-            //if (sym_addr.physical != 0x5bc) continue;
-            //if (sym_addr.physical != 0x5bc && sym_addr.physical != 0x5c0 && sym_addr.physical != 0x5c4) continue;
-
-
             has_new_sym = g_binary_format_find_symbol_at(format, &sym_addr, &symbol);
             assert(has_new_sym);
 
-            new_index = *index;
-            if (!insert_extra_symbol_into_mem_areas(list, count, &new_index, symbol))
-                continue;
+            refresh = insert_extra_symbol_into_mem_areas(list, count, symbol, *index);
+
+            result |= refresh;
 
             /**
-             * Seulement deux cas de figure peuvent intervenir :
-             *
-             *  - le symbole a été inséré avant la position courante,
-             *    dans une autre aire ou en amont dans l'espace de celle courante.
-             *    La position courante est alors à recalculer entièrement,
-             *    et la boucle de parcours à relancer.
-             *
-             *  - le symbole a été inséré après la position courante.
-             *    Dans le pire des cas, l'aire courante a été diminuée,
-             *    et il est juste nécessaire de recalculer la borne de fin.
+             * Si une insertion a été réalisée dans la même zone que celle courante ou avant,
+             * en l'absence d'indication sur les localisations exactes, le plus simple
+             * est de tout recharger.
              */
-
-            /* On ne peut pas faire disparaître de régions */
-            assert(new_index >= *index);
-
-            /* Cas n°1 */
-            if (new_index > *index)
+            if (refresh)
             {
                 *index = find_memory_area_by_addr(*list, *count, &pos);
 
@@ -552,14 +532,11 @@ void load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons
 
             }
 
-            /* Cas n°2 */
-            else /*if (new_index == *index)*/
-            {
-                area = (*list) + *index;
-
-                alen = get_mrange_length(&area->range);
-
-            }
+            /**
+             * Si la zone modifiée se trouve bien après la zone courante, l'emplacement de la liste
+             * peut potentiellement avoir évolué. Donc on ne recharge ici que le minimum.
+             */
+            else area = (*list) + *index;
 
         }
 
@@ -583,6 +560,7 @@ void load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons
 
     g_object_unref(G_OBJECT(proc));
 
+    return result;
 
 }
 
@@ -771,9 +749,8 @@ void fill_mem_area(mem_area **list, size_t *count, size_t *index, const GLoadedB
     phys_t len;                             /* Taille de la zone à remplir */
     phys_t i;                               /* Boucle de parcours          */
     vmpa2t start;                           /* Adresse de départ de combles*/
-    mem_area *old_list;                     /* Sauvegarde pour comparaison */
-    size_t old_index;                       /* Sauvegarde pour comparaison */
 
+    bool refresh;                           /* Besoin de rafraîchissement  */
 
 
     size_t k;
@@ -814,13 +791,14 @@ void fill_mem_area(mem_area **list, size_t *count, size_t *index, const GLoadedB
 
             if (area->exec && get_virt_addr(&start) % 2 == 0)
             {
-                old_list = *list;
-                old_index = *index;
+                refresh = load_code_from_mem_area(list, count, index, binary, ctx, &start, info);
 
-                load_code_from_mem_area(list, count, index, binary, ctx, &start, info);
-
-                /* Rechargement si changement */
-                if (*list != old_list || *index != old_index)
+                /**
+                 * Mêmes commentaires que dans load_code_from_mem_area() :
+                 *  - en cas de décalage avéré, on recharge tout.
+                 *  - sinon, la liste a potentiellement été déplacée, donc on recharge un minimum.
+                 */
+                if (refresh)
                 {
                     area = (*list) + *index;
                     len = get_mrange_length(&area->range);
@@ -828,6 +806,7 @@ void fill_mem_area(mem_area **list, size_t *count, size_t *index, const GLoadedB
                     i = compute_vmpa_diff(get_mrange_addr(&area->range), &start);
 
                 }
+                else area = (*list) + *index;
 
             }
 
@@ -836,11 +815,6 @@ void fill_mem_area(mem_area **list, size_t *count, size_t *index, const GLoadedB
 
         }
 
-
-        if (is_range_blank_in_mem_area(area, i, 1, NULL))
-            printf(" [%p] error with %u @ 0x%08x\n", area, (unsigned int)i,
-                   (unsigned int)get_phy_addr(get_mrange_addr(&area->range)));
-
         assert(!is_range_blank_in_mem_area(area, i, 1, NULL));
 
     }
@@ -1285,25 +1259,22 @@ mem_area *compute_memory_areas(GExeFormat *format, phys_t bin_length, size_t *co
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : area   = aire représentant à contenu à parcourir.            *
-*                list   = liste de zones délimitant des contenus à traiter.   *
-*                count  = nombre de zones à disposition.                      *
-*                index  = indice de l'aire à considérer pendant l'opération.  *
-*                binary = représentation de binaire chargé.                   *
-*                ctx    = contexte offert en soutien à un désassemblage.      *
-*                start  = démarrage de l'exécution au sein de la zone.        *
-*                info   = indications quant à la progression à afficher.      *
+*  Paramètres  : list    = liste de zones délimitant des contenus à traiter.  *
+*                count   = nombre de zones à disposition.                     *
+*                symbol  = élément nouveau à venir insérer dans les zones.    *
+*                working = indice de l'aire de travail courante.              *
 *                                                                             *
 *  Description : Insère un symbole dans un découpage en aires.                *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Recalcul de rafraîchissement de l'aire de travail requis ?   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, size_t *old_index, GBinSymbol *symbol)
+static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, GBinSymbol *symbol, size_t working)
 {
+    bool result;                            /* Besoin à renvoyer           */
     const mrange_t *sym_range;              /* Emplacement du symbole      */
     size_t index;                           /* Zone trouvée à scinder      */
     mem_area *area;                         /* Aire en cours de traitement */
@@ -1319,19 +1290,18 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, s
     index = find_memory_area_by_addr(*list, *count, get_mrange_addr(sym_range));
     assert(index < *count);
 
-    //if (index <= *old_index) (*old_index)++;
+    result = (working >= index);
 
     area = &(*list)[index];
 
 
-    if (strcmp("Value used @ 0x00008a26", g_db_comment_get_text(g_binary_symbol_get_comment(symbol))) == 0)
-        printf("break\n");
-
 
     do
     {
         size_t i;
 
+        printf("--- INDEX = %zu   OLD_INDEX = %zu\n", index, working);
+
         printf("--- comment '%s'...\n",
                g_db_comment_get_text(g_binary_symbol_get_comment(symbol)));
 
@@ -1348,10 +1318,17 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, s
     }
     while (0);
 
-    if (area->has_sym) return true;
+
+
+
+    if (area->has_sym) return false;
 
     assert(!area->has_sym);
 
+
+
+
+
     saved = *area;
 
     copy_mrange(&area_range, &area->range);
@@ -1371,6 +1348,20 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, s
 
     }
 
+    /* Si le symbole a une taille identique à la zone qui le contient, on remplace simplement... */
+    if (get_mrange_length(&area_range) == get_mrange_length(sym_range))
+    {
+        assert((cmp_vmpa(&area_pos, &sym_pos) == 0));
+
+        init_mem_area_from_range(area, sym_range);
+
+        area->has_sym = true;
+        area->symbol = symbol;
+
+        goto iesima_done;
+
+    }
+
     /* Si le symbole se trouve en début de zone... */
     if (cmp_vmpa(&area_pos, &sym_pos) == 0)
     {
@@ -1446,6 +1437,8 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, s
         copy_vmpa(&area_pos, get_mrange_addr(&area_range));
         new_length = compute_vmpa_diff(&area_pos, get_mrange_addr(sym_range));
 
+        assert(new_length != 0);    /* Symbole non présent au début */
+
         area = &(*list)[index];
 
         init_mem_area_from_bigger_area(area, &area_pos, new_length, &saved);
@@ -1469,6 +1462,8 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, s
         new_length = get_mrange_length(&area_range) - get_mrange_length(sym_range) \
             - get_mrange_length(&(*list)[index].range);
 
+        assert(new_length != 0);    /* Symbole non présent à la fin */
+
         area = &(*list)[index + 2];
 
         init_mem_area_from_bigger_area(area, &area_pos, new_length, &saved);
@@ -1479,7 +1474,7 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, s
 
  iesima_done:
 
-    return true;
+    return result;
 
 }
 
diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h
index b517816..35a3533 100644
--- a/src/analysis/disass/area.h
+++ b/src/analysis/disass/area.h
@@ -25,6 +25,10 @@
 #define _ANALYSIS_DISASS_AREA_H
 
 
+#include <stdbool.h>
+
+
+
 #include "../binary.h"
 #include "../../format/executable.h"
 #include "../../gtkext/gtkextstatusbar.h"
@@ -45,7 +49,7 @@ typedef struct _mem_area mem_area;
 
 
 /* Procède au désassemblage d'un contenu binaire exécutable. */
-void load_code_from_mem_area(mem_area **, size_t *, size_t *, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_blob_info *);
+bool load_code_from_mem_area(mem_area **, size_t *, size_t *, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_blob_info *);
 
 
 
diff --git a/src/arch/target.c b/src/arch/target.c
index 93ccbe4..40e9598 100644
--- a/src/arch/target.c
+++ b/src/arch/target.c
@@ -216,7 +216,7 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l
     VMPA_BUFFER(value);                     /* Adresse brute à imprimer    */
     size_t len;                             /* Taille de l'élément inséré  */
 
-    if (operand->symbol != NULL)
+    if (operand->symbol != NULL /* FIXME */ && g_binary_symbol_get_label(operand->symbol) != NULL /* FIXME */)
     {
         if (operand->diff > 0)
             g_buffer_line_insert_text(line, BLC_MAIN, "<", 1, RTT_LTGT);
-- 
cgit v0.11.2-87-g4458