From 461f42dd8eb8b1932c11364d9d15367eeb294848 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 24 Nov 2024 08:56:28 +0100
Subject: Restore and improve the support for PE files.

---
 plugins/Makefile.am           |   3 +-
 plugins/pe/Makefile.am        |  17 +-
 plugins/pe/core.c             |   5 +-
 plugins/pe/core.h             |   2 +-
 plugins/pe/format.c           | 640 +++++++++++++++++++++++-------------------
 plugins/pe/format.h           |  30 +-
 plugins/pe/pe-int.c           |  24 +-
 plugins/pe/pe-int.h           |  28 +-
 plugins/pe/pe_def.h           |  55 ++--
 plugins/pe/python/Makefile.am |   8 +-
 plugins/pe/python/constants.c |   5 +-
 plugins/pe/python/constants.h |   2 +-
 plugins/pe/python/format.c    | 204 +++++++++-----
 plugins/pe/python/module.c    |   6 +-
 plugins/pe/python/translate.c | 290 ++++++++++++++++++-
 plugins/pe/python/translate.h |  10 +-
 plugins/pe/section.c          |  73 -----
 plugins/pe/section.h          |  38 ---
 18 files changed, 870 insertions(+), 570 deletions(-)
 delete mode 100644 plugins/pe/section.c
 delete mode 100644 plugins/pe/section.h

diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 9e177fa..89a8e25 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -13,7 +13,8 @@ endif
 
 # androhelpers
 SUBDIRS = \
-	$(PYTHON3_SUBDIRS)
+	$(PYTHON3_SUBDIRS) \
+	pe
 
 # arm \
 # bootimg \
diff --git a/plugins/pe/Makefile.am b/plugins/pe/Makefile.am
index e9cd482..fb04367 100644
--- a/plugins/pe/Makefile.am
+++ b/plugins/pe/Makefile.am
@@ -41,20 +41,23 @@ libpe_la_SOURCES =							\
 	core.h core.c							\
 	pe-int.h pe-int.c						\
 	format.h format.c						\
-	pe_def.h								\
-	rich.h rich.c							\
-	routine.h routine.c						\
-	section.h section.c						\
-	symbols.h symbols.c
+	pe_def.h
+
+
+# rich.h rich.c							\
+# routine.h routine.c						\
+# symbols.h symbols.c
+
+
 
 libpe_la_LIBADD =							\
 	$(PYTHON3_LIBADD)
 
-libpe_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+libpe_la_CFLAGS = $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src
 
 libpe_la_LDFLAGS =							\
 	-avoid-version							\
-	-L$(top_srcdir)/src/.libs -lchrysacore	\
+	-L$(top_srcdir)/src/.libs -lchrysacore4	\
 	$(RUN_PATH) $(PYTHON3_LDFLAGS)
 
 
diff --git a/plugins/pe/core.c b/plugins/pe/core.c
index ddbacf5..e8e6f5e 100644
--- a/plugins/pe/core.c
+++ b/plugins/pe/core.c
@@ -44,7 +44,7 @@
 
 DEFINE_CHRYSALIDE_PLUGIN("Pe", "PE format support",
                          PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/formats"),
-                         PG_REQ, AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
+                         PG_REQ, AL(PGA_PLUGIN_INIT));//, PGA_CONTENT_RESOLVER));
 
 
 
@@ -90,7 +90,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-
+#if 0
 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     */
@@ -114,3 +114,4 @@ G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule
     }
 
 }
+#endif
diff --git a/plugins/pe/core.h b/plugins/pe/core.h
index 4497cf5..2d9aeb5 100644
--- a/plugins/pe/core.h
+++ b/plugins/pe/core.h
@@ -34,7 +34,7 @@
 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 *);
+//G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *);
 
 
 
diff --git a/plugins/pe/format.c b/plugins/pe/format.c
index 3839063..5ecfb18 100644
--- a/plugins/pe/format.c
+++ b/plugins/pe/format.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * pe.c - support du format Portable Executable
  *
- * Copyright (C) 2010-2017 Cyrille Bagard
+ * Copyright (C) 2010-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -25,15 +25,18 @@
 
 
 #include <assert.h>
+#include <string.h>
 
 
 #include "pe-int.h"
-#include "rich.h"
-#include "section.h"
-#include "symbols.h"
+//#include "rich.h"
+//#include "symbols.h"
 
 
 
+/* ------------------------- DEFINITION D'UN NOUVEAU FORMAT ------------------------- */
+
+
 /* Initialise la classe des formats d'exécutables ELF. */
 static void g_pe_format_class_init(GPeFormatClass *);
 
@@ -46,6 +49,11 @@ static void g_pe_format_dispose(GPeFormat *);
 /* Procède à la libération totale de la mémoire. */
 static void g_pe_format_finalize(GPeFormat *);
 
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
 /* Indique la désignation interne du format. */
 static char *g_pe_format_get_key(const GPeFormat *);
 
@@ -53,39 +61,28 @@ static char *g_pe_format_get_key(const GPeFormat *);
 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 *);
+static bool g_pe_format_analyze(GPeFormat *);
 
 /* 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 *);
+static char *g_pe_format_get_target_machine(const GPeFormat *);
 
-/* Fournit l'adresse principale associée à un format Elf. */
+/* Fournit l'adresse principale associée à un format. */
 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
+static bool g_pe_format_refine_portions(GPeFormat *);
 
 /* 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
 
 
 
+/* ---------------------------------------------------------------------------------- */
+/*                           DEFINITION D'UN NOUVEAU FORMAT                           */
+/* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
@@ -116,7 +113,7 @@ bool check_pe_format(const GBinContent *content)
 
     if (result)
     {
-        G_KNOWN_FORMAT(&format)->content = (GBinContent *)content;
+        ((GKnownFormat *)&format)->content = (GBinContent *)content;
         result = read_dos_image_header(&format, &format.dos_header);
     }
 
@@ -137,7 +134,7 @@ bool check_pe_format(const GBinContent *content)
 
 
 /* Indique le type défini pour un format d'exécutable ELF. */
-G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT);
+G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXECUTABLE_FORMAT);
 
 
 /******************************************************************************
@@ -156,8 +153,8 @@ 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       */
+    GProgramFormatClass *prgm;              /* Version en format basique   */
+    GExecutableFormatClass *exe;            /* Version en exécutable       */
 
     object = G_OBJECT_CLASS(klass);
 
@@ -170,20 +167,19 @@ static void g_pe_format_class_init(GPeFormatClass *klass)
     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);
+    prgm = G_PROGRAM_FORMAT_CLASS(klass);
 
-    fmt->get_endian = (format_get_endian_fc)g_pe_format_get_endianness;
+    prgm->get_endian = (program_get_endian_fc)g_pe_format_get_endianness;
+    prgm->get_range_by_name = (get_range_by_name_fc)g_pe_format_get_section_range_by_name;
 
-    exe = G_EXE_FORMAT_CLASS(klass);
+    exe = G_EXECUTABLE_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->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;
+    exe->translate_phys = g_executable_format_translate_offset_into_vmpa_with_portions;
+    exe->translate_virt = g_executable_format_translate_address_into_vmpa_with_portions;
 
 }
 
