From b3471e0c9ce6cc1becc9f56832fb4b93b337cb21 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 2 Mar 2017 15:33:09 +0100
Subject: Filled rendering lines with relative binary contents.

---
 ChangeLog                  | 16 ++++++++
 src/analysis/disass/area.c |  3 ++
 src/arch/instruction-int.h |  1 +
 src/arch/instruction.c     | 26 +++++++++++++
 src/arch/instruction.h     |  3 ++
 src/arch/raw.c             |  2 +
 src/arch/undefined.c       |  2 +
 src/glibext/gbufferline.c  | 96 ++++++++++++++++++++++++++++++++++++++++++++++
 src/glibext/gbufferline.h  |  3 ++
 9 files changed, 152 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 09e5a32..e36de8b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+17-03-02  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	Set the global content for each collected instruction.
+
+	* src/arch/instruction-int.h:
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	* src/arch/raw.c:
+	* src/arch/undefined.c:
+	Remember the global content and print bytes of each instruction.
+
+	* src/glibext/gbufferline.c:
+	* src/glibext/gbufferline.h:
+	Fill rendering lines with relative binary contents.
+
 17-02-28  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/binary.c:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 8da8b60..74bdfd3 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -367,6 +367,9 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction
         area->instructions[offset] = instr;
         g_atomic_pointer_add(&area->count, 1);
 
+        /* Au passage, association du contenu */
+        g_arch_instruction_set_global_content(instr, area->content);
+
     }
 
     return result;
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index e7d5ba0..89f589a 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -53,6 +53,7 @@ struct _GArchInstruction
 
     const instr_hook_fc *hooks;             /* Traitements complémentaires */
 
+    const GBinContent *content;             /* Contenu binaire global      */
     mrange_t range;                         /* Emplacement en mémoire      */
 
     GArchOperand **operands;                /* Liste des opérandes         */
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index f539ddb..be049e1 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -190,6 +190,9 @@ static void g_arch_instruction_interface_init(GLineGeneratorInterface *iface)
 
 static void g_arch_instruction_dispose(GArchInstruction *instr)
 {
+    if (instr->content != NULL)
+        g_object_unref(G_OBJECT(instr->content));
+
     G_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr));
 
 }
