From ac75fdb77854c6f6d2e8db97a474c8bf3af2b0c4 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 27 Apr 2017 21:55:50 +0200
Subject: Parsed ELF format fields using a new generic parser to save memory.

---
 ChangeLog                   |  24 ++
 configure.ac                |   1 +
 plugins/Makefile.am         |   2 +-
 plugins/fmtp/Makefile.am    |  13 +
 plugins/fmtp/def.h          | 149 ++++++++++
 plugins/fmtp/parser.c       | 223 +++++++++++++++
 plugins/fmtp/parser.h       |  43 +++
 plugins/readelf/Makefile.am |   3 +-
 plugins/readelf/header.c    | 670 +++++++++++++++++++++++---------------------
 plugins/readelf/header.h    |   2 +-
 plugins/readelf/program.c   | 405 +++++++++++++-------------
 plugins/readelf/reader.c    |   2 +-
 plugins/readelf/section.c   | 530 ++++++++++++++++++-----------------
 13 files changed, 1300 insertions(+), 767 deletions(-)
 create mode 100644 plugins/fmtp/Makefile.am
 create mode 100644 plugins/fmtp/def.h
 create mode 100644 plugins/fmtp/parser.c
 create mode 100644 plugins/fmtp/parser.h

diff --git a/ChangeLog b/ChangeLog
index b5de456..c999c6b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+17-04-27  Cyrille Bagard <nocbos@gmail.com>
+
+	* configure.ac:
+	Add the new Makefile from the 'plugins/fmtp' directory.
+
+	* plugins/Makefile.am:
+	Add 'fmtp' to SUBDIRS.
+
+	* plugins/fmtp/Makefile.am:
+	* plugins/fmtp/def.h:
+	* plugins/fmtp/parser.c:
+	* plugins/fmtp/parser.h:
+	New entries: provide a generic parser for format fields.
+
+	* plugins/readelf/Makefile.am:
+	Update LDFLAGS and AM_CPPFLAGS.
+
+	* plugins/readelf/header.c:
+	* plugins/readelf/header.h:
+	* plugins/readelf/program.c:
+	* plugins/readelf/reader.c:
+	* plugins/readelf/section.c:
+	Parse ELF format fields using a new generic parser to save memory.
+
 17-04-22  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/links.c:
diff --git a/configure.ac b/configure.ac
index 60cf9c5..ccace74 100644
--- a/configure.ac
+++ b/configure.ac
@@ -315,6 +315,7 @@ AC_CONFIG_FILES([Makefile
                  pixmaps/Makefile
                  plugins/Makefile
                  plugins/devdbg/Makefile
+                 plugins/fmtp/Makefile
                  plugins/libcsem/Makefile
                  plugins/mobicore/Makefile
                  plugins/pychrysa/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index d0b8fc8..0cbe6fa 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -4,4 +4,4 @@ if HAVE_PYTHON3_CONFIG
 endif
 
 # androhelpers
-SUBDIRS = devdbg libcsem mobicore $(PYTHON3_SUBDIRS) readdex readelf ropgadgets
+SUBDIRS = devdbg fmtp libcsem mobicore $(PYTHON3_SUBDIRS) readdex readelf ropgadgets
diff --git a/plugins/fmtp/Makefile.am b/plugins/fmtp/Makefile.am
new file mode 100644
index 0000000..1c5d0d9
--- /dev/null
+++ b/plugins/fmtp/Makefile.am
@@ -0,0 +1,13 @@
+
+lib_LTLIBRARIES = libfmtp.la
+
+libfmtp_la_SOURCES =					\
+	def.h								\
+	parser.h parser.c
+
+libfmtp_la_CFLAGS = $(AM_CFLAGS)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I../../src
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/fmtp/def.h b/plugins/fmtp/def.h
new file mode 100644
index 0000000..d69d20a
--- /dev/null
+++ b/plugins/fmtp/def.h
@@ -0,0 +1,149 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * def.h - prototypes pour la définition des unités de lecture
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_FMTP_DEF_H
+#define _PLUGINS_FMTP_DEF_H
+
+
+#include <stdbool.h>
+
+
+#include <arch/archbase.h>
+#include <common/cpp.h>
+
+
+
+/**
+ * Assurément utile pour les déclarations...
+ */
+
+#define __(s) s
+
+
+/**
+ * Méthodes de définitions des déclarations.
+ */
+
+/* Possibilités pour un champ à commenter */
+typedef struct _field_desc_switch
+{
+    bool is_range;                          /* Sélection de définition     */
+
+    union
+    {
+        uint64_t fixed;                     /* Valeur fixe                 */
+
+        struct
+        {
+            uint64_t lower;                 /* Borne basse                 */
+            uint64_t upper;                 /* Borne haute                 */
+        };
+
+    };
+
+    const char *desc;                       /* Description associée        */
+
+} field_desc_switch;
+
+/* Partie de commentaire */
+typedef struct _comment_part
+{
+    bool is_static;                         /* Choix du champ textuel      */
+    bool avoid_i18n;                        /* Pas de traduction !         */
+
+    union
+    {
+        const char *static_text;            /* Texte alloué statiquement   */
+        char *dynamic_text;                 /* Texte alloué dynamiquement  */
+    };
+
+} comment_part;
+
+/* Type de commentaires associés */
+typedef enum _FieldCommentType
+{
+    FCT_PLAIN,                              /* Brut et statique            */
+    FCT_SWITCH,                             /* Eventail des possibles      */
+    FCT_MULTI                               /* En plusieurs parties        */
+
+} FieldCommentType;
+
+/* Définition générale */
+typedef struct _fmt_field_def
+{
+    const char *name;                       /* Nom du champ                */
+
+    MemoryDataSize size;                    /* Taille d'un élément         */
+    size_t repeat;                          /* Quantité d'éléments présents*/
+
+    bool is_padding;                        /* Simple bourrage ?           */
+
+    bool has_display_rules;                 /* Validité des champs suivants*/
+    const ImmOperandDisplay *disp_rules;    /* Règles d'affichage          */
+    size_t disp_count;                      /* Quantité de ces règles      */
+
+    FieldCommentType ctype;                 /* Type de commentaire         */
+    union
+    {
+        const char *plain;                  /* Commentaire simple          */
+
+        struct
+        {
+            const field_desc_switch *choices; /* Choix multiples           */
+            size_t ccount;                  /* Quantité de ces choix       */
+            const char *def_choice;         /* Commentaire par défaut      */
+        };
+
+        struct
+        {
+            comment_part *parts;            /* Parties à considérer        */
+            size_t pcount;                  /* Quantité de ces parties     */
+        };
+
+    } comment;
+
+} fmt_field_def;
+
+
+/* Règles d'affichage */
+
+#define DISPLAY_RULES(...)                                              \
+    .has_display_rules = true,                                          \
+    .disp_rules = (ImmOperandDisplay []) { __VA_ARGS__ },               \
+    .disp_count = ARRAY_SIZE(((ImmOperandDisplay []) { __VA_ARGS__ }))
+
+/* Rédaction des commentaires */
+
+#define PLAIN_COMMENT(txt)                  \
+    .ctype = FCT_PLAIN,                     \
+    .comment.plain = txt
+
+#define SWITCH_COMMENT(array, def)          \
+    .ctype = FCT_SWITCH,                    \
+    .comment.choices = array,               \
+    .comment.ccount = ARRAY_SIZE(array),    \
+    .comment.def_choice = def
+
+
+
+#endif  /* _PLUGINS_FMTP_DEF_H */
diff --git a/plugins/fmtp/parser.c b/plugins/fmtp/parser.c
new file mode 100644
index 0000000..2f469c1
--- /dev/null
+++ b/plugins/fmtp/parser.c
@@ -0,0 +1,223 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.c - interprétation des champs d'un format binaire
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "parser.h"
+
+
+#include <assert.h>
+
+
+#include <i18n.h>
+#include <arch/raw.h>
+
+
+
+/* Effectue l'interprétation d'une définition de champ. */
+static bool parse_field_definition(const fmt_field_def *, GBinFormat *, vmpa2t *);
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : def    = définition de champ à considérer.                   *
+*                format = description de l'exécutable à compléter.            *
+*                pos    = tête de lecture pour les données.                   *
+*                                                                             *
+*  Description : Effectue l'interprétation d'une définition de champ.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool parse_field_definition(const fmt_field_def *def, GBinFormat *format, vmpa2t *pos)
+{
+    GBinContent *content;                   /* Contenu binaire à lire      */
+    SourceEndian endian;                    /* Boutisme utilisé            */
+    bool result;                            /* Bilan à retourner           */
+    GArchInstruction *instr;                /* Instruction décodée         */
+    GImmOperand *imm;                       /* Opérande à transformer      */
+    size_t i;                               /* Boucle de parcours          */
+    const vmpa2t *addr;                     /* Emplacement d'instruction   */
+    GDbComment *comment;                    /* Définition de commentaire   */
+    uint64_t raw;                           /* Valeur brute à étudier      */
+    const comment_part *part;               /* Accès plus direct           */
+
+
+    GBinSymbol *symbol;                     /* Symbole à intégrer          */
+
+
+    /* Lecture */
+
+    content = g_binary_format_get_content(format);
+    endian = g_binary_format_get_endianness(format);
+
+    assert(def->repeat > 0);
+
+    instr = g_raw_instruction_new_array(content, def->size, def->repeat, pos, endian);
+
+    result = (instr != NULL);
+
+    if (!result)
+        goto pfd_exit;
+
+    if (def->is_padding)
+        g_raw_instruction_mark_as_padding(G_RAW_INSTRUCTION(instr), true);
+
+    if (def->has_display_rules)
+    {
+        assert(def->disp_count <= def->repeat);
+
+        for (i = 0; i < def->disp_count; i++)
+        {
+            imm = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, i));
+
+            g_imm_operand_set_default_display(&imm, def->disp_rules[i], G_SHARE_CONTAINER(instr));
+            g_imm_operand_set_display(&imm, def->disp_rules[i], G_SHARE_CONTAINER(instr));
+
+            // TODO : unref(imm)
+
+        }
+
+    }
+
+    /* Commentaire */
+
+    addr = get_mrange_addr(g_arch_instruction_get_range(instr));
+
+    comment = g_db_comment_new_inlined(addr, BLF_HAS_CODE, false);
+    g_db_item_set_volatile(G_DB_ITEM(comment), true);
+
+    switch (def->ctype)
+    {
+        case FCT_PLAIN:
+            g_db_comment_add_static_text(comment, _(def->comment.plain));
+            break;
+
+        case FCT_SWITCH:
+
+            imm = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 0));
+            raw = g_imm_operand_get_raw_value(imm);
+            // TODO : unref(imm)
+
+            for (i = 0; i < def->comment.ccount; i++)
+            {
+                if (def->comment.choices[i].is_range)
+                {
+                    if (raw < def->comment.choices[i].lower)
+                        continue;
+                    if (raw > def->comment.choices[i].upper)
+                        continue;
+                }
+
+                else if (raw != def->comment.choices[i].fixed)
+                    continue;
+
+                g_db_comment_add_static_text(comment, _(def->comment.choices[i].desc));
+                break;
+
+            }
+
+            if (i == def->comment.ccount)
+                g_db_comment_add_static_text(comment, _(def->comment.def_choice));
+
+            break;
+
+        case FCT_MULTI:
+
+            for (i = 0; i < def->comment.pcount; i++)
+            {
+                part = &def->comment.parts[i];
+
+                if (part->is_static)
+                {
+                    if (part->avoid_i18n)
+                        g_db_comment_add_static_text(comment, part->static_text);
+                    else
+                        g_db_comment_add_static_text(comment, _(part->static_text));
+                }
+                else
+                {
+                    if (part->avoid_i18n)
+                        g_db_comment_add_dynamic_text(comment, part->dynamic_text);
+                    else
+                        g_db_comment_add_dynamic_text(comment, _(part->dynamic_text));
+                }
+
+            }
+
+            break;
+
+    }
+
+    /* Insertion */
+
+    symbol = g_binary_symbol_new(STP_DATA);
+
+    g_binary_symbol_attach_instruction(symbol, instr);
+    g_binary_symbol_set_comment(symbol, comment);
+
+    result = g_binary_format_add_symbol(format, symbol);
+
+    if (!result)
+        g_object_unref(G_OBJECT(instr));
+
+ pfd_exit:
+
+    g_object_unref(G_OBJECT(content));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : defs   = liste de définitions à traiter.                     *
+*                count  = taille de cette liste.                              *
+*                format = description de l'exécutable à compléter.            *
+*                pos    = tête de lecture pour les données.                   *
+*                                                                             *
+*  Description : Lance l'interprétation d'une série de définitions de champs. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool parse_field_definitions(const fmt_field_def *defs, size_t count, GBinFormat *format, vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    for (i = 0; i < count && result; i++)
+        result = parse_field_definition(defs + i, format, pos);
+
+    return result;
+
+}
diff --git a/plugins/fmtp/parser.h b/plugins/fmtp/parser.h
new file mode 100644
index 0000000..dcd9bf2
--- /dev/null
+++ b/plugins/fmtp/parser.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.h - prototypes pour l'interprétation des champs d'un format binaire
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_FMTP_PARSER_H
+#define _PLUGINS_FMTP_PARSER_H
+
+
+#include <stdbool.h>
+
+
+#include <format/format.h>
+
+
+#include "def.h"
+
+
+
+/* Lance l'interprétation d'une série de définitions de champs. */
+bool parse_field_definitions(const fmt_field_def *, size_t, GBinFormat *, vmpa2t *);
+
+
+
+#endif  /* _PLUGINS_FMTP_PARSER_H */
diff --git a/plugins/readelf/Makefile.am b/plugins/readelf/Makefile.am
index 13f45f8..c3cf822 100644
--- a/plugins/readelf/Makefile.am
+++ b/plugins/readelf/Makefile.am
@@ -10,7 +10,8 @@ libreadelf_la_SOURCES =					\
 
 libreadelf_la_CFLAGS = $(AM_CFLAGS)
 
