From 0e3059731d9687027c913135b3b856596c49a689 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 19 Sep 2015 22:28:42 +0000
Subject: Extended the prototype for matching formats in order to get it
 suitable for plugins.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@577 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                           |  72 +++++
 plugins/devdbg/speed.c              |   3 -
 plugins/mobicore/mclf.c             |  14 +-
 plugins/mobicore/mclf.h             |   3 +-
 plugins/mobicore/mobicore.c         |   6 +-
 plugins/pychrysa/core/Makefile.am   |   1 +
 plugins/pychrysa/core/module.c      |   2 +
 plugins/pychrysa/plugin.c           | 340 ++++++++---------------
 plugins/python/apkfiles/__init__.py |   4 +-
 plugins/python/apkfiles/apkfiles.py |  27 +-
 plugins/ropgadgets/select.c         |  12 +-
 src/analysis/binaries/file.c        |   8 +-
 src/analysis/binary-int.h           |  12 +-
 src/analysis/binary.c               | 307 +++++++++++++++++++--
 src/analysis/binary.h               |  32 ++-
 src/analysis/content-int.h          |  10 +
 src/analysis/content.c              |  86 ++++++
 src/analysis/content.h              |  10 +
 src/analysis/contents/file.c        | 128 +++++++++
 src/analysis/contents/file.h        |   3 +
 src/analysis/disass/disassembler.c  |   2 +-
 src/analysis/project.c              | 530 ++++++++++++++++++++++++++++++++++--
 src/analysis/project.h              |  52 ++++
 src/common/xml.c                    | 108 +++++++-
 src/common/xml.h                    |  11 +-
 src/core/formats.c                  |  34 ++-
 src/core/formats.h                  |  20 +-
 src/format/dwarf/dwarf.c            |  31 ++-
 src/format/dwarf/dwarf.h            |   4 +-
 src/format/elf/elf.c                |  16 +-
 src/format/elf/elf.h                |   5 +-
 src/format/executable-int.h         |   3 +
 src/format/executable.c             |  78 ++++++
 src/format/executable.h             |   9 +
 src/gui/menus/project.c             |  13 +-
 src/plugins/plugin-int.h            |  29 +-
 src/plugins/plugin.c                |  26 +-
 37 files changed, 1689 insertions(+), 362 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 166ef5d..6b28940 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,75 @@
+15-09-19  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/devdbg/speed.c:
+	Remove debug code.
+
+	* plugins/mobicore/mclf.c:
+	* plugins/mobicore/mclf.h:
+	* plugins/mobicore/mobicore.c:
+	Update code.
+
+	* plugins/pychrysa/core/Makefile.am:
+	Add the missing 'formats.[ch]' files to libpychrysacore_la_SOURCES.
+
+	* plugins/pychrysa/core/module.c:
+	Load formats core into Python.
+
+	* plugins/pychrysa/plugin.c:
+	* plugins/python/apkfiles/apkfiles.py:
+	* plugins/python/apkfiles/__init__.py:
+	* plugins/ropgadgets/select.c:
+	Update code.
+
+	* src/analysis/binaries/file.c:
+	Disable this specific kind of instances for loaded binaries.
+
+	* src/analysis/binary.c:
+	* src/analysis/binary.h:
+	* src/analysis/binary-int.h:
+	Build a standalone generic binary. Use binary contents as external
+	entities. Only reference the main binary format and attach debug
+	info to it.
+
+	* src/analysis/content.c:
+	* src/analysis/content.h:
+	* src/analysis/content-int.h:
+	* src/analysis/contents/file.c:
+	* src/analysis/contents/file.h:
+	Describe, save and restore binary contents.
+
+	* src/analysis/disass/disassembler.c:
+	Update code.
+
+	* src/analysis/project.c:
+	* src/analysis/project.h:
+	Store binary contents as well as loaded binaries. Update the storing and
+	restoring routines.
+
+	* src/common/xml.c:
+	* src/common/xml.h:
+	Handle long values for nodes attributes.
+
+	* src/core/formats.c:
+	* src/core/formats.h:
+	Extend the prototype for matching formats in order to get it suitable
+	for plugins.
+
+	* src/format/dwarf/dwarf.c:
+	* src/format/dwarf/dwarf.h:
+	* src/format/elf/elf.c:
+	* src/format/elf/elf.h:
+	Update code.
+
+	* src/format/executable.c:
+	* src/format/executable.h:
+	* src/format/executable-int.h:
+	Store debug information when requested.
+
+	* src/gui/menus/project.c:
+	* src/plugins/plugin.c:
+	* src/plugins/plugin-int.h:
+	Update code.
+
 15-09-11  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/plugins/devdbg/speed.c b/plugins/devdbg/speed.c
index e5042ea..538a741 100644
--- a/plugins/devdbg/speed.c
+++ b/plugins/devdbg/speed.c
@@ -79,7 +79,6 @@ G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *plugin, Plu
 
     }
 
-
     switch (action)
     {
         case PGA_DISASSEMBLY_STARTED:
@@ -115,6 +114,4 @@ G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *plugin, Plu
 
     }
 
-    printf("##########\n\nPassage 0x%08x !!!\n\n################\n", action);
-
 }
diff --git a/plugins/mobicore/mclf.c b/plugins/mobicore/mclf.c
index 99ff7ed..4ff44bb 100644
--- a/plugins/mobicore/mclf.c
+++ b/plugins/mobicore/mclf.c
@@ -56,6 +56,8 @@ static void g_mclf_format_refine_portions(const GMCLFFormat *, GBinPortion *);
 *                                                                             *
 *  Paramètres  : content = contenu binaire à parcourir.                       *
 *                parent  = éventuel format exécutable déjà chargé.            *
+*                unused  = adresse non utilisée ici.                          *
+*                key     = identifiant de format trouvé ou NULL. [OUT]        *
 *                                                                             *
 *  Description : Indique si le format peut être pris en charge ici.           *
 *                                                                             *
@@ -65,9 +67,9 @@ static void g_mclf_format_refine_portions(const GMCLFFormat *, GBinPortion *);
 *                                                                             *
 ******************************************************************************/
 
-const char *mclf_is_matching(GBinContent *content, GExeFormat *parent)
+FormatMatchStatus mclf_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key)
 {
-    const char *result;                     /* Format détecté à renvoyer   */
+    FormatMatchStatus result;               /* Bilan à renvoyer            */
     vmpa2t addr;                            /* Tête de lecture initiale    */
     bool status;                            /* Bilan des accès mémoire     */
     char magic[4];                          /* Idenfiant standard          */
@@ -78,7 +80,13 @@ const char *mclf_is_matching(GBinContent *content, GExeFormat *parent)
 
     status &= (memcmp(magic, MC_SERVICE_HEADER_MAGIC_STR, 4) == 0);
 
-    result = status ? "mclf" : NULL;
+    if (status)
+    {
+        result = FMS_MATCHED;
+        *key = strdup("mclf");
+    }
+    else
+        result = FMS_UNKNOWN;
 
     return result;
 
diff --git a/plugins/mobicore/mclf.h b/plugins/mobicore/mclf.h
index 5ac0926..78ed57b 100644
--- a/plugins/mobicore/mclf.h
+++ b/plugins/mobicore/mclf.h
@@ -30,6 +30,7 @@
 #include <sys/types.h>
 
 
+#include <core/formats.h>
 #include <format/executable.h>
 #include <format/format.h>
 
@@ -51,7 +52,7 @@ typedef struct _GMCLFFormatClass GMCLFFormatClass;
 
 
 /* Indique si le format peut être pris en charge ici. */
-const char *mclf_is_matching(GBinContent *, GExeFormat *);
+FormatMatchStatus mclf_is_matching(GBinContent *, GExeFormat *, void *, char **);
 
 /* Indique le type défini pour un format d'exécutable MCLF. */
 GType g_mclf_format_get_type(void);
diff --git a/plugins/mobicore/mobicore.c b/plugins/mobicore/mobicore.c
index 087297b..8a28a76 100644
--- a/plugins/mobicore/mobicore.c
+++ b/plugins/mobicore/mobicore.c
@@ -54,9 +54,11 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref)
 {
     bool result;                            /* Bilan à retourner           */
 
-    result &= register_format_matcher(mclf_is_matching);
+    result = true;
 
-    result = register_format_loader("mclf", "MobiCore Load Format", g_mclf_format_new);
+    result &= register_format_matcher(mclf_is_matching, NULL);
+
+    result &= register_format_loader("mclf", "MobiCore Load Format", g_mclf_format_new);
 
     return result;
 
diff --git a/plugins/pychrysa/core/Makefile.am b/plugins/pychrysa/core/Makefile.am
index 1ffacf4..129b5af 100644
--- a/plugins/pychrysa/core/Makefile.am
+++ b/plugins/pychrysa/core/Makefile.am
@@ -2,6 +2,7 @@
 noinst_LTLIBRARIES = libpychrysacore.la
 
 libpychrysacore_la_SOURCES =			\
+	formats.h formats.c					\
 	module.h module.c					\
 	params.h params.c
 
diff --git a/plugins/pychrysa/core/module.c b/plugins/pychrysa/core/module.c
index a866c05..9fcede9 100644
--- a/plugins/pychrysa/core/module.c
+++ b/plugins/pychrysa/core/module.c
@@ -28,6 +28,7 @@
 #include <assert.h>
 
 
+#include "formats.h"
 #include "params.h"
 
 
@@ -78,6 +79,7 @@ bool add_core_module_to_python_module(PyObject *super)
 
     result = true;
 
+    result &= register_python_formats(module);
     result &= register_python_params(module);
 
  loading_failed:
diff --git a/plugins/pychrysa/plugin.c b/plugins/pychrysa/plugin.c
index 44cb0d8..5e968e2 100644
--- a/plugins/pychrysa/plugin.c
+++ b/plugins/pychrysa/plugin.c
@@ -30,6 +30,8 @@
 
 
 #include <common/extstr.h>
+#include "../../src/core/formats.h"
+//#include <core/formats.h>
 #include <plugins/plugin-int.h>
 
 
@@ -74,23 +76,11 @@ static bool g_python_plugin_do_init(GPythonPlugin *, GObject *);
 /* Procède à l'extinction du greffon. */
 static bool g_python_plugin_do_exit(GPythonPlugin *, GObject *);
 
+/* Indique si le format peut être pris en charge ici. */
+FormatMatchStatus python_plugin_is_matching(GBinContent *, GExeFormat *, GPythonPlugin *, char **);
 
-
-
-
-
-/* Indique l'utilité pratique du greffon. */
-static PluginAction g_python_plugin_get_action(const GPythonPlugin *);
-
-/* Indentifie un format à associer à un contenu binaire. */
-static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *, char **, bin_t **, off_t *);
-
-/* Exécute une action définie sur un binaire chargé. */
-static bool g_python_plugin_execute_on_binary(GPythonPlugin *, GLoadedBinary *, PluginAction);
-
-
-/* Exécute une action relative à un débogueur. */
-//static bool g_python_plugin_handle_debugger(const GPythonPlugin *, GBinaryDebugger *, PluginAction);
+/* Exécute une action pendant un désassemblage de binaire. */
+static void g_python_plugin_process_disass(const GPythonPlugin *, PluginAction, GLoadedBinary *);
 
 
 
@@ -143,19 +133,10 @@ static void g_python_plugin_class_init(GPythonPluginClass *klass)
 
 static void g_python_plugin_init(GPythonPlugin *plugin)
 {
-    GPluginModule *plugin_parent;           /* Instance parente            */
-
-    plugin_parent = G_PLUGIN_MODULE(plugin);
-
-    plugin_parent->exec_on_bin = (execute_action_on_binary_fc)g_python_plugin_execute_on_binary;
-    //plugin_parent->handle_debugger = (execute_on_debugger_fc)g_python_plugin_handle_debugger;
 
 }
 
 
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : modname  = nom du module à charger.                          *
@@ -184,6 +165,7 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO
     PyObject *class;                        /* Classe à instancier         */
     PyObject *instance;                     /* Instance Python du greffon  */
     size_t i;                               /* Boucle de parcours          */
+    uint32_t action;                        /* Identifiant d'une action    */
     uint32_t category;                      /* Catégorie principale        */
     uint32_t sub;                           /* Sous-catégorie visée        */
 
@@ -246,17 +228,6 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO
         goto gppn_interface_error;
     }
 
-
-    //G_PLUGIN_MODULE(result)->get_action = (get_plugin_action_fc)g_python_plugin_get_action;
-
-    //G_PLUGIN_MODULE(result)->is_matching = (is_matching_fc)g_python_plugin_is_matching;
-
-
-
-
-
-
-
     /* Localisation des différents points d'entrée déclarés */
 
 #define register_python_binding(inst, sym, binding)                                 \
