From 56ee4d3ecddeee05f11083fcc1595e3756b91790 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 5 Aug 2014 20:19:08 +0000
Subject: Defined the first steps for a new disassembling approach.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@387 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                          |  53 +++++++++++++
 src/analysis/decomp/decompiler.c   |  14 ++--
 src/analysis/disass/disassembler.c | 156 +++++++++++++++++++++++++++++++++++--
 src/analysis/disass/fetch.c        | 122 +++++++++++++++++++++++++++++
 src/analysis/disass/fetch.h        |   7 ++
 src/analysis/disass/output.c       |   4 +-
 src/arch/arm/v456/instruction.c    |   2 +-
 src/arch/artificial.c              |  80 +++++++++++++++++--
 src/arch/artificial.h              |   3 +-
 src/arch/dalvik/instruction.c      |  67 ++++++++++++++--
 src/arch/dalvik/pseudo/fill.c      |  67 +++++++++++++++-
 src/arch/dalvik/pseudo/switch.c    |  66 +++++++++++++++-
 src/arch/instruction-int.h         |  10 ++-
 src/arch/instruction.c             | 117 +++++++++++++++++-----------
 src/arch/instruction.h             |  15 ++--
 src/arch/jvm/instruction.c         |   2 +-
 src/arch/mips/instruction.c        |   2 +-
 src/arch/processor.c               |   4 +-
 src/arch/vmpa.c                    | 115 +++++++++++++++++++++++----
 src/arch/vmpa.h                    |  40 +++++++++-
 src/arch/x86/instruction.c         |   2 +-
 src/dialogs/export.c               |   2 +-
 src/glibext/gbufferline.c          | 109 +++++++++++++++++++++-----
 src/glibext/gbufferline.h          |  17 ++--
 src/glibext/gcodebuffer.c          |  49 +++++++-----
 src/glibext/gcodebuffer.h          |   8 +-
 src/glibext/signal.h               |   1 +
 src/gtkext/gtkbufferview.c         |  12 +--
 src/gtkext/gtkviewpanel-int.h      |   1 +
 src/gtkext/gtkviewpanel.c          |   1 +
 30 files changed, 973 insertions(+), 175 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b6662ba..7b3048c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+14-08-05  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/decomp/decompiler.c:
+	Update code.
+
+	* src/analysis/disass/disassembler.c:
+	* src/analysis/disass/fetch.c:
+	* src/analysis/disass/fetch.h:
+	Define the first steps for a new disassembling approach.
+
+	* src/analysis/disass/output.c:
+	Disable some features.
+
+	* src/arch/arm/v456/instruction.c:
+	* src/arch/artificial.c:
+	* src/arch/artificial.h:
+	* src/arch/dalvik/instruction.c:
+	* src/arch/dalvik/pseudo/fill.c:
+	* src/arch/dalvik/pseudo/switch.c:
+	Update code.
+
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	Use the new kind of addresses and class functions in order to get keywords.
+
+	* src/arch/instruction-int.h:
+	* src/arch/jvm/instruction.c:
+	* src/arch/mips/instruction.c:
+	* src/arch/processor.c:
+	Update code.
+
+	* src/arch/vmpa.c:
+	* src/arch/vmpa.h:
+	Extend the type defined for addresses a little bit.
+
+	* src/arch/x86/instruction.c:
+	* src/dialogs/export.c:
+	Update code.
+
+	* src/glibext/gbufferline.c:
+	* src/glibext/gbufferline.h:
+	Update code. Fill the basic information of a ligne into a buffer.
+
+	* src/glibext/gcodebuffer.c:
+	* src/glibext/gcodebuffer.h:
+	* src/glibext/signal.h:
+	Remove a warning by adding the missing header.
+
+	* src/gtkext/gtkbufferview.c:
+	* src/gtkext/gtkviewpanel.c:
+	* src/gtkext/gtkviewpanel-int.h:
+	Update code.
+
 14-07-31  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/binary.c:
diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c
index 3700405..aa2fc84 100644
--- a/src/analysis/decomp/decompiler.c
+++ b/src/analysis/decomp/decompiler.c
@@ -73,20 +73,20 @@ static void build_decomp_prologue(GCodeBuffer *buffer, const char *filename)
     output = g_java_output_new();
 
     line = g_lang_output_start_comments(output, buffer);
-    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     /* Introduction */
 
     line = g_lang_output_continue_comments(output, buffer,
                                            SL(_("Binary data decompiled by Chrysalide")));
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     line = g_lang_output_continue_comments(output, buffer,
                                            SL(_("Chrysalide is free software - © 2008-2012 Cyrille Bagard")));
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     line = g_lang_output_continue_comments(output, buffer, NULL, 0);
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     /* Fichier */
 
@@ -99,19 +99,19 @@ static void build_decomp_prologue(GCodeBuffer *buffer, const char *filename)
     snprintf(content, len, "%s%s", _("File: "), filename);
 
     line = g_lang_output_continue_comments(output, buffer, content, len - 1);
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     free(content);
 
     /* Ligne de séparation */
 
     line = g_lang_output_continue_comments(output, buffer, NULL, 0);
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     /* Conclusion */
 
     line = g_lang_output_end_comments(output, buffer);
-    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     g_object_unref(G_OBJECT(output));
 
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 8020e02..9344089 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -191,9 +191,149 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GBi
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
+#include "../../arch/vmpa.h"
+#include <time.h>
+
+#include <sys/time.h>
+#include <sys/resource.h>
 
 static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar)
 {
+
+
+    unsigned int valid;                     /* Instructions traduites      */
+    unsigned int db;                        /* Instructions non décodées   */
+    unsigned int valid_sum;                 /* Instructions traduites      */
+    unsigned int instr_sum;                 /* Instructions totales        */
+    size_t i;                               /* Boucle de parcours          */
+
+    GBinRoutine **routines;                 /* Liste des routines trouvées */
+    size_t routines_count;                  /* Nombre de ces routines      */
+    bstatus_id_t id;                        /* Identifiant de statut       */
+
+
+
+    vmpa2t base;
+
+
+
+    clock_t begin, end;
+    double time_spent;
+
+
+    struct rusage usage;
+    unsigned long ustart;
+    unsigned long uend;
+
+
+
+    /* Première étape */
+
+    id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true);
+
+
+    init_vmpa(&base, 0, 0);
+
+
+
+    begin = clock();
+
+    getrusage(RUSAGE_THREAD, &usage);
+    ustart = usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec;
+    ustart += usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec;
+
+
+    *disass->instrs = load_raw_binary(disass->binary, &base, 100, statusbar, id);
+
+    /*
+    *disass->instrs = disassemble_binary_parts(disass->binary, disass->parts, disass->count,
+                                               statusbar, id);
+    */
+
+
+
+    getrusage(RUSAGE_THREAD, &usage);
+    uend = usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec;
+    uend += usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec;
+
+
+    end = clock();
+
+    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
+
+    printf("[[ TIME ]] Disassembly :: %.2g (%.2g)\n", time_spent, (uend - ustart) / 1000000.0);
+
+
+
+
+    gtk_extended_status_bar_remove(statusbar, id);
+
+
+    run_plugins_on_binary(disass->binary, PGA_BINARY_DISASSEMBLED, true);
+
+
+
+
+
+
+    /* Septième étape */
+
+    id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true);
+
+    qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare);
+
+
+    begin = clock();
+
+
+    getrusage(RUSAGE_THREAD, &usage);
+    ustart = usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec;
+    ustart += usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec;
+
+
+    print_disassembled_instructions(disass->buffer, disass->format, *disass->instrs,
+                                    routines, routines_count, statusbar, id);
+
+
+
+
+
+    getrusage(RUSAGE_THREAD, &usage);
+    uend = usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec;
+    uend += usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec;
+
+
+    end = clock();
+
+    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
+
+    printf("[[ TIME ]] Printing :: %.2g (%.2g)\n", time_spent, (uend - ustart) / 1000000.0);
+
+
+    gtk_extended_status_bar_remove(statusbar, id);
+
+    run_plugins_on_binary(disass->binary, PGA_BINARY_PRINTED, true);
+
+
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : disass    = analyse à mener.                                 *
+*                statusbar = barre de statut à tenir informée.                *
+*                                                                             *
+*  Description : Assure le désassemblage en différé.                          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_disassembly_process_old(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar)
+{
 #ifdef DEBUG
     unsigned int valid;                     /* Instructions traduites      */
     unsigned int db;                        /* Instructions non décodées   */
@@ -339,20 +479,20 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
     output = g_asm_output_new();
 
     line = g_lang_output_start_comments(output, buffer);
-    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     /* Introduction */
 
     line = g_lang_output_continue_comments(output, buffer,
                                            SL(_("Disassembly generated by Chrysalide")));
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     line = g_lang_output_continue_comments(output, buffer,
                                            SL(_("Chrysalide is free software - © 2008-2014 Cyrille Bagard")));
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     line = g_lang_output_continue_comments(output, buffer, NULL, 0);
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     /* Fichier */
 
@@ -362,7 +502,7 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
     snprintf(content, len, "%s%s", _("File: "), filename);
 
     line = g_lang_output_continue_comments(output, buffer, content, len - 1);
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     free(content);
 
@@ -381,19 +521,19 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con
     g_checksum_free(checksum);
 
     line = g_lang_output_continue_comments(output, buffer, content, len - 1);
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     free(content);
 
     /* Ligne de séparation */
 
     line = g_lang_output_continue_comments(output, buffer, NULL, 0);
-    g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     /* Conclusion */
 
     line = g_lang_output_end_comments(output, buffer);
-    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS);
+    if (line != NULL) g_buffer_line_start_merge_at(line, BLC_PHYSICAL);
 
     g_object_unref(G_OBJECT(output));
 
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 17eea6a..4686fe2 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -23,6 +23,117 @@
 
 #include "fetch.h"
 