+libreadelf_la_LDFLAGS = -L../../plugins/fmtp/.libs -lfmtp
 
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I../../src
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I../../src -I../..
 
 AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/readelf/header.c b/plugins/readelf/header.c
index d0aee92..21884a3 100644
--- a/plugins/readelf/header.c
+++ b/plugins/readelf/header.c
@@ -24,435 +24,473 @@
 #include "header.h"
 
 
-#include <i18n.h>
-#include <arch/raw.h>
-#include <format/symbol.h>
+#include <common/cpp.h>
+#include <plugins/fmtp/parser.h>
+
+
+
+/* Définition des champs */
+
+static field_desc_switch _elf_classes[] = {
+
+    { .fixed = EV_NONE,    .desc = __("File class: invalid") },
+    { .fixed = ELFCLASS32, .desc = __("File class: 32-bit objects") },
+    { .fixed = ELFCLASS64, .desc = __("File class: 64-bit objects") }
+
+};
+
+static field_desc_switch _elf_data[] = {
+
+    { .fixed = ELFDATANONE, .desc = __("Data encoding: invalid") },
+    { .fixed = ELFDATA2LSB, .desc = __("Data encoding: 2's complement, little endian") },
+    { .fixed = ELFDATA2MSB, .desc = __("Data encoding: 2's complement, big endian") }
+
+};
+
+static field_desc_switch _elf_versions[] = {
+
+    { .fixed = EV_NONE,    .desc = __("File version: invalid") },
+    { .fixed = EV_CURRENT, .desc = __("File version: current") }
+
+};
+
+static field_desc_switch _elf_os_abis[] = {
+
+    { .fixed = ELFOSABI_SYSV,       .desc = __("OS ABI: UNIX System V ABI") },
+    { .fixed = ELFOSABI_HPUX,       .desc = __("OS ABI: HP-UX") },
+    { .fixed = ELFOSABI_NETBSD,     .desc = __("OS ABI: NetBSD") },
+    { .fixed = ELFOSABI_GNU,        .desc = __("OS ABI: Object uses GNU ELF extensions") },
+    { .fixed = ELFOSABI_SOLARIS,    .desc = __("OS ABI: Sun Solaris") },
+    { .fixed = ELFOSABI_AIX,        .desc = __("OS ABI: IBM AIX") },
+    { .fixed = ELFOSABI_IRIX,       .desc = __("OS ABI: SGI Irix") },
+    { .fixed = ELFOSABI_FREEBSD,    .desc = __("OS ABI: FreeBSD") },
+    { .fixed = ELFOSABI_TRU64,      .desc = __("OS ABI: Compaq TRU64 UNIX") },
+    { .fixed = ELFOSABI_MODESTO,    .desc = __("OS ABI: Novell Modesto") },
+    { .fixed = ELFOSABI_OPENBSD,    .desc = __("OS ABI: OpenBSD") },
+    { .fixed = ELFOSABI_ARM_AEABI,  .desc = __("OS ABI: ARM EABI") },
+    { .fixed = ELFOSABI_ARM,        .desc = __("OS ABI: ARM") },
+    { .fixed = ELFOSABI_STANDALONE, .desc = __("OS ABI: Standalone (embedded) application") }
+
+};
+
+static field_desc_switch _elf_types[] = {
+
+    { .fixed = ET_NONE, .desc = __("Object file type: no file type") },
+    { .fixed = ET_REL,  .desc = __("Object file type: relocatable file") },
+    { .fixed = ET_EXEC, .desc = __("Object file type: executable file") },
+    { .fixed = ET_DYN,  .desc = __("Object file type: shared object file") },
+    { .fixed = ET_CORE, .desc = __("Object file type: core file") },
+    { .lower = ET_LOOS,   .upper = ET_HIOS,   .desc = __("Object file type: OS-specific") },
+    { .lower = ET_LOPROC, .upper = ET_HIPROC, .desc = __("Object file type: processor-specific") }
+
+};
+
+static field_desc_switch _elf_machines[] = {
+
+    { .fixed = EM_NONE,        .desc = __("Architecture: No machine") },
+    { .fixed = EM_M32,         .desc = __("Architecture: AT&T WE 32100") },
+    { .fixed = EM_SPARC,       .desc = __("Architecture: SUN SPARC") },
+    { .fixed = EM_386,         .desc = __("Architecture: Intel 80386") },
+    { .fixed = EM_68K,         .desc = __("Architecture: Motorola m68k family") },
+    { .fixed = EM_88K,         .desc = __("Architecture: Motorola m88k family") },
+    { .fixed = EM_860,         .desc = __("Architecture: Intel 80860") },
+    { .fixed = EM_MIPS,        .desc = __("Architecture: MIPS R3000 big-endian") },
+    { .fixed = EM_S370,        .desc = __("Architecture: IBM System/370") },
+    { .fixed = EM_MIPS_RS3_LE, .desc = __("Architecture: MIPS R3000 little-endian") },
+    { .fixed = EM_PARISC,      .desc = __("Architecture: HPPA") },
+    { .fixed = EM_VPP500,      .desc = __("Architecture: Fujitsu VPP500") },
+    { .fixed = EM_SPARC32PLUS, .desc = __("Architecture: Sun's \"v8plus\"") },
+    { .fixed = EM_960,         .desc = __("Architecture: Intel 80960") },
+    { .fixed = EM_PPC,         .desc = __("Architecture: PowerPC") },
+    { .fixed = EM_PPC64,       .desc = __("Architecture: PowerPC 64-bit") },
+    { .fixed = EM_S390,        .desc = __("Architecture: IBM S390") },
+    { .fixed = EM_V800,        .desc = __("Architecture: NEC V800 series") },
+    { .fixed = EM_FR20,        .desc = __("Architecture: Fujitsu FR20") },
+    { .fixed = EM_RH32,        .desc = __("Architecture: TRW RH-32") },
+    { .fixed = EM_RCE,         .desc = __("Architecture: Motorola RCE") },
+    { .fixed = EM_ARM,         .desc = __("Architecture: ARM") },
+    { .fixed = EM_FAKE_ALPHA,  .desc = __("Architecture: Digital Alpha") },
+    { .fixed = EM_SH,          .desc = __("Architecture: Hitachi SH") },
+    { .fixed = EM_SPARCV9,     .desc = __("Architecture: SPARC v9 64-bit") },
+    { .fixed = EM_TRICORE,     .desc = __("Architecture: Siemens Tricore") },
+    { .fixed = EM_ARC,         .desc = __("Architecture: Argonaut RISC Core") },
+    { .fixed = EM_H8_300,      .desc = __("Architecture: Hitachi H8/300") },
+    { .fixed = EM_H8_300H,     .desc = __("Architecture: Hitachi H8/300H") },
+    { .fixed = EM_H8S,         .desc = __("Architecture: Hitachi H8S") },
+    { .fixed = EM_H8_500,      .desc = __("Architecture: Hitachi H8/500") },
+    { .fixed = EM_IA_64,       .desc = __("Architecture: Intel Merced") },
+    { .fixed = EM_MIPS_X,      .desc = __("Architecture: Stanford MIPS-X") },
+    { .fixed = EM_COLDFIRE,    .desc = __("Architecture: Motorola Coldfire") },
+    { .fixed = EM_68HC12,      .desc = __("Architecture: Motorola M68HC12") },
+    { .fixed = EM_MMA,         .desc = __("Architecture: Fujitsu MMA Multimedia Accelerator") },
+    { .fixed = EM_PCP,         .desc = __("Architecture: Siemens PCP") },
+    { .fixed = EM_NCPU,        .desc = __("Architecture: Sony nCPU embeeded RISC") },
+    { .fixed = EM_NDR1,        .desc = __("Architecture: Denso NDR1 microprocessor") },
+    { .fixed = EM_STARCORE,    .desc = __("Architecture: Motorola Start*Core processor") },
+    { .fixed = EM_ME16,        .desc = __("Architecture: Toyota ME16 processor") },
+    { .fixed = EM_ST100,       .desc = __("Architecture: STMicroelectronic ST100 processor") },
+    { .fixed = EM_TINYJ,       .desc = __("Architecture: Advanced Logic Corp. Tinyj emb.fam") },
+    { .fixed = EM_X86_64,      .desc = __("Architecture: AMD x86-64 architecture") },
+    { .fixed = EM_PDSP,        .desc = __("Architecture: Sony DSP Processor") },
+    { .fixed = EM_FX66,        .desc = __("Architecture: Siemens FX66 microcontroller") },
+    { .fixed = EM_ST9PLUS,     .desc = __("Architecture: STMicroelectronics ST9+ 8/16 mc") },
+    { .fixed = EM_ST7,         .desc = __("Architecture: STmicroelectronics ST7 8 bit mc") },
+    { .fixed = EM_68HC16,      .desc = __("Architecture: Motorola MC68HC16 microcontroller") },
+    { .fixed = EM_68HC11,      .desc = __("Architecture: Motorola MC68HC11 microcontroller") },
+    { .fixed = EM_68HC08,      .desc = __("Architecture: Motorola MC68HC08 microcontroller") },
+    { .fixed = EM_68HC05,      .desc = __("Architecture: Motorola MC68HC05 microcontroller") },
+    { .fixed = EM_SVX,         .desc = __("Architecture: Silicon Graphics SVx") },
+    { .fixed = EM_ST19,        .desc = __("Architecture: STMicroelectronics ST19 8 bit mc") },
+    { .fixed = EM_VAX,         .desc = __("Architecture: Digital VAX") },
+    { .fixed = EM_CRIS,        .desc = __("Architecture: Axis Communications 32-bit embedded processor") },
+    { .fixed = EM_JAVELIN,     .desc = __("Architecture: Infineon Technologies 32-bit embedded processor") },
+    { .fixed = EM_FIREPATH,    .desc = __("Architecture: Element 14 64-bit DSP Processor") },
+    { .fixed = EM_ZSP,         .desc = __("Architecture: LSI Logic 16-bit DSP Processor") },
+    { .fixed = EM_MMIX,        .desc = __("Architecture: Donald Knuth's educational 64-bit processor") },
+    { .fixed = EM_HUANY,       .desc = __("Architecture: Harvard University machine-independent object files") },
+    { .fixed = EM_PRISM,       .desc = __("Architecture: SiTera Prism") },
+    { .fixed = EM_AVR,         .desc = __("Architecture: Atmel AVR 8-bit microcontroller") },
+    { .fixed = EM_FR30,        .desc = __("Architecture: Fujitsu FR30") },
+    { .fixed = EM_D10V,        .desc = __("Architecture: Mitsubishi D10V") },
+    { .fixed = EM_D30V,        .desc = __("Architecture: Mitsubishi D30V") },
+    { .fixed = EM_V850,        .desc = __("Architecture: NEC v850") },
+    { .fixed = EM_M32R,        .desc = __("Architecture: Mitsubishi M32R") },
+    { .fixed = EM_MN10300,     .desc = __("Architecture: Matsushita MN10300") },
+    { .fixed = EM_MN10200,     .desc = __("Architecture: Matsushita MN10200") },
+    { .fixed = EM_PJ,          .desc = __("Architecture: picoJava") },
+    { .fixed = EM_OPENRISC,    .desc = __("Architecture: OpenRISC 32-bit embedded processor") },
+    { .fixed = EM_ARC_A5,      .desc = __("Architecture: ARC Cores Tangent-A5") },
+    { .fixed = EM_XTENSA,      .desc = __("Architecture: Tensilica Xtensa Architecture") },
+    { .fixed = EM_AARCH64,     .desc = __("Architecture: ARM AARCH64") },
+    { .fixed = EM_TILEPRO,     .desc = __("Architecture: Tilera TILEPro") },
+    { .fixed = EM_MICROBLAZE,  .desc = __("Architecture: Xilinx MicroBlaze") },
+    { .fixed = EM_TILEGX,      .desc = __("Architecture: Tilera TILE-Gx") }
+
+};
+
+static fmt_field_def _elf_header_base[] = {
 
+    {
+        .name = "e_ident[EI_MAG]",
 
+        .size = MDS_8_BITS,
+        .repeat = 4,
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à compléter.            *
-*                                                                             *
-*  Description : Charge tous les symboles de l'en-tête ELF.                   *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+        DISPLAY_RULES(IOD_HEX, IOD_CHAR, IOD_CHAR, IOD_CHAR),
 
-bool annotate_elf_header(GElfFormat *format)
-{
-    GBinContent *content;                   /* Contenu binaire à lire      */
-    const elf_header *header;               /* En-tête principale          */
-    SourceEndian endian;                    /* Boutisme utilisé            */
-    vmpa2t pos;                             /* Tête de lecture des symboles*/
-    GArchInstruction *instr;                /* Instruction décodée         */
-    GArchOperand *operand;                  /* Opérande à venir modifier   */
-    GDbComment *comment;                    /* Définition de commentaire   */
-    GBinSymbol *symbol;                     /* Symbole à intégrer          */
-    const char *text;                       /* Texte constant à insérer    */
+        PLAIN_COMMENT(__("ELF magic number"))
 
-    content = g_binary_format_get_content(G_BIN_FORMAT(format));
+    },
 
-    header = g_elf_format_get_header(format);
-    endian = g_binary_format_get_endianness(G_BIN_FORMAT(format));
+    {
+        .name = "e_ident[EI_CLASS]",
+
+        .size = MDS_8_BITS,
+        .repeat = 1,
+
+        DISPLAY_RULES(IOD_DEC),
 
-    if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), 0, &pos))
-        return false;
+        SWITCH_COMMENT(_elf_classes, __("File class: unknown"))
 
