From d3f9ef68a9939ee43e8a70748dd4b7e97352179e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 17 Aug 2017 00:26:41 +0200
Subject: Kept only the first submission when preloading instructions.

---
 ChangeLog                | 13 +++++++++
 plugins/fmtp/parser.c    | 11 +++++--
 plugins/readdex/ids.c    | 12 +++++---
 plugins/readelf/strtab.c | 29 +++++++++++--------
 src/arch/arm/v7/fetch.c  | 47 +++++++++++++++---------------
 src/format/elf/strings.c | 25 +++++++++-------
 src/format/preload.c     | 75 ++++++++++++++++++++++++++++++++++++++++++------
 src/format/preload.h     |  7 +++--
 8 files changed, 157 insertions(+), 62 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f4fddab..e732a25 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 17-08-16  Cyrille Bagard <nocbos@gmail.com>
 
+	* plugins/fmtp/parser.c:
+	* plugins/readdex/ids.c:
+	* plugins/readelf/strtab.c:
+	* src/arch/arm/v7/fetch.c:
+	* src/format/elf/strings.c:
+	Update code.
+
+	* src/format/preload.c:
+	* src/format/preload.h:
+	Keep only the first submission when preloading instructions.
+
+17-08-16  Cyrille Bagard <nocbos@gmail.com>
+
 	* plugins/mobicore/mclf.c:
 	* src/format/dex/dex-int.c:
 	* src/format/dex/dex_def.h:
