From cd956221a807e4c1961e17602d5ca641b93a937a Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 22 Mar 2017 18:58:36 +0100
Subject: Ensured all string symbols referenced by instructions get a label.

---
 ChangeLog                | 14 ++++++++++++++
 src/arch/target.c        | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/format/elf/strings.c | 18 ++++++++----------
 src/format/format.c      | 12 ++++++++++--
 src/format/format.h      |  2 +-
 5 files changed, 76 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b8cd12c..94c99d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+17-03-22  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/target.c:
+	Ensure all string symbols referenced by instructions get a label.
+
+	* src/format/elf/strings.c:
+	Avoid to allocate memory for reading binary content which can be read
+	directly.
+
+	* src/format/format.c:
+	* src/format/format.h:
+	Use the internal format content instead of a provided one when creating
+	labels.
+
 17-03-21  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/glibext/gbufferline.c:
diff --git a/src/arch/target.c b/src/arch/target.c
index 63ae295..3632b76 100644
--- a/src/arch/target.c
+++ b/src/arch/target.c
@@ -24,6 +24,7 @@
 #include "target.h"
 
 
+#include <assert.h>
 #include <inttypes.h>
 #include <malloc.h>
 #include <stdarg.h>
@@ -305,12 +306,54 @@ void g_target_operand_get_addr(const GTargetOperand *operand, vmpa2t *addr)
 bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool strict)
 {
     bool result;                            /* Bilan à retourner           */
+    GBinSymbol *symbol;                     /* Facilités d'accès au symbole*/
+    SymbolType stype;                       /* Type de symbole trouvé      */
+    const mrange_t *range;                  /* Couverture du symbole       */
+    char *label;                            /* Désignation de la chaîne    */
 
     if (operand->symbol != NULL)
         g_object_unref(G_OBJECT(operand->symbol));
 
     result = g_binary_format_resolve_symbol(format, &operand->addr, strict, &operand->symbol, &operand->diff);
 
+    /**
+     * Si plusieurs chaînes se suivent, la seconde et les suivantes bénéficient
+     * d'une étiquette si et seulement si elles sont détachées des précédentes
+     * par un octet nul.
+     *
+     * S'il y a juste un retour à la ligne ("\n"), alors aucune séparation n'est
+     * considérée, et le bloc de chaînes est uniforme.
+     *
+     * Aussi, si une référence renvoie vers une ligne de ce bloc, alors on
+     * attribue à cette ligne une étiquette propre.
+     */
+
+    if (result && operand->diff == 0)
+    {
+        symbol = operand->symbol;
+
+        stype = g_binary_symbol_get_target_type(symbol);
+
+        if (stype == STP_STRING || stype == STP_RO_STRING)
+        {
+            if (g_binary_symbol_get_label(symbol) == NULL)
+            {
+                range = g_binary_symbol_get_range(symbol);
+
+                assert(cmp_vmpa(&operand->addr, get_mrange_addr(range)) == 0);
+
+                label = create_string_label(format, get_mrange_addr(range), get_mrange_length(range));
+
+                g_binary_symbol_set_alt_label(symbol, label);
+
+                free(label);
+
+            }
+
+        }
+
+    }
+
     return result;
 
 }