-    /* ELFMAG (0) */
+    },
+
+    {
+        .name = "e_ident[EI_DATA]",
 
-    instr = g_raw_instruction_new_array(content, MDS_8_BITS, 4, &pos, endian);
+        .size = MDS_8_BITS,
+        .repeat = 1,
 
-    SET_IMM_DISPLAY(instr, operand, 1, IOD_CHAR);
-    SET_IMM_DISPLAY(instr, operand, 2, IOD_CHAR);
-    SET_IMM_DISPLAY(instr, operand, 3, IOD_CHAR);
+        DISPLAY_RULES(IOD_DEC),
 
-    ADD_RAW_AS_SYM_CST(format, symbol, instr, comment, _("ELF magic number"));
+        SWITCH_COMMENT(_elf_data, __("Data encoding: unknown"))
 
-    /* EI_CLASS (4) */
+    },
 
-    switch (header->hdr32.e_ident[EI_CLASS])
     {
-        case EV_NONE:
-            text = _("File class: invalid");
-            break;
-        case ELFCLASS32:
-            text = _("File class: 32-bit objects");
-            break;
-        case ELFCLASS64:
-            text = _("File class: 64-bit objects");
-            break;
-        default:
-            text = _("File class: unknown");
-            break;
-    }
+        .name = "e_ident[EI_VERSION]",
 
-    instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, &pos, endian);
+        .size = MDS_8_BITS,
+        .repeat = 1,
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        DISPLAY_RULES(IOD_DEC),
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, text);
+        SWITCH_COMMENT(_elf_versions, __("File version: unknown"))
 
-    /* EI_DATA (5) */
+    },
 
-    switch (header->hdr32.e_ident[EI_DATA])
     {
-        case ELFDATANONE:
-            text = _("Data encoding: invalid");
-            break;
-        case ELFDATA2LSB:
-            text = _("Data encoding: 2's complement, little endian");
-            break;
-        case ELFDATA2MSB:
-            text = _("Data encoding: 2's complement, big endian");
-            break;
-        default:
-            text = _("Data encoding: unknown");
-            break;
-    }
+        .name = "e_ident[EI_OSABI]",
 
-    instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, &pos, endian);
+        .size = MDS_8_BITS,
+        .repeat = 1,
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        DISPLAY_RULES(IOD_DEC),
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, text);
+        SWITCH_COMMENT(_elf_os_abis, __("OS ABI: unknown"))
 
-    /* EI_VERSION (6) */
+    },
 
-    switch (header->hdr32.e_ident[EI_VERSION])
     {
-        case EV_NONE:
-            text = _("File version: invalid");
-            break;
-        case EV_CURRENT:
-            text = _("File version: current");
-            break;
-        default:
-            text = _("File version: unknown");
-            break;
-    }
+        .name = "e_ident[EI_ABIVERSION]",
 
-    instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, &pos, endian);
+        .size = MDS_8_BITS,
+        .repeat = 1,
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        DISPLAY_RULES(IOD_DEC),
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, text);
+        PLAIN_COMMENT(__("ABI version"))
 
