From 8ce244d136b32b43d8553866747c68b503b2d10a Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 21 Feb 2022 07:51:14 +0100
Subject: Define the first steps towards format serialization.

---
 src/format/format.c    | 372 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/format/known-int.h |  10 ++
 src/format/known.c     | 181 +++++++++++++++++++++++-
 src/format/symbol.c    |  84 ++++++++++-
 4 files changed, 644 insertions(+), 3 deletions(-)

diff --git a/src/format/format.c b/src/format/format.c
index f8fe13a..d126236 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -33,6 +33,7 @@
 #include "preload.h"
 #include "../arch/processor.h"
 #include "../common/sort.h"
+#include "../core/demanglers.h"
 #include "../plugins/pglist.h"
 
 
@@ -49,6 +50,12 @@ static void g_binary_format_dispose(GBinFormat *);
 /* Procède à la libération totale de la mémoire. */
 static void g_binary_format_finalize(GBinFormat *);
 
+/* Charge les plages de couvertures depuis une mémoire tampon. */
+static bool g_binary_format_load_start_points(GBinFormat *, packed_buffer_t *);
+
+/* Sauvegarde les points de départ enregistrés pour un format. */
+static bool g_binary_format_store_start_points(GBinFormat *, packed_buffer_t *);
+
 
 
 /* ---------------------- RASSEMBLEMENT ET GESTION DE SYMBOLES ---------------------- */
