From bae8c01323703d467ed2cce07c8bf8fd70f7816a Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 21 Aug 2021 17:07:38 +0200
Subject: Define all architecture instructions as serializable.

---
 plugins/arm/instruction.c         | 121 ++++++++++++
 plugins/arm/v7/instruction.c      | 109 +++++++++++
 src/arch/instruction-int.h        |  11 ++
 src/arch/instruction.c            | 387 +++++++++++++++++++++++++++++++++++++-
 src/arch/instruction.h            |   4 +-
 src/arch/instructions/undefined.c | 104 ++++++++++
 src/arch/processor.c              |   4 +-
 src/arch/storage.c                |   4 +-
 8 files changed, 733 insertions(+), 11 deletions(-)

diff --git a/plugins/arm/instruction.c b/plugins/arm/instruction.c
index 4872aba..c42250f 100644
--- a/plugins/arm/instruction.c
+++ b/plugins/arm/instruction.c
@@ -29,6 +29,7 @@
 #include <string.h>
 
 
+#include <analysis/db/misc/rlestr.h>
 #include <common/extstr.h>
 #include <core/logs.h>
 
@@ -62,6 +63,17 @@ static bool g_arm_instruction_serialize(GArmInstruction *, GAsmStorage *, packed
 
 
 
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_arm_instruction_load(GArmInstruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_arm_instruction_store(GArmInstruction *, GObjectStorage *, packed_buffer_t *);
+
+
+
 /* Indique le type défini pour une représentation d'une instruction ARM. */
 G_DEFINE_TYPE(GArmInstruction, g_arm_instruction, G_TYPE_ARCH_INSTRUCTION);
 
@@ -93,6 +105,9 @@ static void g_arm_instruction_class_init(GArmInstructionClass *klass)
     instr->unserialize = (unserialize_instruction_fc)g_arm_instruction_unserialize;
     instr->serialize = (serialize_instruction_fc)g_arm_instruction_serialize;
 
+    instr->load = (load_instruction_fc)g_arm_instruction_load;
+    instr->store = (store_instruction_fc)g_arm_instruction_store;
+
 }
 
 
@@ -382,3 +397,109 @@ static bool g_arm_instruction_serialize(GArmInstruction *instr, GAsmStorage *sto
     return result;
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_arm_instruction_load(GArmInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstructionClass *parent;          /* Classe parente à consulter  */
+    rle_string str;                         /* Chaîne à charger            */
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+
+    parent = G_ARCH_INSTRUCTION_CLASS(g_arm_instruction_parent_class);
+
+    result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+    if (result)
+    {
+        setup_empty_rle_string(&str);
+
+        result = unpack_rle_string(&str, pbuf);
+
+        if (result)
+        {
+            result = (get_rle_string(&str) != NULL);
+
+            if (result)
+                result = g_arm_instruction_extend_keyword(instr, get_rle_string(&str));
+
+            exit_rle_string(&str);
+
+        }
+
+    }
+
+    if (result)
+    {
+        result = unpack_uleb128(&value, pbuf);
+
+        if (result)
+            instr->cond = value;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_arm_instruction_store(GArmInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstructionClass *parent;          /* Classe parente à consulter  */
+    rle_string str;                         /* Chaîne à conserver          */
+
+    parent = G_ARCH_INSTRUCTION_CLASS(g_arm_instruction_parent_class);
+
+    result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+    if (result)
+    {
+        init_static_rle_string(&str, instr->suffix);
+
+        result = pack_rle_string(&str, pbuf);
+
+        exit_rle_string(&str);
+
+    }
+
+    if (result)
+        result = pack_uleb128((uleb128_t []){ instr->cond }, pbuf);
+
+    return result;
+
+}
diff --git a/plugins/arm/v7/instruction.c b/plugins/arm/v7/instruction.c
index 30a5bd8..eb4a082 100644
--- a/plugins/arm/v7/instruction.c
+++ b/plugins/arm/v7/instruction.c
@@ -97,6 +97,17 @@ static bool g_armv7_instruction_serialize(GArmV7Instruction *, GAsmStorage *, pa
 
 
 
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_armv7_instruction_load(GArmV7Instruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_armv7_instruction_store(GArmV7Instruction *, GObjectStorage *, packed_buffer_t *);
+
+
+
 /* Indique le type défini pour une représentation d'une instruction ARMv7. */
 G_DEFINE_TYPE(GArmV7Instruction, g_armv7_instruction, G_TYPE_ARM_INSTRUCTION);
 
@@ -132,6 +143,9 @@ static void g_armv7_instruction_class_init(GArmV7InstructionClass *klass)
     instr->unserialize = (unserialize_instruction_fc)g_armv7_instruction_unserialize;
     instr->serialize = (serialize_instruction_fc)g_armv7_instruction_serialize;
 
+    instr->load = (load_instruction_fc)g_armv7_instruction_load;
+    instr->store = (store_instruction_fc)g_armv7_instruction_store;
+
 }
 
 
@@ -506,3 +520,98 @@ static bool g_armv7_instruction_serialize(GArmV7Instruction *instr, GAsmStorage
     return result;
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_armv7_instruction_load(GArmV7Instruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstructionClass *parent;          /* Classe parente à consulter  */
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+    uint8_t boolean;                        /* Valeur booléenne            */
+
+    parent = G_ARCH_INSTRUCTION_CLASS(g_armv7_instruction_parent_class);
+
+    result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+    if (result)
+        result = unpack_uleb128(&value, pbuf);
+
+    if (result)
+        instr->sid = value;
+
+    if (result)
+        result = extract_packed_buffer(pbuf, &instr->encoding, sizeof(char), false);
+
+    if (result)
+    {
+        result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
+
+        if (result)
+            instr->setflags = (boolean == 1 ? true : false);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_armv7_instruction_store(GArmV7Instruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstructionClass *parent;          /* Classe parente à consulter  */
+    uint8_t boolean;                        /* Valeur booléenne            */
+
+    parent = G_ARCH_INSTRUCTION_CLASS(g_armv7_instruction_parent_class);
+
+    result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+    if (result)
+        result = pack_uleb128((uleb128_t []){ instr->sid }, pbuf);
+
+    if (result)
+        result = extend_packed_buffer(pbuf, &instr->encoding, sizeof(char), false);
+
+    if (result)
+    {
+        boolean = (instr->setflags ? 1 : 0);
+        result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
+    }
+
+    return result;
+
+}
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index 9a23bf2..f8998a1 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -26,6 +26,7 @@
 
 
 #include "instruction.h"
+#include "../analysis/storage/storage.h"
 #include "../common/array.h"
 #include "../glibext/objhole.h"
 
@@ -58,6 +59,13 @@ typedef GBufferLine * (* print_instruction_fc) (const GArchInstruction *, GBuffe
 /* Liste les registres lus et écrits par l'instruction. */
 typedef void (* get_instruction_rw_regs_fc) (const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *);
 
+/* Charge un contenu depuis une mémoire tampon. */
+typedef bool (* load_instruction_fc) (GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+typedef bool (* store_instruction_fc) (GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+
+
 
 /* Informations glissées dans la structure GObject de GArchOperand */
 typedef struct _instr_extra_data_t
@@ -142,6 +150,9 @@ struct _GArchInstructionClass
 
     print_instruction_fc print;             /* Imprime l'ensemble          */
 
+    load_instruction_fc load;               /* Chargement depuis un tampon */
+    store_instruction_fc store;             /* Conservation dans un tampon */
+
     //get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés    */
 
 };
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index e0d1091..c4354d4 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -34,6 +34,7 @@
 
 #include "instruction-int.h"
 #include "storage.h"
+#include "../analysis/storage/serialize-int.h"
 #include "../core/logs.h"
 #include "../core/processors.h"
 #include "../glibext/gbinarycursor.h"
@@ -49,7 +50,10 @@ static void g_arch_instruction_class_init(GArchInstructionClass *);
 static void g_arch_instruction_init(GArchInstruction *);
 
 /* Procède à l'initialisation de l'interface de génération. */
-static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface *);
+static void g_arch_instruction_generator_init(GLineGeneratorInterface *);
+
+/* Procède à l'initialisation de l'interface de sérialisation. */
+static void g_arch_instruction_serializable_init(GSerializableObjectInterface *);
 
 /* Supprime toutes les références externes. */
 static void g_arch_instruction_dispose(GArchInstruction *);
@@ -59,6 +63,18 @@ static void g_arch_instruction_finalize(GArchInstruction *);
 
 
 
+
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_arch_instruction_load_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde toutes les destinations d'une instruction. */
+bool g_arch_instruction_store_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+
+
+
+
+
 /* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */
 
 
@@ -92,10 +108,27 @@ static void _g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t,
 static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *);
 
 
+/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
+
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool _g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool _g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *);
+
+
 
 /* Indique le type défini pour une instruction d'architecture. */
 G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT,
-                        G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_interface_init));
+                        G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_init)
+                        G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_init));
 
 
 /******************************************************************************
@@ -127,6 +160,9 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass)
 
     instr->print = (print_instruction_fc)_g_arch_instruction_print;
 
+    instr->load = (load_instruction_fc)_g_arch_instruction_load;
+    instr->store = (store_instruction_fc)_g_arch_instruction_store;
+
 }
 
 
@@ -170,7 +206,7 @@ static void g_arch_instruction_init(GArchInstruction *instr)
 *                                                                             *
 ******************************************************************************/
 
-static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface *iface)
+static void g_arch_instruction_generator_init(GLineGeneratorInterface *iface)
 {
     iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines;
     iface->compute = (linegen_compute_fc)g_arch_instruction_compute_cursor;
@@ -183,6 +219,26 @@ static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : iface = interface GLib à initialiser.                        *
+*                                                                             *
+*  Description : Procède à l'initialisation de l'interface de sérialisation.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_instruction_serializable_init(GSerializableObjectInterface *iface)
+{
+    iface->load = (load_serializable_object_cb)g_arch_instruction_load;
+    iface->store = (store_serializable_object_cb)g_arch_instruction_store;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr = instance d'objet GLib à traiter.                     *
 *                                                                             *
 *  Description : Supprime toutes les références externes.                     *
@@ -1560,6 +1616,132 @@ instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_instruction_load_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    uleb128_t count;                        /* Nombre de liens à charger   */
+    uleb128_t i;                            /* Boucle de parcours          */
+    GArchInstruction *linked;               /* Lien vers une instruction   */
+    uleb128_t type;                         /* Valeur ULEB128 à charger    */
+
+    g_arch_instruction_lock_dest(instr);
+
+    result = unpack_uleb128(&count, pbuf);
+
+    for (i = 0; i < count && result; i++)
+    {
+        linked = G_ARCH_INSTRUCTION(g_object_storage_unpack_object(storage, "instructions", pbuf));
+        if (linked == NULL)
+        {
+            result = false;
+            break;
+        }
+
+        result = unpack_uleb128(&type, pbuf);
+        if (!result)
+        {
+            g_object_unref(G_OBJECT(linked));
+            break;
+        }
+
+        g_arch_instruction_link_with(instr, linked, type);
+        g_object_unref(G_OBJECT(linked));
+
+    }
+
+    g_arch_instruction_unlock_dest(instr);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction dont les informations sont à consulter.*
+*                storage = conservateur de données à manipuler ou NULL.       *
+*                pbuf    = zone tampon à remplir.                             *
+*                                                                             *
+*  Description : Sauvegarde toutes les destinations d'une instruction.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_arch_instruction_store_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t count;                           /* Nombre d'éléments à traiter */
+    size_t kept;                            /* Nombre de liens conservés   */
+    size_t i;                               /* Boucle de parcours          */
+    const instr_link_t *link;               /* Lien vers une instruction   */
+
+    g_arch_instruction_lock_dest(instr);
+
+    count = g_arch_instruction_count_destinations(instr);
+
+    /**
+     * Le type de lien ILT_REF n'est mis en place que lors de la création
+     * d'opérandes de type G_TYPE_TARGET_OPERAND, et sera donc remis en place
+     * dynamiquement lors de la restauration de ces derniers.
+     */
+
+    kept = 0;
+
+    for (i = 0; i < count; i++)
+    {
+        link = g_arch_instruction_get_destination(instr, i);
+
+        if (link->type != ILT_REF)
+            kept++;
+
+        unref_instr_link(link);
+
+    }
+
+    result = pack_uleb128((uleb128_t []){ kept }, pbuf);
+
+    for (i = 0; i < count && result; i++)
+    {
+        link = g_arch_instruction_get_destination(instr, i);
+
+        if (link->type != ILT_REF)
+        {
+            result = g_object_storage_pack_object(storage, "instructions",
+                                                  G_SERIALIZABLE_OBJECT(link->linked), pbuf);
+
+            if (result)
+                result = pack_uleb128((uleb128_t []){ link->type }, pbuf);
+
+        }
+
+        unref_instr_link(link);
+
+    }
+
+    g_arch_instruction_unlock_dest(instr);
+
+    return result;
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                       CONVERSIONS DU FORMAT DES INSTRUCTIONS                       */
@@ -1787,7 +1969,7 @@ static bool g_arch_instruction_unserialize(GArchInstruction *instr, GAsmStorage
 *                                                                             *
 ******************************************************************************/
 
-GArchInstruction *g_arch_instruction_load(GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+GArchInstruction *g_arch_instruction_load__old(GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
 {
     GArchInstruction *result;               /* Instance à retourner        */
     bool status;                            /* Bilan du chargement         */
@@ -1969,7 +2151,7 @@ static bool g_arch_instruction_serialize(GArchInstruction *instr, GAsmStorage *s
 *                                                                             *
 ******************************************************************************/
 
-bool g_arch_instruction_store(GArchInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf)
+bool g_arch_instruction_store__old(GArchInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf)
 {
     bool result;                            /* Bilan à retourner           */
 
@@ -2175,3 +2357,198 @@ static void g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line,
     G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat, content);
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                      CONSERVATION ET RECHARGEMENT DES DONNEES                      */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    instr_extra_data_t *extra;              /* Données insérées à consulter*/
+    uleb128_t value;                        /* Valeur ULEB128 à charger    */
+    uleb128_t count;                        /* Nombre d'éléments à traiter */
+    uleb128_t i;                            /* Boucle de parcours          */
+    GArchOperand *op;                       /* Opérande à traiter          */
+
+    extra = GET_ARCH_INSTR_EXTRA(instr);
+
+    LOCK_GOBJECT_EXTRA(extra);
+
+    result = unpack_uleb128(&value, pbuf);
+    if (!result) goto exit;
+
+    extra->uid = value;
+
+    result = unpack_uleb128(&value, pbuf);
+    if (!result) goto exit;
+
+    extra->flags = value;
+
+    UNLOCK_GOBJECT_EXTRA(extra);
+
+    result = unpack_mrange(&instr->range, pbuf);
+
+    if (result)
+    {
+        result = unpack_uleb128(&count, pbuf);
+
+        for (i = 0; i < count && result; i++)
+        {
+            op = G_ARCH_OPERAND(g_object_storage_unpack_object(storage, "operands", pbuf));
+            result = (op != NULL);
+
+            if (result)
+                g_arch_instruction_attach_extra_operand(instr, op);
+
+        }
+
+    }
+
+    if (result)
+        result = g_arch_instruction_load_destinations(instr, storage, pbuf);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstructionClass *class;           /* Classe à activer            */
+
+    class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
+
+    result = class->load(instr, storage, pbuf);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    instr_extra_data_t *extra;              /* Données insérées à consulter*/
+    size_t count;                           /* Nombre d'éléments à traiter */
+    size_t i;                               /* Boucle de parcours          */
+    GArchOperand *op;                       /* Opérande à traiter          */
+
+    extra = GET_ARCH_INSTR_EXTRA(instr);
+
+    LOCK_GOBJECT_EXTRA(extra);
+
+    result = pack_uleb128((uleb128_t []){ extra->uid }, pbuf);
+
+    if (result)
+        result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf);
+
+    UNLOCK_GOBJECT_EXTRA(extra);
+
+    if (result)
+        result = pack_mrange(&instr->range, pbuf);
+
+    if (result)
+    {
+        g_arch_instruction_lock_operands(instr);
+
+        count = _g_arch_instruction_count_operands(instr);
+
+        result = pack_uleb128((uleb128_t []){ count }, pbuf);
+
+        for (i = 0; i < count && result; i++)
+        {
+            op = _g_arch_instruction_get_operand(instr, i);
+
+            result = g_object_storage_pack_object(storage, "operands", G_SERIALIZABLE_OBJECT(op), pbuf);
+
+            g_object_unref(G_OBJECT(op));
+
+        }
+
+        g_arch_instruction_unlock_operands(instr);
+
+    }
+
+    if (result)
+        result = g_arch_instruction_store_destinations(instr, storage, pbuf);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstructionClass *class;           /* Classe à activer            */
+
+    class = G_ARCH_INSTRUCTION_GET_CLASS(instr);
+
+    result = class->store(instr, storage, pbuf);
+
+    return result;
+
+}
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index a9d66be..683adfb 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -318,10 +318,10 @@ typedef struct _GAsmStorage GAsmStorage;
 
 
 /* Charge une instruction depuis une mémoire tampon. */
-GArchInstruction *g_arch_instruction_load(GAsmStorage *, GBinFormat *, packed_buffer_t *);
+GArchInstruction *g_arch_instruction_load__old(GAsmStorage *, GBinFormat *, packed_buffer_t *);
 
 /* Sauvegarde une instruction dans une mémoire tampon. */
-bool g_arch_instruction_store(GArchInstruction *, GAsmStorage *, packed_buffer_t *);
+bool g_arch_instruction_store__old(GArchInstruction *, GAsmStorage *, packed_buffer_t *);
 
 
 
diff --git a/src/arch/instructions/undefined.c b/src/arch/instructions/undefined.c
index 663a9eb..7ed5db9 100644
--- a/src/arch/instructions/undefined.c
+++ b/src/arch/instructions/undefined.c
@@ -74,6 +74,17 @@ static void g_undef_instruction_print(GUndefInstruction *, GBufferLine *, size_t
 
 
 
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Charge un contenu depuis une mémoire tampon. */
+static bool g_undef_instruction_load(GUndefInstruction *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un contenu dans une mémoire tampon. */
+static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, packed_buffer_t *);
+
+
+
 /* ---------------------------------------------------------------------------------- */
 /*                           INSTRUCTION INCONNUE / DONNEES                           */
 /* ---------------------------------------------------------------------------------- */
@@ -115,6 +126,9 @@ static void g_undef_instruction_class_init(GUndefInstructionClass *klass)
 
     instr->print = (print_instruction_fc)g_undef_instruction_print;
 
+    instr->load = (load_instruction_fc)g_undef_instruction_load;
+    instr->store = (store_instruction_fc)g_undef_instruction_store;
+
 }
 
 
@@ -440,3 +454,93 @@ InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *
     return result;
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstructionClass *parent;          /* Classe parente à consulter  */
+    undef_extra_data_t *extra;              /* Données insérées à consulter*/
+    uint8_t val;                            /* Champ de bits manipulé      */
+
+    parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
+
+    result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+    if (result)
+    {
+        extra = GET_UNDEF_INSTR_EXTRA(instr);
+
+        LOCK_GOBJECT_EXTRA(extra);
+
+        result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false);
+        extra->behavior = val;
+
+        UNLOCK_GOBJECT_EXTRA(extra);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = é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_undef_instruction_store(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+    bool result;                            /* Bilan à retourner           */
+    GArchInstructionClass *parent;          /* Classe parente à consulter  */
+    undef_extra_data_t *extra;              /* Données insérées à consulter*/
+
+    parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class);
+
+    result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf);
+
+    if (result)
+    {
+        extra = GET_UNDEF_INSTR_EXTRA(instr);
+
+        LOCK_GOBJECT_EXTRA(extra);
+
+        result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false);
+
+        UNLOCK_GOBJECT_EXTRA(extra);
+
+    }
+
+    return result;
+
+}
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 1fbc14b..56a45a4 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -1898,7 +1898,7 @@ instr_iter_t *_g_arch_processor_get_covered_iter_from_address(GArchProcessor *pr
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = élément GLib à constuire.                          *
+*  Paramètres  : proc    = élément GLib à constuire.                          *
 *                storage = conservateur de données à manipuler ou NULL.       *
 *                pbuf    = zone tampon à lire.                                *
 *                                                                             *
@@ -1940,7 +1940,7 @@ static bool g_arch_processor_load(GArchProcessor *proc, GObjectStorage *storage,
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = élément GLib à consulter.                          *
+*  Paramètres  : proc    = élément GLib à consulter.                          *
 *                storage = conservateur de données à manipuler ou NULL.       *
 *                pbuf    = zone tampon à remplir.                             *
 *                                                                             *
diff --git a/src/arch/storage.c b/src/arch/storage.c
index 41fa602..d552ae3 100644
--- a/src/arch/storage.c
+++ b/src/arch/storage.c
@@ -486,7 +486,7 @@ static void g_ins_caching_process_store(GInsCaching *caching, GtkStatusStack *st
 
         instr = g_arch_processor_get_instruction(proc, i);
 
-        caching->status = g_arch_instruction_store(instr, storage, &pbuf);
+        caching->status = g_arch_instruction_store__old(instr, storage, &pbuf);
 
         if (caching->status)
             caching->status = g_asm_storage_store_instruction_data(storage, &pbuf, &pos);
@@ -1544,7 +1544,7 @@ GArchInstruction *g_asm_storage_get_instruction_at(GAsmStorage *storage, GBinFor
                 status = g_asm_storage_load_instruction_data(storage, pbuf, target);
 
             if (status)
-                storage->collected[index] = g_arch_instruction_load(storage, format, pbuf);
+                storage->collected[index] = g_arch_instruction_load__old(storage, format, pbuf);
 
             if (storage->collected[index] != NULL)
             {
-- 
cgit v0.11.2-87-g4458