-    /* EI_OSABI (7) */
+    },
 
-    switch (header->hdr32.e_ident[EI_OSABI])
     {
-        case ELFOSABI_SYSV:
-            text = _("OS ABI: UNIX System V");
-            break;
-        case ELFOSABI_HPUX:
-            text = _("OS ABI: HP-UX");
-            break;
-        case ELFOSABI_NETBSD:
-            text = _("OS ABI: NetBSD");
-            break;
-        case ELFOSABI_GNU:
-            text = _("OS ABI: object uses GNU ELF extensions");
-            break;
-        case ELFOSABI_SOLARIS:
-            text = _("OS ABI: Sun Solaris");
-            break;
-        case ELFOSABI_AIX:
-            text = _("OS ABI: IBM AIX");
-            break;
-        case ELFOSABI_IRIX:
-            text = _("OS ABI: SGI Irix");
-            break;
-        case ELFOSABI_FREEBSD:
-            text = _("OS ABI: FreeBSD");
-            break;
-        case ELFOSABI_TRU64:
-            text = _("OS ABI: Compaq TRU64 UNIX");
-            break;
-        case ELFOSABI_MODESTO:
-            text = _("OS ABI: Novell Modesto");
-            break;
-        case ELFOSABI_OPENBSD:
-            text = _("OS ABI: OpenBSD");
-            break;
-        case ELFOSABI_ARM_AEABI:
-            text = _("OS ABI: ARM EABI");
-            break;
-        case ELFOSABI_ARM:
-            text = _("OS ABI: ARM");
-            break;
-        case ELFOSABI_STANDALONE:
-            text = _("OS ABI: standalone (embedded) application");
-            break;
-        default:
-            text = _("OS ABI: unknown");
-            break;
-    }
+        .name = "...",
+
+        .size = MDS_8_BITS,
+        .repeat = 7,
 
-    instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, &pos, endian);
+        .is_padding = true,
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        PLAIN_COMMENT(__("Padding"))
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, text);
+    },
 
-    /* EI_ABIVERSION (8) */
+    {
+        .name = "e_type",
+
+        .size = MDS_16_BITS,
+        .repeat = 1,
 
-    instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, &pos, endian);
+        DISPLAY_RULES(IOD_DEC),
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        SWITCH_COMMENT(_elf_types, __("Object file type: unkown"))
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("ABI version"));
+    },
 
-    /* Padding */
+    {
+        .name = "e_machine",
 
-    instr = g_raw_instruction_new_array(content, MDS_8_BITS, 7, &pos, endian);
+        .size = MDS_16_BITS,
+        .repeat = 1,
 
-    g_raw_instruction_mark_as_padding(G_RAW_INSTRUCTION(instr), true);
+        DISPLAY_RULES(IOD_DEC),
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Padding"));
+        SWITCH_COMMENT(_elf_machines, __("Architecture: unknown"))
 
-    /* Champ "e_type" */
+    },
 
-    switch (header->hdr32.e_type)
     {
-        case ET_NONE:
-            text = _("Object file type: no file type");
-            break;
-        case ET_REL:
-            text = _("Object file type: relocatable file");
-            break;
-        case ET_EXEC:
-            text = _("Object file type: executable file");
-            break;
-        case ET_DYN:
-            text = _("Object file type: shared object file");
-            break;
-        case ET_CORE:
-            text = _("Object file type: core file");
-            break;
-        case ET_LOOS ... ET_HIOS:
-            text = _("Object file type: OS-specific");
-            break;
-        case ET_LOPROC ... ET_HIPROC:
-            text = _("Object file type: processor-specific");
-            break;
-        default:
-            text = _("Object file type: unkown");
-            break;
+        .name = "e_version",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
+
+        DISPLAY_RULES(IOD_DEC),
+
+        PLAIN_COMMENT(__("Object file version"))
+
     }
 
-    instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian);
+};
+
+static fmt_field_def _elf_header_offset_32[] = {
+
+    {
+        .name = "e_entry",
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, text);
+        PLAIN_COMMENT(__("Entry point virtual address"))
 
-    /* Champ "e_machine" */
+    },
 
-    switch (header->hdr32.e_machine)
     {
-        case EM_NONE:		text = _("Architecture: No machine"); break;
-        case EM_M32:		text = _("Architecture: AT&T WE 32100"); break;
-        case EM_SPARC:		text = _("Architecture: SUN SPARC"); break;
-        case EM_386:		text = _("Architecture: Intel 80386"); break;
-        case EM_68K:		text = _("Architecture: Motorola m68k family"); break;
-        case EM_88K:		text = _("Architecture: Motorola m88k family"); break;
-        case EM_860:		text = _("Architecture: Intel 80860"); break;
-        case EM_MIPS:		text = _("Architecture: MIPS R3000 big-endian"); break;
-        case EM_S370:	    text = _("Architecture: IBM System/370"); break;
-        case EM_MIPS_RS3_LE:text = _("Architecture: MIPS R3000 little-endian"); break;
-        case EM_PARISC:		text = _("Architecture: HPPA"); break;
-        case EM_VPP500:		text = _("Architecture: Fujitsu VPP500"); break;
-        case EM_SPARC32PLUS:text = _("Architecture: Sun's \"v8plus\""); break;
-        case EM_960:		text = _("Architecture: Intel 80960"); break;
-        case EM_PPC:		text = _("Architecture: PowerPC"); break;
-        case EM_PPC64:		text = _("Architecture: PowerPC 64-bit"); break;
-        case EM_S390:		text = _("Architecture: IBM S390"); break;
-        case EM_V800:		text = _("Architecture: NEC V800 series"); break;
-        case EM_FR20:		text = _("Architecture: Fujitsu FR20"); break;
-        case EM_RH32:		text = _("Architecture: TRW RH-32"); break;
-        case EM_RCE:		text = _("Architecture: Motorola RCE"); break;
-        case EM_ARM:		text = _("Architecture: ARM"); break;
-        case EM_FAKE_ALPHA: text = _("Architecture: Digital Alpha"); break;
-        case EM_SH:		    text = _("Architecture: Hitachi SH"); break;
-        case EM_SPARCV9:	text = _("Architecture: SPARC v9 64-bit"); break;
-        case EM_TRICORE:	text = _("Architecture: Siemens Tricore"); break;
-        case EM_ARC:		text = _("Architecture: Argonaut RISC Core"); break;
-        case EM_H8_300:		text = _("Architecture: Hitachi H8/300"); break;
-        case EM_H8_300H:	text = _("Architecture: Hitachi H8/300H"); break;
-        case EM_H8S:		text = _("Architecture: Hitachi H8S"); break;
-        case EM_H8_500:		text = _("Architecture: Hitachi H8/500"); break;
-        case EM_IA_64:		text = _("Architecture: Intel Merced"); break;
-        case EM_MIPS_X:		text = _("Architecture: Stanford MIPS-X"); break;
-        case EM_COLDFIRE:	text = _("Architecture: Motorola Coldfire"); break;
-        case EM_68HC12:		text = _("Architecture: Motorola M68HC12"); break;
-        case EM_MMA:		text = _("Architecture: Fujitsu MMA Multimedia Accelerator"); break;
-        case EM_PCP:		text = _("Architecture: Siemens PCP"); break;
-        case EM_NCPU:		text = _("Architecture: Sony nCPU embeeded RISC"); break;
-        case EM_NDR1:		text = _("Architecture: Denso NDR1 microprocessor"); break;
-        case EM_STARCORE:	text = _("Architecture: Motorola Start*Core processor"); break;
-        case EM_ME16:		text = _("Architecture: Toyota ME16 processor"); break;
-        case EM_ST100:		text = _("Architecture: STMicroelectronic ST100 processor"); break;
-        case EM_TINYJ:		text = _("Architecture: Advanced Logic Corp. Tinyj emb.fam"); break;
-        case EM_X86_64:		text = _("Architecture: AMD x86-64 architecture"); break;
-        case EM_PDSP:		text = _("Architecture: Sony DSP Processor"); break;
-        case EM_FX66:		text = _("Architecture: Siemens FX66 microcontroller"); break;
-        case EM_ST9PLUS:	text = _("Architecture: STMicroelectronics ST9+ 8/16 mc"); break;
-        case EM_ST7:		text = _("Architecture: STmicroelectronics ST7 8 bit mc"); break;
-        case EM_68HC16:		text = _("Architecture: Motorola MC68HC16 microcontroller"); break;
-        case EM_68HC11:		text = _("Architecture: Motorola MC68HC11 microcontroller"); break;
-        case EM_68HC08:		text = _("Architecture: Motorola MC68HC08 microcontroller"); break;
-        case EM_68HC05:		text = _("Architecture: Motorola MC68HC05 microcontroller"); break;
-        case EM_SVX:		text = _("Architecture: Silicon Graphics SVx"); break;
-        case EM_ST19:		text = _("Architecture: STMicroelectronics ST19 8 bit mc"); break;
-        case EM_VAX:		text = _("Architecture: Digital VAX"); break;
-        case EM_CRIS:		text = _("Architecture: Axis Communications 32-bit embedded processor"); break;
-        case EM_JAVELIN:	text = _("Architecture: Infineon Technologies 32-bit embedded processor"); break;
-        case EM_FIREPATH:	text = _("Architecture: Element 14 64-bit DSP Processor"); break;
-        case EM_ZSP:		text = _("Architecture: LSI Logic 16-bit DSP Processor"); break;
-        case EM_MMIX:		text = _("Architecture: Donald Knuth's educational 64-bit processor"); break;
-        case EM_HUANY:		text = _("Architecture: Harvard University machine-independent object files"); break;
-        case EM_PRISM:		text = _("Architecture: SiTera Prism"); break;
-        case EM_AVR:		text = _("Architecture: Atmel AVR 8-bit microcontroller"); break;
-        case EM_FR30:		text = _("Architecture: Fujitsu FR30"); break;
-        case EM_D10V:		text = _("Architecture: Mitsubishi D10V"); break;
-        case EM_D30V:		text = _("Architecture: Mitsubishi D30V"); break;
-        case EM_V850:		text = _("Architecture: NEC v850"); break;
-        case EM_M32R:		text = _("Architecture: Mitsubishi M32R"); break;
-        case EM_MN10300:	text = _("Architecture: Matsushita MN10300"); break;
-        case EM_MN10200:	text = _("Architecture: Matsushita MN10200"); break;
-        case EM_PJ:		    text = _("Architecture: picoJava"); break;
-        case EM_OPENRISC:	text = _("Architecture: OpenRISC 32-bit embedded processor"); break;
-        case EM_ARC_A5:		text = _("Architecture: ARC Cores Tangent-A5"); break;
-        case EM_XTENSA:		text = _("Architecture: Tensilica Xtensa Architecture"); break;
-        case EM_AARCH64:	text = _("Architecture: ARM AARCH64"); break;
-        case EM_TILEPRO:	text = _("Architecture: Tilera TILEPro"); break;
-        case EM_MICROBLAZE:	text = _("Architecture: Xilinx MicroBlaze"); break;
-        case EM_TILEGX:		text = _("Architecture: Tilera TILE-Gx"); break;
-        default:		    text = _("Architecture: unknown"); break;
-    }
+        .name = "e_phoff",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-    instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian);
+        PLAIN_COMMENT(__("Program header table file offset"))
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+    },
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, text);
+    {
+        .name = "e_shoff",
 
-    /* Champ "e_version" */
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-    instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, &pos, endian);
+        PLAIN_COMMENT(__("Section header table file offset"))
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+    }
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Object file version"));
+};
+
+static fmt_field_def _elf_header_offset_64[] = {
 
-    if (header->hdr32.e_ident[EI_CLASS] == ELFCLASS32)
     {
-        /* Champ "e_entry" */
+        .name = "e_entry",
+
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, &pos, endian);
+        PLAIN_COMMENT(__("Entry point virtual address"))
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Entry point virtual address"));
+    },
 