@@ -324,6 +327,27 @@ void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instr   = instruction quelconque à modifier.                 *
+*                content = contenu binaire global à référencer.               *
+*                                                                             *
+*  Description : Note le contenu du sein duquel l'instruction est issue.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_instruction_set_global_content(GArchInstruction *instr, const GBinContent *content)
+{
+    g_object_ref(G_OBJECT(content));
+    instr->content = content;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction quelconque à modifier.                 *
 *                address = adresse virtuelle et/ou position physique.         *
 *                length  = taille de l'instruction.                           *
 *                                                                             *
@@ -1140,6 +1164,8 @@ static void _g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line
 
     g_buffer_line_fill_vmpa(line, get_mrange_addr(&instr->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED);
 
+    g_buffer_line_fill_content(line, instr->content, &instr->range, VMPA_NO_PHYSICAL);
+
     /* Instruction proprement dite */
 
     key = g_arch_instruction_get_keyword(instr, 0/*, syntax*/);
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 7323a2e..27c28f5 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -107,6 +107,9 @@ void g_arch_instruction_set_hooks(GArchInstruction *, const instr_hook_fc [IPH_C
 /* Complète un désassemblage accompli pour une instruction. */
 void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *);
 
+/* Note le contenu du sein duquel l'instruction est issue. */
+void g_arch_instruction_set_global_content(GArchInstruction *, const GBinContent *);
+
 /* Définit la localisation d'une instruction. */
 void g_arch_instruction_set_range(GArchInstruction *, const mrange_t *);
 
diff --git a/src/arch/raw.c b/src/arch/raw.c
index 8a44972..9b4a57d 100644
--- a/src/arch/raw.c
+++ b/src/arch/raw.c
@@ -479,6 +479,8 @@ static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, s
     {
         g_buffer_line_fill_vmpa(line, get_mrange_addr(&base->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED);
 
+        g_buffer_line_fill_content(line, base->content, &base->range, VMPA_NO_PHYSICAL);
+
         /* Instruction proprement dite */
 
         key = g_arch_instruction_get_keyword(base, 0/*, syntax*/);
diff --git a/src/arch/undefined.c b/src/arch/undefined.c
index 39b3e8b..8741c43 100644
--- a/src/arch/undefined.c
+++ b/src/arch/undefined.c
@@ -286,6 +286,8 @@ static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *lin
 
     g_buffer_line_fill_vmpa(line, get_mrange_addr(&base->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED);
 
+    g_buffer_line_fill_content(line, base->content, &base->range, VMPA_NO_PHYSICAL);
+
     /* Instruction proprement dite */
 
     key = g_arch_instruction_get_keyword(base, 0/*, syntax*/);
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index 5a7e53d..d9e974c 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -392,6 +392,102 @@ void g_buffer_line_fill_vmpa(GBufferLine *line, const vmpa2t *addr, MemoryDataSi
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : line    = ligne à venir compléter.                           *
+*                content = contenu binaire global à venir lire.               *
+*                range   = localisation des données à venir lire et présenter.*
+*                max     = taille maximale de la portion binaire en octets.   *
+*                                                                             *
+*  Description : Construit le tronc commun d'une ligne autour de son contenu. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_fill_content(GBufferLine *line, const GBinContent *content, const mrange_t *range, phys_t max)
+{
+    phys_t length;                          /* Taille de la couverture     */
+    bool truncated;                         /* Indique si le code est coupé*/
+    size_t required;                        /* Taille de traitement requise*/
+    char static_buffer[64];                 /* Petit tampon local rapide   */
+    char *bin_code;                         /* Tampon utilisé pour le code */
+    vmpa2t pos;                             /* Boucle de parcours #1       */
+    phys_t i;                               /* Boucle de parcours #2       */
+    char *iter;                             /* Boucle de parcours #3       */
+    int ret;                                /* Progression dans l'écriture */
+    uint8_t byte;                           /* Octet à représenter         */
+
+    static const char *charset = "0123456789abcdef";
+
+    /* Détermination du réceptacle */
+
+    length = get_mrange_length(range);
+
+    truncated = (max != VMPA_NO_PHYSICAL && length > max);
+
+    if (truncated)
+    {
+        length = max;
+        required = length * 3 + 4 /* "..." */ + 1;
+    }
+    else
+        required = length * 3 + 1;
+
+    if (required <= sizeof(static_buffer))
+        bin_code = static_buffer;
+    else
+        bin_code = (char *)calloc(required, sizeof(char));
+
+    /* Code brut */
+
+    copy_vmpa(&pos, get_mrange_addr(range));
+
+    for (i = 0, iter = bin_code; i < length; i++, iter += ret)
+    {
+        if (i == 0)
+            ret = 0;
+        else
+        {
+            iter[0] = ' ';
+            ret = 1;
+        }
+
+        if (!g_binary_content_read_u8(content, &pos, &byte))
+        {
+            iter[ret + 0] = '?';
+            iter[ret + 1] = '?';
+        }
+        else
+        {
+            iter[ret + 0] = charset[byte >> 4];
+            iter[ret + 1] = charset[byte & 0x0f];
+        }
+
+        ret += 2;
+
+    }
+
+    if (truncated)
+    {
+        strcpy(iter, "...");
+        iter += 3;
+    }
+    else
+        *iter = '\0';
+
+    /* Conclusion */
+
+    g_buffer_line_append_text(line, BLC_BINARY, bin_code, iter - bin_code, RTT_RAW_CODE, NULL);
+
+    if (bin_code != static_buffer)
+        free(bin_code);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : line  = ligne à venir compléter.                             *
 *                psize = taille souhaitée de l'impression des positions.      *
 *                vsize = taille souhaitée de l'impression des adresses.       *
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 3095086..9478404 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -117,6 +117,9 @@ void g_buffer_line_fill_virt(GBufferLine *, MemoryDataSize, const vmpa2t *);
 /* Construit le tronc commun d'une ligne autour de sa position. */
 void g_buffer_line_fill_vmpa(GBufferLine *, const vmpa2t *, MemoryDataSize, MemoryDataSize);
 
+/* Construit le tronc commun d'une ligne autour de son contenu. */
+void g_buffer_line_fill_content(GBufferLine *, const GBinContent *, const mrange_t *, phys_t);
+
 /* Construit le tronc commun d'une ligne autour de sa position. */
 void g_buffer_line_fill_mrange(GBufferLine *, MemoryDataSize, MemoryDataSize);
 
-- 
cgit v0.11.2-87-g4458