From b0347ca45a08ac63bc6dd6f244b046c6d19a6cdd Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 6 Apr 2021 00:59:31 +0200
Subject: Build a partial working support for the PE format.

---
 configure.ac                            |   2 +
 plugins/Makefile.am                     |   1 +
 plugins/elf/symbols.c                   |   6 +-
 plugins/pe/Makefile.am                  |  50 ++-
 plugins/pe/core.c                       | 117 ++++++
 plugins/pe/core.h                       |  41 ++
 plugins/pe/format.c                     | 714 ++++++++++++++++++++++++++++----
 plugins/pe/format.h                     |  34 +-
 plugins/pe/pe-int.c                     | 364 +++++++++-------
 plugins/pe/pe-int.h                     |  48 +--
 plugins/pe/pe_def.h                     | 165 ++++++--
 plugins/pe/python/Makefile.am           |  23 +
 plugins/pe/python/constants.c           | 143 +++++++
 plugins/pe/python/constants.h           |  42 ++
 plugins/pe/python/format.c              | 595 ++++++++++++++++++++++++++
 plugins/pe/python/format.h              |  45 ++
 plugins/pe/python/module.c              |  93 +++++
 plugins/pe/python/module.h              |  38 ++
 plugins/pe/python/routine.c             | 472 +++++++++++++++++++++
 plugins/pe/python/routine.h             |  62 +++
 plugins/pe/python/translate.c           | 213 ++++++++++
 plugins/pe/python/translate.h           |  48 +++
 plugins/pe/rich.c                       | 312 ++++++++++++++
 plugins/pe/rich.h                       |  61 +++
 plugins/pe/routine.c                    | 429 +++++++++++++++++++
 plugins/pe/routine.h                    | 111 +++++
 plugins/pe/section.c                    |  36 +-
 plugins/pe/section.h                    |  10 +-
 plugins/pe/symbols.c                    | 335 +++++++++++++--
 plugins/pe/symbols.h                    |  15 +-
 plugins/pychrysalide/format/constants.c |   1 -
 src/format/strsym.h                     |   4 +-
 src/format/symbol.c                     |   2 +-
 src/format/symbol.h                     |   6 +-
 34 files changed, 4265 insertions(+), 373 deletions(-)
 create mode 100644 plugins/pe/core.c
 create mode 100644 plugins/pe/core.h
 create mode 100644 plugins/pe/python/Makefile.am
 create mode 100644 plugins/pe/python/constants.c
 create mode 100644 plugins/pe/python/constants.h
 create mode 100644 plugins/pe/python/format.c
 create mode 100644 plugins/pe/python/format.h
 create mode 100644 plugins/pe/python/module.c
 create mode 100644 plugins/pe/python/module.h
 create mode 100644 plugins/pe/python/routine.c
 create mode 100644 plugins/pe/python/routine.h
 create mode 100644 plugins/pe/python/translate.c
 create mode 100644 plugins/pe/python/translate.h
 create mode 100644 plugins/pe/rich.c
 create mode 100644 plugins/pe/rich.h
 create mode 100644 plugins/pe/routine.c
 create mode 100644 plugins/pe/routine.h

diff --git a/configure.ac b/configure.ac
index c2c3943..dd463e7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -497,6 +497,8 @@ AC_CONFIG_FILES([Makefile
                  plugins/libcsem/Makefile
                  plugins/lnxsyscalls/Makefile
                  plugins/mobicore/Makefile
+                 plugins/pe/Makefile
+                 plugins/pe/python/Makefile
                  plugins/pychrysalide/Makefile
                  plugins/pychrysalide/analysis/Makefile
                  plugins/pychrysalide/analysis/contents/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 678e315..e9258df 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -22,6 +22,7 @@ SUBDIRS = \
 	libcsem \
 	lnxsyscalls \
 	mobicore \
+	pe \
 	readdex \
 	readelf \
 	readmc \
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index a7cf05c..6d037cb 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -1195,11 +1195,11 @@ static bool register_elf_entry_point(GElfFormat *format, virt_t vaddr, GBinRouti
     result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_vaddr, &addr);
     if (!result) goto exit;
 
-    base = G_BIN_FORMAT(format);
-
     /* Comptabilisation en tant que symbole */
 
-    if (g_binary_format_find_symbol_at(G_BIN_FORMAT(format), &addr, &symbol))
+    base = G_BIN_FORMAT(format);
+
+    if (g_binary_format_find_symbol_at(base, &addr, &symbol))
     {
         /**
          * On ne relâche pas tout de suite le symbole trouvé, afin de le traiter
diff --git a/plugins/pe/Makefile.am b/plugins/pe/Makefile.am
index 00050a5..8e9bca6 100644
--- a/plugins/pe/Makefile.am
+++ b/plugins/pe/Makefile.am
@@ -1,21 +1,57 @@
 
-noinst_LTLIBRARIES = libformatpe.la
+DEFAULT_INCLUDES = -idirafter. -I$(top_builddir)
 
-libformatpe_la_SOURCES =				\
+lib_LTLIBRARIES = libpe.la
+
+libdir = $(pluginslibdir)
+
+
+if BUILD_PYTHON3_BINDINGS
+
+PYTHON3_LIBADD = python/libpepython.la
+
+if BUILD_DISCARD_LOCAL
+
+PYTHON3_LDFLAGS = -Wl,-rpath,$(pluginslibdir) \
+					-L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+else
+
+PYTHON3_LDFLAGS = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs \
+					-L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+endif
+
+PYTHON3_SUBDIRS = python
+
+endif
+
+
+libpe_la_SOURCES =						\
+	core.h core.c						\
 	pe-int.h pe-int.c					\
-	pe.h pe.c							\
+	format.h format.c					\
 	pe_def.h							\
+	rich.h rich.c						\
+	routine.h routine.c					\
 	section.h section.c					\
 	symbols.h symbols.c
 
-libformatpe_la_LDFLAGS = 
+libpe_la_LIBADD =						\
+	$(PYTHON3_LIBADD)
+
+libpe_la_LDFLAGS =								\
+	-L$(top_srcdir)/src/.libs -lchrysacore		\
+	$(PYTHON3_LDFLAGS)
 
 
-devdir = $(includedir)/chrysalide/$(subdir:src/%=%)
+devdir = $(includedir)/chrysalide/$(subdir)
 
-dev_HEADERS = $(libformatpe_la_SOURCES:%c=)
+dev_HEADERS = $(libpe_la_SOURCES:%c=)
 
 
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
 
 AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/pe/core.c b/plugins/pe/core.c
new file mode 100644
index 0000000..aa51c18
--- /dev/null
+++ b/plugins/pe/core.c
@@ -0,0 +1,117 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - intégration du support du format PE
+ *
+ * Copyright (C) 2017-2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <config.h>
+#include <core/global.h>
+#include <plugins/self.h>
+
+
+#include "format.h"
+#ifdef HAVE_PYTHON3_BINDINGS
+#   include "python/module.h"
+#endif
+
+
+#ifdef HAVE_PYTHON3_BINDINGS
+#   define PG_REQ RL("PyChrysalide")
+#else
+#   define PG_REQ NO_REQ
+#endif
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("Pe", "PE format support",
+                         PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/formats"),
+                         PG_REQ, AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                                                                             *
+*  Description : Prend acte du chargement du greffon.                         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+    bool result;                            /* Bilan à retourner           */
+
+#ifdef HAVE_PYTHON3_BINDINGS
+    result = add_format_pe_module_to_python_module();
+#else
+    result = true;
+#endif
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                content = contenu binaire à traiter.                         *
+*                wid     = identifiant du groupe de traitement.               *
+*                status  = barre de statut à tenir informée.                  *
+*                                                                             *
+*  Description : Procède à une opération liée à un contenu binaire.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status)
+{
+    bool test;                              /* Bilan des accès mémoire     */
+    GExeFormat *format;                     /* Format PE reconnu           */
+    GLoadedContent *loaded;                 /* Représentation chargée      */
+    GContentResolver *resolver;             /* Resolveur de contenus       */
+
+    test = check_pe_format(content);
+
+    if (test)
+    {
+        format = g_pe_format_new(content);
+        loaded = g_loaded_binary_new(format);
+
+        resolver = get_current_content_resolver();
+        g_content_resolver_add_detected(resolver, wid, loaded);
+        g_object_unref(G_OBJECT(resolver));
+
+        g_object_unref(G_OBJECT(loaded));
+
+    }
+
+}
diff --git a/plugins/pe/core.h b/plugins/pe/core.h
new file mode 100644
index 0000000..4497cf5
--- /dev/null
+++ b/plugins/pe/core.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'intégration du support du format PE
+ *
+ * Copyright (C) 2017-2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_PE_CORE_H
+#define _PLUGINS_PE_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+/* Procède à une opération liée à un contenu binaire. */
+G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *);
+
+
+
+#endif  /* _PLUGINS_PE_CORE_H */
diff --git a/plugins/pe/format.c b/plugins/pe/format.c
index 8533d25..f5bdac1 100644
--- a/plugins/pe/format.c
+++ b/plugins/pe/format.c
@@ -21,74 +21,122 @@
  */
 
 
-#include "pe.h"
+#include "format.h"
 
 
-#include <string.h>
+#include <assert.h>
 
 
 #include "pe-int.h"
+#include "rich.h"
 #include "section.h"
 #include "symbols.h"
 
 
 
-/* Initialise la classe des formats d'exécutables PE. */
+/* Initialise la classe des formats d'exécutables ELF. */
 static void g_pe_format_class_init(GPeFormatClass *);
 
-/* Initialise une instance de format d'exécutable PE. */
+/* Initialise une instance de format d'exécutable ELF. */
 static void g_pe_format_init(GPeFormat *);
 
+/* Supprime toutes les références externes. */
+static void g_pe_format_dispose(GPeFormat *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_pe_format_finalize(GPeFormat *);
+
+/* Indique la désignation interne du format. */
+static char *g_pe_format_get_key(const GPeFormat *);
+
+/* Fournit une description humaine du format. */
+static char *g_pe_format_get_description(const GPeFormat *);
+
+/* Assure l'interprétation d'un format en différé. */
+static bool g_pe_format_analyze(GPeFormat *, wgroup_id_t, GtkStatusStack *);
+
+/* Informe quant au boutisme utilisé. */
+static SourceEndian g_pe_format_get_endianness(const GPeFormat *);
+
 /* Indique le type d'architecture visée par le format. */
 static const char *g_pe_format_get_target_machine(const GPeFormat *);
 
-/* Fournit les références aux zones binaires à analyser. */
-//static GBinPart **g_pe_format_get_parts(const GPeFormat *, size_t *);
+/* Fournit l'adresse principale associée à un format Elf. */
+static bool g_pe_format_get_main_address(GPeFormat *, vmpa2t *);
+
+
+#if 0
+
+/* Etend la définition des portions au sein d'un binaire. */
+static void g_pe_format_refine_portions(GPeFormat *);
+
+#endif
+
+
+
+/* Fournit l'emplacement correspondant à une adresse virtuelle. */
+bool g_pe_format_translate_address_into_vmpa_using_portions(GPeFormat *, virt_t, vmpa2t *);
+
+
+#if 0
+
+/* Fournit l'emplacement d'une section donnée. */
+static bool g_pe_format_get_section_range_by_name(const GPeFormat *, const char *, mrange_t *);
+#endif
+
+
 
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = contenu binaire à parcourir.                       *
+*  Paramètres  : content = contenu binaire à traiter.                         *
 *                                                                             *
-*  Description : Indique si le format peut être pris en charge ici.           *
+*  Description : Valide un contenu comme étant un format PE.                  *
 *                                                                             *
-*  Retour      : true si la réponse est positive, false sinon.                *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool pe_is_matching(GBinContent *content)
+bool check_pe_format(const GBinContent *content)
 {
-    bool result;                            /* Bilan à faire connaître     */
-    image_dos_header dos_header;            /* En-tête DOS                 */
+    bool result;                            /* Bilan à faire remonter      */
+    vmpa2t addr;                            /* Tête de lecture initiale    */
+    char magic[4];                          /* Idenfiant standard          */
+    GPeFormat format;                       /* Format factice              */
 
-    result = false;
-#if 0
-    if (length >= 2)
+    init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
+
+    result = g_binary_content_read_raw(content, &addr, 2, (bin_t *)magic);
+
+    if (result)
+        result = (memcmp(magic, "\x4d\x5a" /* MZ */, 2) == 0);
+
+    if (result)
     {
-        result = (strncmp((const char *)content, "\x4d\x5a" /* MZ */, 2) == 0);
-        result &= length >= sizeof(image_dos_header);
+        G_KNOWN_FORMAT(&format)->content = (GBinContent *)content;
+        result = read_dos_image_header(&format, &format.dos_header);
     }
 
     if (result)
     {
-        memcpy(&dos_header, content, sizeof(image_dos_header));
+        init_vmpa(&addr, format.dos_header.e_lfanew, VMPA_NO_VIRTUAL);
 
-        result = length >= (dos_header.e_lfanew + 4);
+        result = g_binary_content_read_raw(content, &addr, 4, (bin_t *)magic);
 
-        result &= (strncmp((const char *)&content[dos_header.e_lfanew],
-                           "\x50\x45\x00\x00" /* PE00 */, 4) == 0);
+        if (result)
+            result = (memcmp(magic, "\x50\x45\x00\x00" /* PE00 */, 4) == 0);
 
     }
-#endif
+
     return result;
 
 }
 
 
-/* Indique le type défini pour un format d'exécutable PE. */
+/* Indique le type défini pour un format d'exécutable ELF. */
 G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT);
 
 
@@ -96,7 +144,7 @@ G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT);
 *                                                                             *
 *  Paramètres  : klass = classe à initialiser.                                *
 *                                                                             *
-*  Description : Initialise la classe des formats d'exécutables PE.           *
+*  Description : Initialise la classe des formats d'exécutables ELF.          *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -106,6 +154,36 @@ G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT);
 
 static void g_pe_format_class_init(GPeFormatClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GKnownFormatClass *known;               /* Version de format connu     */
+    GBinFormatClass *fmt;                   /* Version en format basique   */
+    GExeFormatClass *exe;                   /* Version en exécutable       */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_pe_format_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_pe_format_finalize;
+
+    known = G_KNOWN_FORMAT_CLASS(klass);
+
+    known->get_key = (known_get_key_fc)g_pe_format_get_key;
+    known->get_desc = (known_get_desc_fc)g_pe_format_get_description;
+    known->analyze = (known_analyze_fc)g_pe_format_analyze;
+
+    fmt = G_BIN_FORMAT_CLASS(klass);
+
+    fmt->get_endian = (format_get_endian_fc)g_pe_format_get_endianness;
+
+    exe = G_EXE_FORMAT_CLASS(klass);
+
+    exe->get_machine = (get_target_machine_fc)g_pe_format_get_target_machine;
+    exe->get_main_addr = (get_main_addr_fc)g_pe_format_get_main_address;
+    //exe->refine_portions = (refine_portions_fc)g_pe_format_refine_portions;
+
+    //exe->translate_phys = (translate_phys_fc)g_exe_format_translate_offset_into_vmpa_using_portions;
+    exe->translate_virt = (translate_virt_fc)g_pe_format_translate_address_into_vmpa_using_portions;
+
+    //exe->get_range_by_name = (get_range_by_name_fc)g_pe_format_get_section_range_by_name;
 
 }
 
@@ -114,7 +192,7 @@ static void g_pe_format_class_init(GPeFormatClass *klass)
 *                                                                             *
 *  Paramètres  : format = instance à initialiser.                             *
 *                                                                             *
