From 8dff3daac4d2dc98b90adaecea834fb65db4fb10 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 10 Oct 2016 22:03:23 +0200
Subject: Handled switch and fill-array data pseudo-instructions without
 plugin.

---
 ChangeLog                          |  25 ++++
 src/analysis/contents/restricted.c |  29 +++++
 src/analysis/contents/restricted.h |   3 +
 src/arch/dalvik/context.c          | 227 ++++++++++++++++++++++++++++---------
 src/arch/dalvik/context.h          |  15 ++-
 src/arch/dalvik/operand.c          |   1 -
 src/arch/dalvik/processor.c        |  28 +++--
 src/arch/dalvik/pseudo/fill.c      |  94 ++-------------
 src/arch/dalvik/pseudo/fill.h      |  13 ++-
 src/arch/dalvik/pseudo/switch.c    | 130 ++++++++++++---------
 src/arch/dalvik/pseudo/switch.h    |  16 ++-
 src/arch/vmpa.h                    |   5 +
 12 files changed, 364 insertions(+), 222 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a33e4ab..515d4b9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+16-10-10  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/contents/restricted.c:
+	* src/analysis/contents/restricted.h:
+	Create a pseudo read-only restricted content on demand.
+
+	* src/arch/dalvik/context.c:
+	* src/arch/dalvik/context.h:
+	Store data areas in Dalvik code and provide instructions for them.
+
+	* src/arch/dalvik/operand.c:
+	Remove an unused variable.
+
+	* src/arch/dalvik/processor.c:
+	Update code.
+
+	* src/arch/dalvik/pseudo/fill.c:
+	* src/arch/dalvik/pseudo/fill.h:
+	* src/arch/dalvik/pseudo/switch.c:
+	* src/arch/dalvik/pseudo/switch.h:
+	Handle switch and fill-array data pseudo-instructions without plugin.
+
+	* src/arch/vmpa.h:
+	Provide a suitable function to compare ranges and positions with bsearch().
+
 16-10-09  Cyrille Bagard <nocbos@gmail.com>
 
 	* plugins/readdex/ids.c:
diff --git a/src/analysis/contents/restricted.c b/src/analysis/contents/restricted.c
index 1f996d1..3eaab6d 100644
--- a/src/analysis/contents/restricted.c
+++ b/src/analysis/contents/restricted.c
@@ -252,6 +252,35 @@ GBinContent *g_restricted_content_new(GBinContent *content, const mrange_t *rang
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : content = contenu binaire où puiser les données à fournir.   *
+*                range   = espace de restrictions pour les accès.             *
+*                                                                             *
+*  Description : Charge en mémoire le contenu d'un contenu restreint.         *
+*                                                                             *
+*  Retour      : Représentation de contenu à manipuler ou NULL en cas d'échec.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinContent *g_restricted_content_new_ro(const GBinContent *content, const mrange_t *range)
+{
+    GRestrictedContent *result;              /* Structure à retourner      */
+
+    result = g_object_new(G_TYPE_RESTRICTED_CONTENT, NULL);
+
+    result->internal = (GBinContent *)content;
+    g_object_ref(G_OBJECT(result->internal));
+
+    copy_mrange(&result->range, range);
+
+    return G_BIN_CONTENT(result);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : content  = contenu binaire à venir lire.                     *
 *                checksum = empreinte de zone mémoire à compléter.            *
 *                                                                             *
diff --git a/src/analysis/contents/restricted.h b/src/analysis/contents/restricted.h
index 3cf5d60..a96e403 100644
--- a/src/analysis/contents/restricted.h
+++ b/src/analysis/contents/restricted.h
@@ -53,6 +53,9 @@ GType g_restricted_content_get_type(void);
 /* Charge en mémoire le contenu d'un contenu restreint. */
 GBinContent *g_restricted_content_new(GBinContent *, const mrange_t *);
 
+/* Charge en mémoire le contenu d'un contenu restreint. */
+GBinContent *g_restricted_content_new_ro(const GBinContent *, const mrange_t *);
+
 
 
 #endif  /* _ANALYSIS_CONTENTS_RESTRICTED_H */
diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c
index 0eb8b48..b093345 100644
--- a/src/arch/dalvik/context.c
+++ b/src/arch/dalvik/context.c
@@ -25,31 +25,39 @@
 
 
 #include <malloc.h>
+#include <stdlib.h>
 #include <string.h>
 
 
 #include "operands/register.h"
 #include "../context-int.h"
+#include "../raw.h"
+#include "../../analysis/contents/restricted.h"
+#include "../../common/sort.h"
 #include "../../decomp/context-int.h"
 #include "../../decomp/expr/pseudo.h"
 #include "../../format/dex/dex-int.h"
 
 
 
-/* Mémorisation d'un saut dans le code */
-typedef struct _skipped_dalvik_area skipped_dalvik_area;
+/* ------------------------ MANIPULATION GLOBALE DU CONTEXTE ------------------------ */
 
 
+/* Mémorisation de données brutes dans le code */
+typedef struct _raw_data_area
+{
+    mrange_t range;                         /* Couverture à laisser en 1er */
 
-/* ------------------------ MANIPULATION GLOBALE DU CONTEXTE ------------------------ */
+    phys_t item_len;                        /* Taille de chaque élément    */
 
+} raw_data_area;
 
 /* Définition d'un contexte pour processeur Dalkvik (instance) */
 struct _GDalvikContext
 {
     GProcContext parent;                    /* A laisser en premier        */
 
-    skipped_dalvik_area *skip;              /* Liste de Zones à écarter    */
+    raw_data_area *data;                    /* Liste de zones brutes       */
     size_t count;                           /* Taille de cette liste       */
 
 };
@@ -69,18 +77,11 @@ static void g_dalvik_context_class_init(GDalvikContextClass *);
 /* Initialise une instance de contexte de processeur Dalkvik. */
 static void g_dalvik_context_init(GDalvikContext *);
 
+/* Supprime toutes les références externes. */
+static void g_dalvik_context_dispose(GDalvikContext *);
 
-
-/* ------------------------- MEMORISATION DES SAUTS DE CODE ------------------------- */
-
-
-/* Mémorisation d'un saut dans le code */
-struct _skipped_dalvik_area
-{
-    vmpa_t start;                           /* Début de la zone concernée  */
-    vmpa_t end;                             /* Fin de la zone concernée    */
-
-};
+/* Procède à la libération totale de la mémoire. */
+static void g_dalvik_context_finalize(GDalvikContext *);
 
 
 
@@ -154,6 +155,12 @@ G_DEFINE_TYPE(GDalvikContext, g_dalvik_context, G_TYPE_PROC_CONTEXT);
 
 static void g_dalvik_context_class_init(GDalvikContextClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_context_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_dalvik_context_finalize;
 
 }
 
@@ -178,6 +185,47 @@ static void g_dalvik_context_init(GDalvikContext *ctx)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : ctx = instance d'objet GLib à traiter.                       *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dalvik_context_dispose(GDalvikContext *ctx)
+{
+    G_OBJECT_CLASS(g_dalvik_context_parent_class)->dispose(G_OBJECT(ctx));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx = instance d'objet GLib à traiter.                       *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dalvik_context_finalize(GDalvikContext *ctx)
+{
+    if (ctx->data != NULL)
+        free(ctx->data);
+
+    G_OBJECT_CLASS(g_dalvik_context_parent_class)->finalize(G_OBJECT(ctx));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Crée un contexte pour l'exécution du processeur Dalvik.      *
@@ -199,82 +247,155 @@ GDalvikContext *g_dalvik_context_new(void)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx    = contexte de désassemblage Dalvik à actualiser.      *
+*                start  = début de la zone à considérer.                      *
+*                length = taille de la zone couverte.                         *
+*                                                                             *
+*  Description : Mémorise une zone comme étant des données de branchements.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-/* ---------------------------------------------------------------------------------- */
-/*                           MEMORISATION DES SAUTS DE CODE                           */
-/* ---------------------------------------------------------------------------------- */
+bool g_dalvik_context_register_switch_data(GDalvikContext *ctx, const vmpa2t *start, phys_t length)
+{
+    bool result;                            /* Bilan à retourner           */
+    raw_data_area new;                      /* Nouvel élément à insérer    */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    /* Vérification quant aux chevauchements */
+
+    init_mrange(&new.range, start, length);
+
+    for (i = 0; i < ctx->count && result; i++)
+        result = !mrange_intersects_mrange(&ctx->data[i].range, &new.range);
+
+    /* Insertion d'une nouvelle zone */
+
+    if (result)
+    {
+        new.item_len = 4;
+
+        ctx->data = qinsert(ctx->data, &ctx->count, sizeof(raw_data_area),
+                            (__compar_fn_t)cmp_mrange_with_vmpa_swapped, &new);
+
+    }
+
+    return result;
+
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : ctx   = instance à mettre à jour.                            *
-*                start = début de la zone à écarter du traitement.            *
-*                end   = fin de la zone à écarter du traitement.              *
+*  Paramètres  : ctx    = contexte de désassemblage Dalvik à actualiser.      *
+*                start  = début de la zone à considérer.                      *
+*                width  = taille de chacun des éléments.                      *
+*                length = taille de la zone couverte.                         *
 *                                                                             *
-*  Description : Mémorise une nouvelle zone de code comme étant des données.  *
+*  Description : Mémorise une zone comme étant des données d'un tableau.      *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_dalvik_context_skip_new_area(GDalvikContext *ctx, vmpa_t start, vmpa_t end)
+bool g_dalvik_context_register_array_data(GDalvikContext *ctx, const vmpa2t *start, uint16_t width, phys_t length)
 {
-    ctx->skip = (skipped_dalvik_area *)realloc(ctx->skip,
-                                               ++ctx->count * sizeof(skipped_dalvik_area));
+    bool result;                            /* Bilan à retourner           */
+    raw_data_area new;                      /* Nouvel élément à insérer    */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = true;
+
+    /* Vérification quant aux chevauchements */
+
+    init_mrange(&new.range, start, length);
+
+    for (i = 0; i < ctx->count && result; i++)
+        result = !mrange_intersects_mrange(&ctx->data[i].range, &new.range);
+
+    /* Insertion d'une nouvelle zone */
+
+    if (result)
+    {
+        new.item_len = width;
+
+        ctx->data = qinsert(ctx->data, &ctx->count, sizeof(raw_data_area),
+                            (__compar_fn_t)cmp_mrange_with_vmpa_swapped, &new);
+
+    }
 
-    ctx->skip[ctx->count - 1].start = start;
-    ctx->skip[ctx->count - 1].end = end;
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : ctx  = instance à consulter.                                 *
-*                addr = adresse à mainupuler.                                 *
+*  Paramètres  : ctx     = contexte de désassemblage Dalvik à consulter.      *
+*                content = flux de données à analyser.                        *
+*                pos     = position courante dans ce flux. [OUT]              *
 *                                                                             *
-*  Description : Indique si l'adresse est considérée comme zone de données.   *
+*  Description : Place une donnée en tant qu'instruction si besoin est.       *
 *                                                                             *
-*  Retour      : true si l'adresse est considérée comme zone de données.      *
+*  Retour      : Instruction mise en place ou NULL en cas d'échec.            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_dalvik_context_have_to_skip(GDalvikContext *ctx, vmpa_t addr)
+GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos)
 {
-    bool result;                            /* verdict à retourner         */
-    size_t i;                               /* Boucle de parcours          */
+    GArchInstruction *result;               /* Instruction à retourner     */
+    raw_data_area *found;                   /* Zone de couverture trouvée  */
+    GBinContent *restricted;                /* Zone de lecture effective   */
 
-    result = false;
+    result = NULL;
 
-    for (i = 0; i < ctx->count && !result; i++)
-        if (ctx->skip[i].start <= addr && addr < ctx->skip[i].end)
-        {
-            result = true;
-            ctx->skip[i].start += sizeof(uint16_t);
+    found = bsearch(pos, ctx->data, ctx->count, sizeof(raw_data_area),
+                    (__compar_fn_t)cmp_mrange_with_vmpa_swapped);
 
-            /* BUG_ON(ctx->skip[i].start > ctx->skip[i].end) */
+    if (found)
+    {
+        restricted = g_restricted_content_new_ro(content, &found->range);
 
-            if (ctx->skip[i].start >= ctx->skip[i].end)
-            {
-                if (i <= (ctx->count - 1))
-                    memmove(&ctx->skip[i], &ctx->skip[i + 1], ctx->count - i - 1);
+        switch (found->item_len)
+        {
+            case 1:
+                result = g_raw_instruction_new_array(restricted, MDS_8_BITS_UNSIGNED, 1, pos, SRE_LITTLE);
+                break;
 
-                if (--ctx->count == 0)
-                    ctx->skip = NULL;
-                else
-                    ctx->skip = (skipped_dalvik_area *)realloc(ctx->skip,
-                                                               ++ctx->count * sizeof(skipped_dalvik_area));
+            case 2:
+                result = g_raw_instruction_new_array(restricted, MDS_16_BITS_UNSIGNED, 1, pos, SRE_LITTLE);
+                break;
 
-            }
+            case 4:
+                result = g_raw_instruction_new_array(restricted, MDS_32_BITS_UNSIGNED, 1, pos, SRE_LITTLE);
+                break;
+
+            case 8:
+                result = g_raw_instruction_new_array(restricted, MDS_64_BITS_UNSIGNED, 1, pos, SRE_LITTLE);
+                break;
 
-            break;
+            default:
+                result = g_raw_instruction_new_array(restricted, MDS_8_BITS_UNSIGNED,
+                                                     found->item_len, pos, SRE_LITTLE);
+                break;
 
         }
 
+        g_object_unref(G_OBJECT(restricted));
+
+    }
+
     return result;
 
 }
diff --git a/src/arch/dalvik/context.h b/src/arch/dalvik/context.h
index 711849d..09fc256 100644
--- a/src/arch/dalvik/context.h
+++ b/src/arch/dalvik/context.h
@@ -29,6 +29,7 @@
 #include <stdbool.h>
 
 
+#include "instruction.h"
 #include "../archbase.h"
 #include "../../decomp/context.h"
 
@@ -58,16 +59,14 @@ GType g_dalvik_context_get_type(void);
 /* Crée un contexte pour l'exécution du processeur Dalvik. */
 GDalvikContext *g_dalvik_context_new(void);
 
+/* Mémorise une zone comme étant des données de branchements. */
+bool g_dalvik_context_register_switch_data(GDalvikContext *ctx, const vmpa2t *start, phys_t length);
 
+/* Mémorise une zone comme étant des données d'un tableau. */
+bool g_dalvik_context_register_array_data(GDalvikContext *, const vmpa2t *, uint16_t, phys_t);
 
-/* ------------------------- MEMORISATION DES SAUTS DE CODE ------------------------- */
-
-
-/* Mémorise une nouvelle zone de code comme étant des données. */
-void g_dalvik_context_skip_new_area(GDalvikContext *, vmpa_t, vmpa_t);
-
-/* Indique si l'adresse est considérée comme zone de données. */
-bool g_dalvik_context_have_to_skip(GDalvikContext *, vmpa_t);
+/* Place une donnée en tant qu'instruction si besoin est. */
+GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *, const GBinContent *, vmpa2t *);
 
 
 
diff --git a/src/arch/dalvik/operand.c b/src/arch/dalvik/operand.c
index f0e8c1e..b6ee466 100644
--- a/src/arch/dalvik/operand.c
+++ b/src/arch/dalvik/operand.c
@@ -617,7 +617,6 @@ bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBi
 #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         */
diff --git a/src/arch/dalvik/processor.c b/src/arch/dalvik/processor.c
index ab64db7..9003d72 100644
--- a/src/arch/dalvik/processor.c
+++ b/src/arch/dalvik/processor.c
@@ -485,23 +485,31 @@ static GArchInstruction *g_dalvik_processor_disassemble(const GArchProcessor *pr
 
     };
 
+    /* Données brutes associées à une instruction ? */
+
+    result = g_dalvik_context_get_raw_data(ctx, content, pos);
+
+    if (result != NULL) goto gdpd_done;
+
+    /* Pseudo-instruction... */
+
     if (!g_binary_content_read_u8(content, pos, &raw8))
         return NULL;
 
-    /* Pseudo-instruction... */
     result = g_dalvik_processor_disassemble_pseudo(proc, ctx, content, pos, raw8);
 
+    if (result != NULL) goto gdpd_done;
+
     /* ... ou instruction classique */
-    if (result == NULL)
-    {
-        assert(raw8 < DOP_COUNT);
 
-        id = (DalvikOpcodes)raw8;
+    assert(raw8 < DOP_COUNT);
 
-        if (decodings[id] != NULL)
-            result = decodings[id](proc, G_PROC_CONTEXT(ctx), content, pos, format);
+    id = (DalvikOpcodes)raw8;
 
-    }
+    if (decodings[id] != NULL)
+        result = decodings[id](proc, G_PROC_CONTEXT(ctx), content, pos, format);
+
+ gdpd_done:
 
     return result;
 
@@ -549,11 +557,11 @@ static GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProces
     {
         case DPO_PACKED_SWITCH:
         case DPO_SPARSE_SWITCH:
-            result = g_dalvik_switch_instr_new(ident, content, pos);
+            result = g_dalvik_switch_instr_new(ident, ctx, content, pos);
             break;
 
         case DPO_FILL_ARRAY_DATA:
-            result = g_dalvik_fill_instr_new(ident, content, pos);
+            result = g_dalvik_fill_instr_new(ident, ctx, content, pos);
             break;
 
         default:
diff --git a/src/arch/dalvik/pseudo/fill.c b/src/arch/dalvik/pseudo/fill.c
index e1e1822..69452b5 100644
--- a/src/arch/dalvik/pseudo/fill.c
+++ b/src/arch/dalvik/pseudo/fill.c
@@ -37,7 +37,7 @@ struct _GDalvikFillInstr
 {
     GDalvikInstruction parent;              /* A laisser en premier        */
 
-    uint16_t array_width;                   /* Taille des éléments         */
+    uint16_t item_width;                    /* Taille des éléments         */
     uint32_t array_size;                    /* Taille du tableau           */
 
 };
@@ -63,9 +63,6 @@ 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(GDalvikFillInstr *, GCodeBuffer *, MemoryDataSize, const bin_t *, AsmSyntax);
-
 
 
 /* Indique le type défini pour une pseudo-instruction Dalvik de remplissage. */
@@ -87,17 +84,12 @@ 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;
-
 }
 
 
@@ -115,7 +107,7 @@ static void g_dalvik_fill_instr_class_init(GDalvikFillInstrClass *klass)
 
 static void g_dalvik_fill_instr_init(GDalvikFillInstr *instr)
 {
-    G_DALVIK_INSTRUCTION(instr)->keyword = "##fill-array##";
+    G_DALVIK_INSTRUCTION(instr)->keyword = "array-data";
 
 }
 
@@ -161,6 +153,7 @@ static void g_dalvik_fill_instr_finalize(GDalvikFillInstr *instr)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : ident   = identifiant de l'instruction déjà lu.              *
+*                ctx     = contexte lié à l'exécution du processeur.          *
 *                content = flux de données à analyser.                        *
 *                pos     = position courante dans ce flux. [OUT]              *
 *                                                                             *
@@ -172,7 +165,7 @@ static void g_dalvik_fill_instr_finalize(GDalvikFillInstr *instr)
 *                                                                             *
 ******************************************************************************/
 
-GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, const GBinContent *content, vmpa2t *pos)
+GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos)
 {
     GDalvikFillInstr *result;               /* Structure à retourner       */
     phys_t consumed;                        /* Données consommées          */
@@ -183,19 +176,17 @@ GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, const GBinContent *con
 
     G_DALVIK_INSTRUCTION(result)->ptype = ident;
 
-    if (!g_binary_content_read_u16(content, pos, SRE_LITTLE, &result->array_width))
+    if (!g_binary_content_read_u16(content, pos, SRE_LITTLE, &result->item_width))
         goto gdfin_bad;
 
     if (!g_binary_content_read_u32(content, pos, SRE_LITTLE, &result->array_size))
         goto gdfin_bad;
 
-    consumed = result->array_width * result->array_size;
+    consumed = result->item_width * result->array_size;
 
-    if (!g_binary_content_seek(content, pos, consumed))
+    if (!g_dalvik_context_register_array_data(ctx, pos, result->item_width, consumed))
         goto gdfin_bad;
 
-    g_arch_instruction_set_displayed_max_length(G_ARCH_INSTRUCTION(result), 8);
-
     return G_ARCH_INSTRUCTION(result);
 
  gdfin_bad:
@@ -205,74 +196,3 @@ GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, const GBinContent *con
     return NULL;
 
 }
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : instr  = instruction d'assemblage à représenter.             *
-*                buffer = espace où placer ledit contenu.                     *
-*                syntax = type de représentation demandée.                    *
-*                                                                             *
-*  Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée.  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dalvik_fill_instr_print(GDalvikFillInstr *instr, GCodeBuffer *buffer, MemoryDataSize msize, const bin_t *content, AsmSyntax syntax)
-{
-    GArchInstruction *base;                 /* Version basique de l'objet  */
-    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          */
-    const char *key;                        /* Mot clef principal          */
-    size_t klen;                            /* Taille de ce mot clef       */
-
-    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_PHYSICAL, address, len, RTT_RAW);
-
-    /* TODO ... */
-
-    /* Code brut */
-
-    bin_code = (char *)calloc(3 * 3 + 3, sizeof(char));
-
-    for (i = 0; i < 3; i++)
-    {
-        if ((i + 1) < 3)
-            snprintf(&bin_code[i * (2 + 1)], 4, "%02hhx ", content[base->offset + i]);
-        else
-            snprintf(&bin_code[i * (2 + 1)], 6, "%02hhx...", content[base->offset + i]);
-    }
-
-    g_buffer_line_insert_text(line, BLC_BINARY,
-                              bin_code, 3 * 3 + 2, RTT_RAW_CODE);
-
-    free(bin_code);
-
-#endif
-
-    /* Instruction proprement dite */
-
-    key = "<fill-array>";
-    klen = strlen(key);
-
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION);
-
-}
diff --git a/src/arch/dalvik/pseudo/fill.h b/src/arch/dalvik/pseudo/fill.h
index aeb04b8..9c5a852 100644
--- a/src/arch/dalvik/pseudo/fill.h
+++ b/src/arch/dalvik/pseudo/fill.h
@@ -25,6 +25,7 @@
 #define _ARCH_DALVIK_PSEUDO_FILL_H
 
 
+#include "../context.h"
 #include "../instruction.h"
 #include "../processor.h"
 
@@ -33,10 +34,12 @@
 
 
 
-#define G_TYPE_DALVIK_FILL_INSTR                 g_dalvik_fill_instr_get_type()
-#define G_DALVIK_FILL_INSTR(obj)                 (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_fill_instr_get_type(), GDalvikFillInstr))
-#define G_IS_DALVIK_FILL_INSTR(obj)              (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_fill_instr_get_type()))
-#define G_DALVIK_FILL_INSTR_GET_IFACE(inst)      (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_fill_instr_get_type(), GDalvikFillInstrIface))
+#define G_TYPE_DALVIK_FILL_INSTR        g_dalvik_fill_instr_get_type()
+#define G_DALVIK_FILL_INSTR(obj)        (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DALVIK_FILL_INSTR, GDalvikFillInstr))
+#define G_IS_DALVIK_FILL_INSTR(obj)     (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DALVIK_FILL_INSTR))
+#define G_DALVIK_FILL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_FILL, GGDalvikFillClass))
+#define G_IS_DALVIK_FILL_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_FILL))
+#define G_DALVIK_FILL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_FILL, GGDalvikFillClass))
 
 
 /* Définition générique d'une instruction d'architecture (instance) */
@@ -50,7 +53,7 @@ typedef struct _GDalvikFillInstrClass GDalvikFillInstrClass;
 GType g_dalvik_fill_instr_get_type(void);
 
 /* Crée une pesudo-instruction Dalvik de remplissage. */
-GArchInstruction *g_dalvik_fill_instr_new(uint16_t, const GBinContent *, vmpa2t *);
+GArchInstruction *g_dalvik_fill_instr_new(uint16_t, GDalvikContext *, const GBinContent *, vmpa2t *);
 
 
 
diff --git a/src/arch/dalvik/pseudo/switch.c b/src/arch/dalvik/pseudo/switch.c
index c1d0982..fd7e442 100644
--- a/src/arch/dalvik/pseudo/switch.c
+++ b/src/arch/dalvik/pseudo/switch.c
@@ -25,7 +25,7 @@
 
 
 #include <assert.h>
-#include <string.h> 
+#include <malloc.h>
 
 
 #include "../instruction-int.h"
@@ -39,6 +39,9 @@ struct _GDalvikSwitchInstr
 
     uint16_t switch_size;                   /* Taille du switch considéré  */
 
+    uint32_t *keys;                         /* Table de clefs              */
+    uint32_t *targets;                      /* Table des sauts relatifs    */
+
 };
 
 /* Définition générique d'une instruction d'architecture Dalvik (classe) */