-        /* Champ "e_phoff" */
+    {
+        .name = "e_phoff",
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, &pos, endian);
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Program header table file offset"));
+        PLAIN_COMMENT(__("Program header table file offset"))
 
-        /* Champ "e_shoff" */
+    },
+
+    {
+        .name = "e_shoff",
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, &pos, endian);
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section header table file offset"));
+        PLAIN_COMMENT(__("Section header table file offset"))
 
     }
 
-    else if (header->hdr32.e_ident[EI_CLASS] == ELFCLASS64)
+};
+
+static fmt_field_def _elf_header_ending[] = {
+
     {
-        /* Champ "e_entry" */
+        .name = "e_flags",
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, &pos, endian);
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Entry point virtual address"));
+        PLAIN_COMMENT(__("Processor-specific flags"))
 
-        /* Champ "e_phoff" */
+    },
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, &pos, endian);
+    {
+        .name = "e_ehsize",
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Program header table file offset"));
+        .size = MDS_16_BITS,
+        .repeat = 1,
 
-        /* Champ "e_shoff" */
+        DISPLAY_RULES(IOD_DEC),
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, &pos, endian);
+        PLAIN_COMMENT(__("ELF header size in bytes"))
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section header table file offset"));
+    },
 
-    }
+    {
+        .name = "e_phentsize",
 
-    else return false;
+        .size = MDS_16_BITS,
+        .repeat = 1,
 
-    /* Champ "e_flags" */
+        DISPLAY_RULES(IOD_DEC),
 
-    instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, &pos, endian);
+        PLAIN_COMMENT(__("Program header table entry size"))
+
+    },
+
+    {
+        .name = "e_phnum",
+
+        .size = MDS_16_BITS,
+        .repeat = 1,
+
+        DISPLAY_RULES(IOD_DEC),
+
+        PLAIN_COMMENT(__("Program header table entry count"))
+
+    },
+
+    {
+        .name = "e_shentsize",
 
-    //SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        .size = MDS_16_BITS,
+        .repeat = 1,
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Processor-specific flags"));
+        DISPLAY_RULES(IOD_DEC),
 
-    /* Champ "e_ehsize" */
+        PLAIN_COMMENT(__("Section header table entry size"))
 
-    instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian);
+    },
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+    {
+        .name = "e_shnum",
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("ELF header size in bytes"));
+        .size = MDS_16_BITS,
+        .repeat = 1,
 
-    /* Champ "e_phentsize" */
+        DISPLAY_RULES(IOD_DEC),
 
-    instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian);
+        PLAIN_COMMENT(__("Section header table entry count"))
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+    },
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Program header table entry size"));
+    {
+        .name = "e_shstrndx",
 
-    /* Champ "e_phnum" */
+        .size = MDS_16_BITS,
+        .repeat = 1,
 
-    instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian);
+        DISPLAY_RULES(IOD_DEC),
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        PLAIN_COMMENT(__("Section header string table index"))
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Program header table entry count"));
+    }
 
-    /* Champ "e_shentsize" */
+};
 
-    instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian);
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section header table entry size"));
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à compléter.            *
+*                                                                             *
+*  Description : Charge tous les symboles de l'en-tête ELF.                   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    /* Champ "e_shnum" */
+bool annotate_elf_header(GBinFormat *format)
+{
+    bool result;                            /* Bilan à retourner           */
+    const elf_header *header;               /* En-tête principale          */
+    vmpa2t pos;                             /* Tête de lecture des symboles*/
 
-    instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian);
+    header = g_elf_format_get_header(G_ELF_FORMAT(format));
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+    result = g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), 0, &pos);
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section header table entry count"));
+    if (result)
+        result = parse_field_definitions(_elf_header_base, ARRAY_SIZE(_elf_header_base), format, &pos);
 
-    /* Champ "e_shstrndx" */
+    if (result)
+    {
+        if (header->hdr32.e_ident[EI_CLASS] == ELFCLASS32)
+            result = parse_field_definitions(_elf_header_offset_32, ARRAY_SIZE(_elf_header_offset_32),
+                                             format, &pos);
 
-    instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, &pos, endian);
+        else if (header->hdr32.e_ident[EI_CLASS] == ELFCLASS64)
+            result = parse_field_definitions(_elf_header_offset_64, ARRAY_SIZE(_elf_header_offset_64),
+                                             format, &pos);
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        else
+            result = false;
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section header string table index"));
+    }
 
-    g_object_unref(G_OBJECT(content));
+    if (result)
+        result = parse_field_definitions(_elf_header_ending, ARRAY_SIZE(_elf_header_ending), format, &pos);
 
-    return true;
+    return result;
 
 }
diff --git a/plugins/readelf/header.h b/plugins/readelf/header.h
index 87724e3..9d1744e 100644
--- a/plugins/readelf/header.h
+++ b/plugins/readelf/header.h
@@ -30,7 +30,7 @@
 
 
 /* Charge tous les symboles de l'en-tête ELF. */
-bool annotate_elf_header(GElfFormat *);
+bool annotate_elf_header(GBinFormat *);
 
 
 
diff --git a/plugins/readelf/program.c b/plugins/readelf/program.c
index 6bf117c..ba47639 100644
--- a/plugins/readelf/program.c
+++ b/plugins/readelf/program.c
@@ -24,284 +24,297 @@
 #include "program.h"
 
 
+#include <string.h>
+
+
 #include <i18n.h>
-#include <arch/raw.h>
+#include <common/cpp.h>
 #include <common/extstr.h>
-#include <format/symbol.h>
 #include <format/elf/elf-int.h>
+#include <plugins/fmtp/parser.h>
 
 
 
-/* Charge tous les symboles liés à un en-tête de programme ELF. */
-static bool annotate_elf_program_header(GElfFormat *, SourceEndian, vmpa2t *);
+/* Définition des champs */
 
+static field_desc_switch _elf_prgm_types[] = {
 
+    { .fixed = PT_NULL,         .desc = __("Segment type: unused") },
+    { .fixed = PT_LOAD,         .desc = __("Segment type: loadable program segment") },
+    { .fixed = PT_DYNAMIC,      .desc = __("Segment type: dynamic linking information") },
+    { .fixed = PT_INTERP,       .desc = __("Segment type: program interpreter") },
+    { .fixed = PT_NOTE,         .desc = __("Segment type: auxiliary information") },
+    { .fixed = PT_SHLIB,        .desc = __("Segment type: reserved") },
+    { .fixed = PT_PHDR,         .desc = __("Segment type: entry for header table itself") },
+    { .fixed = PT_TLS,          .desc = __("Segment type: thread-local storage segment") },
+    { .fixed = PT_GNU_EH_FRAME, .desc = __("Segment type: GCC .eh_frame_hdr segment") },
+    { .fixed = PT_GNU_STACK,    .desc = __("Segment type: indicates stack executability") },
+    { .fixed = PT_GNU_RELRO,    .desc = __("Segment type: read-only after relocation") },
+    { .fixed = PT_SUNWSTACK,    .desc = __("Segment type: Sun Stack segment") },
+    { .lower = PT_LOSUNW, .upper = PT_HISUNW, .desc = __("Segment type: Sun specific segment") },
+    { .lower = PT_LOOS,   .upper = PT_HIOS,   .desc = __("Segment type: OS-specific") },
+    { .lower = PT_LOPROC, .upper = PT_HIPROC, .desc = __("Segment type: processor-specific") }
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à compléter.            *
-*                endian = boutisme présentement utilisé.                      *
-*                pos    = tête de lecture à déplacer. [OUT]                   *
-*                                                                             *
-*  Description : Charge tous les symboles liés à un en-tête de programme ELF. *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+};
 