-*  Description : Initialise une instance de format d'exécutable PE.           *
+*  Description : Initialise une instance de format d'exécutable ELF.          *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -124,6 +202,50 @@ static void g_pe_format_class_init(GPeFormatClass *klass)
 
 static void g_pe_format_init(GPeFormat *format)
 {
+    format->sections = NULL;
+
+    format->loaded = false;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_format_dispose(GPeFormat *format)
+{
+    G_OBJECT_CLASS(g_pe_format_parent_class)->dispose(G_OBJECT(format));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_format_finalize(GPeFormat *format)
+{
+    if (format->sections != NULL)
+        free(format->sections);
+
+    G_OBJECT_CLASS(g_pe_format_parent_class)->finalize(G_OBJECT(format));
 
 }
 
@@ -131,7 +253,6 @@ static void g_pe_format_init(GPeFormat *format)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu binaire à parcourir.                       *
-*                length  = taille du contenu en question.                     *
 *                                                                             *
 *  Description : Prend en charge un nouveau format PE.                        *
 *                                                                             *
@@ -141,53 +262,140 @@ static void g_pe_format_init(GPeFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-GBinFormat *g_pe_format_new(const bin_t *content, off_t length)
+GExeFormat *g_pe_format_new(GBinContent *content)
 {
     GPeFormat *result;                      /* Structure à retourner       */
-    off_t offset;                           /* Tête de lecture             */
 
+    if (!check_pe_format(content))
+        return NULL;
 
-    int i;
+    result = g_object_new(G_TYPE_PE_FORMAT, NULL);
 
+    g_known_format_set_content(G_KNOWN_FORMAT(result), content);
 
-    result = g_object_new(G_TYPE_PE_FORMAT, NULL);
+    return G_EXE_FORMAT(result);
 
-    //g_binary_format_set_content(G_BIN_FORMAT(result), content, length);
+}
 
-    offset = 0;
 
-    if (!read_dos_image_header(result, &offset, &result->dos_header))
-    {
-        /* TODO */
-        return NULL;
-    }
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                                                                             *
+*  Description : Indique la désignation interne du format.                    *
+*                                                                             *
+*  Retour      : Désignation du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    offset = result->dos_header.e_lfanew;
+static char *g_pe_format_get_key(const GPeFormat *format)
+{
+    char *result;                           /* Désignation à retourner     */
 
-    if (!read_pe_nt_header(result, &offset, &result->nt_headers))
-    {
-        /* TODO */
-        return NULL;
-    }
+    result = strdup("pe");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                                                                             *
+*  Description : Fournit une description humaine du format.                   *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static char *g_pe_format_get_description(const GPeFormat *format)
+{
+    char *result;                           /* Désignation à retourner     */
+
+    result = strdup("Portable Executable");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Assure l'interprétation d'un format en différé.              *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    result->section_offset = offset;
+static bool g_pe_format_analyze(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    GExeFormat *exe;                        /* Autre version du format     */
+    vmpa2t section_start;                   /* Zone de départ des sections */
 
-    printf("offset :: 0x%08x\n", offset);
+    exe = G_EXE_FORMAT(format);
 
-    printf("Format :: 0x%08x\n", result->nt_headers.signature);
+    result = read_dos_image_header(format, &format->dos_header);
+    if (!result) goto error;
 
-    printf("directories :: %d\n", result->nt_headers.optional_header.number_of_rva_and_sizes);
+    result = read_pe_nt_header(format, &format->nt_headers, &section_start);
+    if (!result) goto error;
 
-    for (i = 0; i < result->nt_headers.optional_header.number_of_rva_and_sizes; i++)
-        printf(" [%d] addr=0x%08x size=%d\n", i,
-               result->nt_headers.optional_header.data_directory[i].virtual_address,
-               result->nt_headers.optional_header.data_directory[i].size);
+    format->sections = read_all_pe_sections(format, &section_start);
+    if (format->sections == NULL) goto error;
 
+    extract_pe_rich_header(format);
 
-    load_pe_symbols(result);
+    result = load_pe_symbols(format, gid, status);
+    if (!result) goto error;
 
+    result = g_executable_format_complete_loading(exe, gid, status);
+    if (!result) goto error;
 
-    return G_BIN_FORMAT(result);
+ error:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                                                                             *
+*  Description : Informe quant au boutisme utilisé.                           *
+*                                                                             *
+*  Retour      : Indicateur de boutisme.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static SourceEndian g_pe_format_get_endianness(const GPeFormat *format)
+{
+    SourceEndian result;                    /* Boutisme à retourner        */
+
+    /**
+     * Sauf exception, le boutisme est généralement petit.
+     *
+     * Cf. https://reverseengineering.stackexchange.com/a/17923
+     *     https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions?view=msvc-160#endianness
+     */
+
+    result = SRE_LITTLE;
+
+    return result;
 
 }
 
@@ -206,69 +414,405 @@ GBinFormat *g_pe_format_new(const bin_t *content, off_t length)
 
 static const char *g_pe_format_get_target_machine(const GPeFormat *format)
 {
-    return "i386";
+    const char *result;                     /* Identifiant à retourner     */
+
+    switch (format->nt_headers.file_header.machine)
+    {
+        case IMAGE_FILE_MACHINE_I386:
+            result = "i386";
+            break;
+
+        case IMAGE_FILE_MACHINE_R3000:
+        case IMAGE_FILE_MACHINE_R4000:
+        case IMAGE_FILE_MACHINE_R10000:
+        case IMAGE_FILE_MACHINE_WCEMIPSV2:
+        case IMAGE_FILE_MACHINE_MIPS16:
+        case IMAGE_FILE_MACHINE_MIPSFPU:
+        case IMAGE_FILE_MACHINE_MIPSFPU16:
+            result = "mips";
+            break;
+
+        case IMAGE_FILE_MACHINE_ARM:
+        case IMAGE_FILE_MACHINE_THUMB:
+        case IMAGE_FILE_MACHINE_ARMNT:
+            result = "armv7";
+            break;
+
+        case IMAGE_FILE_MACHINE_UNKNOWN:
+        default:
+            result = NULL;
+            break;
+
+    }
+
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = informations chargées à consulter.                  *
-*                count  = quantité de zones listées. [OUT]                    *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                addr   = adresse principale trouvée si possible. [OUT]       *
 *                                                                             *
-*  Description : Fournit les références aux zones binaires à analyser.        *
+*  Description : Fournit l'adresse principale associée à un format Elf.       *
 *                                                                             *
-*  Retour      : Zones binaires à analyser.                                   *
+*  Retour      : Bilan des recherches.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
+
+static bool g_pe_format_get_main_address(GPeFormat *format, vmpa2t *addr)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinSymbol *symbol;                     /* Point d'entrée trouvé       */
+    GBinFormat *base;                       /* Version d'instance parente  */
+    const mrange_t *range;                  /* Emplacement de ce point     */
+
+    result = false;
+    symbol = NULL;
+
+    base = G_BIN_FORMAT(format);
+
+    if (g_binary_format_find_symbol_by_label(base, "main", &symbol))
+        goto done;
+
+    if (g_binary_format_find_symbol_by_label(base, "_start", &symbol))
+        goto done;
+
+    if (g_binary_format_find_symbol_by_label(base, "entry_point", &symbol))
+        goto done;
+
+ done:
+
+    if (symbol != NULL)
+    {
+        result = true;
+
+        range = g_binary_symbol_get_range(symbol);
+
+        copy_vmpa(addr, get_mrange_addr(range));
+
+        g_object_unref(G_OBJECT(symbol));
+
+    }
+
+    return result;
+
+}
+
+
 #if 0
-static GBinPart **g_pe_format_get_parts(const GPeFormat *format, size_t *count)
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                                                                             *
+*  Description : Etend la définition des portions au sein d'un binaire.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_format_refine_portions(GPeFormat *format)
+{
+
+}
+
+#endif
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                addr   = adresse virtuelle à retrouver.                      *
+*                pos    = position correspondante. [OUT]                      *
+*                                                                             *
+*  Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_pe_format_translate_address_into_vmpa_using_portions(GPeFormat *format, virt_t addr, vmpa2t *pos)
 {
-    GBinPart **result;                      /* Tableau à retourner         */
+    bool result;                            /* Bilan à retourner           */
     uint16_t i;                             /* Boucle de parcours          */
-    image_section_header section;           /* En-tête de section PE       */
-    GBinPart *part;                         /* Partie à intégrer à la liste*/
-    char name[IMAGE_SIZEOF_SHORT_NAME + 1]; /* Nom de section utilisable   */
+    const image_section_header *section;    /* Section à consulter         */
+    phys_t diff;                            /* Décallage à appliquer       */
 
-    result = NULL;
-    *count = 0;
+    result = false;
 
-    for (i = 0; i < format->nt_headers.file_header.number_of_sections; i++)
+    for (i = 0; i < format->nt_headers.file_header.number_of_sections && !result; i++)
     {
-        if (!find_pe_section_by_index(format, i, &section))
+        section = &format->sections[i];
+
+        if (addr < section->virtual_address)
+            continue;
+
+        if (addr >= (section->virtual_address + section->size_of_raw_data))
             continue;
 
-        if (section.characteristics & IMAGE_SCN_MEM_EXECUTE)
-        {
-            part = g_binary_part_new();
+        diff = addr - section->virtual_address;
 
-            memset(name, 0, (IMAGE_SIZEOF_SHORT_NAME + 1) * sizeof(char));
-            memcpy(name, section.name, (IMAGE_SIZEOF_SHORT_NAME + 1) * sizeof(char));
+        init_vmpa(pos, section->pointer_to_raw_data + diff, addr);
 
-            g_binary_part_set_name(part, name);
+        result = true;
 
-            printf("section '%s'\n", name);
+    }
 
-            g_binary_part_set_values(part,
-                                     section.pointer_to_raw_data,
-                                     section.size_of_raw_data,
-                                     section.virtual_address);
+    //printf(" // trans // %x -> %x  (valid? %d)\n", (unsigned int)addr, (unsigned int)pos->physical, result);
 
-            printf("section[%d] start=0x%08x  size=%d  addr=0x%08x\n", i,
-                   section.pointer_to_raw_data,
-                   section.size_of_raw_data,
-                   section.virtual_address);
+    return result;
 
-            result = (GBinPart **)realloc(result, ++(*count) * sizeof(GBinPart *));
-            result[*count - 1] = part;
+}
+
+
+
+
+#if 0
 
-        }
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                name   = nom de la section recherchée.                       *
+*                range  = emplacement en mémoire à renseigner. [OUT]          *
+*                                                                             *
+*  Description : Fournit l'emplacement d'une section donnée.                  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_pe_format_get_section_range_by_name(const GPeFormat *format, const char *name, mrange_t *range)
+{
+    bool result;                            /* Bilan à retourner           */
+    phys_t offset;                          /* Position physique de section*/
+    phys_t size;                            /* Taille de la section trouvée*/
+    virt_t address;                         /* Adresse virtuelle de section*/
+    vmpa2t tmp;                             /* Adresse à initialiser       */
+
+    result = find_elf_section_content_by_name(format, name, &offset, &size, &address);
+
+    if (result)
+    {
+        init_vmpa(&tmp, offset, address);
+        init_mrange(range, &tmp, size);
     }
 
     return result;
 
 }
 #endif
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format en place à consulter.                        *
+*                                                                             *
+*  Description : Présente l'en-tête MS-DOS du format chargé.                  *
+*                                                                             *
+*  Retour      : Pointeur vers la description principale.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const image_dos_header *g_pe_format_get_dos_header(const GPeFormat *format)
+{
+    const image_dos_header *result;         /* Informations à retourner    */
+
+    result = &format->dos_header;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format en place à consulter.                        *
+*                                                                             *
+*  Description : Présente l'en-tête NT du format chargé.                      *
+*                                                                             *
+*  Retour      : Pointeur vers la description principale.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const image_nt_headers *g_pe_format_get_nt_headers(const GPeFormat *format)
+{
+    const image_nt_headers *result;         /* Informations à retourner    */
+
+    result = &format->nt_headers;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format en place à consulter.                        *
+*                                                                             *
+*  Description : Indique si le format PE est en 32 bits ou en 64 bits.        *
+*                                                                             *
+*  Retour      : true si le format est en 32 bits, false sinon.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_pe_format_get_is_32b(const GPeFormat *format)
+{
+    bool result;                            /* Nature à retourner          */
+
+    assert(format->loaded);
+
+    switch (format->nt_headers.optional_header.header_32.magic)
+    {
+        case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+            result = true;
+            break;
+        case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+            result = false;
+            break;
+        default:
+            result = true;
+            assert(false);
+            break;
+    }
+
+    return result;
+
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format en place à consulter.                        *
+*                count  = taille (fixe) du tableau renvoyé. [OUT]             *
+*                                                                             *
+*  Description : Offre un raccourci vers les répertoires du format PE.        *
+*                                                                             *
+*  Retour      : Pointeur vers le tableau des répertoires.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const image_data_directory *g_pe_format_get_directories(const GPeFormat *format, size_t *count)
+{
+    const image_data_directory *result;     /* Liste à retourner           */
+
+    if (count != NULL)
+        *count = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
+
+    if (g_pe_format_get_is_32b(format))
+        result = format->nt_headers.optional_header.header_32.data_directory;
+    else
+        result = format->nt_headers.optional_header.header_64.data_directory;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format en place à consulter.                        *
+*                index  = indice du répertoire visé.                          *
+*                                                                             *
+*  Description : Extrait le contenu d'un répertoire du format PE.             *
+*                                                                             *
+*  Retour      : Pointeur vers un contenu chargé ou NULL.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void *g_pe_format_get_directory(const GPeFormat *format, size_t index)
+{
+    void *result;                           /* Données à retourner         */
+    const image_data_directory *dir;        /* Localisation du répertoire  */
+    vmpa2t pos;                             /* Tête de lecture             */
+    bool status;                            /* Bilan d'un traitement       */
+    image_export_directory *export;         /* Répertoire de type 0        */
+    image_import_descriptor *imports;       /* Répertoire de type 1        */
+    size_t imported_count;                  /* Quantité de DLL requises    */
+
+    result = NULL;
+
+    if (index >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
+        goto exit;
+
+    dir = g_pe_format_get_directories(format, NULL);
+    dir += index;
+
+    status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), dir->virtual_address, &pos);
+    if (!status) goto exit;
+
+    switch (index)
+    {
+        case IMAGE_DIRECTORY_ENTRY_EXPORT:
+
+            export = malloc(sizeof(image_export_directory));
+
+            status = read_pe_image_export_directory(format, &pos, export);
+
+            if (!status)
+            {
+                free(export);
+                goto exit;
+            }
+
+            result = export;
+            break;
+
+        case IMAGE_DIRECTORY_ENTRY_IMPORT:
+
+            imports = NULL;
+            imported_count = 0;
+
+            do
+            {
+                imports = realloc(imports, ++imported_count * sizeof(image_import_descriptor));
+
+                status = read_pe_image_import_descriptor(format, &pos, imports + (imported_count - 1));
+
+                if (!status)
+                {
+                    free(imports);
+                    goto exit;
+                }
+
+            }
+            while (imports[imported_count - 1].original_first_thunk != 0);
+
+            result = imports;
+            break;
+
+    }
+
+ exit:
+
+    return result;
+
+}
diff --git a/plugins/pe/format.h b/plugins/pe/format.h
index f757d26..a48e04d 100644
--- a/plugins/pe/format.h
+++ b/plugins/pe/format.h
@@ -21,16 +21,19 @@
  */
 
 
-#ifndef _FORMAT_PE_PE_H
-#define _FORMAT_PE_PE_H
+#ifndef _PLUGINS_PE_FORMAT_H
+#define _PLUGINS_PE_FORMAT_H
 
 
 #include <glib-object.h>
 #include <stdbool.h>
-#include <sys/types.h>
 
 
-#include "../../core/formats.h"
+#include <analysis/content.h>
+#include <format/executable.h>
+
+
+#include "pe_def.h"
 
 
 
@@ -49,15 +52,30 @@ typedef struct _GPeFormat GPeFormat;
 typedef struct _GPeFormatClass GPeFormatClass;
 
 
-/* Indique si le format peut être pris en charge ici. */
-bool pe_is_matching(GBinContent *);
+/* Valide un contenu comme étant un format PE. */
+bool check_pe_format(const GBinContent *);
 
 /* Indique le type défini pour un format d'exécutable PE. */
 GType g_pe_format_get_type(void);
 
 /* Prend en charge un nouveau format PE. */
-GBinFormat *g_pe_format_new(const bin_t *, off_t);
+GExeFormat *g_pe_format_new(GBinContent *);
+
+/* Présente l'en-tête MS-DOS du format chargé. */
+const image_dos_header *g_pe_format_get_dos_header(const GPeFormat *);
+
+/* Présente l'en-tête NT du format chargé. */
+const image_nt_headers *g_pe_format_get_nt_headers(const GPeFormat *);
+
+/* Indique si le format PE est en 32 bits ou en 64 bits. */
+bool g_pe_format_get_is_32b(const GPeFormat *);
+
+/* Offre un raccourci vers les répertoires du format PE. */
+const image_data_directory *g_pe_format_get_directories(const GPeFormat *, size_t *);
+
+/* Extrait le contenu d'un répertoire du format PE. */
+void *g_pe_format_get_directory(const GPeFormat *, size_t);
 
 
 
-#endif  /* _FORMAT_PE_PE_H */
+#endif  /* _PLUGINS_PE_FORMAT_H */
diff --git a/plugins/pe/pe-int.c b/plugins/pe/pe-int.c
index 0ce1577..db09c15 100644
--- a/plugins/pe/pe-int.c
+++ b/plugins/pe/pe-int.c
@@ -27,18 +27,16 @@
 #include <malloc.h>
 #include <string.h>
 
-
-#include "../../common/endianness.h"
+#include <common/endianness.h>
 
 
 
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
-*                pos    = position de début de lecture. [OUT]                 *
 *                header = structure lue à retourner. [OUT]                    *
 *                                                                             *
-*  Description : Procède à la lecture d'une en-tête de programme DOS.         *
+*  Description : Procède à la lecture d'un en-tête de programme DOS.          *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -46,41 +44,44 @@
 *                                                                             *
 ******************************************************************************/
 
-bool read_dos_image_header(const GPeFormat *format, off_t *pos, image_dos_header *header)
+bool read_dos_image_header(const GPeFormat *format, image_dos_header *header)
 {
     bool result;                            /* Bilan à retourner           */
-    const bin_t *content;                   /* Contenu binaire à lire      */
-    off_t length;                           /* Taille totale du contenu    */
+    const GBinContent *content;             /* Contenu binaire à lire      */
+    vmpa2t pos;                             /* Position de lecture         */
     size_t i;                               /* Boucle de parcours          */
 
-    content = NULL; //G_BIN_FORMAT(format)->content;
-    length = 0; //G_BIN_FORMAT(format)->length;
-
-    result = read_u16(&header->e_magic, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_cblp, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_cp, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_crlc, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_cparhdr, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_minalloc, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_maxalloc, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_ss, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_sp, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_csum, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_ip, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_cs, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_lfarlc, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_ovno, content, pos, length, SRE_LITTLE);
+    result = true;
+
+    content = G_KNOWN_FORMAT(format)->content;
+
+    init_vmpa(&pos, 0, VMPA_NO_VIRTUAL);
+
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_magic);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_cblp);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_cp);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_crlc);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_cparhdr);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_minalloc);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_maxalloc);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_ss);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_sp);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_csum);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_ip);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_cs);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_lfarlc);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_ovno);
 
     for (i = 0; i < 4 && result; i++)
-        result = read_u16(&header->e_res[i], content, pos, length, SRE_LITTLE);
+        result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_res[i]);
 
-    result &= read_u16(&header->e_oemid, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->e_oeminfo, content, pos, length, SRE_LITTLE);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_oemid);
+    if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_oeminfo);
 
     for (i = 0; i < 10 && result; i++)
-        result = read_u16(&header->e_res2[i], content, pos, length, SRE_LITTLE);
+        result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_res2[i]);
 
-    result &= read_u32(&header->e_lfanew, content, pos, length, SRE_LITTLE);
+    if (result) result = g_binary_content_read_u32(content, &pos, SRE_LITTLE, &header->e_lfanew);
 
     return result;
 