+
+#include "../../arch/artificial.h"
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary    = représentation de binaire chargé.                *
+*                parts     = parties binaires à désassembler.                 *
+*                count     = nombre de parties à traiter.                     *
+*                statusbar = barre de statut avec progression à mettre à jour.*
+*                id        = identifiant du message affiché à l'utilisateur.  *
+*                                                                             *
+*  Description : Procède au désassemblage basique d'un contenu binaire.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GArchInstruction *load_raw_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, GtkExtStatusBar *statusbar, bstatus_id_t id)
+{
+    GArchInstruction *result;               /* Liste d'instr. à renvoyer   */
+    GBinFormat *format;                     /* Format du fichier binaire   */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    off_t bin_length;                       /* Taille des données à lire   */
+    bin_t *bin_data;                        /* Données binaires à lire     */
+    vmpa2t *pos;                            /* Boucle de parcours          */
+    vmpa2t *prev;                           /* Boucle de parcours          */
+    off_t old_phy;                          /* Ancienne position physique  */
+    GArchInstruction *instr;                /* Instruction décodée         */
+    off_t new_phy;                          /* Nouvelle position physique  */
+
+    result = NULL;
+
+    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+    proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
+    bin_data = g_loaded_binary_get_data(binary, &bin_length);
+
+    end = bin_length;
+
+    pos = local_dup_vmpa(base);
+    prev = local_dup_vmpa(base);
+
+    old_phy = get_phy_addr(prev);
+
+    while (old_phy < end)
+    {
+        instr = g_db_instruction_new_from_data(bin_data, pos, end, proc);
+        if (instr == NULL) break;
+
+        new_phy = get_phy_addr(pos);
+
+        g_arch_instruction_set_location(instr, prev, new_phy - old_phy);
+        g_arch_instruction_add_to_list(&result, instr);
+
+        copy_vmpa(prev, pos);
+        old_phy = get_phy_addr(prev);
+
+        //done += (new_phy - old_phy);
+        //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
+
+    }
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 #ifdef DEBUG
 #   include "../../arch/artificial.h"
 #endif
@@ -139,3 +250,14 @@ GArchInstruction *disassemble_binary_parts(const GLoadedBinary *binary, GBinPart
     return result;
 
 }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/analysis/disass/fetch.h b/src/analysis/disass/fetch.h
index 87f3134..ff62ce8 100644
--- a/src/analysis/disass/fetch.h
+++ b/src/analysis/disass/fetch.h
@@ -30,6 +30,13 @@
 #include "../../gtkext/gtkextstatusbar.h"
 
 
+
+
+GArchInstruction *load_raw_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, GtkExtStatusBar *statusbar, bstatus_id_t id);
+
+
+
+
 /* Procède au désassemblage basique d'un contenu binaire. */
 GArchInstruction *disassemble_binary_parts(const GLoadedBinary *, GBinPart **, size_t, GtkExtStatusBar *, bstatus_id_t);
 
diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c
index fd7efce..97f9989 100644
--- a/src/analysis/disass/output.c
+++ b/src/analysis/disass/output.c
@@ -76,6 +76,7 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
          iter != NULL;
          iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX))
     {
+#if 0
         g_arch_instruction_get_location(iter, NULL, NULL, &iaddr);
 
         /* Ajout des prototypes de fonction */
@@ -87,10 +88,11 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
             g_binary_routine_output_info(routines[i], output, buffer);
 
         }
+#endif
 
         g_arch_instruction_print(iter, buffer, msize, content, ASX_INTEL);
 
-        gtk_extended_status_bar_update_activity(statusbar, id, (iaddr - start) * 1.0 / (end - start));
+        //gtk_extended_status_bar_update_activity(statusbar, id, (iaddr - start) * 1.0 / (end - start));
 
     }
 
diff --git a/src/arch/arm/v456/instruction.c b/src/arch/arm/v456/instruction.c
index 3ba3c54..b5df0f8 100644
--- a/src/arch/arm/v456/instruction.c
+++ b/src/arch/arm/v456/instruction.c
@@ -180,7 +180,7 @@ static void g_armv456_instruction_init(GArmV456Instruction *instr)
 
     parent = G_ARCH_INSTRUCTION(instr);
 
-    parent->get_text = (get_instruction_text_fc)g_armv456_get_instruction_text;
+    //parent->get_text = (get_instruction_text_fc)g_armv456_get_instruction_text;
 
     /*
     parent->get_rw_regs = (get_instruction_rw_regs_fc)g_armv456_instruction_get_rw_registers;
diff --git a/src/arch/artificial.c b/src/arch/artificial.c
index 6fbd6d9..4131e5f 100644
--- a/src/arch/artificial.c
+++ b/src/arch/artificial.c
@@ -57,8 +57,14 @@ static void g_db_instruction_class_init(GDbInstructionClass *);
 /* Initialise une instance d'opérande d'architecture. */
 static void g_db_instruction_init(GDbInstruction *);
 
-/* Traduit une instruction en version humainement lisible. */
-static const char *g_db_instruction_get_text(const GDbInstruction *, const GExeFormat *, AsmSyntax);
+/* Supprime toutes les références externes. */
+static void g_db_instruction_dispose(GDbInstruction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_db_instruction_finalize(GDbInstruction *);
+
+/* Fournit le nom humain de l'instruction manipulée. */
+static const char *g_db_instruction_get_keyword(const GDbInstruction *, AsmSyntax);
 
 /* Informe sur une éventuelle référence à une autre instruction. */
 static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *, vmpa_t *);