@@ -62,8 +65,8 @@ 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(GDalvikSwitchInstr *, GCodeBuffer *, MemoryDataSize, const bin_t *, AsmSyntax);
+/* Lit toutes les valeurs associés aux branchements. */
+static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *, const GBinContent *, const vmpa2t *);
 
 
 
@@ -86,17 +89,12 @@ 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;
-
 }
 
 
@@ -114,7 +112,7 @@ static void g_dalvik_switch_instr_class_init(GDalvikSwitchInstrClass *klass)
 
 static void g_dalvik_switch_instr_init(GDalvikSwitchInstr *instr)
 {
-    G_DALVIK_INSTRUCTION(instr)->keyword = "##switch##";
+    G_DALVIK_INSTRUCTION(instr)->keyword = "switch-data";
 
 }
 
@@ -152,6 +150,12 @@ static void g_dalvik_switch_instr_dispose(GDalvikSwitchInstr *instr)
 
 static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *instr)
 {
+    if (instr->keys != NULL)
+        free(instr->keys);
+
+    if (instr->targets != NULL)
+        free(instr->targets);
+
     G_OBJECT_CLASS(g_dalvik_switch_instr_parent_class)->finalize(G_OBJECT(instr));
 
 }
@@ -160,6 +164,7 @@ static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *instr)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : ident   = identifiant de l'instruction déjà lu.              *
+*                ctx     = contexte lié à l'exécution du processeur.          *
 *                content = flux de données à analyser.                        *
 *                pos     = position courante dans ce flux. [OUT]              *
 *                                                                             *