@@ -93,7 +94,7 @@ bool read_dos_image_header(const GPeFormat *format, off_t *pos, image_dos_header
 *                pos    = position de début de lecture. [OUT]                 *
 *                header = structure lue à retourner. [OUT]                    *
 *                                                                             *
-*  Description : Procède à la lecture d'une en-tête de programme PE (1).      *
+*  Description : Procède à la lecture d'un en-tête de programme PE (1).       *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -101,22 +102,22 @@ bool read_dos_image_header(const GPeFormat *format, off_t *pos, image_dos_header
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_file_header(const GPeFormat *format, off_t *pos, image_file_header *header)
+bool read_pe_file_header(const GPeFormat *format, vmpa2t *pos, image_file_header *header)
 {
     bool result;                            /* Bilan à retourner           */
-    const bin_t *content;                   /* Contenu binaire à lire      */
-    off_t length;                           /* Taille totale du contenu    */
+    const GBinContent *content;             /* Contenu binaire à lire      */
+
+    result = true;
 
-    content = NULL; //G_BIN_FORMAT(format)->content;
-    length = 0; //G_BIN_FORMAT(format)->length;
+    content = G_KNOWN_FORMAT(format)->content;
 
-    result = read_u16(&header->machine, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->number_of_sections, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->time_date_stamp, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->pointer_to_symbol_table, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->number_of_symbols, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->size_of_optional_header, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->characteristics, content, pos, length, SRE_LITTLE);
+    if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->machine);
+    if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->number_of_sections);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->time_date_stamp);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->pointer_to_symbol_table);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->number_of_symbols);
+    if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->size_of_optional_header);
+    if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->characteristics);
 
     return result;
 
@@ -129,7 +130,7 @@ bool read_pe_file_header(const GPeFormat *format, off_t *pos, image_file_header
 *                pos    = position de début de lecture. [OUT]                 *
 *                header = structure lue à retourner. [OUT]                    *
 *                                                                             *
-*  Description : Procède à la lecture d'une en-tête de programme PE (2).      *
+*  Description : Procède à la lecture d'un en-tête de programme PE (2).       *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -137,53 +138,115 @@ bool read_pe_file_header(const GPeFormat *format, off_t *pos, image_file_header
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_optional_header(const GPeFormat *format, off_t *pos, image_optional_header *header)
+bool read_pe_optional_header(const GPeFormat *format, vmpa2t *pos, image_optional_header *header)
 {
     bool result;                            /* Bilan à retourner           */
-    const bin_t *content;                   /* Contenu binaire à lire      */
-    off_t length;                           /* Taille totale du contenu    */
+    const GBinContent *content;             /* Contenu binaire à lire      */
+    image_optional_header_32 *hdr32;        /* Version 32 bits             */
+    image_optional_header_64 *hdr64;        /* Version 64 bits             */
+    image_data_directory *directories;      /* Répertoires à charger       */
+    uint32_t number_of_rva_and_sizes;       /* Quantité de ces répertoires */
     uint32_t i;                             /* Boucle de parcours          */
 
-    content = NULL; //G_BIN_FORMAT(format)->content;
-    length = 0; //G_BIN_FORMAT(format)->length;
-
-    result = read_u16(&header->magic, content, pos, length, SRE_LITTLE);
-    result &= read_u8(&header->major_linker_version, content, pos, length);
-    result &= read_u8(&header->minor_linker_version, content, pos, length);
-    result &= read_u32(&header->size_of_code, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->size_of_initialized_data, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->size_of_uninitialized_data, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->address_of_entry_point, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->base_of_code, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->base_of_data, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->image_base, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->section_alignment, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->file_alignment, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->major_operating_system_version, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->minor_operating_system_version, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->major_image_version, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->minor_image_version, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->major_subsystem_version, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->minor_subsystem_version, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->win32_version_value, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->size_of_image, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->size_of_headers, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->subsystem, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&header->dll_characteristics, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->size_of_stack_reserve, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->size_of_stack_commit, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->size_of_heap_reserve, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->size_of_heap_commit, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->loader_flags, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&header->number_of_rva_and_sizes, content, pos, length, SRE_LITTLE);
-
-    for (i = 0; i < header->number_of_rva_and_sizes && result; i++)
+    content = G_KNOWN_FORMAT(format)->content;
+
+    result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->header_32.magic);
+    if (!result) goto exit;
+
+    ((GPeFormat *)format)->loaded = true;
+
+    if (g_pe_format_get_is_32b(format))
+    {
+        hdr32 = &header->header_32;
+
+        if (result) result = g_binary_content_read_u8(content, pos, &hdr32->major_linker_version);
+        if (result) result = g_binary_content_read_u8(content, pos, &hdr32->minor_linker_version);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_code);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_initialized_data);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_uninitialized_data);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->address_of_entry_point);
+
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->base_of_code);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->base_of_data);
+
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->image_base);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->section_alignment);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->file_alignment);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->major_operating_system_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->minor_operating_system_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->major_image_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->minor_image_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->major_subsystem_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->minor_subsystem_version);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->win32_version_value);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_image);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_headers);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->checksum);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->subsystem);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->dll_characteristics);
+
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_stack_reserve);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_stack_commit);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_heap_reserve);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_heap_commit);
+
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->loader_flags);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->number_of_rva_and_sizes);
+
+        directories = hdr32->data_directory;
+        number_of_rva_and_sizes = hdr32->number_of_rva_and_sizes;
+
+    }
+    else
+    {
+        hdr64 = &header->header_64;
+
+        if (result) result = g_binary_content_read_u8(content, pos, &hdr64->major_linker_version);
+        if (result) result = g_binary_content_read_u8(content, pos, &hdr64->minor_linker_version);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_code);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_initialized_data);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_uninitialized_data);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->address_of_entry_point);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->base_of_code);
+
+        if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->image_base);
+
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->section_alignment);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->file_alignment);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->major_operating_system_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->minor_operating_system_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->major_image_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->minor_image_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->major_subsystem_version);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->minor_subsystem_version);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->win32_version_value);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_image);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_headers);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->checksum);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->subsystem);
+        if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->dll_characteristics);
+
+        if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->size_of_stack_reserve);
+        if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->size_of_stack_commit);
+        if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->size_of_heap_reserve);
+        if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->size_of_heap_commit);
+
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->loader_flags);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->number_of_rva_and_sizes);
+
+        directories = hdr64->data_directory;
+        number_of_rva_and_sizes = hdr64->number_of_rva_and_sizes;
+
+    }
+
+    for (i = 0; i < number_of_rva_and_sizes && result; i++)
     {
-        result = read_u32(&header->data_directory[i].virtual_address, content, pos, length, SRE_LITTLE);
-        result &= read_u32(&header->data_directory[i].size, content, pos, length, SRE_LITTLE);
+        result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &directories[i].virtual_address);
+        if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &directories[i].size);
     }
 
+ exit:
+
     return result;
 
 }
@@ -192,10 +255,10 @@ bool read_pe_optional_header(const GPeFormat *format, off_t *pos, image_optional
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
-*                pos    = position de début de lecture. [OUT]                 *
 *                header = structure lue à retourner. [OUT]                    *
+*                next   = position en fin de lecture. [OUT]                   *
 *                                                                             *
-*  Description : Procède à la lecture d'une en-tête de programme PE.          *
+*  Description : Procède à la lecture d'un en-tête de programme PE.           *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -203,19 +266,26 @@ bool read_pe_optional_header(const GPeFormat *format, off_t *pos, image_optional
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_nt_header(const GPeFormat *format, off_t *pos, image_nt_headers *header)
+bool read_pe_nt_header(const GPeFormat *format, image_nt_headers *header, vmpa2t *next)
 {
     bool result;                            /* Bilan à retourner           */
-    const bin_t *content;                   /* Contenu binaire à lire      */
-    off_t length;                           /* Taille totale du contenu    */
+    const GBinContent *content;             /* Contenu binaire à lire      */
+    vmpa2t pos;                             /* Position de lecture         */
+
+    result = true;
+
+    content = G_KNOWN_FORMAT(format)->content;
+
+    init_vmpa(&pos, format->dos_header.e_lfanew, VMPA_NO_VIRTUAL);
 
-    content = NULL; //G_BIN_FORMAT(format)->content;
-    length = 0; //G_BIN_FORMAT(format)->length;
+    result = g_binary_content_read_u32(content, &pos, SRE_LITTLE, &header->signature);
 
-    result = read_u32(&header->signature, content, pos, length, SRE_LITTLE);
+    if (result) result = read_pe_file_header(format, &pos, &header->file_header);
 
-    result &= read_pe_file_header(format, pos, &header->file_header);
-    result &= read_pe_optional_header(format, pos, &header->optional_header);
+    if (result) result = read_pe_optional_header(format, &pos, &header->optional_header);
+
+    if (result)
+        copy_vmpa(next, &pos);
 
     return result;
 
@@ -228,7 +298,7 @@ bool read_pe_nt_header(const GPeFormat *format, off_t *pos, image_nt_headers *he
 *                pos     = position de début de lecture. [OUT]                *
 *                section = structure lue à retourner. [OUT]                   *
 *                                                                             *
-*  Description : Procède à la lecture d'une en-tête de section PE.            *
+*  Description : Procède à la lecture d'un en-tête de section PE.             *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -236,31 +306,29 @@ bool read_pe_nt_header(const GPeFormat *format, off_t *pos, image_nt_headers *he
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_image_section_header(const GPeFormat *format, off_t *pos, image_section_header *section)
+bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_section_header *section)
 {
     bool result;                            /* Bilan à retourner           */
-    const bin_t *content;                   /* Contenu binaire à lire      */
-    off_t length;                           /* Taille totale du contenu    */
+    const GBinContent *content;             /* Contenu binaire à lire      */
     size_t i;                               /* Boucle de parcours          */
 
-    content = NULL; //G_BIN_FORMAT(format)->content;
-    length = 0; //G_BIN_FORMAT(format)->length;
-
     result = true;
 
+    content = G_KNOWN_FORMAT(format)->content;
+
     for (i = 0; i < IMAGE_SIZEOF_SHORT_NAME && result; i++)
-        result = read_u8((uint8_t *)&section->name[i], content, pos, length);
+        result = g_binary_content_read_u8(content, pos, (uint8_t *)&section->name[i]);
 
-    result &= read_u32(&section->misc.physical_address, content, pos, length, SRE_LITTLE);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->misc.physical_address);
 
-    result &= read_u32(&section->virtual_address, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&section->size_of_raw_data, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&section->pointer_to_raw_data, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&section->pointer_to_relocations, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&section->pointer_to_line_numbers, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&section->number_of_relocations, content, pos, length, SRE_LITTLE);
-    result &= read_u16(&section->number_of_line_numbers, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&section->characteristics, content, pos, length, SRE_LITTLE);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->virtual_address);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->size_of_raw_data);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->pointer_to_raw_data);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->pointer_to_relocations);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->pointer_to_line_numbers);
+    if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &section->number_of_relocations);
+    if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &section->number_of_line_numbers);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->characteristics);
 
     return result;
 
@@ -271,9 +339,9 @@ bool read_pe_image_section_header(const GPeFormat *format, off_t *pos, image_sec
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                pos    = position de début de lecture. [OUT]                 *
-*                desc   = structure lue à retourner. [OUT]                    *
+*                dir    = structure lue à retourner. [OUT]                    *
 *                                                                             *
-*  Description : Procède à la lecture d'un répertoire de programme PE.        *
+*  Description : Procède à la lecture d'un répertoire d'exportations.         *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -281,20 +349,26 @@ bool read_pe_image_section_header(const GPeFormat *format, off_t *pos, image_sec
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_image_import_descriptor(const GPeFormat *format, off_t *pos, image_import_descriptor *desc)
+bool read_pe_image_export_directory(const GPeFormat *format, vmpa2t *pos, image_export_directory *dir)
 {
     bool result;                            /* Bilan à retourner           */
-    const bin_t *content;                   /* Contenu binaire à lire      */
-    off_t length;                           /* Taille totale du contenu    */
+    const GBinContent *content;             /* Contenu binaire à lire      */
 
-    content = NULL; //G_BIN_FORMAT(format)->content;
-    length = 0; //G_BIN_FORMAT(format)->length;
+    result = true;
 
-    result = read_u32(&desc->original_first_thunk, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&desc->time_date_stamp, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&desc->forwarder_chain, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&desc->module_name, content, pos, length, SRE_LITTLE);
-    result &= read_u32(&desc->first_thunk, content, pos, length, SRE_LITTLE);
+    content = G_KNOWN_FORMAT(format)->content;
+
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->characteristics);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->time_date_stamp);
+    if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &dir->major_version);
+    if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &dir->minor_version);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->name);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->base);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->number_of_functions);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->number_of_names);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->address_of_functions);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->address_of_names);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->address_of_name_ordinals);
 
     return result;
 
@@ -305,9 +379,9 @@ bool read_pe_image_import_descriptor(const GPeFormat *format, off_t *pos, image_
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                pos    = position de début de lecture. [OUT]                 *
-*                import = structure lue à retourner. [OUT]                    *
+*                desc   = structure lue à retourner. [OUT]                    *
 *                                                                             *
-*  Description : Procède à la lecture d'une fonction importée par son nom.    *
+*  Description : Procède à la lecture d'un répertoire de programme PE.        *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -315,44 +389,20 @@ bool read_pe_image_import_descriptor(const GPeFormat *format, off_t *pos, image_
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_image_import_by_name(const GPeFormat *format, off_t *pos, image_import_by_name *import)
+bool read_pe_image_import_descriptor(const GPeFormat *format, vmpa2t *pos, image_import_descriptor *desc)
 {
     bool result;                            /* Bilan à retourner           */
-    const bin_t *content;                   /* Contenu binaire à lire      */
-    off_t length;                           /* Taille totale du contenu    */
-    uint32_t link;                          /* Lien vers la prochaine zone */
-    off_t new_pos;                          /* Nouvelle tête de lecture    */
-    size_t i;                               /* Boucle de parcours          */
-
-    content = NULL; //G_BIN_FORMAT(format)->content;
-    length = 0; //G_BIN_FORMAT(format)->length;
+    const GBinContent *content;             /* Contenu binaire à lire      */
 
-    result = read_u32(&link, content, pos, length, SRE_LITTLE);
-
-    if (link == 0)
-        memset(import, 0, sizeof(image_import_by_name));
-
-    else if (link % 2 == 0)
-    {
-        new_pos = link;
-
-        result = read_u16(&import->hint, content, &new_pos, length, SRE_LITTLE);
-
-        import->name = (char *)calloc(1, sizeof(char));
-
-        for (i = 0; result; i++)
-        {
-            result = read_u8((uint8_t *)&import->name[i], content, &new_pos, length);
-
-            if (import->name[i] == '\0')
-                break;
-
-            import->name = (char *)realloc(import->name, (i + 2) * sizeof(char));
+    result = true;
 
-        }
+    content = G_KNOWN_FORMAT(format)->content;
 
-    }
-    else /* TODO */;
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->original_first_thunk);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->time_date_stamp);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->forwarder_chain);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->module_name);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->first_thunk);
 
     return result;
 
diff --git a/plugins/pe/pe-int.h b/plugins/pe/pe-int.h
index 14a6007..ebcf3f0 100644
--- a/plugins/pe/pe-int.h
+++ b/plugins/pe/pe-int.h
@@ -21,17 +21,15 @@
  */
 
 
-#ifndef _FORMAT_PE_E_PE_INT_H
-#define _FORMAT_PE_E_PE_INT_H
-
-
-#include "pe.h"
-#include "pe_def.h"
-#include "../executable-int.h"
+#ifndef _PLUGINS_PE_PE_INT_H
+#define _PLUGINS_PE_PE_INT_H
 
 
+#include <format/executable-int.h>
 
 
+#include "pe_def.h"
+#include "format.h"
 
 
 
@@ -41,9 +39,12 @@ struct _GPeFormat
     GExeFormat parent;                      /* A laisser en premier        */
 
     image_dos_header dos_header;            /* En-tête DOS                 */
+    mrange_t rich_header;                   /* En-tête enrichi             */
     image_nt_headers nt_headers;            /* En-tête Windows             */
 
-    off_t section_offset;                   /* Début des sections          */
+    image_section_header *sections;         /* Liste des sections          */
+
+    bool loaded;                            /* Détection partielle menée   */
 
 };
 
@@ -55,30 +56,27 @@ struct _GPeFormatClass
 };
 
 
+/* Procède à la lecture d'un en-tête de programme DOS. */
+bool read_dos_image_header(const GPeFormat *, image_dos_header *);
 
+/* Procède à la lecture d'un en-tête de programme PE (1). */
+bool read_pe_file_header(const GPeFormat *, vmpa2t *, image_file_header *);
 
+/* Procède à la lecture d'un en-tête de programme PE (2). */
+bool read_pe_optional_header(const GPeFormat *, vmpa2t *, image_optional_header *);
 
-/* Procède à la lecture d'une en-tête de programme DOS. */
-bool read_dos_image_header(const GPeFormat *, off_t *, image_dos_header *);
-
-/* Procède à la lecture d'une en-tête de programme PE (1). */
-bool read_pe_file_header(const GPeFormat *, off_t *, image_file_header *);
+/* Procède à la lecture d'un en-tête de programme PE. */
+bool read_pe_nt_header(const GPeFormat *, image_nt_headers *, vmpa2t *);
 
-/* Procède à la lecture d'une en-tête de programme PE (2). */
-bool read_pe_optional_header(const GPeFormat *, off_t *, image_optional_header *);
+/* Procède à la lecture d'un en-tête de section PE. */
+bool read_pe_image_section_header(const GPeFormat *, vmpa2t *, image_section_header *);
 
-/* Procède à la lecture d'une en-tête de programme PE. */
-bool read_pe_nt_header(const GPeFormat *, off_t *, image_nt_headers *);
-
-/* Procède à la lecture d'une en-tête de section PE. */
-bool read_pe_image_section_header(const GPeFormat *, off_t *, image_section_header *);
+/* Procède à la lecture d'un répertoire d'exportations. */
+bool read_pe_image_export_directory(const GPeFormat *, vmpa2t *, image_export_directory *);
 
 /* Procède à la lecture d'un répertoire de programme PE. */