@@ -279,8 +250,9 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO
 
     for (i = 0; i < G_PLUGIN_MODULE(result)->interface->actions_count; i++)
     {
-        category = MASK_PLUGIN_CATEGORY(G_PLUGIN_MODULE(result)->interface->actions[i]);
-        sub = MASK_PLUGIN_SUB_CATEGORY(G_PLUGIN_MODULE(result)->interface->actions[i]);
+        action = G_PLUGIN_MODULE(result)->interface->actions[i];
+        category = MASK_PLUGIN_CATEGORY(action);
+        sub = MASK_PLUGIN_SUB_CATEGORY(action);
 
         switch (category)
         {
@@ -309,26 +281,39 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO
                 }
 
                 break;
-#if 0
+
             case DPC_BINARY_PROCESSING:
 
                 switch (sub)
                 {
                     case DPS_FORMAT:
 
-                        switch (result->interface->actions[i])
+                        switch (action)
                         {
+                            case PGA_FORMAT_MATCHER:
+
+                                if (!has_python_method(instance, "is_format_matching"))
+                                {
+                                    log_variadic_message(LMT_ERROR,
+                                                         _("No '%s' entry in plugin candidate '%s'"),
+                                                         "is_format_matching",
+                                                         G_PLUGIN_MODULE(result)->filename);
+                                    goto gppn_bad_plugin;
+                                }
+
+                                if (!register_format_matcher((format_match_fc)python_plugin_is_matching, result))
+                                    goto gppn_bad_plugin;
+
+                                break;
 
                             case PGA_FORMAT_LOADER_LAST:
-                                if (!load_plugin_symbol(result->module,
-                                                        "handle_binary_format", &result->handle_format))
-                                    goto bad_plugin;
+                                /* TODO */
                                 break;
 
                             default:
                                 log_variadic_message(LMT_WARNING,
                                                      _("Unknown action '0x%02x' in plugin '%s'..."),
-                                                     result->interface->actions[i], filename);
+                                                     action, filename);
                                 break;
 
                         }
@@ -336,9 +321,9 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO
                         break;
 
                     case DPS_DISASSEMBLY:
-                        if (!load_plugin_symbol(result->module,
-                                                "process_binary_disassembly", &result->proc_disass))
-                            goto bad_plugin;
+                        if (!register_python_binding(instance, process_disass,
+                                                     (pg_process_disassembly_fc)g_python_plugin_process_disass))
+                            goto gppn_bad_plugin;
                         break;
 
                     default:
@@ -349,7 +334,7 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO
                 }
 
                 break;
-#endif
+
             default:
                 log_variadic_message(LMT_WARNING,
                                      _("Unknown category '0x%02x' in plugin '%s'..."), category, filename);
@@ -555,234 +540,152 @@ static bool g_python_plugin_do_exit(GPythonPlugin *plugin, GObject *ref)
 }
 
 
-
-
-
-
-
-
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon de prise en charge à utiliser.              *
+*  Paramètres  : content = contenu binaire à parcourir.                       *
+*                parent  = éventuel format exécutable déjà chargé.            *
+*                plugin  = grefon C interne représentant le grefon Python.    *
+*                key     = identifiant de format trouvé ou NULL. [OUT]        *
 *                                                                             *
-*  Description : Indique l'utilité pratique du greffon.                       *
+*  Description : Indique si le format peut être pris en charge ici.           *
 *                                                                             *
-*  Retour      : Action(s) codifiée(s), PGA_NONE par défaut.                  *
+*  Retour      : Conclusion de haut niveau sur la reconnaissance effectuée.   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PluginAction g_python_plugin_get_action(const GPythonPlugin *plugin)
+FormatMatchStatus python_plugin_is_matching(GBinContent *content, GExeFormat *parent, GPythonPlugin *plugin, char **key)
 {
-    PluginAction result;                    /* Valeur à retourner          */
-    PyObject *value;                        /* Valeur obtenue              */
-
-    value = run_python_method(plugin->instance, "get_action", NULL);
-
-    if (value != NULL)
-    {
-        result = PyLong_AsLong(value);
-        Py_DECREF(value);
-    }
-    else
-        result = 0;//PGA_NONE;
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : plugin   = greffon de prise en charge à utiliser.            *
-*                filename = éventuel nom de fichier associé ou NULL. [OUT]    *
-*                data     = données chargées. [OUT]                           *
-*                length   = quantité de ces données. [OUT]                    *
-*                                                                             *
-*  Description : Indentifie un format à associer à un contenu binaire.        *
-*                                                                             *
-*  Retour      : Bilan de la recherche de correspondances.                    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *plugin, char **filename, bin_t **data, off_t *length)
-{
-    return MFA_NONE;
-
-#if 0
-    MatchingFormatAction result;            /* Valeur à retourner          */
+    FormatMatchStatus result;               /* Bilan à renvoyer            */
     PyObject *args;                         /* Arguments pour l'appel      */
-    PyObject *value;                        /* Valeurs obtenues            */
-    PyObject *action;                       /* Action à faire suivre       */
-    PyObject *new_filename;                 /* Nouveau fichier             */
-    PyObject *new_data;                     /* Nouvelles données           */
-    char *tmp;                              /* Stockage avant recopie      */
+    PyObject *value;                        /* Valeur obtenue              */
+    PyObject *arg;                          /* Argument en élément de tuple*/
 
-    if (*filename == NULL)
-        return MFA_NONE;
+    result = FMS_UNKNOWN;
 
     args = PyTuple_New(2);
+    PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(content)));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(parent)));
 
-    PyTuple_SetItem(args, 0, PyString_FromString(*filename));
-    PyTuple_SetItem(args, 1, PyByteArray_FromStringAndSize((char *)*data, *length));
-
-    value = run_python_method(plugin->instance, "is_matching", args);
+    value = run_python_method(plugin->instance, "is_format_matching", args);
 
-    if (value != NULL && PyTuple_Check(value) && PyTuple_Size(value) == 3)
+    if (PyTuple_Check(value))
     {
-        action = PyTuple_GetItem(value, 0);
-        new_filename = PyTuple_GetItem(value, 1);
-        new_data = PyTuple_GetItem(value, 2);
-
-        if (action == NULL || new_filename == NULL || new_data == NULL)
-            goto is_matching_bad;
-
-        if (!PyInt_Check(action)
-            || (new_filename != Py_None && !PyString_Check(new_filename))
-            || (new_data != Py_None && !PyByteArray_Check(new_data)))
-            goto is_matching_bad;
-
-        result = PyInt_AsLong(action);
-        if (result >= MFA_COUNT) goto is_matching_bad;
-
-        if (result != MFA_NONE && new_data == Py_None) goto is_matching_bad;
-
-        if (new_filename != Py_None)
-        {
-            free(*filename);
-            *filename = strdup(PyString_AsString(new_filename));
-        }
-
-        /**
-         * La suppression de la part du greffon n'est permise que
-         * si une prise en charge est assurée.
-         */
-        else if (result != MFA_NONE)
-        {
-            free(*filename);
-            *filename = NULL;
-        }
-
-        /**
-         * Pareil que précédemment.
-         */
-        if (new_data != Py_None)
+        if (PyTuple_Size(value) > 0)
         {
-            tmp = PyByteArray_AsString(new_data);
-            *length = PyByteArray_Size(new_data);
-
-            free(*data);
-
-            *data = (bin_t *)calloc(*length, sizeof(bin_t));
-            memcpy(*data, tmp, *length * sizeof(bin_t));
-
-        }
+            arg = PyTuple_GetItem(value, 0);
 
-        goto is_matching_ok;
+            if (PyLong_Check(arg))
+            {
+                result = PyLong_AsLong(arg);
 
-    }
-
- is_matching_bad:
-
-    printf("<LOG>Bad result from is_matching() plugin function.\n");
+                switch (result)
+                {
+                    case FMS_MATCHED:
 
-    result = MFA_NONE;
+                        if (PyTuple_Size(value) != 2)
+                        {
+                            g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+                                                                 _("Expecting only a tuple [ status, key ] " \
+                                                                   "as result for format matching."));
+                            result = FMS_UNKNOWN;
+                            break;
+                        }
 
- is_matching_ok:
+                        arg = PyTuple_GetItem(value, 1);
 
-    Py_XDECREF(value);
-    Py_DECREF(args);
+                        if (PyUnicode_Check(arg))
+                            *key = strdup(PyUnicode_AsUTF8(arg));
 
-    return result;
-#endif
-}
+                        else
+                        {
+                            g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+                                                                 _("Expecting a key string for format matching."));
+                            result = FMS_UNKNOWN;
+                        }
 
+                        break;
 
+                    case FMS_FORWARDED:
+                    case FMS_UNKNOWN:
+                        if (PyTuple_Size(value) != 1)
+                        {
+                            g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_WARNING,
+                                                 _("Unused second item for format matching."));
+                        }
+                        break;
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : plugin = greffon de prise en charge à utiliser.              *
-*                binary = représentation binaire à traiter.                   *
-*                action = action attendue.                                    *
-*                                                                             *
-*  Description : Exécute une action définie sur un binaire chargé.            *
-*                                                                             *
-*  Retour      : true si une action a été menée, false sinon.                 *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+                    default:
+                        g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+                                                             _("Unexpected result for format matching."));
+                        result = FMS_UNKNOWN;
+                        break;
 
-static bool g_python_plugin_execute_on_binary(GPythonPlugin *plugin, GLoadedBinary *binary, PluginAction action)
-{
-    bool result;                            /* Bilan à remonter            */
-    PyObject *args;                         /* Arguments pour l'appel      */
-    PyObject *value;                        /* Valeurs obtenues            */
+                }
 
-    args = PyTuple_New(2);
+            }
 
-    PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(binary)));
-    PyTuple_SetItem(args, 1, Py_None);//PyInt_FromLong(action));
+            else
+            {
+                g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+                                                     _("Unexpected result status for format matching."));
+                result = FMS_UNKNOWN;
+            }
 
-    value = run_python_method(plugin->instance, "execute_on_binary", args);
+        }
+        else
+            g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_WARNING,
+                                                 _("Interpreting a empty tuple as FMS_UNKNOWN " \
+                                                   "for format matching."));
 
-    result = (value == Py_True);
+    }
+    else
+        g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR,
+                                             _("Expected a tuple containing [ status, key ] as result " \
+                                               "for format matching."));
 
     Py_XDECREF(value);
     Py_DECREF(args);
 
     return result;
 
-}
 
 
 
+}
 
 
-#if 0
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin   = greffon à consulter.                              *
-*                debugger = débogueur à l'origine de l'opération.             *
-*                action   = action attendue.                                  *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                binary = binaire dont le contenu est en cours de traitement. *
 *                                                                             *
-*  Description : Exécute une action relative à un débogueur.                  *
+*  Description : Exécute une action pendant un désassemblage de binaire.      *
 *                                                                             *
-*  Retour      : true si une action a été menée, false sinon.                 *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_python_plugin_handle_debugger(const GPythonPlugin *plugin, GBinaryDebugger *debugger, PluginAction action)
+static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAction action, GLoadedBinary *binary)
 {
-    bool result;                            /* Bilan à remonter            */
     PyObject *args;                         /* Arguments pour l'appel      */
     PyObject *value;                        /* Valeurs obtenues            */
 
     args = PyTuple_New(2);
 
-    PyTuple_SetItem(args, 0, py_binary_debugger_from_c(debugger));
-    PyTuple_SetItem(args, 1, Py_None);//PyInt_FromLong(action));
+    PyTuple_SetItem(args, 0, PyLong_FromLong(action));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary)));
 
-    value = run_python_method(plugin->instance, "handle_debugger", args);
-
-    result = (value == Py_True);
+    value = run_python_method(plugin->instance, "process_binary_disassembly", args);
 
     Py_XDECREF(value);
     Py_DECREF(args);
 
-    return result;
-
 }
-#endif
-
-
-
-
 
 
 