@@ -171,7 +176,7 @@ static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *instr)
 *                                                                             *
 ******************************************************************************/
 
-GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, const GBinContent *content, vmpa2t *pos)
+GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos)
 {
     GDalvikSwitchInstr *result;             /* Structure à retourner       */
     phys_t consumed;                        /* Données consommées          */
@@ -185,16 +190,17 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, const GBinContent *c
     if (!g_binary_content_read_u16(content, pos, SRE_LITTLE, &result->switch_size))
         goto gdsin_bad;
 
+    if (!g_dalvik_switch_decode_data(result, content, pos))
+        goto gdsin_bad;
+
     if (ident != DPO_PACKED_SWITCH)
         consumed = (1 + result->switch_size) * sizeof(uint32_t);
     else
         consumed = (2 * result->switch_size) * sizeof(uint32_t);
 
-    if (!g_binary_content_seek(content, pos, consumed))
+    if (!g_dalvik_context_register_switch_data(ctx, pos, consumed))
         goto gdsin_bad;
 
-    g_arch_instruction_set_displayed_max_length(G_ARCH_INSTRUCTION(result), 4);
-
     return G_ARCH_INSTRUCTION(result);
 
  gdsin_bad:
@@ -208,70 +214,88 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, const GBinContent *c
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : instr  = instruction d'assemblage à représenter.             *
-*                buffer = espace où placer ledit contenu.                     *
-*                syntax = type de représentation demandée.                    *
+*  Paramètres  : instr   = instruction d'assemblage à compléter.              *
+*                content = flux de données à analyser.                        *
+*                pos     = position de lecture courante dans ce flux.         *
 *                                                                             *
-*  Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée.  *
+*  Description : Lit toutes les valeurs associés aux branchements.            *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_dalvik_switch_instr_print(GDalvikSwitchInstr *instr, GCodeBuffer *buffer, MemoryDataSize msize, const bin_t *content, AsmSyntax syntax)
+static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinContent *content, const vmpa2t *pos)
 {
-    GArchInstruction *base;                 /* Version basique de l'objet  */
-    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          */
-    const char *key;                        /* Mot clef principal          */
-    size_t klen;                            /* Taille de ce mot clef       */
+    vmpa2t iter;                            /* Position modifiable         */
+    uint32_t first_key;                     /* Première clef               */
+    uint16_t i;                             /* Boucle de parcours          */
 
-    base = G_ARCH_INSTRUCTION(instr);
+    instr->keys = (uint32_t *)calloc(instr->switch_size, sizeof(uint32_t));
+    instr->targets = (uint32_t *)calloc(instr->switch_size, sizeof(uint32_t));
 
-    line = NULL;
+    copy_vmpa(&iter, pos);
 
-    //line = g_code_buffer_prepare_new_line(buffer, &range);
-
-#if 0
-    line = g_code_buffer_append_new_line(buffer, base->address);
+    if (G_DALVIK_INSTRUCTION(instr)->ptype == DPO_PACKED_SWITCH)
+    {
+        if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &first_key))
+            goto gdsdd_bad;
 