-bool read_pe_image_import_descriptor(const GPeFormat *, off_t *, image_import_descriptor *);
-
-/* Procède à la lecture d'une fonction importée par son nom. */
-bool read_pe_image_import_by_name(const GPeFormat *, off_t *, image_import_by_name *);
+bool read_pe_image_import_descriptor(const GPeFormat *, vmpa2t *, image_import_descriptor *);
 
 
 
-#endif  /* _FORMAT_PE_E_PE_INT_H */
+#endif  /* _PLUGINS_PE_PE_INT_H */
diff --git a/plugins/pe/pe_def.h b/plugins/pe/pe_def.h
index 62d8afc..62b4607 100644
--- a/plugins/pe/pe_def.h
+++ b/plugins/pe/pe_def.h
@@ -21,13 +21,20 @@
  */
 
 
-#ifndef _FORMAT_PE_PE_DEF_H
-#define _FORMAT_PE_PE_DEF_H
+#ifndef _PLUGINS_PE_PE_DEF_H
+#define _PLUGINS_PE_PE_DEF_H
 
 
 #include <stdint.h>
 
 
+/**
+ * Références :
+ *
+ *  - https://fr.wikipedia.org/wiki/Portable_Executable#En-tête_MZ_sous_MS-DOS
+ *  - https://www.nirsoft.net/kernel_struct/vista/IMAGE_DOS_HEADER.html
+ *
+ */
 
 
 
@@ -59,10 +66,44 @@ typedef struct _image_dos_header
 
 } image_dos_header;
 
-/* Archtecture supportées */
-#define IMAGE_FILE_MACHINE_I386     0x014c  /* x86                         */
-#define IMAGE_FILE_MACHINE_IA64     0x0200  /* Intel IPF                   */
-#define IMAGE_FILE_MACHINE_AMD64    0x8664  /* x64                         */
+/* Archtectures supportées */
+
+/**
+ * Cf. https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants
+ */
+
+#define IMAGE_FILE_MACHINE_UNKNOWN      0x0000  /* Unknown */
+#define IMAGE_FILE_MACHINE_TARGET_HOST  0x0001  /* Interacts with the host and not a WOW64 guest */
+#define IMAGE_FILE_MACHINE_I386         0x014c  /* Intel 386 */
+#define IMAGE_FILE_MACHINE_R3000        0x0162  /* MIPS little-endian, 0x160 big-endian */
+#define IMAGE_FILE_MACHINE_R4000        0x0166  /* MIPS little-endian */
+#define IMAGE_FILE_MACHINE_R10000       0x0168  /* MIPS little-endian */
+#define IMAGE_FILE_MACHINE_WCEMIPSV2    0x0169  /* MIPS little-endian WCE v2 */
+#define IMAGE_FILE_MACHINE_ALPHA        0x0184  /* Alpha_AXP */
+#define IMAGE_FILE_MACHINE_SH3          0x01a2  /* SH3 little-endian */
+#define IMAGE_FILE_MACHINE_SH3DSP       0x01a3  /* SH3DSP */
+#define IMAGE_FILE_MACHINE_SH3E         0x01a4  /* SH3E little-endian */
+#define IMAGE_FILE_MACHINE_SH4          0x01a6  /* SH4 little-endian */
+#define IMAGE_FILE_MACHINE_SH5          0x01a8  /* SH5 */
+#define IMAGE_FILE_MACHINE_ARM          0x01c0  /* ARM Little-Endian */
+#define IMAGE_FILE_MACHINE_THUMB        0x01c2  /* ARM Thumb/Thumb-2 Little-Endian */
+#define IMAGE_FILE_MACHINE_ARMNT        0x01c4  /* ARM Thumb-2 Little-Endian */
+#define IMAGE_FILE_MACHINE_AM33         0x01d3  /* TAM33BD */
+#define IMAGE_FILE_MACHINE_POWERPC      0x01f0  /* IBM PowerPC Little-Endian */
+#define IMAGE_FILE_MACHINE_POWERPCFP    0x01f1  /* POWERPCFP */
+#define IMAGE_FILE_MACHINE_IA64         0x0200  /* Intel 64 */
+#define IMAGE_FILE_MACHINE_MIPS16       0x0266  /* MIPS */
+#define IMAGE_FILE_MACHINE_ALPHA64      0x0284  /* ALPHA64 */
+/*#define IMAGE_FILE_MACHINE_AXP64        0x0284*/ /* AXP64 */
+#define IMAGE_FILE_MACHINE_MIPSFPU      0x0366  /* MIPS */
+#define IMAGE_FILE_MACHINE_MIPSFPU16    0x0466  /* MIPS */
+#define IMAGE_FILE_MACHINE_TRICORE      0x0520  /*Infineon */
+#define IMAGE_FILE_MACHINE_CEF          0x0cef  /* CEF */
+#define IMAGE_FILE_MACHINE_EBC          0x0ebc  /* EFI Byte Code */
+#define IMAGE_FILE_MACHINE_AMD64        0x8664  /* AMD64 (K8) */
+#define IMAGE_FILE_MACHINE_M32R         0x9041  /* M32R little-endian */
+#define IMAGE_FILE_MACHINE_ARM64        0xaa64  /* ARM64 Little-Endian */
+#define IMAGE_FILE_MACHINE_CEE          0xc0ee  /* CEE */
 
 /* Caractéristiques de l'image */
 #define IMAGE_FILE_RELOCS_STRIPPED      0x0001  /* Pas de relocalisation   */
@@ -96,18 +137,14 @@ typedef struct _image_file_header
 
 
 
-
-
-
-
-
-
-
 /* -------------------------- EN-TETE EVOLUEE DU FORMAT PE -------------------------- */
 
 
 /**
- * cf. http://msdn.microsoft.com/en-us/library/ms680305(VS.85).aspx
+ * Références :
+ *
+ *  - http://msdn.microsoft.com/en-us/library/ms680305(VS.85).aspx
+ *  - https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32
  */
 
 /* Zone de données Windows */
@@ -144,7 +181,8 @@ typedef struct _image_data_directory
 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
 
 /* Seconde en-tête, optionnelle */
-typedef struct _image_optional_header
+
+typedef struct _image_optional_header_32
 {
     uint16_t magic;                         /* Type de binaire manipulé    */
     uint8_t major_linker_version;           /* Version majeure du linker   */
@@ -178,8 +216,54 @@ typedef struct _image_optional_header
     uint32_t number_of_rva_and_sizes;       /* Nombre d'entrées suivantes  */
     image_data_directory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
 
+} image_optional_header_32;
+
+typedef struct _image_optional_header_64
+{
+
+    uint16_t magic;                         /* Type de binaire manipulé    */
+    uint8_t major_linker_version;           /* Version majeure du linker   */
+    uint8_t minor_linker_version;           /* Version mineure du linker   */
+    uint32_t size_of_code;                  /* Taille de tout le code      */
+    uint32_t size_of_initialized_data;      /* Taille des données init.    */
+    uint32_t size_of_uninitialized_data;    /* Taille des données non init.*/
+    uint32_t address_of_entry_point;        /* Point d'entrée pour un exe. */
+    uint32_t base_of_code;                  /* Adresse relative du code    */
+    uint64_t image_base;                    /* Adresse souhaitée en mémoire*/
+    uint32_t section_alignment;             /* Alignement des sections     */
+    uint32_t file_alignment;                /* Alignement des données      */
+    uint16_t major_operating_system_version;/* Numéro majeur d'OS requis   */
+    uint16_t minor_operating_system_version;/* Numéro mineur d'OS requis   */
+    uint16_t major_image_version;           /* Numéro majeur du binaire    */
+    uint16_t minor_image_version;           /* Numéro mineur du binaire    */
+    uint16_t major_subsystem_version;       /* Numéro majeur du sous-sys.  */
+    uint16_t minor_subsystem_version;       /* Numéro mineur du sous-sys.  */
+    uint32_t win32_version_value;           /* Réservé (-> 0)              */
+    uint32_t size_of_image;                 /* Taille de l'image           */
+    uint32_t size_of_headers;               /* Taille de l'en-tête         */
+    uint32_t checksum;                      /* Somme de contrôle           */
+    uint16_t subsystem;                     /* Sous-système visé           */
+    uint16_t dll_characteristics;           /* Propriétés de la DLL        */
+    uint64_t size_of_stack_reserve;         /* Taille de pile reservée     */
+    uint64_t size_of_stack_commit;          /* Taille de pile au démarrage */
+    uint64_t size_of_heap_reserve;          /* Taille de tas reservée      */
+    uint64_t size_of_heap_commit;           /* Taille de tas au démarrage  */
+    uint32_t loader_flags;                  /* Champ obslète               */
+    uint32_t number_of_rva_and_sizes;       /* Nombre d'entrées suivantes  */
+    image_data_directory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+
+} image_optional_header_64;
+
+typedef union _image_optional_header
+{
+    image_optional_header_32 header_32;     /* Version 32 bits             */
+    image_optional_header_64 header_64;     /* Version 64 bits             */
+
 } image_optional_header;
 
+
+
+
 /* Valeurs pour le champ 'magic' */
 #define IMAGE_NT_OPTIONAL_HDR32_MAGIC   0x10b   /* Exécutable 32 bits      */
 #define IMAGE_NT_OPTIONAL_HDR64_MAGIC   0x20b   /* Exécutable 64 bits      */
@@ -246,10 +330,11 @@ typedef struct _image_section_header
     {
         uint32_t physical_address;          /* Adresse physique            */
         uint32_t virtual_size;              /* Taille en mémoire           */
+
     } misc;
 
     uint32_t virtual_address;               /* Adresse en mémoire          */
-    uint32_t size_of_raw_data;              /* Taille de données non init. */
+    uint32_t size_of_raw_data;              /* Taille de données définies  */
     uint32_t pointer_to_raw_data;           /* Position de ces données     */
     uint32_t pointer_to_relocations;        /* Position des relocalisations*/
     uint32_t pointer_to_line_numbers;       /* Position de numéros de ligne*/
@@ -308,10 +393,37 @@ typedef struct _image_section_header
 
 /* --------------------------- IDENTIFICATION DE SYMBOLES --------------------------- */
 
+
 /**
- * cf. http://msdn.microsoft.com/en-us/library/ms809762.aspx
- *     http://sandsprite.com/CodeStuff/Understanding_imports.html
- *     http://olance.developpez.com/articles/windows/pe-iczelion/import-table/
+ * https://docs.microsoft.com/en-us/previous-versions/ms809762(v=msdn.10)?redirectedfrom=MSDN#pe-file-exports
+ * https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-edata-section-image-only
+ */
+
+/* Répertoire des importations */
+typedef struct _image_export_directory
+{
+    uint32_t characteristics;               /* Zéro !?                     */
+    uint32_t time_date_stamp;               /* Date de création du fichier */
+    uint16_t major_version;                 /* Numéro majeur de version    */
+    uint16_t minor_version;                 /* Numéro lineur de version    */
+    uint32_t name;                          /* RVA du nom de la DLL visée  */
+    uint32_t base;                          /* Départ des ordinaux listés  */
+    uint32_t number_of_functions;           /* Taille de liste de fonctions*/
+    uint32_t number_of_names;               /* Taille de liste de noms     */
+    uint32_t address_of_functions;          /* Liste de RVA de fonctions   */
+    uint32_t address_of_names;              /* Liste de RVA de noms        */
+    uint32_t address_of_name_ordinals;      /* Liste de RVA d'ordinaux     */
+
+} image_export_directory;
+
+
+/**
+ * http://msdn.microsoft.com/en-us/library/ms809762.aspx
+ * http://sandsprite.com/CodeStuff/Understanding_imports.html
+ * http://olance.developpez.com/articles/windows/pe-iczelion/import-table/
+ *
+ * https://docs.microsoft.com/en-us/previous-versions/ms809762(v=msdn.10)?redirectedfrom=MSDN#pe-file-imports
+ * https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
  */
 
 /* Point de départ de la chaîne des importations */
@@ -327,17 +439,4 @@ typedef struct _image_import_descriptor
 
 
 