@@ -791,19 +694,6 @@ static bool g_python_plugin_handle_debugger(const GPythonPlugin *plugin, GBinary
 /* ---------------------------------------------------------------------------------- */
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
diff --git a/plugins/python/apkfiles/__init__.py b/plugins/python/apkfiles/__init__.py
index 2ebf824..7da894e 100644
--- a/plugins/python/apkfiles/__init__.py
+++ b/plugins/python/apkfiles/__init__.py
@@ -1,2 +1,4 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
 
-from apkfiles import ApkFiles as apkfiles
+from apkfiles.apkfiles import ApkFiles as AutoLoad
diff --git a/plugins/python/apkfiles/apkfiles.py b/plugins/python/apkfiles/apkfiles.py
index 7c05ca9..b85b0c8 100644
--- a/plugins/python/apkfiles/apkfiles.py
+++ b/plugins/python/apkfiles/apkfiles.py
@@ -1,15 +1,36 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 
-from pychrysalide import Plugin
-
+from pychrysalide import PluginModule
 import zipfile
 
 
-class ApkFiles(Plugin):
+class ApkFiles(PluginModule):
     """Open and process APK files."""
 
 
+    def get_interface(self):
+        """Provide the full plugin description."""
+
+        desc = {
+
+            'name' : 'Welcome',
+            'desc' : 'Add suppport for the APK file format',
+            'version' : '0.1',
+
+            'actions' : [ PluginModule.PGA_PLUGIN_INIT ]
+
+        }
+
+        return desc
+
+
+    def init(self, ref):
+        """Initialise l'extension."""
+
+        return True
+
+
     def get_action(self):
         """Register the plugin for given actions."""
 
diff --git a/plugins/ropgadgets/select.c b/plugins/ropgadgets/select.c
index 53995e5..2497dd1 100644
--- a/plugins/ropgadgets/select.c
+++ b/plugins/ropgadgets/select.c
@@ -1316,7 +1316,8 @@ static GBinFormat *load_external_format_for_rop_gadgets(GObject *ref)
     GtkEntry *entry;                        /* Zone de saisie de texte     */
     const gchar *filename;                  /* Nom du fichier à charger    */
     GBinContent *content;                   /* Contenu binaire chargé      */
-    const char *target;                     /* Sous-traitance requise      */
+    FormatMatchStatus status;               /* Statut d'une reconnaissance */
+    char *target;                           /* Sous-traitance requise      */
     const char *desc;                       /* Description humaine associée*/
 
     /* Récupération du nom de fichier */
@@ -1338,18 +1339,21 @@ static GBinFormat *load_external_format_for_rop_gadgets(GObject *ref)
 
     /* Récupération du format de fichier associé */
 
-    target = find_matching_format(content, NULL);
-    desc = get_binary_format_name(target);
+    status = find_matching_format(content, NULL, &target);
 
-    if (desc == NULL)
+    if (status != FMS_MATCHED)
     {
         g_object_unref(G_OBJECT(content));
         push_status_printing_of_rop_search_step(ref, "format", _("unknown binary format"), false);
         goto leffrg_error;
     }
 
+    desc = get_binary_format_name(target);
+
     result = load_new_named_format(target, content, NULL);
 
+    free(target);
+
     if (result == NULL)
     {
         push_status_printing_of_rop_search_step(ref, "format", _("error while loading the binary"), false);
diff --git a/src/analysis/binaries/file.c b/src/analysis/binaries/file.c
index 32cd41f..c31828c 100644
--- a/src/analysis/binaries/file.c
+++ b/src/analysis/binaries/file.c
@@ -116,8 +116,8 @@ static void g_file_binary_init(GFileBinary *binary)
 
     loaded = G_LOADED_BINARY(binary);
 
-    loaded->save = (save_binary_fc)g_file_binary_save;
-    loaded->get_name = (get_binary_name_fc)g_file_binary_get_name;
+    //loaded->save = (save_binary_fc)g_file_binary_save;
+    //loaded->get_name = (get_binary_name_fc)g_file_binary_get_name;
 
 }
 
@@ -173,7 +173,7 @@ GLoadedBinary *g_file_binary_new_from_file(const char *filename)
     content = g_file_content_new(filename);
     if (content == NULL) goto lbf_error;
 
-    target = find_matching_format(content, NULL);
+    target = "";//find_matching_format(content, NULL);
     desc = get_binary_format_name(target);
 
     if (desc == NULL)
@@ -194,7 +194,7 @@ GLoadedBinary *g_file_binary_new_from_file(const char *filename)
         goto lbf_error;
     }
 
-    target = find_matching_format(content, loaded->format);
+    target = "";//find_matching_format(content, loaded->format);
     desc = get_binary_format_name(target);
 
     if (desc != NULL)
diff --git a/src/analysis/binary-int.h b/src/analysis/binary-int.h
index 4bfb14e..60b9662 100644
--- a/src/analysis/binary-int.h
+++ b/src/analysis/binary-int.h
@@ -33,11 +33,8 @@
 
 
 
-/* Ecrit une sauvegarde du binaire dans un fichier XML. */
-typedef bool (* save_binary_fc) (const GLoadedBinary *, xmlDocPtr, xmlXPathContextPtr, const char *);
-
 /* Fournit le fichier correspondant à l'élément binaire. */
-typedef const char * (* get_binary_name_fc) (const GLoadedBinary *, bool);
+typedef const char * (* get_binary_name_fc) (const GLoadedBinary *, bool); //// REMME
 
 
 /* Description de fichier binaire (instance) */
@@ -57,11 +54,12 @@ struct _GLoadedBinary
     DBStorage storages[DBF_COUNT];          /* Lieux d'enregistrement      */
     GList *collections;                     /* Ensemble de modifications   */
 
-    save_binary_fc save;                    /* Sauvegarde au format XML    */
-    get_binary_name_fc get_name;            /* Obtention d'une description */
+    get_binary_name_fc get_name;            /* Obtention d'une description */ //// REMME
+
+    GBinContent *content;                   /* Contenu binaire chargé      */ //// REMME
 
     GExeFormat *format;                     /* Format du binaire           */
-    GDbgFormat *debug;                      /* Informations de débogage    */
+    GDbgFormat *debug;                      /* Informations de débogage    */ //// REMME
     GArchProcessor *proc;                   /* Architecture du binaire     */
 
     GArchInstruction *instrs;               /* Instructions d'assemblage   */
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 615e72e..c94f4f6 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -24,12 +24,14 @@
 #include "binary.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 
+
 #include <i18n.h>
 
 
@@ -41,8 +43,11 @@
 #include "../common/extstr.h"
 #include "../common/cpp.h"
 #include "../core/collections.h"
+#include "../core/formats.h"
 #include "../core/params.h"
+#include "../core/processors.h"
 #include "../glibext/chrysamarshal.h"
+#include "../gui/panels/log.h"
 
 
 