-    /* Adresse virtuelle ou physique */
+        for (i = 0; i < instr->switch_size; i++)
+        {
+            instr->keys[i] = first_key + i;
 
-    len = vmpa_to_string(base->address, msize, address);
+            if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->targets[i]))
+                goto gdsdd_bad;
 
-    g_buffer_line_insert_text(line, BLC_PHYSICAL, address, len, RTT_RAW);
+        }
 
-    /* TODO ... */
+    }
 
-    /* Code brut */
+    else
+    {
+        for (i = 0; i < instr->switch_size; i++)
+            if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->keys[i]))
+                goto gdsdd_bad;
 
-    bin_code = (char *)calloc(3 * 3 + 3, sizeof(char));
+        for (i = 0; i < instr->switch_size; i++)
+            if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->targets[i]))
+                goto gdsdd_bad;
 
-    for (i = 0; i < 3; i++)
-    {
-        if ((i + 1) < 3)
-            snprintf(&bin_code[i * (2 + 1)], 4, "%02hhx ", content[base->offset + i]);
-        else
-            snprintf(&bin_code[i * (2 + 1)], 6, "%02hhx...", content[base->offset + i]);
     }
 
-    g_buffer_line_insert_text(line, BLC_BINARY,
-                              bin_code, 3 * 3 + 2, RTT_RAW_CODE);
+    return true;
+
+ gdsdd_bad:
 