-
-/* Désignation de fonction importée */
-typedef struct _image_import_by_name
-{
-    uint16_t hint;
-    char *name;
-
-} image_import_by_name;
-
-
-
-
-
-#endif  /* _FORMAT_PE_PE_DEF_H */
+#endif  /* _PLUGINS_PE_PE_DEF_H */
diff --git a/plugins/pe/python/Makefile.am b/plugins/pe/python/Makefile.am
new file mode 100644
index 0000000..18634a3
--- /dev/null
+++ b/plugins/pe/python/Makefile.am
@@ -0,0 +1,23 @@
+
+noinst_LTLIBRARIES = libpepython.la
+
+libpepython_la_SOURCES =				\
+	constants.h constants.c				\
+	format.h format.c					\
+	module.h module.c					\
+	routine.h routine.c					\
+	translate.h translate.c
+
+
+libpepython_la_LDFLAGS = 
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpepython_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pe/python/constants.c b/plugins/pe/python/constants.c
new file mode 100644
index 0000000..9b4942d
--- /dev/null
+++ b/plugins/pe/python/constants.c
@@ -0,0 +1,143 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - équivalent Python partiel du fichier "plugins/pe/pe_def.h"
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "constants.h"
+
+
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../pe_def.h"
+#include "../routine.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type dont le dictionnaire est à compléter.            *
+*                                                                             *
+*  Description : Définit les constantes pour le format PE.                    *
+*                                                                             *
+*  Retour      : true en cas de succès de l'opération, false sinon.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool define_python_pe_format_constants(PyTypeObject *type)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *values;                       /* Groupe de valeurs à établir */
+
+    result = true;
+
+    /**
+     * Indices des répertoires PE
+     */
+
+    values = PyDict_New();
+
+    if (result) result = add_const_to_group(values, "EXPORT", IMAGE_DIRECTORY_ENTRY_EXPORT);
+    if (result) result = add_const_to_group(values, "IMPORT", IMAGE_DIRECTORY_ENTRY_IMPORT);
+    if (result) result = add_const_to_group(values, "RESOURCE", IMAGE_DIRECTORY_ENTRY_RESOURCE);
+    if (result) result = add_const_to_group(values, "EXCEPTION", IMAGE_DIRECTORY_ENTRY_EXCEPTION);
+    if (result) result = add_const_to_group(values, "SECURITY", IMAGE_DIRECTORY_ENTRY_SECURITY);
+    if (result) result = add_const_to_group(values, "BASERELOC", IMAGE_DIRECTORY_ENTRY_BASERELOC);
+    if (result) result = add_const_to_group(values, "DEBUG", IMAGE_DIRECTORY_ENTRY_DEBUG);
+    if (result) result = add_const_to_group(values, "ARCHITECTURE", IMAGE_DIRECTORY_ENTRY_ARCHITECTURE);
+    if (result) result = add_const_to_group(values, "GLOBALPTR", IMAGE_DIRECTORY_ENTRY_GLOBALPTR);
+    if (result) result = add_const_to_group(values, "TLS", IMAGE_DIRECTORY_ENTRY_TLS);
+    if (result) result = add_const_to_group(values, "LOAD_CONFIG", IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
+    if (result) result = add_const_to_group(values, "BOUND_IMPORT", IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT);
+    if (result) result = add_const_to_group(values, "IAT", IMAGE_DIRECTORY_ENTRY_IAT);
+    if (result) result = add_const_to_group(values, "DELAY_IMPORT", IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
+    if (result) result = add_const_to_group(values, "COM_DESCRIPTOR", IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
+
+    if (!result)
+    {
+        Py_DECREF(values);
+        goto exit;
+    }
+
+    result = attach_constants_group_to_type(type, false, "ImageDirectoryEntry", values,
+                                            "Index number for a kind of data directory entry.");
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type dont le dictionnaire est à compléter.            *
+*                                                                             *
+*  Description : Définit les constantes pour les routines du format PE.       *
+*                                                                             *
+*  Retour      : true en cas de succès de l'opération, false sinon.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool define_python_pe_exported_routine_constants(PyTypeObject *type)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *values;                       /* Groupe de valeurs à établir */
+
+    result = true;
+
+    values = PyDict_New();
+
+    if (result) result = add_const_to_group(values, "HAS_ORDINAL", PSF_HAS_ORDINAL);
+    if (result) result = add_const_to_group(values, "FORWARDED", PSF_FORWARDED);
+
+    if (!result)
+    {
+        Py_DECREF(values);
+        goto exit;
+    }
+
+    result = attach_constants_group_to_type(type, true, "PeSymbolFlag", values,
+                                            "Extra indications for exported PE routine symbols.");
+
+    values = PyDict_New();
+
+    if (result) result = add_const_to_group(values, "UNDEF_PE_ORDINAL", UNDEF_PE_ORDINAL);
+
+    if (!result)
+    {
+        Py_DECREF(values);
+        goto exit;
+    }
+
+    result = attach_constants_group_to_type(type, false, "OrdinalValue", values,
+                                            "Extra value for exported PE routine ordinals.");
+
+ exit:
+
+    return result;
+
+}
diff --git a/plugins/pe/python/constants.h b/plugins/pe/python/constants.h
new file mode 100644
index 0000000..25b0adb
--- /dev/null
+++ b/plugins/pe/python/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour l'équivalent Python partiel du fichier "plugins/pe/pe_def.h"
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_CONSTANTS_H
+#define _PLUGINS_PE_PYTHON_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes pour le format PE. */
+bool define_python_pe_format_constants(PyTypeObject *);
+
+/* Définit les constantes pour les routines du format PE. */
+bool define_python_pe_exported_routine_constants(PyTypeObject *);
+
+
+
+#endif  /* _PLUGINS_PE_PYTHON_CONSTANTS_H */
diff --git a/plugins/pe/python/format.c b/plugins/pe/python/format.c
new file mode 100644
index 0000000..d295da4
--- /dev/null
+++ b/plugins/pe/python/format.c
@@ -0,0 +1,595 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * format.c - équivalent Python du fichier "plugins/pe/format.c"
+ *
+ * Copyright (C) 2017-2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "format.h"
+
+
+#include <pygobject.h>
+
+
+#include <format/known.h>
+#include <plugins/dt.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/format/executable.h>
+
+
+#include "constants.h"
+#include "translate.h"
+#include "../format.h"
+#include "../rich.h"
+
+
+
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_pe_format_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_pe_format_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/* ------------------------------ DEFINITION DE FORMAT ------------------------------ */
+
+
+/* Présente l'en-tête MS-DOS du format chargé. */
+static PyObject *py_pe_format_get_dos_header(PyObject *, void *);
+
+/* Offre un raccourci vers les répertoires du format PE. */
+static PyObject *py_pe_format_get_directories(PyObject *, void *);
+
+/* Présente l'en-tête enrichi du format chargé. */
+static PyObject *py_pe_format_get_rich_header(PyObject *, void *);
+
+/* Présente l'empreinte d'un en-tête enrichi du format chargé. */
+static PyObject *py_pe_format_get_rich_header_checksum(PyObject *, void *);
+
+/* Présente les identifiants contenues dans l'en-tête enrichi. */
+static PyObject *py_pe_format_get_comp_ids(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          GLUE POUR CREATION DEPUIS PYTHON                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type du nouvel objet à mettre en place.               *
+*                args = éventuelle liste d'arguments.                         *
+*                kwds = éventuel dictionnaire de valeurs mises à disposition. *
+*                                                                             *
+*  Description : Accompagne la création d'une instance dérivée en Python.     *
+*                                                                             *
+*  Retour      : Nouvel objet Python mis en place ou NULL en cas d'échec.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyObject *result;                       /* Objet à retourner           */
+    PyTypeObject *base;                     /* Type de base à dériver      */
+    bool first_time;                        /* Evite les multiples passages*/
+    GType gtype;                            /* Nouveau type de processeur  */
+    bool status;                            /* Bilan d'un enregistrement   */
+
+    /* Validations diverses */
+
+    base = get_python_pe_format_type();
+
+    if (type == base)
+        goto simple_way;
+
+    /* Mise en place d'un type dédié */
+
+    first_time = (g_type_from_name(type->tp_name) == 0);
+
+    gtype = build_dynamic_type(G_TYPE_PE_FORMAT, type->tp_name, NULL, NULL, NULL);
+
+    if (first_time)
+    {
+        status = register_class_for_dynamic_pygobject(gtype, type, base);
+
+        if (!status)
+        {
+            result = NULL;
+            goto exit;
+        }
+
+    }
+
+    /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+ simple_way:
+
+    result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
+*                                                                             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
+*                                                                             *
+*  Retour      : 0.                                                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_pe_format_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    GBinContent *content;                   /* Instance GLib du contenu    */
+    int ret;                                /* Bilan de lecture des args.  */
+    GPeFormat *format;                      /* Création GLib à transmettre */
+
+#define PE_FORMAT_DOC                                                       \
+    "The PeFormat class handles executables with a Portable Executable"     \
+    " structure.\n"                                                         \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    PeFormat(content)"                                                 \
+    "\n"                                                                    \
+    "Where content points to data as a pychrysalide.analysis.BinContent"    \
+    " instance."
+
+    /* Récupération des paramètres */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
+    if (!ret) return -1;
+
+    /* Initialisation d'un objet GLib */
+
+    ret = forward_pygobjet_init(self);
+    if (ret == -1) return -1;
+
+    /* Eléments de base */
+
+    format = G_PE_FORMAT(pygobject_get(self));
+
+    g_known_format_set_content(G_KNOWN_FORMAT(format), content);
+
+    return 0;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                                DEFINITION DE FORMAT                                */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = format en place à consulter.                       *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Présente l'en-tête MS-DOS du format chargé.                  *
+*                                                                             *
+*  Retour      : Structure Python créée pour l'occasion.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_dos_header(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvaille à retourner      */
+    GPeFormat *format;                      /* Version GLib du format      */
+
+#define PE_FORMAT_DOS_HEADER_ATTRIB PYTHON_GET_DEF_FULL         \
+(                                                               \
+    dos_header, py_pe_format,                                   \
+    "MS-DOS header of the file format.\n"                       \
+    "\n"                                                        \
+    "This property is a pychrysalide.StructObject instance."    \
+    "\n"                                                        \
+    "The provided information is composed of the following"     \
+    " properties :\n"                                           \
+    "\n"                                                        \
+    "* e_magic;\n"                                              \
+    "* e_cblp;\n"                                               \
+    "* e_cp;\n"                                                 \
+    "* e_crlc;\n"                                               \
+    "* e_cparhdr;\n"                                            \
+    "* e_minalloc;\n"                                           \
+    "* e_maxalloc;\n"                                           \
+    "* e_ss;\n"                                                 \
+    "* e_sp;\n"                                                 \
+    "* e_csum;\n"                                               \
+    "* e_ip;\n"                                                 \
+    "* e_cs;\n"                                                 \
+    "* e_lfarlc;\n"                                             \
+    "* e_ovno;\n"                                               \
+    "* e_res;\n"                                                \
+    "* e_oemid;\n"                                              \
+    "* e_oeminfo;\n"                                            \
+    "* e_res2;\n"                                               \
+    "* e_lfanew."                                               \
+)
+
+    format = G_PE_FORMAT(pygobject_get(self));
+
+    result = translate_pe_dos_header_to_python(format, g_pe_format_get_dos_header(format));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = format en place à consulter.                       *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Offre un raccourci vers les répertoires du format PE.        *
+*                                                                             *
+*  Retour      : Structure Python créée pour l'occasion.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_directories(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvaille à retourner      */
+    GPeFormat *format;                      /* Version GLib du format      */
+    size_t count;                           /* Quantité de répertoires     */
+    const image_data_directory *directories; /* Répertoires à exporter     */
+    size_t i;                               /* Boucle de parcours          */
+    PyObject *item;                         /* Elément de tableau          */
+    int ret;                                /* Bilan d'une mise en place   */
+
+#define PE_FORMAT_DIRECTORIES_ATTRIB PYTHON_GET_DEF_FULL            \
+(                                                                   \
+    directories, py_pe_format,                                      \
+    "Shortcut to the PE format directories.\n"                      \
+    "\n"                                                            \
+    "This property is a pychrysalide.StructObject instance and"     \
+    " can also be access trough the"                                \
+    " *self.nt_headers.data_directory* attribute.\n"                \
+    "\n"                                                            \
+    "Each returned item is composed of the following properties :\n"\
+    "\n"                                                            \
+    "* virtual_address;\n"                                          \
+    "* size."                                                       \
+)
+
+    format = G_PE_FORMAT(pygobject_get(self));
+
+    directories = g_pe_format_get_directories(format, &count);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+    {
+        item = translate_pe_image_data_directory_to_python(format, directories + i);
+
+        ret = PyTuple_SetItem(result, i, item);
+
+        if (ret != 0)
+        {
+            Py_DECREF(result);
+            result = NULL;
+            break;
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = format en place à consulter.                       *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Présente l'en-tête enrichi du format chargé.                 *
+*                                                                             *
+*  Retour      : Tableau de valeurs brutes d'information.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_rich_header(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvaille à retourner      */
+    GPeFormat *format;                      /* Version GLib du format      */
+    size_t count;                           /* Quantité de valeurs obtenues*/
+    uint64_t *values;                       /* Valeurs brutes à transcrire */
+    size_t i;                               /* Boucle de parcours          */
+
+#define PE_FORMAT_RICH_HEADER_ATTRIB PYTHON_GET_DEF_FULL    \
+(                                                           \
+    rich_header, py_pe_format,                              \
+    "Raw values from the Rich header of the file format.\n" \
+    "\n"                                                    \
+    "This property is a tuple of 64-bit values or an empty" \
+    " tuple if no Rich header exists in the PE file."       \
+)
+
+    format = G_PE_FORMAT(pygobject_get(self));
+
+    values = g_pe_format_get_rich_header(format, &count);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+        PyTuple_SetItem(result, i, PyLong_FromUnsignedLongLong(values[i]));
+
+    if (values != NULL)
+        free(values);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = format en place à consulter.                       *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Présente l'empreinte d'un en-tête enrichi du format chargé.  *
+*                                                                             *
+*  Retour      : Valeur de l'empreinte ou None en cas d'erreur.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_rich_header_checksum(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvaille à retourner      */
+    GPeFormat *format;                      /* Version GLib du format      */
+    uint32_t checksum;                      /* Valeur à transcrire         */
+    bool status;                            /* Validité de cette valeur    */
+
+#define PE_FORMAT_RICH_HEADER_CHECKSUM_ATTRIB PYTHON_GET_DEF_FULL   \
+(                                                                   \
+    rich_header_checksum, py_pe_format,                             \
+    "Checksum used as XOR value for the Rich header of the file"    \
+    " format.\n"                                                    \
+    "\n"                                                            \
+    "This property is a 32-bit integer value."                      \
+)
+
+    format = G_PE_FORMAT(pygobject_get(self));
+
+    status = g_pe_format_get_rich_header_checksum(format, &checksum);
+
+    if (status)
+        result = PyLong_FromUnsignedLong(checksum);
+
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = format en place à consulter.                       *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Présente les identifiants contenues dans l'en-tête enrichi.  *
+*                                                                             *
+*  Retour      : Tableau de valeurs raffinées d'information.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_comp_ids(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvaille à retourner      */
+    GPeFormat *format;                      /* Version GLib du format      */
+    size_t count;                           /* Quantité de valeurs obtenues*/
+    comp_id_t *ids;                         /* Valeurs raffinées à émettre */
+    size_t i;                               /* Boucle de parcours          */
+
+#define PE_FORMAT_COMP_IDS_ATTRIB PYTHON_GET_DEF_FULL               \
+(                                                                   \
+    comp_ids, py_pe_format,                                         \
+    "Compiler identifiers carried by the Rich header of the file"   \
+    " format.\n"                                                    \
+    "\n"                                                            \
+    "This property is a tuple of"                                   \
+    " pychrysalide.StructObject items or an empty tuple if no"      \
+    " information is found.\n"                                      \
+    "\n"                                                            \
+    "Each item contains the the following properties :\n"           \
+    "\n"                                                            \
+    "* minor_cv;\n"                                                 \
+    "* prod_id;\n"                                                  \
+    "* count."                                                      \
+)
+
+    format = G_PE_FORMAT(pygobject_get(self));
+
+    ids = g_pe_format_get_comp_ids(format, &count);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+        PyTuple_SetItem(result, i, translate_pe_comp_id_to_python(format, &ids[i]));
+
+    if (ids != NULL)
+        free(ids);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_pe_format_type(void)
+{
+    static PyMethodDef py_pe_format_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_pe_format_getseters[] = {
+        PE_FORMAT_DOS_HEADER_ATTRIB,
+        PE_FORMAT_DIRECTORIES_ATTRIB,
+        PE_FORMAT_RICH_HEADER_ATTRIB,
+        PE_FORMAT_RICH_HEADER_CHECKSUM_ATTRIB,
+        PE_FORMAT_COMP_IDS_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_pe_format_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.format.pe.PeFormat",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = PE_FORMAT_DOC,
+
+        .tp_methods     = py_pe_format_methods,
+        .tp_getset      = py_pe_format_getseters,
+
+        .tp_init        = py_pe_format_init,
+        .tp_new         = py_pe_format_new,
+
+    };
+
+    return &py_pe_format_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.format.pe.PeFormat'.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_pe_format(PyObject *module)
+{
+    PyTypeObject *type;                     /* Type Python 'PeFormat'      */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_pe_format_type();
+
+    dict = PyModule_GetDict(module);
+
+    if (!register_class_for_pygobject(dict, G_TYPE_PE_FORMAT, type, get_python_executable_format_type()))
+        return false;
+
+    if (!define_python_pe_format_constants(type))
+        return false;
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en format PE.                             *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_pe_format(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_format_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE format");
+            break;
+
+        case 1:
+            *((GPeFormat **)dst) = G_PE_FORMAT(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pe/python/format.h b/plugins/pe/python/format.h
new file mode 100644
index 0000000..4f52a61
--- /dev/null
+++ b/plugins/pe/python/format.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * format.h - prototypes pour l'équivalent Python du fichier "plugins/pe/format.h"
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_FORMAT_H
+#define _PLUGINS_PE_PYTHON_FORMAT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_pe_format_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.pe.PeFormat'. */
+bool register_python_pe_format(PyObject *);
+
+/* Tente de convertir en format PE. */
+int convert_to_pe_format(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PE_PYTHON_FORMAT_H */
diff --git a/plugins/pe/python/module.c b/plugins/pe/python/module.c
new file mode 100644
index 0000000..93b1337
--- /dev/null
+++ b/plugins/pe/python/module.c
@@ -0,0 +1,93 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire pe en tant que module
+ *
+ * Copyright (C) 2017-2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "format.h"
+#include "routine.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Ajoute le module 'format.pe' au module Python.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool add_format_pe_module_to_python_module(void)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *super;                        /* Module à compléter          */
+    PyObject *module;                       /* Sous-module mis en place    */
+
+#define PYCHRYSALIDE_FORMAT_PE_MODULE_DOC                                   \
+    "This module provides support for the Portable Executable file format"  \
+    " defined by Microsoft.\n"                                              \
+    "\n"                                                                    \
+    "The specification for this format can be found at:"                    \
+    "\n"                                                                    \
+    "* https://web.archive.org/web/20081208121446/http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx"
+
+    static PyModuleDef py_chrysalide_pe_module = {
+
+        .m_base = PyModuleDef_HEAD_INIT,
+
+        .m_name = "pychrysalide.format.pe",
+        .m_doc = PYCHRYSALIDE_FORMAT_PE_MODULE_DOC,
+
+        .m_size = -1,
+
+    };
+
+    result = false;
+
+    super = get_access_to_python_module("pychrysalide.format");
+
+    module = build_python_module(super, &py_chrysalide_pe_module);
+
+    result = (module != NULL);
+
+    if (result) result = register_python_pe_format(module);
+    if (result) result = register_python_pe_exported_routine(module);
+    if (result) result = register_python_pe_imported_routine(module);
+
+    assert(result);
+
+    return result;
+
+}
diff --git a/plugins/pe/python/module.h b/plugins/pe/python/module.h
new file mode 100644
index 0000000..9e9b33a
--- /dev/null
+++ b/plugins/pe/python/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire pe en tant que module
+ *
+ * Copyright (C) 2017-2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_MODULE_H
+#define _PLUGINS_PE_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'format.pe' au module Python. */
+bool add_format_pe_module_to_python_module(void);
+
+
+
+#endif  /* _PLUGINS_PE_PYTHON_MODULE_H */
diff --git a/plugins/pe/python/routine.c b/plugins/pe/python/routine.c
new file mode 100644
index 0000000..89075ea
--- /dev/null
+++ b/plugins/pe/python/routine.c
@@ -0,0 +1,472 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * routine.c - équivalent Python du fichier "plugins/pe/routine.c"
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "routine.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/routine.h>
+
+
+#include "constants.h"
+#include "../routine.h"
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */
+
+
+#define PE_EXPORTED_ROUTINE_DOC                                     \
+    "The PeExportedRoutine is a definition of a binary routine"     \
+    " exported for other PE file."
+
+
+/* Fournit l'indice de la routine dans un fichier PE. */
+static PyObject *py_pe_exported_routine_get_ordinal(PyObject *, void *);
+
+/* Définit l'indice de la routine dans un fichier PE. */
+static int py_pe_exported_routine_set_ordinal(PyObject *, PyObject *, void *);
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */
+
+
+#define PE_IMPORTED_ROUTINE_DOC                                     \
+    "The PeImportedRoutine is a definition of a binary routine"     \
+    " imported from other PE file symbol."
+
+
+/* Fournit le fichier DLL visé par une importation de format PE. */
+static PyObject *py_pe_imported_routine_get_library(PyObject *, void *);
+
+/* Définit le fichier DLL visé par une importation de format PE. */
+static int py_pe_imported_routine_set_library(PyObject *, PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          SYMBOLES D'UN FORMAT PE EXPORTES                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit l'indice de la routine dans un fichier PE.           *
+*                                                                             *
+*  Retour      : Numéro de la routine.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_exported_routine_get_ordinal(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GPeExportedRoutine *routine;            /* Version native              */
+    uint16_t ordinal;                       /* Valeur native de l'ordinal  */
+
+#define PE_EXPORTED_ROUTINE_ORDINAL_ATTRIB PYTHON_GETSET_DEF_FULL       \
+(                                                                       \
+    ordinal, py_pe_exported_routine,                                    \
+    "Ordinal number linked to the symbol.\n"                            \
+    "\n"                                                                \
+    "The returned integer value is valid only if"                       \
+    " the pychrysalide.format.pe.PeRoutine.PeSymbolFlag.HAS_ORDINAL"    \
+    " bit is set in the symbol flags.\n"                                \
+    "\n"                                                                \
+    "This bit is automatically set when the value is defined."          \
+)
+
+    routine = G_PE_EXPORTED_ROUTINE(pygobject_get(self));
+
+    ordinal = g_pe_exported_routine_get_ordinal(routine);
+
+    //result = cast_with_constants_group_from_type(get_python_pe_exported_routine_type(), "OrdinalValue", ordinal);
+
+    result = PyLong_FromUnsignedLong(ordinal);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Définit l'indice de la routine dans un fichier PE.           *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_pe_exported_routine_set_ordinal(PyObject *self, PyObject *value, void *closure)
+{
+    int ret;                                /* Bilan d'analyse             */
+    GPeExportedRoutine *routine;            /* Version native              */
+    uint16_t ordinal;                       /* Valeur native de l'ordinal  */
+
+    ret = PyObject_IsInstance(value, (PyObject *)&PyLong_Type);
+    if (!ret) return -1;
+
+    routine = G_PE_EXPORTED_ROUTINE(pygobject_get(self));
+
+    ordinal = PyLong_AsUnsignedLong(value);
+
+    g_pe_exported_routine_set_ordinal(routine, ordinal);
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_pe_exported_routine_type(void)
+{
+    static PyMethodDef py_pe_exported_routine_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_pe_exported_routine_getseters[] = {
+        PE_EXPORTED_ROUTINE_ORDINAL_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_pe_exported_routine_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.format.pe.PeExportedRoutine",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = PE_EXPORTED_ROUTINE_DOC,
+
+        .tp_methods     = py_pe_exported_routine_methods,
+        .tp_getset      = py_pe_exported_routine_getseters
+
+    };
+
+    return &py_pe_exported_routine_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.format.pe.PeRoutine'.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_pe_exported_routine(PyObject *module)
+{
+    PyTypeObject *type;                     /* Type Python 'PeRoutine'     */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_pe_exported_routine_type();
+
+    dict = PyModule_GetDict(module);
+
+    if (!register_class_for_pygobject(dict, G_TYPE_PE_EXPORTED_ROUTINE, type, get_python_binary_routine_type()))
+        return false;
+
+    if (!define_python_pe_exported_routine_constants(type))
+        return false;
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en routine de fichier PE.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_pe_exported_routine(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_exported_routine_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE exported routine");
+            break;
+
+        case 1:
+            *((GPeExportedRoutine **)dst) = G_PE_EXPORTED_ROUTINE(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          SYMBOLES D'UN FORMAT PE IMPORTES                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le fichier DLL visé par une importation de format PE.*
+*                                                                             *
+*  Retour      : Désignation d'une bibliothèque Windows.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_imported_routine_get_library(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Valeur à retourner          */
+    GPeImportedRoutine *routine;            /* Version native              */
+    const char *library;                    /* Nom de bibliothèque         */
+
+#define PE_IMPORTED_ROUTINE_ORDINAL_ATTRIB PYTHON_GETSET_DEF_FULL   \
+(                                                                   \
+    library, py_pe_imported_routine,                                \
+    "Imported DLL's name for the symbol.\n"                         \
+    "\n"                                                            \
+    "The returned value is a string."                               \
+)
+
+    routine = G_PE_IMPORTED_ROUTINE(pygobject_get(self));
+
+    library = g_pe_imported_routine_get_library(routine);
+
+    result = PyUnicode_FromString(library);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                value   = valeur fournie à intégrer ou prendre en compte.    *
+*                closure = adresse non utilisée ici.                          *
+*                                                                             *
+*  Description : Définit le fichier DLL visé par une importation de format PE.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int py_pe_imported_routine_set_library(PyObject *self, PyObject *value, void *closure)
+{
+    GPeImportedRoutine *routine;            /* Version native              */
+
+    if (!PyUnicode_Check(value) && value != Py_None)
+    {
+        PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string or None."));
+        return -1;
+    }
+
+    routine = G_PE_IMPORTED_ROUTINE(pygobject_get(self));
+
+    if (value == Py_None)
+        g_pe_imported_routine_set_library(routine, NULL);
+    else
+        g_pe_imported_routine_set_library(routine, strdup(PyUnicode_DATA(value)));
+
+    return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
+*                                                                             *
+*  Retour      : Définition d'objet pour Python.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyTypeObject *get_python_pe_imported_routine_type(void)
+{
+    static PyMethodDef py_pe_imported_routine_methods[] = {
+        { NULL }
+    };
+
+    static PyGetSetDef py_pe_imported_routine_getseters[] = {
+        PE_IMPORTED_ROUTINE_ORDINAL_ATTRIB,
+        { NULL }
+    };
+
+    static PyTypeObject py_pe_imported_routine_type = {
+
+        PyVarObject_HEAD_INIT(NULL, 0)
+
+        .tp_name        = "pychrysalide.format.pe.PeImportedRoutine",
+        .tp_basicsize   = sizeof(PyGObject),
+
+        .tp_flags       = Py_TPFLAGS_DEFAULT,
+
+        .tp_doc         = PE_IMPORTED_ROUTINE_DOC,
+
+        .tp_methods     = py_pe_imported_routine_methods,
+        .tp_getset      = py_pe_imported_routine_getseters
+
+    };
+
+    return &py_pe_imported_routine_type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : module = module dont la définition est à compléter.          *
+*                                                                             *
+*  Description : Prend en charge l'objet 'pychrysalide.format.pe.PeRoutine'.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_python_pe_imported_routine(PyObject *module)
+{
+    PyTypeObject *type;                     /* Type Python 'PeRoutine'     */
+    PyObject *dict;                         /* Dictionnaire du module      */
+
+    type = get_python_pe_imported_routine_type();
+
+    dict = PyModule_GetDict(module);
+
+    if (!register_class_for_pygobject(dict, G_TYPE_PE_IMPORTED_ROUTINE, type, get_python_pe_exported_routine_type()))
+        return false;
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en routine de fichier PE.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_pe_imported_routine(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_imported_routine_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE imported routine");
+            break;
+
+        case 1:
+            *((GPeImportedRoutine **)dst) = G_PE_IMPORTED_ROUTINE(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pe/python/routine.h b/plugins/pe/python/routine.h
new file mode 100644
index 0000000..71cb085
--- /dev/null
+++ b/plugins/pe/python/routine.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * routine.h - prototypes pour l'équivalent Python du fichier "plugins/pe/routine.h"
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_ROUTINE_H
+#define _PLUGINS_PE_PYTHON_ROUTINE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_pe_exported_routine_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.pe.PeExportedRoutine'. */
+bool register_python_pe_exported_routine(PyObject *);
+
+/* Tente de convertir en routine de fichier PE. */
+int convert_to_pe_exported_routine(PyObject *, void *);
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_pe_imported_routine_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.pe.PeImportedRoutine'. */
+bool register_python_pe_imported_routine(PyObject *);
+
+/* Tente de convertir en routine de fichier PE. */
+int convert_to_pe_imported_routine(PyObject *, void *);
+
+
+
+#endif  /* _PLUGINS_PE_PYTHON_ROUTINE_H */
diff --git a/plugins/pe/python/translate.c b/plugins/pe/python/translate.c
new file mode 100644
index 0000000..c01a337
--- /dev/null
+++ b/plugins/pe/python/translate.c
@@ -0,0 +1,213 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * translate.c - conversion de structures PE en objets Python
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "translate.h"
+
+
+#include <assert.h>
+
+
+#include <plugins/pychrysalide/struct.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format PE chargé sur lequel s'appuyer.              *
+*                header = en-tête MS-DOS à décrire en Python.                 *
+*                                                                             *
+*  Description : Traduit un en-tête MS-DOS en Python.                         *
+*                                                                             *
+*  Retour      : Structure mise en place ou NULL en cas d'erreur.             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_header *header)
+{
+    PyObject *result;                       /* Construction à retourner    */
+    PyTypeObject *base;                     /* Modèle d'objet à créer      */
+    PyObject *attrib;                       /* Attribut à constituer       */
+    int ret;                                /* Bilan d'une mise en place   */
+    size_t i;                               /* Boucle de parcours          */
+    PyObject *item;                         /* Elément de tableau          */
+
+    base = get_python_py_struct_type();
+
+    result = PyObject_CallFunction((PyObject *)base, NULL);
+    assert(result != NULL);
+
+#define TRANSLATE_DOS_HEADER_FIELD(_f)                                  \
+    do                                                                  \
+    {                                                                   \
+        attrib = PyLong_FromUnsignedLongLong(header->e_ ## _f);         \
+        ret = PyDict_SetItemString(result, "e_" #_f, attrib);           \
+        if (ret != 0) goto failed;                                      \
+    }                                                                   \
+    while (0);
+
+#define TRANSLATE_DOS_HEADER_FIELD_ARRAY(_f, _n)                        \
+    do                                                                  \
+    {                                                                   \
+        attrib = PyTuple_New(_n);                                       \
+        ret = 0;                                                        \
+        for (i = 0; i < _n; i++)                                        \
+        {                                                               \
+            item = PyLong_FromUnsignedLongLong(header->e_ ## _f [i]);   \
+            ret = PyTuple_SetItem(attrib, i, item);                     \
+            if (ret != 0) break;                                        \
+        }                                                               \
+        if (ret != 0) goto failed;                                      \
+        ret = PyDict_SetItemString(result, "e_" #_f, attrib);           \
+        if (ret != 0) goto failed;                                      \
+    }                                                                   \
+    while (0);
+
+    TRANSLATE_DOS_HEADER_FIELD(magic);
+    TRANSLATE_DOS_HEADER_FIELD(cblp);
+    TRANSLATE_DOS_HEADER_FIELD(cp);
+    TRANSLATE_DOS_HEADER_FIELD(crlc);
+    TRANSLATE_DOS_HEADER_FIELD(cparhdr);
+    TRANSLATE_DOS_HEADER_FIELD(minalloc);
+    TRANSLATE_DOS_HEADER_FIELD(maxalloc);
+    TRANSLATE_DOS_HEADER_FIELD(ss);
+    TRANSLATE_DOS_HEADER_FIELD(sp);
+    TRANSLATE_DOS_HEADER_FIELD(csum);
+    TRANSLATE_DOS_HEADER_FIELD(ip);
+    TRANSLATE_DOS_HEADER_FIELD(cs);
+    TRANSLATE_DOS_HEADER_FIELD(lfarlc);
+    TRANSLATE_DOS_HEADER_FIELD(ovno);
+    TRANSLATE_DOS_HEADER_FIELD_ARRAY(res, 4);
+    TRANSLATE_DOS_HEADER_FIELD(oemid);
+    TRANSLATE_DOS_HEADER_FIELD(oeminfo);
+    TRANSLATE_DOS_HEADER_FIELD_ARRAY(res2, 10);
+    TRANSLATE_DOS_HEADER_FIELD(lfanew);
+
+    return result;
+
+ failed:
+
+    Py_DECREF(result);
+
+    return NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format PE chargé sur lequel s'appuyer.              *
+*                dir    = répertoire PE à décrire en Python.                  *
+*                                                                             *
+*  Description : Traduit un répertoire PE en Python.                          *
+*                                                                             *
+*  Retour      : Structure mise en place ou NULL en cas d'erreur.             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const image_data_directory *dir)
+{
+    PyObject *result;                       /* Construction à retourner    */
+    PyTypeObject *base;                     /* Modèle d'objet à créer      */
+    PyObject *attrib;                       /* Attribut à constituer       */
+    int ret;                                /* Bilan d'une mise en place   */
+
+    base = get_python_py_struct_type();
+
+    result = PyObject_CallFunction((PyObject *)base, NULL);
+    assert(result != NULL);
+
+#define TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(_f)            \
+    do                                                      \
+    {                                                       \
+        attrib = PyLong_FromUnsignedLongLong(dir->_f);      \
+        ret = PyDict_SetItemString(result, #_f, attrib);    \
+        if (ret != 0) goto failed;                          \
+    }                                                       \
+    while (0);
+
+    TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(virtual_address);
+    TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(size);
+
+    return result;
+
+ failed:
+
+    Py_DECREF(result);
+
+    return NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format PE chargé sur lequel s'appuyer.              *
+*                id     = ensemble d'informations à décrire en Python.        *
+*                                                                             *
+*  Description : Traduit une série d'informations enrichies en Python.        *
+*                                                                             *
+*  Retour      : Structure mise en place ou NULL en cas d'erreur.             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *translate_pe_comp_id_to_python(GPeFormat *format, const comp_id_t *id)
+{
+    PyObject *result;                       /* Construction à retourner    */
+    PyTypeObject *base;                     /* Modèle d'objet à créer      */
+    PyObject *attrib;                       /* Attribut à constituer       */
+    int ret;                                /* Bilan d'une mise en place   */
+
+    base = get_python_py_struct_type();
+
+    result = PyObject_CallFunction((PyObject *)base, NULL);
+    assert(result != NULL);
+
+#define TRANSLATE_COMP_ID_VALUE(_f)                         \
+    do                                                      \
+    {                                                       \
+        attrib = PyLong_FromUnsignedLongLong(id->_f);       \
+        ret = PyDict_SetItemString(result, #_f, attrib);    \
+        if (ret != 0) goto failed;                          \
+    }                                                       \
+    while (0);
+
+    TRANSLATE_COMP_ID_VALUE(minor_cv);
+    TRANSLATE_COMP_ID_VALUE(prod_id);
+    TRANSLATE_COMP_ID_VALUE(count);
+
+    return result;
+
+ failed:
+
+    Py_DECREF(result);
+
+    return NULL;
+
+}
diff --git a/plugins/pe/python/translate.h b/plugins/pe/python/translate.h
new file mode 100644
index 0000000..dbde6c8
--- /dev/null
+++ b/plugins/pe/python/translate.h
@@ -0,0 +1,48 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * translate.h - prototypes pour la conversion de structures PE en objets Python
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_TRANSLATE_H
+#define _PLUGINS_PE_PYTHON_TRANSLATE_H
+
+
+#include <Python.h>
+
+
+#include "../format.h"
+#include "../rich.h"
+
+
+
+/* Traduit un en-tête MS-DOS en Python. */
+PyObject *translate_pe_dos_header_to_python(GPeFormat *, const image_dos_header *);
+
+/* Traduit un répertoire PE en Python. */
+PyObject *translate_pe_image_data_directory_to_python(GPeFormat *, const image_data_directory *);
+
+/* Traduit une série d'informations enrichies en Python. */
+PyObject *translate_pe_comp_id_to_python(GPeFormat *, const comp_id_t *);
+
+
+
+#endif  /* _PLUGINS_PE_PYTHON_TRANSLATE_H */
diff --git a/plugins/pe/rich.c b/plugins/pe/rich.c
new file mode 100644
index 0000000..7764f09
--- /dev/null
+++ b/plugins/pe/rich.c
@@ -0,0 +1,312 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rich.c - lecture des informations enrichies d'un format PE
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "rich.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include <format/known.h>
+
+
+#include "pe-int.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à compléter.            *
+*                                                                             *
+*  Description : Extrait si elles existant les informations enrichies du PE.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void extract_pe_rich_header(GPeFormat *format)
+{
+    const image_dos_header *header;         /* En-tête avec positions      */
+    bin_t *dans;                            /* Motif "DanS" trouvé         */
+    GBinContent *content;                   /* Contenu à parcourir         */
+    vmpa2t start;                           /* Position de départ          */
+    const bin_t *data;                      /* Données brutes à analyser   */
+    bin_t *rich;                            /* Marqueur "Rich" trouvé      */
+    uint32_t checksum;                      /* Empreinte appliquée         */
+    bool status;                            /* Bilan d'une lecture         */
+    bin_t words[8];                         /* Premiers mots trouvés       */
+
+    header = g_pe_format_get_dos_header(format);
+
+    dans = NULL;
+
+    /* Recherche du marqueur final */
+
+    content = g_known_format_get_content(G_KNOWN_FORMAT(format));
+
+    g_binary_content_compute_start_pos(content, &start);
+
+    data = g_binary_content_get_raw_access(content, &start, header->e_lfanew);
+    if (data == NULL) goto exit;
+
+    rich = memmem(data, header->e_lfanew, "Rich", 4);
+    if (rich == NULL) goto exit;
+
+    /* Constitution des premiers mots */
+
+    g_binary_content_compute_start_pos(content, &start);
+
+    advance_vmpa(&start, rich - data);
+    advance_vmpa(&start, 4);
+
+
+    status = g_binary_content_read_u32(content, &start, SRE_LITTLE, &checksum);
+    if (!status) goto exit;
+
+    g_binary_content_compute_start_pos(content, &start);
+
+    advance_vmpa(&start, rich - data);
+    advance_vmpa(&start, 4);
+
+    status = g_binary_content_read_raw(content, &start, 4, words + 4);
+    assert(status);
+
+    words[0] = 'D' ^ words[4];
+    words[1] = 'a' ^ words[5];
+    words[2] = 'n' ^ words[6];
+    words[3] = 'S' ^ words[7];
+
+    /* Recherche du marqueur initial et conclusion */
+
+    dans = memmem(data, header->e_lfanew, words, 8);
+
+    if (dans != NULL && ((rich - dans) % 8 != 0))
+        dans = NULL;
+
+ exit:
+
+    if (dans == NULL)
+    {
+        init_vmpa(&start, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+        init_mrange(&format->rich_header, &start, 0);
+    }
+
+    else
+    {
+        init_vmpa(&start, (bin_t *)dans - data, VMPA_NO_VIRTUAL);
+        init_mrange(&format->rich_header, &start, rich + 8 - dans);
+    }
+
+    g_object_unref(G_OBJECT(content));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format en place à consulter.                        *
+*                area   = localisation à constituer. [OUT]                    *
+*                                                                             *
+*  Description : Décrit la zone couverte par l'en-tête enrichi du format.     *
+*                                                                             *
+*  Retour      : Validité de la zone définie en sortie.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_pe_format_get_rich_header_area(const GPeFormat *format, mrange_t *area)
+{
+    bool result;                            /* Validité à renvoyer         */
+
+    result = (get_mrange_length(&format->rich_header) > 0);
+
+    if (result)
+        copy_mrange(area, &format->rich_header);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format   = format en place à consulter.                      *
+*                checksum = empreinte incrustée à retrouver. [OUT]            *
+*                                                                             *
+*  Description : Présente l'empreinte d'un en-tête enrichi du format chargé.  *
+*                                                                             *
+*  Retour      : Validité de la zone définie en sortie.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_pe_format_get_rich_header_checksum(const GPeFormat *format, uint32_t *checksum)
+{
+    bool result;                            /* Validité à renvoyer         */
+    GBinContent *content;                   /* Contenu à parcourir         */
+    vmpa2t pos;                             /* Tête de lecture             */
+#ifndef NDEBUG
+    bool status;                            /* Bilan d'une lecture         */
+#endif
+
+    result = (get_mrange_length(&format->rich_header) > 0);
+
+    if (result)
+    {
+        content = g_known_format_get_content(G_KNOWN_FORMAT(format));
+
+        copy_vmpa(&pos, get_mrange_addr(&format->rich_header));
+        advance_vmpa(&pos, sizeof(uint32_t));
+
+#ifndef NDEBUG
+        status = g_binary_content_read_u32(content, &pos, SRE_LITTLE, checksum);
+        assert(status);
+#else
+        g_binary_content_read_u32(content, &pos, SRE_LITTLE, checksum);
+#endif
+
+        g_object_unref(G_OBJECT(content));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format en place à consulter.                        *
+*                count  = nombre d'éléments de la liste constituée. [OUT]     *
+*                                                                             *
+*  Description : Présente l'en-tête enrichi du format chargé.                 *
+*                                                                             *
+*  Retour      : Tableau de valeurs brutes d'information.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+uint64_t *g_pe_format_get_rich_header(const GPeFormat *format, size_t *count)
+{
+    uint64_t *result;                       /* Valeurs à retourner         */
+    GBinContent *content;                   /* Contenu à parcourir         */
+    vmpa2t iter;                            /* Tête de lecture             */
+    size_t i;                               /* Boucle de parcours          */
+#ifndef NDEBUG
+    bool status;                            /* Bilan d'une lecture         */
+#endif
+
+    if (get_mrange_length(&format->rich_header) == 0)
+    {
+        *count = 0;
+        result = NULL;
+    }
+
+    else
+    {
+        *count = get_mrange_length(&format->rich_header) / 8;
+        result = malloc(*count * sizeof(uint64_t));
+
+        content = g_known_format_get_content(G_KNOWN_FORMAT(format));
+
+        copy_vmpa(&iter, get_mrange_addr(&format->rich_header));
+
+        for (i = 0; i < *count; i++)
+        {
+#ifndef NDEBUG
+            status = g_binary_content_read_u64(content, &iter, SRE_LITTLE, &result[i]);
+            assert(status);
+#else
+            g_binary_content_read_u64(content, &iter, SRE_LITTLE, &result[i]);
+#endif
+        }
+
+        g_object_unref(G_OBJECT(content));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format en place à consulter.                        *
+*                count  = nombre d'éléments de la liste constituée. [OUT]     *
+*                                                                             *
+*  Description : Présente les identifiants contenues dans l'en-tête enrichi.  *
+*                                                                             *
+*  Retour      : Tableau de valeurs raffinées d'information.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+comp_id_t *g_pe_format_get_comp_ids(const GPeFormat *format, size_t *count)
+{
+    comp_id_t *result;                      /* Identifiants à retourner    */
+    uint64_t *values;                       /* Valeurs brutes à traiter    */
+    size_t vcount;                          /* Quantité de ces valeurs     */
+    uint64_t mask;                          /* Masque à appliquer          */
+    size_t i;                               /* Boucle de parcours          */
+
+    values = g_pe_format_get_rich_header(format, &vcount);
+
+    if (vcount > 2)
+    {
+        mask = ((values[0] >> 32) & 0xffffffff);
+        mask |= (mask << 32);
+
+        *count = vcount - 2;
+        result = malloc(*count * sizeof(comp_id_t));
+
+        for (i = 0; i < *count; i++)
+        {
+            values[i + 1] ^= mask;
+
+            result[i].minor_cv = values[i + 1] & 0xffff;
+            result[i].prod_id = (values[i + 1] >> 16) & 0xffff;
+            result[i].count = (values[i + 1] >> 32) & 0xffffffff;
+
+        }
+
+    }
+    else
+    {
+        *count = 0;
+        result = NULL;
+    }
+
+    if (values != NULL)
+        free(values);
+
+    return result;
+
+}
diff --git a/plugins/pe/rich.h b/plugins/pe/rich.h
new file mode 100644
index 0000000..c8fb677
--- /dev/null
+++ b/plugins/pe/rich.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rich.h - prototypes pour la lecture des informations enrichies d'un format PE
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_PE_RICH_H
+#define _PLUGINS_PE_RICH_H
+
+
+#include <stdint.h>
+
+
+#include "format.h"
+
+
+
+/* Extrait si elles existant les informations enrichies du PE. */
+void extract_pe_rich_header(GPeFormat *);
+
+/* Décrit la zone couverte par l'en-tête enrichi du format. */
+bool g_pe_format_get_rich_header_area(const GPeFormat *, mrange_t *);
+
+/* Présente l'empreinte d'un en-tête enrichi du format chargé. */
+bool g_pe_format_get_rich_header_checksum(const GPeFormat *, uint32_t *);
+
+/* Présente l'en-tête enrichi du format chargé. */
+uint64_t *g_pe_format_get_rich_header(const GPeFormat *, size_t *);
+
+/* Identifiants apportés par le compilateur */
+typedef struct _comp_id_t
+{
+    uint16_t minor_cv;                      /* Version mineure du compilo  */
+    uint16_t prod_id;                       /* Identifiant du type d'objet */
+    uint32_t count;                         /* Nombre d'objets en cause    */
+
+} comp_id_t;
+
+/* Présente les identifiants contenues dans l'en-tête enrichi. */
+comp_id_t *g_pe_format_get_comp_ids(const GPeFormat *, size_t *);
+
+
+
+#endif  /* _PLUGINS_PE_RICH_H */
diff --git a/plugins/pe/routine.c b/plugins/pe/routine.c
new file mode 100644
index 0000000..3f2e5ba
--- /dev/null
+++ b/plugins/pe/routine.c
@@ -0,0 +1,429 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * routine.c - prototypes pour la manipulation des routines du format PE
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "routine.h"
+
+
+#include <analysis/routine-int.h>
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */
+
+
+/* Représentation de routine PE exportée (instance) */
+struct _GPeExportedRoutine
+{
+    GBinRoutine parent;                     /* A laisser en premier        */
+
+    uint16_t ordinal;                       /* Numéro du symbole           */
+
+};
+
+
+/* Représentation de routine PE exportée (classe) */
+struct _GPeExportedRoutineClass
+{
+    GBinRoutineClass parent;                /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des routine PE exportées. */
+static void g_pe_exported_routine_class_init(GPeExportedRoutineClass *);
+
+/* Initialise une instance de routine PE exportée. */
+static void g_pe_exported_routine_init(GPeExportedRoutine *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_pe_exported_routine_finalize(GPeExportedRoutine *);
+
+/* Supprime toutes les références externes. */
+static void g_pe_exported_routine_dispose(GPeExportedRoutine *);
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */
+
+
+/* Représentation de routine PE importée (instance) */
+struct _GPeImportedRoutine
+{
+    GPeExportedRoutine parent;              /* A laisser en premier        */
+
+    char *library;                          /* Bibliothèque de rattachement*/
+
+};
+
+
+/* Représentation de routine PE importée (classe) */
+struct _GPeImportedRoutineClass
+{
+    GPeExportedRoutineClass parent;         /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des routines PE importées. */
+static void g_pe_imported_routine_class_init(GPeImportedRoutineClass *);
+
+/* Initialise une instance de routine PE importée. */
+static void g_pe_imported_routine_init(GPeImportedRoutine *);
+
+/* Supprime toutes les références externes. */
+static void g_pe_imported_routine_dispose(GPeImportedRoutine *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_pe_imported_routine_finalize(GPeImportedRoutine *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          SYMBOLES D'UN FORMAT PE EXPORTES                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une représentation de routine exportée. */
+G_DEFINE_TYPE(GPeExportedRoutine, g_pe_exported_routine, G_TYPE_BIN_ROUTINE);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des routines PE exportées.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_exported_routine_class_init(GPeExportedRoutineClass *klass)
+{
+    GObjectClass *object;                   /* Version de base de la classe*/
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_pe_exported_routine_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_pe_exported_routine_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = instance à initialiser.                            *
+*                                                                             *
+*  Description : Initialise une instance de routine PE exportée.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_exported_routine_init(GPeExportedRoutine *routine)
+{
+    routine->ordinal = UNDEF_PE_ORDINAL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_exported_routine_dispose(GPeExportedRoutine *routine)
+{
+    G_OBJECT_CLASS(g_pe_exported_routine_parent_class)->dispose(G_OBJECT(routine));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_exported_routine_finalize(GPeExportedRoutine *routine)
+{
+    G_OBJECT_CLASS(g_pe_exported_routine_parent_class)->finalize(G_OBJECT(routine));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : name = désignation humainement lisible.                      *
+*                                                                             *
+*  Description : Crée une représentation de routine exportée pour format PE.  *
+*                                                                             *
+*  Retour      : Adresse de la structure mise en place.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GPeExportedRoutine *g_pe_exported_routine_new(const char *name)
+{
+    GPeExportedRoutine *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_PE_EXPORTED_ROUTINE, NULL);
+
+    if (name != NULL)
+        g_binary_routine_set_name(G_BIN_ROUTINE(result), strdup(name));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = routine ayant pour origine un fichier PE.          *
+*                ordinal = indice de symbole à associer à la routine.         *
+*                                                                             *
+*  Description : Définit l'indice de la routine dans un fichier PE.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_pe_exported_routine_set_ordinal(GPeExportedRoutine *routine, uint16_t ordinal)
+{
+    routine->ordinal = ordinal;
+
+    g_binary_symbol_set_flag(G_BIN_SYMBOL(routine), PSF_HAS_ORDINAL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = routine ayant pour origine un fichier PE.          *
+*                                                                             *
+*  Description : Fournit l'indice de la routine dans un fichier PE.           *
+*                                                                             *
+*  Retour      : Numéro de la routine.                                        *
+*                                                                             *
+*  Remarques   : C'est à l'appelant de s'assurer de la validité du retour.    *
+*                                                                             *
+******************************************************************************/
+
+uint16_t g_pe_exported_routine_get_ordinal(const GPeExportedRoutine *routine)
+{
+    uint16_t result;                        /* Indice à retourner          */
+
+     result = routine->ordinal;
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          SYMBOLES D'UN FORMAT PE IMPORTES                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une représentation de routine importée. */
+G_DEFINE_TYPE(GPeImportedRoutine, g_pe_imported_routine, G_TYPE_PE_EXPORTED_ROUTINE);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des routines PE importées.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_imported_routine_class_init(GPeImportedRoutineClass *klass)
+{
+    GObjectClass *object;                   /* Version de base de la classe*/
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_pe_imported_routine_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_pe_imported_routine_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = instance à initialiser.                            *
+*                                                                             *
+*  Description : Initialise une instance de routine PE importée.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_imported_routine_init(GPeImportedRoutine *routine)
+{
+    routine->library = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_imported_routine_dispose(GPeImportedRoutine *routine)
+{
+    G_OBJECT_CLASS(g_pe_imported_routine_parent_class)->dispose(G_OBJECT(routine));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_pe_imported_routine_finalize(GPeImportedRoutine *routine)
+{
+    if (routine->library != NULL)
+        free(routine->library);
+
+    G_OBJECT_CLASS(g_pe_imported_routine_parent_class)->finalize(G_OBJECT(routine));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : name = désignation humainement lisible.                      *
+*                                                                             *
+*  Description : Crée une représentation de routine importée pour format PE.  *
+*                                                                             *
+*  Retour      : Adresse de la structure mise en place.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GPeImportedRoutine *g_pe_imported_routine_new(const char *name)
+{
+    GPeImportedRoutine *result;                    /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_PE_IMPORTED_ROUTINE, NULL);
+
+    if (name != NULL)
+        g_binary_routine_set_name(G_BIN_ROUTINE(result), strdup(name));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = routine ayant pour origine un fichier PE.          *
+*                library = désignation d'une bibliothèque Windows.            *
+*                                                                             *
+*  Description : Définit le fichier DLL visé par une importation de format PE.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_pe_imported_routine_set_library(GPeImportedRoutine *routine, const char *library)
+{
+    if (routine->library != NULL)
+        free(routine->library);
+
+    if (library == NULL)
+        routine->library = NULL;
+
+    else
+        routine->library = strdup(library);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = routine ayant pour origine un fichier PE.          *
+*                                                                             *
+*  Description : Fournit le fichier DLL visé par une importation de format PE.*
+*                                                                             *
+*  Retour      : Désignation d'une bibliothèque Windows.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_pe_imported_routine_get_library(const GPeImportedRoutine *routine)
+{
+    char *result;                           /* Bibliothèque à retourner    */
+
+    result = routine->library;
+
+    return result;
+
+}
diff --git a/plugins/pe/routine.h b/plugins/pe/routine.h
new file mode 100644
index 0000000..62faaaa
--- /dev/null
+++ b/plugins/pe/routine.h
@@ -0,0 +1,111 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * routine.h - prototypes pour la manipulation des routines du format PE
+ *
+ * Copyright (C) 2020 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_PE_ROUTINE_H
+#define _PLUGINS_PE_ROUTINE_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/routine.h>
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */
+
+
+#define G_TYPE_PE_EXPORTED_ROUTINE            g_pe_exported_routine_get_type()
+#define G_PE_EXPORTED_ROUTINE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PE_EXPORTED_ROUTINE, GPeExportedRoutine))
+#define G_IS_PE_EXPORTED_ROUTINE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PE_EXPORTED_ROUTINE))
+#define G_PE_EXPORTED_ROUTINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PE_EXPORTED_ROUTINE, GPeExportedRoutineClass))
+#define G_IS_PE_EXPORTED_ROUTINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PE_EXPORTED_ROUTINE))
+#define G_PE_EXPORTED_ROUTINE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PE_EXPORTED_ROUTINE, GPeExportedRoutineClass))
+
+
+/* Représentation de routine PE exportée (instance) */
+typedef struct _GPeExportedRoutine GPeExportedRoutine;
+
+/* Représentation de routine PE exportée (classe) */
+typedef struct _GPeExportedRoutineClass GPeExportedRoutineClass;
+
+
+/* Drapeaux pour informations complémentaires */
+typedef enum _PeSymbolFlag
+{
+    PSF_HAS_ORDINAL = (1 << (SFL_LOW_USER + 0)), /* Numérotation présente  */
+    PSF_FORWARDED   = (1 << (SFL_LOW_USER + 1)), /* Renvoi vers une DLL ?  */
+
+} PeSymbolFlag;
+
+
+#define UNDEF_PE_ORDINAL 0xffff
+
+
+/* Indique le type défini pour une représentation de routine exportée. */
+GType g_pe_exported_routine_get_type(void);
+
+/* Crée une représentation de routine exportée pour format PE. */
+GPeExportedRoutine *g_pe_exported_routine_new(const char *);
+
+/* Définit l'indice de la routine dans un fichier PE. */
+void g_pe_exported_routine_set_ordinal(GPeExportedRoutine *, uint16_t);
+
+/* Fournit l'indice de la routine dans un fichier PE. */
+uint16_t g_pe_exported_routine_get_ordinal(const GPeExportedRoutine *);
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */
+
+
+#define G_TYPE_PE_IMPORTED_ROUTINE            g_pe_imported_routine_get_type()
+#define G_PE_IMPORTED_ROUTINE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PE_IMPORTED_ROUTINE, GPeImportedRoutine))
+#define G_IS_PE_IMPORTED_ROUTINE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PE_IMPORTED_ROUTINE))
+#define G_PE_IMPORTED_ROUTINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PE_IMPORTED_ROUTINE, GPeImportedRoutineClass))
+#define G_IS_PE_IMPORTED_ROUTINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PE_IMPORTED_ROUTINE))
+#define G_PE_IMPORTED_ROUTINE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PE_IMPORTED_ROUTINE, GPeImportedRoutineClass))
+
+
+/* Représentation de routine PE importée (instance) */
+typedef struct _GPeImportedRoutine GPeImportedRoutine;
+
+/* Représentation de routine PE importée (classe) */
+typedef struct _GPeImportedRoutineClass GPeImportedRoutineClass;
+
+
+/* Indique le type défini pour une représentation de routine importée. */
+GType g_pe_imported_routine_get_type(void);
+
+/* Crée une représentation de routine importée pour format PE. */
+GPeImportedRoutine *g_pe_imported_routine_new(const char *);
+
+/* Définit le fichier DLL visé par une importation de format PE. */
+void g_pe_imported_routine_set_library(GPeImportedRoutine *, const char *);
+
+/* Fournit le fichier DLL visé par une importation de format PE. */
+const char *g_pe_imported_routine_get_library(const GPeImportedRoutine *);
+
+
+
+#endif  /* _PLUGINS_PE_ROUTINE_H */
diff --git a/plugins/pe/section.c b/plugins/pe/section.c
index f4cdaf3..732b35c 100644
--- a/plugins/pe/section.c
+++ b/plugins/pe/section.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * section.h - prototypes pour la gestion des sections d'un PE
  *
- * Copyright (C) 2010-2017 Cyrille Bagard
+ * Copyright (C) 2010-2021 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -25,7 +25,6 @@
 
 
 #include <malloc.h>
-#include <string.h>
 
 
 #include "pe-int.h"
@@ -34,26 +33,41 @@
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format  = description de l'exécutable à consulter.           *
-*                index   = indice de la section recherchée.                   *
-*                section = ensemble d'informations à faire remonter. [OUT]    *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                pos    = tête de lecture positionnée. [OUT]                  *
 *                                                                             *
 *  Description : Recherche une section donnée au sein de binaire par indice.  *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : Liste de sections reconstituées ou NULL en cas d'échec.      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool find_pe_section_by_index(const GPeFormat *format, uint16_t index, image_section_header *section)
+image_section_header *read_all_pe_sections(const GPeFormat *format, vmpa2t *pos)
 {
-    off_t offset;                           /* Emplacement à venir lire    */
+    image_section_header *result;           /* Liste à retourner           */
+    uint16_t count;                         /* Quantité de sections        */
+    uint16_t i;                             /* Boucle de parcours          */
+    bool status;                            /* Bilan d'une lecture         */
 
-    if (index >= format->nt_headers.file_header.number_of_sections) return false;
+    count = format->nt_headers.file_header.number_of_sections;
 
-    offset = format->section_offset + sizeof(image_section_header) * index;
+    result = malloc(count * sizeof(image_section_header));
 
-    return read_pe_image_section_header(format, &offset, section);
+    for (i = 0; i < count; i++)
+    {
+        status = read_pe_image_section_header(format, pos, &result[i]);
+
+        if (!status)
+        {
+            free(result);
+            result = NULL;
+            break;
+        }
+
+    }
+
+    return result;
 
 }
diff --git a/plugins/pe/section.h b/plugins/pe/section.h
index e7c399b..2ac21d3 100644
--- a/plugins/pe/section.h
+++ b/plugins/pe/section.h
@@ -21,18 +21,18 @@
  */
 
 
-#ifndef _FORMAT_PE_SECTION_H
-#define _FORMAT_PE_SECTION_H
+#ifndef _PLUGINS_PE_SECTION_H
+#define _PLUGINS_PE_SECTION_H
 
 
-#include "pe.h"
+#include "format.h"
 #include "pe_def.h"
 
 
 
 /* Recherche une section donnée au sein de binaire par indice. */
-bool find_pe_section_by_index(const GPeFormat *, uint16_t, image_section_header *);
+image_section_header *read_all_pe_sections(const GPeFormat *, vmpa2t *);
 
 
 
-#endif  /* _FORMAT_PE_SECTION_H */
+#endif  /* _PLUGINS_PE_SECTION_H */
diff --git a/plugins/pe/symbols.c b/plugins/pe/symbols.c
index 30e43b5..9217466 100644
--- a/plugins/pe/symbols.c
+++ b/plugins/pe/symbols.c
@@ -24,20 +24,35 @@
 #include "symbols.h"
 
 
+#include <malloc.h>
+
+
+#include <i18n.h>
+
+
 #include "pe-int.h"
+#include "routine.h"
 
 
 
+/* Charge en mémoire la liste humaine des symboles exportés. */
+static bool load_pe_exported_symbols(GPeFormat *, wgroup_id_t, GtkStatusStack *);
 
+/* Charge en mémoire la liste humaine des symboles importés. */
+static bool load_pe_imported_symbols(GPeFormat *, wgroup_id_t, GtkStatusStack *);
 
+/* Assure l'inscription du point d'entrée d'un binaire PE. */
+static bool load_pe_entry_point(GPeFormat *, GtkStatusStack *);
 
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à compléter.            *
+*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
 *                                                                             *
-*  Description : Charge en mémoire la liste humaine des symboles importés.    *
+*  Description : Charge en mémoire la liste humaine des symboles exportés.    *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -45,74 +60,331 @@
 *                                                                             *
 ******************************************************************************/
 
-bool load_pe_imported_symbols(GPeFormat *format)
+static bool load_pe_exported_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
-    const image_data_directory *directory;  /* Répertoire original         */
-    image_import_descriptor dll;            /* DLL importée                */
-    off_t pos;                              /* Position de tête de lecture */
-    off_t i;                                /* Boucle de parcours          */
-    image_import_by_name import;            /* Fonction importée           */
+    image_export_directory *export;         /* Répertoire de type 0        */
+    const image_data_directory *dir;        /* Localisation du répertoire  */
+    GBinFormat *base;                       /* Version basique du format   */
+    GExeFormat *exe;                        /* Autre vision du format      */
+    bool ret;                               /* Bilan d'un traitement       */
+    vmpa2t functions;                       /* Localisation des adresses   */
+    vmpa2t names;                           /* Localisation de RVA de noms */
+    vmpa2t ordinals;                        /* Localisation des ordinaux   */
+    const GBinContent *content;             /* Contenu binaire à lire      */
+    uint32_t i;                             /* Boucle de parcours          */
+    uint32_t rva;                           /* Adresse relative à traiter  */
+    vmpa2t pos;                             /* Position correspondante     */
+    const bin_t *name;                      /* Pointeur vers des données   */
+    uint16_t ordinal;                       /* Indice de l'exportation     */
+    bool forwarded;                         /* Le symbole est renvoyé ?    */
+    GPeExportedRoutine *routine;            /* Nouvelle routine trouvée    */
+    GBinSymbol *symbol;                     /* Equivalence en symbole      */
+    mrange_t range;                         /* Couverture mémoire associée */
+
+    result = false;
+
+    export = g_pe_format_get_directory(format, IMAGE_DIRECTORY_ENTRY_EXPORT);
+    if (export == NULL) goto exit;
+
+    dir = g_pe_format_get_directories(format, NULL);
+    dir += IMAGE_DIRECTORY_ENTRY_EXPORT;
+
+    base = G_BIN_FORMAT(format);
+    exe = G_EXE_FORMAT(format);
+
+    ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_functions, &functions);
+    if (!ret) goto exit_loading;
+
+    ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_names, &names);
+    if (!ret) goto exit_loading;
+
+    ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_name_ordinals, &ordinals);
+    if (!ret) goto exit_loading;
+
+    content = G_KNOWN_FORMAT(format)->content;
+
+    for (i = 0; i < export->number_of_names; i++)
+    {
+        /* Dénomination */
+
+        ret = g_binary_content_read_u32(content, &names, SRE_LITTLE, &rva);
+        if (!ret) goto exit_loading;
+
+        ret = g_exe_format_translate_address_into_vmpa(exe, rva, &pos);
+        if (!ret) goto exit_loading;
+
+        name = g_binary_content_get_raw_access(content, &pos, 1);
+        if (name == NULL) goto exit_loading;
+
+        /* Ordinal */
+
+        ret = g_binary_content_read_u16(content, &ordinals, SRE_LITTLE, &ordinal);
+        if (!ret) goto exit_loading;
+
+        ordinal += export->base;
+
+        /* Adresse */
+
+        copy_vmpa(&pos, &functions);
+        advance_vmpa(&pos, ordinal * sizeof(uint32_t));
+
+        ret = g_binary_content_read_u32(content, &pos, SRE_LITTLE, &rva);
+        if (!ret) goto exit_loading;
+
+        /**
+         * Entrée de type "Forwarder RVA" ?
+         */
+        forwarded = (dir->virtual_address <= rva && rva < (dir->virtual_address + dir->size));
+
+        ret = g_exe_format_translate_address_into_vmpa(exe, rva, &pos);
+        if (!ret) continue;
+
+        /* Mise en place du symbole */
+
+        routine = g_pe_exported_routine_new((char *)name);
+
+        g_pe_exported_routine_set_ordinal(routine, ordinal);
+
+        symbol = G_BIN_SYMBOL(routine);
+
+        if (forwarded)
+            g_binary_symbol_set_flag(symbol, PSF_FORWARDED);
+
+        g_binary_symbol_set_status(symbol, SSS_EXPORTED);
+
+        init_mrange(&range, &pos, 0);
+
+        g_binary_symbol_set_range(symbol, &range);
+
+        g_binary_format_add_symbol(base, symbol);
+
+    }
 
     result = true;
 
-    directory = &format->nt_headers.optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+ exit_loading:
+
+    free(export);
+
+ exit:
+
+    return result;
+
+}
+
 
-    /* TODO : msg si size !% sizeof(...) */
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Charge en mémoire la liste humaine des symboles importés.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    for (pos = directory->virtual_address;
-         result && pos < (directory->virtual_address + directory->size); )
+static bool load_pe_imported_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    bool is_32b;                            /* Exécutable 32 bits ?        */
+    image_import_descriptor *imports;       /* Répertoire de type 1        */
+    GBinFormat *base;                       /* Version basique du format   */
+    GExeFormat *exe;                        /* Autre vision du format      */
+    const GBinContent *content;             /* Contenu binaire à lire      */
+    image_import_descriptor *iter;          /* Boucle de parcours          */
+    vmpa2t dll;                             /* Nom de la DLL concernée     */
+    bool ret;                               /* Bilan d'un traitement       */
+    const bin_t *library;                   /* Pointeur vers des données   */
+    vmpa2t lookup;                          /* Informations d'importation  */
+    vmpa2t overwritten;                     /* Emplacement d'adresse finale*/
+    uint32_t val32;                         /* Indications sur 32 bits     */
+    uint64_t val64;                         /* Indications sur 64 bits     */
+    uint32_t rva;                           /* Adresse relative à traiter  */
+    vmpa2t name;                            /* Désignation humaine         */
+    const bin_t *hint;                      /* Pointeur vers des données   */
+    GPeImportedRoutine *routine;            /* Nouvelle routine trouvée    */
+    GBinSymbol *symbol;                     /* Equivalence en symbole      */
+    mrange_t range;                         /* Couverture mémoire associée */
+
+    result = false;
+
+    is_32b = g_pe_format_get_is_32b(format);
+
+    imports = g_pe_format_get_directory(format, IMAGE_DIRECTORY_ENTRY_IMPORT);
+    if (imports == NULL) goto exit;
+
+    base = G_BIN_FORMAT(format);
+    exe = G_EXE_FORMAT(format);
+
+    content = G_KNOWN_FORMAT(format)->content;
+
+    for (iter = imports; iter->original_first_thunk != 0; iter++)
     {
-        result = read_pe_image_import_descriptor(format, &pos, &dll);
+        /* Bibliothèque impactée */
 
-        printf("mod orig thunk :: 0x%08x\n", dll.original_first_thunk);
-        printf("mod name :: 0x%08x\n", dll.module_name);
-        printf("mod first thunk :: 0x%08x\n", dll.first_thunk);
+        ret = g_exe_format_translate_address_into_vmpa(exe, iter->module_name, &dll);
+        if (!ret) goto exit_loading;
 
-        i = dll.original_first_thunk;
+        library = g_binary_content_get_raw_access(content, &dll, 1);
+        if (library == NULL) goto exit_loading;
 
-        /* TODO : i == 0 */
-        if (i == 0) continue;
+        /* Liste des fonctions importées */
 
-        while ((result = read_pe_image_import_by_name(format, &i, &import)))
+        ret = g_exe_format_translate_address_into_vmpa(exe, iter->original_first_thunk, &lookup);
+        if (!ret) goto exit_loading;
+
+        ret = g_exe_format_translate_address_into_vmpa(exe, iter->first_thunk, &overwritten);
+        if (!ret) goto exit_loading;
+
+        do
         {
-            if (import.hint == 0 && import.name == NULL)
+            if (is_32b)
+            {
+                ret = g_binary_content_read_u32(content, &lookup, SRE_LITTLE, &val32);
+                if (!ret) goto exit_loading;
+
+                val64 = ((uint64_t)(val32 & 0x80000000)) << 32 | val32;
+
+            }
+            else
+            {
+                ret = g_binary_content_read_u64(content, &lookup, SRE_LITTLE, &val64);
+                if (!ret) goto exit_loading;
+            }
+
+            if (val64 == 0)
                 break;
 
+            if (val64 & 0x8000000000000000)
+            {
+                routine = g_pe_imported_routine_new(NULL);
 
+                g_pe_exported_routine_set_ordinal(G_PE_EXPORTED_ROUTINE(routine), val64 & 0xffff);
 
-            printf(" >> import '%s'\n", import.name);
+            }
+            else
+            {
+                rva = (val64 & 0x7fffffff);
 
+                ret = g_exe_format_translate_address_into_vmpa(exe, rva, &name);
+                if (!ret) goto exit_loading;
 
-        }
+                hint = g_binary_content_get_raw_access(content, &name, 3);
+                if (hint == NULL) goto exit_loading;
+
+                hint += 2;
+
+                //routine = g_binary_format_decode_routine(base, hint);
+                routine = g_pe_imported_routine_new((char *)hint);
 
+            }
+
+            g_pe_imported_routine_set_library(routine, (char *)library);
+
+            symbol = G_BIN_SYMBOL(routine);
+
+            g_binary_symbol_set_status(symbol, SSS_IMPORTED);
+
+            init_mrange(&range, &overwritten, sizeof(uint32_t));
+            advance_vmpa(&overwritten, sizeof(uint32_t));
+
+            g_binary_symbol_set_range(symbol, &range);
+
+            g_binary_format_add_symbol(base, symbol);
+
+        }
+        while (true);
 
     }
 
- lpis_exit:
+    result = true;
+
+ exit_loading:
+
+    free(imports);
+
+ exit:
 
     return result;
 
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Assure l'inscription du point d'entrée d'un binaire PE.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool load_pe_entry_point(GPeFormat *format, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    activity_id_t msg;                      /* Message de progression      */
+    const image_nt_headers *headers;        /* Informations d'entête       */
+    virt_t ep;                              /* Point d'entrée détecté      */
+    vmpa2t addr;                            /* Localisation d'une routine  */
+    GBinFormat *base;                       /* Autre version du format     */
+    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
+    GBinRoutine *routine;                   /* Routine à associer au point */
+    mrange_t range;                         /* Couverture mémoire associée */
+
+    msg = gtk_status_stack_add_activity(status, _("Registering entry point..."), 0);
+
+    headers = g_pe_format_get_nt_headers(format);
+    ep = headers->optional_header.header_32.address_of_entry_point;
 
+    result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), ep, &addr);
+    if (!result) goto exit;
 
+    base = G_BIN_FORMAT(format);
 
+    if (!g_binary_format_find_symbol_at(base, &addr, &symbol))
+    {
+        routine = g_binary_format_decode_routine(base, "entry_point");
 
+        symbol = G_BIN_SYMBOL(routine);
+        g_object_ref(G_OBJECT(symbol));
 
+        init_mrange(&range, &addr, 0);
+        g_binary_symbol_set_range(symbol, &range);
 
+        g_binary_format_add_symbol(base, symbol);
 
+    }
 
+    g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT);
 
+    g_object_unref(G_OBJECT(symbol));
 
+    /* Comptabilisation pour le désassemblage brut */
+    g_binary_format_register_code_point(base, get_virt_addr(&addr), DPL_ENTRY_POINT);
 
+ exit:
 
+    gtk_status_stack_remove_activity(status, msg);
+
+    return result;
+
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à compléter.            *
+*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
 *                                                                             *
 *  Description : Charge en mémoire la liste humaine des symboles.             *
 *                                                                             *
@@ -122,14 +394,19 @@ bool load_pe_imported_symbols(GPeFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-bool load_pe_symbols(GPeFormat *format)
+bool load_pe_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
 
-    /* Symboles externes */
-    result = load_pe_imported_symbols(format);
+    result = load_pe_exported_symbols(format, gid, status);
+
+    if (result)
+        result = load_pe_imported_symbols(format, gid, status);
+
+    /* Symbole d'entrée, si encore besoin */
 
-    /* Symboles internes */
+    if (result)
+        result = load_pe_entry_point(format, status);
 
     return result;
 
diff --git a/plugins/pe/symbols.h b/plugins/pe/symbols.h
index 7581152..bb260cd 100644
--- a/plugins/pe/symbols.h
+++ b/plugins/pe/symbols.h
@@ -21,16 +21,21 @@
  */
 
 
-#ifndef _FORMAT_PE_SYMBOLS_H
-#define _FORMAT_PE_SYMBOLS_H
+#ifndef _PLUGINS_PE_SYMBOLS_H
+#define _PLUGINS_PE_SYMBOLS_H
 
 
-#include "pe.h"
+#include "format.h"
+
+
+#include <glibext/delayed.h>
+#include <gtkext/gtkstatusstack.h>
+
 
 
 /* Charge en mémoire la liste humaine des symboles. */
-bool load_pe_symbols(GPeFormat *);
+bool load_pe_symbols(GPeFormat *, wgroup_id_t, GtkStatusStack *);
 
 
 
-#endif  /* _FORMAT_PE_SYMBOLS_H */
+#endif  /* _PLUGINS_PE_SYMBOLS_H */
diff --git a/plugins/pychrysalide/format/constants.c b/plugins/pychrysalide/format/constants.c
index df40479..08d4502 100644
--- a/plugins/pychrysalide/format/constants.c
+++ b/plugins/pychrysalide/format/constants.c
@@ -200,7 +200,6 @@ bool define_binary_symbol_constants(PyTypeObject *type)
 
     result = add_const_to_group(values, "NONE", SFL_NONE);
     if (result) result = add_const_to_group(values, "HAS_NM_PREFIX", SFL_HAS_NM_PREFIX);
-    if (result) result = add_const_to_group(values, "MASK", SFL_MASK);
 
     if (!result)
     {
diff --git a/src/format/strsym.h b/src/format/strsym.h
index 5c8a34f..10ae769 100644
--- a/src/format/strsym.h
+++ b/src/format/strsym.h
@@ -52,8 +52,8 @@ typedef enum _StringEncodingType
 
 
 #define G_TYPE_STR_SYMBOL            g_string_symbol_get_type()
-#define G_STR_SYMBOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), g_string_symbol_get_type(), GStrSymbol))
-#define G_IS_STR_SYMBOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_string_symbol_get_type()))
+#define G_STR_SYMBOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STR_SYMBOL, GStrSymbol))
+#define G_IS_STR_SYMBOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STR_SYMBOL))
 #define G_STR_SYMBOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STR_SYMBOL, GStrSymbolClass))
 #define G_IS_STR_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STR_SYMBOL))
 #define G_STR_SYMBOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STR_SYMBOL, GStrSymbolClass))
diff --git a/src/format/symbol.c b/src/format/symbol.c
index 9e57e14..eb61db8 100644
--- a/src/format/symbol.c
+++ b/src/format/symbol.c
@@ -550,7 +550,7 @@ SymbolFlag g_binary_symbol_get_flags(const GBinSymbol *symbol)
 
     g_bit_lock(&extra->lock, HOLE_LOCK_BIT);
 
-    result = (extra->flags & SFL_MASK);
+    result = extra->flags;
 
     g_bit_unlock(&extra->lock, HOLE_LOCK_BIT);
 
diff --git a/src/format/symbol.h b/src/format/symbol.h
index 577eb83..5235410 100644
--- a/src/format/symbol.h
+++ b/src/format/symbol.h
@@ -63,12 +63,16 @@ typedef enum _SymbolStatus
 } SymbolStatus;
 
 /* Indications supplémentaires liées aux symboles */
+
+#define SFL_USER_BIT 1
+
 typedef enum _SymbolFlag
 {
     SFL_NONE          = (0 << 0),           /* Aucune propriété            */
     SFL_HAS_NM_PREFIX = (1 << 0),           /* Indication de nature        */
 
-    SFL_MASK          = (1 << 1) - 1,       /* Indication de nature        */
+    SFL_LOW_USER      = (1 << SFL_USER_BIT),/* Premier bit disponible      */
+    SFL_HIGH_USER     = (1 << 7),           /* Dernier bit disponible      */
 
 } SymbolFlag;
 
-- 
cgit v0.11.2-87-g4458