-static bool annotate_elf_program_header(GElfFormat *format, SourceEndian endian, vmpa2t *pos)
-{
-    elf_phdr phdr;                          /* En-tête de programme ELF    */
-    GBinContent *content;                   /* Contenu binaire à lire      */
-    ImmOperandDisplay disp;                 /* Afficahge de valeur         */
-    const char *text;                       /* Texte constant à insérer    */
-    GArchInstruction *instr;                /* Instruction décodée         */
-    GArchOperand *operand;                  /* Opérande à venir modifier   */
-    GDbComment *comment;                    /* Définition de commentaire   */
-    GBinSymbol *symbol;                     /* Symbole à intégrer          */
-    char *dtext;                            /* Texte dynamique à créer     */
-    bool filled;                            /* Suivi de mise en place      */
-
-    if (!read_elf_program_header(format, get_phy_addr(pos), &phdr))
-        return false;
+static fmt_field_def _elf_phdr_base[] = {
 
-    content = g_binary_format_get_content(G_BIN_FORMAT(format));
+    {
+        .name = "p_type",
 
-    /* Champ "p_type" */
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-    disp = IOD_DEC;
+        SWITCH_COMMENT(_elf_prgm_types, __("Segment type: unknown"))
 
-    switch (ELF_PHDR(format, phdr, p_type))
-    {
-        case PT_NULL:
-            text = _("Segment type: unused");
-            break;
-        case PT_LOAD:
-            text = _("Segment type: loadable program segment");
-            break;
-        case PT_DYNAMIC:
-            text = _("Segment type: dynamic linking information");
-            break;
-        case PT_INTERP:
-            text = _("Segment type: program interpreter");
-            break;
-        case PT_NOTE:
-            text = _("Segment type: auxiliary information");
-            break;
-        case PT_SHLIB:
-            text = _("Segment type: reserved");
-            break;
-        case PT_PHDR:
-            text = _("Segment type: entry for header table itself");
-            break;
-        case PT_TLS:
-            text = _("Segment type: thread-local storage segment");
-            break;
-        case PT_LOOS ... PT_HIOS:
-            disp = IOD_HEX;
-            switch (ELF_PHDR(format, phdr, p_type))
-            {
-                case PT_GNU_EH_FRAME:
-                    text = _("Segment type: GCC .eh_frame_hdr segment");
-                    break;
-                case PT_GNU_STACK:
-                    text = _("Segment type: indicates stack executability");
-                    break;
-                case PT_GNU_RELRO:
-                    text = _("Segment type: read-only after relocation");
-                    break;
-                case PT_LOSUNW ... PT_HISUNW:
-                    switch (ELF_PHDR(format, phdr, p_type))
-                    {
-                        case PT_SUNWSTACK:
-                            text = _("Segment type: Sun Stack segment");
-                            break;
-                        default:
-                            text = _("Segment type: Sun specific segment");
-                            break;
-                    }
-                    break;
-                default:
-                    text = _("Segment type: OS-specific");
-                    break;
-            }
-            break;
-        case PT_LOPROC ... PT_HIPROC:
-            disp = IOD_HEX;
-            text = _("Segment type: processor-specific");
-            break;
-        default:
-            disp = IOD_HEX;
-            text = _("Segment type: unknown");
-            break;
     }
 
-    instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+};
+
+static fmt_field_def _elf_phdr_32b_a[] = {
 
-    SET_IMM_DISPLAY(instr, operand, 0, disp);
+    {
+        .name = "p_offset",
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, text);
+        .size = MDS_32_BITS,
+        .repeat = 1,
+
+        PLAIN_COMMENT(__("Segment file offset"))
+
+    },
 
-    if (format->is_32b)
     {
-        /* Champ "p_offset" */
+        .name = "p_vaddr",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
+
+        PLAIN_COMMENT(__("Segment virtual address"))
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+    },
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment file offset"));
+    {
+        .name = "p_paddr",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-        /* Champ "p_vaddr" */
+        PLAIN_COMMENT(__("Segment physical address"))
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+    },
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment virtual address"));
+    {
+        .name = "p_filesz",
 
-        /* Champ "p_paddr" */
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        PLAIN_COMMENT(__("Segment size in file"))
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment physical address"));
+    },
 
-        /* Champ "p_filesz" */
+    {
+        .name = "p_memsz",
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment size in file"));
+        PLAIN_COMMENT(__("Segment size in memory"))
 
-        /* Champ "p_memsz" */
+    }
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+};
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment size in memory"));
+static fmt_field_def _elf_phdr_32b_b[] = {
 
-        /* Champ "p_flags" */
+    {
+        .name = "p_align",
 
-        dtext = strdup(_("Segment flags: "));
-        filled = false;
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_R)
-        {
-            dtext = stradd(dtext, "R");
-            filled = true;
-        }
+        PLAIN_COMMENT(__("Segment alignment"))
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_W)
-        {
-            dtext = stradd(dtext, "W");
-            filled = true;
-        }
+    }
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_X)
-        {
-            dtext = stradd(dtext, "X");
-            filled = true;
-        }
+};
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_MASKOS)
-            /* TODO */;
+static fmt_field_def _elf_phdr_64b[] = {
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_MASKPROC)
-            /* TODO */;
+    {
+        .name = "p_offset",
 
-        if (!filled)
-            dtext = stradd(dtext, _("none"));
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        PLAIN_COMMENT(__("Segment file offset"))
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, dtext);
+    },
 
-        free(dtext);
+    {
+        .name = "p_vaddr",
 
-        /* Champ "p_align" */
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        PLAIN_COMMENT(__("Segment virtual address"))
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment alignment"));
+    },
 
-    }
-    else
     {
-        /* Champ "p_flags" */
+        .name = "p_paddr",
 
-        dtext = strdup(_("Segment flags: "));
-        filled = false;
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_R)
-        {
-            dtext = stradd(dtext, "R");
-            filled = true;
-        }
+        PLAIN_COMMENT(__("Segment physical address"))
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_W)
-        {
-            dtext = stradd(dtext, "W");
-            filled = true;
-        }
+    },
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_X)
-        {
-            dtext = stradd(dtext, "X");
-            filled = true;
-        }
+    {
+        .name = "p_filesz",
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_MASKOS)
-            /* TODO */;
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        if (ELF_PHDR(format, phdr, p_flags) & PF_MASKPROC)
-            /* TODO */;
+        PLAIN_COMMENT(__("Segment size in file"))
 
-        if (!filled)
-            dtext = stradd(dtext, _("none"));
+    },
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+    {
+        .name = "p_memsz",
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, dtext);
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        free(dtext);
+        PLAIN_COMMENT(__("Segment size in memory"))
 
-        /* Champ "p_offset" */
+    },
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+    {
+        .name = "p_align",
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment file offset"));
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        /* Champ "p_vaddr" */
+        PLAIN_COMMENT(__("Segment alignment"))
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+    }
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment virtual address"));
+};
 
-        /* Champ "p_paddr" */
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment physical address"));
+/* Charge tous les symboles liés à un en-tête de programme ELF. */
+static bool annotate_elf_program_header(GElfFormat *, SourceEndian, vmpa2t *);
 
-        /* Champ "p_filesz" */
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment size in file"));
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à compléter.            *
+*                endian = boutisme présentement utilisé.                      *
+*                pos    = tête de lecture à déplacer. [OUT]                   *
+*                                                                             *
+*  Description : Charge tous les symboles liés à un en-tête de programme ELF. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-        /* Champ "p_memsz" */
+static bool annotate_elf_program_header(GElfFormat *format, SourceEndian endian, vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+    elf_phdr phdr;                          /* En-tête de programme ELF    */
+    fmt_field_def flags_field;              /* Définition des drapeaux     */
+    char *rights;                           /* Reconstruction dynamique    */
+    comment_part parts[2];                  /* Mise en place des parties   */
+    GBinFormat *bformat;                    /* Autre version du format     */
+
+    result = read_elf_program_header(format, get_phy_addr(pos), &phdr);
+
+    if (!result)
+        goto aeph_exit;
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+    /* Préparation de la partie des drapeaux */
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment size in memory"));
+    memset(&flags_field, 0, sizeof(flags_field));
 
-        /* Champ "p_align" */
+    flags_field.name = "p_flags";
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+    flags_field.size = MDS_32_BITS;
+    flags_field.repeat = 1;
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment alignment"));
+    rights = NULL;
 
+    if (ELF_PHDR(format, phdr, p_flags) & PF_R)
+        rights = stradd(rights, "R");
+
+    if (ELF_PHDR(format, phdr, p_flags) & PF_W)
+        rights = stradd(rights, "W");
+
+    if (ELF_PHDR(format, phdr, p_flags) & PF_X)
+        rights = stradd(rights, "X");
+
+    if (ELF_PHDR(format, phdr, p_flags) & PF_MASKOS)
+        /* TODO */;
+
+    if (ELF_PHDR(format, phdr, p_flags) & PF_MASKPROC)
+        /* TODO */;
+
+    if (rights == NULL)
+    {
+        flags_field.ctype = FCT_PLAIN;
+        flags_field.comment.plain = __("Segment flags: none");
     }
+    else
+    {
+        parts[0].is_static = true;
+        parts[0].static_text = __("Segment flags: ");
+
+        parts[1].is_static = false;
+        parts[1].dynamic_text = rights;
+
+        flags_field.ctype = FCT_MULTI;
+        flags_field.comment.parts = parts;
+        flags_field.comment.pcount = ARRAY_SIZE(parts);
+
+    }
+
+    /* Interprétation générale */
+
+    bformat = G_BIN_FORMAT(format);
+
+    result = parse_field_definitions(_elf_phdr_base, ARRAY_SIZE(_elf_phdr_base), bformat, pos);
+
+    if (format->is_32b)
+    {
+        if (result)
+            result = parse_field_definitions(_elf_phdr_32b_a, ARRAY_SIZE(_elf_phdr_32b_a), bformat, pos);
 
-    g_object_unref(G_OBJECT(content));
+        if (result)
+            result = parse_field_definitions(&flags_field, 1, bformat, pos);
 
-    return true;
+        if (result)
+            result = parse_field_definitions(_elf_phdr_32b_b, ARRAY_SIZE(_elf_phdr_32b_b), bformat, pos);
+
+    }
+    else
+    {
+
+        if (result)
+            result = parse_field_definitions(&flags_field, 1, bformat, pos);
+
+        if (result)
+            result = parse_field_definitions(_elf_phdr_64b, ARRAY_SIZE(_elf_phdr_64b), bformat, pos);
+
+    }
+
+ aeph_exit:
+
+    return result;
 
 }
 
