From 465488d5b231c2552116a305c48b5fcccea55a09 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 10 Feb 2016 11:02:16 +0100
Subject: Improved the support of the DEX format.

---
 ChangeLog                         | 39 +++++++++++++++
 src/analysis/disass/links.c       | 19 ++++++--
 src/arch/dalvik/instruction.c     | 27 +++++++++++
 src/arch/dalvik/operand.c         | 99 ++++++++++++++++++++++++++++++++++-----
 src/arch/dalvik/operand.h         |  4 +-
 src/arch/dalvik/operands/target.c | 17 ++++---
 src/arch/dalvik/operands/target.h |  2 +-
 src/arch/processor.c              |  3 ++
 src/format/dex/class.c            | 47 +++++++++++++++++--
 src/format/dex/class.h            |  8 +++-
 src/format/dex/dex.c              | 40 ++++++++++++++--
 src/format/dex/dex.h              |  4 ++
 src/format/dex/method.c           |  9 ++--
 src/format/dex/method.h           |  2 +-
 src/format/elf/elf.c              | 12 ++---
 src/format/executable-int.c       |  8 +++-
 src/format/format-int.h           |  6 +--
 src/format/format.c               | 29 +++++++++++-
 18 files changed, 330 insertions(+), 45 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ddd89ea..e9f09cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+16-02-10  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/links.c:
+	Translate immediate values into targets with mode care.
+
+	* src/arch/dalvik/instruction.c:
+	Provide the encoding of Dalvik instructions, as required.
+
+	* src/arch/dalvik/operand.c:
+	* src/arch/dalvik/operand.h:
+	Update the decoding of operands. Check the quantity of bytes consumed
+	from the binary stream.
+
+	* src/arch/dalvik/operands/target.c:
+	* src/arch/dalvik/operands/target.h:
+	Update code.
+
+	* src/arch/processor.c:
+	Check all decoded instructions have a full defined location.
+
+	* src/format/dex/class.c:
+	* src/format/dex/class.h:
+	* src/format/dex/dex.c:
+	* src/format/dex/dex.h:
+	* src/format/dex/method.c:
+	* src/format/dex/method.h:
+	Improve the support of the DEX format.
+
+	* src/format/elf/elf.c:
+	Update code.
+
+	* src/format/executable-int.c:
+	Create full defined locations for architectures without virtual
+	addresses support.
+
+	* src/format/format-int.h:
+	* src/format/format.c:
+	Implement common code to complete format loading.
+
 16-02-09  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/raw.c:
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c
index 8d826c5..5e1e483 100644
--- a/src/analysis/disass/links.c
+++ b/src/analysis/disass/links.c
@@ -26,6 +26,7 @@
 
 
 #include "../../arch/instruction.h"
+#include "../../arch/raw.h"
 #include "../../arch/target.h"
 
 