-    free(bin_code);
+    return false;
+
+}
 
-#endif
 
-    /* Instruction proprement dite */
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction d'assemblage à compléter.              *
+*                keys    = tableau renseignant les conditions de saut. [OUT]  *
+*                targets = tableau renseignant les sauts relatifs. [OUT]      *
+*                                                                             *
+*  Description : Fournit les données associées à un branchement Dalvik.       *
+*                                                                             *
+*  Retour      : Taille des tableaux renseignés.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *instr, const uint32_t **keys, const uint32_t **targets)
+{
+    if (keys != NULL)
+        *keys = instr->keys;
 
-    key = "<fill-array>";
-    klen = strlen(key);
+    if (targets != NULL)
+        *targets = instr->targets;
 
-    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION);
+    return instr->switch_size;
 
 }
diff --git a/src/arch/dalvik/pseudo/switch.h b/src/arch/dalvik/pseudo/switch.h
index 02d61d0..ae52758 100644
--- a/src/arch/dalvik/pseudo/switch.h
+++ b/src/arch/dalvik/pseudo/switch.h
@@ -25,6 +25,7 @@
 #define _ARCH_DALVIK_PSEUDO_SWITCH_H
 
 
+#include "../context.h"
 #include "../instruction.h"
 #include "../processor.h"
 
