From 7cc35e17f3af39ad9a23bff93c42d86f73dd1001 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 9 Jan 2013 20:36:26 +0000
Subject: Restored some parts of the decompilation process using the new basic
 blocks.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@320 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                        |  29 ++++
 src/analysis/block-int.h         |   4 +
 src/analysis/block.c             |  20 +++
 src/analysis/block.h             |   3 +
 src/analysis/blocks/flow.c       |  62 +++++++-
 src/analysis/blocks/flow.h       |   3 +
 src/analysis/blocks/virtual.c    |  56 +++++++
 src/analysis/blocks/virtual.h    |   3 +
 src/analysis/decomp/decompiler.c |  11 +-
 src/analysis/decomp/il.c         | 326 +++++++++++++++++++++++++++++++++++++++
 src/analysis/decomp/il.h         |  14 +-
 src/analysis/variable.c          |   7 +-
 src/arch/dalvik/instruction.c    |  12 +-
 src/arch/instruction.c           |  29 ++++
 src/arch/instruction.h           |   3 +
 src/decomp/context.c             |   1 -
 16 files changed, 567 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 13973d7..bc68fcf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+13-01-09  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/block.c:
+	* src/analysis/block.h:
+	* src/analysis/block-int.h:
+	* src/analysis/blocks/flow.c:
+	* src/analysis/blocks/flow.h:
+	* src/analysis/blocks/virtual.c:
+	* src/analysis/blocks/virtual.h:
+	Find a basic block using an address.
+
+	* src/analysis/decomp/decompiler.c:
+	* src/analysis/decomp/il.c:
+	* src/analysis/decomp/il.h:
+	Restore some parts of the decompilation process using the new basic blocks.
+
+	* src/analysis/variable.c:
+	Set a pretty output by removing the type in the result (need to be fixed!).
+
+	* src/arch/dalvik/instruction.c:
+	Disable buggy decompilation of some opcodes.
+
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	Provide a fast way to get a given destination if it exists.
+
+	* src/decomp/context.c:
+	Remove an useless header.
+
 13-01-06  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/gtkext/gtkbufferview.c:
diff --git a/src/analysis/block-int.h b/src/analysis/block-int.h
index ba84fcb..355c1ee 100644
--- a/src/analysis/block-int.h
+++ b/src/analysis/block-int.h
@@ -29,6 +29,9 @@
 
 
 
+/* Recherche le bloc contenant une adresse donnée. */
+typedef GInstrBlock * (* find_by_addr_fc) (const GInstrBlock *, vmpa_t);
+
 /* Parcours tous les blocs d'instructions dans un ordre donné. */
 typedef bool (* visit_all_blocks_fc) (GInstrBlock *, instr_block_visitor_cb, void *);
 