@@ -128,6 +129,7 @@ static void establish_natural_link(GArchInstruction *instr, GArchInstruction *pr
 static void convert_immediate_into_target(GArchInstruction *instr, size_t index, GBinFormat *format)
 {
     GArchOperand *op;                       /* Opérande numérique en place */
+    GImmOperand *imm;                       /* Version native de l'opérande*/
     virt_t addr;                            /* Adresse visée par le saut   */
     MemoryDataSize msize;                   /* Taille de l'opérande        */
     GArchOperand *new;                      /* Instruction de ciblage      */
@@ -135,9 +137,13 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index,
     op = g_arch_instruction_get_operand(instr, index);
     if (!G_IS_IMM_OPERAND(op)) return;
 
-    if (g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &addr))
+    imm = G_IMM_OPERAND(op);
+
+    if (g_imm_operand_get_display(imm) != IOD_HEX) return;
+
+    if (g_imm_operand_to_virt_t(imm, &addr))
     {
-        msize = g_imm_operand_get_size(G_IMM_OPERAND(op));
+        msize = g_imm_operand_get_size(imm);
 
         new = g_target_operand_new(msize, addr);
 
@@ -167,6 +173,7 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index,
 
 static void establish_links_for_instruction(GArchInstruction *instr, GArchInstruction *list, GBinFormat *format)
 {
+    bool skip;                              /* Saut des conversions        */
     size_t count;                           /* Nombre d'opérandes présents */
     size_t i;                               /* Boucle de parcours          */
     GArchOperand *op;                       /* Opérande numérique en place */
@@ -174,11 +181,17 @@ static void establish_links_for_instruction(GArchInstruction *instr, GArchInstru
     vmpa2t addr;                            /* Localisation plus complète  */
     GArchInstruction *target;               /* Instruction visée au final  */
 
+    if (G_IS_RAW_INSTRUCTION(instr))
+        skip = g_raw_instruction_is_string(G_RAW_INSTRUCTION(instr));
+    else
+        skip = false;
+
     count = g_arch_instruction_count_operands(instr);
 
     for (i = 0; i < count; i++)
     {
-        convert_immediate_into_target(instr, i, format);
+        if (!skip)
+            convert_immediate_into_target(instr, i, format);
 
         op = g_arch_instruction_get_operand(instr, i);
         if (!G_IS_TARGET_OPERAND(op)) continue;
diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c
index 31f02c8..4c1dee0 100644
--- a/src/arch/dalvik/instruction.c
+++ b/src/arch/dalvik/instruction.c
@@ -48,6 +48,9 @@ static void g_dalvik_instruction_dispose(GDalvikInstruction *);
 /* Procède à la libération totale de la mémoire. */
 static void g_dalvik_instruction_finalize(GDalvikInstruction *);
 
+/* Indique l'encodage d'une instruction de façon détaillée. */
+static const char *g_dalvik_instruction_get_encoding(const 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 *);
 
@@ -373,6 +376,7 @@ static void g_dalvik_instruction_class_init(GDalvikInstructionClass *klass)
 
     instr = G_ARCH_INSTRUCTION_CLASS(klass);
 
+    instr->get_encoding = (get_instruction_encoding_fc)g_dalvik_instruction_get_encoding;
     instr->build_key = (build_instruction_keyword_fc)dalvik_build_instruction_keyword;
 
 }
@@ -469,6 +473,29 @@ GArchInstruction *g_dalvik_instruction_new(const char *keyword)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : instr = instruction quelconque à consulter.                  *
+*                                                                             *
+*  Description : Indique l'encodage d'une instruction de façon détaillée.     *
+*                                                                             *
+*  Retour      : Description humaine de l'encodage utilisé.                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const char *g_dalvik_instruction_get_encoding(const GDalvikInstruction *instr)
+{
+    const char *result;                     /* Description à retourner     */
+
+    result = "Dalvik";
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : instr = instruction Dalvik à consulter.                      *
 *                                                                             *
 *  Description : Indique l'opcode associé à une instruction Dalvik.           *
diff --git a/src/arch/dalvik/operand.c b/src/arch/dalvik/operand.c
index f8f7b39..83d95e5 100644
--- a/src/arch/dalvik/operand.c
+++ b/src/arch/dalvik/operand.c
@@ -24,6 +24,7 @@
 #include "operand.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 #include <stdarg.h>
 
@@ -56,7 +57,7 @@ typedef enum _DalvikOperandID
 
 
 /* Procède à la lecture d'opérandes pour une instruction. */
-static bool dalvik_read_basic_operands(GArchInstruction *, GDexFormat *, const GBinContent *, vmpa2t *, bool *, SourceEndian, DalvikOperandType, va_list);
+static bool dalvik_read_basic_operands(GArchInstruction *, GDexFormat *, const GBinContent *, vmpa2t *, bool *, SourceEndian, DalvikOperandType, ...);
 
 /* Procède à la lecture d'opérandes pour une instruction. */
 static bool dalvik_read_fixed_operands(GArchInstruction *, GDexFormat *, const GBinContent *, vmpa2t *, bool *, SourceEndian, DalvikOperandType);
@@ -75,7 +76,7 @@ static bool dalvik_read_variatic_operands(GArchInstruction *, GDexFormat *, cons
 *                low     = position éventuelle des 4 bits visés. [OUT]        *
 *                endian  = boutisme lié au binaire accompagnant.              *
 *                model   = type d'opérandes attendues.                        *
-*                ap      = éventuels arguments complémentaires.               *
+*                ...     = éventuels arguments complémentaires.               *
 *                                                                             *
 *  Description : Procède à la lecture d'opérandes pour une instruction.       *
 *                                                                             *
@@ -85,7 +86,7 @@ static bool dalvik_read_variatic_operands(GArchInstruction *, GDexFormat *, cons
 *                                                                             *
 ******************************************************************************/
 
-static bool dalvik_read_basic_operands(GArchInstruction *instr, GDexFormat *format, const GBinContent *content, vmpa2t *pos, bool *low, SourceEndian endian, DalvikOperandType model, va_list ap)
+static bool dalvik_read_basic_operands(GArchInstruction *instr, GDexFormat *format, const GBinContent *content, vmpa2t *pos, bool *low, SourceEndian endian, DalvikOperandType model, ...)
 {
     bool result;                            /* Bilan à retourner           */
     DalvikOperandID *types;                 /* Liste des chargements       */
@@ -93,6 +94,8 @@ static bool dalvik_read_basic_operands(GArchInstruction *instr, GDexFormat *form
     GArchOperand *op;                       /* Opérande unique décodé      */
     uint16_t value16;                       /* Valeur sur 16 bits          */
     DalvikPoolType pool_type;               /* Type de table à manipuler   */
+    va_list ap;                             /* Arguments complémentaires   */
+    const vmpa2t *base;                     /* Base pour les sauts de code */
 
     result = true;
 
@@ -334,15 +337,24 @@ static bool dalvik_read_basic_operands(GArchInstruction *instr, GDexFormat *form
                 break;
 
             case DOI_TARGET_8:
-                op = g_dalvik_target_operand_new(content, pos, MDS_8_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
+                va_start(ap, model);
+                base = va_arg(ap, const vmpa2t *);
+                op = g_dalvik_target_operand_new(content, pos, MDS_8_BITS_SIGNED, endian, base);
+                va_end(ap);
                 break;
 
             case DOI_TARGET_16:
-                op = g_dalvik_target_operand_new(content, pos, MDS_16_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
+                va_start(ap, model);
+                base = va_arg(ap, const vmpa2t *);
+                op = g_dalvik_target_operand_new(content, pos, MDS_16_BITS_SIGNED, endian, base);
+                va_end(ap);
                 break;
 
             case DOI_TARGET_32:
-                op = g_dalvik_target_operand_new(content, pos, MDS_32_BITS_SIGNED, endian, va_arg(ap, vmpa_t));
+                va_start(ap, model);
+                base = va_arg(ap, const vmpa2t *);
+                op = g_dalvik_target_operand_new(content, pos, MDS_32_BITS_SIGNED, endian, base);
+                va_end(ap);
                 break;
 
             default:
@@ -413,6 +425,12 @@ static bool dalvik_read_fixed_operands(GArchInstruction *instr, GDexFormat *form
 
     }
 
+    /* Consommation pleine et entière */
+
+    for (; i < 4; i++)
+        if (!g_binary_content_read_u4(content, pos, low, (uint8_t []) { 0 }))
+            goto err_padding;
+
     /* Rajout des éléments finaux déjà chargés */
 
     if (a == 5)
@@ -428,6 +446,8 @@ static bool dalvik_read_fixed_operands(GArchInstruction *instr, GDexFormat *form
 
     return true;
 
+ err_padding:
+
  err_registers:
 
     g_object_unref(G_OBJECT(target));
@@ -522,7 +542,6 @@ static bool dalvik_read_variatic_operands(GArchInstruction *instr, GDexFormat *f
 *                pos     = position courante dans ce flux. [OUT]              *
 *                endian  = boutisme lié au binaire accompagnant.              *
 *                model   = type d'opérandes attendues.                        *
-*                ...     = éventuelles données complémentaires.               *
 *                                                                             *
 *  Description : Procède à la lecture d'opérandes pour une instruction.       *
 *                                                                             *
@@ -532,12 +551,21 @@ static bool dalvik_read_variatic_operands(GArchInstruction *instr, GDexFormat *f
 *                                                                             *
 ******************************************************************************/
 
-bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBinContent *content, vmpa2t *pos, SourceEndian endian, DalvikOperandType model, ...)
+bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBinContent *content, vmpa2t *pos, SourceEndian endian, DalvikOperandType model)
 {
     bool result;                            /* Bilan à retourner           */
     GDexFormat *dformat;                    /* Autre version du format     */
     bool low;                               /* Partie d'octets à lire      */
+#ifndef NDEBUG
+    vmpa2t old;                             /* Position avant traitements  */
+#endif
+    vmpa2t base;                            /* Base pour les sauts de code */
+    vmpa2t *extra;                          /* Information complémentaire  */
     va_list ap;                             /* Arguments complémentaires   */
+#ifndef NDEBUG
+    phys_t expected;                        /* Consommation attendue       */
+    phys_t consumed;                        /* Consommation réelle         */
+#endif
 
     result = true;
 
@@ -545,6 +573,42 @@ bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBi
 
     low = true;
 
+#ifndef NDEBUG
+
+    copy_vmpa(&old, pos);
+
+#endif
+
+    /* Récupération de la base ? */
+
+    if (DALVIK_OP_GET_MNEMONIC(model) == 'T')
+    {
+        extra = &base;
+
+        copy_vmpa(extra, pos);
+        deminish_vmpa(extra, 1);
+
+    }
+    else extra = NULL;
+
+    /* Bourrage : ØØ|op ? */
+
+    switch (model & ~DALVIK_OP_EXTRA_MASK)
+    {
+        case DALVIK_OPT_10X:
+        case DALVIK_OPT_20T:
+        case DALVIK_OPT_30T:
+        case DALVIK_OPT_32X:
+            advance_vmpa(pos, 1);
+            break;
+
+        default:
+            break;
+
+    }
+
+    /* Décodage... */
+
     switch (model & ~DALVIK_OP_EXTRA_MASK)
     {
         case DALVIK_OPT_10T:
@@ -568,9 +632,7 @@ bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBi
         case DALVIK_OPT_31T:
         case DALVIK_OPT_32X:
         case DALVIK_OPT_51L:
-            va_start(ap, model);
-            result = dalvik_read_basic_operands(instr, dformat, content, pos, &low, endian, model, ap);
-            va_end(ap);
+            result = dalvik_read_basic_operands(instr, dformat, content, pos, &low, endian, model, extra);
             break;
 
         case DALVIK_OPT_35C:
@@ -588,6 +650,21 @@ bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBi
 
     }
 
+#ifndef NDEBUG
+
+    /* Vérification d'implémentation */
+
+    if (result)
+    {
+        expected = DALVIK_OP_GET_LEN(model) * 2;
+        consumed = 1 + compute_vmpa_diff(&old, pos);
+
+        assert(consumed == expected);
+
+    }
+
+#endif
+
     return result;
 
 }
diff --git a/src/arch/dalvik/operand.h b/src/arch/dalvik/operand.h
index 27901be..af15bde 100644
--- a/src/arch/dalvik/operand.h
+++ b/src/arch/dalvik/operand.h
@@ -65,6 +65,8 @@
 #define DALVIK_OP_POOL(p)       ((p) << DALVIK_OP_POOL_OFF)
 #define DALVIK_OP_GET_POOL(v)   (((v) & DALVIK_OP_POOL_MASK) >> DALVIK_OP_POOL_OFF)
 
+#define DALVIK_OP_GET_MNEMONIC(v) ((v) & 0xff)
+
 
 /* Types d'opérandes supportés */
 typedef enum _DalvikOperandType
@@ -112,7 +114,7 @@ typedef enum _DalvikOperandType
 
 
 /* Procède à la lecture d'opérandes pour une instruction. */
-bool dalvik_read_operands(GArchInstruction *, GExeFormat *, const GBinContent *, vmpa2t *, SourceEndian, DalvikOperandType, ...);
+bool dalvik_read_operands(GArchInstruction *, GExeFormat *, const GBinContent *, vmpa2t *, SourceEndian, DalvikOperandType);
 
 /* Procède à la lecture d'opérandes pour une instruction. */
 void dalvik_mark_first_operand_as_written(GArchInstruction *);
diff --git a/src/arch/dalvik/operands/target.c b/src/arch/dalvik/operands/target.c
index 42d09cf..5e8b91a 100644
--- a/src/arch/dalvik/operands/target.c
+++ b/src/arch/dalvik/operands/target.c
@@ -169,31 +169,34 @@ static void g_dalvik_target_operand_finalize(GDalvikTargetOperand *operand)
 *                                                                             *
 ******************************************************************************/
 
-GArchOperand *g_dalvik_target_operand_new(const GBinContent *content, vmpa2t *pos, MemoryDataSize size, SourceEndian endian, vmpa_t base)
+GArchOperand *g_dalvik_target_operand_new(const GBinContent *content, vmpa2t *pos, MemoryDataSize size, SourceEndian endian, const vmpa2t *base)
 {
     GDalvikTargetOperand *result;           /* Structure à retourner       */
+    phys_t offset;                          /* Emplacement de base         */
     int8_t val8;                            /* Valeur sur 8 bits           */
     int16_t val16;                          /* Valeur sur 16 bits          */
     int32_t val32;                          /* Valeur sur 32 bits          */
     bool test;                              /* Bilan de lecture            */
-    vmpa_t address;                         /* Adresse finale visée        */
+    phys_t address;                         /* Adresse finale visée        */
+
+    offset = get_phy_addr(base);
 
     switch (size)
     {
         case MDS_8_BITS_SIGNED:
             test = g_binary_content_read_s8(content, pos, &val8);
-            address = base + val8 * sizeof(uint16_t);
+            address = offset + val8 * sizeof(uint16_t);
             break;
         case MDS_16_BITS_SIGNED:
             test = g_binary_content_read_s16(content, pos, endian, &val16);
-            address = base + val16 * sizeof(uint16_t);
+            address = offset + val16 * sizeof(uint16_t);
             break;
         case MDS_32_BITS_SIGNED:
             test = g_binary_content_read_s32(content, pos, endian, &val32);
-            address = base + val32 * sizeof(uint16_t);
+            address = offset + val32 * sizeof(uint16_t);
             break;
         default:
-            return NULL;
+            test = false;
             break;
     }
 
@@ -201,7 +204,7 @@ GArchOperand *g_dalvik_target_operand_new(const GBinContent *content, vmpa2t *po
         return NULL;
 
     result = g_object_new(G_TYPE_DALVIK_TARGET_OPERAND, NULL);
-    result->immediate = G_IMM_OPERAND(g_imm_operand_new_from_value(MDS_32_BITS/*FIXME*/, (uint32_t)address/* FIXME */));
+    result->immediate = G_IMM_OPERAND(g_imm_operand_new_from_value(MDS_32_BITS, address));
 
     return G_ARCH_OPERAND(result);
 
diff --git a/src/arch/dalvik/operands/target.h b/src/arch/dalvik/operands/target.h
index cb0e9f1..6328546 100644
--- a/src/arch/dalvik/operands/target.h
+++ b/src/arch/dalvik/operands/target.h
@@ -51,7 +51,7 @@ typedef struct _GDalvikTargetOperandClass GDalvikTargetOperandClass;
 GType g_dalvik_target_operand_get_type(void);
 
 /* Crée un opérande visant un instruction Dalvik. */
-GArchOperand *g_dalvik_target_operand_new(const GBinContent *, vmpa2t *, MemoryDataSize, SourceEndian, vmpa_t);
+GArchOperand *g_dalvik_target_operand_new(const GBinContent *, vmpa2t *, MemoryDataSize, SourceEndian, const vmpa2t *);
 
 /* Fournit l'adresse représentée par une opérande Dalvik. */
 const GImmOperand *g_dalvik_target_operand_get_value(const GDalvikTargetOperand *);
diff --git a/src/arch/processor.c b/src/arch/processor.c
index bbe506a..21db869 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -24,6 +24,7 @@
 #include "processor.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 #include <stdlib.h>
 
@@ -304,6 +305,8 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *proc, GProc
     GArchInstruction *result;               /* Instruction à renvoyer      */
     vmpa2t back;                            /* Position sauvegardée        */
 
+    assert(has_phys_addr(pos) && has_virt_addr(pos));
+
     copy_vmpa(&back, pos);
 
     result = G_ARCH_PROCESSOR_GET_CLASS(proc)->disassemble(proc, ctx, content, pos, format);
diff --git a/src/format/dex/class.c b/src/format/dex/class.c
index 1dc3a40..a5181d2 100644
--- a/src/format/dex/class.c
+++ b/src/format/dex/class.c
@@ -39,6 +39,7 @@ struct _GDexClass
     GObject parent;                         /* A laisser en premier        */
 
     class_def_item definition;              /* Définition de la classe     */
+    class_data_item data;                   /* Contenu de la classe        */
 
     GDexMethod **direct_methods;            /* Méthodes propres            */
     size_t dmethods_count;                  /* Quantité de ces méthodes    */
@@ -204,6 +205,7 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
     result = g_object_new(G_TYPE_DEX_CLASS, NULL);
 
     result->definition = *def;
+    result->data = data;
 
     /**
      * On évite ici les méthodes (virtuelles) non définies.
@@ -254,6 +256,44 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : class   = informations chargées à consulter.                 *
+*                                                                             *
+*  Description : Fournit la définition brute d'une classe.                    *
+*                                                                             *
+*  Retour      : Données brutes issues du binaire chargé.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const class_def_item *g_dex_class_get_definition(const GDexClass *class)
+{
+    return &class->definition;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class   = informations chargées à consulter.                 *
+*                                                                             *
+*  Description : Fournit la définition brute des données d'une classe.        *
+*                                                                             *
+*  Retour      : Données brutes issues du binaire chargé.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const class_data_item *g_dex_class_get_data(const GDexClass *class)
+{
+    return &class->data;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class   = informations chargées à consulter.                 *
 *                virtual = précise la nature des méthodes ciblées.            *
 *                                                                             *
 *  Description : Dénombre les méthodes chargées d'un type donné.              *
@@ -309,6 +349,7 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : class = informations chargées à consulter.                   *
+*                format = format permettant d'obtenir une adresse complète.   *
 *                layer = couche de portions à raffiner.                       *
 *                                                                             *
 *  Description : Intègre la méthode en tant que portion de code.              *
@@ -319,15 +360,15 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t
 *                                                                             *
 ******************************************************************************/
 
-void g_dex_class_include_as_portion(const GDexClass *class, GPortionLayer *layer)
+void g_dex_class_include_as_portion(const GDexClass *class, const GDexFormat *format, GPortionLayer *layer)
 {
     size_t i;                               /* Boucle de parcours          */
 
     for (i = 0; i < class->dmethods_count; i++)
-        g_dex_method_include_as_portion(class->direct_methods[i], layer);
+        g_dex_method_include_as_portion(class->direct_methods[i], format, layer);
 
     for (i = 0; i < class->vmethods_count; i++)
-        g_dex_method_include_as_portion(class->virtual_methods[i], layer);
+        g_dex_method_include_as_portion(class->virtual_methods[i], format, layer);
 
 }
 
diff --git a/src/format/dex/class.h b/src/format/dex/class.h
index fb7cada..bee9553 100644
--- a/src/format/dex/class.h
+++ b/src/format/dex/class.h
@@ -57,6 +57,12 @@ GType g_dex_class_get_type(void);
 /* Crée une nouvelle représentation de classe issue de code. */
 GDexClass *g_dex_class_new(GDexFormat *, const class_def_item *);
 
+/* Fournit la définition brute d'une classe. */
+const class_def_item *g_dex_class_get_definition(const GDexClass *);
+
+/* Fournit la définition brute des données d'une classe. */
+const class_data_item *g_dex_class_get_data(const GDexClass *);
+
 /* Dénombre les méthodes chargées d'un type donné. */
 size_t g_dex_class_count_methods(const GDexClass *, bool);
 
@@ -64,7 +70,7 @@ size_t g_dex_class_count_methods(const GDexClass *, bool);
 GDexMethod *g_dex_class_get_method(const GDexClass *, bool, size_t);
 
 /* Intègre la méthode en tant que portion de code. */
-void g_dex_class_include_as_portion(const GDexClass *, GPortionLayer *);
+void g_dex_class_include_as_portion(const GDexClass *, const GDexFormat *, GPortionLayer *);
 
 /* Retrouve si possible la méthode associée à une adresse. */
 GDexMethod *g_dex_class_find_method_by_address(const GDexClass *, vmpa_t);
diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c
index ed2565f..764b6dc 100755
--- a/src/format/dex/dex.c
+++ b/src/format/dex/dex.c
@@ -256,6 +256,11 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent)
     if (!read_dex_header(result, &pos, &result->header))
         goto gdfn_error;
 
+
+
+    /* TODO : vérifier que les *_id ne se chevauchent pas */
+
+
     if (!load_all_dex_types(result))
         goto gdfn_error;
 
@@ -271,14 +276,15 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent)
     if (!load_all_dex_classes(result))
         goto gdfn_error;
 
+    if (!g_binary_format_complete_loading(G_BIN_FORMAT(result)))
+        goto gdfn_error;
+
     return G_BIN_FORMAT(result);
 
  gdfn_error:
 
     g_object_unref(G_OBJECT(result));
 
-    exit(0);
-
     return NULL;
 
 }
@@ -328,7 +334,7 @@ static void g_dex_format_refine_portions(const GDexFormat *format, GPortionLayer
     max = g_dex_format_count_classes(format);
 
     for (i = 0; i < max; i++)
-        g_dex_class_include_as_portion(format->classes[i], layer);
+        g_dex_class_include_as_portion(format->classes[i], format, layer);
 
 }
 
@@ -508,6 +514,32 @@ char *_g_data_type_to_string(const GDataType *type, bool simple)
 
 
 
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                                                                             *
+*  Description : Présente l'en-tête DEX du format chargé.                     *
+*                                                                             *
+*  Retour      : Pointeur vers la description principale.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const dex_header *g_dex_format_get_header(const GDexFormat *format)
+{
+    return &format->header;
+
+}
+
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = description de l'exécutable à consulter.            *
@@ -542,6 +574,8 @@ size_t g_dex_format_count_classes(const GDexFormat *format)
 
 GDexClass *g_dex_format_get_class(const GDexFormat *format, size_t index)
 {
+    /* TODO : ref() */
+
     return format->classes[index];
 
 }
diff --git a/src/format/dex/dex.h b/src/format/dex/dex.h
index 1ff3809..28d2a49 100755
--- a/src/format/dex/dex.h
+++ b/src/format/dex/dex.h
@@ -30,6 +30,7 @@
 #include <sys/types.h>
 
 
+#include "dex_def.h"
 #include "../../core/formats.h"
 
 
@@ -57,6 +58,9 @@ GType g_dex_format_get_type(void);
 /* Prend en charge un nouveau format DEX. */
 GBinFormat *g_dex_format_new(GBinContent *, GExeFormat *);
 
+/* Présente l'en-tête DEX du format chargé. */
+const dex_header *g_dex_format_get_header(const GDexFormat *);
+
 /* Redéfinition : classe issue du code source (instance) */
 typedef struct _GDexClass GDexClass;
 
diff --git a/src/format/dex/method.c b/src/format/dex/method.c
index b74a713..316f094 100644
--- a/src/format/dex/method.c
+++ b/src/format/dex/method.c
@@ -294,6 +294,7 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : method = représentation interne du format DEX à consulter.   *
+*                format = format permettant d'obtenir une adresse complète.   *
 *                layer  = couche de portions à raffiner.                      *
 *                                                                             *
 *  Description : Intègre la méthode en tant que portion de code.              *
@@ -304,16 +305,19 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method)
 *                                                                             *
 ******************************************************************************/
 
-void g_dex_method_include_as_portion(const GDexMethod *method, GPortionLayer *layer)
+void g_dex_method_include_as_portion(const GDexMethod *method, const GDexFormat *format, GPortionLayer *layer)
 {
+    vmpa2t addr;                            /* Emplacement dans le binaire */
     GBinPortion *new;                       /* Nouvelle portion définie    */
     char *desc;                             /* Description d'une portion   */
-    vmpa2t addr;                            /* Emplacement dans le binaire */
 
     /* Si la taille est nulle, on ne fait rien */
     if (method->info.access_flags & ACC_NATIVE)
         return;
 
+    if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), method->offset, &addr))
+        return;
+
     new = g_binary_portion_new(BPC_CODE);
 
     asprintf(&desc, _("Dalvik code"));
@@ -322,7 +326,6 @@ void g_dex_method_include_as_portion(const GDexMethod *method, GPortionLayer *la
 
     free(desc);
 
-    init_vmpa(&addr, method->offset, VMPA_NO_VIRTUAL);
     g_binary_portion_set_values(new, &addr, method->body.insns_size * sizeof(uint16_t));
 
     g_binary_portion_set_rights(new, PAC_READ | PAC_EXEC);
diff --git a/src/format/dex/method.h b/src/format/dex/method.h
index 4d29bac..4ed3960 100644
--- a/src/format/dex/method.h
+++ b/src/format/dex/method.h
@@ -82,7 +82,7 @@ const code_item *g_dex_method_get_dex_body(const GDexMethod *);
 GBinRoutine *g_dex_method_get_routine(const GDexMethod *);
 
 /* Intègre la méthode en tant que portion de code. */
-void g_dex_method_include_as_portion(const GDexMethod *, GPortionLayer *);
+void g_dex_method_include_as_portion(const GDexMethod *, const GDexFormat *, GPortionLayer *);
 
 /* Indique la position de la méthode au sein du binaire. */
 off_t g_dex_method_get_offset(const GDexMethod *);
diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c
index a48e3b3..4bc8bbf 100644
--- a/src/format/elf/elf.c
+++ b/src/format/elf/elf.c
@@ -39,7 +39,6 @@
 #include "strings.h"
 #include "symbols.h"
 #include "../../gui/panels/log.h"
-#include "../../plugins/pglist.h"
 
 
 
@@ -294,15 +293,16 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent)
     }
 
 
-    /* TODO : à bouger dans un épilogue commun */
+    if (!g_binary_format_complete_loading(G_BIN_FORMAT(result)))
+        goto gefn_error;
 
-    handle_binary_format(PGA_FORMAT_LOADER_LAST, G_BIN_FORMAT(result));
+    return G_BIN_FORMAT(result);
 
-    g_binary_format_delete_duplicated_symbols(G_BIN_FORMAT(result));
+ gefn_error:
 
-    /* .... */
+    g_object_unref(G_OBJECT(result));
 
-    return G_BIN_FORMAT(result);
+    return NULL;
 
 }
 
diff --git a/src/format/executable-int.c b/src/format/executable-int.c
index c4b8e6e..0189d76 100644
--- a/src/format/executable-int.c
+++ b/src/format/executable-int.c
@@ -41,7 +41,13 @@
 
 bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *format, phys_t off, vmpa2t *pos)
 {
-    init_vmpa(pos, off, VMPA_NO_VIRTUAL);
+    /**
+     * On ne peut pas initialiser la partie virtuelle à VMPA_NO_VIRTUAL
+     * car les manipulations au niveau des formats (par exemple, cf. la fonction
+     * _g_binary_format_add_symbol()) attendent des définitions complètes.
+     */
+
+    init_vmpa(pos, off, off);
 
     return true;
 
diff --git a/src/format/format-int.h b/src/format/format-int.h
index f97a4ad..84f77c4 100644
--- a/src/format/format-int.h
+++ b/src/format/format-int.h
@@ -78,12 +78,12 @@ struct _GBinFormatClass
 };
 
 
+/* Effectue les ultimes opérations de chargement d'un binaire. */
+bool g_binary_format_complete_loading(GBinFormat *);
+
 /* Définit le contenu binaire à analyser. */
 void g_binary_format_set_content(GBinFormat *, GBinContent *);
 
-/* Supprime les éventuels doublons au sein des symboles. */
-void g_binary_format_delete_duplicated_symbols(GBinFormat *);
-
 
 
 #endif  /* _FORMAT_FORMAT_INT_H */
diff --git a/src/format/format.c b/src/format/format.c
index 8395c6e..387894c 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -52,6 +52,9 @@ static void g_binary_format_init(GBinFormat *);
 /* Retire un symbole de la collection du format binaire. */
 static void _g_binary_format_remove_symbol(GBinFormat *, size_t);
 
+/* Supprime les éventuels doublons au sein des symboles. */
+static void g_binary_format_delete_duplicated_symbols(GBinFormat *);
+
 /* Recherche le symbole associé à une adresse. */
 static bool _g_binary_format_find_symbol(const GBinFormat *, const vmpa2t *, __compar_fn_t, GBinSymbol **);
 
@@ -101,6 +104,30 @@ static void g_binary_format_init(GBinFormat *format)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = instance à traiter.                                 *
+*                                                                             *
+*  Description : Effectue les ultimes opérations de chargement d'un binaire.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_format_complete_loading(GBinFormat *format)
+{
+    handle_binary_format(PGA_FORMAT_LOADER_LAST, format);
+
+    g_binary_format_delete_duplicated_symbols(format);
+
+    return true;
+
+}
+
+
+
 
 /* FIXME : g_rw_lock_clear(&format->syms_lock);*/
 
@@ -431,7 +458,7 @@ void g_binary_format_sort_symbols(GBinFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-void g_binary_format_delete_duplicated_symbols(GBinFormat *format)
+static void g_binary_format_delete_duplicated_symbols(GBinFormat *format)
 {
     size_t i;                               /* Boucle de parcours          */
     const mrange_t *range;                  /* Emplacement à consulter     */
-- 
cgit v0.11.2-87-g4458