@@ -33,10 +34,12 @@
 
 
 
-#define G_TYPE_DALVIK_SWITCH_INSTR                 g_dalvik_switch_instr_get_type()
-#define G_DALVIK_SWITCH_INSTR(obj)                 (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_switch_instr_get_type(), GDalvikSwitchInstr))
-#define G_IS_DALVIK_SWITCH_INSTR(obj)              (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_switch_instr_get_type()))
-#define G_DALVIK_SWITCH_INSTR_GET_IFACE(inst)      (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_switch_instr_get_type(), GDalvikSwitchInstrIface))
+#define G_TYPE_DALVIK_SWITCH_INSTR      g_dalvik_switch_instr_get_type()
+#define G_DALVIK_SWITCH_INSTR(obj)      (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DALVIK_SWITCH_INSTR, GDalvikSwitchInstr))
+#define G_IS_DALVIK_SWITCH_INSTR(obj)   (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DALVIK_SWITCH_INSTR))
+#define G_DALVIK_SWITCH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_SWITCH, GGDalvikSwitchClass))
+#define G_IS_DALVIK_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_SWITCH))
+#define G_DALVIK_SWITCH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_SWITCH, GGDalvikSwitchClass))
 
 
 /* Définition générique d'une instruction d'architecture (instance) */