diff --git a/src/format/elf/strings.c b/src/format/elf/strings.c
index 755163e..9bcb87f 100644
--- a/src/format/elf/strings.c
+++ b/src/format/elf/strings.c
@@ -152,7 +152,7 @@ bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t
 {
     bool result;                            /* Bilan à faire remonter      */
     GBinContent *content;                   /* Contenu binaire à lire      */
-    char *data;                             /* Données copiées à traiter   */
+    const bin_t *data;                      /* Contenu complet et original */
     vmpa2t pos;                             /* Tête de lecture             */
     bool cut;                               /* Séparation nette ?          */
     off_t i;                                /* Boucle de parcours          */
@@ -161,7 +161,8 @@ bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t
     GBinSymbol *symbol;                     /* Symbole à intégrer          */
     char *label;                            /* Désignation de la chaîne    */
 
-    if (address == 0) return false;
+    if (address == 0)
+        return false;
 
     result = false;
 
@@ -169,11 +170,11 @@ bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t
 
     content = g_binary_format_get_content(G_BIN_FORMAT(format));
 
-    data = (char *)malloc(size * sizeof(char));
-
     init_vmpa(&pos, start, address);
 
-    if (!g_binary_content_read_raw(content, &pos, size, (bin_t *)data))
+    data = g_binary_content_get_raw_access(content, &pos, size);
+
+    if (data == NULL)
         goto pesd_error;
 
     /* Boucle de parcours */
@@ -194,8 +195,7 @@ bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t
 
             init_vmpa(&pos, start + i, address + i);
 
-            instr = g_raw_instruction_new_array(G_BIN_FORMAT(format)->content, MDS_8_BITS,
-                                                end - i, &pos, format->endian);
+            instr = g_raw_instruction_new_array(content, MDS_8_BITS, end - i, &pos, format->endian);
 
             g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true);
 
@@ -207,7 +207,7 @@ bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t
             {
                 init_vmpa(&pos, start + i, address + i);
 
-                label = create_string_label(G_BIN_FORMAT(format), &pos, &data[i], end - i);
+                label = create_string_label(G_BIN_FORMAT(format), &pos, end - i);
 
                 g_binary_symbol_set_alt_label(symbol, label);
 
@@ -229,8 +229,6 @@ bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t
 
     g_object_unref(G_OBJECT(content));
 
-    free(data);
-
     return result;
 
 }
diff --git a/src/format/format.c b/src/format/format.c
index 327b28e..978a3d2 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -546,7 +546,6 @@ GBinSymbol **g_binary_format_get_symbols(const GBinFormat *format, size_t *count
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                addr   = adresse liée à la chaîne à traiter.                 *
-*                base   = contenu complet et original d'une chaîne.           *
 *                length = taille de la chaîne à représenter.                  *
 *                                                                             *
 *  Description : Construit une désignation pour chaîne de caractères.         *
@@ -557,9 +556,11 @@ GBinSymbol **g_binary_format_get_symbols(const GBinFormat *format, size_t *count
 *                                                                             *
 ******************************************************************************/
 
-char *create_string_label(GBinFormat *format, const vmpa2t *addr, const char *base, size_t length)
+char *create_string_label(GBinFormat *format, const vmpa2t *addr, size_t length)
 {
     char *result;                           /* Nouvelle chaîne à retourner */
+    vmpa2t pos;                             /* Tête de lecture modifiable  */
+    const bin_t *base;                      /* Contenu complet et original */
     unsigned int wc;                        /* Nombre de mots rencontrés   */
     size_t iter;                            /* Tête d'écriture de recopie  */
     size_t i;                               /* Boucle de parcours          */
@@ -567,6 +568,13 @@ char *create_string_label(GBinFormat *format, const vmpa2t *addr, const char *ba
     GBinSymbol *found;                      /* Symbole similaire trouvé    */
     VMPA_BUFFER(last_sfx);                  /* Dernier suffixe à intégrer  */
 
+    copy_vmpa(&pos, addr);
+
+    base = g_binary_content_get_raw_access(format->content, &pos, length);
+
+    if (base == NULL)
+        return NULL;
+
     result = (char *)calloc(length + 5 + VMPA_MAX_LEN + 1, sizeof(char));
 
     wc = 0;
diff --git a/src/format/format.h b/src/format/format.h
index d97f542..c2ef895 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -77,7 +77,7 @@ void g_binary_format_remove_symbol(GBinFormat *, GBinSymbol *);
 GBinSymbol **g_binary_format_get_symbols(const GBinFormat *, size_t *);
 
 /* Construit une désignation pour chaîne de caractères. */
-char *create_string_label(GBinFormat *, const vmpa2t *, const char *, size_t);
+char *create_string_label(GBinFormat *, const vmpa2t *, size_t);
 
 /* Recherche le symbole correspondant à une étiquette. */
 bool g_binary_format_find_symbol_by_label(GBinFormat *, const char *, GBinSymbol **);
-- 
cgit v0.11.2-87-g4458