diff --git a/plugins/readelf/reader.c b/plugins/readelf/reader.c
index 01d5d90..62efdf4 100644
--- a/plugins/readelf/reader.c
+++ b/plugins/readelf/reader.c
@@ -66,7 +66,7 @@ G_MODULE_EXPORT bool handle_binary_format(const GPluginModule *plugin, PluginAct
 
     elf_fmt = G_ELF_FORMAT(format);
 
-    result = annotate_elf_header(elf_fmt);
+    result = annotate_elf_header(format);
 
     result &= annotate_elf_program_header_table(elf_fmt, status);
 
diff --git a/plugins/readelf/section.c b/plugins/readelf/section.c
index f2cae76..e689aac 100644
--- a/plugins/readelf/section.c
+++ b/plugins/readelf/section.c
@@ -24,357 +24,385 @@
 #include "section.h"
 
 
+#include <string.h>
+
+
 #include <i18n.h>
-#include <arch/raw.h>
+#include <common/cpp.h>
 #include <common/extstr.h>
-#include <format/symbol.h>
 #include <format/elf/elf-int.h>
 #include <format/elf/section.h>
+#include <plugins/fmtp/parser.h>
+
+
+
+/* Définition des champs */
+
+static field_desc_switch _elf_section_types[] = {
+
+    { .fixed = SHT_NULL,           .desc = __("Section type: unused") },
+    { .fixed = SHT_PROGBITS,       .desc = __("Section type: program data") },
+    { .fixed = SHT_SYMTAB,         .desc = __("Section type: symbol table") },
+    { .fixed = SHT_STRTAB,         .desc = __("Section type: string table") },
+    { .fixed = SHT_RELA,           .desc = __("Section type: relocation entries with addends") },
+    { .fixed = SHT_HASH,           .desc = __("Section type: symbol hash table") },
+    { .fixed = SHT_DYNAMIC,        .desc = __("Section type: dynamic linking information") },
+    { .fixed = SHT_NOTE,           .desc = __("Section type: notes") },
+    { .fixed = SHT_NOBITS,         .desc = __("Section type: program space with no data (bss)") },
+    { .fixed = SHT_REL,            .desc = __("Section type: relocation entries, no addends") },
+    { .fixed = SHT_SHLIB,          .desc = __("Section type: reserved") },
+    { .fixed = SHT_DYNSYM,         .desc = __("Section type: dynamic linker symbol table") },
+    { .fixed = SHT_INIT_ARRAY,     .desc = __("Section type: array of constructors") },
+    { .fixed = SHT_FINI_ARRAY,     .desc = __("Section type: array of destructors") },
+    { .fixed = SHT_PREINIT_ARRAY,  .desc = __("Section type: array of pre-constructors") },
+    { .fixed = SHT_GROUP,          .desc = __("Section type: section group") },
+    { .fixed = SHT_SYMTAB_SHNDX,   .desc = __("Section type: extended section indeces") },
+    { .fixed = SHT_GNU_ATTRIBUTES, .desc = __("Section type: object attributes") },
+    { .fixed = SHT_GNU_HASH,       .desc = __("Section type: GNU-style hash table") },
+    { .fixed = SHT_GNU_LIBLIST,    .desc = __("Section type: prelink library list") },
+    { .fixed = SHT_CHECKSUM,       .desc = __("Section type: checksum for DSO content") },
+    { .fixed = SHT_SUNW_move,      .desc = __("Section type: SHT_SUNW_move") },
+    { .fixed = SHT_SUNW_COMDAT,    .desc = __("Section type: SHT_SUNW_COMDAT") },
+    { .fixed = SHT_SUNW_syminfo,   .desc = __("Section type: SHT_SUNW_syminfo") },
+    { .fixed = SHT_GNU_verdef,     .desc = __("Section type: version definition section") },
+    { .fixed = SHT_GNU_verneed,    .desc = __("Section type: version needs section") },
+    { .fixed = SHT_GNU_versym,     .desc = __("Section type: version symbol table") },
+    { .lower = SHT_LOSUNW, .upper = SHT_HISUNW, .desc = __("Section type: Sun-specific") },
+    { .lower = SHT_LOOS,   .upper = SHT_HIOS,   .desc = __("Section type: OS-specific") },
+    { .lower = SHT_LOPROC, .upper = SHT_HIPROC, .desc = __("Section type: processor-specific") },
+    { .lower = SHT_LOUSER, .upper = SHT_HIUSER, .desc = __("Section type: application-specific") }
+
+};
+
+static fmt_field_def _elf_sh_type[] = {
 
+    {
+        .name = "sh_type",
 
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-/* Charge tous les symboles liés à un en-tête de section ELF. */
-static bool annotate_elf_section_header(GElfFormat *, SourceEndian, const elf_shdr *, vmpa2t *);
+        SWITCH_COMMENT(_elf_section_types, __("Section type: unknown"))
 
+    }
 
+};
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format  = description de l'exécutable à compléter.           *
-*                endian  = boutisme présentement utilisé.                     *
-*                strings = section renvoyant vers des chaînes de caractères.  *
-*                pos     = tête de lecture à déplacer. [OUT]                  *
-*                                                                             *
-*  Description : Charge tous les symboles liés à un en-tête de section ELF.   *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+static fmt_field_def _elf_shdr_32b[] = {
 
-static bool annotate_elf_section_header(GElfFormat *format, SourceEndian endian, const elf_shdr *strings, vmpa2t *pos)
-{
-    elf_shdr shdr;                          /* En-tête de programme ELF    */
-    GBinContent *content;                   /* Contenu binaire à lire      */
-    const char *secname;                    /* Nom d'une section analysée  */
-    ImmOperandDisplay disp;                 /* Afficahge de valeur         */
-    const char *text;                       /* Texte constant à insérer    */
-    GArchInstruction *instr;                /* Instruction décodée         */
-    GArchOperand *operand;                  /* Opérande à venir modifier   */
-    GDbComment *comment;                    /* Définition de commentaire   */
-    GBinSymbol *symbol;                     /* Symbole à intégrer          */
-    char *dtext;                            /* Texte dynamique à créer     */
-    bool filled;                            /* Suivi de mise en place      */
-
-    if (!read_elf_section_header(format, get_phy_addr(pos), &shdr))
-        return false;
+    {
+        .name = "sh_addr",
 
-    content = g_binary_format_get_content(G_BIN_FORMAT(format));
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-    /* Champ "sh_name" */
+        PLAIN_COMMENT(__("Section virtual addr at execution"))
 
-    secname = extract_name_from_elf_string_section(format, strings,
-                                                   ELF_SHDR(format, shdr, sh_name));
+    },
 
-    if (secname == NULL)
-        dtext = strdup(_("Section name: <invalid>"));
-    else
     {
-        dtext = strdup(_("Section name: '"));
-        dtext = stradd(dtext, secname);
-        dtext = stradd(dtext, "'");
-    }
+        .name = "sh_offset",
 
-    instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-    SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        PLAIN_COMMENT(__("Section file offset"))
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, dtext);
+    },
 
-    free(dtext);
+    {
+        .name = "sh_size",
 
-    /* Champ "sh_type" */
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-    disp = IOD_DEC;
+        DISPLAY_RULES(IOD_DEC),
 
-    switch (ELF_SHDR(format, shdr, sh_type))
-    {
-        case SHT_NULL:
-            text = _("Section type: unused");
-            break;
-        case SHT_PROGBITS:
-            text = _("Section type: program data");
-            break;
-        case SHT_SYMTAB:
-            text = _("Section type: symbol table");
-            break;
-        case SHT_STRTAB:
-            text = _("Section type: string table");
-            break;
-        case SHT_RELA:
-            text = _("Section type: relocation entries with addends");
-            break;
-        case SHT_HASH:
-            text = _("Section type: symbol hash table");
-            break;
-        case SHT_DYNAMIC:
-            text = _("Section type: dynamic linking information");
-            break;
-        case SHT_NOTE:
-            text = _("Section type: notes");
-            break;
-        case SHT_NOBITS:
-            text = _("Section type: program space with no data (bss)");
-            break;
-        case SHT_REL:
-            text = _("Section type: relocation entries, no addends");
-            break;
-        case SHT_SHLIB:
-            text = _("Section type: reserved");
-            break;
-        case SHT_DYNSYM:
-            text = _("Section type: dynamic linker symbol table");
-            break;
-        case SHT_INIT_ARRAY:
-            text = _("Section type: array of constructors");
-            break;
-        case SHT_FINI_ARRAY:
-            text = _("Section type: array of destructors");
-            break;
-        case SHT_PREINIT_ARRAY:
-            text = _("Section type: array of pre-constructors");
-            break;
-        case SHT_GROUP:
-            text = _("Section type: section group");
-            break;
-        case SHT_SYMTAB_SHNDX:
-            text = _("Section type: extended section indeces");
-            break;
-        case SHT_LOOS ... SHT_HIOS:
-            disp = IOD_HEX;
-            switch (ELF_SHDR(format, shdr, sh_type))
-            {
-                case SHT_GNU_ATTRIBUTES:
-                    text = _("Section type: object attributes");
-                    break;
-                case SHT_GNU_HASH:
-                    text = _("Section type: GNU-style hash table");
-                    break;
-                case SHT_GNU_LIBLIST:
-                    text = _("Section type: prelink library list");
-                    break;
-                case SHT_CHECKSUM:
-                    text = _("Section type: checksum for DSO content");
-                    break;
-                case SHT_LOSUNW ... SHT_HISUNW:
-                    switch (ELF_SHDR(format, shdr, sh_type))
-                    {
-                        case SHT_SUNW_move:
-                            text = _("Section type: SHT_SUNW_move");
-                            break;
-                        case SHT_SUNW_COMDAT:
-                            text = _("Section type: SHT_SUNW_COMDAT");
-                            break;
-                        case SHT_SUNW_syminfo:
-                            text = _("Section type: SHT_SUNW_syminfo");
-                            break;
-                        case SHT_GNU_verdef:
-                            text = _("Section type: version definition section");
-                            break;
-                        case SHT_GNU_verneed:
-                            text = _("Section type: version needs section");
-                            break;
-                        case SHT_GNU_versym:
-                            text = _("Section type: version symbol table");
-                            break;
-                        default:
-                            text = _("Section type: Sun-specific");
-                            break;
-                    }
-                    break;
-                default:
-                    text = _("Section type: OS-specific");
-                    break;
-            }
-            break;
-        case SHT_LOPROC ... SHT_HIPROC:
-            disp = IOD_HEX;
-            text = _("Section type: processor-specific");
-            break;
-        case SHT_LOUSER ... SHT_HIUSER:
-            disp = IOD_HEX;
-            text = _("Section type: application-specific");
-            break;
-        default:
-            disp = IOD_HEX;
-            text = _("Section type: unknown");
-            break;
-    }
+        PLAIN_COMMENT(__("Section size in bytes"))
 
-    instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+    },
 
-    SET_IMM_DISPLAY(instr, operand, 0, disp);
+    {
+        .name = "sh_link",
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, text);
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-    /* Champ "sh_flags"... */
+        PLAIN_COMMENT(__("Link to another section"))
 
-    dtext = strdup(_("Section flags: "));
-    filled = false;
+    },
 