@@ -50,7 +53,10 @@ typedef struct _GDalvikSwitchInstrClass GDalvikSwitchInstrClass;
 GType g_dalvik_switch_instr_get_type(void);
 
 /* Crée une pesudo-instruction Dalvik de branchement. */
-GArchInstruction *g_dalvik_switch_instr_new(uint16_t, const GBinContent *, vmpa2t *);
+GArchInstruction *g_dalvik_switch_instr_new(uint16_t, GDalvikContext *, const GBinContent *, vmpa2t *);
+
+/* Fournit les données associées à un branchement Dalvik. */
+uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *, const uint32_t **, const uint32_t **);
 
 
 
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index f20cff0..753802f 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -193,6 +193,11 @@ int cmp_mrange(const mrange_t *, const mrange_t *);
 /* Compare une couverture mémoire avec une localisation simple. */
 int cmp_mrange_with_vmpa(const mrange_t *, const vmpa2t *);
 
+static inline int cmp_mrange_with_vmpa_swapped(const vmpa2t *k, const mrange_t *r)
+{
+    return cmp_mrange_with_vmpa(r, k);
+}
+
 /* Indique si une zone en contient une autre ou non. */
 bool mrange_contains_mrange(const mrange_t *, const mrange_t *);
 
-- 
cgit v0.11.2-87-g4458