From 8c84aa2e41305fd388b7dac49f29ae17ee0554fb Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 3 Aug 2018 00:25:15 +0200
Subject: Introduced symbols dedicated to strings.

---
 plugins/dex/pool.c                   |  12 +-
 plugins/elf/strings.c                |  13 +-
 plugins/pychrysalide/format/symbol.c |   3 +-
 plugins/readelf/strtab.c             |  16 +-
 src/arch/target.c                    |  20 +-
 src/common/Makefile.am               |   1 +
 src/common/alloc.c                   |  60 +++++
 src/common/alloc.h                   |  37 +++
 src/format/Makefile.am               |   1 +
 src/format/format.c                  |  91 -------
 src/format/format.h                  |   3 -
 src/format/strsym.c                  | 474 +++++++++++++++++++++++++++++++++++
 src/format/strsym.h                  |  80 ++++++
 src/format/symbol.h                  |   5 +-
 src/gui/panels/strings.c             |  16 +-
 15 files changed, 680 insertions(+), 152 deletions(-)
 create mode 100644 src/common/alloc.c
 create mode 100644 src/common/alloc.h
 create mode 100644 src/format/strsym.c
 create mode 100644 src/format/strsym.h

diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c
index 75841df..d95f519 100644
--- a/plugins/dex/pool.c
+++ b/plugins/dex/pool.c
@@ -31,6 +31,7 @@
 #include <i18n.h>
 #include <core/global.h>
 #include <core/nproc.h>
+#include <format/strsym.h>
 #include <mangling/demangler.h>
 
 
@@ -205,9 +206,8 @@ GBinSymbol *get_string_symbol_from_dex_pool(GDexFormat *format, uint32_t index)
     uint32_t count;                         /* Nombre d'éléments présents  */
     mrange_t range;                         /* Emplacement de la chaîne    */
     const char *string;                     /* Chaîne de caractères liée   */
-    GBinSymbol *new;                        /* Nouveau symbol créé         */
     GBinFormat *base;                       /* Autre version du format     */
-    char *label;                            /* Désignation de la chaîne    */
+    GBinSymbol *new;                        /* Nouveau symbol créé         */
     bool inserted;                          /* Bilan d'une insertion       */
 
     result = NULL;
@@ -222,15 +222,11 @@ GBinSymbol *get_string_symbol_from_dex_pool(GDexFormat *format, uint32_t index)
         string = get_string_from_dex_pool(format, index, &range);
         if (string == NULL) goto gssfdp_error;
 
-        new = g_binary_symbol_new(&range, STP_RO_STRING);
-
         base = G_BIN_FORMAT(format);
 
-        label = create_string_label(base, get_mrange_addr(&range), get_mrange_length(&range));
-
-        g_binary_symbol_set_alt_label(new, label);
+        new = g_string_symbol_new_read_only(base, &range, SET_MUTF_8);
 
-        free(label);
+        g_string_symbol_build_label(G_STR_SYMBOL(new), base);
 
         g_object_ref(G_OBJECT(new));
         inserted = g_binary_format_add_symbol(base, new);
diff --git a/plugins/elf/strings.c b/plugins/elf/strings.c
index a14b389..4d6b5c8 100644
--- a/plugins/elf/strings.c
+++ b/plugins/elf/strings.c
@@ -36,6 +36,7 @@
 #include <arch/raw.h>
 #include <core/global.h>
 #include <core/nproc.h>
+#include <format/strsym.h>
 
 
 #include "elf-int.h"