-    if (ELF_SHDR(format, shdr, sh_type) & SHF_WRITE)
     {
-        dtext = stradd(dtext, "W");
-        filled = true;
-    }
+        .name = "sh_info",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
+
+        PLAIN_COMMENT(__("Additional section information"))
+
+    },
 
-    if (ELF_SHDR(format, shdr, sh_type) & SHF_ALLOC)
     {
-        dtext = stradd(dtext, "A");
-        filled = true;
-    }
+        .name = "sh_addralign",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
+
+        PLAIN_COMMENT(__("Section alignment"))
+
+    },
 
-    if (ELF_SHDR(format, shdr, sh_type) & SHF_EXECINSTR)
     {
-        dtext = stradd(dtext, "X");
-        filled = true;
+        .name = "sh_entsize",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
+
+        DISPLAY_RULES(IOD_DEC),
+
+        PLAIN_COMMENT(__("Entry size if section holds table"))
+
     }
 
-    if (ELF_SHDR(format, shdr, sh_type) & SHF_MERGE)
+};
+
+static fmt_field_def _elf_shdr_64b[] = {
+
     {
-        dtext = stradd(dtext, "M");
-        filled = true;
-    }
+        .name = "sh_addr",
+
+        .size = MDS_64_BITS,
+        .repeat = 1,
+
+        PLAIN_COMMENT(__("Section virtual addr at execution"))
+
+    },
 
-    if (ELF_SHDR(format, shdr, sh_type) & SHF_LINK_ORDER)
     {
-        dtext = stradd(dtext, "L");
-        filled = true;
-    }
+        .name = "sh_offset",
+
+        .size = MDS_64_BITS,
+        .repeat = 1,
+
+        PLAIN_COMMENT(__("Section file offset"))
+
+    },
 
-    if (ELF_SHDR(format, shdr, sh_type) & SHF_TLS)
     {
-        dtext = stradd(dtext, "T");
-        filled = true;
-    }
+        .name = "sh_size",
 
-    if (!filled)
-        dtext = stradd(dtext, _("none"));
+        .size = MDS_64_BITS,
+        .repeat = 1,
+
+        DISPLAY_RULES(IOD_DEC),
+
+        PLAIN_COMMENT(__("Section size in bytes"))
+
+    },
 
-    if (format->is_32b)
     {
-        /* Champ "sh_flags" (suite) */
+        .name = "sh_link",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        PLAIN_COMMENT(__("Link to another section"))
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, dtext);
+    },
 
-        free(dtext);
+    {
+        .name = "sh_info",
+
+        .size = MDS_32_BITS,
+        .repeat = 1,
 
-        /* Champ "sh_addr" */
+        PLAIN_COMMENT(__("Additional section information"))
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+    },
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section virtual addr at execution"));
+    {
+        .name = "sh_addralign",
 
-        /* Champ "sh_offset" */
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        PLAIN_COMMENT(__("Section alignment"))
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section file offset"));
+    },
 
-        /* Champ "sh_size" */
+    {
+        .name = "sh_entsize",
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        .size = MDS_64_BITS,
+        .repeat = 1,
 
-        SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        DISPLAY_RULES(IOD_DEC),
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section size in bytes"));
+        PLAIN_COMMENT(__("Entry size if section holds table"))
 
     }
-    else
-    {
-        /* Champ "sh_flags" (suite) */
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+};
+
+
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, dtext);
+/* Charge tous les symboles liés à un en-tête de section ELF. */
+static bool annotate_elf_section_header(GElfFormat *, SourceEndian, const elf_shdr *, vmpa2t *);
 
-        free(dtext);
 
-        /* Champ "sh_addr" */
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format  = description de l'exécutable à compléter.           *
+*                endian  = boutisme présentement utilisé.                     *
+*                strings = section renvoyant vers des chaînes de caractères.  *
+*                pos     = tête de lecture à déplacer. [OUT]                  *
+*                                                                             *
+*  Description : Charge tous les symboles liés à un en-tête de section ELF.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool annotate_elf_section_header(GElfFormat *format, SourceEndian endian, const elf_shdr *strings, vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+    elf_shdr shdr;                          /* En-tête de programme ELF    */
+    fmt_field_def name_field;               /* Définition du nom de section*/
+    const char *secname;                    /* Nom d'une section analysée  */
+    comment_part nparts[2];                 /* Mise en place des parties   */
+    fmt_field_def flags_field;              /* Définition des drapeaux     */
+    char *rights;                           /* Reconstruction dynamique    */
+    comment_part fparts[2];                 /* Mise en place des parties   */
+    GBinFormat *bformat;                    /* Autre version du format     */
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section virtual addr at execution"));
+    result = read_elf_section_header(format, get_phy_addr(pos), &shdr);
 
-        /* Champ "sh_offset" */
+    if (!result)
+        goto aesh_exit;
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+    /* Préparation de la partie nominative */
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section file offset"));
+    memset(&name_field, 0, sizeof(name_field));
 
-        /* Champ "sh_size" */
+    name_field.name = "sh_name";
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+    name_field.size = MDS_32_BITS;
+    name_field.repeat = 1;
 
-        SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+    name_field.has_display_rules = true;
+    name_field.disp_rules = (ImmOperandDisplay []) { IOD_DEC };
+    name_field.disp_count = 1;
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section size in bytes"));
+    secname = extract_name_from_elf_string_section(format, strings,
+                                                   ELF_SHDR(format, shdr, sh_name));
 
+    if (secname == NULL)
+    {
+        name_field.ctype = FCT_PLAIN;
+        name_field.comment.plain = __("Section name: <invalid>");
     }
+    else
+    {
+        nparts[0].is_static = true;
+        nparts[0].static_text = __("Segment name: ");
 
-    /* Champ "sh_link" */
+        nparts[1].is_static = true;
+        nparts[1].avoid_i18n = true;
+        nparts[1].static_text = secname;
 
-    instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+        name_field.ctype = FCT_MULTI;
+        name_field.comment.parts = nparts;
+        name_field.comment.pcount = ARRAY_SIZE(nparts);
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Link to another section"));
+    }
 
-    /* Champ "sh_info" */
+    /* Préparation de la partie des drapeaux */
 
-    instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+    memset(&flags_field, 0, sizeof(flags_field));
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Additional section information"));
+    flags_field.name = "sh_flags";
 
-    if (format->is_32b)
-    {
-        /* Champ "sh_addralign" */
+    flags_field.repeat = 1;
+
+    rights = NULL;
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+    if (ELF_SHDR(format, shdr, sh_type) & SHF_WRITE)
+        rights = stradd(rights, "W");
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section alignment"));
+    if (ELF_SHDR(format, shdr, sh_type) & SHF_ALLOC)
+        rights = stradd(rights, "A");
 
-        /* Champ "sh_entsize" */
+    if (ELF_SHDR(format, shdr, sh_type) & SHF_EXECINSTR)
+        rights = stradd(rights, "X");
 
-        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian);
+    if (ELF_SHDR(format, shdr, sh_type) & SHF_MERGE)
+        rights = stradd(rights, "M");
 
-        SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+    if (ELF_SHDR(format, shdr, sh_type) & SHF_LINK_ORDER)
+        rights = stradd(rights, "L");
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Entry size if section holds table"));
+    if (ELF_SHDR(format, shdr, sh_type) & SHF_TLS)
+        rights = stradd(rights, "T");
 
+    if (rights == NULL)
+    {
+        flags_field.ctype = FCT_PLAIN;
+        flags_field.comment.plain = __("Section flags: none");
     }
     else
     {
-        /* Champ "sh_addralign" */
+        fparts[0].is_static = true;
+        fparts[0].static_text = __("Section flags: ");
+
+        fparts[1].is_static = false;
+        fparts[1].dynamic_text = rights;
+
+        flags_field.ctype = FCT_MULTI;
+        flags_field.comment.parts = fparts;
+        flags_field.comment.pcount = ARRAY_SIZE(fparts);
+
+    }
+
+    /* Interprétation générale */
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+    bformat = G_BIN_FORMAT(format);
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Section alignment"));
+    result = parse_field_definitions(&name_field, 1, bformat, pos);
 
-        /* Champ "sh_entsize" */
+    if (result)
+        result = parse_field_definitions(_elf_sh_type, ARRAY_SIZE(_elf_sh_type), bformat, pos);
 
-        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian);
+    if (format->is_32b)
+    {
+        if (result)
+        {
+            flags_field.size = MDS_32_BITS;
+            result = parse_field_definitions(&flags_field, 1, bformat, pos);
+        }
 
-        SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC);
+        if (result)
+            result = parse_field_definitions(_elf_shdr_32b, ARRAY_SIZE(_elf_shdr_32b), bformat, pos);
+
+    }
+    else
+    {
+        if (result)
+        {
+            flags_field.size = MDS_64_BITS;
+            result = parse_field_definitions(&flags_field, 1, bformat, pos);
+        }
 
-        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Entry size if section holds table"));
+        if (result)
+            result = parse_field_definitions(_elf_shdr_64b, ARRAY_SIZE(_elf_shdr_64b), bformat, pos);
 
     }
 
-    g_object_unref(G_OBJECT(content));
+ aesh_exit:
 
-    return true;
+    return result;
 
 }
 
@@ -415,7 +443,7 @@ bool annotate_elf_section_header_table(GElfFormat *format, GtkStatusStack *statu
     offset = ELF_HDR(format, *header, e_shoff);
 
     if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), offset, &pos))
-        return false;
+        init_vmpa(&pos, offset, VMPA_NO_VIRTUAL);
 
     e_shnum = ELF_HDR(format, *header, e_shnum);
 
-- 
cgit v0.11.2-87-g4458