@@ -185,8 +190,11 @@ static void g_loaded_binary_init(GLoadedBinary *binary)
 
 static void g_loaded_binary_dispose(GLoadedBinary *binary)
 {
+    g_object_unref(G_OBJECT(binary->content));
+
     if (binary->format != NULL)
         g_object_unref(G_OBJECT(binary->format));
+
     if (binary->proc != NULL)
         g_object_unref(G_OBJECT(binary->proc));
 
@@ -222,10 +230,103 @@ static void g_loaded_binary_finalize(GLoadedBinary *binary)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : context = contexte pour les recherches XPath.                *
+*  Paramètres  : content = contenu binaire chargé en mémoire.                 *
+*                                                                             *
+*  Description : Interprète un contenu binaire chargé.                        *
+*                                                                             *
+*  Retour      : Adresse de la représentation ou NULL en cas d'échec.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GLoadedBinary *g_loaded_binary_new(GBinContent *content)
+{
+    GLoadedBinary *result;                  /* Adresse à retourner         */
+    FormatMatchStatus status;               /* Statut d'une reconnaissance */
+    char *target;                           /* Sous-traitance requise      */
+    const char *desc;                       /* Description humaine associée*/
+    const char *arch;                       /* Architecture d'exécution    */
+
+    result = g_object_new(G_TYPE_LOADED_BINARY, NULL);
+
+    log_variadic_message(LMT_PROCESS, _("Opening binary data from '%s'..."),
+                         g_binary_content_describe(content, true));
+
+    g_object_ref(G_OBJECT(content));
+    result->content = content;
+
+    /* Format d'exécutable */
+
+    status = find_matching_format(content, NULL, &target);
+    assert(status == FMS_MATCHED);
+
+    desc = get_binary_format_name(target);
+
+    if (desc == NULL)
+    {
+        free(target);
+        log_simple_message(LMT_INFO, _("Unknown binary format"));
+        goto lbf_error;
+    }
+    else
+        log_variadic_message(LMT_INFO, _("Detected format: %s"), desc);
+
+    result->format = G_EXE_FORMAT(load_new_named_format(target, content, NULL));
+
+    free(target);
+
+    if (result->format == NULL)
+    {
+        log_simple_message(LMT_ERROR, _("Error while loading the binary"));
+        goto lbf_error;
+    }
+
+    /* Informations de débogage associées */
+
+    if (!g_loaded_binary_attach_debug_info(result, content))
+        goto lbf_error;
+
+    /* Architecture visée */
+
+    arch = g_exe_format_get_target_machine(result->format);
+    desc = get_arch_processor_name(arch);
+
+    if (desc == NULL)
+    {
+        log_simple_message(LMT_INFO, _("Unknown architecture"));
+        goto lbf_error;
+    }
+    else
+        log_variadic_message(LMT_INFO, _("Detected architecture: %s"), desc);
+
+    result->proc = get_arch_processor_for_type(arch);
+
+    if (result->proc == NULL)
+    {
+        log_simple_message(LMT_ERROR, _("Unable to load the required processor"));
+        goto lbf_error;
+    }
+
+    return G_LOADED_BINARY(result);
+
+ lbf_error:
+
+    g_object_unref(G_OBJECT(result));
+
+    return NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire chargé en mémoire.                 *
+*                context = contexte pour les recherches XPath.                *
 *                path    = chemin d'accès au noeud XML à lire.                *
+*                project = projet dans lequel venir rechercher les contenus.  *
 *                                                                             *
-*  Description : Charge en mémoire le contenu d'un fichier à partir d'XML.    *
+*  Description : Interprète un contenu binaire chargé avec un appui XML.      *
 *                                                                             *
 *  Retour      : Adresse de la représentation ou NULL en cas d'échec.         *
 *                                                                             *
@@ -233,39 +334,94 @@ static void g_loaded_binary_finalize(GLoadedBinary *binary)
 *                                                                             *
 ******************************************************************************/
 
-GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const char *path)
+GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const char *path, GStudyProject *project)
 {
     GLoadedBinary *result;                  /* Adresse à retourner         */
-    char *type;                             /* Type de binaire à charger   */
+    char *content_path;                     /* Partie "Contenus"           */
+    char *access;                           /* Chemin d'accès à un élément */
+    char *hash;                             /* Empreinte à retrouver       */
+    GBinContent *content;                   /* Contenu à référencer        */
+
+    xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */
+    unsigned int i;                         /* Boucle de parcours          */
+
+    /* Contenus binaires associés */
+
+    content_path = strdup(path);
+    content_path = stradd(content_path, "/Contents");
+
+    access = strdup(content_path);
+    access = stradd(access, "/Main");
 
+    hash = get_node_text_value(context, access);
 
+    free(access);
 
-    result = NULL;
+    if (hash == NULL)
+    {
+        free(content_path);
+        return NULL;
+    }
 
-    type = get_node_prop_value(context, path, "type");
+    content = g_study_project_find_binary_content_by_hash(project, hash);
+    free(hash);
 
-    if (strcmp(type, "file") == 0)
-        result = g_file_binary_new_from_xml(context, path);
+    if (content == NULL)
+    {
+        free(content_path);
+        return NULL;
+    }
 
-    free(type);
+    result = g_loaded_binary_new(content);
 
     if (result == NULL)
+    {
+        free(content_path);
         return NULL;
+    }
 
-    /* --------- %< --------- TODO : à bouger pour + de générique --------- %< --------- */
+    xobject = get_node_xpath_object(context, "/ChrysalideProject/Contents/Content");
 
+    for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
+    {
+        asprintf(&access, "%s/DebugInfo[position()=%u]", content_path, i + 1);
 
-    // -> init()
-    //result->collections = create_collections_list();
+        hash = get_node_text_value(context, access);
 
+        free(access);
 
-    if (!g_loaded_binary_load_storage(result, context, path))
-        goto glbnfx_error;
+        if (hash == NULL)
+        {
+            free(content_path);
+            goto glbnfx_error;
+        }
+
+        content = g_study_project_find_binary_content_by_hash(project, hash);
+        free(hash);
+
+        if (content == NULL)
+        {
+            free(content_path);
+            goto glbnfx_error;
+        }
 
+        if (!g_loaded_binary_attach_debug_info(result, content))
+        {
+            free(content_path);
+            goto glbnfx_error;
+        }
+
+    }
+
+    if(xobject != NULL)
+        xmlXPathFreeObject(xobject);
 
-    /* --------- %< --------- TODO : à bouger pur + de générique --------- %< --------- */
+    free(content_path);
 
+    /* Elément divers associés au binaire */
 
+    if (!g_loaded_binary_load_storage(result, context, path))
+        goto glbnfx_error;
 
     return result;
 
@@ -296,15 +452,88 @@ GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const ch
 bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
 {
     bool result;                            /* Bilan à faire remonter      */
+    char *content_path;                     /* Partie "Contenus"           */
+    char *access;                           /* Chemin d'accès à un élément */
+    GBinContent *content;                   /* Contenu à référencer        */
+    const gchar *hash;                      /* Empreinte à mémoriser       */
+    size_t debugs_count;                    /* Quantité de formats liés    */
+    size_t i;                               /* Boucle de parcours          */
+    GDbgFormat *debug;                      /* Informations de débogage    */
+
+    /* Contenus binaires associés */
 
-    result = binary->save(binary, xdoc, context, path);
+    content_path = strdup(path);
+    content_path = stradd(content_path, "/Contents");
+
+    access = strdup(content_path);
+    access = stradd(access, "/Main");
+
+    content = g_binary_format_get_content(G_BIN_FORMAT(binary->format));
+    hash = g_binary_content_get_cheksum(content);
+    g_object_unref(G_OBJECT(content));
+
+    result = add_content_to_node(xdoc, context, access, hash);
+
+    free(access);
+
+    debugs_count = g_exe_format_count_debug_info(binary->format);
+
+    for (i = 0; i < debugs_count; i++)
+    {
+        asprintf(&access, "%s/DebugInfo[position()=%zu]", content_path, i);
+
+        debug = g_exe_format_get_debug_info(binary->format, i);
+
+        content = g_binary_format_get_content(G_BIN_FORMAT(debug));
+        hash = g_binary_content_get_cheksum(content);
+        g_object_unref(G_OBJECT(content));
+
+        g_object_unref(G_OBJECT(debug));
+
+        result &= add_content_to_node(xdoc, context, access, hash);
+
+        free(access);
+
+    }
+
+    free(content_path);
+
+    /* Elément divers associés au binaire */
 
     result = g_loaded_binary_save_storage(binary, xdoc, context, path);
 
+    /* Sauvegarde côté serveur */
 
-    ////
     g_db_client_save(binary->local);
 
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = élément binaire à consulter.                        *
+*                full   = précise s'il s'agit d'une version longue ou non.    *
+*                                                                             *
+*  Description : Fournit le nom associé à l'élément binaire.                  *
+*                                                                             *
+*  Retour      : Nom de fichier avec chemin absolu.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_loaded_binary_get_name(const GLoadedBinary *binary, bool full)
+{
+    const char *result;                     /* Description à retourner     */
+    GBinContent *content;                   /* Contenu binaire mannipulé   */
+
+    content = g_binary_format_get_content(G_BIN_FORMAT(binary->format));
+
+    result = g_binary_content_describe(content, full);
+
+    g_object_unref(G_OBJECT(content));
 
     return result;
 
@@ -961,19 +1190,53 @@ void g_loaded_binary_analyse(GLoadedBinary *binary)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary = élément binaire à consulter.                        *
-*                full   = précise s'il s'agit d'une version longue ou non.    *
 *                                                                             *
-*  Description : Fournit le nom associé à l'élément binaire.                  *
+*  Description : Fournit le format de fichier reconnu dans le contenu binaire.*
 *                                                                             *
-*  Retour      : Nom de fichier avec chemin absolu.                           *
+*  Retour      : Instance du format reconnu.                                  *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const char *g_loaded_binary_get_name(const GLoadedBinary *binary, bool full)
+bool g_loaded_binary_attach_debug_info(GLoadedBinary *binary, GBinContent *content)
 {
-    return binary->get_name(binary, full);
+    bool result;                            /* Bilan à retourner pour info */
+    FormatMatchStatus status;               /* Statut d'une reconnaissance */
+    char *target;                           /* Sous-traitance requise      */
+    const char *desc;                       /* Description humaine associée*/
+    GDbgFormat *debug;                      /* Format de débogage trouvé   */
+
+    result = false;
+
+    status = find_matching_format(content, binary->format, &target);
+
+    if (status == FMS_MATCHED)
+    {
+        desc = get_binary_format_name(target);
+
+        if (desc != NULL)
+        {
+            log_variadic_message(LMT_INFO, _("Detected debug format: %s"), desc);
+
+            debug = G_DBG_FORMAT(load_new_named_format(target, content, binary->format));
+
+            if (debug == NULL)
+                log_simple_message(LMT_ERROR, _("Error while loading the debug information for binary"));
+
+            else
+            {
+                result = true;
+                g_exe_format_add_debug_info(binary->format, debug);
+            }
+
+        }
+
+        free(target);
+
+    }
+
+    return result;
 
 }
 
diff --git a/src/analysis/binary.h b/src/analysis/binary.h
index 6b7d338..4ef3a0d 100644
--- a/src/analysis/binary.h
+++ b/src/analysis/binary.h
@@ -28,6 +28,7 @@
 #include <glib-object.h>
 #include <stdbool.h>
 
+#include "content.h"
 #include "db/collection.h"
 #include "db/client.h"
 #include "db/protocol.h"
@@ -39,6 +40,23 @@
 
 
 
+/* Redéfinition depuis project.c : projet d'étude regroupant les binaires analysés (instance) */
+typedef struct _GStudyProject GStudyProject;
+
+
+
+#define G_TYPE_LOADED_BINARY               g_loaded_binary_get_type()
+#define G_LOADED_BINARY(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_loaded_binary_get_type(), GLoadedBinary))
+#define G_IS_LOADED_BINARY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_loaded_binary_get_type()))
+#define G_LOADED_BINARY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LOADED_BINARY, GLoadedBinaryClass))
+#define G_IS_LOADED_BINARY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LOADED_BINARY))
+#define G_LOADED_BINARY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LOADED_BINARY, GLoadedBinaryClass))
+
+
+
+
+
+
 #define G_TYPE_LOADED_BINARY               g_loaded_binary_get_type()
 #define G_LOADED_BINARY(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_loaded_binary_get_type(), GLoadedBinary))
 #define G_IS_LOADED_BINARY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_loaded_binary_get_type()))
@@ -79,12 +97,18 @@ typedef enum _BinaryView
 /* Indique le type défini pour une description de fichier binaire. */
 GType g_loaded_binary_get_type(void);
 
-/* Charge en mémoire le contenu d'un fichier à partir d'XML. */
-GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr, const char *);
+/* Interprète un contenu binaire chargé. */
+GLoadedBinary *g_loaded_binary_new(GBinContent *);
+
+/* Interprète un contenu binaire chargé avec un appui XML. */
+GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr, const char *, GStudyProject *);
 
 /* Ecrit une sauvegarde du binaire dans un fichier XML. */
 bool g_loaded_binary_save(const GLoadedBinary *, xmlDocPtr, xmlXPathContextPtr, const char *);
 
+/* Fournit le nom associé à l'élément binaire. */
+const char *g_loaded_binary_get_name(const GLoadedBinary *, bool);
+
 
 
 /* ------------------------- INFORMATIONS D'ENREGISTREMENTS ------------------------- */
@@ -155,8 +179,8 @@ bool _g_loaded_binary_remove_from_collection(GLoadedBinary *, DBFeatures, GDbIte
 /* Lance l'analyse d'un élément binaire chargé. */
 void g_loaded_binary_analyse(GLoadedBinary *);
 
-/* Fournit le nom associé à l'élément binaire. */
-const char *g_loaded_binary_get_name(const GLoadedBinary *, bool);
+/* Fournit le format de fichier reconnu dans le contenu binaire. */
+bool g_loaded_binary_attach_debug_info(GLoadedBinary *, GBinContent *);
 
 /* Fournit le format de fichier reconnu dans le contenu binaire. */
 GExeFormat *g_loaded_binary_get_format(const GLoadedBinary *);
diff --git a/src/analysis/content-int.h b/src/analysis/content-int.h
index 7734916..c5b1659 100644
--- a/src/analysis/content-int.h
+++ b/src/analysis/content-int.h
@@ -29,6 +29,12 @@
 
 
 
+/* Fournit le nom associé au contenu binaire. */
+typedef const char * (* describe_content_fc) (const GBinContent *, bool);
+
+/* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */
+typedef bool (* save_content_fc) (const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *);
+
 /* Fournit une empreinte unique (SHA256) pour les données. */
 typedef const gchar * (* get_checksum_fc) (GBinContent *);
 
@@ -62,6 +68,10 @@ struct _GBinContentIface
 {
     GTypeInterface base_iface;              /* A laisser en premier        */
 
+    describe_content_fc describe;           /* Fournit une description     */
+
+    save_content_fc save;                   /* Sauvegarde du contenu       */
+
     get_checksum_fc get_checksum;           /* Calcul de l'empreinte       */
 
     compute_size_fc compute_size;           /* Calcul de la taille totale  */
diff --git a/src/analysis/content.c b/src/analysis/content.c
index 5a4c899..d314d0c 100644
--- a/src/analysis/content.c
+++ b/src/analysis/content.c
@@ -24,7 +24,11 @@
 #include "content.h"
 
 
+#include <string.h>
+
+
 #include "content-int.h"
+#include "contents/file.h"
 
 
 
@@ -57,6 +61,88 @@ static void g_binary_content_default_init(GBinContentInterface *iface)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : context = contexte pour les recherches XPath.                *
+*                path    = chemin d'accès au noeud XML à lire.                *
+*                                                                             *
+*  Description : Charge en mémoire un contenu binaire à partir d'XML.         *
+*                                                                             *
+*  Retour      : Adresse de la représentation ou NULL en cas d'échec.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr context, const char *path)
+{
+    GBinContent *result;                    /* Contenu en place à renvoyer */
+    char *type;                             /* Type de binaire à charger   */
+
+    result = NULL;
+
+    type = get_node_prop_value(context, path, "type");
+
+    if (strcmp(type, "file") == 0)
+        result = g_file_content_new_from_xml(context, path);
+
+    free(type);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à consulter.                       *
+*                full    = précise s'il s'agit d'une version longue ou non.   *
+*                                                                             *
+*  Description : Fournit le nom associé au contenu binaire.                   *
+*                                                                             *
+*  Retour      : Nom de fichier avec chemin absolu au besoin.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_binary_content_describe(const GBinContent *content, bool full)
+{
+    GBinContentIface *iface;                /* Interface utilisée          */
+
+    iface = G_BIN_CONTENT_GET_IFACE(content);
+
+    return iface->describe(content, full);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à traiter.                         *
+*                xdoc    = structure XML en cours d'édition.                  *
+*                context = contexte à utiliser pour les recherches.           *
+*                path    = chemin d'accès réservé au binaire.                 *
+*                                                                             *
+*  Description : Ecrit une sauvegarde de contenu binaire dans un fichier XML. *
+*                                                                             *
+*  Retour      : true si l'opération a bien tourné, false sinon.              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_content_save(const GBinContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
+{
+    GBinContentIface *iface;                /* Interface utilisée          */
+
+    iface = G_BIN_CONTENT_GET_IFACE(content);
+
+    return iface->save(content, xdoc, context, path);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : content = contenu binaire à venir lire.                      *
 *                                                                             *
 *  Description : Fournit une empreinte unique (SHA256) pour les données.      *
diff --git a/src/analysis/content.h b/src/analysis/content.h
index d422dc6..0d991b9 100644
--- a/src/analysis/content.h
+++ b/src/analysis/content.h
@@ -31,6 +31,7 @@
 
 #include "../arch/vmpa.h"
 #include "../common/endianness.h"
+#include "../common/xml.h"
 
 
 
@@ -52,6 +53,15 @@ typedef struct _GBinContentIface GBinContentIface;
 /* Détermine le type d'une interface pour la lecture de binaire. */
 GType g_binary_content_get_type(void) G_GNUC_CONST;
 
+/* Charge en mémoire un contenu binaire à partir d'XML. */
+GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr, const char *);
+
+/* Fournit le nom associé au contenu binaire. */
+const char *g_binary_content_describe(const GBinContent *, bool);
+
+/* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */
+bool g_binary_content_save(const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *);
+
 /* Fournit une empreinte unique (SHA256) pour les données. */
 const gchar *g_binary_content_get_cheksum(GBinContent *);
 
diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c
index eb0d488..9f1c10c 100644
--- a/src/analysis/contents/file.c
+++ b/src/analysis/contents/file.c
@@ -27,12 +27,14 @@
 #include <assert.h>
 #include <fcntl.h>
 #include <malloc.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
 
 #include "../content-int.h"
+#include "../../common/extstr.h"
 
 
 
@@ -41,6 +43,8 @@ struct _GFileContent
 {
     GObject parent;                         /* A laisser en premier        */
 
+    char *filename;                         /* Fichier chargé en mémoire   */
+
     bin_t *data;                            /* Contenu binaire représenté  */
     mrange_t range;                         /* Couverture du binaire       */
 
@@ -72,6 +76,12 @@ static void g_file_content_dispose(GFileContent *);
 /* Procède à la libération totale de la mémoire. */
 static void g_file_content_finalize(GFileContent *);
 
+/* Fournit le nom associé au contenu binaire. */
+static const char *g_file_content_describe(const GFileContent *, bool);
+
+/* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */
+static bool g_file_content_save(const GFileContent *, xmlDocPtr, xmlXPathContextPtr, const char *);
+
 /* Fournit une empreinte unique (SHA256) pour les données. */
 static const gchar *g_file_content_get_checksum(GFileContent *);
 
@@ -166,6 +176,10 @@ static void g_file_content_init(GFileContent *content)
 
 static void g_file_content_interface_init(GBinContentInterface *iface)
 {
+    iface->describe = (describe_content_fc)g_file_content_describe;
+
+    iface->save = (save_content_fc)g_file_content_save;
+
     iface->get_checksum = (get_checksum_fc)g_file_content_get_checksum;
 
     iface->compute_size = (compute_size_fc)g_file_content_compute_size;
@@ -217,6 +231,8 @@ static void g_file_content_dispose(GFileContent *content)
 
 static void g_file_content_finalize(GFileContent *content)
 {
+    free(content->filename);
+
     if (content->data != NULL)
         free(content->data);
 
@@ -275,6 +291,8 @@ GBinContent *g_file_content_new(const char *filename)
 
     result = g_object_new(G_TYPE_FILE_CONTENT, NULL);
 
+    result->filename = strdup(filename);
+
     result->data = (bin_t *)malloc(info.st_size);
     memcpy(result->data, content, info.st_size);
 
@@ -295,6 +313,116 @@ GBinContent *g_file_content_new(const char *filename)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : context = contexte pour les recherches XPath.                *
+*                path    = chemin d'accès au noeud XML à lire.                *
+*                                                                             *
+*  Description : Charge en mémoire le contenu d'un fichier à partir d'XML.    *
+*                                                                             *
+*  Retour      : Adresse de la représentation ou NULL en cas d'échec.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr context, const char *path)
+{
+    GBinContent *result;                    /* Adresse à retourner         */
+    char *access;                           /* Chemin pour une sous-config.*/
+    char *filename;                         /* Chemin du binaire à charger */
+
+    result = NULL;
+
+    /* Chemin du fichier à retrouver */
+
+    access = strdup(path);
+    access = stradd(access, "/Filename");
+
+    filename = get_node_text_value(context, access);
+
+    free(access);
+
+    /* Chargement */
+
+    if (filename != NULL)
+    {
+        result = g_file_content_new(filename);
+        free(filename);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à consulter.                       *
+*                full    = précise s'il s'agit d'une version longue ou non.   *
+*                                                                             *
+*  Description : Fournit le nom associé au contenu binaire.                   *
+*                                                                             *
+*  Retour      : Nom de fichier avec chemin absolu au besoin.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const char *g_file_content_describe(const GFileContent *content, bool full)
+{
+    const char *result;                     /* Description à retourner     */
+
+    if (full)
+        result = content->filename;
+    else
+        result = strrchr(content->filename, G_DIR_SEPARATOR) + 1;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à traiter.                         *
+*                xdoc    = structure XML en cours d'édition.                  *
+*                context = contexte à utiliser pour les recherches.           *
+*                path    = chemin d'accès réservé au binaire.                 *
+*                                                                             *
+*  Description : Ecrit une sauvegarde de contenu binaire dans un fichier XML. *
+*                                                                             *
+*  Retour      : true si l'opération a bien tourné, false sinon.              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_file_content_save(const GFileContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    char *access;                           /* Chemin d'accès à un élément */
+
+    result = true;
+
+    /* Type */
+
+    result &= add_string_attribute_to_node(xdoc, context, path, "type", "file");
+
+    /* Nom du fichier associé */
+
+    access = strdup(path);
+    access = stradd(access, "/Filename");
+
+    result &= add_content_to_node(xdoc, context, access, content->filename);
+
+    free(access);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : content = contenu binaire à venir lire.                      *
 *                                                                             *
 *  Description : Fournit une empreinte unique (SHA256) pour les données.      *
diff --git a/src/analysis/contents/file.h b/src/analysis/contents/file.h
index 2e3cfef..0985f6b 100644
--- a/src/analysis/contents/file.h
+++ b/src/analysis/contents/file.h
@@ -53,6 +53,9 @@ GType g_file_content_get_type(void);
 /* Charge en mémoire le contenu d'un fichier donné. */
 GBinContent *g_file_content_new(const char *);
 
+/* Charge en mémoire le contenu d'un fichier à partir d'XML. */
+GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr, const char *);
+
 
 
 #endif  /* _ANALYSIS_CONTENTS_FILE_H */
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index cd16429..990ab0f 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -705,7 +705,7 @@ void disassemble_binary(GLoadedBinary *binary, GArchInstruction **instrs, GCodeB
     checksum = g_binary_content_get_cheksum(content);
     g_object_unref(G_OBJECT(content));
 
-    build_disass_prologue(*buffer, g_loaded_binary_get_name(binary, true), checksum);
+    build_disass_prologue(*buffer, g_binary_content_describe(content, true), checksum);
 
     disass = g_delayed_disassembly_new(binary, instrs, *buffer);
     g_signal_connect(disass, "work-completed", G_CALLBACK(ack), binary);
diff --git a/src/analysis/project.c b/src/analysis/project.c
index 5bb028f..db00f09 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -29,14 +29,20 @@
 #include <string.h>
 
 
+#include <i18n.h>
+
+
 #include "binaries/file.h"
 #include "../common/xml.h"
+#include "../core/formats.h"
 #include "../core/params.h"
 #include "../glibext/signal.h"
 #include "../gtkext/easygtk.h"
+#include "../glibext/delayed-int.h"
 #include "../gtkext/gtkblockview.h"
 #include "../gtkext/gtkgraphview.h"
 #include "../gtkext/gtksourceview.h"
+#include "../gui/panels/log.h"
 #include "../gui/panels/panel.h"
 
 
@@ -44,6 +50,14 @@
 /* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */
 
 
+/* Conservation d'un contenu chargé */
+typedef struct _loaded_content
+{
+    GBinContent *content;                   /* Contenu binaire en place    */
+    ProjectContentState state;              /* Renseigne le type de contenu*/
+
+} loaded_content;
+
 /* Conservation d'un binaire chargé */
 typedef struct _loaded_binary
 {
@@ -65,9 +79,13 @@ struct _GStudyProject
 
     char *filename;                         /* Lieu d'enregistrement       */
 
+    loaded_content *contents;               /* Contenus binaires chargés   */
+    size_t contents_count;                  /* Nombre de ces contenus      */
+    GMutex cnt_mutex;                       /* Modification de la liste    */
+
     loaded_binary **binaries;               /* Fichiers binaires associés  */
     size_t binaries_count;                  /* Nombre de ces fichiers      */
-    GMutex mutex;                           /* Modification de la liste    */
+    GMutex bin_mutex;                       /* Modification de la liste    */
 
 };
 
@@ -91,6 +109,49 @@ static void g_study_project_hide(const GStudyProject *);
 
 
 
+
+
+/* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */
+
+
+/* Ensembles binaires à désassembler (instance) */
+struct _GDelayedStudy
+{
+    GDelayedWork parent;                    /* A laisser en premier        */
+
+    GStudyProject *project;                 /* Projet de rattachement      */
+    GBinContent *content;                   /* Contenu binaire à traiter   */
+    ProjectContentState state;              /* Renseigne le type de contenu*/
+
+    bool only_preload;                      /* Enregistrement seulement ?  */
+
+};
+
+/* Ensembles binaires à désassembler (classe) */
+struct _GDelayedStudyClass
+{
+    GDelayedWorkClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des intégrations de binaires à étudier. */
+static void g_delayed_study_class_init(GDelayedStudyClass *);
+
+/* Initialise une intégration de binaire à étudier. */
+static void g_delayed_study_init(GDelayedStudy *);
+
+/* Supprime toutes les références externes. */
+static void g_delayed_study_dispose(GDelayedStudy *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_delayed_study_finalize(GDelayedStudy *);
+
+/* Prépare une intégration de binaire au projet courant. */
+static void g_delayed_study_process(GDelayedStudy *, GtkExtStatusBar *);
+
+
+
 /* ---------------------------------------------------------------------------------- */
 /*                           DEFINITION D'UN PROJET INTERNE                           */
 /* ---------------------------------------------------------------------------------- */
@@ -132,7 +193,9 @@ static void g_study_project_class_init(GStudyProjectClass *klass)
 
 static void g_study_project_init(GStudyProject *project)
 {
-    g_mutex_init(&project->mutex);
+    g_mutex_init(&project->cnt_mutex);
+
+    g_mutex_init(&project->bin_mutex);
 
 }
 
@@ -180,11 +243,17 @@ GStudyProject *g_study_project_open(GObject *ref, const char *filename)
     GStudyProject *result;                  /* Adresse à retourner         */
     xmlDocPtr xdoc;                         /* Structure XML chargée       */
     xmlXPathContextPtr context;             /* Contexte pour les XPath     */
+    unsigned int root_contents;             /* Quantité de contenus majeurs*/
+    GAsyncQueue *sema;                      /* Sémaphore taisant son nom   */
     xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */
     unsigned int i;                         /* Boucle de parcours          */
     size_t access_len;                      /* Taille d'un chemin interne  */
     char *access;                           /* Chemin pour une sous-config.*/
-    GLoadedBinary *binary;                 /* Représentation à intégrer   */
+    GBinContent *content;                   /* Contenu binaire retrouvé    */
+    long state;                             /* Etat de ce contenu binaire  */
+    bool status;                            /* Bilan d'une lecture         */
+    GDelayedStudy *dstudy;                  /* Etude complémentaire à mener*/
+    GLoadedBinary *binary;                  /* Représentation à intégrer   */
 
     if (!open_xml_file(filename, &xdoc, &context)) return NULL;
 
@@ -192,19 +261,78 @@ GStudyProject *g_study_project_open(GObject *ref, const char *filename)
 
     result->filename = strdup(filename);
 
-    /* Chargement des éléments binaires attachés */
+    /* Préparations aux traitements parallèles */
+
+    root_contents = 0;
+
+    sema = g_async_queue_new();
+
+    void ack_content_processing(GDelayedStudy *dstudy, GAsyncQueue *aqueue)
+    {
+        g_async_queue_push(aqueue, GINT_TO_POINTER(1));
+    }
+
+    /* Chargement des contenus binaires attachés */
+
+    xobject = get_node_xpath_object(context, "/ChrysalideProject/Contents/Content");
+
+    for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
+    {
+        access_len = strlen("/ChrysalideProject/Contents/Content[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
+
+        access = calloc(access_len, sizeof(char));
+        snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%u]", i + 1);
+
+        content = g_binary_content_new_from_xml(context, access);
+        status = get_node_prop_long_value(context, access, "state", &state);
+
+        free(access);
+
+        if (!status)
+        {
+            log_variadic_message(LMT_PROCESS, _("bad state for content '%s' ; skipping..."),
+                                 g_binary_content_describe(content, true));
+            continue;
+        }
+
+        /* Le contenu peut être un conteneur ? */
+        if (state == PCS_ROOT)
+        {
+            dstudy = g_delayed_study_new(result, content, state);
+            g_signal_connect(dstudy, "work-completed", G_CALLBACK(ack_content_processing), sema);
+
+            g_delayed_study_preload_only(dstudy);
+
+            root_contents++;
+
+            study_new_content(dstudy);
+
+        }
+
+    }
+
+    if(xobject != NULL)
+        xmlXPathFreeObject(xobject);
+
+    /* Attente pour la réception de contenus supplémentaires éventuels */
+
+    for (i = 0; i < root_contents; i++)
+        g_async_queue_pop(sema);
+
+    g_async_queue_unref(sema);
 
-    xobject = get_node_xpath_object(context, "/OpenIDAProject/Binaries/Binary");
+    /* Chargement des binaires analysés */
+
+    xobject = get_node_xpath_object(context, "/ChrysalideProject/Binaries/Binary");
 
     for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
     {
-        access_len = strlen("/OpenIDAProject/Binaries/Binary[position()=")
-            + strlen("4294967295" /* UINT_MAX */) + strlen("]") + 1;
+        access_len = strlen("/ChrysalideProject/Binaries/Binary[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
 
         access = calloc(access_len, sizeof(char));
-        snprintf(access, access_len, "/OpenIDAProject/Binaries/Binary[position()=%u]", i + 1);
+        snprintf(access, access_len, "/ChrysalideProject/Binaries/Binary[position()=%u]", i + 1);
 
-        binary = g_loaded_binary_new_from_xml(context, access);
+        binary = g_loaded_binary_new_from_xml(context, access, result);
 
         free(access);
 
@@ -254,17 +382,36 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
 
     result = create_new_xml_file(&xdoc, &context);
 
-    result &= (ensure_node_exist(xdoc, context, "/OpenIDAProject") != NULL);
+    result &= (ensure_node_exist(xdoc, context, "/ChrysalideProject") != NULL);
+
+    /* Enregistrement des contenus binaires attachés */
 
-    /* Enregistrement des éléments binaires attachés */
+    for (i = 0; i < project->contents_count && result; i++)
+    {
+        if (!project->contents[i].state == PCS_INTERNAL) continue;
+
+        access_len = strlen("/ChrysalideProject/Contents/Content[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
+
+        access = calloc(access_len, sizeof(char));
+        snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%zu]", i + 1);
+
+        result = g_binary_content_save(project->contents[i].content, xdoc, context, access);
+
+        if (result)
+            result = add_long_attribute_to_node(xdoc, context, access, "state", project->contents[i].state);
+
+        free(access);
+
+    }
+
+    /* Enregistrement des binaires analysés */
 
     for (i = 0; i < project->binaries_count && result; i++)
     {
-        access_len = strlen("/OpenIDAProject/Binaries/Binary[position()=")
-            + strlen("4294967295" /* UINT_MAX */) + strlen("]") + 1;
+        access_len = strlen("/ChrysalideProject/Binaries/Binary[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
 
         access = calloc(access_len, sizeof(char));
-        snprintf(access, access_len, "/OpenIDAProject/Binaries/Binary[position()=%zu]", i + 1);
+        snprintf(access, access_len, "/ChrysalideProject/Binaries/Binary[position()=%zu]", i + 1);
 
         result = g_loaded_binary_save(project->binaries[i]->binary, xdoc, context, access);
 
@@ -311,6 +458,88 @@ const char *g_study_project_get_filename(const GStudyProject *project)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : project = projet dont le contenu est à compléter.            *
+*                content = contenu binaire à mémoriser pour le projet.        *
+*                state   = état du contenu à conserver.                       *
+*                                                                             *
+*  Description : Assure l'intégration d'un contenu binaire dans un projet.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_study_project_add_binary_content(GStudyProject *project, GBinContent *content, ProjectContentState state)
+{
+    loaded_content *new;                    /* Nouveau contenu à définir   */
+
+    g_mutex_lock(&project->cnt_mutex);
+
+    project->contents = (loaded_content *)realloc(project->contents,
+                                                  ++project->contents_count * sizeof(loaded_content));
+
+    new = &project->contents[project->contents_count - 1];
+
+    g_object_ref(G_OBJECT(content));
+
+    new->content = content;
+    new->state = state;
+
+    g_mutex_unlock(&project->cnt_mutex);
+
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = projet dont le contenu est à compléter.            *
+*                hash    = empreinte du contenu à retrouver.                  *
+*                                                                             *
+*  Description : Recherche un contenu binaire du projet selon son empreinte.  *
+*                                                                             *
+*  Retour      : Contenu avec propriété transférée ou NULL en cas d'échec.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *project, const char *hash)
+{
+    GBinContent *result;                    /* Trouvaille à retourner      */
+    size_t i;                               /* Boucle de parcours          */
+    GBinContent *iter;                      /* Contenu binaire analysé     */
+    const gchar *other;                     /* Autre empreinte à comparer  */
+
+    result = NULL;
+
+    g_mutex_lock(&project->cnt_mutex);
+
+    for (i = 0; i < project->contents_count && result == NULL; i++)
+    {
+        iter = project->contents[i].content;
+        other = g_binary_content_get_cheksum(iter);
+
+        if (strcmp(hash, other) == 0)
+        {
+            g_object_ref(G_OBJECT(iter));
+            result = iter;
+        }
+
+    }
+
+    g_mutex_unlock(&project->cnt_mutex);
+
+    return result;
+
+}
+
+
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : binary  = élément binaire tout juste désassemblé.            *
 *                project = projet dont le contenu est à compléter.            *
 *                                                                             *
@@ -431,7 +660,7 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina
 
     /* Enregistrement dans le projet */
 
-    g_mutex_lock(&project->mutex);
+    g_mutex_lock(&project->bin_mutex);
 
     project->binaries = (loaded_binary **)realloc(project->binaries,
                                                   ++project->binaries_count * sizeof(loaded_binary *));
@@ -440,7 +669,7 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina
 
     project->binaries[result] = loaded;
 
-    g_mutex_unlock(&project->mutex);
+    g_mutex_unlock(&project->bin_mutex);
 
     update_project_area(project);
 
@@ -714,3 +943,272 @@ void push_project_into_recent_list(const GStudyProject *project)
     g_generic_config_set_value(get_main_configuration(), MPK_LAST_PROJECT, project->filename);
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         AMORCE POUR CHARGEMENT DE CONTENUS                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches de préparations d'étude. */
+G_DEFINE_TYPE(GDelayedStudy, g_delayed_study, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des intégrations de binaires à étudier. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_study_class_init(GDelayedStudyClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_study_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_delayed_study_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dstudy = instance à initialiser.                             *
+*                                                                             *
+*  Description : Initialise une intégration de binaire à étudier.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_study_init(GDelayedStudy *dstudy)
+{
+    G_DELAYED_WORK(dstudy)->run = (run_task_fc)g_delayed_study_process;
+
+    dstudy->only_preload = false;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_study_dispose(GDelayedStudy *dstudy)
+{
+    g_object_unref(G_OBJECT(dstudy->project));
+    g_object_unref(G_OBJECT(dstudy->content));
+
+    G_OBJECT_CLASS(g_delayed_study_parent_class)->dispose(G_OBJECT(dstudy));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_study_finalize(GDelayedStudy *dstudy)
+{
+    G_OBJECT_CLASS(g_delayed_study_parent_class)->finalize(G_OBJECT(dstudy));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = projet dont le contenu est à compléter.            *
+*                content = contenu binaire chargé à analyser.                 *
+*                state   = état du contenu à conserver.                       *
+*                                                                             *
+*  Description : Crée une tâche d'intégration de contenu binaire.             *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : L'appelant perd la propriété du contenu.                     *
+*                                                                             *
+******************************************************************************/
+
+GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content, ProjectContentState state)
+{
+    GDelayedStudy *result;            /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_DELAYED_STUDY, NULL);
+
+    g_object_ref(G_OBJECT(project));
+    result->project = project;
+
+    g_object_ref(G_OBJECT(content));
+    result->content = content;
+
+    result->state = state;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dstudy    = intégration à mener.                             *
+*                statusbar = barre de statut à tenir informée.                *
+*                                                                             *
+*  Description : Prépare une intégration de binaire au projet courant.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_study_process(GDelayedStudy *dstudy, GtkExtStatusBar *statusbar)
+{
+    FormatMatchStatus status;               /* Statut d'une reconnaissance */
+    char *target;                           /* Sous-traitance requise      */
+    GLoadedBinary *binary;                  /* Représentation chargée      */
+
+    status = find_matching_format(dstudy->content, NULL, &target);
+
+    switch (status)
+    {
+        case FMS_MATCHED:
+
+            if (dstudy->only_preload)
+                g_study_project_add_binary_content(dstudy->project, dstudy->content, dstudy->state);
+
+            else
+            {
+                binary = g_loaded_binary_new(dstudy->content);
+
+                if (binary != NULL)
+                {
+                    g_study_project_add_binary_content(dstudy->project, dstudy->content, dstudy->state);
+
+                    g_signal_connect_to_main(binary, "disassembly-done",
+                                             G_CALLBACK(g_study_project_add_loaded_binary),
+                                             dstudy->project, g_cclosure_marshal_VOID__VOID);
+
+                    g_loaded_binary_analyse(binary);
+
+                }
+
+            }
+
+            break;
+
+        case FMS_FORWARDED:
+            /**
+             * L'émetteur de ce type de réponse a pour charge de
+             * reprogrammer lui même l'analyse de nouveaux contenus.
+             */
+            log_variadic_message(LMT_PROCESS, _("binary '%s' contains other binaries..."),
+                                 g_binary_content_describe(dstudy->content, true));
+
+            if (dstudy->state == PCS_ROOT)
+                g_study_project_add_binary_content(dstudy->project, dstudy->content, PCS_ROOT);
+
+            break;
+
+        default:
+            /**
+             * Les jeux sont faits pour le contenu binaire courant.
+             */
+            log_variadic_message(LMT_PROCESS, _("Unknown binary format for '%s'..."),
+                                 g_binary_content_describe(dstudy->content, true));
+            break;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dstudy = tâche d'analyse de contenu pour projet à mener.     *
+*                                                                             *
+*  Description : Limite l'étude et l'intégration d'un contenu binaire.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_delayed_study_preload_only(GDelayedStudy *dstudy)
+{
+    dstudy->only_preload = true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire chargé à analyser.                 *
+*                state   = état du contenu à conserver.                       *
+*                                                                             *
+*  Description : Programme l'étude et l'intégration d'un contenu binaire.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void qck_study_new_content(GBinContent *content, ProjectContentState state)
+{
+    GDelayedStudy *dstudy;                  /* Etude à conduire            */
+
+    dstudy = g_delayed_study_new(get_current_project(), content, state);
+
+    study_new_content(dstudy);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire chargé à analyser.                 *
+*                state   = état du contenu à conserver.                       *
+*                                                                             *
+*  Description : Programme l'étude et l'intégration d'un contenu binaire.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void study_new_content(GDelayedStudy *dstudy)
+{
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+
+    queue = get_work_queue();
+    g_work_queue_schedule_work(queue, G_DELAYED_WORK(dstudy));
+
+}
diff --git a/src/analysis/project.h b/src/analysis/project.h
index 05e7f12..5f5b38c 100644
--- a/src/analysis/project.h
+++ b/src/analysis/project.h
@@ -66,6 +66,23 @@ bool g_study_project_save(GStudyProject *, const char *);
 /* Indique le chemin du fichier destiné à la sauvegarde. */
 const char *g_study_project_get_filename(const GStudyProject *);
 
+/* Etat d'un contenu binaire du projet */
+typedef enum _ProjectContentState
+{
+    PCS_ROOT,                               /* Contenu principal           */
+    PCS_INTERNAL,                           /* Contenu dérivé              */
+    PCS_ATTACHED,                           /* Contenu complémentaire      */
+
+    PCS_COUNT
+
+} ProjectContentState;
+
+/* Assure l'intégration d'un contenu binaire dans un projet. */
+void g_study_project_add_binary_content(GStudyProject *, GBinContent *, ProjectContentState);
+
+/* Recherche un contenu binaire du projet selon son empreinte. */
+GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *, const char *);
+
 /* Assure l'intégration d'un élément binaire dans un projet. */
 void g_study_project_add_loaded_binary(GLoadedBinary *, GStudyProject *);
 
@@ -103,4 +120,39 @@ void push_project_into_recent_list(const GStudyProject *);
 
 
 
+/* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */
+
+
+#define G_TYPE_DELAYED_STUDY               g_delayed_study_get_type()
+#define G_DELAYED_STUDY(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_study_get_type(), GDelayedStudy))
+#define G_IS_DELAYED_STUDY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_study_get_type()))
+#define G_DELAYED_STUDY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_STUDY, GDelayedStudyClass))
+#define G_IS_DELAYED_STUDY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_STUDY))
+#define G_DELAYED_STUDY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_STUDY, GDelayedStudyClass))
+
+
+/* Ensembles binaires à désassembler (instance) */
+typedef struct _GDelayedStudy GDelayedStudy;
+
+/* Ensembles binaires à désassembler (classe) */
+typedef struct _GDelayedStudyClass GDelayedStudyClass;
+
+
+/* Indique le type défini pour les tâches de préparations d'étude. */
+GType g_delayed_study_get_type(void);
+
+/* Crée une tâche d'intégration de contenu binaire. */
+GDelayedStudy *g_delayed_study_new(GStudyProject *, GBinContent *, ProjectContentState);
+
+/* Limite l'étude et l'intégration d'un contenu binaire. */
+void g_delayed_study_preload_only(GDelayedStudy *);
+
+/* Programme l'étude et l'intégration d'un contenu binaire. */
+void qck_study_new_content(GBinContent *, ProjectContentState);
+
+/* Programme l'étude et l'intégration d'un contenu binaire. */
+void study_new_content(GDelayedStudy *);
+
+
+
 #endif  /* _PROJECT_H */
diff --git a/src/common/xml.c b/src/common/xml.c
index 1e2871b..a9c65b5 100644
--- a/src/common/xml.c
+++ b/src/common/xml.c
@@ -27,6 +27,7 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 
@@ -322,6 +323,43 @@ char *qck_get_node_prop_value(xmlNodePtr node, const char *name)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : node = noeud dont une propriété est à lire.                  *
+*                name = nom de la propriété à lire.                           *
+*                out  = valeur entière lue depuis le contenu textuel. [OUT]   *
+*                                                                             *
+*  Description : Obtient la valeur entière d'une propriété d'un élément.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool qck_get_node_prop_long_value(xmlNodePtr node, const char *name, long *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    char *value;                            /* Valeur brute lue            */
+
+    value = qck_get_node_prop_value(node, name);
+
+    if (value)
+    {
+        result = true;
+
+        *out = strtol(value, NULL, 10);
+        free(value);
+
+    }
+    else
+        result = false;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : xpathCtx = contexte à utiliser pour les recherches.          *
 *                path     = chemin d'accès au noeud à traiter.                *
 *                name     = nom de la propriété à lire.                       *
@@ -356,6 +394,41 @@ char *get_node_prop_value(xmlXPathContextPtr xpathCtx, const char *path, const c
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : xpathCtx = contexte à utiliser pour les recherches.          *
+*                path     = chemin d'accès au noeud à traiter.                *
+*                name     = nom de la propriété à lire.                       *
+*                out      = valeur entière obtenue via contenu textuel. [OUT] *
+*                                                                             *
+*  Description : Obtient la valeur entière d'une propriété d'un élément.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool get_node_prop_long_value(xmlXPathContextPtr xpathCtx, const char *path, const char *name, long *out)
+{
+    bool result;                            /* Bilan à retourner           */
+    xmlXPathObjectPtr xpathObj;             /* Point de départ XML         */
+
+    result = NULL;
+
+    xpathObj = get_node_xpath_object(xpathCtx, path);
+    if (xpathObj == NULL) return NULL;
+
+    if (xpathObj->nodesetval->nodeNr > 0)
+        result = qck_get_node_prop_long_value(xpathObj->nodesetval->nodeTab[0], name, out);
+
+    xmlXPathFreeObject(xpathObj);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : node = noeud de texte avec un lien avec le document XML.     *
 *                                                                             *
 *  Description : Construit un chemin d'accès complet selon le fichier XML.    *
@@ -965,16 +1038,13 @@ bool _add_string_attribute_to_node(xmlNodePtr node, const char *name, const char
 bool add_string_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *name, const char *value)
 {
     xmlNodePtr node;                        /* Noeud à modifier            */
-    xmlAttrPtr attrib;                      /* Attribut créé et en place   */
 
     if (value == NULL) return true;
 
     node = ensure_node_exist(xdoc, context, path);
     if (node == NULL) return false;
 
-    attrib = xmlSetProp(node, BAD_CAST name, BAD_CAST value);
-
-    return (attrib != NULL);
+    return _add_string_attribute_to_node(node, name, value);
 
 }
 
@@ -993,7 +1063,7 @@ bool add_string_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, co
 *                                                                             *
 ******************************************************************************/
 
-bool add_long_attribute_to_node(xmlNodePtr node, const char *name, long value)
+bool _add_long_attribute_to_node(xmlNodePtr node, const char *name, long value)
 {
     char tmp[11/*strlen("2147483647")*/];   /* Stockage temporaire         */
 
@@ -1002,3 +1072,31 @@ bool add_long_attribute_to_node(xmlNodePtr node, const char *name, long value)
     return _add_string_attribute_to_node(node, name, tmp);
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : xdoc    = structure XML chargée.                             *
+*                context = contexte à utiliser pour les recherches.           *
+*                path    = chemin d'accès au noeud visé.                      *
+*                name    = nom de la propriété à créer.                       *
+*                value   = valeur numérique à placer.                         *
+*                                                                             *
+*  Description : Ajoute une propriété à un noeud existant donné.              *
+*                                                                             *
+*  Retour      : true en cas de succès, false sinon.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool add_long_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *name, long value)
+{
+    xmlNodePtr node;                        /* Noeud à modifier            */
+
+    node = ensure_node_exist(xdoc, context, path);
+    if (node == NULL) return false;
+
+    return _add_long_attribute_to_node(node, name, value);
+
+}
diff --git a/src/common/xml.h b/src/common/xml.h
index 8cb8c0e..60891f7 100644
--- a/src/common/xml.h
+++ b/src/common/xml.h
@@ -68,9 +68,15 @@ char *get_node_text_value(xmlXPathContextPtr, const char *);
 /* Obtient la valeur d'une propriété d'un élément. */
 char *qck_get_node_prop_value(xmlNodePtr, const char *);
 
+/* Obtient la valeur entière d'une propriété d'un élément. */
+bool qck_get_node_prop_long_value(xmlNodePtr, const char *, long *);
+
 /* Obtient la valeur d'une propriété d'un élément. */
 char *get_node_prop_value(xmlXPathContextPtr, const char *, const char *);
 
+/* Obtient la valeur entière d'une propriété d'un élément. */
+bool get_node_prop_long_value(xmlXPathContextPtr, const char *, const char *, long *);
+
 /* Construit un chemin d'accès complet selon le fichier XML. */
 char *qck_build_filename_with_doc_url(xmlNodePtr);
 
@@ -133,7 +139,10 @@ bool _add_string_attribute_to_node(xmlNodePtr, const char *, const char *);
 bool add_string_attribute_to_node(xmlDocPtr, xmlXPathContextPtr, const char *, const char *, const char *);
 
 /* Ajoute une propriété à un noeud existant donné. */
-bool add_long_attribute_to_node(xmlNodePtr, const char *, long);
+bool _add_long_attribute_to_node(xmlNodePtr, const char *, long);
+
+/* Ajoute une propriété à un noeud existant donné. */
+bool add_long_attribute_to_node(xmlDocPtr, xmlXPathContextPtr, const char *, const char *, long);
 
 
 
diff --git a/src/core/formats.c b/src/core/formats.c
index 891fc12..1326fc4 100644
--- a/src/core/formats.c
+++ b/src/core/formats.c
@@ -41,6 +41,7 @@
 typedef struct _format_matcher_t
 {
     format_match_fc func;                   /* Recherche de correspondance */
+    void *data;                             /* Eventuelle donnée à y lier  */
 
 } format_matcher_t;
 
@@ -76,6 +77,7 @@ static format_loader_t *find_format_by_key(const char *);
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : func = procédure de détection à utiliser.                    *
+*                data = éventuelle donnée à associer aux opérations.          *
 *                                                                             *
 *  Description : Enregistre un détection de format(s) binaire(s).             *
 *                                                                             *
@@ -85,18 +87,24 @@ static format_loader_t *find_format_by_key(const char *);
 *                                                                             *
 ******************************************************************************/
 
-bool register_format_matcher(format_match_fc func)
+bool register_format_matcher(format_match_fc func, void *data)
 {
     bool result;                            /* Bilan à retourner           */
     size_t i;                               /* Boucle de parcours          */
+    const format_matcher_t *cur;            /* Elément parcouru et analysé */
     format_matcher_t *new;                  /* Nouvel élément à définir    */
 
     g_rw_lock_writer_lock(&_formats_lock);
 
     for (i = 0; i < _formats_matchers_count; i++)
-        if (_formats_matchers[i].func == func)
+    {
+        cur = &_formats_matchers[i];
+
+        if (cur->func == func && cur->data == data)
             break;
 
+    }
+
     result = (i == _formats_matchers_count);
 
     if (result)
@@ -107,6 +115,7 @@ bool register_format_matcher(format_match_fc func)
         new = &_formats_matchers[_formats_matchers_count - 1];
 
         new->func = func;
+        new->data = data;
 
     }
 
@@ -186,9 +195,9 @@ bool load_hard_coded_formats_definitions(void)
 
     /* Détections */
 
-    result &= register_format_matcher(dwarf_is_matching);
+    result &= register_format_matcher(dwarf_is_matching, NULL);
 
-    result &= register_format_matcher(elf_is_matching);
+    result &= register_format_matcher(elf_is_matching, NULL);
 
     /* Chargements */
 
@@ -315,27 +324,32 @@ const char *get_binary_format_name(const char *key)
 *                                                                             *
 *  Paramètres  : content = contenu binaire à parcourir.                       *
 *                parent  = éventuel format exécutable déjà chargé.            *
+*                key     = identifiant de format trouvé ou NULL. [OUT]        *
 *                                                                             *
 *  Description : Identifie un format binaire par son contenu.                 *
 *                                                                             *
-*  Retour      : Identifiant du format binaire trouvé ou NULL si échec.       *
+*  Retour      : Conclusion de haut niveau sur la reconnaissance effectuée.   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const char *find_matching_format(GBinContent *content, GExeFormat *parent)
+FormatMatchStatus find_matching_format(GBinContent *content, GExeFormat *parent, char **key)
 {
-    const char *result;                     /* Identifiant à retourner     */
+    FormatMatchStatus result;               /* Bilan à retourner           */
     size_t i;                               /* Boucle de parcours          */
+    const format_matcher_t *cur;            /* Elément parcouru et analysé */
 
-    result = NULL;
+    result = FMS_UNKNOWN;
 
     g_rw_lock_reader_lock(&_formats_lock);
 
-    for (i = 0; i < _formats_matchers_count && result == NULL; i++)
+    for (i = 0; i < _formats_matchers_count && result == FMS_UNKNOWN; i++)
     {
-        result = _formats_matchers[i].func(content, parent);
+        cur = &_formats_matchers[i];
+
+        result = cur->func(content, parent, cur->data, key);
+
     }
 
     g_rw_lock_reader_unlock(&_formats_lock);
diff --git a/src/core/formats.h b/src/core/formats.h
index 8857217..76b57d0 100644
--- a/src/core/formats.h
+++ b/src/core/formats.h
@@ -34,15 +34,27 @@
 
 
 
+/* Conclusion d'une opération de reconnaissance */
+typedef enum _FormatMatchStatus
+{
+    FMS_MATCHED,                            /* Correspondance établie      */
+    FMS_FORWARDED,                          /* Sous-formats détectés       */
+    FMS_UNKNOWN,                            /* Aucun format reconnu        */
+
+    FMS_COUNT
+
+} FormatMatchStatus;
+
+
 /* Indication à propos du support d'un format */
-typedef const char * (* format_match_fc) (GBinContent *, GExeFormat *);
+typedef FormatMatchStatus (* format_match_fc) (GBinContent *, GExeFormat *, void *, char **);
 
 /* Méthode de chargement d'un format */
 typedef GBinFormat * (* format_load_fc) (GBinContent *, GExeFormat *);
 
 
 /* Enregistre un détection de format(s) binaire(s). */
-bool register_format_matcher(format_match_fc);
+bool register_format_matcher(format_match_fc, void *);
 
 /* Enregistre un format de contenu binaire donné. */
 bool register_format_loader(const char *, const char *, format_load_fc);
@@ -57,11 +69,11 @@ void unload_formats_definitions(void);
 const char *get_binary_format_name(const char *);
 
 /* Identifie un format binaire par son contenu. */
-const char *find_matching_format(GBinContent *, GExeFormat *);
+FormatMatchStatus find_matching_format(GBinContent *, GExeFormat *, char **);
 
 /* Charge le format binaire correspondant à un type. */
 GBinFormat *load_new_named_format(const char *, GBinContent *, GExeFormat *);
 
 
 
-#endif  /* _ANALYSIS_DB_COLLECTION_H */
+#endif  /* _CORE_FORMATS_H */
diff --git a/src/format/dwarf/dwarf.c b/src/format/dwarf/dwarf.c
index db8335b..519aa49 100644
--- a/src/format/dwarf/dwarf.c
+++ b/src/format/dwarf/dwarf.c
@@ -47,18 +47,20 @@ static void g_dwarf_format_finalize(GDwarfFormat *);
 *                                                                             *
 *  Paramètres  : content = contenu binaire à parcourir.                       *
 *                parent  = éventuel format exécutable déjà chargé.            *
+*                unused  = adresse non utilisée ici.                          *
+*                key     = identifiant de format trouvé ou NULL. [OUT]        *
 *                                                                             *
 *  Description : Indique si le format peut être pris en charge ici.           *
 *                                                                             *
-*  Retour      : Désignation du format reconnu ou NULL si aucun.              *
+*  Retour      : Conclusion de haut niveau sur la reconnaissance effectuée.   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const char *dwarf_is_matching(GBinContent *content, GExeFormat *parent)
+FormatMatchStatus dwarf_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key)
 {
-    const char *result;                     /* Format détecté à renvoyer   */
+    FormatMatchStatus result;               /* Bilan à renvoyer            */
     size_t i;                               /* Boucle de parcours          */
     mrange_t range;                         /* Couverture d'une section    */
     dw_section_header header;               /* En-tête DWARF de section    */
@@ -114,10 +116,10 @@ const char *dwarf_is_matching(GBinContent *content, GExeFormat *parent)
         0   /* .debug_types */
     };
 
-    result = NULL;
+    result = FMS_UNKNOWN;
 
     if (parent == NULL)
-        return NULL;
+        return FMS_UNKNOWN;
 
     /* Lecture des indices présents */
 
@@ -159,23 +161,32 @@ const char *dwarf_is_matching(GBinContent *content, GExeFormat *parent)
     found = check_dwarf_version(dwarf_v4_versions, current_versions, ARRAY_SIZE(section_names));
 
     if (found)
-        result = "dwarf_v4";
+    {
+        result = FMS_MATCHED;
+        *key = strdup("dwarf_v4");
+    }
 
-    if (result == NULL)
+    if (result == FMS_UNKNOWN)
     {
         found = check_dwarf_version(dwarf_v3_versions, current_versions, ARRAY_SIZE(section_names));
 
         if (found)
-            result = "dwarf_v3";
+        {
+            result = FMS_MATCHED;
+            *key = strdup("dwarf_v3");
+        }
 
     }
 
-    if (result == NULL)
+    if (result == FMS_UNKNOWN)
     {
         found = check_dwarf_version(dwarf_v2_versions, current_versions, ARRAY_SIZE(section_names));
 
         if (found)
-            result = "dwarf_v2";
+        {
+            result = FMS_MATCHED;
+            *key = strdup("dwarf_v2");
+        }
 
     }
 
diff --git a/src/format/dwarf/dwarf.h b/src/format/dwarf/dwarf.h
index a5e988b..da5b70a 100644
--- a/src/format/dwarf/dwarf.h
+++ b/src/format/dwarf/dwarf.h
@@ -25,7 +25,7 @@
 #define _FORMAT_DWARF_DWARF_H
 
 
-#include "../executable.h"
+#include "../../core/formats.h"
 
 
 
@@ -45,7 +45,7 @@ typedef struct _GDwarfFormatClass GDwarfFormatClass;
 
 
 /* Indique si le format peut être pris en charge ici. */
-const char *dwarf_is_matching(GBinContent *, GExeFormat *);
+FormatMatchStatus dwarf_is_matching(GBinContent *, GExeFormat *, void *, char **);
 
 /* Indique le type défini pour un format de débogage DWARF. */
 GType g_dwarf_format_get_type(void);
diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c
index 5c81b2f..50df077 100644
--- a/src/format/elf/elf.c
+++ b/src/format/elf/elf.c
@@ -84,18 +84,20 @@ bool g_elf_format_get_section_range_by_name(const GElfFormat *, const char *, mr
 *                                                                             *
 *  Paramètres  : content = contenu binaire à parcourir.                       *
 *                parent  = éventuel format exécutable déjà chargé.            *
+*                unused  = adresse non utilisée ici.                          *
+*                key     = identifiant de format trouvé ou NULL. [OUT]        *
 *                                                                             *
 *  Description : Indique si le format peut être pris en charge ici.           *
 *                                                                             *
-*  Retour      : Désignation du format reconnu ou NULL si aucun.              *
+*  Retour      : Conclusion de haut niveau sur la reconnaissance effectuée.   *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const char *elf_is_matching(GBinContent *content, GExeFormat *parent)
+FormatMatchStatus elf_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key)
 {
-    const char *result;                     /* Format détecté à renvoyer   */
+    FormatMatchStatus result;               /* Bilan à renvoyer            */
     vmpa2t addr;                            /* Tête de lecture initiale    */
     bool status;                            /* Bilan des accès mémoire     */
     char magic[4];                          /* Idenfiant standard          */
@@ -106,7 +108,13 @@ const char *elf_is_matching(GBinContent *content, GExeFormat *parent)
 
     status &= (memcmp(magic, "\x7f\x45\x4c\x46" /* .ELF */, 4) == 0);
 
-    result = status ? "elf" : NULL;
+    if (status)
+    {
+        result = FMS_MATCHED;
+        *key = strdup("elf");
+    }
+    else
+        result = FMS_UNKNOWN;
 
     return result;
 
diff --git a/src/format/elf/elf.h b/src/format/elf/elf.h
index 8e9a2cc..a557927 100644
--- a/src/format/elf/elf.h
+++ b/src/format/elf/elf.h
@@ -31,8 +31,7 @@
 
 
 #include "elf_def.h"
-#include "../executable.h"
-#include "../format.h"
+#include "../../core/formats.h"
 
 
 
@@ -51,7 +50,7 @@ typedef struct _GElfFormatClass GElfFormatClass;
 
 
 /* Indique si le format peut être pris en charge ici. */
-const char *elf_is_matching(GBinContent *, GExeFormat *);
+FormatMatchStatus elf_is_matching(GBinContent *, GExeFormat *, void *, char **);
 
 /* Indique le type défini pour un format d'exécutable ELF. */
 GType g_elf_format_get_type(void);
diff --git a/src/format/executable-int.h b/src/format/executable-int.h
index 704466e..f5a25b5 100644
--- a/src/format/executable-int.h
+++ b/src/format/executable-int.h
@@ -62,6 +62,9 @@ struct _GExeFormat
 {
     GBinFormat parent;                      /* A laisser en premier        */
 
+    GDbgFormat **debugs;                    /* Informations de débogage    */
+    size_t debugs_count;                    /* Nombre de ces informations  */
+
     get_target_machine_fc get_machine;      /* Architecture ciblée         */
     refine_portions_fc refine_portions;     /* Décrit les portions binaires*/
 
diff --git a/src/format/executable.c b/src/format/executable.c
index aae182a..5ff773c 100644
--- a/src/format/executable.c
+++ b/src/format/executable.c
@@ -84,6 +84,84 @@ static void g_executable_format_init(GExeFormat *format)
 
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à compléter.                  *
+*                info   = informations de débogage à lier.                    *
+*                                                                             *
+*  Description : Rajoute des informations de débogage à un exécutable.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_exe_format_add_debug_info(GExeFormat *format, GDbgFormat *info)
+{
+    /* Ajout dans la liste */
+
+    format->debugs = (GDbgFormat **)realloc(format->debugs,
+                                            ++format->debugs_count * sizeof(GDbgFormat *));
+
+    format->debugs[format->debugs_count - 1] = info;
+
+    /* Intégration des symboles */
+
+    /* TODO */
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                                                                             *
+*  Description : Compte le nombre de formats de débogage liés à l'exécutable. *
+*                                                                             *
+*  Retour      : Nombre de formats de débogage attachés.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+size_t g_exe_format_count_debug_info(const GExeFormat *format)
+{
+    return format->debugs_count;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                index  = indice des informations à transmettre.              *
+*                                                                             *
+*  Description : Fournit un format de débogage attaché à l'exécutable.        *
+*                                                                             *
+*  Retour      : Informations de débogage attachées.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index)
+{
+    GDbgFormat *result;                     /* Format à retourner          */
+
+    if (index >= format->debugs_count)
+        result = NULL;
+
+    else
+    {
+        result = format->debugs[index];
+        g_object_ref(G_OBJECT(result));
+    }
+
+    return result;
+
+}
+
 
 
 
diff --git a/src/format/executable.h b/src/format/executable.h
index 45c736b..48a8139 100644
--- a/src/format/executable.h
+++ b/src/format/executable.h
@@ -28,6 +28,7 @@
 #include <glib-object.h>
 
 
+#include "debuggable.h"
 #include "../glibext/gbinportion.h"
 
 
@@ -52,6 +53,14 @@ typedef struct _GExeFormatClass GExeFormatClass;
 GType g_executable_format_get_type(void);
 
 
+/* Rajoute des informations de débogage à un exécutable. */
+void g_exe_format_add_debug_info(GExeFormat *, GDbgFormat *);
+
+/* Compte le nombre de formats de débogage liés à l'exécutable. */
+size_t g_exe_format_count_debug_info(const GExeFormat *);
+
+/* Fournit un format de débogage attaché à l'exécutable. */
+GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *, size_t);
 
 
 /* Indique le type d'architecture visée par le format. */
diff --git a/src/gui/menus/project.c b/src/gui/menus/project.c
index a68b137..6b7e6b4 100644
--- a/src/gui/menus/project.c
+++ b/src/gui/menus/project.c
@@ -32,7 +32,7 @@
 
 
 #include "../editem-int.h"
-#include "../../analysis/binaries/file.h"
+#include "../../analysis/contents/file.h"
 #include "../../dialogs/shellcode.h"
 #include "../../gtkext/easygtk.h"
 
@@ -270,7 +270,7 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar)
     GtkWidget *dialog;                      /* Boîte à afficher            */
     char *dir;                              /* Répertoire courant          */
     gchar *filename;                        /* Nom du fichier à intégrer   */
-    GLoadedBinary *binary;                  /* Représentation chargée      */
+    GBinContent *content;                   /* Contenu binaire à charger   */
 
     dialog = gtk_file_chooser_dialog_new(_("Open a binary file"),
                                          GTK_WINDOW(G_EDITOR_ITEM(bar)->ref),
@@ -299,14 +299,9 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar)
     {
         filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
 
-        binary = g_file_binary_new_from_file(filename);
+        content = g_file_content_new(filename);
 
-        if (binary != NULL)
-        {
-            g_signal_connect(binary, "disassembly-done",
-                             G_CALLBACK(g_study_project_add_loaded_binary), get_current_project());
-            g_loaded_binary_analyse(binary);
-        }
+        qck_study_new_content(content, PCS_ROOT);
 
         g_free(filename);
 
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index acaf735..f786c08 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -39,37 +39,40 @@
 /* Prend acte du [dé]chargement du greffon. */
 typedef bool (* pg_management_fc) (GPluginModule *, GObject *);
 
+/* Exécute une action pendant un désassemblage de binaire. */
+typedef void (* pg_process_disassembly_fc) (const GPluginModule *, PluginAction, GLoadedBinary *);
+
+
+
+
 /* Indique si le format peut être pris en charge ici. */
-typedef bool (* pg_format_is_matching) (const GPluginModule *, GBinContent **);
+//typedef bool (* pg_format_is_matching) (const GPluginModule *, GBinContent **);
 
 /* Procède à une opération liée au format de fichier uniquement. */
 typedef bool (* pg_handle_format) (const GPluginModule *, PluginAction, GBinFormat *);
 
-/* Exécute une action pendant un désassemblage de binaire. */
-typedef void (* pg_process_disassembly) (const GPluginModule *, PluginAction, GLoadedBinary *);
-
 
 
 
 
 
 /* Précise le nom associé au greffon. */
-typedef char * (* get_plugin_name_fc) (void);
+//typedef char * (* get_plugin_name_fc) (void);
 
 /* Procède à l'initialisation du greffon. */
-typedef bool (* init_plugin_fc) (GPluginModule *, GObject *);
+//typedef bool (* init_plugin_fc) (GPluginModule *, GObject *);
 
 /* Procède à l'extinction du greffon. */
-typedef void (* exit_plugin_fc) (GPluginModule *);
+//typedef void (* exit_plugin_fc) (GPluginModule *);
 
 /* Fournit une indication sur le type d'opération(s) menée(s). */
-typedef PluginAction (* get_plugin_action_fc) (const GPluginModule *);
+//typedef PluginAction (* get_plugin_action_fc) (const GPluginModule *);
 
 /* Identifie un format à associer à un contenu binaire. */
 //typedef MatchingFormatAction (* is_matching_fc) (const GPluginModule *, char **, bin_t **, off_t *);
 
 /* Exécute une action définie sur un binaire chargé. */
-typedef bool (* execute_action_on_binary_fc) (const GPluginModule *, GLoadedBinary *, PluginAction);
+//typedef bool (* execute_action_on_binary_fc) (const GPluginModule *, GLoadedBinary *, PluginAction);
 
 /* Exécute une action relative à un débogueur. */
 //typedef bool (* execute_on_debugger_fc) (const GPluginModule *, GBinaryDebugger *, PluginAction);
@@ -88,6 +91,7 @@ struct _GPluginModule
     pg_management_fc init;                  /* Procédure d'initialisation  */
     pg_management_fc exit;                  /* Procédure d'extinction      */
 
+    pg_process_disassembly_fc process_disass; /* Catégorie 'désassemblage' */
 
 
     //char *name;                             /* Nom associé au greffon      */
@@ -95,18 +99,17 @@ struct _GPluginModule
 
     //init_plugin_fc init;                    /* Procédure d'initialisation  */
     //exit_plugin_fc exit;                    /* Procédure d'extinction      */
-    get_plugin_action_fc get_action;        /* Opération(s) menée(s)       */
+    //get_plugin_action_fc get_action;        /* Opération(s) menée(s)       */
 
     //is_matching_fc is_matching;             /* Recherche de correspondance */
 
-    execute_action_on_binary_fc exec_on_bin;/* Action sur un binaire       */
+    //execute_action_on_binary_fc exec_on_bin;/* Action sur un binaire       */
     //execute_on_debugger_fc handle_debugger; /* Action liée à un débogueur  */
 
 
-    pg_format_is_matching is_matching;      /* Recherche de correspondance */
+    //pg_format_is_matching is_matching;      /* Recherche de correspondance */
     pg_handle_format handle_format;         /* Manipulation du format      */
 
-    pg_process_disassembly proc_disass;     /* Catégorie 'désassemblage'   */
 
 };
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 9322bcb..c0e9fd1 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -37,6 +37,9 @@
 #include "plugin-int.h"
 
 
+#include "../core/formats.h"
+
+
 
 /* Initialise la classe des greffons. */
 static void g_plugin_module_class_init(GPluginModuleClass *);
@@ -162,8 +165,10 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
     GPluginModule *result;                  /* Structure à retourner       */
     plugin_abi_version_t current;           /* Version de l'ABI actuelle   */
     size_t i;                               /* Boucle de parcours          */
+    uint32_t action;                        /* Identifiant d'une action    */
     uint32_t category;                      /* Catégorie principale        */
     uint32_t sub;                           /* Sous-catégorie visée        */
+    format_match_fc matcher;                /* Routine de reconnaissance   */
 
     result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL);
 
@@ -215,8 +220,9 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 
     for (i = 0; i < result->interface->actions_count; i++)
     {
-        category = MASK_PLUGIN_CATEGORY(result->interface->actions[i]);
-        sub = MASK_PLUGIN_SUB_CATEGORY(result->interface->actions[i]);
+        action = result->interface->actions[i];
+        category = MASK_PLUGIN_CATEGORY(action);
+        sub = MASK_PLUGIN_SUB_CATEGORY(action);
 
         switch (category)
         {
@@ -254,8 +260,18 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
                 {
                     case DPS_FORMAT:
 
-                        switch (result->interface->actions[i])
+                        switch (action)
                         {
+                            case PGA_FORMAT_MATCHER:
+
+                                if (!load_plugin_symbol(result->module,
+                                                        "is_format_matching", &matcher))
+                                    goto bad_plugin;
+
+                                if (!register_format_matcher(matcher, result))
+                                    goto bad_plugin;
+
+                                break;
 
                             case PGA_FORMAT_LOADER_LAST:
                                 if (!load_plugin_symbol(result->module,
@@ -275,7 +291,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 
                     case DPS_DISASSEMBLY:
                         if (!load_plugin_symbol(result->module,
-                                                "process_binary_disassembly", &result->proc_disass))
+                                                "process_binary_disassembly", &result->process_disass))
                             goto bad_plugin;
                         break;
 
@@ -504,6 +520,6 @@ bool g_plugin_module_handle_binary_format(const GPluginModule *plugin, PluginAct
 
 void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary)
 {
-    plugin->proc_disass(plugin, action, binary);
+    plugin->process_disass(plugin, action, binary);
 
 }
-- 
cgit v0.11.2-87-g4458