@@ -262,39 +258,41 @@ static void g_pe_format_finalize(GPeFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-GExeFormat *g_pe_format_new(GBinContent *content)
+GPeFormat *g_pe_format_new(GBinContent *content)
 {
     GPeFormat *result;                      /* Structure à retourner       */
 
-    if (!check_pe_format(content))
-        return NULL;
-
     result = g_object_new(G_TYPE_PE_FORMAT, NULL);
 
-    g_known_format_set_content(G_KNOWN_FORMAT(result), content);
+    if (!g_pe_format_create(result, content))
+        g_clear_object(&result);
 
-    return G_EXE_FORMAT(result);
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
+*  Paramètres  : format  = description du format connu à consulter.           *
+*                content = contenu binaire à parcourir.                       *
 *                                                                             *
-*  Description : Indique la désignation interne du format.                    *
+*  Description : Met en place une nouvelle instance de format PE.             *
 *                                                                             *
-*  Retour      : Désignation du format.                                       *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *g_pe_format_get_key(const GPeFormat *format)
+bool g_pe_format_create(GPeFormat *format, GBinContent *content)
 {
-    char *result;                           /* Désignation à retourner     */
+    bool result;                            /* Bilan à retourner           */
 
-    result = strdup("pe");
+    result = true;//check_pe_format(content);
+
+    if (result)
+        result = g_executable_format_create(G_EXECUTABLE_FORMAT(format), content);
 
     return result;
 
@@ -303,21 +301,21 @@ static char *g_pe_format_get_key(const GPeFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
+*  Paramètres  : format = format en place à consulter.                        *
 *                                                                             *
-*  Description : Fournit une description humaine du format.                   *
+*  Description : Présente l'en-tête MS-DOS du format chargé.                  *
 *                                                                             *
-*  Retour      : Description du format.                                       *
+*  Retour      : Pointeur vers la description principale.                     *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *g_pe_format_get_description(const GPeFormat *format)
+const image_dos_header_t *g_pe_format_get_dos_header(const GPeFormat *format)
 {
-    char *result;                           /* Désignation à retourner     */
+    const image_dos_header_t *result;       /* Informations à retourner    */
 
-    result = strdup("Portable Executable");
+    result = &format->dos_header;
 
     return result;
 
@@ -326,44 +324,21 @@ static char *g_pe_format_get_description(const GPeFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
-*                gid    = groupe de travail dédié.                            *
-*                status = barre de statut à tenir informée.                   *
+*  Paramètres  : format = format en place à consulter.                        *
 *                                                                             *
-*  Description : Assure l'interprétation d'un format en différé.              *
+*  Description : Présente l'en-tête NT du format chargé.                      *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : Pointeur vers la description principale.                     *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_pe_format_analyze(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+const image_nt_headers_t *g_pe_format_get_nt_headers(const GPeFormat *format)
 {
-    bool result;                            /* Bilan à retourner           */
-    GExeFormat *exe;                        /* Autre version du format     */
-    vmpa2t section_start;                   /* Zone de départ des sections */
-
-    exe = G_EXE_FORMAT(format);
-
-    result = read_dos_image_header(format, &format->dos_header);
-    if (!result) goto error;
-
-    result = read_pe_nt_header(format, &format->nt_headers, &section_start);
-    if (!result) goto error;
+    const image_nt_headers_t *result;       /* Informations à retourner    */
 
-    format->sections = read_all_pe_sections(format, &section_start);
-    if (format->sections == NULL) goto error;
-
-    extract_pe_rich_header(format);
-
-    result = load_pe_symbols(format, gid, status);
-    if (!result) goto error;
-
-    result = g_executable_format_complete_loading(exe, gid, status);
-    if (!result) goto error;
-
- error:
+    result = &format->nt_headers;
 
     return result;
 
@@ -372,76 +347,73 @@ static bool g_pe_format_analyze(GPeFormat *format, wgroup_id_t gid, GtkStatusSta
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = informations chargées à consulter.                  *
+*  Paramètres  : format = format en place à consulter.                        *
 *                                                                             *
-*  Description : Informe quant au boutisme utilisé.                           *
+*  Description : Indique si le format PE est en 32 bits ou en 64 bits.        *
 *                                                                             *
-*  Retour      : Indicateur de boutisme.                                      *
+*  Retour      : true si le format est en 32 bits, false sinon.               *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static SourceEndian g_pe_format_get_endianness(const GPeFormat *format)
+bool g_pe_format_get_is_32b(const GPeFormat *format)
 {
-    SourceEndian result;                    /* Boutisme à retourner        */
+    bool result;                            /* Nature à 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
-     */
+    assert(format->loaded);
 
-    result = SRE_LITTLE;
+    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 = informations chargées à consulter.                  *
+*  Paramètres  : format = format en place à consulter.                        *
+*                count  = taille (fixe) du tableau renvoyé. [OUT]             *
 *                                                                             *
-*  Description : Indique le type d'architecture visée par le format.          *
+*  Description : Offre un raccourci vers les répertoires du format PE.        *
 *                                                                             *
-*  Retour      : Identifiant de l'architecture ciblée par le format.          *
+*  Retour      : Pointeur vers le tableau des répertoires.                    *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static const char *g_pe_format_get_target_machine(const GPeFormat *format)
+const image_data_directory_t *g_pe_format_get_directories(const GPeFormat *format, size_t *count)
 {
-    const char *result;                     /* Identifiant à retourner     */
+    const image_data_directory_t *result;   /* Liste à retourner           */
 
-    switch (format->nt_headers.file_header.machine)
+    if (g_pe_format_get_is_32b(format))
     {
-        case IMAGE_FILE_MACHINE_I386:
-            result = "i386";
-            break;
+        result = format->nt_headers.optional_header.header_32.data_directory;
 
-        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;
+        if (count != NULL)
+            *count = format->nt_headers.optional_header.header_32.number_of_rva_and_sizes;
 
-        case IMAGE_FILE_MACHINE_ARM:
-        case IMAGE_FILE_MACHINE_THUMB:
-        case IMAGE_FILE_MACHINE_ARMNT:
-            result = "armv7";
-            break;
+    }
+    else
+    {
+        result = format->nt_headers.optional_header.header_64.data_directory;
 
-        case IMAGE_FILE_MACHINE_UNKNOWN:
-        default:
-            result = NULL;
-            break;
+        if (count != NULL)
+            *count = format->nt_headers.optional_header.header_64.number_of_rva_and_sizes;
 
     }
 
@@ -452,140 +424,174 @@ static const char *g_pe_format_get_target_machine(const GPeFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                addr   = adresse principale trouvée si possible. [OUT]       *
+*  Paramètres  : format = format en place à consulter.                        *
+*                index  = indice du répertoire visé.                          *
 *                                                                             *
-*  Description : Fournit l'adresse principale associée à un format Elf.       *
+*  Description : Extrait le contenu d'un répertoire du format PE.             *
 *                                                                             *
-*  Retour      : Bilan des recherches.                                        *
+*  Retour      : Pointeur vers un contenu chargé ou NULL.                     *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_pe_format_get_main_address(GPeFormat *format, vmpa2t *addr)
+void *g_pe_format_get_directory(const GPeFormat *format, size_t index)
 {
-    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;
+    void *result;                           /* Données à retourner         */
+    size_t max;                             /* Quantité de répertoires     */
+    const image_data_directory_t *dir;      /* Localisation du répertoire  */
+    vmpa2t pos;                             /* Tête de lecture             */
+    bool status;                            /* Bilan d'un traitement       */
+    image_export_directory_t *export;       /* Répertoire de type 0        */
+    image_import_descriptor_t *imports;     /* Répertoire de type 1        */
+    size_t imported_count;                  /* Quantité de DLL requises    */
 
-    base = G_BIN_FORMAT(format);
+    result = NULL;
 
-    if (g_binary_format_find_symbol_by_label(base, "main", &symbol))
-        goto done;
+    dir = g_pe_format_get_directories(format, &max);
 
-    if (g_binary_format_find_symbol_by_label(base, "_start", &symbol))
-        goto done;
+    if (index >= max)
+        goto exit;
 
-    if (g_binary_format_find_symbol_by_label(base, "entry_point", &symbol))
-        goto done;
+    dir += index;
 
- done:
+    status = g_executable_format_translate_address_into_vmpa(G_EXECUTABLE_FORMAT(format),
+                                                             dir->virtual_address, &pos);
+    if (!status) goto exit;
 
-    if (symbol != NULL)
+    switch (index)
     {
-        result = true;
+        case IMAGE_DIRECTORY_ENTRY_EXPORT:
 
-        range = g_binary_symbol_get_range(symbol);
+            export = malloc(sizeof(image_export_directory_t));
 
-        copy_vmpa(addr, get_mrange_addr(range));
+            status = read_pe_image_export_directory(format, &pos, export);
 
-        g_object_unref(G_OBJECT(symbol));
+            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_t));
+
+                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;
 
 }
 
 
-#if 0
-
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = informations chargées à consulter.                  *
+*  Paramètres  : format = format en place à consulter.                        *
+*                count  = taille (fixe) du tableau renvoyé. [OUT]             *
 *                                                                             *
-*  Description : Etend la définition des portions au sein d'un binaire.       *
+*  Description : Offre un raccourci vers les sections du format PE.           *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Pointeur vers la liste des sections.                         *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_pe_format_refine_portions(GPeFormat *format)
+const image_section_header_t *g_pe_format_get_sections(const GPeFormat *format, size_t *count)
 {
+    const image_section_header_t *result;   /* Liste à retourner           */
+
+    if (count != NULL)
+        *count = format->nt_headers.file_header.number_of_sections;
+
+    result = format->sections;
+
+    return result;
 
 }
 
-#endif
 
 
+/* ---------------------------------------------------------------------------------- */
+/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
+/* ---------------------------------------------------------------------------------- */
+
 
 /******************************************************************************
 *                                                                             *
 *  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. *
+*  Description : Indique la désignation interne du format.                    *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : Désignation du format.                                       *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_pe_format_translate_address_into_vmpa_using_portions(GPeFormat *format, virt_t addr, vmpa2t *pos)
+static char *g_pe_format_get_key(const GPeFormat *format)
 {
-    bool result;                            /* Bilan à retourner           */
-    uint16_t i;                             /* Boucle de parcours          */
-    const image_section_header *section;    /* Section à consulter         */
-    phys_t diff;                            /* Décallage à appliquer       */
-
-    result = false;
-
-    for (i = 0; i < format->nt_headers.file_header.number_of_sections && !result; i++)
-    {
-        section = &format->sections[i];
+    char *result;                           /* Désignation à retourner     */
 
-        if (addr < section->virtual_address)
-            continue;
+    result = strdup("pe");
 
-        if (addr >= (section->virtual_address + section->size_of_raw_data))
-            continue;
+    return result;
 
-        diff = addr - section->virtual_address;
+}
 
-        init_vmpa(pos, section->pointer_to_raw_data + diff, addr);
 
-        result = true;
+/******************************************************************************
+*                                                                             *
+*  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     */
 
-    //printf(" // trans // %x -> %x  (valid? %d)\n", (unsigned int)addr, (unsigned int)pos->physical, result);
+    result = strdup("Portable Executable");
 
     return result;
 
 }
 
 
-
-
-#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]          *
+*  Paramètres  : format = format chargé dont l'analyse est lancée.            *
 *                                                                             *
-*  Description : Fournit l'emplacement d'une section donnée.                  *
+*  Description : Assure l'interprétation d'un format en différé.              *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -593,51 +599,82 @@ bool g_pe_format_translate_address_into_vmpa_using_portions(GPeFormat *format, v
 *                                                                             *
 ******************************************************************************/
 
-static bool g_pe_format_get_section_range_by_name(const GPeFormat *format, const char *name, mrange_t *range)
+static bool g_pe_format_analyze(GPeFormat *format)
 {
     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       */
+    vmpa2t start;                           /* Zone de départ des sections */
+    uint16_t count;                         /* Quantité de sections        */
+    uint16_t i;                             /* Boucle de parcours          */
 
-    result = find_elf_section_content_by_name(format, name, &offset, &size, &address);
+    result = read_dos_image_header(format, &format->dos_header);
+    if (!result) goto error;
 
-    if (result)
+    result = read_pe_nt_header(format, &format->nt_headers, &start);
+    if (!result) goto error;
+
+    /* Chargement des définitions des sections déclarées */
+
+    copy_vmpa(&format->sections_start, &start);
+
+    count = format->nt_headers.file_header.number_of_sections;
+
+    format->sections = malloc(count * sizeof(image_section_header_t));
+
+    for (i = 0; i < count; i++)
     {
-        init_vmpa(&tmp, offset, address);
-        init_mrange(range, &tmp, size);
+        result = read_pe_image_section_header(format, &start, &format->sections[i]);
+        if (!result) goto error;
     }
 
-    return result;
+    /* Passage de relais */
 
-}
-#endif
+    if (result)
+        result = G_KNOWN_FORMAT_CLASS(g_pe_format_parent_class)->analyze(G_KNOWN_FORMAT(format));
 
 
 
 
+#if 0
 
+    extract_pe_rich_header(format);
 
+    result = load_pe_symbols(format, gid, status);
+    if (!result) goto error;
+
+#endif
+
+
+ error:
+
+    return result;
+
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = format en place à consulter.                        *
+*  Paramètres  : format = informations chargées à consulter.                  *
 *                                                                             *
-*  Description : Présente l'en-tête MS-DOS du format chargé.                  *
+*  Description : Informe quant au boutisme utilisé.                           *
 *                                                                             *
-*  Retour      : Pointeur vers la description principale.                     *
+*  Retour      : Indicateur de boutisme.                                      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const image_dos_header *g_pe_format_get_dos_header(const GPeFormat *format)
+static SourceEndian g_pe_format_get_endianness(const GPeFormat *format)
 {
-    const image_dos_header *result;         /* Informations à retourner    */
+    SourceEndian result;                    /* Boutisme à retourner        */
 
-    result = &format->dos_header;
+    /**
+     * 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;
 
@@ -646,21 +683,43 @@ const image_dos_header *g_pe_format_get_dos_header(const GPeFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = format en place à consulter.                        *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                name   = nom de la section recherchée.                       *
+*                range  = emplacement en mémoire à renseigner. [OUT]          *
 *                                                                             *
-*  Description : Présente l'en-tête NT du format chargé.                      *
+*  Description : Fournit l'emplacement d'une section donnée.                  *
 *                                                                             *
-*  Retour      : Pointeur vers la description principale.                     *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const image_nt_headers *g_pe_format_get_nt_headers(const GPeFormat *format)
+static bool g_pe_format_get_section_range_by_name(const GPeFormat *format, const char *name, mrange_t *range)
 {
-    const image_nt_headers *result;         /* Informations à retourner    */
+    bool result;                            /* Bilan à retourner           */
+    uint16_t i;                             /* Boucle de parcours          */
+    image_section_header_t *section;        /* Section à traiter           */
+    char tmp[IMAGE_SIZEOF_SHORT_NAME + 1];  /* Nom de la section           */
+    vmpa2t addr;                            /* Emplacement dans le binaire */
 
-    result = &format->nt_headers;
+    result = false;
+
+    for (i = 0, section = format->sections; i < format->nt_headers.file_header.number_of_sections; i++, section++)
+    {
+        memcpy(tmp, section->name, IMAGE_SIZEOF_SHORT_NAME);
+        tmp[IMAGE_SIZEOF_SHORT_NAME] = '\0';
+
+        if (strcmp(name, tmp) != 0)
+            continue;
+
+        init_vmpa(&addr, section->pointer_to_raw_data, section->virtual_address);
+        init_mrange(range, &addr, section->size_of_raw_data);
+
+        result = true;
+        break;
+
+    }
 
     return result;
 
@@ -669,75 +728,78 @@ const image_nt_headers *g_pe_format_get_nt_headers(const GPeFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = format en place à consulter.                        *
+*  Paramètres  : format = informations chargées à consulter.                  *
 *                                                                             *
-*  Description : Indique si le format PE est en 32 bits ou en 64 bits.        *
+*  Description : Indique le type d'architecture visée par le format.          *
 *                                                                             *
-*  Retour      : true si le format est en 32 bits, false sinon.               *
+*  Retour      : Identifiant de l'architecture ciblée par le format.          *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_pe_format_get_is_32b(const GPeFormat *format)
+static char *g_pe_format_get_target_machine(const GPeFormat *format)
 {
-    bool result;                            /* Nature à retourner          */
-
-    assert(format->loaded);
+    char *result;                           /* Identifiant à retourner     */
 
-    switch (format->nt_headers.optional_header.header_32.magic)
+    switch (format->nt_headers.file_header.machine)
     {
-        case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
-            result = true;
+        case IMAGE_FILE_MACHINE_I386:
+            result = strdup("i386");
             break;
-        case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
-            result = false;
+
+        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 = strdup("mips");
             break;
+
+        case IMAGE_FILE_MACHINE_ARM:
+        case IMAGE_FILE_MACHINE_THUMB:
+        case IMAGE_FILE_MACHINE_ARMNT:
+            result = strdup("armv7");
+            break;
+
+        case IMAGE_FILE_MACHINE_UNKNOWN:
         default:
-            result = true;
-            assert(false);
+            result = NULL;
             break;
+
     }
 
     return result;
 
-
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = format en place à consulter.                        *
-*                count  = taille (fixe) du tableau renvoyé. [OUT]             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                addr   = adresse principale trouvée si possible. [OUT]       *
 *                                                                             *
-*  Description : Offre un raccourci vers les répertoires du format PE.        *
+*  Description : Fournit l'adresse principale associée à un format.           *
 *                                                                             *
-*  Retour      : Pointeur vers le tableau des répertoires.                    *
+*  Retour      : Bilan des recherches.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const image_data_directory *g_pe_format_get_directories(const GPeFormat *format, size_t *count)
+static bool g_pe_format_get_main_address(GPeFormat *format, vmpa2t *addr)
 {
-    const image_data_directory *result;     /* Liste à retourner           */
+    bool result;                            /* Bilan à retourner           */
+    virt_t ep;                              /* Point d'entrée              */
 
     if (g_pe_format_get_is_32b(format))
-    {
-        result = format->nt_headers.optional_header.header_32.data_directory;
-
-        if (count != NULL)
-            *count = format->nt_headers.optional_header.header_32.number_of_rva_and_sizes;
-
-    }
+        ep = format->nt_headers.optional_header.header_32.address_of_entry_point;
     else
-    {
-        result = format->nt_headers.optional_header.header_64.data_directory;
-
-        if (count != NULL)
-            *count = format->nt_headers.optional_header.header_64.number_of_rva_and_sizes;
+        ep = format->nt_headers.optional_header.header_64.address_of_entry_point;
 
-    }
+    result = g_executable_format_translate_address_into_vmpa(G_EXECUTABLE_FORMAT(format), ep, addr);
 
     return result;
 
@@ -746,83 +808,75 @@ const image_data_directory *g_pe_format_get_directories(const GPeFormat *format,
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = format en place à consulter.                        *
-*                index  = indice du répertoire visé.                          *
+*  Paramètres  : format = informations chargées à consulter.                  *
 *                                                                             *
-*  Description : Extrait le contenu d'un répertoire du format PE.             *
+*  Description : Etend la définition des portions au sein d'un binaire.       *
 *                                                                             *
-*  Retour      : Pointeur vers un contenu chargé ou NULL.                     *
+*  Retour      : Bilan des définitions de portions.                           *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void *g_pe_format_get_directory(const GPeFormat *format, size_t index)
+static bool g_pe_format_refine_portions(GPeFormat *format)
 {
-    void *result;                           /* Données à retourner         */
-    size_t max;                             /* Quantité de répertoires     */
-    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    */
+    bool result;                            /* Bilan à retourner           */
+    vmpa2t origin;                          /* Origine d'une définition    */
+    uint16_t i;                             /* Boucle de parcours          */
+    image_section_header_t *section;        /* Section à traiter           */
+    vmpa2t addr;                            /* Emplacement dans le binaire */
+    GBinaryPortion *portion;                /* Nouvelle portion de binaire */
+    char name[IMAGE_SIZEOF_SHORT_NAME + 1]; /* Nom de la section           */
+    PortionAccessRights rights;             /* Droits d'accès à la section */
 
-    result = NULL;
+    result = true;
 
-    dir = g_pe_format_get_directories(format, &max);
+    copy_vmpa(&origin, &format->sections_start);
 
-    if (index >= max)
-        goto exit;
+    for (i = 0, section = format->sections; i < format->nt_headers.file_header.number_of_sections; i++, section++)
+    {
+        if (section->pointer_to_raw_data == 0)
+            continue;
 
-    dir += index;
+        /* Emplacement */
 
-    status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), dir->virtual_address, &pos);
-    if (!status) goto exit;
+        init_vmpa(&addr, section->pointer_to_raw_data, section->virtual_address);
 
-    switch (index)
-    {
-        case IMAGE_DIRECTORY_ENTRY_EXPORT:
+        portion = g_binary_portion_new(&addr, section->size_of_raw_data);
 
-            export = malloc(sizeof(image_export_directory));
+        /* Nom */
 
-            status = read_pe_image_export_directory(format, &pos, export);
+        memcpy(name, section->name, IMAGE_SIZEOF_SHORT_NAME);
+        name[IMAGE_SIZEOF_SHORT_NAME] = '\0';
 
-            if (!status)
-            {
-                free(export);
-                goto exit;
-            }
+        g_binary_portion_set_desc(portion, name);
 
-            result = export;
-            break;
+        /* Droits d'accès */
 
-        case IMAGE_DIRECTORY_ENTRY_IMPORT:
+        rights = PAC_NONE;
 
-            imports = NULL;
-            imported_count = 0;
+        if (section->characteristics & IMAGE_SCN_MEM_EXECUTE)
+            rights |= PAC_EXEC;
 
-            do
-            {
-                imports = realloc(imports, ++imported_count * sizeof(image_import_descriptor));
+        if (section->characteristics & IMAGE_SCN_MEM_READ)
+            rights |= PAC_READ;
 
-                status = read_pe_image_import_descriptor(format, &pos, imports + (imported_count - 1));
+        if (section->characteristics & IMAGE_SCN_MEM_WRITE)
+            rights |= PAC_WRITE;
 
-                if (!status)
-                {
-                    free(imports);
-                    goto exit;
-                }
+        g_binary_portion_set_rights(portion, rights);
 
-            }
-            while (imports[imported_count - 1].original_first_thunk != 0);
+        /* Inclusion finale */
 
-            result = imports;
-            break;
+        result = g_executable_format_include_portion(G_EXECUTABLE_FORMAT(format), portion, &origin);
 
-    }
+        unref_object(portion);
 
- exit:
+        if (!result) break;
+
+        advance_vmpa(&origin, sizeof(image_section_header_t));
+
+    }
 
     return result;
 
diff --git a/plugins/pe/format.h b/plugins/pe/format.h
index a48e04d..5cc7c53 100644
--- a/plugins/pe/format.h
+++ b/plugins/pe/format.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * pe.h - prototypes pour le support du format Portable Executable
  *
- * Copyright (C) 2010-2017 Cyrille Bagard
+ * Copyright (C) 2010-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -25,31 +25,20 @@
 #define _PLUGINS_PE_FORMAT_H
 
 
-#include <glib-object.h>
 #include <stdbool.h>
 
 
 #include <analysis/content.h>
-#include <format/executable.h>
+#include <glibext/helpers.h>
 
 
 #include "pe_def.h"
 
 
 
-#define G_TYPE_PE_FORMAT            g_pe_format_get_type()
-#define G_PE_FORMAT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PE_FORMAT, GPeFormat))
-#define G_IS_PE_FORMAT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PE_FORMAT))
-#define G_PE_FORMAT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PE_FORMAT, GPeFormatClass))
-#define G_IS_PE_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PE_FORMAT))
-#define G_PE_FORMAT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PE_FORMAT, GPeFormatClass))
+#define G_TYPE_PE_FORMAT (g_pe_format_get_type())
 
-
-/* Format d'exécutable PE (instance) */
-typedef struct _GPeFormat GPeFormat;
-
-/* Format d'exécutable PE (classe) */
-typedef struct _GPeFormatClass GPeFormatClass;
+DECLARE_GTYPE(GPeFormat, g_pe_format, G, PE_FORMAT);
 
 
 /* Valide un contenu comme étant un format PE. */
@@ -59,23 +48,26 @@ bool check_pe_format(const GBinContent *);
 GType g_pe_format_get_type(void);
 
 /* Prend en charge un nouveau format PE. */
-GExeFormat *g_pe_format_new(GBinContent *);
+GPeFormat *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 *);
+const image_dos_header_t *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 *);
+const image_nt_headers_t *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 *);
+const image_data_directory_t *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);
 
+/* Offre un raccourci vers les sections du format PE. */
+const image_section_header_t *g_pe_format_get_sections(const GPeFormat *, size_t *);
+
 
 
 #endif  /* _PLUGINS_PE_FORMAT_H */
diff --git a/plugins/pe/pe-int.c b/plugins/pe/pe-int.c
index 4104ce1..1c09929 100644
--- a/plugins/pe/pe-int.c
+++ b/plugins/pe/pe-int.c
@@ -28,7 +28,7 @@
 #include <string.h>
 
 #include <i18n.h>
-#include <common/endianness.h>
+#include <common/datatypes.h>
 #include <core/logs.h>
 
 
@@ -46,7 +46,7 @@
 *                                                                             *
 ******************************************************************************/
 
-bool read_dos_image_header(const GPeFormat *format, image_dos_header *header)
+bool read_dos_image_header(const GPeFormat *format, image_dos_header_t *header)
 {
     bool result;                            /* Bilan à retourner           */
     const GBinContent *content;             /* Contenu binaire à lire      */
@@ -104,7 +104,7 @@ bool read_dos_image_header(const GPeFormat *format, image_dos_header *header)
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_file_header(const GPeFormat *format, vmpa2t *pos, image_file_header *header)
+bool read_pe_file_header(const GPeFormat *format, vmpa2t *pos, image_file_header_t *header)
 {
     bool result;                            /* Bilan à retourner           */
     const GBinContent *content;             /* Contenu binaire à lire      */
@@ -140,13 +140,13 @@ bool read_pe_file_header(const GPeFormat *format, vmpa2t *pos, image_file_header
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_optional_header(const GPeFormat *format, vmpa2t *pos, image_optional_header *header)
+bool read_pe_optional_header(const GPeFormat *format, vmpa2t *pos, image_optional_header_t *header)
 {
     bool result;                            /* Bilan à retourner           */
     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       */
+    image_optional_header_32_t *hdr32;      /* Version 32 bits             */
+    image_optional_header_64_t *hdr64;      /* Version 64 bits             */
+    image_data_directory_t *directories;    /* Répertoires à charger       */
     uint32_t *number_of_rva_and_sizes;      /* Quantité de ces répertoires */
     uint32_t i;                             /* Boucle de parcours          */
 
@@ -278,7 +278,7 @@ bool read_pe_optional_header(const GPeFormat *format, vmpa2t *pos, image_optiona
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_nt_header(const GPeFormat *format, image_nt_headers *header, vmpa2t *next)
+bool read_pe_nt_header(const GPeFormat *format, image_nt_headers_t *header, vmpa2t *next)
 {
     bool result;                            /* Bilan à retourner           */
     const GBinContent *content;             /* Contenu binaire à lire      */
@@ -318,7 +318,7 @@ bool read_pe_nt_header(const GPeFormat *format, image_nt_headers *header, vmpa2t
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_section_header *section)
+bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_section_header_t *section)
 {
     bool result;                            /* Bilan à retourner           */
     const GBinContent *content;             /* Contenu binaire à lire      */
@@ -331,7 +331,7 @@ bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_se
     for (i = 0; i < IMAGE_SIZEOF_SHORT_NAME && result; i++)
         result = g_binary_content_read_u8(content, pos, (uint8_t *)&section->name[i]);
 
-    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->misc.physical_address);
+    if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->physical_address);
 
     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);
@@ -361,7 +361,7 @@ bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_se
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_image_export_directory(const GPeFormat *format, vmpa2t *pos, image_export_directory *dir)
+bool read_pe_image_export_directory(const GPeFormat *format, vmpa2t *pos, image_export_directory_t *dir)
 {
     bool result;                            /* Bilan à retourner           */
     const GBinContent *content;             /* Contenu binaire à lire      */
@@ -401,7 +401,7 @@ bool read_pe_image_export_directory(const GPeFormat *format, vmpa2t *pos, image_
 *                                                                             *
 ******************************************************************************/
 
-bool read_pe_image_import_descriptor(const GPeFormat *format, vmpa2t *pos, image_import_descriptor *desc)
+bool read_pe_image_import_descriptor(const GPeFormat *format, vmpa2t *pos, image_import_descriptor_t *desc)
 {
     bool result;                            /* Bilan à retourner           */
     const GBinContent *content;             /* Contenu binaire à lire      */
diff --git a/plugins/pe/pe-int.h b/plugins/pe/pe-int.h
index ebcf3f0..262fe1f 100644
--- a/plugins/pe/pe-int.h
+++ b/plugins/pe/pe-int.h
@@ -36,13 +36,14 @@
 /* Format d'exécutable PE (instance) */
 struct _GPeFormat
 {
-    GExeFormat parent;                      /* A laisser en premier        */
+    GExecutableFormat parent;               /* A laisser en premier        */
 
-    image_dos_header dos_header;            /* En-tête DOS                 */
+    image_dos_header_t dos_header;          /* En-tête DOS                 */
     mrange_t rich_header;                   /* En-tête enrichi             */
-    image_nt_headers nt_headers;            /* En-tête Windows             */
+    image_nt_headers_t nt_headers;          /* En-tête Windows             */
 
-    image_section_header *sections;         /* Liste des sections          */
+    vmpa2t sections_start;                  /* Début de la zone de sections*/
+    image_section_header_t *sections;       /* Liste des sections          */
 
     bool loaded;                            /* Détection partielle menée   */
 
@@ -51,31 +52,34 @@ struct _GPeFormat
 /* Format d'exécutable PE (classe) */
 struct _GPeFormatClass
 {
-    GExeFormatClass parent;                 /* A laisser en premier        */
+    GExecutableFormatClass parent;          /* A laisser en premier        */
 
 };
 
 
+/* Met en place une nouvelle instance de format PE. */
+bool g_pe_format_create(GPeFormat *, GBinContent *);
+
 /* Procède à la lecture d'un en-tête de programme DOS. */
-bool read_dos_image_header(const GPeFormat *, image_dos_header *);
+bool read_dos_image_header(const GPeFormat *, image_dos_header_t *);
 
 /* Procède à la lecture d'un en-tête de programme PE (1). */
-bool read_pe_file_header(const GPeFormat *, vmpa2t *, image_file_header *);
+bool read_pe_file_header(const GPeFormat *, vmpa2t *, image_file_header_t *);
 
 /* Procède à la lecture d'un en-tête de programme PE (2). */
-bool read_pe_optional_header(const GPeFormat *, vmpa2t *, image_optional_header *);
+bool read_pe_optional_header(const GPeFormat *, vmpa2t *, image_optional_header_t *);
 
 /* Procède à la lecture d'un en-tête de programme PE. */
-bool read_pe_nt_header(const GPeFormat *, image_nt_headers *, vmpa2t *);
+bool read_pe_nt_header(const GPeFormat *, image_nt_headers_t *, vmpa2t *);
 
 /* Procède à la lecture d'un en-tête de section PE. */
-bool read_pe_image_section_header(const GPeFormat *, vmpa2t *, image_section_header *);
+bool read_pe_image_section_header(const GPeFormat *, vmpa2t *, image_section_header_t *);
 
 /* Procède à la lecture d'un répertoire d'exportations. */
-bool read_pe_image_export_directory(const GPeFormat *, vmpa2t *, image_export_directory *);
+bool read_pe_image_export_directory(const GPeFormat *, vmpa2t *, image_export_directory_t *);
 
 /* Procède à la lecture d'un répertoire de programme PE. */
-bool read_pe_image_import_descriptor(const GPeFormat *, vmpa2t *, image_import_descriptor *);
+bool read_pe_image_import_descriptor(const GPeFormat *, vmpa2t *, image_import_descriptor_t *);
 
 
 
diff --git a/plugins/pe/pe_def.h b/plugins/pe/pe_def.h
index 62b4607..4812897 100644
--- a/plugins/pe/pe_def.h
+++ b/plugins/pe/pe_def.h
@@ -31,6 +31,7 @@
 /**
  * Références :
  *
+ *  - https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
  *  - 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
  *
@@ -42,7 +43,7 @@
 
 
 /* En-tête DOS */
-typedef struct _image_dos_header
+typedef struct _image_dos_header_t
 {
     uint16_t e_magic;                       /* Numéro magique              */
     uint16_t e_cblp;                        /* Octets de la dernière page  */
@@ -64,7 +65,7 @@ typedef struct _image_dos_header
     uint16_t e_res2[10];                    /* Mots réservés               */
     uint32_t e_lfanew;                      /* Décalage de bon en-tête     */
 
-} image_dos_header;
+} image_dos_header_t;
 
 /* Archtectures supportées */
 
@@ -123,7 +124,7 @@ typedef struct _image_dos_header
 #define IMAGE_FILE_BYTES_REVERSED_HI    0x8000  /* Octets inv. ; obsolète  */
 
 /* Première en-tête du "vrai" format */
-typedef struct _image_file_header
+typedef struct _image_file_header_t
 {
     uint16_t machine;                       /* Type de machine visée       */
     uint16_t number_of_sections;            /* Nombre de sections          */
@@ -133,7 +134,7 @@ typedef struct _image_file_header
     uint16_t size_of_optional_header;       /* Taille de l'en-tête n°2     */
     uint16_t characteristics;               /* Propriétés de l'image       */
 
-} image_file_header;
+} image_file_header_t;
 
 
 
@@ -148,12 +149,12 @@ typedef struct _image_file_header
  */
 
 /* Zone de données Windows */
-typedef struct _image_data_directory
+typedef struct _image_data_directory_t
 {
     uint32_t virtual_address;               /* Adresse de la table         */
     uint32_t size;                          /* Taille de la table          */
 
-} image_data_directory;
+} image_data_directory_t;
 
 // Directory Entries
 #define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory
@@ -182,7 +183,7 @@ typedef struct _image_data_directory
 
 /* Seconde en-tête, optionnelle */
 
-typedef struct _image_optional_header_32
+typedef struct _image_optional_header_32_t
 {
     uint16_t magic;                         /* Type de binaire manipulé    */
     uint8_t major_linker_version;           /* Version majeure du linker   */
@@ -214,11 +215,11 @@ typedef struct _image_optional_header_32
     uint32_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_data_directory_t data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
 
-} image_optional_header_32;
+} image_optional_header_32_t;
 
-typedef struct _image_optional_header_64
+typedef struct _image_optional_header_64_t
 {
 
     uint16_t magic;                         /* Type de binaire manipulé    */
@@ -250,16 +251,16 @@ typedef struct _image_optional_header_64
     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_data_directory_t data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
 
-} image_optional_header_64;
+} image_optional_header_64_t;
 
-typedef union _image_optional_header
+typedef union _image_optional_header_t
 {
-    image_optional_header_32 header_32;     /* Version 32 bits             */
-    image_optional_header_64 header_64;     /* Version 64 bits             */
+    image_optional_header_32_t header_32;   /* Version 32 bits             */
+    image_optional_header_64_t header_64;   /* Version 64 bits             */
 
-} image_optional_header;
+} image_optional_header_t;
 
 
 
@@ -302,13 +303,13 @@ typedef union _image_optional_header
 
 
 /* Résumé global */
-typedef struct _image_nt_headers
+typedef struct _image_nt_headers_t
 {
     uint32_t signature;                     /* Numéro magique              */
-    image_file_header file_header;          /* En-tête n°1                 */
-    image_optional_header optional_header;  /* En-tête n°2                 */
+    image_file_header_t file_header;        /* En-tête n°1                 */
+    image_optional_header_t optional_header;/* En-tête n°2                 */
 
-} image_nt_headers;
+} image_nt_headers_t;
 
 
 
@@ -322,7 +323,7 @@ typedef struct _image_nt_headers
 #define IMAGE_SIZEOF_SHORT_NAME 8
 
 /* Description d'une section */
-typedef struct _image_section_header
+typedef struct _image_section_header_t
 {
     char name[IMAGE_SIZEOF_SHORT_NAME];     /* Nom de la section           */
 
@@ -331,7 +332,7 @@ 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 définies  */
@@ -342,7 +343,7 @@ typedef struct _image_section_header
     uint16_t number_of_line_numbers;        /* Quantité de numéros de ligne*/
     uint32_t characteristics;               /* Caractéristiques            */
 
-} image_section_header;
+} image_section_header_t;
 
 /* Détails des caractéristiques d'une image (champ 'characteristics') */
 #define IMAGE_SCN_UNKNOWN_0         0x00000000  /* Réservé                 */
@@ -400,7 +401,7 @@ typedef struct _image_section_header
  */
 
 /* Répertoire des importations */
-typedef struct _image_export_directory
+typedef struct _image_export_directory_t
 {
     uint32_t characteristics;               /* Zéro !?                     */
     uint32_t time_date_stamp;               /* Date de création du fichier */
@@ -414,7 +415,7 @@ typedef struct _image_export_directory
     uint32_t address_of_names;              /* Liste de RVA de noms        */
     uint32_t address_of_name_ordinals;      /* Liste de RVA d'ordinaux     */
 
-} image_export_directory;
+} image_export_directory_t;
 
 
 /**
@@ -427,7 +428,7 @@ typedef struct _image_export_directory
  */
 
 /* Point de départ de la chaîne des importations */
-typedef struct _image_import_descriptor
+typedef struct _image_import_descriptor_t
 {
     uint32_t original_first_thunk;
     uint32_t time_date_stamp;
@@ -435,7 +436,7 @@ typedef struct _image_import_descriptor
     uint32_t module_name;
     uint32_t first_thunk;
 
-} image_import_descriptor;
+} image_import_descriptor_t;
 
 
 
diff --git a/plugins/pe/python/Makefile.am b/plugins/pe/python/Makefile.am
index 5949821..4a70769 100644
--- a/plugins/pe/python/Makefile.am
+++ b/plugins/pe/python/Makefile.am
@@ -1,14 +1,16 @@
 
 noinst_LTLIBRARIES = libpepython.la
 
+# libpepython_la_SOURCES =					\
+# 	constants.h constants.c					\
+# 	routine.h routine.c
+
 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_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+libpepython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
 	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
 
 
diff --git a/plugins/pe/python/constants.c b/plugins/pe/python/constants.c
index 9b4942d..bb10a7e 100644
--- a/plugins/pe/python/constants.c
+++ b/plugins/pe/python/constants.c
@@ -29,7 +29,7 @@
 
 
 #include "../pe_def.h"
-#include "../routine.h"
+//#include "../routine.h"
 
 
 
@@ -101,7 +101,7 @@ bool define_python_pe_format_constants(PyTypeObject *type)
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-
+#if 0
 bool define_python_pe_exported_routine_constants(PyTypeObject *type)
 {
     bool result;                            /* Bilan à retourner           */
@@ -141,3 +141,4 @@ bool define_python_pe_exported_routine_constants(PyTypeObject *type)
     return result;
 
 }
+#endif
diff --git a/plugins/pe/python/constants.h b/plugins/pe/python/constants.h
index 25b0adb..fe4293c 100644
--- a/plugins/pe/python/constants.h
+++ b/plugins/pe/python/constants.h
@@ -35,7 +35,7 @@
 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 *);
+//bool define_python_pe_exported_routine_constants(PyTypeObject *);
 
 
 
diff --git a/plugins/pe/python/format.c b/plugins/pe/python/format.c
index 4bbb99a..6c97c7d 100644
--- a/plugins/pe/python/format.c
+++ b/plugins/pe/python/format.c
@@ -28,25 +28,23 @@
 #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 "constants.h"
 #include "translate.h"
-#include "../format.h"
-#include "../rich.h"
+#include "../pe-int.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 *);
+CREATE_DYN_CONSTRUCTOR(pe_format, G_TYPE_PE_FORMAT);
 
 /* Initialise une instance sur la base du dérivé de GObject. */
 static int py_pe_format_init(PyObject *, PyObject *, PyObject *);
@@ -59,9 +57,15 @@ static int py_pe_format_init(PyObject *, PyObject *, PyObject *);
 /* Présente l'en-tête MS-DOS du format chargé. */
 static PyObject *py_pe_format_get_dos_header(PyObject *, void *);
 
+/* Présente l'en-tête NT du format chargé. */
+static PyObject *py_pe_format_get_nt_headers(PyObject *, void *);
+
 /* Offre un raccourci vers les répertoires du format PE. */
 static PyObject *py_pe_format_get_directories(PyObject *, void *);
 
+/* Offre un raccourci vers les sections du format PE. */
+static PyObject *py_pe_format_get_sections(PyObject *, void *);
+
 /* Présente l'en-tête enrichi du format chargé. */
 static PyObject *py_pe_format_get_rich_header(PyObject *, void *);
 
@@ -80,66 +84,6 @@ static PyObject *py_pe_format_get_comp_ids(PyObject *, void *);
 
 /******************************************************************************
 *                                                                             *
-*  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);
-
-        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.                    *
@@ -183,7 +127,8 @@ static int py_pe_format_init(PyObject *self, PyObject *args, PyObject *kwds)
 
     format = G_PE_FORMAT(pygobject_get(self));
 
-    g_known_format_set_content(G_KNOWN_FORMAT(format), content);
+    if (!g_pe_format_create(format, content))
+        return -1;
 
     return 0;
 
@@ -223,7 +168,6 @@ static PyObject *py_pe_format_get_dos_header(PyObject *self, void *closure)
     "\n"                                                        \
     "The provided information is composed of the following"     \
     " properties :\n"                                           \
-    "\n"                                                        \
     "* e_magic;\n"                                              \
     "* e_cblp;\n"                                               \
     "* e_cp;\n"                                                 \
@@ -259,6 +203,52 @@ static PyObject *py_pe_format_get_dos_header(PyObject *self, void *closure)
 *  Paramètres  : self    = format en place à consulter.                       *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
+*  Description : Présente l'en-tête NT du format chargé.                      *
+*                                                                             *
+*  Retour      : Structure Python créée pour l'occasion.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_nt_headers(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvaille à retourner      */
+    GPeFormat *format;                      /* Version GLib du format      */
+
+#define PE_FORMAT_NT_HEADERS_ATTRIB PYTHON_GET_DEF_FULL         \
+(                                                               \
+    nt_headers, py_pe_format,                                   \
+    "NT headers of the file format.\n"                          \
+    "\n"                                                        \
+    "This property is a pychrysalide.StructObject instance."    \
+    "\n"                                                        \
+    "The provided information is composed of the following"     \
+    " properties :\n"                                           \
+    "* signature;\n"                                            \
+    "* file_header;\n"                                          \
+    "* optional_header.\n"                                      \
+    "\n"                                                        \
+    "The last two fields are pychrysalide.StructObject"         \
+    " which contain more fields. These fields can be"           \
+    " enumerated with the keys() method (for instance:"         \
+    " *mype.nt_headers.file_header.keys()*).\n"                 \
+)
+
+    format = G_PE_FORMAT(pygobject_get(self));
+
+    result = translate_pe_nt_headers_to_python(format, g_pe_format_get_nt_headers(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.                      *
@@ -272,7 +262,7 @@ 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     */
+    const image_data_directory_t *directories; /* Répertoires à exporter   */
     size_t i;                               /* Boucle de parcours          */
     PyObject *item;                         /* Elément de tableau          */
     int ret;                                /* Bilan d'une mise en place   */
@@ -323,6 +313,76 @@ static PyObject *py_pe_format_get_directories(PyObject *self, void *closure)
 *  Paramètres  : self    = format en place à consulter.                       *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
+*  Description : Offre un raccourci vers les sections du format PE.           *
+*                                                                             *
+*  Retour      : Structure Python créée pour l'occasion.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_sections(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvaille à retourner      */
+    GPeFormat *format;                      /* Version GLib du format      */
+    size_t count;                           /* Quantité de répertoires     */
+    const image_section_header_t *sections; /* Sections à exporter         */
+    size_t i;                               /* Boucle de parcours          */
+    PyObject *item;                         /* Elément de tableau          */
+    int ret;                                /* Bilan d'une mise en place   */
+
+#define PE_FORMAT_SECTIONS_ATTRIB PYTHON_GET_DEF_FULL               \
+(                                                                   \
+    sections, py_pe_format,                                         \
+    "Shortcut to the definitions of all PE format sections.\n"      \
+    "\n"                                                            \
+    "This property is a pychrysalide.StructObject instance.\n"      \
+    "\n"                                                            \
+    "Each returned item is composed of the following properties :\n"\
+    "\n"                                                            \
+    "* name;\n"                                                     \
+    "* misc.virtual_size;\n"                                        \
+    "* virtual_address;\n"			                                \
+    "* size_of_raw_data;\n"			                                \
+    "* pointer_to_raw_data;\n"			                            \
+    "* pointer_to_relocations;\n"			                        \
+    "* pointer_to_line_numbers;\n"			                        \
+    "* number_of_relocations;\n"			                        \
+    "* number_of_line_numbers;\n"			                        \
+    "* characteristics."			                                \
+)
+
+    format = G_PE_FORMAT(pygobject_get(self));
+
+    sections = g_pe_format_get_sections(format, &count);
+
+    result = PyTuple_New(count);
+
+    for (i = 0; i < count; i++)
+    {
+        item = translate_pe_section_header_to_python(format, sections + 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.                     *
@@ -487,7 +547,9 @@ PyTypeObject *get_python_pe_format_type(void)
 
     static PyGetSetDef py_pe_format_getseters[] = {
         PE_FORMAT_DOS_HEADER_ATTRIB,
+        PE_FORMAT_NT_HEADERS_ATTRIB,
         PE_FORMAT_DIRECTORIES_ATTRIB,
+        PE_FORMAT_SECTIONS_ATTRIB,
         PE_FORMAT_RICH_HEADER_ATTRIB,
         PE_FORMAT_RICH_HEADER_CHECKSUM_ATTRIB,
         PE_FORMAT_COMP_IDS_ATTRIB,
@@ -545,8 +607,8 @@ bool register_python_pe_format(PyObject *module)
     if (!register_class_for_pygobject(dict, G_TYPE_PE_FORMAT, type))
         return false;
 
-    if (!define_python_pe_format_constants(type))
-        return false;
+    //if (!define_python_pe_format_constants(type))
+    //    return false;
 
     return true;
 
diff --git a/plugins/pe/python/module.c b/plugins/pe/python/module.c
index 93b1337..ce0c8d7 100644
--- a/plugins/pe/python/module.c
+++ b/plugins/pe/python/module.c
@@ -33,7 +33,7 @@
 
 
 #include "format.h"
-#include "routine.h"
+//#include "routine.h"
 
 
 
@@ -83,8 +83,8 @@ bool add_format_pe_module_to_python_module(void)
     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);
+    //if (result) result = register_python_pe_exported_routine(module);
+    //if (result) result = register_python_pe_imported_routine(module);
 
     assert(result);
 
diff --git a/plugins/pe/python/translate.c b/plugins/pe/python/translate.c
index c01a337..1b4b3ce 100644
--- a/plugins/pe/python/translate.c
+++ b/plugins/pe/python/translate.c
@@ -45,7 +45,7 @@
 *                                                                             *
 ******************************************************************************/
 
-PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_header *header)
+PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_header_t *header)
 {
     PyObject *result;                       /* Construction à retourner    */
     PyTypeObject *base;                     /* Modèle d'objet à créer      */
@@ -64,6 +64,7 @@ PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_h
     {                                                                   \
         attrib = PyLong_FromUnsignedLongLong(header->e_ ## _f);         \
         ret = PyDict_SetItemString(result, "e_" #_f, attrib);           \
+        Py_DECREF(attrib);                                              \
         if (ret != 0) goto failed;                                      \
     }                                                                   \
     while (0);
@@ -79,8 +80,13 @@ PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_h
             ret = PyTuple_SetItem(attrib, i, item);                     \
             if (ret != 0) break;                                        \
         }                                                               \
-        if (ret != 0) goto failed;                                      \
+        if (i < _n)                                                     \
+        {                                                               \
+            Py_DECREF(attrib);                                          \
+            goto failed;                                                \
+        }                                                               \
         ret = PyDict_SetItemString(result, "e_" #_f, attrib);           \
+        Py_DECREF(attrib);                                              \
         if (ret != 0) goto failed;                                      \
     }                                                                   \
     while (0);
@@ -119,6 +125,215 @@ PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_h
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = format PE chargé sur lequel s'appuyer.              *
+*                header = en-tête NT à décrire en Python.                     *
+*                                                                             *
+*  Description : Traduit un en-tête PE en Python.                             *
+*                                                                             *
+*  Retour      : Structure mise en place ou NULL en cas d'erreur.             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *translate_pe_nt_headers_to_python(GPeFormat *format, const image_nt_headers_t *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   */
+    PyObject *sub;                          /* Sous-construction #1        */
+    bool is_32b;                            /* Format en version 32 bits ? */
+    const image_data_directory_t *directories; /* Répertoires à charger    */
+    uint32_t number_of_rva_and_sizes;       /* Quantité de ces répertoires */
+    uint32_t i;                             /* Boucle de parcours          */
+    PyObject *dirs;                         /* Répertoires de données      */
+    PyObject *subsub;                       /* Sous-construction #2        */
+
+    base = get_python_py_struct_type();
+
+    result = PyObject_CallFunction((PyObject *)base, NULL);
+    assert(result != NULL);
+
+#define TRANSLATE_IMAGE_NT_HEADERS_FIELD(_f)                \
+    do                                                      \
+    {                                                       \
+        attrib = PyLong_FromUnsignedLongLong(header->_f);   \
+        ret = PyDict_SetItemString(result, #_f, attrib);    \
+        Py_DECREF(attrib);                                  \
+        if (ret != 0) goto failed;                          \
+    }                                                       \
+    while (0);
+
+    TRANSLATE_IMAGE_NT_HEADERS_FIELD(signature);
+
+    /* Partie file_header */
+
+    sub = PyObject_CallFunction((PyObject *)base, NULL);
+    assert(sub != NULL);
+
+#define TRANSLATE_IMAGE_FILE_HEADER_FIELD(_f)                           \
+    do                                                                  \
+    {                                                                   \
+        attrib = PyLong_FromUnsignedLongLong(header->file_header._f);   \
+        ret = PyDict_SetItemString(sub, #_f, attrib);                   \
+        Py_DECREF(attrib);                                              \
+        if (ret != 0)                                                   \
+        {                                                               \
+            Py_DECREF(sub);                                             \
+            goto failed;                                                \
+        }                                                               \
+    }                                                                   \
+    while (0);
+
+    TRANSLATE_IMAGE_FILE_HEADER_FIELD(machine);
+    TRANSLATE_IMAGE_FILE_HEADER_FIELD(number_of_sections);
+    TRANSLATE_IMAGE_FILE_HEADER_FIELD(time_date_stamp);
+    TRANSLATE_IMAGE_FILE_HEADER_FIELD(pointer_to_symbol_table);
+    TRANSLATE_IMAGE_FILE_HEADER_FIELD(number_of_symbols);
+    TRANSLATE_IMAGE_FILE_HEADER_FIELD(size_of_optional_header);
+    TRANSLATE_IMAGE_FILE_HEADER_FIELD(characteristics);
+
+    ret = PyDict_SetItemString(result, "file_header", sub);
+    Py_DECREF(sub);
+    if (ret != 0) goto failed;
+
+    /* Partie optional_header */
+
+    sub = PyObject_CallFunction((PyObject *)base, NULL);
+    assert(sub != NULL);
+
+    is_32b = g_pe_format_get_is_32b(format);
+
+#define TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(_f)                                       \
+    do                                                                                  \
+    {                                                                                   \
+        if (is_32b)                                                                     \
+            attrib = PyLong_FromUnsignedLongLong(header->optional_header.header_32._f); \
+        else                                                                            \
+            attrib = PyLong_FromUnsignedLongLong(header->optional_header.header_64._f); \
+        ret = PyDict_SetItemString(sub, #_f, attrib);                                   \
+        Py_DECREF(attrib);                                                              \
+        if (ret != 0)                                                                   \
+        {                                                                               \
+            Py_DECREF(sub);                                                             \
+            goto failed;                                                                \
+        }                                                                               \
+    }                                                                                   \
+    while (0);
+
+#define TRANSLATE_IMAGE_OPTIONAL_HEADER_32B_FIELD(_f)                               \
+    do                                                                              \
+    {                                                                               \
+        attrib = PyLong_FromUnsignedLongLong(header->optional_header.header_32._f); \
+        ret = PyDict_SetItemString(sub, #_f, attrib);                               \
+        Py_DECREF(attrib);                                                          \
+        if (ret != 0)                                                               \
+        {                                                                           \
+            Py_DECREF(sub);                                                         \
+            goto failed;                                                            \
+        }                                                                           \
+    }                                                                               \
+    while (0);
+
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(magic);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(major_linker_version);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(minor_linker_version);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_code);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_initialized_data);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_uninitialized_data);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(address_of_entry_point);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(base_of_code);
+    if (is_32b) TRANSLATE_IMAGE_OPTIONAL_HEADER_32B_FIELD(base_of_data);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(image_base);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(section_alignment);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(file_alignment);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(major_operating_system_version);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(minor_operating_system_version);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(major_image_version);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(minor_image_version);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(major_subsystem_version);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(minor_subsystem_version);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(win32_version_value);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_image);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_headers);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(checksum);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(subsystem);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(dll_characteristics);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_stack_reserve);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_stack_commit);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_heap_reserve);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_heap_commit);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(loader_flags);
+    TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(number_of_rva_and_sizes);
+
+    ret = PyDict_SetItemString(result, "optional_header", sub);
+    Py_DECREF(sub);
+    if (ret != 0) goto failed;
+
+    /* Répertoires de données */
+
+    if (is_32b)
+    {
+        directories = header->optional_header.header_32.data_directory;
+        number_of_rva_and_sizes = header->optional_header.header_32.number_of_rva_and_sizes;
+    }
+    else
+    {
+        directories = header->optional_header.header_64.data_directory;
+        number_of_rva_and_sizes = header->optional_header.header_64.number_of_rva_and_sizes;
+    }
+
+    dirs = PyTuple_New(number_of_rva_and_sizes);
+
+    for (i = 0; i < number_of_rva_and_sizes; i++)
+    {
+        subsub = translate_pe_image_data_directory_to_python(format, directories + i);
+        if (subsub == NULL) break;
+
+        ret = PyTuple_SetItem(dirs, i, subsub);
+        if (ret != 0) break;
+
+    }
+
+    if (i < number_of_rva_and_sizes)
+        goto failed_with_dirs;
+
+    /**
+     * La fonction PyTuple_SetItem() comporte le prologue suivant :
+     *
+     *    if (!PyTuple_Check(op) || Py_REFCNT(op) != 1) {
+     *        Py_XDECREF(newitem);
+     *        PyErr_BadInternalCall();
+     *        return -1;
+     *    }
+     *
+     * Comme l'appel à PyDict_SetItemString() incrémente le compte de référence
+     * de dirs, il convient de le réaliser après la consitution de la liste.
+     */
+
+    ret = PyDict_SetItemString(sub, "directories", dirs);
+    if (ret != 0) goto failed_with_dirs;
+
+    Py_DECREF(dirs);
+
+    return result;
+
+ failed_with_dirs:
+
+    Py_DECREF(dirs);
+
+ 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.                          *
@@ -129,7 +344,7 @@ PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_h
 *                                                                             *
 ******************************************************************************/
 
-PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const image_data_directory *dir)
+PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const image_data_directory_t *dir)
 {
     PyObject *result;                       /* Construction à retourner    */
     PyTypeObject *base;                     /* Modèle d'objet à créer      */
@@ -146,6 +361,7 @@ PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const i
     {                                                       \
         attrib = PyLong_FromUnsignedLongLong(dir->_f);      \
         ret = PyDict_SetItemString(result, #_f, attrib);    \
+        Py_DECREF(attrib);                                  \
         if (ret != 0) goto failed;                          \
     }                                                       \
     while (0);
@@ -167,6 +383,73 @@ PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const i
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = format PE chargé sur lequel s'appuyer.              *
+*                header = en-tête de section à décrire en Python.             *
+*                                                                             *
+*  Description : Traduit une section PE en Python.                            *
+*                                                                             *
+*  Retour      : Structure mise en place ou NULL en cas d'erreur.             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *translate_pe_section_header_to_python(GPeFormat *format, const image_section_header_t *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   */
+
+    base = get_python_py_struct_type();
+
+    result = PyObject_CallFunction((PyObject *)base, NULL);
+    assert(result != NULL);
+
+    /* Nom de la section */
+
+    attrib = PyBytes_FromStringAndSize(header->name, IMAGE_SIZEOF_SHORT_NAME);
+
+    ret = PyDict_SetItemString(result, "name", attrib);
+    Py_DECREF(attrib);
+
+    if (ret != 0) goto failed;
+
+    /* Eléments classiques */
+
+#define TRANSLATE_IMAGE_SECTION_HEADER_FIELD(_f)            \
+    do                                                      \
+    {                                                       \
+        attrib = PyLong_FromUnsignedLongLong(header->_f);   \
+        ret = PyDict_SetItemString(result, #_f, attrib);    \
+        Py_DECREF(attrib);                                  \
+        if (ret != 0) goto failed;                          \
+    }                                                       \
+    while (0);
+
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(virtual_size);
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(virtual_address);
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(size_of_raw_data);
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(pointer_to_raw_data);
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(pointer_to_relocations);
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(pointer_to_line_numbers);
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(number_of_relocations);
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(number_of_line_numbers);
+    TRANSLATE_IMAGE_SECTION_HEADER_FIELD(characteristics);
+
+    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.        *
@@ -194,6 +477,7 @@ PyObject *translate_pe_comp_id_to_python(GPeFormat *format, const comp_id_t *id)
     {                                                       \
         attrib = PyLong_FromUnsignedLongLong(id->_f);       \
         ret = PyDict_SetItemString(result, #_f, attrib);    \
+        Py_DECREF(attrib);                                  \
         if (ret != 0) goto failed;                          \
     }                                                       \
     while (0);
diff --git a/plugins/pe/python/translate.h b/plugins/pe/python/translate.h
index dbde6c8..e12b4ae 100644
--- a/plugins/pe/python/translate.h
+++ b/plugins/pe/python/translate.h
@@ -35,10 +35,16 @@
 
 
 /* Traduit un en-tête MS-DOS en Python. */
-PyObject *translate_pe_dos_header_to_python(GPeFormat *, const image_dos_header *);
+PyObject *translate_pe_dos_header_to_python(GPeFormat *, const image_dos_header_t *);
+
+/* Traduit un en-tête PE en Python. */
+PyObject *translate_pe_nt_headers_to_python(GPeFormat *, const image_nt_headers_t *);
 
 /* Traduit un répertoire PE en Python. */
-PyObject *translate_pe_image_data_directory_to_python(GPeFormat *, const image_data_directory *);
+PyObject *translate_pe_image_data_directory_to_python(GPeFormat *, const image_data_directory_t *);
+
+/* Traduit une section PE en Python. */
+PyObject *translate_pe_section_header_to_python(GPeFormat *, const image_section_header_t *);
 
 /* Traduit une série d'informations enrichies en Python. */
 PyObject *translate_pe_comp_id_to_python(GPeFormat *, const comp_id_t *);
diff --git a/plugins/pe/section.c b/plugins/pe/section.c
deleted file mode 100644
index 732b35c..0000000
--- a/plugins/pe/section.c
+++ /dev/null
@@ -1,73 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * section.h - prototypes pour la gestion des sections d'un PE
- *
- * Copyright (C) 2010-2021 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 "section.h"
-
-
-#include <malloc.h>
-
-
-#include "pe-int.h"
-
-
-
-/******************************************************************************
-*                                                                             *
-*  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      : Liste de sections reconstituées ou NULL en cas d'échec.      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-image_section_header *read_all_pe_sections(const GPeFormat *format, vmpa2t *pos)
-{
-    image_section_header *result;           /* Liste à retourner           */
-    uint16_t count;                         /* Quantité de sections        */
-    uint16_t i;                             /* Boucle de parcours          */
-    bool status;                            /* Bilan d'une lecture         */
-
-    count = format->nt_headers.file_header.number_of_sections;
-
-    result = malloc(count * sizeof(image_section_header));
-
-    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
deleted file mode 100644
index 2ac21d3..0000000
--- a/plugins/pe/section.h
+++ /dev/null
@@ -1,38 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * section.h - prototypes pour la gestion des sections d'un PE
- *
- * Copyright (C) 2010-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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _PLUGINS_PE_SECTION_H
-#define _PLUGINS_PE_SECTION_H
-
-
-#include "format.h"
-#include "pe_def.h"
-
-
-
-/* Recherche une section donnée au sein de binaire par indice. */
-image_section_header *read_all_pe_sections(const GPeFormat *, vmpa2t *);
-
-
-
-#endif  /* _PLUGINS_PE_SECTION_H */
-- 
cgit v0.11.2-87-g4458