From dc9e68505c4cc7ad208e63dbc7d0e0e8f582d0d9 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 3 Mar 2015 23:51:04 +0000
Subject: Loaded and displayed found strings in ELF.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@481 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                |  22 +++++++-
 src/arch/arm/v7/post.c   |   8 +--
 src/arch/raw.c           | 132 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/arch/raw.h           |   6 +++
 src/format/elf/strings.c |  80 ++++++++++++++++++++++------
 src/format/format.c      |  84 ++++++++++++++++++++++++++++++
 src/format/format.h      |   3 ++
 src/format/symbol.c      |  15 ++++++
 src/format/symbol.h      |  15 ++++++
 9 files changed, 342 insertions(+), 23 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6c31b70..ed1a6f7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+15-03-04  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/arm/v7/post.c:
+	Add some comments for variables.
+
+	* src/arch/raw.c:
+	* src/arch/raw.h:
+	Deal with strings as raw instructions.
+
+	* src/format/elf/strings.c:
+	Load and display found strings in ELF.
+
+	* src/format/format.c:
+	* src/format/format.h:
+	Create labels for string data.
+
+	* src/format/symbol.c:
+	* src/format/symbol.h:
+	Allow to define labels and register string symbols.
+
 15-02-25  Cyrille Bagard <nocbos@gmail.com>
 
 	* plugins/pychrysa/gtkext/viewpanel.c:
@@ -22,7 +42,7 @@
 	Update.
 
 	* src/project.c:
-	Wait a little bit before being abl able to use sizes to compute the position of the entry point.
+	Wait before using sizes to compute the position of the entry point.
 
 15-02-24  Cyrille Bagard <nocbos@gmail.com>
 
diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c
index 084fc84..c7b0f64 100644
--- a/src/arch/arm/v7/post.c
+++ b/src/arch/arm/v7/post.c
@@ -51,7 +51,7 @@ void post_process_branch_instructions(GArchInstruction *instr, GProcContext *con
     uint32_t addr;                          /* Adresse visée par le saut   */
     GArchOperand *new;                      /* Instruction de ciblage      */
     vmpa2t target;
-    mrange_t trange;
+    mrange_t trange;                        /* Etendue du symbole à créer  */
     VMPA_BUFFER(loc);
     char name[5 + VMPA_MAX_LEN];
     GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
@@ -114,7 +114,7 @@ void post_process_branch_and_link_instructions(GArchInstruction *instr, GProcCon
     uint32_t addr;                          /* Adresse visée par le saut   */
     GArchOperand *new;                      /* Instruction de ciblage      */
     vmpa2t target;
-    mrange_t trange;
+    mrange_t trange;                        /* Etendue du symbole à créer  */
     VMPA_BUFFER(loc);
     char name[5 + VMPA_MAX_LEN];
     GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
@@ -177,7 +177,7 @@ void post_process_comp_and_branch_instructions(GArchInstruction *instr, GProcCon
     uint32_t addr;                          /* Adresse visée par le saut   */
     GArchOperand *new;                      /* Instruction de ciblage      */
     vmpa2t target;
-    mrange_t trange;
+    mrange_t trange;                        /* Etendue du symbole à créer  */
     VMPA_BUFFER(loc);
     char name[5 + VMPA_MAX_LEN];
     GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
@@ -240,7 +240,7 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex
     uint32_t addr;                          /* Adresse visée par le saut   */
     GArchOperand *new;                      /* Instruction de ciblage      */
     vmpa2t target;
-    mrange_t trange;
+    mrange_t trange;                        /* Etendue du symbole à créer  */
     VMPA_BUFFER(loc);
     char name[5 + VMPA_MAX_LEN];
     GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
diff --git a/src/arch/raw.c b/src/arch/raw.c
index 808d973..3338613 100644
--- a/src/arch/raw.c
+++ b/src/arch/raw.c
@@ -24,6 +24,8 @@
 #include "raw.h"
 
 
+#include <assert.h>
+#include <ctype.h>
 #include <string.h>
 
 
@@ -41,6 +43,7 @@ struct _GRawInstruction
     GArchInstruction parent;                /* A laisser en premier        */
 
     bool is_padding;                        /* Bourrage à représenter ?    */
+    bool is_string;                         /* Chaîne de caractères ?      */
 
 };
 
@@ -370,16 +373,24 @@ static GBufferLine *g_raw_instruction_print(const GRawInstruction *instr, GCodeB
     GArchInstruction *base;                 /* Autre version de l'instance */
     const char *key;                        /* Mot clef principal          */
     size_t klen;                            /* Taille de ce mot clef       */
+    char *string;                           /* Chaîne reconstituée         */
+    size_t iter;                            /* Tête d'écriture             */
+    bool first;                             /* Mémorise une énumération    */
+    size_t i;                               /* Boucle de parcours          */
+    char byte;                              /* Octet à afficher (ou pas)   */
+    bool status;                            /* Bilan d'une récupération    */
 
     base = G_ARCH_INSTRUCTION(instr);
 
-    if (!instr->is_padding)
+    if (!instr->is_padding && !instr->is_string)
         result = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class)->print(base, buffer, msize, content, syntax);
 
     else
     {
         result = g_code_buffer_append_new_line(buffer, &base->range);
 
+        g_buffer_line_add_flag(result, BLF_HAS_CODE);
+
         g_buffer_line_fill_for_instr(result, msize/* TODO ! */, msize, content, base->length, true);
 
         /* Instruction proprement dite */
@@ -389,7 +400,84 @@ static GBufferLine *g_raw_instruction_print(const GRawInstruction *instr, GCodeB
 
         g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION);
 
-        g_buffer_line_insert_text(result, BLC_ASSEMBLY, "...", 3, RTT_RAW);
+        if (instr->is_padding)
+            g_buffer_line_insert_text(result, BLC_ASSEMBLY, "...", 3, RTT_RAW);
+
+        else /*if (instr->is_string)*/
+        {
+            string = (char *)calloc(base->operands_count + 3, sizeof(char));
+
+            strcpy(string, "\"");
+            iter = 1;
+
+            first = true;
+
+            for (i = 0; i < base->operands_count; i++)
+            {
+                status = g_imm_operand_get_value(G_IMM_OPERAND(base->operands[i]), MDS_8_BITS, &byte);
+                assert(status);
+
+                /* Si le caractère doit apparaître en hexadécimal... */
+                if (!isprint(byte))
+                {
+                    /* Si une chaîne précède */
+                    if (iter > 1)
+                    {
+                        if (!first)
+                        {
+                            g_buffer_line_insert_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
+                            g_buffer_line_insert_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+                        }
+                        else
+                            first = false;
+
+                        string[iter++] = '"';
+
+                        g_buffer_line_insert_text(result, BLC_ASSEMBLY, string, iter, RTT_STRING);
+
+                        iter = 1;
+
+                    }
+
+                    /* Impression de l'octet */
+
+                    if (!first)
+                    {
+                        g_buffer_line_insert_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
+                        g_buffer_line_insert_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+                    }
+                    else
+                        first = false;
+
+                    g_arch_operand_print(base->operands[i], result, syntax);
+
+                }
+
+                else
+                    string[iter++] = byte;
+
+            }
+
+            /* Si une chaîne reste encore */
+            if (iter > 1)
+            {
+                if (!first)
+                {
+                    g_buffer_line_insert_text(result, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
+                    g_buffer_line_insert_text(result, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+                }
+                else
+                    first = false;
+
+                string[iter++] = '"';
+
+                g_buffer_line_insert_text(result, BLC_ASSEMBLY, string, iter, RTT_STRING);
+
+            }
+
+            free(string);
+
+        }
 
     }
 
@@ -465,3 +553,43 @@ bool g_raw_instruction_is_padding(const GRawInstruction *instr)
     return instr->is_padding;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr     = instruction à traiter.                           *
+*                is_string = nouveau statut à associer au contenu.            *
+*                                                                             *
+*  Description : Marque l'instruction comme contenant une chaîne de texte.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string)
+{
+    instr->is_string = is_string;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr     = instruction à traiter.                           *
+*                is_string = nouveau statut à associer au contenu.            *
+*                                                                             *
+*  Description : Indique si le contenu de l'instruction est un texte.         *
+*                                                                             *
+*  Retour      : Statut du contenu de l'instruction.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_raw_instruction_is_string(const GRawInstruction *instr)
+{
+    return instr->is_string;
+
+}
diff --git a/src/arch/raw.h b/src/arch/raw.h
index f7e1715..6712b81 100644
--- a/src/arch/raw.h
+++ b/src/arch/raw.h
@@ -67,6 +67,12 @@ void g_raw_instruction_mark_as_padding(GRawInstruction *, bool);
 /* Indique si le contenu de l'instruction est du bourrage. */
 bool g_raw_instruction_is_padding(const GRawInstruction *);
 
+/* Marque l'instruction comme contenant une chaîne de texte. */
+void g_raw_instruction_mark_as_string(GRawInstruction *, bool);
+
+/* Indique si le contenu de l'instruction est un texte. */
+bool g_raw_instruction_is_string(const GRawInstruction *);
+
 
 
 #endif  /* _ARCH_RAW_H */
diff --git a/src/format/elf/strings.c b/src/format/elf/strings.c
index 09bd442..f2c5dd3 100644
--- a/src/format/elf/strings.c
+++ b/src/format/elf/strings.c
@@ -32,6 +32,7 @@
 
 #include "elf-int.h"
 #include "section.h"
+#include "../../arch/raw.h"
 
 
 
@@ -141,7 +142,7 @@ bool find_all_elf_strings(GElfFormat *format)
 *                                                                             *
 *  Description : Enregistre toutes les chaînes de caractères trouvées.        *
 *                                                                             *
-*  Retour      : true si des chaînes ont été ajoutées, false sinon.           *
+*  Retour      : true si des chaînes ont été ajoutées sans erreur, ou false.  *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
@@ -150,36 +151,83 @@ bool find_all_elf_strings(GElfFormat *format)
 bool parse_elf_string_data(GElfFormat *format, off_t start, off_t size, vmpa_t address)
 {
     bool result;                            /* Bilan à faire remonter      */
-    const bin_t *content;                   /* Contenu binaire à lire      */
-    off_t length;                           /* Taille totale du contenu    */
+    GBinContent *content;                   /* Contenu binaire à lire      */
+    char *data;                             /* Données copiées à traiter   */
+    vmpa2t pos;                             /* Tête de lecture             */
+    bool cut;                               /* Séparation nette ?          */
     off_t i;                                /* Boucle de parcours          */
     off_t end;                              /* Position de fin de chaîne   */
-    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
+    GArchInstruction *instr;                /* Instruction décodée         */
+    GBinSymbol *symbol;                     /* Symbole à intégrer          */
+    char *label;                            /* Désignation de la chaîne    */
 
     if (address == 0) return false;
 
     result = false;
 
-    content = G_BIN_FORMAT(format)->content;
-    length = G_BIN_FORMAT(format)->length;
+    /* Préparation des accès */
+
+    content = g_binary_format_get_conten_(G_BIN_FORMAT(format));
+
+    data = (char *)malloc(size * sizeof(char));
+
+    init_vmpa(&pos, start, address);
+
+    if (!g_binary_content_get_raw(content, &pos, size, (bin_t *)data))
+        goto pesd_error;
+
+    /* Boucle de parcours */
 
-    length = MIN(length, start + size);
+    cut = true;
 
-    for (i = start; i < length; i++)
-        if (isprint(content[i]))
+    for (i = 0; i < size; i++)
+        if (isprint(data[i]))
         {
-            for (end = i + 1; end < length; end++)
-                if (!isprint(content[end])) break;
- 
-            symbol = g_binary_symbol_new(STP_STRING, NULL, address + i - start);
-            g_binary_symbol_set_alt_name(symbol, strndup((const char *)&content[i], end - i));
+            for (end = i + 1; end < size; end++)
+                if (!isprint(data[end])) break;
+
+            if (isspace(data[end]) && (end + 1) < size)
+                end++;
+
+            if (data[end] == '\0' && (end + 1) < size)
+                end++;
+
+            init_vmpa(&pos, start + i, address + i);
+
+            instr = g_raw_instruction_new_array(G_BIN_FORMAT(format)->conten_, MDS_8_BITS,
+                                                end - i, &pos, format->endian);
+
+            g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true);
 
-            ///// reactiver g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+            ADD_STR_AS_SYM(format, symbol, instr);
 
-            i = end;
+            /* Jointure avec la chaîne précédente ? */
+
+            if (cut)
+            {
+                init_vmpa(&pos, start + i, address + i);
+
+                label = create_string_label(G_BIN_FORMAT(format), &pos, &data[i], end - i);
+
+                g_binary_symbol_set_label(symbol, label);
+
+                free(label);
+
+            }
+
+            /* Conclusion */
+
+            cut = (data[end - 1] == '\0');
+
+            i = end - 1;
             result = true;
 
         }
+        else cut = true;
+
+ pesd_error:
+
+    free(data);
 
     return result;
 
diff --git a/src/format/format.c b/src/format/format.c
index 6b63556..2808b67 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -24,6 +24,8 @@
 #include "format.h"
 
 
+#include <assert.h>
+#include <ctype.h>
 #include <malloc.h>
 #include <string.h>
 
@@ -224,6 +226,88 @@ 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.         *
+*                                                                             *
+*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *create_string_label(GBinFormat *format, const vmpa2t *addr, const char *base, size_t length)
+{
+    char *result;                           /* Nouvelle chaîne à retourner */
+    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  */
+
+    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 e23b4bd..38418b3 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -70,6 +70,9 @@ void g_binary_format_add_symbol(GBinFormat *, GBinSymbol *);
 /* Fournit la liste de tous les symboles détectés. */
 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);
+
 /* Recherche le symbole correspondant à une étiquette. */
 bool g_binary_format_find_symbol_by_label(const GBinFormat *, const char *, GBinSymbol **);
 
diff --git a/src/format/symbol.c b/src/format/symbol.c
index 7817d5f..8ab76b6 100644
--- a/src/format/symbol.c
+++ b/src/format/symbol.c
@@ -41,6 +41,8 @@ struct _GBinSymbol
 
     char *alt;                              /* Nom alternatif              */
 
+    char *tmp_label;    /* REMME */
+
     union
     {
         GArchInstruction *instr;            /* Instruction correspondante  */
@@ -255,6 +257,13 @@ vmpa_t g_binary_symbol_get_address(const GBinSymbol *symbol)
 
 
 
+void g_binary_symbol_set_label(GBinSymbol *symbol, const char *lbl)
+{
+    symbol->tmp_label = strdup(lbl);
+
+}
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : symbol = symbole à venir consulter.                          *
@@ -273,6 +282,12 @@ const char *g_binary_symbol_get_label(const GBinSymbol *symbol)
 
     result = NULL;
 
+
+    /* TODO : utiliser des types pour les instructions */
+    if (symbol->tmp_label != NULL)
+        return symbol->tmp_label;
+
+
     switch (symbol->type)
     {
         case STP_ROUTINE:
diff --git a/src/format/symbol.h b/src/format/symbol.h
index e123898..c3e53cc 100644
--- a/src/format/symbol.h
+++ b/src/format/symbol.h
@@ -79,6 +79,12 @@ const char *g_binary_symbol_to_string(const GBinSymbol *);
 /* Fournit l'adresse associée à un symbole. */
 vmpa_t g_binary_symbol_get_address(const GBinSymbol *); ///////////////////
 
+
+
+void g_binary_symbol_set_label(GBinSymbol *symbol, const char *lbl);
+
+
+
 /* Fournit un étiquette pour viser un symbole. */
 const char *g_binary_symbol_get_label(const GBinSymbol *);
 
@@ -133,6 +139,15 @@ GDbComment *g_binary_symbol_get_comment(const GBinSymbol *);
     }                                                           \
     while (0)
 
+#define ADD_STR_AS_SYM(_fmt, _sym, _ins)                        \
+    do                                                          \
+    {                                                           \
+        _sym = g_binary_symbol_new(STP_DATA, NULL, 0);          \
+        g_binary_symbol_attach_instruction(_sym, _ins);         \
+        g_binary_format_add_symbol(G_BIN_FORMAT(_fmt), _sym);   \
+    }                                                           \
+    while (0)
+
 
 
 #endif  /* _FORMAT_SYMBOL_H */
-- 
cgit v0.11.2-87-g4458