@@ -91,6 +97,17 @@ G_DEFINE_TYPE(GDbInstruction, g_db_instruction, G_TYPE_ARCH_INSTRUCTION);
 
 static void g_db_instruction_class_init(GDbInstructionClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GArchInstructionClass *instr;           /* Encore une autre vision...  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_db_instruction_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_db_instruction_finalize;
+
+    instr = G_ARCH_INSTRUCTION_CLASS(klass);
+
+    instr->get_key = (get_instruction_keyword_fc)g_db_instruction_get_keyword;
 
 }
 
@@ -113,7 +130,6 @@ static void g_db_instruction_init(GDbInstruction *instr)
 
     parent = G_ARCH_INSTRUCTION(instr);
 
-    parent->get_text = (get_instruction_text_fc)g_db_instruction_get_text;
     parent->get_link = (get_instruction_link_fc)g_db_instruction_get_link;
     parent->is_return = (is_instruction_return_fc)g_db_instruction_is_return;
 
@@ -122,6 +138,44 @@ static void g_db_instruction_init(GDbInstruction *instr)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_db_instruction_dispose(GDbInstruction *instr)
+{
+    G_OBJECT_CLASS(g_db_instruction_parent_class)->dispose(G_OBJECT(instr));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_db_instruction_finalize(GDbInstruction *instr)
+{
+    G_OBJECT_CLASS(g_db_instruction_parent_class)->finalize(G_OBJECT(instr));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : data = flux de données à analyser.                           *
 *                pos  = position courante dans ce flux. [OUT]                 *
 *                end  = limite des données à analyser.                        *
@@ -136,16 +190,26 @@ static void g_db_instruction_init(GDbInstruction *instr)
 *                                                                             *
 ******************************************************************************/
 
-GArchInstruction *g_db_instruction_new_from_data(const bin_t *data, off_t *pos, off_t end, vmpa_t addr, const GArchProcessor *proc)
+GArchInstruction *g_db_instruction_new_from_data(const bin_t *data, vmpa2t *address, off_t end, const GArchProcessor *proc)
 {
     GArchInstruction *result;               /* Instruction à retourner     */
+    off_t pos;
+    off_t old;
     GArchOperand *operand;                  /* Octet non décodé à afficher */
 
     result = g_object_new(G_TYPE_DB_INSTRUCTION, NULL);
 
+    pos = get_phy_addr(address);
+    old = pos;
+
     operand = g_imm_operand_new_from_data(g_arch_processor_get_instruction_size(proc),
-                                          data, pos, end,
+                                          data, &pos, end,
                                           g_arch_processor_get_endianness(proc));
+
+    address->physical += (pos - old);
+
+    /* FIXME : essayer une taille plus petite en cas d'échec (on peut être en bout de binaire) */
+
     if (operand == NULL) goto gdinfd_error;
 
     g_imm_operand_pad(G_IMM_OPERAND(operand), true);
@@ -169,15 +233,15 @@ GArchInstruction *g_db_instruction_new_from_data(const bin_t *data, off_t *pos,
 *                format = format du binaire manipulé.                         *
 *                syntax = type de représentation demandée.                    *
 *                                                                             *
-*  Description : Traduit une instruction en version humainement lisible.      *
+*  Description : Fournit le nom humain de l'instruction manipulée.            *
 *                                                                             *
-*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
+*  Retour      : Mot clef de bas niveau.                                      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static const char *g_db_instruction_get_text(const GDbInstruction *instr, const GExeFormat *format, AsmSyntax syntax)
+static const char *g_db_instruction_get_keyword(const GDbInstruction *instr, AsmSyntax syntax)
 {
     return "db";
 
diff --git a/src/arch/artificial.h b/src/arch/artificial.h
index b341644..65eb4fe 100644
--- a/src/arch/artificial.h
+++ b/src/arch/artificial.h
@@ -30,6 +30,7 @@
 
 #include "archbase.h"
 #include "processor.h"
+#include "vmpa.h"
 
 
 
@@ -53,7 +54,7 @@ typedef struct _GDbInstructionClass GDbInstructionClass;
 GType g_db_instruction_get_type(void);
 
 /* Crée une instruction de type 'db' à partir de données. */
-GArchInstruction *g_db_instruction_new_from_data(const bin_t *, off_t *, off_t, vmpa_t, const GArchProcessor *);
+GArchInstruction *g_db_instruction_new_from_data(const bin_t *, vmpa2t *, off_t, const GArchProcessor *);
 
 #ifdef DEBUG
 
diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c
index 83e0e6c..c0c6675 100644
--- a/src/arch/dalvik/instruction.c
+++ b/src/arch/dalvik/instruction.c
@@ -39,6 +39,12 @@ static void g_dalvik_instruction_class_init(GDalvikInstructionClass *);
 /* Initialise une instance d'opérande d'architecture Dalvik. */
 static void g_dalvik_instruction_init(GDalvikInstruction *);
 
+/* Supprime toutes les références externes. */
+static void g_dalvik_instruction_dispose(GDalvikInstruction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dalvik_instruction_finalize(GDalvikInstruction *);
+
 /* Liste les registres lus et écrits par l'instruction. */
 static void g_dalvik_instruction_get_rw_registers(const GDalvikInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *);
 
@@ -321,8 +327,8 @@ static dalvik_instruction _instructions[DOP_COUNT] = {
 };
 
 
-/* Traduit une instruction en version humainement lisible. */
-static const char *dalvik_get_instruction_text(const GDalvikInstruction *, const GExeFormat *, AsmSyntax);
+/* Fournit le nom humain de l'instruction manipulée. */
+static const char *dalvik_get_instruction_keyword(const GDalvikInstruction *, AsmSyntax);
 
 /* Informe sur une éventuelle référence à une autre instruction. */
 static InstructionLinkType dalvik_get_instruction_link(const GDalvikInstruction *, vmpa_t *);
@@ -354,6 +360,17 @@ G_DEFINE_TYPE(GDalvikInstruction, g_dalvik_instruction, G_TYPE_ARCH_INSTRUCTION)
 
 static void g_dalvik_instruction_class_init(GDalvikInstructionClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GArchInstructionClass *instr;           /* Encore une autre vision...  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_instruction_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_dalvik_instruction_finalize;
+
+    instr = G_ARCH_INSTRUCTION_CLASS(klass);
+
+    instr->get_key = (get_instruction_keyword_fc)dalvik_get_instruction_keyword;
 
 }
 
@@ -377,7 +394,6 @@ static void g_dalvik_instruction_init(GDalvikInstruction *instr)
     parent = G_ARCH_INSTRUCTION(instr);
 
     parent->get_rw_regs = (get_instruction_rw_regs_fc)g_dalvik_instruction_get_rw_registers;
-    parent->get_text = (get_instruction_text_fc)dalvik_get_instruction_text;
     parent->get_link = (get_instruction_link_fc)dalvik_get_instruction_link;
     parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return;
     parent->decomp = (decomp_instr_fc)dalvik_instruction_decompile;
@@ -387,6 +403,44 @@ static void g_dalvik_instruction_init(GDalvikInstruction *instr)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dalvik_instruction_dispose(GDalvikInstruction *instr)
+{
+    G_OBJECT_CLASS(g_dalvik_instruction_parent_class)->dispose(G_OBJECT(instr));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dalvik_instruction_finalize(GDalvikInstruction *instr)
+{
+    G_OBJECT_CLASS(g_dalvik_instruction_parent_class)->finalize(G_OBJECT(instr));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : type = type d'instruction à représenter.                     *
 *                                                                             *
 *  Description : Crée une instruction pour l'architecture Dalvik.             *
@@ -517,18 +571,17 @@ DalvikOpcodes dalvik_guess_next_instruction(const bin_t *data, off_t pos, off_t
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instr  = instruction à traiter.                              *
-*                format = format du binaire manipulé.                         *
 *                syntax = type de représentation demandée.                    *
 *                                                                             *
-*  Description : Traduit une instruction en version humainement lisible.      *
+*  Description : Fournit le nom humain de l'instruction manipulée.            *
 *                                                                             *
-*  Retour      : Chaîne de caractères à libérer de la mémoire.                *
+*  Retour      : Mot clef de bas niveau.                                      *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static const char *dalvik_get_instruction_text(const GDalvikInstruction *instr, const GExeFormat *format, AsmSyntax syntax)
+static const char *dalvik_get_instruction_keyword(const GDalvikInstruction *instr, AsmSyntax syntax)
 {
     return _instructions[instr->type].keyword;
 
diff --git a/src/arch/dalvik/pseudo/fill.c b/src/arch/dalvik/pseudo/fill.c
index 702f4b9..acb8551 100644
--- a/src/arch/dalvik/pseudo/fill.c
+++ b/src/arch/dalvik/pseudo/fill.c
@@ -56,6 +56,12 @@ static void g_dalvik_fill_instr_class_init(GDalvikFillInstrClass *);
 /* Initialise une instance d'opérande d'architecture. */
 static void g_dalvik_fill_instr_init(GDalvikFillInstr *);
 
+/* Supprime toutes les références externes. */
+static void g_dalvik_fill_instr_dispose(GDalvikFillInstr *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dalvik_fill_instr_finalize(GDalvikFillInstr *);
+
 /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
 static void g_dalvik_fill_instr_print(const GDalvikFillInstr *, GCodeBuffer *, MemoryDataSize, const bin_t *, AsmSyntax);
 
@@ -79,6 +85,17 @@ G_DEFINE_TYPE(GDalvikFillInstr, g_dalvik_fill_instr, G_TYPE_DALVIK_INSTRUCTION);
 
 static void g_dalvik_fill_instr_class_init(GDalvikFillInstrClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GArchInstructionClass *instr;           /* Encore une autre vision...  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_fill_instr_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_dalvik_fill_instr_finalize;
+
+    instr = G_ARCH_INSTRUCTION_CLASS(klass);
+
+    instr->print = (print_instruction_fc)g_dalvik_fill_instr_print;
 
 }
 
@@ -97,11 +114,44 @@ static void g_dalvik_fill_instr_class_init(GDalvikFillInstrClass *klass)
 
 static void g_dalvik_fill_instr_init(GDalvikFillInstr *instr)
 {
-    GArchInstruction *parent;               /* Instance parente            */
 
-    parent = G_ARCH_INSTRUCTION(instr);
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    parent->print = (print_instruction_fc)g_dalvik_fill_instr_print;
+static void g_dalvik_fill_instr_dispose(GDalvikFillInstr *instr)
+{
+    G_OBJECT_CLASS(g_dalvik_fill_instr_parent_class)->dispose(G_OBJECT(instr));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dalvik_fill_instr_finalize(GDalvikFillInstr *instr)
+{
+    G_OBJECT_CLASS(g_dalvik_fill_instr_parent_class)->finalize(G_OBJECT(instr));
 
 }
 
@@ -179,13 +229,20 @@ static void g_dalvik_fill_instr_print(const GDalvikFillInstr *instr, GCodeBuffer
 
     base = G_ARCH_INSTRUCTION(instr);
 
+    line = NULL;
+
+
+#if 0
+
     line = g_code_buffer_append_new_line(buffer, base->address);
 
     /* Adresse virtuelle ou physique */
 
     len = vmpa_to_string(base->address, msize, address);
 
-    g_buffer_line_insert_text(line, BLC_ADDRESS, address, len, RTT_RAW);
+    g_buffer_line_insert_text(line, BLC_PHYSICAL, address, len, RTT_RAW);
+
+    /* TODO ... */
 
     /* Code brut */
 
@@ -204,6 +261,8 @@ static void g_dalvik_fill_instr_print(const GDalvikFillInstr *instr, GCodeBuffer
 
     free(bin_code);
 
+#endif
+
     /* Instruction proprement dite */
 
     key = "<fill-array>";
diff --git a/src/arch/dalvik/pseudo/switch.c b/src/arch/dalvik/pseudo/switch.c
index c97c82b..169c5bf 100644
--- a/src/arch/dalvik/pseudo/switch.c
+++ b/src/arch/dalvik/pseudo/switch.c
@@ -55,6 +55,12 @@ static void g_dalvik_switch_instr_class_init(GDalvikSwitchInstrClass *);
 /* Initialise une instance d'opérande d'architecture. */
 static void g_dalvik_switch_instr_init(GDalvikSwitchInstr *);
 
+/* Supprime toutes les références externes. */
+static void g_dalvik_switch_instr_dispose(GDalvikSwitchInstr *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *);
+
 /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
 static void g_dalvik_switch_instr_print(const GDalvikSwitchInstr *, GCodeBuffer *, MemoryDataSize, const bin_t *, AsmSyntax);
 
@@ -78,6 +84,17 @@ G_DEFINE_TYPE(GDalvikSwitchInstr, g_dalvik_switch_instr, G_TYPE_DALVIK_INSTRUCTI
 
 static void g_dalvik_switch_instr_class_init(GDalvikSwitchInstrClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GArchInstructionClass *instr;           /* Encore une autre vision...  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_switch_instr_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_dalvik_switch_instr_finalize;
+
+    instr = G_ARCH_INSTRUCTION_CLASS(klass);
+
+    instr->print = (print_instruction_fc)g_dalvik_switch_instr_print;
 
 }
 
@@ -96,11 +113,44 @@ static void g_dalvik_switch_instr_class_init(GDalvikSwitchInstrClass *klass)
 
 static void g_dalvik_switch_instr_init(GDalvikSwitchInstr *instr)
 {
-    GArchInstruction *parent;               /* Instance parente            */
 
-    parent = G_ARCH_INSTRUCTION(instr);
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dalvik_switch_instr_dispose(GDalvikSwitchInstr *instr)
+{
+    G_OBJECT_CLASS(g_dalvik_switch_instr_parent_class)->dispose(G_OBJECT(instr));
+
+}
 
-    parent->print = (print_instruction_fc)g_dalvik_switch_instr_print;
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *instr)
+{
+    G_OBJECT_CLASS(g_dalvik_switch_instr_parent_class)->finalize(G_OBJECT(instr));
 
 }
 
@@ -182,13 +232,19 @@ static void g_dalvik_switch_instr_print(const GDalvikSwitchInstr *instr, GCodeBu
 
     base = G_ARCH_INSTRUCTION(instr);
 
+    line = NULL;
+
+
+#if 0
     line = g_code_buffer_append_new_line(buffer, base->address);
 
     /* Adresse virtuelle ou physique */
 
     len = vmpa_to_string(base->address, msize, address);
 
-    g_buffer_line_insert_text(line, BLC_ADDRESS, address, len, RTT_RAW);
+    g_buffer_line_insert_text(line, BLC_PHYSICAL, address, len, RTT_RAW);
+
+    /* TODO ... */
 
     /* Code brut */
 
@@ -207,6 +263,8 @@ static void g_dalvik_switch_instr_print(const GDalvikSwitchInstr *instr, GCodeBu
 
     free(bin_code);
 
+#endif
+
     /* Instruction proprement dite */
 
     key = "<fill-array>";
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index 98f1eea..076eec2 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -39,7 +39,7 @@ typedef void (* get_instruction_rw_regs_fc) (const GArchInstruction *, GArchRegi
 typedef void (* print_instruction_fc) (const GArchInstruction *, GCodeBuffer *, MemoryDataSize, const bin_t *, AsmSyntax);
 
 /* Traduit une instruction en version humainement lisible. */
-typedef const char * (* get_instruction_text_fc) (const GArchInstruction *, const GExeFormat *, AsmSyntax);
+typedef const char * (* get_instruction_keyword_fc) (const GArchInstruction *, AsmSyntax);
 
 /* Informe sur une éventuelle référence à une autre instruction. */
 typedef InstructionLinkType (* get_instruction_link_fc) (const GArchInstruction *, vmpa_t *);
@@ -55,6 +55,7 @@ struct _GArchInstruction
 
     DL_LIST_ITEM(flow);                     /* Maillon de liste chaînée    */
 
+    vmpa2t address2;                         /* Position associée           */
     off_t offset;                           /* Position physique de départ */
     off_t length;                           /* Taille de l'instruction     */
 
@@ -72,8 +73,8 @@ struct _GArchInstruction
     size_t to_count;                        /* Nombre de ces destinations  */
 
     get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés    */
-    print_instruction_fc print;             /* Imprime l'ensemble          */
-    get_instruction_text_fc get_text;       /* Texte humain équivalent     */
+    //print_instruction_fc print;             /* Imprime l'ensemble          */
+    //get_instruction_keyword_fc get_key;     /* Texte humain équivalent     */
     get_instruction_link_fc get_link;       /* Référence à une instruction */
     is_instruction_return_fc is_return;     /* Retour de fonction ou pas ? */
     decomp_instr_fc decomp;                 /* Procédure de décompilation  */
@@ -86,6 +87,9 @@ struct _GArchInstructionClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
+    print_instruction_fc print;             /* Imprime l'ensemble          */
+    get_instruction_keyword_fc get_key;     /* Texte humain équivalent     */
+
 };
 
 
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 72911bf..3a62a90 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -39,6 +39,12 @@ static void g_arch_instruction_class_init(GArchInstructionClass *);
 /* Initialise une instance d'opérande d'architecture. */
 static void g_arch_instruction_init(GArchInstruction *);
 
+/* Supprime toutes les références externes. */
+static void g_arch_instruction_dispose(GArchInstruction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_arch_instruction_finalize(GArchInstruction *);
+
 
 
 /* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */
@@ -67,6 +73,17 @@ G_DEFINE_TYPE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT);
 
 static void g_arch_instruction_class_init(GArchInstructionClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GArchInstructionClass *instr;           /* Encore une autre vision...  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_instruction_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_arch_instruction_finalize;
+
+    instr = G_ARCH_INSTRUCTION_CLASS(klass);
+
+    instr->print = (print_instruction_fc)_g_arch_instruction_print;
 
 }
 
@@ -92,10 +109,47 @@ static void g_arch_instruction_init(GArchInstruction *instr)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_instruction_dispose(GArchInstruction *instr)
+{
+    G_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arch_instruction_finalize(GArchInstruction *instr)
+{
+    G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr   = instruction quelconque à modifier.                 *
-*                offset  = position physique dans le code binaire.            *
+*                address = adresse virtuelle et/ou position physique.         *
 *                length  = taille de l'instruction.                           *
-*                address = adresse virtuelle ou position physique.            *
 *                                                                             *
 *  Description : Définit la localisation d'une instruction.                   *
 *                                                                             *
@@ -105,12 +159,15 @@ static void g_arch_instruction_init(GArchInstruction *instr)
 *                                                                             *
 ******************************************************************************/
 
-void g_arch_instruction_set_location(GArchInstruction *instr, off_t offset, off_t length, vmpa_t address)
+void g_arch_instruction_set_location(GArchInstruction *instr, const vmpa2t *address, off_t length)
 {
-    instr->offset = offset;
-    instr->length = length;
+    copy_vmpa(&instr->address2, address);
+
+    /* FIXME */
+    instr->offset = get_phy_addr(address);
+    instr->address = get_virt_addr(address);
 
-    instr->address = address;
+    instr->length = length;
 
 }
 
@@ -578,6 +635,7 @@ size_t g_arch_instruction_compute_group_index(GArchInstruction **iter, GArchInst
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instr  = instruction d'assemblage à consulter.               *
+*                syntax = type de représentation demandée.                    *
 *                                                                             *
 *  Description : Fournit le nom humain de l'instruction manipulée.            *
 *                                                                             *
@@ -587,9 +645,9 @@ size_t g_arch_instruction_compute_group_index(GArchInstruction **iter, GArchInst
 *                                                                             *
 ******************************************************************************/
 
-const char *g_arch_instruction_get_keyword(const GArchInstruction *instr)
+const char *g_arch_instruction_get_keyword(const GArchInstruction *instr, AsmSyntax syntax)
 {
-    return instr->get_text(instr, NULL/* FIXME */, 0/* FIXME */);
+    G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_key(instr, syntax);
 
 }
 
@@ -611,42 +669,17 @@ const char *g_arch_instruction_get_keyword(const GArchInstruction *instr)
 static void _g_arch_instruction_print(const GArchInstruction *instr, GCodeBuffer *buffer, MemoryDataSize msize, const bin_t *content, AsmSyntax syntax)
 {
     GBufferLine *line;                      /* Ligne de destination        */
-    char address[VMPA_MAX_SIZE];            /* Adresse au format texte     */
-    size_t len;                             /* Taille de l'élément inséré  */
-    char *bin_code;                         /* Tampon du code binaire      */
-    off_t i;                                /* Boucle de parcours #1       */
     const char *key;                        /* Mot clef principal          */
     size_t klen;                            /* Taille de ce mot clef       */
-    size_t j;                               /* Boucle de parcours #2       */
-
-    line = g_code_buffer_append_new_line(buffer, instr->address);
-
-    /* Adresse virtuelle ou physique */
-
-    len = vmpa_to_string(instr->address, msize, address);
-
-    g_buffer_line_insert_text(line, BLC_ADDRESS, address, len, RTT_RAW);
-
-    /* Code brut */
-
-    bin_code = (char *)calloc(instr->length * 3, sizeof(char));
-
-    for (i = 0; i < instr->length; i++)
-    {
-        if ((i + 1) < instr->length)
-            snprintf(&bin_code[i * (2 + 1)], 4, "%02hhx ", content[instr->offset + i]);
-        else
-            snprintf(&bin_code[i * (2 + 1)], 3, "%02hhx", content[instr->offset + i]);
-    }
+    size_t i;                               /* Boucle de parcours          */
 
-    g_buffer_line_insert_text(line, BLC_BINARY,
-                              bin_code, instr->length * 3 - 1, RTT_RAW_CODE);
+    line = g_code_buffer_append_new_line(buffer, &instr->address2);
 
-    free(bin_code);
+    g_buffer_line_fill_for_instr(line, msize/* TODO ! */, msize, content, instr->length, true);
 
     /* Instruction proprement dite */
 
-    key = instr->get_text(instr, NULL/* FIXME */, 0/* FIXME */);
+    key = g_arch_instruction_get_keyword(instr, syntax);
     klen = strlen(key);
 
     g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION);
@@ -655,12 +688,12 @@ static void _g_arch_instruction_print(const GArchInstruction *instr, GCodeBuffer
     {
         g_arch_operand_print(instr->operands[0], line, syntax);
 
-        for (j = 1; j < instr->operands_count; j++)
+        for (i = 1; i < instr->operands_count; i++)
         {
             g_buffer_line_insert_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
             g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW);
 
-            g_arch_operand_print(instr->operands[j], line, syntax);
+            g_arch_operand_print(instr->operands[i], line, syntax);
 
         }
 
@@ -685,11 +718,7 @@ static void _g_arch_instruction_print(const GArchInstruction *instr, GCodeBuffer
 
 void g_arch_instruction_print(const GArchInstruction *instr, GCodeBuffer *buffer, MemoryDataSize msize, const bin_t *content, AsmSyntax syntax)
 {
-    if (instr->print != NULL)
-        instr->print(instr, buffer, msize, content, syntax);
-
-    else
-        _g_arch_instruction_print(instr, buffer, msize, content, syntax);
+    G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, buffer, msize, content, syntax);
 
 }
 
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 06a29bf..a059161 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -30,6 +30,7 @@
 
 #include "immediate.h"
 #include "register.h"
+#include "vmpa.h"
 #include "../analysis/type.h"
 #include "../decomp/context.h"
 #include "../decomp/instruction.h"
@@ -37,10 +38,12 @@
 
 
 
-#define G_TYPE_ARCH_INSTRUCTION                 g_arch_instruction_get_type()
-#define G_ARCH_INSTRUCTION(obj)                 (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_instruction_get_type(), GArchInstruction))
-#define G_IS_ARCH_INSTRUCTION(obj)              (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_instruction_get_type()))
-#define G_ARCH_INSTRUCTION_GET_IFACE(inst)      (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_arch_instruction_get_type(), GArchInstructionIface))
+#define G_TYPE_ARCH_INSTRUCTION               g_arch_instruction_get_type()
+#define G_ARCH_INSTRUCTION(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_instruction_get_type(), GArchInstruction))
+#define G_IS_ARCH_INSTRUCTION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_instruction_get_type()))
+#define G_ARCH_INSTRUCTION_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass))
+#define G_IS_ARCH_INSTRUCTION_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_INSTRUCTION))
+#define G_ARCH_INSTRUCTION_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass))
 
 
 /* Définition générique d'une instruction d'architecture (instance) */
@@ -54,7 +57,7 @@ typedef struct _GArchInstructionClass GArchInstructionClass;
 GType g_arch_instruction_get_type(void);
 
 /* Définit la localisation d'une instruction. */
-void g_arch_instruction_set_location(GArchInstruction *, off_t, off_t, vmpa_t);
+void g_arch_instruction_set_location(GArchInstruction *, const vmpa2t *, off_t);
 
 /* Fournit la localisation d'une instruction. */
 void g_arch_instruction_get_location(const GArchInstruction *, off_t *, off_t *, vmpa_t *);
@@ -139,7 +142,7 @@ size_t g_arch_instruction_compute_group_index(GArchInstruction **, GArchInstruct
 
 
 /* Fournit le nom humain de l'instruction manipulée. */
-const char *g_arch_instruction_get_keyword(const GArchInstruction *);
+const char *g_arch_instruction_get_keyword(const GArchInstruction *, AsmSyntax);
 
 /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
 void g_arch_instruction_print(const GArchInstruction *, GCodeBuffer *, MemoryDataSize, const bin_t *, AsmSyntax);
diff --git a/src/arch/jvm/instruction.c b/src/arch/jvm/instruction.c
index bfb6fc1..c2daaf5 100644
--- a/src/arch/jvm/instruction.c
+++ b/src/arch/jvm/instruction.c
@@ -199,7 +199,7 @@ static void g_jvm_instruction_init(GJvmInstruction *instr)
 
     parent = G_ARCH_INSTRUCTION(instr);
 
-    parent->get_text = (get_instruction_text_fc)jvm_get_instruction_text;
+    //parent->get_text = (get_instruction_text_fc)jvm_get_instruction_text;
 
 }
 
diff --git a/src/arch/mips/instruction.c b/src/arch/mips/instruction.c
index b3ef65d..93c32e7 100644
--- a/src/arch/mips/instruction.c
+++ b/src/arch/mips/instruction.c
@@ -177,7 +177,7 @@ static void g_mips_instruction_init(GMipsInstruction *instr)
 
     parent = G_ARCH_INSTRUCTION(instr);
 
-    parent->get_text = (get_instruction_text_fc)mips_get_instruction_text;
+    //parent->get_text = (get_instruction_text_fc)mips_get_instruction_text;
 
 }
 
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 8ca58a7..48d0924 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -259,7 +259,7 @@ GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *proc
         skipped = (result == SKIPPED_INSTR);
 
         *pos = old_pos;
-        result = g_db_instruction_new_from_data(data, pos, end, addr, proc);
+        result = NULL;// changed !!! g_db_instruction_new_from_data(data, pos, end, addr, proc);
 
 #ifdef DEBUG /* FIXME */
         if (skipped)
@@ -267,7 +267,7 @@ GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *proc
 #endif
     }
 
-    g_arch_instruction_set_location(result, old_pos, *pos - old_pos, addr);
+    //g_arch_instruction_set_location(result, old_pos, *pos - old_pos, addr);
 
     return result;
 
diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c
index c6972af..4ee0b99 100644
--- a/src/arch/vmpa.c
+++ b/src/arch/vmpa.c
@@ -26,6 +26,7 @@
 
 #include <inttypes.h>
 #include <malloc.h>
+#include <string.h>
 
 
 #include "../common/io.h"
@@ -35,6 +36,76 @@
 
 
 
+
+#if 0
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : src = définition à copier.                                   *
+*                                                                             *
+*  Description : Crée la copie d'un adressage mémoire en local.               *
+*                                                                             *
+*  Retour      : Adressage alloué sur la pile.                                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+inline vmpa2t *local_dup_vmpa(const vmpa2t *src)
+{
+    vmpa2t *result;                         /* Adressage à retourner       */
+
+    result = alloca(sizeof(vmpa2t));
+
+    copy_vmpa(result, src);
+
+    return result;
+
+}
+#endif
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dest = structure de destination pour la copie.               *
+*                src  = structure de source pour la copie.                    *
+*                                                                             *
+*  Description : Copie la définition d'un adressage dans un autre.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void copy_vmpa(vmpa2t *dest, const vmpa2t *src)
+{
+    dest->physical = src->physical;
+    dest->virtual= src->virtual;
+
+    dest->last_phys_size = src->last_phys_size;
+    dest->last_virt_size = src->last_virt_size;
+
+    strncpy(dest->phys_cache, src->phys_cache, VMPA_MAX_SIZE);
+    dest->phys_cache[VMPA_MAX_SIZE - 1] = '\0';
+
+    strncpy(dest->virt_cache, src->virt_cache, VMPA_MAX_SIZE);
+    dest->virt_cache[VMPA_MAX_SIZE - 1] = '\0';
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : phy  = position dans la mémoire physique.                    *
@@ -164,6 +235,7 @@ bool send_vmpa(const vmpa2t *addr, int fd, int flags)
 *                                                                             *
 *  Paramètres  : addr   = adresse virtuelle ou physique à traiter.            *
 *                msize  = taille de cette adresse, réelle ou désirée.         *
+*                length = transmission de la taille du résultat ou NULL. [OUT]*
 *                                                                             *
 *  Description : Transforme une adresse physique en chaîne de caractères.     *
 *                                                                             *
@@ -173,39 +245,45 @@ bool send_vmpa(const vmpa2t *addr, int fd, int flags)
 *                                                                             *
 ******************************************************************************/
 
-const char *vmpa2_phy_to_string(vmpa2t *addr, MemoryDataSize msize)
+const char *vmpa2_phys_to_string(vmpa2t *addr, MemoryDataSize msize, size_t *length)
 {
-    if (addr->phy_cache[0] == '\0' || addr->last_phy_size != msize)
+    size_t ret;                             /* Retour de l'impression      */
+
+    if (addr->phys_cache[0] == '\0' || addr->last_phys_size != msize)
     {
         switch (msize)
         {
             case MDS_8_BITS:
-                snprintf(addr->phy_cache, VMPA_MAX_SIZE,"0x%02" PRIx64, addr->physical);
+                ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE,"0x%02" PRIx64, addr->physical);
                 break;
 
             case MDS_16_BITS:
-                snprintf(addr->phy_cache, VMPA_MAX_SIZE, "0x%04" PRIx64, addr->physical);
+                ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE, "0x%04" PRIx64, addr->physical);
                 break;
 
             case MDS_32_BITS:
-                snprintf(addr->phy_cache, VMPA_MAX_SIZE, "0x%08" PRIx64, addr->physical);
+                ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE, "0x%08" PRIx64, addr->physical);
                 break;
 
             case MDS_64_BITS:
-                snprintf(addr->phy_cache, VMPA_MAX_SIZE, "0x%016" PRIx64, addr->physical);
+                ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE, "0x%016" PRIx64, addr->physical);
                 break;
 
             default:
-                snprintf(addr->phy_cache, VMPA_MAX_SIZE, "???");
+                ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE, "???");
                 break;
 
         }
 
-        addr->last_phy_size = msize;
+        addr->last_phys_size = msize;
+        addr->last_phys_len = ret;
 
     }
 
-    return addr->phy_cache;
+    if (length != NULL)
+        *length = addr->last_phys_size;
+
+    return addr->phys_cache;
 
 }
 
@@ -214,6 +292,7 @@ const char *vmpa2_phy_to_string(vmpa2t *addr, MemoryDataSize msize)
 *                                                                             *
 *  Paramètres  : addr   = adresse virtuelle ou physique à traiter.            *
 *                msize  = taille de cette adresse, réelle ou désirée.         *
+*                length = transmission de la taille du résultat ou NULL. [OUT]*
 *                                                                             *
 *  Description : Transforme une adresse virtuelle en chaîne de caractères.    *
 *                                                                             *
@@ -223,38 +302,44 @@ const char *vmpa2_phy_to_string(vmpa2t *addr, MemoryDataSize msize)
 *                                                                             *
 ******************************************************************************/
 
-const char *vmpa2_virt_to_string(vmpa2t *addr, MemoryDataSize msize)
+const char *vmpa2_virt_to_string(vmpa2t *addr, MemoryDataSize msize, size_t *length)
 {
+    size_t ret;                             /* Retour de l'impression      */
+
     if (addr->virt_cache[0] == '\0' || addr->last_virt_size != msize)
     {
         switch (msize)
         {
             case MDS_8_BITS:
-                snprintf(addr->virt_cache, VMPA_MAX_SIZE,"0x%02" PRIx64, addr->virtual);
+                ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE,"0x%02" PRIx64, addr->virtual);
                 break;
 
             case MDS_16_BITS:
-                snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%04" PRIx64, addr->virtual);
+                ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%04" PRIx64, addr->virtual);
                 break;
 
             case MDS_32_BITS:
-                snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%08" PRIx64, addr->virtual);
+                ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%08" PRIx64, addr->virtual);
                 break;
 
             case MDS_64_BITS:
-                snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%016" PRIx64, addr->virtual);
+                ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%016" PRIx64, addr->virtual);
                 break;
 
             default:
-                snprintf(addr->virt_cache, VMPA_MAX_SIZE, "???");
+                ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE, "???");
                 break;
 
         }
 
         addr->last_virt_size = msize;
+        addr->last_virt_len = ret;
 
     }
 
+    if (length != NULL)
+        *length = addr->last_virt_size;
+
     return addr->virt_cache;
 
 }
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index 5df9b8a..461780c 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -25,6 +25,7 @@
 #define _ARCH_VMPA_H
 
 
+#include <alloca.h>
 #include <limits.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -50,9 +51,11 @@ struct _vmpa2_t
     off_t physical;                         /* Position physique           */
     uint64_t virtual;                       /* Adresse virtuelle           */
 
-    MemoryDataSize last_phy_size;           /* Dernière taille demandée #1 */
+    MemoryDataSize last_phys_size;          /* Dernière taille demandée #1 */
     MemoryDataSize last_virt_size;          /* Dernière taille demandée #2 */
-    char phy_cache[VMPA_MAX_SIZE];          /* Impression physique cachée  */
+    size_t last_phys_len;                   /* Dernière taille fournie #1  */
+    size_t last_virt_len;                   /* Dernière taille fournie #2  */
+    char phys_cache[VMPA_MAX_SIZE];         /* Impression physique cachée  */
     char virt_cache[VMPA_MAX_SIZE];         /* Impression virtuelle cachée */
 
 };
@@ -66,6 +69,30 @@ typedef struct _vmpa2_t vmpa2_t;
 typedef struct _vmpa2_t vmpa2t;
 
 
+
+
+/* Crée la copie d'un adressage mémoire en local. */
+//inline vmpa2t *local_dup_vmpa(const vmpa2t *) __attribute__((always_inline));
+
+
+
+#define local_dup_vmpa(src) \
+    ({                      \
+        vmpa2t *__result;           \
+        __result = alloca(sizeof(vmpa2t));        \
+        copy_vmpa(__result, src);               \
+        __result;                           \
+    })
+
+
+
+/* Copie la définition d'un adressage dans un autre. */
+void copy_vmpa(vmpa2t *, const vmpa2t *);
+
+
+
+
+
 /* Initialise une localisation dans l'espace mémoire/physique. */
 void init_vmpa(vmpa2t *, off_t, uint64_t);
 
@@ -81,6 +108,11 @@ vmpa2t *make_vmpa(off_t, uint64_t);
 
 
 
+#define get_phy_addr(a) a->physical
+#define get_virt_addr(a) a->virtual
+
+
+
 
 /* Lit la définition d'une adresse depuis un flux réseau. */
 bool recv_vmpa(vmpa2t *, int, int);
@@ -89,10 +121,10 @@ bool recv_vmpa(vmpa2t *, int, int);
 bool send_vmpa(const vmpa2t *, int, int);
 
 /* Transforme une adresse physique en chaîne de caractères. */
-const char *vmpa2_phy_to_string(vmpa2t *, MemoryDataSize);
+const char *vmpa2_phys_to_string(vmpa2t *, MemoryDataSize, size_t *);
 
 /* Transforme une adresse virtuelle en chaîne de caractères. */
-const char *vmpa2_virt_to_string(vmpa2t *, MemoryDataSize);
+const char *vmpa2_virt_to_string(vmpa2t *, MemoryDataSize, size_t *);
 
 
 
diff --git a/src/arch/x86/instruction.c b/src/arch/x86/instruction.c
index 789aab2..0450d96 100644
--- a/src/arch/x86/instruction.c
+++ b/src/arch/x86/instruction.c
@@ -494,7 +494,7 @@ static void g_x86_instruction_init(GX86Instruction *instr)
 
     parent = G_ARCH_INSTRUCTION(instr);
 
-    parent->get_text = (get_instruction_text_fc)x86_get_instruction_text;
+    //parent->get_text = (get_instruction_text_fc)x86_get_instruction_text;
     parent->get_link = (get_instruction_link_fc)x86_get_instruction_link;
     parent->is_return = (is_instruction_return_fc)x86_instruction_is_return;
 
diff --git a/src/dialogs/export.c b/src/dialogs/export.c
index 25d62a7..2f572a5 100644
--- a/src/dialogs/export.c
+++ b/src/dialogs/export.c
@@ -243,7 +243,7 @@ static bool export_buffer_line(GCodeBuffer *buffer, GBufferLine *line, struct _e
 
     else
         g_buffer_line_export(line, export->fd, export->type,
-                             export->addr, export->code, export->content);
+                             true/* FIX%E */, export->addr, export->code, export->content);
 
     return true;
 
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index 63804a5..201c64b 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -80,7 +80,7 @@ struct _GBufferLine
 {
     GObject parent;                         /* A laisser en premier        */
 
-    vmpa_t addr;                            /* Adresse geographique        */
+    const vmpa2t *addr;                     /* Emplacement geographique    */
     BufferLineColumn main_column;           /* Colonne principale          */
 
     buffer_line_column columns[BLC_COUNT];  /* Répartition du texte        */
@@ -343,7 +343,7 @@ static void g_buffer_line_init(GBufferLine *line)
 {
     BufferLineColumn i;                     /* Boucle de parcours          */
 
-    for (i = BLC_ADDRESS; i < BLC_COUNT; i++)
+    for (i = 0; i < BLC_COUNT; i++)
         reset_column(&line->columns[i]);
 
     line->merge_start = BLC_COUNT;
@@ -354,7 +354,7 @@ static void g_buffer_line_init(GBufferLine *line)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : addr = adresse où va se situer la ligne.                     *
+*  Paramètres  : addr = emplacement où va se situer la ligne.                 *
 *                main = colonne à référencer comme étant la principale.       *
 *                                                                             *
 *  Description : Crée une nouvelle représentation de fragments de texte.      *
@@ -365,7 +365,7 @@ static void g_buffer_line_init(GBufferLine *line)
 *                                                                             *
 ******************************************************************************/
 
-GBufferLine *g_buffer_line_new(vmpa_t addr, BufferLineColumn main)
+GBufferLine *g_buffer_line_new(const vmpa2t *addr, BufferLineColumn main)
 {
     GBufferLine *result;                    /* Composant à retourner       */
 
@@ -393,7 +393,66 @@ GBufferLine *g_buffer_line_new(vmpa_t addr, BufferLineColumn main)
 
 vmpa_t g_buffer_line_get_address(const GBufferLine *line)
 {
-    return line->addr;
+    return 0/* FIXME line->addr*/;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line    = ligne à venir compléter.                           *
+*                psize   = taille souhaitée de l'impression des positions.    *
+*                vsize   = taille souhaitée de l'impression des adresses.     *
+*                content = contenu binaire global.                            *
+*                length  = taille de l'extrait de code à afficher.            *
+*                full    = la portion est assez courte pour être entière ?    *
+*                                                                             *
+*  Description : Construit le tronc commun d'une ligne d'instruction.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_buffer_line_fill_for_instr(GBufferLine *line, MemoryDataSize psize, MemoryDataSize vsize, const bin_t *content, off_t length, bool full)
+{
+    size_t len;                             /* Taille de l'élément inséré  */
+    char *address;                          /* Adresse au format texte     */
+    char *bin_code;                         /* Tampon du code binaire      */
+    off_t start;                            /* Début de traitement         */
+    off_t end;                              /* Limite de traitement        */
+    off_t i;                                /* Boucle de parcours #1       */
+    char *iter;                             /* Boucle de parcours #2       */
+    int ret;                                /* Progression dans l'écriture */
+
+    /* Adresse physique puis virtuelle */
+
+    address = vmpa2_phys_to_string(line->addr, psize, &len);
+    g_buffer_line_insert_text(line, BLC_PHYSICAL, address, len, RTT_RAW);
+
+    address = vmpa2_virt_to_string(line->addr, vsize, &len);
+    g_buffer_line_insert_text(line, BLC_VIRTUAL, address, len, RTT_RAW);
+
+    /* Code brut */
+
+    bin_code = (char *)calloc(length * 3 + 3, sizeof(char));
+
+    start = get_phy_addr(line->addr);
+    end = start + length;
+
+    for (i = start, iter = bin_code; i < end; i++, iter += ret)
+    {
+        if ((i + 1) < end)
+            ret = snprintf(iter, 4, "%02hhx ", content[i]);
+        else
+            ret = snprintf(iter, 6, "%02hhx%s", content[i], full ? "" : "...");
+
+    }
+
+    g_buffer_line_insert_text(line, BLC_BINARY, bin_code, iter - bin_code, RTT_RAW_CODE);
+
+    free(bin_code);
 
 }
 
@@ -441,7 +500,7 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
 
     result = NULL;
 
-    for (i = BLC_ADDRESS; i < BLC_COUNT; i++)
+    for (i = 0; i < BLC_COUNT; i++)
     {
         /* FIXME : addr/code */
 
@@ -470,7 +529,8 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
 *                caret = position du curseur à faire évoluer.                 *
 *                ctrl  = indique la demande d'un parcours rapide.             *
 *                dir   = direction du parcours.                               *
-*                addr  = indique si les positions doivent être affichées.     *
+*                phys  = indique si les positions doivent être affichées.     *
+*                virt  = indique si les adresses doivent être affichées.      *
 *                code  = indique si le code binaire doit être affiché.        *
 *                                                                             *
 *  Description : Déplace le curseur au sein d'une vue de tampon.              *
@@ -481,9 +541,11 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint
 *                                                                             *
 ******************************************************************************/
 
-bool g_buffer_line_move_caret(const GBufferLine *line, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, bool addr, bool code)
+bool g_buffer_line_move_caret(const GBufferLine *line, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, bool phys, bool virt, bool code)
 {
 
+    /* TODO : utiliser les arguments booléens */
+
     caret->x += (dir == GDK_SCROLL_RIGHT ? 10 : -10);
 
     return true;
@@ -512,7 +574,7 @@ GSList *g_buffer_line_highlight_all_same_segments(const GBufferLine *line, GSLis
 {
     BufferLineColumn i;                     /* Boucle de parcours          */
 
-    for (i = BLC_ADDRESS; i < BLC_COUNT; i++)
+    for (i = 0; i < BLC_COUNT; i++)
         list = highlight_all_same_segments(&line->columns[i], list, ref);
 
     return list;
@@ -621,7 +683,8 @@ gint g_buffer_line_get_column_width(GBufferLine *line, BufferLineColumn index)
 *                                                                             *
 *  Paramètres  : line  = ligne à venir compléter.                             *
 *                merge = précise la première colonne marquant la fusion. [OUT]*
-*                addr  = indique si les positions doivent être affichées.     *
+*                phys  = indique si les positions doivent être affichées.     *
+*                virt  = indique si les adresses doivent être affichées.      *
 *                code  = indique si le code binaire doit être affiché.        *
 *                                                                             *
 *  Description : Fournit la dernière largeur d'une ligne avec fusion.         *
@@ -632,12 +695,14 @@ gint g_buffer_line_get_column_width(GBufferLine *line, BufferLineColumn index)
 *                                                                             *
 ******************************************************************************/
 
-gint g_buffer_line_get_merge_width(GBufferLine *line, BufferLineColumn *merge, bool addr, bool code)
+gint g_buffer_line_get_merge_width(GBufferLine *line, BufferLineColumn *merge, bool phys, bool virt, bool code)
 {
     gint result;                            /* Largeur à retourner         */
 
     result = 0;
 
+    /* TODO : wtf ?! quelle est l'utilité des arguments booléens ? */
+
     *merge = line->merge_start;
 
     if (line->merge_start < BLC_COUNT)
@@ -678,7 +743,8 @@ void g_buffer_line_start_merge_at(GBufferLine *line, BufferLineColumn start)
 *                max_widths = largeurs de colonne à respecter.                *
 *                x_init     = abscisse du point d'impression de départ.       *
 *                y          = ordonnée du point d'impression.                 *
-*                addr       = indique si les positions doivent être affichées.*
+*                phys       = indique si les positions doivent être affichées.*
+*                virt       = indique si les adresses doivent être affichées. *
 *                code       = indique si le code binaire doit être affiché.   *
 *                                                                             *
 *  Description : Imprime la ligne de texte représentée.                       *
@@ -689,7 +755,7 @@ void g_buffer_line_start_merge_at(GBufferLine *line, BufferLineColumn start)
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths[BLC_COUNT], gint x_init, gint y, bool addr, bool code)
+void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths[BLC_COUNT], gint x_init, gint y, bool phys, bool virt, bool code)
 {
     GBufferLineClass *class;                /* Stockage de briques de base */
     gint x;                                 /* Point de départ d'impression*/
@@ -702,9 +768,10 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths
 
     x = x_init;
 
-    for (i = BLC_ADDRESS; i < BLC_COUNT; i++)
+    for (i = 0; i < BLC_COUNT; i++)
     {
-        if (i == BLC_ADDRESS && !addr) continue;
+        if (i == BLC_PHYSICAL && !phys) continue;
+        if (i == BLC_VIRTUAL && !virt) continue;
         if (i == BLC_BINARY && !code) continue;
 
         draw_segments_of_column(&line->columns[i], cairo, x, y);
@@ -723,7 +790,8 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths
 *  Paramètres  : line    = ligne de texte à manipuler.                        *
 *                fd      = flux ouvert en écriture.                           *
 *                type    = type d'exportation attendue.                       *
-*                addr    = indique si les positions doivent être affichées.   *
+*                phys    = indique si les positions doivent être affichées.   *
+*                virt    = indique si les adresses doivent être affichées.    *
 *                code    = indique si le code binaire doit être affiché.      *
 *                content = indique si le gros du contenu doit être affiché.   *
 *                                                                             *
@@ -735,15 +803,16 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_line_export(GBufferLine *line, int fd, BufferExportType type, bool addr, bool code, bool content)
+void g_buffer_line_export(GBufferLine *line, int fd, BufferExportType type, bool phys, bool virt, bool code, bool content)
 {
     BufferLineColumn i;                     /* Boucle de parcours          */
 
-    for (i = BLC_ADDRESS; i < BLC_COUNT; i++)
+    for (i = 0; i < BLC_COUNT; i++)
     {
-        if (i == BLC_ADDRESS && !addr) continue;
+        if (i == BLC_PHYSICAL && !phys) continue;
+        if (i == BLC_VIRTUAL && !virt) continue;
         if (i == BLC_BINARY && !code) continue;
-        if (!(i == BLC_ADDRESS || i == BLC_BINARY) && !content) continue;
+        if (!(i == BLC_PHYSICAL || i == BLC_VIRTUAL || i == BLC_BINARY) && !content) continue;
 
         dprintf(fd, "TODO\n");
 
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index 7d48cf3..fa64fe1 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -31,6 +31,7 @@
 
 #include "gbuffersegment.h"
 #include "../arch/archbase.h"
+#include "../arch/vmpa.h"
 
 
 
@@ -53,7 +54,8 @@ typedef struct _GBufferLineClass GBufferLineClass;
 /* Désignation des colonnes d'une ligne */
 typedef enum _BufferLineColumn
 {
-    BLC_ADDRESS,                            /* Adresse virtuelle           */
+    BLC_PHYSICAL,                           /* Position physique           */
+    BLC_VIRTUAL,                            /* Adresse virtuelle           */
     BLC_BINARY,                             /* Contenu sous forme binaire  */
     BLC_ASSEMBLY_HEAD,                      /* Instruction pour assembleur */
     BLC_ASSEMBLY,                           /* Code pour assembleur        */
@@ -81,16 +83,19 @@ typedef enum _BufferLineColumn
 GType g_buffer_line_get_type(void);
 
 /* Crée une nouvelle représentation de fragments de texte. */
-GBufferLine *g_buffer_line_new(vmpa_t, BufferLineColumn);
+GBufferLine *g_buffer_line_new(const vmpa2t *, BufferLineColumn);
 
 /* Indique l'adresse à laquelle se situe la ligne. */
 vmpa_t g_buffer_line_get_address(const GBufferLine *);
 
+/* Construit le tronc commun d'une ligne d'instruction. */
+void g_buffer_line_fill_for_instr(GBufferLine *, MemoryDataSize, MemoryDataSize, const bin_t *, off_t, bool);
+
 /* Ajoute un fragment de texte à une colonne de ligne. */
 void g_buffer_line_add_segment(GBufferLine *, BufferLineColumn, GBufferSegment *) __attribute__ ((deprecated));
 
 /* Déplace le curseur au sein d'une vue de tampon. */
-bool g_buffer_line_move_caret(const GBufferLine *, GdkRectangle *, bool, GdkScrollDirection, bool, bool);
+bool g_buffer_line_move_caret(const GBufferLine *, GdkRectangle *, bool, GdkScrollDirection, bool, bool, bool);
 
 /* Donne le segment présent à une abscisse donnée. */
 GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BLC_COUNT], gint *, bool);
@@ -108,16 +113,16 @@ char *g_buffer_line_get_text(const GBufferLine *);
 gint g_buffer_line_get_column_width(GBufferLine *, BufferLineColumn);
 
 /* Fournit la dernière largeur d'une ligne avec fusion. */
-gint g_buffer_line_get_merge_width(GBufferLine *, BufferLineColumn *, bool, bool);
+gint g_buffer_line_get_merge_width(GBufferLine *, BufferLineColumn *, bool, bool, bool);
 
 /* Définit la colonne à partir de laquelle la fusion opère. */
 void g_buffer_line_start_merge_at(GBufferLine *, BufferLineColumn);
 
 /* Imprime la ligne de texte représentée. */
-void g_buffer_line_draw(GBufferLine *, cairo_t *, const gint [BLC_COUNT], gint, gint, bool, bool);
+void g_buffer_line_draw(GBufferLine *, cairo_t *, const gint [BLC_COUNT], gint, gint, bool, bool, bool);
 
 /* Exporte la ligne de texte représentée. */
-void g_buffer_line_export(GBufferLine *, int, BufferExportType, bool, bool, bool);
+void g_buffer_line_export(GBufferLine *, int, BufferExportType, bool, bool, bool, bool);
 
 
 
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 5be632c..708a089 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -182,7 +182,7 @@ static void g_buffer_view_reset_required_height(GBufferView *);
 static void g_buffer_view_reset_required_widths(GBufferView *);
 
 /* Calcule les largeurs requises par une visualisation. */
-static void g_buffer_view_compute_required_widths(GBufferView *, bool, bool);
+static void g_buffer_view_compute_required_widths(GBufferView *, bool, bool, bool);
 
 
 
@@ -466,7 +466,7 @@ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, vmpa_t a
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : buffer = composant GTK à mettre à jour.                      *
-*                addr   = adresse où va se situer la ligne.                   *
+*                addr   = emplacement où va se situer la ligne.               *
 *                                                                             *
 *  Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. *
 *                                                                             *
@@ -476,7 +476,7 @@ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, vmpa_t a
 *                                                                             *
 ******************************************************************************/
 
-GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, vmpa_t addr)
+GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, const vmpa2t *addr)
 {
     GBufferLine *result;                    /* Instance à retourner        */
     size_t i;                               /* Boucle de parcours          */
@@ -886,7 +886,8 @@ static void g_buffer_view_compute_required_height(GBufferView *view)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : view = visualisation à mettre à jour.                        *
-*                addr = indique si les positions doivent être affichées.      *
+*                phys = indique si les positions doivent être affichées.      *
+*                virt = indique si les adresses doivent être affichées.       *
 *                code = indique si le code binaire doit être affiché.         *
 *                                                                             *
 *  Description : Calcule les largeurs requises par une visualisation.         *
@@ -897,7 +898,7 @@ static void g_buffer_view_compute_required_height(GBufferView *view)
 *                                                                             *
 ******************************************************************************/
 
-static void g_buffer_view_compute_required_widths(GBufferView *view, bool addr, bool code)
+static void g_buffer_view_compute_required_widths(GBufferView *view, bool phys, bool virt, bool code)
 {
     GBufferLine **lines;                    /* Liste des lignes à traiter  */
     size_t first;                           /* Première ligne intégrée     */
@@ -930,7 +931,7 @@ static void g_buffer_view_compute_required_widths(GBufferView *view, bool addr,
                 view->max_widths[j] = MAX(view->max_widths[j], width);
             }
 
-            width = g_buffer_line_get_merge_width(lines[i], &merge, addr, code);
+            width = g_buffer_line_get_merge_width(lines[i], &merge, phys, virt, code);
             view->last_width = MAX(view->last_width, width);
             if (merge != BLC_COUNT)
             {
@@ -973,7 +974,8 @@ gint g_buffer_view_get_line_height(GBufferView *view)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : view = visualisation à consulter.                            *
-*                addr = indique si les positions doivent être affichées.      *
+*                phys = indique si les positions doivent être affichées.      *
+*                virt = indique si les adresses doivent être affichées.       *
 *                code = indique si le code binaire doit être affiché.         *
 *                                                                             *
 *  Description : Fournit la largeur requise par une visualisation.            *
@@ -984,7 +986,7 @@ gint g_buffer_view_get_line_height(GBufferView *view)
 *                                                                             *
 ******************************************************************************/
 
-gint g_buffer_view_get_width(GBufferView *view, bool addr, bool code)
+gint g_buffer_view_get_width(GBufferView *view, bool phys, bool virt, bool code)
 {
     gint result;                            /* Taille à retourner          */
     gint col_width;                         /* Calcul selon les colonnes   */
@@ -992,7 +994,7 @@ gint g_buffer_view_get_width(GBufferView *view, bool addr, bool code)
     BufferLineColumn i;                     /* Boucle de parcours          */
 
     if (!WIDTHS_CACHED(view))
-        g_buffer_view_compute_required_widths(view, addr, code);
+        g_buffer_view_compute_required_widths(view, phys, virt, code);
 
     result = view->left_text;
 
@@ -1003,7 +1005,8 @@ gint g_buffer_view_get_width(GBufferView *view, bool addr, bool code)
 
     for (i = 0; i < BLC_COUNT; i++)
     {
-        if (i == BLC_ADDRESS && !addr) continue;
+        if (i == BLC_PHYSICAL && !phys) continue;
+        if (i == BLC_VIRTUAL && !virt) continue;
         if (i == BLC_BINARY && !code) continue;
 
         col_width += view->max_widths[i];
@@ -1017,7 +1020,8 @@ gint g_buffer_view_get_width(GBufferView *view, bool addr, bool code)
 
     for (i = 0; i < view->last_merge; i++)
     {
-        if (i == BLC_ADDRESS && !addr) continue;
+        if (i == BLC_PHYSICAL && !phys) continue;
+        if (i == BLC_VIRTUAL && !virt) continue;
         if (i == BLC_BINARY && !code) continue;
 
         full_width += view->max_widths[i];
@@ -1118,7 +1122,8 @@ vmpa_t g_buffer_view_compute_caret(GBufferView *view, GBufferLine *line, size_t
 *                caret = position du curseur à faire évoluer.                 *
 *                ctrl  = indique la demande d'un parcours rapide.             *
 *                dir   = direction du parcours.                               *
-*                addr  = indique si les positions doivent être affichées.     *
+*                phys  = indique si les positions doivent être affichées.     *
+*                virt  = indique si les adresses doivent être affichées.      *
 *                code  = indique si le code binaire doit être affiché.        *
 *                                                                             *
 *  Description : Déplace le curseur au sein d'une vue de tampon.              *
@@ -1129,7 +1134,7 @@ vmpa_t g_buffer_view_compute_caret(GBufferView *view, GBufferLine *line, size_t
 *                                                                             *
 ******************************************************************************/
 
-vmpa_t g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, bool addr, bool code)
+vmpa_t g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctrl, GdkScrollDirection dir, bool phys, bool virt, bool code)
 {
     bool result;                            /* Actualisation à renvoyer    */
     bool computed;                          /* Récursivité pris en compte  */
@@ -1153,7 +1158,8 @@ vmpa_t g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctr
         case GDK_SCROLL_LEFT:
         case GDK_SCROLL_RIGHT:
             left_pos = view->left_text;
-            if (addr) left_pos += view->max_widths[BLC_ADDRESS] + COL_MARGIN;
+            if (phys) left_pos += view->max_widths[BLC_PHYSICAL] + COL_MARGIN;
+            if (virt) left_pos += view->max_widths[BLC_VIRTUAL] + COL_MARGIN;
             if (code) left_pos += view->max_widths[BLC_BINARY] + COL_MARGIN;
             right_pos = left_pos;
             for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++)
@@ -1184,13 +1190,13 @@ vmpa_t g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctr
             line = g_buffer_view_find_line_at(view, caret->y, NULL);
             if (line == NULL) break;
 
-            result = g_buffer_line_move_caret(line, caret, ctrl, GDK_SCROLL_LEFT, addr, code);
+            result = g_buffer_line_move_caret(line, caret, ctrl, GDK_SCROLL_LEFT, phys, virt, code);
 
             if (caret->x < left_pos)
             {
                 caret->x = right_pos;
 
-                result = g_buffer_view_move_caret(view, caret, ctrl, GDK_SCROLL_UP, addr, code);
+                result = g_buffer_view_move_caret(view, caret, ctrl, GDK_SCROLL_UP, phys, virt, code);
 
                 if (result == VMPA_INVALID)
                     caret->x = left_pos;
@@ -1205,13 +1211,13 @@ vmpa_t g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, bool ctr
             line = g_buffer_view_find_line_at(view, caret->y, NULL);
             if (line == NULL) break;
 
-            result = g_buffer_line_move_caret(line, caret, ctrl, GDK_SCROLL_RIGHT, addr, code);
+            result = g_buffer_line_move_caret(line, caret, ctrl, GDK_SCROLL_RIGHT, phys, virt, code);
 
             if (!result)
             {
                 caret->x = left_pos;
 
-                result = g_buffer_view_move_caret(view, caret, ctrl, GDK_SCROLL_DOWN, addr, code);
+                result = g_buffer_view_move_caret(view, caret, ctrl, GDK_SCROLL_DOWN, phys, virt, code);
 
                 if (result == VMPA_INVALID)
                     caret->x = right_pos;
@@ -1347,7 +1353,8 @@ void g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y)
 *                fake_x = abscisse réelle du point 0 à l'écran.               *
 *                fake_y = ordonnée réelle du point 0 à l'écran.               *
 *                area   = position et surface à traiter.                      *
-*                addr   = indique si les positions doivent être affichées.    *
+*                phys   = indique si les positions doivent être affichées.    *
+*                virt   = indique si les adresses doivent être affichées.     *
 *                code   = indique si le code binaire doit être affiché.       *
 *                                                                             *
 *  Description : Imprime la visualisation du tampon de code désassemblé.      *
@@ -1358,7 +1365,7 @@ void g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y)
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint fake_y, const cairo_rectangle_int_t *area, bool addr, bool code)
+void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint fake_y, const cairo_rectangle_int_t *area, bool phys, bool virt, bool code)
 {
     gint real_x;                            /* Abscisse réelle pour tampon */
     gint real_y;                            /* Ordonnée réelle pour tampon */
@@ -1395,7 +1402,7 @@ void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint fake_x, gint
             */
 
             g_buffer_line_draw(lines[i], cr,
-                               view->max_widths, real_x, y, addr, code);
+                               view->max_widths, real_x, y, phys, virt, code);
 
             y += view->line_height;
 
diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h
index 18d13f0..3167d41 100644
--- a/src/glibext/gcodebuffer.h
+++ b/src/glibext/gcodebuffer.h
@@ -60,7 +60,7 @@ GCodeBuffer *g_code_buffer_new(BufferLineColumn);
 #define g_code_buffer_append_new_line_fixme(b) g_code_buffer_append_new_line(b, 0ull)
 
 /* Ajoute une nouvelle ligne à un tampon pour code désassemblé. */
-GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *, vmpa_t);
+GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *, const vmpa2t *);
 
 /* Ajoute une nouvelle ligne à un tampon pour code désassemblé. */
 GBufferLine *g_code_buffer_insert_at(GCodeBuffer *, vmpa_t, bool);
@@ -122,7 +122,7 @@ GCodeBuffer *g_buffer_view_get_buffer(const GBufferView *);
 gint g_buffer_view_get_line_height(GBufferView *);
 
 /* Fournit la largeur requise par une visualisation. */
-gint g_buffer_view_get_width(GBufferView *, bool, bool);
+gint g_buffer_view_get_width(GBufferView *, bool, bool, bool);
 
 /* Fournit la hauteur requise par une visualisation. */
 gint g_buffer_view_get_height(const GBufferView *);
@@ -131,7 +131,7 @@ gint g_buffer_view_get_height(const GBufferView *);
 vmpa_t g_buffer_view_compute_caret(GBufferView *, GBufferLine *, size_t, gint, GdkRectangle *);
 
 /* Déplace le curseur au sein d'une vue de tampon. */
-vmpa_t g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkScrollDirection, bool, bool);
+vmpa_t g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkScrollDirection, bool, bool, bool);
 
 /* Supprime toute mise en évidence de segments. */
 bool g_buffer_view_unhighlight_segments(GBufferView *);
@@ -140,7 +140,7 @@ bool g_buffer_view_unhighlight_segments(GBufferView *);
 void g_buffer_view_highlight_segments(GBufferView *, gint, gint);
 
 /* Imprime la visualisation du tampon de code désassemblé. */
-void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, gint, const cairo_rectangle_int_t *, bool, bool);
+void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, gint, const cairo_rectangle_int_t *, bool, bool, bool);
 
 /* Fournit la ligne présente à une ordonnée donnée. */
 GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
diff --git a/src/glibext/signal.h b/src/glibext/signal.h
index 8d139a7..c2a442d 100644
--- a/src/glibext/signal.h
+++ b/src/glibext/signal.h
@@ -26,6 +26,7 @@
 
 
 #include <glib-object.h>
+#include <gobject/gclosure.h>
 
 
 
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index 26f67c1..e58ae5c 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -372,6 +372,7 @@ static void gtk_buffer_view_get_preferred_width(GtkWidget *widget, gint *minimal
 
     if (view->buffer_view != NULL)
         *minimal = g_buffer_view_get_width(view->buffer_view,
+                                           *GTK_VIEW_PANEL(view)->display_phys,
                                            *GTK_VIEW_PANEL(view)->display_addr,
                                            *GTK_VIEW_PANEL(view)->display_code);
     else
@@ -420,7 +421,7 @@ static void gtk_buffer_view_size_allocate(GtkWidget *widget, GtkAllocation *allo
 
     view = GTK_BUFFER_VIEW(widget);
 
-    width = g_buffer_view_get_width(view->buffer_view, *panel->display_addr, *panel->display_code);
+    width = g_buffer_view_get_width(view->buffer_view, *panel->display_phys, *panel->display_addr, *panel->display_code);
     height = g_buffer_view_get_height(view->buffer_view);
 
     gtk_view_panel_compute_allocation(panel, &valloc);
@@ -516,7 +517,7 @@ static gboolean gtk_buffer_view_draw(GtkWidget *widget, cairo_t *cr)
 
     if (view->buffer_view != NULL)
         g_buffer_view_draw(view->buffer_view, cr, fake_x, fake_y, &area,
-                           *pview->display_addr, *pview->display_code);
+                           *pview->display_phys, *pview->display_addr, *pview->display_code);
 
     return TRUE;
 
@@ -623,7 +624,8 @@ static void gtk_buffer_view_cache_glance(GtkBufferView *view, cairo_t *cairo, co
 *                                                                             *
 *  Paramètres  : view   = composant GTK à mettre à jour.                      *
 *                buffer = tampon de lignes à encadrer.                        *
-*                addr   = indique si les positions doivent être affichées.    *
+*                phys   = indique si les positions doivent être affichées.    *
+*                virt   = indique si les adresses doivent être affichées.     *
 *                code   = indique si le code binaire doit être affiché.       *
 *                                                                             *
 *  Description : Prend acte de l'association d'un tampon de lignes.           *
@@ -634,7 +636,7 @@ static void gtk_buffer_view_cache_glance(GtkBufferView *view, cairo_t *cairo, co
 *                                                                             *
 ******************************************************************************/
 
-void gtk_buffer_view_attach_buffer(GtkBufferView *view, GBufferView *buffer, bool *addr, bool *code)
+void gtk_buffer_view_attach_buffer(GtkBufferView *view, GBufferView *buffer, /*bool *phys, */bool *addr, bool *code)
 {
     gint width;                             /* Largeur de l'objet actuelle */
     gint height;                            /* Hauteur de l'objet actuelle */
@@ -658,7 +660,7 @@ void gtk_buffer_view_attach_buffer(GtkBufferView *view, GBufferView *buffer, boo
 
     /* Validation finale */
 
-    width = g_buffer_view_get_width(view->buffer_view, *addr, *code);
+    width = g_buffer_view_get_width(view->buffer_view, true/* FIXME : *phys*/, *addr, *code);
     height = g_buffer_view_get_height(view->buffer_view);
 
     width += -view->left_text + 1;
diff --git a/src/gtkext/gtkviewpanel-int.h b/src/gtkext/gtkviewpanel-int.h
index 63a6a5b..b3a6cf6 100644
--- a/src/gtkext/gtkviewpanel-int.h
+++ b/src/gtkext/gtkviewpanel-int.h
@@ -68,6 +68,7 @@ struct _GtkViewPanel
     get_addr_coordinates_fc get_coordinates;/* Conversion adresse <-> pos. */
     cache_glance_fc cache_glance;           /* Cache de la mignature       */
 
+    bool *display_phys;                     /* Affichage des adresses ?    */
     bool *display_addr;                     /* Affichage des adresses ?    */
     bool *display_code;                     /* Affichage du code binaire ? */
 
diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c
index 2b1aa97..739fde7 100644
--- a/src/gtkext/gtkviewpanel.c
+++ b/src/gtkext/gtkviewpanel.c
@@ -303,6 +303,7 @@ void gtk_view_panel_attach_binary(GtkViewPanel *panel, GLoadedBinary *binary, bo
     g_object_ref(G_OBJECT(binary));
     panel->binary = binary;
 
+    panel->display_phys = addr;
     panel->display_addr = addr;
     panel->display_code = code;
 
-- 
cgit v0.11.2-87-g4458