diff --git a/plugins/fmtp/parser.c b/plugins/fmtp/parser.c
index 96aeb11..fe41e9b 100644
--- a/plugins/fmtp/parser.c
+++ b/plugins/fmtp/parser.c
@@ -55,10 +55,10 @@ static bool parse_field_definition(const fmt_field_def *, GBinFormat *, GPreload
 
 static bool parse_field_definition(const fmt_field_def *def, GBinFormat *format, GPreloadInfo *info, vmpa2t *pos, void *data)
 {
+    bool result;                            /* Bilan à retourner           */
     GBinContent *content;                   /* Contenu binaire à lire      */
     SourceEndian endian;                    /* Boutisme utilisé            */
     vmpa2t mod;                             /* Position  modifiable        */
-    bool result;                            /* Bilan à retourner           */
     GArchInstruction *instr;                /* Instruction décodée         */
     GImmOperand *imm;                       /* Opérande à transformer      */
     size_t i;                               /* Boucle de parcours          */
@@ -66,6 +66,7 @@ static bool parse_field_definition(const fmt_field_def *def, GBinFormat *format,
     GDbComment *comment;                    /* Définition de commentaire   */
     uint64_t raw;                           /* Valeur brute à étudier      */
     const comment_part *part;               /* Accès plus direct           */
+    bool inserted;                          /* Bilan d'une insertion       */
 
     /* Lecture */
 
@@ -192,9 +193,13 @@ static bool parse_field_definition(const fmt_field_def *def, GBinFormat *format,
 
     /* Insertions */
 
-    g_preload_info_add_instruction(info, instr);
+    inserted = g_preload_info_add_instruction(info, instr);
 
-    g_preload_info_add_comment(info, comment);
+    if (inserted)
+        g_preload_info_add_comment(info, comment);
+
+    else
+        g_object_unref(G_OBJECT(comment));
 
  pfd_exit:
 
diff --git a/plugins/readdex/ids.c b/plugins/readdex/ids.c
index e09036e..518e9ad 100644
--- a/plugins/readdex/ids.c
+++ b/plugins/readdex/ids.c
@@ -254,6 +254,7 @@ bool annotate_dex_string_ids(const GDexFormat *format, GPreloadInfo *info, GtkSt
     vmpa2t item_pos;                        /* Position d'un élément       */
     uleb128_t length;                       /* Taille de la chaîne en cours*/
     GArchInstruction *instr;                /* Instruction décodée         */
+    bool inserted;                          /* Bilan d'une insertion       */
     const mrange_t *range;                  /* Espace occupé par une chaîne*/
     GBinSymbol *symbol;                     /* Symbole à intégrer          */
 
@@ -331,13 +332,16 @@ bool annotate_dex_string_ids(const GDexFormat *format, GPreloadInfo *info, GtkSt
 
             g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true);
 
-            g_preload_info_add_instruction(info, instr);
+            inserted = g_preload_info_add_instruction(info, instr);
 
-            range = g_arch_instruction_get_range(instr);
+            if (inserted)
+            {
+                range = g_arch_instruction_get_range(instr);
 
-            symbol = g_binary_symbol_new(range, STP_RO_STRING);
-            g_binary_format_add_symbol(bformat, symbol);
+                symbol = g_binary_symbol_new(range, STP_RO_STRING);
+                g_binary_format_add_symbol(bformat, symbol);
 
+            }
 
         }
 
diff --git a/plugins/readelf/strtab.c b/plugins/readelf/strtab.c
index 1564674..7cdb4c9 100644
--- a/plugins/readelf/strtab.c
+++ b/plugins/readelf/strtab.c
@@ -63,6 +63,7 @@ static void parse_elf_string_table(GElfFormat *format, GPreloadInfo *info, const
     phys_t i;                               /* Boucle de parcours          */
     phys_t end;                             /* Position de fin de chaîne   */
     GArchInstruction *instr;                /* Instruction décodée         */
+    bool inserted;                          /* Bilan d'une insertion       */
     const mrange_t *irange;                 /* Espace occupé par une chaîne*/
     GBinSymbol *symbol;                     /* Symbole à intégrer          */
     char *label;                            /* Désignation de la chaîne    */
@@ -103,25 +104,29 @@ static void parse_elf_string_table(GElfFormat *format, GPreloadInfo *info, const
 
             g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true);
 
-            g_preload_info_add_instruction(info, instr);
+            inserted = g_preload_info_add_instruction(info, instr);
 
-            irange = g_arch_instruction_get_range(instr);
+            if (inserted)
+            {
+                irange = g_arch_instruction_get_range(instr);
 
-            symbol = g_binary_symbol_new(irange, STP_RO_STRING);
-            g_binary_format_add_symbol(base, symbol);
+                symbol = g_binary_symbol_new(irange, STP_RO_STRING);
+                g_binary_format_add_symbol(base, symbol);
 
-            /* Jointure avec la chaîne précédente ? */
+                /* Jointure avec la chaîne précédente ? */
 
-            if (cut)
-            {
-                copy_vmpa(&pos, get_mrange_addr(range));
-                advance_vmpa(&pos, i);
+                if (cut)
+                {
+                    copy_vmpa(&pos, get_mrange_addr(range));
+                    advance_vmpa(&pos, i);
+
+                    label = create_string_label(base, get_mrange_addr(irange), end - i);
 
-                label = create_string_label(base, get_mrange_addr(irange), end - i);
+                    g_binary_symbol_set_alt_label(symbol, label);
 
-                g_binary_symbol_set_alt_label(symbol, label);
+                    free(label);
 
-                free(label);
+                }
 
             }
 
diff --git a/src/arch/arm/v7/fetch.c b/src/arch/arm/v7/fetch.c
index 42788af..a1ddd3e 100644
--- a/src/arch/arm/v7/fetch.c
+++ b/src/arch/arm/v7/fetch.c
@@ -369,6 +369,7 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst
     VMPA_BUFFER(loc);                       /* Adresse au format texte     */
     GPreloadInfo *info;                     /* Informations préchargées    */
     GArchInstruction *loaded;               /* Instruction de valeur       */
+    bool inserted;                          /* Bilan d'une insertion       */
     char *desc;                             /* Description d'accompagnement*/
     GDbComment *comment;                    /* Définition de commentaire   */
     GArchOperand *new;                      /* Instruction de ciblage      */
@@ -442,41 +443,41 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst
 
     info = G_PRELOAD_INFO(context);
 
-    g_preload_info_lock_instructions(info);
+    loaded = g_raw_instruction_new_from_value(&pos, MDS_32_BITS_UNSIGNED, target);
 
-    if (!_g_preload_info_has_instruction_at(info, &loaded_addr))
+    inserted = g_preload_info_add_instruction(info, loaded);
+
+    if (inserted)
     {
-        loaded = g_raw_instruction_new_from_value(&pos, MDS_32_BITS_UNSIGNED, target);
-        _g_preload_info_add_instruction(info, loaded);
-    }
+        /* Commentaire associé */
 
-    g_preload_info_unlock_instructions(info);
+        vmpa2_virt_to_string(get_mrange_addr(range), MDS_32_BITS, loc, NULL);
+        asprintf(&desc, _("Value used @ %s"), loc);
 
-    vmpa2_virt_to_string(get_mrange_addr(range), MDS_32_BITS, loc, NULL);
-    asprintf(&desc, _("Value used @ %s"), loc);
+        g_preload_info_lock_comments(info);
 
-    g_preload_info_lock_comments(info);
+        comment = _g_preload_info_find_comment_at(info, &loaded_addr);
 
-    comment = _g_preload_info_find_comment_at(info, &loaded_addr);
+        if (comment != NULL)
+        {
+            g_db_comment_add_static_text(comment, "\n");
+            g_db_comment_add_dynamic_text(comment, desc);
+        }
 
-    if (comment != NULL)
-    {
-        g_db_comment_add_static_text(comment, "\n");
-        g_db_comment_add_dynamic_text(comment, desc);
-    }
+        else
+        {
+            comment = g_db_comment_new_inlined(&loaded_addr, BLF_HAS_CODE, false);
+            g_db_item_set_volatile(G_DB_ITEM(comment), true);
 
-    else
-    {
-        comment = g_db_comment_new_inlined(&loaded_addr, BLF_HAS_CODE, false);
-        g_db_item_set_volatile(G_DB_ITEM(comment), true);
+            g_db_comment_add_dynamic_text(comment, desc);
 
-        g_db_comment_add_dynamic_text(comment, desc);
+            _g_preload_info_add_comment(info, comment);
 
-        _g_preload_info_add_comment(info, comment);
+        }
 
-    }
+        g_preload_info_unlock_comments(info);
 
-    g_preload_info_unlock_comments(info);
+    }
 
     /* Mise à jour de l'affichage et conclusion */
 
diff --git a/src/format/elf/strings.c b/src/format/elf/strings.c
index 53d4e92..e885632 100644
--- a/src/format/elf/strings.c
+++ b/src/format/elf/strings.c
@@ -159,6 +159,7 @@ static bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size,
     phys_t i;                               /* Boucle de parcours          */
     phys_t end;                             /* Position de fin de chaîne   */
     GArchInstruction *instr;                /* Instruction décodée         */
+    bool inserted;                          /* Bilan d'une insertion       */
     const mrange_t *range;                  /* Espace occupé par une chaîne*/
     GBinSymbol *symbol;                     /* Symbole à intégrer          */
     char *label;                            /* Désignation de la chaîne    */
@@ -203,22 +204,26 @@ static bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size,
 
             g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true);
 
-            g_preload_info_add_instruction(base->info, instr);
+            inserted = g_preload_info_add_instruction(base->info, instr);
 
-            range = g_arch_instruction_get_range(instr);
+            if (inserted)
+            {
+                range = g_arch_instruction_get_range(instr);
 
-            symbol = g_binary_symbol_new(range, STP_RO_STRING);
-            g_binary_format_add_symbol(base, symbol);
+                symbol = g_binary_symbol_new(range, STP_RO_STRING);
+                g_binary_format_add_symbol(base, symbol);
 
-            /* Jointure avec la chaîne précédente ? */
+                /* Jointure avec la chaîne précédente ? */
 
-            if (cut)
-            {
-                label = create_string_label(base, get_mrange_addr(range), end - i);
+                if (cut)
+                {
+                    label = create_string_label(base, get_mrange_addr(range), end - i);
 
-                g_binary_symbol_set_alt_label(symbol, label);
+                    g_binary_symbol_set_alt_label(symbol, label);
 
-                free(label);
+                    free(label);
+
+                }
 
             }
 
diff --git a/src/format/preload.c b/src/format/preload.c
index cddc60e..14bb4b0 100644
--- a/src/format/preload.c
+++ b/src/format/preload.c
@@ -259,20 +259,24 @@ void g_preload_info_unlock_instructions(GPreloadInfo *info)
 *                                                                             *
 *  Description : Ajoute une instruction supplémentaire aux préchargements.    *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : true si l'instruction a bien été insérée, false sinon.       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr)
+bool g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr)
 {
+    bool result;                            /* Bilan à retourner           */
+
     g_preload_info_lock_instructions(info);
 
-    _g_preload_info_add_instruction(info, instr);
+    result = _g_preload_info_add_instruction(info, instr);
 
     g_preload_info_unlock_instructions(info);
 
+    return result;
+
 }
 
 
@@ -283,14 +287,16 @@ void g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr)
 *                                                                             *
 *  Description : Ajoute une instruction supplémentaire aux préchargements.    *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : true si l'instruction a bien été insérée, false sinon.       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void _g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr)
+bool _g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr)
 {
+    bool result;                            /* Bilan à retourner           */
+
     int cmp_instr_by_addr(const GArchInstruction **a, const GArchInstruction **b)
     {
         const mrange_t *range_a;            /* Emplacement pour l'instr. A */
@@ -303,8 +309,16 @@ void _g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr
 
     }
 
-    insert_item_into_flat_array(&info->instructions, &instr, sizeof(GArchInstruction *),
-                                (__compar_fn_t)cmp_instr_by_addr);
+    result = _g_preload_info_has_instruction_for(info, g_arch_instruction_get_range(instr));
+
+    if (result)
+        insert_item_into_flat_array(&info->instructions, &instr, sizeof(GArchInstruction *),
+                                    (__compar_fn_t)cmp_instr_by_addr);
+
+    else
+        g_object_unref(G_OBJECT(instr));
+
+    return result;
 
 }
 
@@ -312,7 +326,52 @@ void _g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : info  = instance à mettre à jour.                            *
-*                addr = localisation du commentaire recherché.                *
+*                range = emplacement de l'instruction recherchés.             *
+*                                                                             *
+*  Description : Détermine si une instruction existe sur un espace donné.     *
+*                                                                             *
+*  Retour      : true si une instruction existe à l'emplacement indiqué.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool _g_preload_info_has_instruction_for(GPreloadInfo *info, const mrange_t *range)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstruction **ptr;                 /* Adresse dans le tableau     */
+
+    int check_for_overlap(const mrange_t *key, const GArchInstruction **i)
+    {
+        const mrange_t *irange;             /* Emplacement pour l'instr.   */
+        int status;                         /* Bilan de la recherche       */
+
+        irange = g_arch_instruction_get_range(*i);
+
+        if (mrange_intersects_mrange(irange, key))
+            status = 0;
+
+        else
+            status = cmp_vmpa(get_mrange_addr(key), get_mrange_addr(irange));
+
+        return status;
+
+    }
+
+    ptr = find_item_in_flat_array(info->instructions, sizeof(GArchInstruction *),
+                                  (__compar_fn_t)check_for_overlap, range);
+
+    result = (ptr != NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info  = instance à mettre à jour.                            *
+*                addr = localisation de l'instruction recherchée.             *
 *                                                                             *
 *  Description : Détermine si une instruction est présente à un point donné.  *
 *                                                                             *
diff --git a/src/format/preload.h b/src/format/preload.h
index 1e28222..de79f83 100644
--- a/src/format/preload.h
+++ b/src/format/preload.h
@@ -64,10 +64,13 @@ void g_preload_info_lock_instructions(GPreloadInfo *);
 void g_preload_info_unlock_instructions(GPreloadInfo *);
 
 /* Ajoute une instruction supplémentaire aux préchargements. */
-void g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *);
+bool g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *);
 
 /* Ajoute une instruction supplémentaire aux préchargements. */
-void _g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *);
+bool _g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *);
+
+/* Détermine si une instruction existe sur un espace donné. */
+bool _g_preload_info_has_instruction_for(GPreloadInfo *, const mrange_t *);
 
 /* Détermine si une instruction est présente à un point donné. */
 bool _g_preload_info_has_instruction_at(GPreloadInfo *, const vmpa2t *);
-- 
cgit v0.11.2-87-g4458