@@ -65,6 +72,30 @@ static bool __g_binary_format_find_symbol(const GBinFormat *, const void *, __co
 
 
 
+/* ------------------ CONSERVATION DES SOUCIS DURANT LE CHARGEMENT ------------------ */
+
+
+/* Charge les erreurs de chargement depuis une mémoire tampon. */
+static bool g_binary_format_load_errors(GBinFormat *, packed_buffer_t *);
+
+/* Sauvegarde les erreurs de chargement dans une mémoire tampon. */
+static bool g_binary_format_store_errors(GBinFormat *, packed_buffer_t *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Charge un format depuis une mémoire tampon. */
+static bool g_binary_format_load(GBinFormat *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un format dans une mémoire tampon. */
+static bool g_binary_format_store(GBinFormat *, GObjectStorage *, packed_buffer_t *);
+
+
+
+
+
 /* Indique le type défini pour un format binaire générique. */
 G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_KNOWN_FORMAT);
 
@@ -84,12 +115,18 @@ G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_KNOWN_FORMAT);
 static void g_binary_format_class_init(GBinFormatClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
+    GKnownFormatClass *known;               /* Version de classe parente   */
 
     object = G_OBJECT_CLASS(klass);
 
     object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_format_dispose;
     object->finalize = (GObjectFinalizeFunc)g_binary_format_finalize;
 
+    known = G_KNOWN_FORMAT_CLASS(klass);
+
+    known->load = (load_known_fc)g_binary_format_load;
+    known->store = (load_known_fc)g_binary_format_store;
+
     g_signal_new("symbol-added",
                  G_TYPE_BIN_FORMAT,
                  G_SIGNAL_RUN_LAST,
@@ -411,6 +448,101 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, DisassPr
 
 /******************************************************************************
 *                                                                             *
+*  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_binary_format_load_start_points(GBinFormat *format, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    DisassPriorityLevel i;                  /* Boucle de parcours #1       */
+    uleb128_t count;                        /* Quantité de points présents */
+    size_t k;                               /* Boucle de parcours #2       */
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+
+    result = true;
+
+    g_rw_lock_writer_lock(&format->pt_lock);
+
+    for (i = 0; i < DPL_COUNT && result; i++)
+    {
+        result = unpack_uleb128(&count, pbuf);
+        if (!result) break;
+
+        format->pt_allocated[i] = count;
+        format->pt_count[i] = count;
+
+        format->start_points[i] = calloc(format->pt_count[i], sizeof(virt_t));
+
+        for (k = 0; k < format->pt_count[i] && result; k++)
+        {
+            result = unpack_uleb128(&value, pbuf);
+            if (!result) break;
+
+            format->start_points[i][k] = value;
+
+        }
+
+    }
+
+    g_rw_lock_writer_unlock(&format->pt_lock);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                pbuf = zone tampon à remplir.                                *
+*                                                                             *
+*  Description : Sauvegarde les points de départ enregistrés pour un format.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_binary_format_store_start_points(GBinFormat *format, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    DisassPriorityLevel i;                  /* Boucle de parcours #1       */
+    size_t count;                           /* Quantité de points présents */
+    size_t k;                               /* Boucle de parcours #2       */
+
+    result = true;
+
+    g_rw_lock_writer_lock(&format->pt_lock);
+
+    for (i = 0; i < DPL_COUNT && result; i++)
+    {
+        count = format->pt_count[i];
+
+        result = pack_uleb128((uleb128_t []){ count }, pbuf);
+
+        for (k = 0; k < count && result; k++)
+            result = pack_uleb128((uleb128_t []){ format->start_points[i][k] }, pbuf);
+
+    }
+
+    g_rw_lock_writer_unlock(&format->pt_lock);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = description de l'exécutable à consulter.            *
 *                ctx    = contexte de désassemblage à préparer.               *
 *                status = barre de statut à tenir informée.                   *
@@ -1546,3 +1678,243 @@ bool g_binary_format_get_error(GBinFormat *format, size_t index, BinaryFormatErr
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format de binaire concerné 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_binary_format_load_errors(GBinFormat *format, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+    size_t i;                               /* Boucle de parcours          */
+    fmt_error *error;                       /* Raccourci de confort        */
+    rle_string str;                         /* Chaîne à charger            */
+
+    g_binary_format_lock_errors(format);
+
+    result = unpack_uleb128(&value, pbuf);
+    if (!result) goto exit;
+
+    format->error_count = value;
+
+    format->errors = calloc(format->error_count, sizeof(fmt_error));
+
+    for (i = 0; i < format->error_count && result; i++)
+    {
+        error = &format->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_binary_format_unlock_errors(format);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format de binaire concerné 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_binary_format_store_errors(GBinFormat *format, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+    fmt_error *error;                       /* Raccourci de confort        */
+    rle_string str;                         /* Chaîne à conserver          */
+
+    g_binary_format_lock_errors(format);
+
+    result = pack_uleb128((uleb128_t []){ format->error_count }, pbuf);
+
+    for (i = 0; i < format->error_count && result; i++)
+    {
+        error = &format->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_binary_format_unlock_errors(format);
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = élément GLib à constuire.                          *
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à lire.                                *
+*                                                                             *
+*  Description : Charge un format depuis une mémoire tampon.                  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_binary_format_load(GBinFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    fmt_extra_data_t *extra;                /* Données insérées à consulter*/
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+    rle_string str;                         /* Chaîne à charger            */
+
+    extra = GET_BIN_FORMAT_EXTRA(format);
+
+    LOCK_GOBJECT_EXTRA(extra);
+
+    result = unpack_uleb128(&value, pbuf);
+
+    if (result)
+        extra->flags = value;
+
+    UNLOCK_GOBJECT_EXTRA(extra);
+
+    if (result)
+        result = g_binary_format_load_start_points(format, pbuf);
+
+    if (result)
+    {
+        setup_empty_rle_string(&str);
+
+        result = unpack_rle_string(&str, pbuf);
+
+        if (result)
+            result = (get_rle_string(&str) != NULL);
+
+        if (result)
+            format->demangler = get_compiler_demangler_for_key(get_rle_string(&str));
+
+        if (result)
+            result = (format->demangler != NULL);
+
+        exit_rle_string(&str);
+
+    }
+
+
+
+
+
+    if (result)
+        result = g_binary_format_load_errors(format, pbuf);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = élément GLib à consulter.                          *
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à remplir.                             *
+*                                                                             *
+*  Description : Sauvegarde un format dans une mémoire tampon.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_binary_format_store(GBinFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    fmt_extra_data_t *extra;                /* Données insérées à consulter*/
+    char *key;                              /* Désignation du décodeur     */
+    rle_string str;                         /* Chaîne à conserver          */
+
+    extra = GET_BIN_FORMAT_EXTRA(format);
+
+    LOCK_GOBJECT_EXTRA(extra);
+
+    result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf);
+
+    UNLOCK_GOBJECT_EXTRA(extra);
+
+    if (result)
+        result = g_binary_format_store_start_points(format, pbuf);
+
+    if (result)
+    {
+        key = g_compiler_demangler_get_key(format->demangler);
+        init_dynamic_rle_string(&str, key);
+
+        result = pack_rle_string(&str, pbuf);
+
+        exit_rle_string(&str);
+
+    }
+
+
+
+
+
+
+    if (result)
+        result = g_binary_format_store_errors(format, pbuf);
+
+    return result;
+
+}
diff --git a/src/format/known-int.h b/src/format/known-int.h
index 950c75f..3328a96 100644
--- a/src/format/known-int.h
+++ b/src/format/known-int.h
@@ -26,6 +26,7 @@
 
 
 #include "known.h"
+#include "../analysis/storage/storage.h"
 
 
 
@@ -41,6 +42,12 @@ typedef bool (* known_analyze_fc) (GKnownFormat *, wgroup_id_t, GtkStatusStack *
 /* Réalise un traitement post-désassemblage. */
 typedef void (* known_complete_analysis_fc) (GKnownFormat *, wgroup_id_t, GtkStatusStack *);
 
+/* Charge un format depuis une mémoire tampon. */
+typedef bool (* load_known_fc) (GKnownFormat *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un format dans une mémoire tampon. */
+typedef bool (* store_known_fc) (GKnownFormat *, GObjectStorage *, packed_buffer_t *);
+
 
 /* Format binaire générique (instance) */
 struct _GKnownFormat
@@ -62,6 +69,9 @@ struct _GKnownFormatClass
     known_analyze_fc analyze;               /* Interprétation du format    */
     known_complete_analysis_fc complete;    /* Terminaison d'analyse       */
 
+    load_known_fc load;                     /* Chargement depuis un tampon */
+    store_known_fc store;                   /* Conservation dans un tampon */
+
 };
 
 
diff --git a/src/format/known.c b/src/format/known.c
index 6865d0d..7512ae1 100644
--- a/src/format/known.c
+++ b/src/format/known.c
@@ -28,16 +28,23 @@
 
 
 #include "known-int.h"
+#include "../analysis/storage/serialize-int.h"
 #include "../plugins/pglist.h"
 
 
 
+/* ---------------------- DEFINITION DE LA BASE DE TOUT FORMAT ---------------------- */
+
+
 /* Initialise la classe des formats binaires génériques. */
 static void g_known_format_class_init(GKnownFormatClass *);
 
 /* Initialise une instance de format binaire générique. */
 static void g_known_format_init(GKnownFormat *);
 
+/* Procède à l'initialisation de l'interface de sérialisation. */
+static void g_known_format_serializable_init(GSerializableObjectInterface *);
+
 /* Supprime toutes les références externes. */
 static void g_known_format_dispose(GKnownFormat *);
 
@@ -46,8 +53,31 @@ static void g_known_format_finalize(GKnownFormat *);
 
 
 
+/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
+
+
+/* Charge un format depuis une mémoire tampon. */
+static bool _g_known_format_load(GKnownFormat *, GObjectStorage *, packed_buffer_t *);
+
+/* Charge un format depuis une mémoire tampon. */
+static bool g_known_format_load(GKnownFormat *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un format dans une mémoire tampon. */
+static bool _g_known_format_store(GKnownFormat *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un format dans une mémoire tampon. */
+static bool g_known_format_store(GKnownFormat *, GObjectStorage *, packed_buffer_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        DEFINITION DE LA BASE DE TOUT FORMAT                        */
+/* ---------------------------------------------------------------------------------- */
+
+
 /* Indique le type défini pour un format binaire générique. */
-G_DEFINE_TYPE(GKnownFormat, g_known_format, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_CODE(GKnownFormat, g_known_format, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_known_format_serializable_init));
 
 
 /******************************************************************************
@@ -71,6 +101,9 @@ static void g_known_format_class_init(GKnownFormatClass *klass)
     object->dispose = (GObjectFinalizeFunc/* ! */)g_known_format_dispose;
     object->finalize = (GObjectFinalizeFunc)g_known_format_finalize;
 
+    klass->load = (load_known_fc)_g_known_format_load;
+    klass->store = (store_known_fc)_g_known_format_store;
+
 }
 
 
@@ -95,6 +128,26 @@ static void g_known_format_init(GKnownFormat *format)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : iface = interface GLib à initialiser.                        *
+*                                                                             *
+*  Description : Procède à l'initialisation de l'interface de sérialisation.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_known_format_serializable_init(GSerializableObjectInterface *iface)
+{
+    iface->load = (load_serializable_object_cb)g_known_format_load;
+    iface->store = (store_serializable_object_cb)g_known_format_store;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = instance d'objet GLib à traiter.                    *
 *                                                                             *
 *  Description : Supprime toutes les références externes.                     *
@@ -289,3 +342,129 @@ void g_known_format_complete_analysis(GKnownFormat *format, wgroup_id_t gid, Gtk
     handle_known_format_analysis(PGA_FORMAT_POST_ANALYSIS_ENDED, format, gid, status);
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      CONSERVATION ET RECHARGEMENT DES DONNEES                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = élément GLib à constuire.                          *
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à lire.                                *
+*                                                                             *
+*  Description : Charge un format depuis une mémoire tampon.                  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool _g_known_format_load(GKnownFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinContent *content;                   /* Contenu binaire rechargé    */
+
+    content = G_BIN_CONTENT(g_object_storage_unpack_object(storage, "contents", pbuf));
+    result = (content != NULL);
+
+    if (result)
+    {
+        g_known_format_set_content(format, content);
+
+        g_object_unref(G_OBJECT(content));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = élément GLib à constuire.                          *
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à lire.                                *
+*                                                                             *
+*  Description : Charge un format depuis une mémoire tampon.                  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_known_format_load(GKnownFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GKnownFormatClass *class;               /* Classe à activer            */
+
+    class = G_KNOWN_FORMAT_GET_CLASS(format);
+
+    result = class->load(format, storage, pbuf);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = élément GLib à consulter.                          *
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à remplir.                             *
+*                                                                             *
+*  Description : Sauvegarde un format dans une mémoire tampon.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool _g_known_format_store(GKnownFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    if (format->content == NULL)
+        result = false;
+
+    else
+        result = g_object_storage_pack_object(storage, "contents", G_SERIALIZABLE_OBJECT(format->content), pbuf);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = élément GLib à consulter.                          *
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à remplir.                             *
+*                                                                             *
+*  Description : Sauvegarde un format dans une mémoire tampon.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_known_format_store(GKnownFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GKnownFormatClass *class;               /* Classe à activer            */
+
+    class = G_KNOWN_FORMAT_GET_CLASS(format);
+
+    result = class->store(format, storage, pbuf);
+
+    return result;
+
+}
diff --git a/src/format/symbol.c b/src/format/symbol.c
index 2cd4f87..9b054e6 100644
--- a/src/format/symbol.c
+++ b/src/format/symbol.c
@@ -30,6 +30,7 @@
 
 
 #include "symbol-int.h"
+#include "../analysis/db/misc/rlestr.h"
 #include "../glibext/gbinarycursor.h"
 #include "../glibext/linegen-int.h"
 #include "../gtkext/gtkblockdisplay.h"
@@ -940,8 +941,57 @@ static void g_binary_symbol_print(GBinSymbol *symbol, GBufferLine *line, size_t
 static bool _g_binary_symbol_load(GBinSymbol *symbol, GObjectStorage *storage, packed_buffer_t *pbuf)
 {
     bool result;                            /* Bilan à retourner           */
+    sym_extra_data_t *extra;                /* Données insérées à consulter*/
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+    rle_string str;                         /* Chaîne à charger            */
 
-    result = true;
+    extra = GET_BIN_SYMBOL_EXTRA(symbol);
+
+    LOCK_GOBJECT_EXTRA(extra);
+
+    result = unpack_uleb128(&value, pbuf);
+
+    if (result)
+        extra->stype = value;
+
+    if (result)
+    {
+        result = unpack_uleb128(&value, pbuf);
+
+        if (result)
+            extra->status = value;
+
+    }
+
+    if (result)
+        result = extract_packed_buffer(pbuf, &extra->nm_prefix, 1, false);
+
+    if (result)
+    {
+        result = unpack_uleb128(&value, pbuf);
+
+        if (result)
+            extra->flags = value;
+
+    }
+
+    UNLOCK_GOBJECT_EXTRA(extra);
+
+    if (result)
+        result = unpack_mrange(&symbol->range, pbuf);
+
+    if (result)
+    {
+        setup_empty_rle_string(&str);
+
+        result = unpack_rle_string(&str, pbuf);
+
+        if (result && get_rle_string(&str) != NULL)
+            symbol->alt = strdup(get_rle_string(&str));
+
+        exit_rle_string(&str);
+
+    }
 
     return result;
 
@@ -993,8 +1043,38 @@ static bool g_binary_symbol_load(GBinSymbol *symbol, GObjectStorage *storage, pa
 static bool _g_binary_symbol_store(GBinSymbol *symbol, GObjectStorage *storage, packed_buffer_t *pbuf)
 {
     bool result;                            /* Bilan à retourner           */
+    sym_extra_data_t *extra;                /* Données insérées à consulter*/
+    rle_string str;                         /* Chaîne à conserver          */
+
+    extra = GET_BIN_SYMBOL_EXTRA(symbol);
+
+    LOCK_GOBJECT_EXTRA(extra);
+
+    result = pack_uleb128((uleb128_t []){ extra->stype }, pbuf);
+
+    if (result)
+        result = pack_uleb128((uleb128_t []){ extra->status }, pbuf);
+
+    if (result)
+        result = extend_packed_buffer(pbuf, &extra->nm_prefix, 1, false);
+
+    if (result)
+        result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf);
+
+    UNLOCK_GOBJECT_EXTRA(extra);
+
+    if (result)
+        result = pack_mrange(&symbol->range, pbuf);
 
-    result = true;
+    if (result)
+    {
+        init_static_rle_string(&str, symbol->alt);
+
+        result = pack_rle_string(&str, pbuf);
+
+        exit_rle_string(&str);
+
+    }
 
     return result;
 
-- 
cgit v0.11.2-87-g4458