From 9ed9405f37244832570f48b42dced1c92704ba3d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 21 Aug 2021 00:31:12 +0200
Subject: Prepare architecture processors for serialization.

---
 src/arch/processor.c | 419 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 405 insertions(+), 14 deletions(-)

diff --git a/src/arch/processor.c b/src/arch/processor.c
index 59af6cd..1fbc14b 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -35,6 +35,8 @@
 
 #include "instruction-int.h"
 #include "processor-int.h"
+#include "../analysis/db/misc/rlestr.h"
+#include "../analysis/storage/serialize-int.h"
 #include "../common/sort.h"
 #include "../core/logs.h"
 #include "../glibext/chrysamarshal.h"
@@ -62,6 +64,9 @@ static void g_arch_processor_class_init(GArchProcessorClass *);
 /* Initialise une instance de processeur d'architecture. */
 static void g_arch_processor_init(GArchProcessor *);
 
+/* Procède à l'initialisation de l'interface de sérialisation. */
+static void g_arch_processor_serializable_init(GSerializableObjectInterface *);
+
 /* Supprime toutes les références externes. */
 static void g_arch_processor_dispose(GArchProcessor *);
 
@@ -73,10 +78,26 @@ static GProcContext *_g_arch_processor_get_context(const GArchProcessor *);
 
 
 
+/* ------------------ CONSERVATION DES SOUCIS DURANT LE CHARGEMENT ------------------ */
+
+
+/* Procède à la libération totale de la mémoire. */
+static void g_arch_processor_finalize_errors(GArchProcessor *);
+
+/* Charge les erreurs de chargement depuis une mémoire tampon. */
+static bool g_arch_processor_load_errors(GArchProcessor *, packed_buffer_t *);
+
+/* Sauvegarde les erreurs de chargement dans une mémoire tampon. */
+static bool g_arch_processor_store_errors(GArchProcessor *, packed_buffer_t *);
+
+
 
 /* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */
 
 
+/* Procède à la libération totale de la mémoire. */
+static void g_arch_processor_finalize_coverages(GArchProcessor *);
+
 /* Démarre la définition d'un nouveau groupe d'instructions. */
 static void g_arch_processor_add_new_coverage(GArchProcessor *, GArchInstruction *, size_t);
 