@@ -45,6 +48,7 @@ struct _GInstrBlock
 {
     GObject parent;                         /* A laisser en premier        */
 
+    find_by_addr_fc find_by_addr;           /* Recherche par adresse       */
     visit_all_blocks_fc visit_blocks;       /* Visite des différents blocs */
     list_all_blocks_fc list_blocks;         /* Liste de tous les blocs     */
     list_regs_accesses_fc list_regs;        /* Liste des accès registres   */
diff --git a/src/analysis/block.c b/src/analysis/block.c
index 3b3eaf3..62b56ab 100644
--- a/src/analysis/block.c
+++ b/src/analysis/block.c
@@ -157,6 +157,26 @@ static void g_instr_block_finalize(GInstrBlock *block)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : block = bloc de départ des recherches.                       *
+*                addr  = ensemble de blocs à parcourir.                       *
+*                                                                             *
+*  Description : Recherche le bloc contenant une adresse donnée.              *
+*                                                                             *
+*  Retour      : bloc basique trouvé ou NULL en cas d'échec.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GInstrBlock *g_instr_block_find_by_addr(const GInstrBlock *block, vmpa_t addr)
+{
+    return block->find_by_addr(block, addr);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : block    = bloc d'instructions démarrant la visite.          *
 *                callback = ensemble de blocs à parcourir.                    *
 *                data     = donnée utilisateur à associer au parcours.        *
diff --git a/src/analysis/block.h b/src/analysis/block.h
index a85e4aa..1574dc1 100644
--- a/src/analysis/block.h
+++ b/src/analysis/block.h
@@ -95,6 +95,9 @@ typedef bool (* instr_block_visitor_cb) (GInstrBlock *, BlockVisitOrder, void *)
 /* Indique le type défini pour un bloc d'instructions. */
 GType g_instr_block_get_type(void);
 
+/* Recherche le bloc contenant une adresse donnée. */
+GInstrBlock *g_instr_block_find_by_addr(const GInstrBlock *, vmpa_t);
+
 /* Parcours tous les blocs d'instructions dans un ordre donné. */
 bool g_instr_block_visit(GInstrBlock *, instr_block_visitor_cb, void *);
 
diff --git a/src/analysis/blocks/flow.c b/src/analysis/blocks/flow.c
index 85d98ee..6fb5849 100644
--- a/src/analysis/blocks/flow.c
+++ b/src/analysis/blocks/flow.c
@@ -65,6 +65,9 @@ static void g_flow_block_dispose(GFlowBlock *);
 /* Procède à la libération totale de la mémoire. */
 static void g_flow_block_finalize(GFlowBlock *);
 
+/* Recherche le bloc contenant une adresse donnée. */
+static GInstrBlock *g_flow_block_find_by_addr(const GFlowBlock *, vmpa_t);
+
 /* Parcours le bloc d'instructions dans un ordre donné. */
 static bool g_flow_block_visit(GFlowBlock *, instr_block_visitor_cb, void *);
 
@@ -128,6 +131,7 @@ static void g_flow_block_init(GFlowBlock *block)
 
     parent = G_INSTR_BLOCK(block);
 
+    parent->find_by_addr = (find_by_addr_fc)g_flow_block_find_by_addr;
     parent->visit_blocks = (visit_all_blocks_fc)g_flow_block_visit;
     parent->list_blocks = (list_all_blocks_fc)g_flow_block_list_all_blocks;
     parent->list_regs = (list_regs_accesses_fc)g_flow_block_list_regs_accesses;
@@ -236,6 +240,38 @@ GInstrBlock *g_flow_block_new(GArchInstruction *instrs, GArchInstruction *first,
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : block = bloc de départ des recherches.                       *
+*                addr  = ensemble de blocs à parcourir.                       *
+*                                                                             *
+*  Description : Recherche le bloc contenant une adresse donnée.              *
+*                                                                             *
+*  Retour      : bloc basique trouvé ou NULL en cas d'échec.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GInstrBlock *g_flow_block_find_by_addr(const GFlowBlock *block, vmpa_t addr)
+{
+    GInstrBlock *result;                    /* Resultat à retourner        */
+    vmpa_t start;                           /* Adresse de début du bloc    */
+    vmpa_t end;                             /* Adresse de fin du bloc      */
+
+    g_flow_block_get_boundary_addresses(block, &start, &end);
+
+    if (start <= addr && addr <= end)
+        result = G_INSTR_BLOCK(block);
+
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : block    = bloc d'instructions concerné par la visite.       *
 *                callback = ensemble de blocs à parcourir.                    *
 *                data     = donnée utilisateur à associer au parcours.        *
@@ -419,6 +455,25 @@ static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *block
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : block = bloc d'instructions à consulter.                     *
+*                                                                             *
+*  Description : Fournit la liste d'appartenance des instructions du bloc.    *
+*                                                                             *
+*  Retour      : Liste de l'ensemble des instructions.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GArchInstruction *g_flow_block_get_all_instructions_list(const GFlowBlock *block)
+{
+    return block->instrs;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc d'instructions à consulter.                     *
 *                first = instruction de départ du bloc. [OUT]                 *
 *                last  = dernière instruction du bloc. [OUT]                  *
 *                                                                             *
@@ -432,8 +487,11 @@ static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *block
 
 void g_flow_block_get_boundary(const GFlowBlock *block, GArchInstruction **first, GArchInstruction **last)
 {
-    *first = block->first;
-    *last = block->last;
+    if (first != NULL)
+        *first = block->first;
+
+    if (last != NULL)
+        *last = block->last;
 
 }
 
diff --git a/src/analysis/blocks/flow.h b/src/analysis/blocks/flow.h
index 8bd7257..28fb5a9 100644
--- a/src/analysis/blocks/flow.h
+++ b/src/analysis/blocks/flow.h
@@ -55,6 +55,9 @@ GType g_flow_block_get_type(void);
 /* Crée un bloc d'exécution d'instructions. */
 GInstrBlock *g_flow_block_new(GArchInstruction *, GArchInstruction *, GArchInstruction *);
 
+/* Fournit la liste d'appartenance des instructions du bloc. */
+GArchInstruction *g_flow_block_get_all_instructions_list(const GFlowBlock *);
+
 /* Fournit les instructions limites d'un bloc d'exécution. */
 void g_flow_block_get_boundary(const GFlowBlock *, GArchInstruction **, GArchInstruction **);
 
diff --git a/src/analysis/blocks/virtual.c b/src/analysis/blocks/virtual.c
index 90bccca..71a6d06 100644
--- a/src/analysis/blocks/virtual.c
+++ b/src/analysis/blocks/virtual.c
@@ -69,6 +69,9 @@ static void g_virtual_block_dispose(GVirtualBlock *);
 /* Procède à la libération totale de la mémoire. */
 static void g_virtual_block_finalize(GVirtualBlock *);
 
+/* Recherche le bloc contenant une adresse donnée. */
+static GInstrBlock *g_virtual_block_find_by_addr(const GVirtualBlock *, vmpa_t);
+
 /* Parcours le bloc d'instructions dans un ordre donné. */
 static bool g_virtual_block_visit(GVirtualBlock *, instr_block_visitor_cb, void *);
 
@@ -126,6 +129,7 @@ static void g_virtual_block_init(GVirtualBlock *block)
 
     parent = G_INSTR_BLOCK(block);
 
+    parent->find_by_addr = (find_by_addr_fc)g_virtual_block_find_by_addr;
     parent->visit_blocks = (visit_all_blocks_fc)g_virtual_block_visit;
     parent->list_blocks = (list_all_blocks_fc)g_virtual_block_list_all_blocks;
     parent->list_regs = (list_regs_accesses_fc)g_virtual_block_list_regs_accesses;
@@ -207,6 +211,34 @@ GInstrBlock *g_virtual_block_new(void)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : block = bloc de départ des recherches.                       *
+*                addr  = ensemble de blocs à parcourir.                       *
+*                                                                             *
+*  Description : Recherche le bloc contenant une adresse donnée.              *
+*                                                                             *
+*  Retour      : bloc basique trouvé ou NULL en cas d'échec.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GInstrBlock *g_virtual_block_find_by_addr(const GVirtualBlock *block, vmpa_t addr)
+{
+    GInstrBlock *result;                    /* Resultat à retourner        */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = NULL;
+
+    for (i = 0; i < block->children_count && result == NULL; i++)
+        result = g_instr_block_find_by_addr(block->children[i], addr);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : block    = bloc d'instructions concerné par la visite.       *
 *                callback = ensemble de blocs à parcourir.                    *
 *                data     = donnée utilisateur à associer au parcours.        *
@@ -324,3 +356,27 @@ size_t g_virtual_block_count_children(GVirtualBlock *block)
     return block->children_count;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc d'instructions à consulter.                     *
+*                index = indice du sous-bloc recherché.                       *
+*                                                                             *
+*  Description : Renvoie un des blocs contenus dans le groupe courant.        *
+*                                                                             *
+*  Retour      : Un des blocs du groupe.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GInstrBlock *g_virtual_block_get_child(GVirtualBlock *block, size_t index)
+{
+    if (index >= block->children_count)
+        return NULL;
+
+    else
+        return block->children[index];
+
+}
diff --git a/src/analysis/blocks/virtual.h b/src/analysis/blocks/virtual.h
index 5e8ddcd..b254a27 100644
--- a/src/analysis/blocks/virtual.h
+++ b/src/analysis/blocks/virtual.h
@@ -61,6 +61,9 @@ void g_virtual_block_add_child(GVirtualBlock *, GInstrBlock *);
 /* Compte le nombre de blocs contenus dans le groupe courant. */
 size_t g_virtual_block_count_children(GVirtualBlock *);
 
+/* Renvoie un des blocs contenus dans le groupe courant. */
+GInstrBlock *g_virtual_block_get_child(GVirtualBlock *, size_t);
+
 
 
 #endif  /* _ANALYSIS_BLOCKS_VIRTUAL_H */
diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c
index c824697..47c379d 100644
--- a/src/analysis/decomp/decompiler.c
+++ b/src/analysis/decomp/decompiler.c
@@ -167,11 +167,16 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c
         max = g_binary_routine_get_address(routines[i])
             + g_binary_routine_get_size(routines[i]);
 
-        //printf("##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i]));
+        printf("##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i]));
 
+
+        dinstrs = decompiled_routine_instructions(routines[i], format, proc);
+
+        /*
         dinstrs = build_decompiled_block(instrs,
                                          g_binary_routine_get_address(routines[i]),
                                          max, VMPA_MAX, context);
+        */
 
         //instr = g_binary_format_decompile_routine(G_BIN_FORMAT(format), routines[i], context);
 
@@ -216,8 +221,6 @@ GCodeBuffer *decompile_all_from_file(const GLoadedBinary *binary, const char *fi
 
     build_decomp_prologue(result, filename);
 
-
-    /*
     prepare_all_routines_for_decomp(binary, filename);
 
 
@@ -225,7 +228,7 @@ GCodeBuffer *decompile_all_from_file(const GLoadedBinary *binary, const char *fi
 
     format = g_loaded_binary_get_format(binary);
     g_binary_format_decompile(G_BIN_FORMAT(format), result, filename);
-    */
+
 
     return result;
 
diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c
index 693b8cb..c2bc0be 100644
--- a/src/analysis/decomp/il.c
+++ b/src/analysis/decomp/il.c
@@ -24,6 +24,330 @@
 #include "il.h"
 
 
+#include "../blocks/flow.h"
+#include "../blocks/virtual.h"
+#include "../../decomp/expr/block.h"
+#include "../../decomp/instr/ite.h"
+
+
+
+/* --------------------- GESTION DES CONTEXTES DE DECOMPILATION --------------------- */
+
+
+
+
+
+
+
+/* -------------------------- ENCADREMENT DES INSTRUCTIONS -------------------------- */
+
+
+/* Retrouve et rassemble les instructions décompilées. */
+static GDecInstruction *merge_decompiled_instructions(GDecInstruction *, GDecInstruction *);
+
+/* Procède à la décompilation d'un bloc déterminé. */
+static GDecInstruction *decompiled_instructions_block(GFlowBlock *, GVirtualBlock *, GDecContext *);
+
+/* Procède à la décompilation d'un ensemble de blocs déterminé. */
+static GDecInstruction *decompiled_instructions_blocks(GVirtualBlock *, GDecContext *);
+
+/* Procède à la décompilation d'un bloc basique quelconque. */
+static GDecInstruction *decompiled_basic_block(GInstrBlock *, GDecContext *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                       GESTION DES CONTEXTES DE DECOMPILATION                       */
+/* ---------------------------------------------------------------------------------- */
+
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            ENCADREMENT DES INSTRUCTIONS                            */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : group = groupe d'instructions à compléter ou constituer.     *
+*                list  = liste d'instructions à intégrer.                     *
+*                                                                             *
+*  Description : Retrouve et rassemble les instructions décompilées.          *
+*                                                                             *
+*  Retour      : Groupe fourni ou nouveau groupe créé pour l'occasion.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDecInstruction *merge_decompiled_instructions(GDecInstruction *group, GDecInstruction *list)
+{
+    GExprBlock *block;                      /* Autre vision du groupe      */
+    GDecInstruction *iter;                  /* Boucle de parcours          */
+
+    if (group == NULL) block = NULL;
+    else block = G_EXPR_BLOCK(group);
+
+    for (iter = list;
+         iter != NULL;
+         iter = g_dec_instruction_get_next_iter(list, iter))
+    {
+        if (block == NULL)
+            block = G_EXPR_BLOCK(g_expr_block_new(iter));
+        else
+            g_expr_block_add_item(block, iter);
+
+    }
+
+    return G_DEC_INSTRUCTION(block);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block  = ensemble des instructions d'assemblage à traiter.   *
+*                parent = groupe de blocs d'appartenance.                     *
+*                ctx    = contexte de soutien à associer à l'opération.       *
+*                                                                             *
+*  Description : Procède à la décompilation d'un bloc déterminé.              *
+*                                                                             *
+*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GVirtualBlock *parent, GDecContext *ctx)
+{
+    GDecInstruction *res;
+
+    GArchInstruction *instrs;               /* Liste d'instructions natives*/
+    GArchInstruction *first;                /* Première instruction du lot */
+    GArchInstruction *last;                 /* Dernière instruction du lot */
+    vmpa_t max;                             /* Adresse de fin du bloc      */
+    GArchInstruction *iter;                 /* Boucle de parcours          */
+    GDecInstruction *decomp;                /* Dernier résultat de décomp. */
+    GDecInstruction *true_dinstr;           /* Décompilation 'cond vraie'  */
+    GDecInstruction *false_dinstr;          /* Décompilation 'cond fausse' */
+    GArchInstruction *next;                 /* Instruction de branchement  */
+    vmpa_t next_addr;                       /* Adresse de cette instruct°  */
+    GInstrBlock *next_block;                /* Bloc basique correspondant  */
+
+    instrs = g_flow_block_get_all_instructions_list(block);
+    g_flow_block_get_boundary(block, &first, &last);
+
+    g_flow_block_get_boundary_addresses(block, NULL, &max);
+    max++;
+
+    /* Décompilation du corps du bloc */
+
+    for (iter = first;
+         iter != NULL;
+         iter = g_arch_instruction_get_next_iter(instrs, iter, max))
+    {
+        decomp = g_arch_instruction_decompile(iter, ctx);
+    }
+
+    /* Post-traitement selon les types de lien */
+
+
+    res = g_dec_context_get_decomp_instrs(ctx);
+
+
+    /* if ... then ... else ... */
+    if (G_IS_ITE_INSTRUCTION(decomp))
+    {
+        next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_TRUE);
+
+        printf("@ 0x%08llx : true : %p\n", max, next);
+
+        true_dinstr = NULL;
+
+        if (next != NULL)
+        {
+            g_arch_instruction_get_location(next, NULL, NULL, &next_addr);
+            next_block = g_instr_block_find_by_addr(G_INSTR_BLOCK(parent), next_addr);
+
+            if (next_block != NULL)
+            {
+                next_block = g_instr_block_find_by_addr(next_block, next_addr);
+                true_dinstr = decompiled_basic_block(next_block, ctx);
+            }
+
+        }
+
+        next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_FALSE);
+
+        printf("@ 0x%08llx : false : %p\n", max, next);
+
+        false_dinstr = NULL;
+
+        if (next != NULL)
+        {
+            g_arch_instruction_get_location(next, NULL, NULL, &next_addr);
+            next_block = g_instr_block_find_by_addr(G_INSTR_BLOCK(parent), next_addr);
+
+            if (next_block != NULL)
+            {
+                next_block = g_instr_block_find_by_addr(next_block, next_addr);
+                false_dinstr = decompiled_basic_block(next_block, ctx);
+            }
+
+        }
+
+        printf(" -> ite : %p + %p\n", true_dinstr, false_dinstr);
+
+        printf(" -> ite : %s + %s\n",
+               g_type_name(G_TYPE_FROM_INSTANCE(true_dinstr)),
+               g_type_name(G_TYPE_FROM_INSTANCE(false_dinstr)));
+
+
+        g_ite_instruction_set_branches(G_ITE_INSTRUCTION(decomp), true_dinstr, false_dinstr);
+
+    }
+
+    /* Renvoi des instructions mises en place */
+
+    return res;
+
+    //return g_dec_context_get_decomp_instrs(ctx);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = ensemble des instructions d'assemblage à traiter.    *
+*                ctx   = contexte de soutien à associer à l'opération.        *
+*                                                                             *
+*  Description : Procède à la décompilation d'un ensemble de blocs déterminé. *
+*                                                                             *
+*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDecInstruction *decompiled_instructions_blocks(GVirtualBlock *block, GDecContext *ctx)
+{
+    GDecInstruction *result;                /* Instructions à renvoyer     */
+    size_t count;                           /* Nombre de sous-blocs        */
+    size_t i;                               /* Boucle de parcours          */
+    GInstrBlock *sub_block;                 /* Sous-bloc à traiter         */
+    GDecInstruction *dinstrs;               /* Instructions décompilées    */
+
+    result = NULL;
+
+    count = g_virtual_block_count_children(block);
+
+    for (i = 0; i < count; i++)
+    {
+        sub_block = g_virtual_block_get_child(block, i);
+
+        /**
+         * Les groupes de blocs sont forcément rattachés à une instruction,
+         * donc ils sont décompilés depuis ces instructions, pas ici.
+         */
+        if (!G_IS_FLOW_BLOCK(sub_block)) continue;
+
+        /* FIXME */
+        g_dec_context_set_decomp_instrs(ctx, NULL);
+
+        dinstrs = decompiled_instructions_block(G_FLOW_BLOCK(sub_block), block, ctx);
+        result = merge_decompiled_instructions(result, dinstrs);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = ensemble des instructions d'assemblage à traiter.    *
+*                ctx   = contexte de soutien à associer à l'opération.        *
+*                                                                             *
+*  Description : Procède à la décompilation d'un bloc basique quelconque.     *
+*                                                                             *
+*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDecInstruction *decompiled_basic_block(GInstrBlock *block, GDecContext *ctx)
+{
+    GDecInstruction *result;                /* Instructions à retourner    */
+
+    /* FIXME */
+    g_dec_context_set_decomp_instrs(ctx, NULL);
+
+    if (G_IS_VIRTUAL_BLOCK(block))
+        result = decompiled_instructions_blocks(G_VIRTUAL_BLOCK(block), ctx);
+
+    else
+    {
+        result = decompiled_instructions_block(G_FLOW_BLOCK(block), NULL, ctx);
+
+        if (!G_IS_EXPR_BLOCK(result))
+            result = merge_decompiled_instructions(NULL, result);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = routine dont le corps est à traiter.               *
+*                format  = format du binaire contenant les instructions.      *
+*                proc    = architecture du code machine.                      *
+*                                                                             *
+*  Description : Procède à la décompilation d'une routinée déterminée.        *
+*                                                                             *
+*  Retour      : Instructions créées ou NULL si erreur.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *decompiled_routine_instructions(GBinRoutine *routine, GExeFormat *format, GArchProcessor *proc)
+{
+    GDecInstruction *result;                /* Instructions à retourner    */
+    GDecContext *context;                   /* Contexte pour la décompil.  */
+    GInstrBlock *blocks;                    /* Blocs basiques de routine   */
+
+    context = g_arch_processor_get_decomp_context(proc);
+
+    g_object_set_data(G_OBJECT(context), "format", format);
+    g_object_set_data(G_OBJECT(context), "routine", routine);
+
+    blocks = g_binary_routine_get_basic_blocks(routine);
+
+    result = decompiled_basic_block(blocks, context);
+
+    g_object_unref(context);
+
+    return result;
+
+}
+
+
+
+
+
+#if 0
+
+
 #include <malloc.h>
 #include <stdlib.h>
 #include <string.h>
@@ -380,3 +704,5 @@ GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start,
     return result;
 
 }
+
+#endif
diff --git a/src/analysis/decomp/il.h b/src/analysis/decomp/il.h
index 4f38b4f..670505c 100644
--- a/src/analysis/decomp/il.h
+++ b/src/analysis/decomp/il.h
@@ -25,6 +25,18 @@
 #define _ANALYSIS_DECOMP_IL_H
 
 
+#include "../routine.h"
+#include "../../arch/processor.h"
+
+
+
+/* Procède à la décompilation d'une routinée déterminée. */
+GDecInstruction *decompiled_routine_instructions(GBinRoutine *, GExeFormat *, GArchProcessor *);
+
+
+
+
+#if 0
 #include "../../arch/instruction.h"
 #include "../../decomp/instruction.h"
 
@@ -32,7 +44,7 @@
 
 /* Procède à la décompilation basique d'un bloc déterminé. */
 GDecInstruction *build_decompiled_block(GArchInstruction *, vmpa_t, vmpa_t, vmpa_t, GDecContext *);
-
+#endif
 
 
 #endif  /* _ANALYSIS_DECOMP_IL_H */
diff --git a/src/analysis/variable.c b/src/analysis/variable.c
index 6a7c145..edc176a 100644
--- a/src/analysis/variable.c
+++ b/src/analysis/variable.c
@@ -253,11 +253,14 @@ char *g_binary_variable_to_string(const GBinVariable *var, bool simple)
 {
     char *result;                           /* Valeur à retourner          */
 
-    result = _g_data_type_to_string(var->type, simple);
+    /* FIXME : décompilation sans type ! */
+    //result = _g_data_type_to_string(var->type, simple);
+
+    result = strdup("");
 
     if (var->name != NULL)
     {
-        if (!g_data_type_is_pointer(var->type, true))
+        if (!g_data_type_is_pointer(var->type, true) /* FIXME */ && strlen(result) > 0 /* FIXME */)
             result = stradd(result, " ");
 
         result = stradd(result, var->name);
diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c
index 1c109ba..20982b7 100644
--- a/src/arch/dalvik/instruction.c
+++ b/src/arch/dalvik/instruction.c
@@ -117,12 +117,12 @@ static dalvik_instruction _instructions[DOP_COUNT] = {
     [DOP_IF_GE]                 = { 0x35, "if-ge",              dalvik_decomp_instr_if },
     [DOP_IF_GT]                 = { 0x36, "if-gt",              dalvik_decomp_instr_if },
     [DOP_IF_LE]                 = { 0x37, "if-le",              dalvik_decomp_instr_if },
-    [DOP_IF_EQZ]                = { 0x38, "if-eqz",             dalvik_decomp_instr_if_zero },
-    [DOP_IF_NEZ]                = { 0x39, "if-nez",             dalvik_decomp_instr_if_zero },
-    [DOP_IF_LTZ]                = { 0x3a, "if-ltz",             dalvik_decomp_instr_if_zero },
-    [DOP_IF_GEZ]                = { 0x3b, "if-gez",             dalvik_decomp_instr_if_zero },
-    [DOP_IF_GTZ]                = { 0x3c, "if-gtz",             dalvik_decomp_instr_if_zero },
-    [DOP_IF_LEZ]                = { 0x3d, "if-lez",             dalvik_decomp_instr_if_zero },
+    [DOP_IF_EQZ]                = { 0x38, "if-eqz"/*,             dalvik_decomp_instr_if_zero*/ },
+    [DOP_IF_NEZ]                = { 0x39, "if-nez"/*,             dalvik_decomp_instr_if_zero*/ },
+    [DOP_IF_LTZ]                = { 0x3a, "if-ltz"/*,             dalvik_decomp_instr_if_zero*/ },
+    [DOP_IF_GEZ]                = { 0x3b, "if-gez"/*,             dalvik_decomp_instr_if_zero*/ },
+    [DOP_IF_GTZ]                = { 0x3c, "if-gtz"/*,             dalvik_decomp_instr_if_zero*/ },
+    [DOP_IF_LEZ]                = { 0x3d, "if-lez"/*,             dalvik_decomp_instr_if_zero*/ },
     [DOP_UNUSED_3E]             = { 0x3e, NULL /* unused */ },
     [DOP_UNUSED_3F]             = { 0x3f, NULL /* unused */ },
     [DOP_UNUSED_40]             = { 0x40, NULL /* unused */ },
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index b460b37..06d3e71 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -448,6 +448,35 @@ size_t g_arch_instruction_get_destinations(const GArchInstruction *instr, GArchI
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
+*                type  = type de lien recherché.                              *
+*                                                                             *
+*  Description : Fournit la destination d'une instruction et d'un type donné. *
+*                                                                             *
+*  Retour      : Instruction de destination trouvée ou NULL.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GArchInstruction *g_arch_instruction_get_given_destination(const GArchInstruction *instr, InstructionLinkType type)
+{
+    GArchInstruction *result;               /* Résultat à remonter         */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = NULL;
+
+    for (i = 0; i < instr->to_count && result == NULL; i++)
+        if (instr->links_type[i] == type)
+            result = instr->to[i];
+
+    return result;
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                       CONVERSIONS DU FORMAT DES INSTRUCTIONS                       */
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 2eddc3c..051ce51 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -117,6 +117,9 @@ bool g_arch_instruction_has_destinations(const GArchInstruction *);
 /* Fournit les destinations d'une instruction donnée. */
 size_t g_arch_instruction_get_destinations(const GArchInstruction *, GArchInstruction ***, InstructionLinkType **);
 
+/* Fournit la destination d'une instruction et d'un type donné. */
+GArchInstruction *g_arch_instruction_get_given_destination(const GArchInstruction *, InstructionLinkType);
+
 
 
 /* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */
diff --git a/src/decomp/context.c b/src/decomp/context.c
index 9db0bca..94a50c1 100644
--- a/src/decomp/context.c
+++ b/src/decomp/context.c
@@ -30,7 +30,6 @@
 #include "context-int.h"
 #include "instruction-int.h"
 #include "../arch/operand.h"
-#include "../format/dex/method.h"
 
 
 
-- 
cgit v0.11.2-87-g4458