@@ -285,7 +286,6 @@ static bool do_elf_string_loading(GElfLoading *loading, GElfFormat *format, phys
     const mrange_t *range;                  /* Espace occupé par une chaîne*/
     GBinSymbol *symbol;                     /* Symbole à intégrer          */
     bool cut;                               /* Coupure par étiquette ?     */
-    char *label;                            /* Désignation de la chaîne    */
 
     result = false;
 
@@ -355,7 +355,7 @@ static bool do_elf_string_loading(GElfLoading *loading, GElfFormat *format, phys
         {
             range = g_arch_instruction_get_range(instr);
 
-            symbol = g_binary_symbol_new(range, STP_RO_STRING);
+            symbol = g_string_symbol_new_read_only(base, range, SET_GUESS);
             g_binary_format_add_symbol(base, symbol);
 
             /* Jointure avec la chaîne précédente ? */
@@ -366,14 +366,7 @@ static bool do_elf_string_loading(GElfLoading *loading, GElfFormat *format, phys
                 cut = (data[*iter - offset - 1] == '\0');
 
             if (cut)
-            {
-                label = create_string_label(base, get_mrange_addr(range), end - *iter);
-
-                g_binary_symbol_set_alt_label(symbol, label);
-
-                free(label);
-
-            }
+                g_string_symbol_build_label(G_STR_SYMBOL(symbol), base);
 
         }
 
diff --git a/plugins/pychrysalide/format/symbol.c b/plugins/pychrysalide/format/symbol.c
index 7dcb0eb..d6298d4 100644
--- a/plugins/pychrysalide/format/symbol.c
+++ b/plugins/pychrysalide/format/symbol.c
@@ -342,13 +342,14 @@ static bool py_binary_symbol_define_constants(PyTypeObject *obj_type)
     result &= PyDict_AddIntMacro(obj_type, STP_CODE_LABEL);
     result &= PyDict_AddIntMacro(obj_type, STP_OBJECT);
     result &= PyDict_AddIntMacro(obj_type, STP_ENTRY_POINT);
-    result &= PyDict_AddIntMacro(obj_type, STP_STRING);
     result &= PyDict_AddIntMacro(obj_type, STP_RO_STRING);
+    result &= PyDict_AddIntMacro(obj_type, STP_DYN_STRING);
     result &= PyDict_AddIntMacro(obj_type, STP_COUNT);
 
     result &= PyDict_AddIntMacro(obj_type, SSS_INTERNAL);
     result &= PyDict_AddIntMacro(obj_type, SSS_EXPORTED);
     result &= PyDict_AddIntMacro(obj_type, SSS_IMPORTED);
+    result &= PyDict_AddIntMacro(obj_type, SSS_DYNAMIC);
 
     return result;
 
diff --git a/plugins/readelf/strtab.c b/plugins/readelf/strtab.c
index e8d0f45..3cbe353 100644
--- a/plugins/readelf/strtab.c
+++ b/plugins/readelf/strtab.c
@@ -29,6 +29,7 @@
 
 
 #include <arch/raw.h>
+#include <format/strsym.h>
 #include <plugins/elf/section.h>
 
 
@@ -67,7 +68,6 @@ static void parse_elf_string_table(GElfFormat *format, GPreloadInfo *info, const
     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    */
 
     length = get_mrange_length(range);
 
@@ -112,23 +112,13 @@ static void parse_elf_string_table(GElfFormat *format, GPreloadInfo *info, const
             {
                 irange = g_arch_instruction_get_range(instr);
 
-                symbol = g_binary_symbol_new(irange, STP_RO_STRING);
+                symbol = g_string_symbol_new_read_only(base, irange, SET_GUESS);
                 g_binary_format_add_symbol(base, symbol);
 
                 /* Jointure avec la chaîne précédente ? */
 
                 if (cut)
-                {
-                    copy_vmpa(&pos, get_mrange_addr(range));
-                    advance_vmpa(&pos, i);
-
-                    label = create_string_label(base, get_mrange_addr(irange), end - i);
-
-                    g_binary_symbol_set_alt_label(symbol, label);
-
-                    free(label);
-
-                }
+                    g_string_symbol_build_label(G_STR_SYMBOL(symbol), base);
 
             }
 
diff --git a/src/arch/target.c b/src/arch/target.c
index bdae746..a2e1f34 100644
--- a/src/arch/target.c
+++ b/src/arch/target.c
@@ -37,6 +37,7 @@
 #include "../analysis/routine.h"
 #include "../common/extstr.h"
 #include "../format/format.h"
+#include "../format/strsym.h"
 #include "../glibext/gbinarycursor.h"
 
 
@@ -422,8 +423,8 @@ static char *g_target_operand_build_tooltip(const GTargetOperand *operand, const
                 result = g_binary_routine_build_tooltip(G_BIN_ROUTINE(operand->symbol), binary);
                 break;
 
-            case STP_STRING:
             case STP_RO_STRING:
+            case STP_DYN_STRING:
 
                 srange = g_binary_symbol_get_range(operand->symbol);
 
@@ -499,9 +500,10 @@ bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool
 {
     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    */
+#ifndef NDEBUG
+    const mrange_t *range;                  /* Couverture du symbole       */
+#endif
 
     if (operand->symbol != NULL)
         g_object_unref(G_OBJECT(operand->symbol));
@@ -528,9 +530,7 @@ bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool
     {
         symbol = operand->symbol;
 
-        stype = g_binary_symbol_get_target_type(symbol);
-
-        if (stype == STP_STRING || stype == STP_RO_STRING)
+        if (G_IS_STR_SYMBOL(symbol))
         {
             label = g_binary_symbol_get_label(symbol);
 
@@ -539,15 +539,13 @@ bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool
 
             else
             {
+#ifndef NDEBUG
                 range = g_binary_symbol_get_range(symbol);
 
                 assert(cmp_vmpa(&operand->addr, get_mrange_addr(range)) == 0);
+#endif
 
-                label = create_string_label(format, get_mrange_addr(range), get_mrange_length(range));
-
-                g_binary_symbol_set_alt_label(symbol, label);
-
-                free(label);
+                g_string_symbol_build_label(G_STR_SYMBOL(symbol), format);
 
             }
 
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 7a13aa8..3fabc73 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -2,6 +2,7 @@
 noinst_LTLIBRARIES = libcommon.la
 
 libcommon_la_SOURCES =					\
+	alloc.h alloc.c						\
 	array.h array.c						\
 	asm.h asm.c							\
 	bconst.h							\
diff --git a/src/common/alloc.c b/src/common/alloc.c
new file mode 100644
index 0000000..70f2f01
--- /dev/null
+++ b/src/common/alloc.c
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * alloc.c - gestion particulière des allocations
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "alloc.h"
+
+
+#include <malloc.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ptr       = pointeur à traiter.                              *
+*                allocated = taille actuellement allouée. [OUT]               *
+*                needed    = taille finale nécessaire.                        *
+*                                                                             *
+*  Description : Assure qu'une zone de mémoire allouée a la taille requise.   *
+*                                                                             *
+*  Retour      : Pointeur à utiliser avec assurance.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void *ensure_allocation_size(void *ptr, size_t *allocated, size_t needed)
+{
+    void *result;                           /* Pointeur à renvoyer         */
+
+    if (needed < *allocated)
+        result = ptr;
+
+    else
+    {
+        *allocated = needed;
+        result = realloc(ptr, needed);
+    }
+
+    return result;
+
+}
diff --git a/src/common/alloc.h b/src/common/alloc.h
new file mode 100644
index 0000000..5dd564e
--- /dev/null
+++ b/src/common/alloc.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * alloc.h - prototypes pour une gestion particulière des allocations
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _COMMON_ALLOC_H
+#define _COMMON_ALLOC_H
+
+
+#include <sys/types.h>
+
+
+
+/* Assure qu'une zone de mémoire allouée a la taille requise. */
+void *ensure_allocation_size(void *, size_t *, size_t);
+
+
+
+#endif  /* _COMMON_ALLOC_H */
diff --git a/src/format/Makefile.am b/src/format/Makefile.am
index 504055d..8a47b82 100644
--- a/src/format/Makefile.am
+++ b/src/format/Makefile.am
@@ -12,6 +12,7 @@ libformat_la_SOURCES =					\
 	format.h format.c					\
 	preload-int.h						\
 	preload.h preload.c					\
+	strsym.h strsym.c					\
 	symiter.h symiter.c					\
 	symbol-int.h						\
 	symbol.h symbol.c
diff --git a/src/format/format.c b/src/format/format.c
index 449f0f0..91cca37 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -25,7 +25,6 @@
 
 
 #include <assert.h>
-#include <ctype.h>
 #include <malloc.h>
 #include <string.h>
 
@@ -957,96 +956,6 @@ static void g_binary_format_delete_duplicated_symbols(GBinFormat *format)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
-*                addr   = adresse liée à la chaîne à traiter.                 *
-*                length = taille de la chaîne à représenter.                  *
-*                                                                             *
-*  Description : Construit une désignation pour chaîne de caractères.         *
-*                                                                             *
-*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-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          */
-    bool empty;                             /* Base de l'étiquette vide ?  */
-    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;
-
-    iter = 0;
-
-    for (i = 0; i < length; i++)
-    {
-        if (isalnum(base[i])) result[iter++] = tolower(base[i]);
-
-        else if (iter > 0)
-        {
-            if (result[iter - 1] != '_') wc++;
-
-            if (wc == 3) break;
-
-            if (result[iter - 1] != '_') result[iter++] = '_';
-
-        }
-
-    }
-
-    /* Détermination du suffixe suffisant */
-
-    empty = (iter == 0);
-
-    if (iter > 0 && result[iter - 1] != '_') result[iter++] = '_';
-
-    strcpy(&result[iter], "str");
-    iter += 3;
-
-    found = NULL;
-
-    if (empty || g_binary_format_find_symbol_by_label(format, result, &found))
-    {
-        if (found != NULL)
-            g_object_unref(G_OBJECT(found));
-
-        if (iter > 0 && result[iter - 1] != '_') result[iter++] = '_';
-
-        assert(has_phys_addr(addr) || has_virt_addr(addr));
-
-        /* TODO : use_phy_instead_of_virt */
-        if (has_virt_addr(addr))
-            vmpa2_virt_to_string(addr, MDS_UNDEFINED, last_sfx, NULL);
-        else
-            vmpa2_phys_to_string(addr, MDS_UNDEFINED, last_sfx, NULL);
-
-        strcpy(&result[iter], last_sfx);
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = informations chargées à consulter.                  *
 *                label  = étiquette à retrouver lors des recherches.          *
 *                symbol = éventuel symbole trouvé à déréfenrencer. [OUT]      *
 *                                                                             *
diff --git a/src/format/format.h b/src/format/format.h
index 372b3b0..a9152ba 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -132,9 +132,6 @@ bool g_binary_format_add_symbol(GBinFormat *, GBinSymbol *);
 /* Retire un symbole de la collection du format binaire. */
 void g_binary_format_remove_symbol(GBinFormat *, GBinSymbol *);
 
-/* Construit une désignation pour chaîne de caractères. */
-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 **);
 
diff --git a/src/format/strsym.c b/src/format/strsym.c
new file mode 100644
index 0000000..b709b93
--- /dev/null
+++ b/src/format/strsym.c
@@ -0,0 +1,474 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strsym.c - gestion des chaînes dans un binaire
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "strsym.h"
+
+
+#include <assert.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "symbol-int.h"
+#include "../common/alloc.h"
+
+
+
+/* ----------------------- VITRINE POUR CHAINES DE CARACTERES ----------------------- */
+
+
+/* Symbole pour chaîne de caractères (instance) */
+struct _GStrSymbol
+{
+    GBinSymbol parent;                      /* A laisser en premier        */
+
+    StringEncodingType encoding;            /* Encodage de la chaîne liée  */
+
+    union
+    {
+        GBinContent *content;               /* Conteneur d'origine         */
+        char *utf8;                         /* Données utilisables         */
+
+    };
+
+    bool has_content;                       /* Choix dans l'union          */
+
+};
+
+/* Symbole pour chaîne de caractères (classe) */
+struct _GStrSymbolClass
+{
+    GBinSymbolClass parent;                 /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des chaînes de caractères. */
+static void g_string_symbol_class_init(GStrSymbolClass *);
+
+/* Initialise une instance de chaîne de caractères. */
+static void g_string_symbol_init(GStrSymbol *);
+
+/* Supprime toutes les références externes. */
+static void g_string_symbol_dispose(GStrSymbol *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_string_symbol_finalize(GStrSymbol *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         VITRINE POUR CHAINES DE CARACTERES                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un symbole d'exécutable. */
+/*
+G_DEFINE_TYPE_WITH_CODE(GStrSymbol, g_string_symbol, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_string_symbol_interface_init));
+*/
+G_DEFINE_TYPE(GStrSymbol, g_string_symbol, G_TYPE_BIN_SYMBOL);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des chaînes de caractères.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_string_symbol_class_init(GStrSymbolClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_string_symbol_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_string_symbol_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : symbol = instance à initialiser.                             *
+*                                                                             *
+*  Description : Initialise une instance de chaîne de caractères.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_string_symbol_init(GStrSymbol *symbol)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : symbol = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_string_symbol_dispose(GStrSymbol *symbol)
+{
+    if (symbol->has_content)
+        g_object_unref(G_OBJECT(symbol->content));
+
+    G_OBJECT_CLASS(g_string_symbol_parent_class)->dispose(G_OBJECT(symbol));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : symbol = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_string_symbol_finalize(GStrSymbol *symbol)
+{
+    G_OBJECT_CLASS(g_string_symbol_parent_class)->finalize(G_OBJECT(symbol));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format   = format binaire reconnu.                           *
+*                range    = espace couvert par le nouveau symbole.            *
+*                encoding = encodage de la chaîne de caractères à représenter.*
+*                                                                             *
+*  Description : Crée un nouveau symbole pour chaîne de caractères.           *
+*                                                                             *
+*  Retour      : Adresse de l'instance mise en place ou NULL en cas d'échec.  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinSymbol *g_string_symbol_new_read_only(GBinFormat *format, const mrange_t *range, StringEncodingType encoding)
+{
+    GStrSymbol *result;                     /* Nouveau symbole à renvoyer  */
+    GBinSymbol *parent;                     /* Type d'instance parent      */
+    vmpa2t pos;                             /* Tête de lecture modifiable  */
+    phys_t length;                          /* Taille de la chaîne         */
+    const char *base;                       /* Contenu complet et original */
+
+    result = g_object_new(G_TYPE_STR_SYMBOL, NULL);
+
+    parent = G_BIN_SYMBOL(result);
+
+    g_binary_symbol_set_range(parent, range);
+    g_binary_symbol_set_target_type(parent, STP_RO_STRING);
+
+    result->encoding = encoding;
+
+    result->content = g_binary_format_get_content(format);
+    result->has_content = true;
+
+    switch (encoding)
+    {
+        case SET_ASCII:
+            break;
+
+        case SET_UTF_8:
+        case SET_MUTF_8:
+
+            copy_vmpa(&pos, get_mrange_addr(range));
+            length = get_mrange_length(range);
+
+            base = (const char *)g_binary_content_get_raw_access(result->content, &pos, length);
+
+            if (!g_utf8_validate(base, -1, NULL))
+                result->encoding = SET_ASCII;
+
+            break;
+
+        case SET_GUESS:
+
+            copy_vmpa(&pos, get_mrange_addr(range));
+            length = get_mrange_length(range);
+
+            base = (const char *)g_binary_content_get_raw_access(result->content, &pos, length);
+
+            if (g_str_is_ascii(base))
+                result->encoding = SET_ASCII;
+
+            else if (g_utf8_validate(base, -1, NULL))
+                result->encoding = SET_UTF_8;
+
+            else
+                result->encoding = SET_ASCII;
+
+            break;
+
+    }
+
+    return G_BIN_SYMBOL(result);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : symbol = symbole à venir consulter.                          *
+*                                                                             *
+*  Description : Fournit l'encodage d'une chaîne de caractères.               *
+*                                                                             *
+*  Retour      : Type d'encodage utilisé.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+StringEncodingType g_string_symbol_get_encoding(const GStrSymbol *symbol)
+{
+    StringEncodingType result;              /* Type à retourner            */
+
+    result = symbol->encoding;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : symbol = chaîne de caractères à consulter.                   *
+*                format = informations chargées à consulter.                  *
+*                                                                             *
+*  Description : Construit une désignation pour chaîne de caractères.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération de mise en place.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_string_symbol_build_label(GStrSymbol *symbol, GBinFormat *format)
+{
+    const mrange_t *range;                  /* Couverture du symbole       */
+    vmpa2t pos;                             /* Tête de lecture modifiable  */
+    phys_t length;                          /* Taille de la chaîne         */
+    const char *base;                       /* Contenu complet et original */
+    size_t allocated;                       /* Taille réservée             */
+    char *label;                            /* Etiquette à constituer      */
+    size_t cur;                             /* Point d'écriture courant    */
+    unsigned int wc;                        /* Nombre de mots rencontrés   */
+    size_t i;                               /* Boucle de parcours #1       */
+    char *iter;                             /* Boucle de parcours #2       */
+    gunichar c;                             /* Caractère unicode           */
+    gchar *converted;                       /* Caractère converti          */
+    glong size;                             /* Taille du caractère         */
+    bool empty;                             /* Base de l'étiquette vide ?  */
+    GBinSymbol *found;                      /* Symbole similaire trouvé    */
+    VMPA_BUFFER(last_sfx);                  /* Dernier suffixe à intégrer  */
+
+    /* Base de décision */
+
+    range = g_binary_symbol_get_range(G_BIN_SYMBOL(symbol));
+
+    copy_vmpa(&pos, get_mrange_addr(range));
+
+    switch (g_binary_symbol_get_target_type(G_BIN_SYMBOL(symbol)))
+    {
+        case STP_RO_STRING:
+            length = get_mrange_length(range);
+            base = (const char *)g_binary_content_get_raw_access(symbol->content, &pos, length);
+            break;
+
+        case STP_DYN_STRING:
+            base = symbol->utf8;
+            length = strlen((char *)base);
+            break;
+
+        default:
+            assert(false);
+            base = NULL;
+            break;
+
+    }
+
+    if (base == NULL)
+        return false;
+
+    /* Phase de constitution */
+
+    allocated = length + 5 + VMPA_MAX_LEN + 1;
+    label = (char *)malloc(allocated * sizeof(char));
+
+    cur = 0;
+
+    wc = 0;
+
+    /**
+     * Version simple et rapide.
+     */
+    if (symbol->encoding == SET_ASCII || g_str_is_ascii(base))
+    {
+        for (i = 0; i < length; i++)
+        {
+            if (isalnum(base[i])) label[cur++] = tolower(base[i]);
+
+            else if (cur > 0)
+            {
+                if (label[cur - 1] != '_') wc++;
+
+                if (wc == 3) break;
+
+                if (label[cur - 1] != '_') label[cur++] = '_';
+
+            }
+
+        }
+
+    }
+
+    /**
+     * Version complète.
+     */
+    else
+    {
+        for (iter = g_utf8_offset_to_pointer(base, 0);
+             iter != NULL;
+             iter = g_utf8_find_next_char(iter, NULL))
+        {
+            c = g_utf8_get_char_validated(iter, -1);
+
+            /**
+             * Si le caractère n'est pas valide (chaîne chiffrée ?)...
+             */
+            if (c == (gunichar)-1 || c == (gunichar)-2)
+                break;
+
+            if (c == '\0')
+                break;
+
+            else if (g_unichar_isalnum(c))
+            {
+                c = g_unichar_tolower(c);
+
+                converted = g_ucs4_to_utf8(&c, 1, NULL, &size, NULL);
+
+                label = ensure_allocation_size(label, &allocated, cur + size);
+
+                memcpy(label + cur, converted, size);
+
+                g_free(converted);
+
+                cur += size;
+
+            }
+
+            else if (cur > 0)
+            {
+                if (label[cur - 1] != '_') wc++;
+
+                if (wc == 3) break;
+
+                if (label[cur - 1] != '_')
+                {
+                    label = ensure_allocation_size(label, &allocated, cur + 1);
+                    label[cur++] = '_';
+                }
+
+            }
+
+        }
+
+    }
+
+    empty = (cur == 0);
+
+    if (!empty && label[cur - 1] != '_')
+    {
+        label = ensure_allocation_size(label, &allocated, cur + 1);
+        label[cur++] = '_';
+    }
+
+    label = ensure_allocation_size(label, &allocated, cur + 4);
+
+    strcpy(label + cur, "str");
+    cur += 3;
+
+    /* Détermination du suffixe suffisant */
+
+    found = NULL;
+
+    if (empty || g_binary_format_find_symbol_by_label(format, label, &found))
+    {
+        if (found != NULL)
+            g_object_unref(G_OBJECT(found));
+
+        if (label[cur - 1] != '_')
+        {
+            label = ensure_allocation_size(label, &allocated, cur + 1);
+            label[cur++] = '_';
+        }
+
+        copy_vmpa(&pos, get_mrange_addr(range));
+
+        assert(has_phys_addr(&pos) || has_virt_addr(&pos));
+
+        if (has_virt_addr(&pos))
+            vmpa2_virt_to_string(&pos, MDS_UNDEFINED, last_sfx, NULL);
+        else
+            vmpa2_phys_to_string(&pos, MDS_UNDEFINED, last_sfx, NULL);
+
+        label = ensure_allocation_size(label, &allocated, cur + strlen(last_sfx) + 1);
+
+        strcpy(label + cur, last_sfx);
+
+    }
+
+    /* Application */
+
+    g_binary_symbol_set_alt_label(G_BIN_SYMBOL(symbol), label);
+
+    free(label);
+
+    return true;
+
+}
diff --git a/src/format/strsym.h b/src/format/strsym.h
new file mode 100644
index 0000000..e827e6a
--- /dev/null
+++ b/src/format/strsym.h
@@ -0,0 +1,80 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strsym.h - prototypes pour la gestion des chaînes dans un binaire
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _FORMAT_STRSYM_H
+#define _FORMAT_STRSYM_H
+
+
+#include <glib-object.h>
+
+
+#include "format.h"
+#include "symbol.h"
+
+
+
+/* ----------------------- VITRINE POUR CHAINES DE CARACTERES ----------------------- */
+
+
+/* Types de chaînes */
+typedef enum _StringEncodingType
+{
+    SET_ASCII,                              /* Format brut                 */
+    SET_UTF_8,                              /* Format UTF-8                */
+    SET_MUTF_8,                             /* Format UTF-8 modifié        */
+
+    SET_GUESS,                              /* Détection automatique       */
+
+} StringEncodingType;
+
+
+#define G_TYPE_STR_SYMBOL               g_string_symbol_get_type()
+#define G_STR_SYMBOL(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_string_symbol_get_type(), GStrSymbol))
+#define G_IS_STR_SYMBOL(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_string_symbol_get_type()))
+#define G_STR_SYMBOL_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STR_SYMBOL, GStrSymbolClass))
+#define G_IS_STR_SYMBOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STR_SYMBOL))
+#define G_STR_SYMBOL_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STR_SYMBOL, GStrSymbolClass))
+
+
+/*/* Symbole pour chaîne de caractères (instance) */
+typedef struct _GStrSymbol GStrSymbol;
+
+/* Symbole pour chaîne de caractères (classe) */
+typedef struct _GStrSymbolClass GStrSymbolClass;
+
+
+/* Indique le type défini pour un symbole d'exécutable. */
+GType g_string_symbol_get_type(void);
+
+/* Crée un nouveau symbole pour chaîne de caractères. */
+GBinSymbol *g_string_symbol_new_read_only(GBinFormat *, const mrange_t *, StringEncodingType);
+
+/* Fournit l'encodage d'une chaîne de caractères. */
+StringEncodingType g_string_symbol_get_encoding(const GStrSymbol *);
+
+/* Construit une désignation pour chaîne de caractères. */
+bool g_string_symbol_build_label(GStrSymbol *, GBinFormat *);
+
+
+
+#endif  /* _FORMAT_STRSYM_H */
diff --git a/src/format/symbol.h b/src/format/symbol.h
index 13747d4..577a6a0 100644
--- a/src/format/symbol.h
+++ b/src/format/symbol.h
@@ -43,8 +43,8 @@ typedef enum _SymbolType
     STP_CODE_LABEL,                         /* Renvoi au sein de code      */
     STP_OBJECT,                             /* Objet quelconque            */
     STP_ENTRY_POINT,                        /* Morceau de code en entrée   */
-    STP_STRING,                             /* Chaîne de caractères        */
-    STP_RO_STRING,                          /* Chaîne de caractères        */
+    STP_RO_STRING,                          /* Chaîne d'origine            */
+    STP_DYN_STRING,                         /* Chaîne créée ex-nihilo      */
 
     STP_COUNT
 
@@ -57,6 +57,7 @@ typedef enum _SymbolStatus
     SSS_INTERNAL,                           /* Visibilité nulle            */
     SSS_EXPORTED,                           /* Disponibilité extérieure    */
     SSS_IMPORTED,                           /* Besoin interne              */
+    SSS_DYNAMIC,                            /* Création durant l'analyse   */
 
     SSS_COUNT
 
diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c
index 6e9324f..895a1b9 100644
--- a/src/gui/panels/strings.c
+++ b/src/gui/panels/strings.c
@@ -39,6 +39,7 @@
 #include "../../core/params.h"
 #include "../../core/queue.h"
 #include "../../format/format.h"
+#include "../../format/strsym.h"
 #include "../../format/symiter.h"
 #include "../../gtkext/easygtk.h"
 #include "../../gtkext/gtkdisplaypanel.h"
@@ -766,7 +767,7 @@ static void reload_strings_for_new_list_view(const GStringsPanel *panel, GtkStat
          symbol != NULL;
          symbol = get_symbol_iterator_next(siter))
     {
-        if (g_binary_symbol_get_target_type(symbol) != STP_RO_STRING)
+        if (!G_IS_STR_SYMBOL(symbol))
             goto rsfnlv_next;
 
         range = g_binary_symbol_get_range(symbol);
@@ -1378,21 +1379,10 @@ static bool is_string_name_matching(const strings_update_data *data, GtkTreeMode
 {
     bool result;                            /* Bilan à retourner           */
     GBinSymbol *symbol;                     /* Symbole manipulé            */
-#ifndef NDEBUG
-    SymbolType type;                        /* Type associé au symbole     */
-#endif
     char *label;                            /* Etiquette à analyser        */
 
     gtk_tree_model_get(model, iter, STC_SYMBOL, &symbol, -1);
-    assert(symbol != NULL);
-
-#ifndef NDEBUG
-
-    type = g_binary_symbol_get_target_type(symbol);
-
-    assert(type == STP_RO_STRING);
-
-#endif
+    assert(G_IS_STR_SYMBOL(symbol));
 
     label = g_binary_symbol_get_label(symbol);
 
-- 
cgit v0.11.2-87-g4458