@@ -92,17 +113,35 @@ static void g_arch_processor_merge_coverages(GArchProcessor *, instr_coverage *,
 /* Met à jour une série de groupes d'instructions. */
 static void g_arch_processor_update_coverages(GArchProcessor *, instr_coverage *, bool);
 
+/* Charge les plages de couvertures depuis une mémoire tampon. */
+static bool g_arch_processor_load_coverages(GArchProcessor *, packed_buffer_t *);
+
+/* Sauvegarde les plages de couvertures dans une mémoire tampon. */
+static bool g_arch_processor_store_coverages(GArchProcessor *, packed_buffer_t *);
+
 /* Recherche rapidement un indice d'instruction via une adresse. */
 static bool g_arch_processor_find_covered_index_by_address(const GArchProcessor *, const instr_coverage *, const vmpa2t *, bool, size_t *);
 
 
 
+/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
+
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_arch_processor_load(GArchProcessor *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_arch_processor_store(GArchProcessor *, GObjectStorage *, packed_buffer_t *);
+
+
 
 
 
 
 /* Indique le type défini pour un processeur d'architecture. */
-G_DEFINE_TYPE(GArchProcessor, g_arch_processor, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_CODE(GArchProcessor, g_arch_processor, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_processor_serializable_init));
+
 
 
 /******************************************************************************
@@ -174,6 +213,26 @@ static void g_arch_processor_init(GArchProcessor *proc)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : iface = interface GLib à initialiser.                        *
+*                                                                             *
+*  Description : Procède à l'initialisation de l'interface de sérialisation.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_processor_serializable_init(GSerializableObjectInterface *iface)
+{
+    iface->load = (load_serializable_object_cb)g_arch_processor_load;
+    iface->store = (store_serializable_object_cb)g_arch_processor_store;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc = instance d'objet GLib à traiter.                      *
 *                                                                             *
 *  Description : Supprime toutes les références externes.                     *
@@ -224,23 +283,12 @@ static void g_arch_processor_dispose(GArchProcessor *proc)
 
 static void g_arch_processor_finalize(GArchProcessor *proc)
 {
-    size_t i;                               /* Boucle de parcours          */
-
     if (proc->instructions != NULL)
         free(proc->instructions);
 
-    if (proc->errors != NULL)
-    {
-        for (i = 0; i < proc->error_count; i++)
-            if (proc->errors[i].desc != NULL)
-                free(proc->errors[i].desc);
-
-        free(proc->errors);
+    g_arch_processor_finalize_errors(proc);
 
-    }
-
-    if (proc->coverages != NULL)
-        free(proc->coverages);
+    g_arch_processor_finalize_coverages(proc);
 
     G_OBJECT_CLASS(g_arch_processor_parent_class)->finalize(G_OBJECT(proc));
 
@@ -923,6 +971,41 @@ GArchInstruction *g_arch_processor_get_instruction(const GArchProcessor *proc, s
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc = architecture à manipuler.                             *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_processor_finalize_errors(GArchProcessor *proc)
+{
+    size_t i;                               /* Boucle de parcours          */
+    proc_error *error;                      /* Raccourci de confort        */
+
+    if (proc->errors != NULL)
+    {
+        for (i = 0; i < proc->error_count; i++)
+        {
+            error = &proc->errors[i];
+
+            if (error->desc != NULL)
+                free(error->desc);
+
+        }
+
+        free(proc->errors);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc  = architecture à manipuler.                            *
 *                state = nouvel état de l'accès aux erreurs relevées.         *
 *                                                                             *
@@ -1066,6 +1149,118 @@ bool g_arch_processor_get_error(GArchProcessor *proc, size_t index, ArchProcessi
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = architecture concernée par la procédure.              *
+*                pbuf = zone tampon à vider.                                  *
+*                                                                             *
+*  Description : Charge les erreurs de chargement depuis une mémoire tampon.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arch_processor_load_errors(GArchProcessor *proc, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+    size_t i;                               /* Boucle de parcours          */
+    proc_error *error;                      /* Raccourci de confort        */
+    rle_string str;                         /* Chaîne à charger            */
+
+    g_arch_processor_lock_errors(proc);
+
+    result = unpack_uleb128(&value, pbuf);
+    if (!result) goto exit;
+
+    proc->error_count = value;
+
+    proc->errors = calloc(proc->error_count, sizeof(proc_error));
+
+    for (i = 0; i < proc->error_count && result; i++)
+    {
+        error = &proc->errors[i];
+
+        result = unpack_uleb128(&value, pbuf);
+        if (!result) break;
+
+        error->type = value;
+
+        result = unpack_vmpa(&error->addr, pbuf);
+        if (!result) break;
+
+        setup_empty_rle_string(&str);
+
+        result = unpack_rle_string(&str, pbuf);
+        if (!result) break;
+
+        if (get_rle_string(&str) != NULL)
+            error->desc = strdup(get_rle_string(&str));
+
+        exit_rle_string(&str);
+
+    }
+
+ exit:
+
+    g_arch_processor_unlock_errors(proc);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = architecture concernée par la procédure.              *
+*                pbuf = zone tampon à remplir.                                *
+*                                                                             *
+*  Description : Sauvegarde les erreurs de chargement dans une mémoire tampon.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arch_processor_store_errors(GArchProcessor *proc, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+    proc_error *error;                      /* Raccourci de confort        */
+    rle_string str;                         /* Chaîne à conserver          */
+
+    g_arch_processor_lock_errors(proc);
+
+    result = pack_uleb128((uleb128_t []){ proc->error_count }, pbuf);
+
+    for (i = 0; i < proc->error_count && result; i++)
+    {
+        error = &proc->errors[i];
+
+        result = pack_uleb128((uleb128_t []){ error->type }, pbuf);
+        if (!result) break;
+
+        result = pack_vmpa(&error->addr, pbuf);
+        if (!result) break;
+
+        init_static_rle_string(&str, error->desc);
+
+        result = pack_rle_string(&str, pbuf);
+
+        exit_rle_string(&str);
+
+    }
+
+    g_arch_processor_unlock_errors(proc);
+
+    return result;
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                    MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES                    */
@@ -1074,6 +1269,24 @@ bool g_arch_processor_get_error(GArchProcessor *proc, size_t index, ArchProcessi
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc = architecture à manipuler.                             *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_processor_finalize_coverages(GArchProcessor *proc)
+{
+    if (proc->coverages != NULL)
+        free(proc->coverages);
+
+}
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc  = architecture à comléter par la procédure.            *
 *                first = première instruction d'un nouveau groupe.            *
 *                start = indice de cette instruction dans l'ensemble global.  *
@@ -1342,6 +1555,101 @@ static void g_arch_processor_update_coverages(GArchProcessor *proc, instr_covera
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : proc = architecture concernée par la procédure.              *
+*                pbuf = zone tampon à vider.                                  *
+*                                                                             *
+*  Description : Charge les plages de couvertures depuis une mémoire tampon.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arch_processor_load_coverages(GArchProcessor *proc, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+    size_t i;                               /* Boucle de parcours          */
+    instr_coverage *coverage;               /* Raccourci de confort        */
+
+    result = unpack_uleb128(&value, pbuf);
+    if (!result) goto exit;
+
+    proc->cov_allocated = value;
+    proc->cov_count = value;
+
+    proc->coverages = calloc(proc->cov_count, sizeof(instr_coverage));
+
+    for (i = 0; i < proc->cov_count && result; i++)
+    {
+        coverage = &proc->coverages[i];
+
+        result = unpack_mrange(&coverage->range, pbuf);
+        if (!result) break;
+
+        result = unpack_uleb128(&value, pbuf);
+        if (!result) break;
+
+        coverage->start = value;
+
+        result = unpack_uleb128(&value, pbuf);
+        if (!result) break;
+
+        coverage->count = value;
+
+    }
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = architecture concernée par la procédure.              *
+*                pbuf = zone tampon à remplir.                                *
+*                                                                             *
+*  Description : Sauvegarde les plages de couvertures dans une mémoire tampon.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arch_processor_store_coverages(GArchProcessor *proc, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+    instr_coverage *coverage;               /* Raccourci de confort        */
+
+    result = pack_uleb128((uleb128_t []){ proc->cov_count }, pbuf);
+
+    for (i = 0; i < proc->error_count && result; i++)
+    {
+        coverage = &proc->coverages[i];
+
+        result = pack_mrange(&coverage->range, pbuf);
+        if (!result) break;
+
+        result = pack_uleb128((uleb128_t []){ coverage->start }, pbuf);
+        if (!result) break;
+
+        result = pack_uleb128((uleb128_t []){ coverage->count }, pbuf);
+        if (!result) break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : proc  = processeur recensant diverses instructions.          *
 *                addr  = position en mémoire ou physique à chercher.          *
 *                                                                             *
@@ -1580,3 +1888,86 @@ instr_iter_t *_g_arch_processor_get_covered_iter_from_address(GArchProcessor *pr
     return result;
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      CONSERVATION ET RECHARGEMENT DES DONNEES                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = élément GLib à constuire.                          *
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à lire.                                *
+*                                                                             *
+*  Description : Charge un contenu depuis une mémoire tampon.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arch_processor_load(GArchProcessor *proc, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+
+    result = unpack_uleb128(&value, pbuf);
+    if (!result) goto exit;
+
+    proc->endianness = value;
+
+
+
+
+
+
+    if (result)
+        result = g_arch_processor_load_errors(proc, pbuf);
+
+    if (result)
+        result = g_arch_processor_load_coverages(proc, pbuf);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = élément GLib à consulter.                          *
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à remplir.                             *
+*                                                                             *
+*  Description : Sauvegarde un contenu dans une mémoire tampon.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_arch_processor_store(GArchProcessor *proc, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = pack_uleb128((uleb128_t []){ proc->endianness }, pbuf);
+
+
+
+
+
+    if (result)
+        result = g_arch_processor_store_coverages(proc, pbuf);
+
+    if (result)
+        result = g_arch_processor_store_errors(proc, pbuf);
+
+    return result;
+
+}
-- 
cgit v0.11.2-87-g4458