From 37fd2f1329c56078bc8a8b2fc955aa001c109c01 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 20 Jan 2013 13:10:06 +0000
Subject: Took care of shared allocations between blocks when converting
 registers.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@326 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                        |  46 +++++++++
 src/analysis/blocks/raccess.c    |   2 +-
 src/analysis/blocks/raccess.h    |   2 +-
 src/analysis/decomp/decompiler.c |   2 +-
 src/analysis/decomp/il.c         |  86 +++++++++++------
 src/analysis/disass/macro.c      |   4 +-
 src/arch/dalvik/context.c        |  73 ++++++++++++--
 src/arch/dalvik/decomp/aget.c    |   9 +-
 src/arch/dalvik/decomp/aput.c    |   9 +-
 src/arch/dalvik/decomp/arithm.c  |  23 +++--
 src/arch/dalvik/decomp/array.c   |   7 +-
 src/arch/dalvik/decomp/const.c   |  10 +-
 src/arch/dalvik/decomp/if.c      |  16 ++-
 src/arch/dalvik/decomp/iget.c    |   7 +-
 src/arch/dalvik/decomp/invoke.c  |  17 +++-
 src/arch/dalvik/decomp/iput.c    |   7 +-
 src/arch/dalvik/decomp/move.c    |  19 +++-
 src/arch/dalvik/decomp/new.c     |   5 +-
 src/arch/dalvik/decomp/ret.c     |   5 +-
 src/arch/dalvik/register.c       |  23 +++++
 src/arch/register-int.h          |   4 +
 src/arch/register.c              |  43 +++++++++
 src/arch/register.h              |   6 ++
 src/decomp/context-int.h         |  16 ++-
 src/decomp/context.c             | 203 ++++++++++++++++++++++++++++++++++++++-
 src/decomp/context.h             |  18 +++-
 26 files changed, 583 insertions(+), 79 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 620779f..b5b4590 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+13-01-20  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/blocks/raccess.c:
+	* src/analysis/blocks/raccess.h:
+	Typo: constify the source list when merging two lists.
+
+	* src/analysis/decomp/decompiler.c:
+	Disable (again) debug output.
+
+	* src/analysis/decomp/il.c:
+	Build awaited registers lists and attach them to decompilation contexts.
+	Share the allocation list between these contexts.
+
+	* src/analysis/disass/macro.c:
+	Disable (again) debug output.
+
+	* src/arch/dalvik/context.c:
+	Take care of shared allocations between blocks when converting registers.
+
+	* src/arch/dalvik/decomp/aget.c:
+	* src/arch/dalvik/decomp/aput.c:
+	* src/arch/dalvik/decomp/arithm.c:
+	* src/arch/dalvik/decomp/array.c:
+	* src/arch/dalvik/decomp/const.c:
+	* src/arch/dalvik/decomp/if.c:
+	* src/arch/dalvik/decomp/iget.c:
+	* src/arch/dalvik/decomp/invoke.c:
+	* src/arch/dalvik/decomp/iput.c:
+	* src/arch/dalvik/decomp/move.c:
+	* src/arch/dalvik/decomp/new.c:
+	* src/arch/dalvik/decomp/ret.c:
+	Update code: provide the address of the decompiled instruction when
+	converting registers into variables.
+
+	* src/arch/dalvik/register.c:
+	* src/arch/register.c:
+	* src/arch/register.h:
+	* src/arch/register-int.h:
+	Provide more functions about registers for GLib: equal() and hash().
+
+	* src/decomp/context.c:
+	* src/decomp/context.h:
+	* src/decomp/context-int.h:
+	Define lists tracking awaited and allocated [shared] registers. Provides
+	functions to access them from all context implementations.
+
 13-01-17  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/decomp/il.c:
diff --git a/src/analysis/blocks/raccess.c b/src/analysis/blocks/raccess.c
index 7fe084c..4c76e22 100644
--- a/src/analysis/blocks/raccess.c
+++ b/src/analysis/blocks/raccess.c
@@ -190,7 +190,7 @@ GRAccessList *g_raccess_list_new(void)
 *                                                                             *
 ******************************************************************************/
 
-void g_raccess_list_merge(GRAccessList *list, GRAccessList *src)
+void g_raccess_list_merge(GRAccessList *list, const GRAccessList *src)
 {
     size_t count;                           /* Taille d'un parcours        */
     size_t i;                               /* Boucle de parcours          */
diff --git a/src/analysis/blocks/raccess.h b/src/analysis/blocks/raccess.h
index cc2fd00..843933b 100644
--- a/src/analysis/blocks/raccess.h
+++ b/src/analysis/blocks/raccess.h
@@ -77,7 +77,7 @@ GType g_raccess_list_get_type(void);
 GRAccessList *g_raccess_list_new(void);
 
 /* Intègre une liste d'accès à des registres dans une autre. */
-void g_raccess_list_merge(GRAccessList *, GRAccessList *);
+void g_raccess_list_merge(GRAccessList *, const GRAccessList *);
 
 /* Compare un accès registre avec un autre. */
 int compare_reg_accesses(const reg_access *, const reg_access *);
diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c
index 71a9286..a61e7c7 100644
--- a/src/analysis/decomp/decompiler.c
+++ b/src/analysis/decomp/decompiler.c
@@ -169,7 +169,7 @@ 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("\n##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i]));
 
 
         dinstrs = decompiled_routine_instructions(routines[i], format, proc);
diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c
index 642c921..64f6398 100644
--- a/src/analysis/decomp/il.c
+++ b/src/analysis/decomp/il.c
@@ -40,8 +40,11 @@ static bool track_used_registers(GFlowBlock *, BlockFollowPosition, GRAccessList
 /* Etablit le relévé des allocations de registre. */
 static void setup_awaited_regs_allocation(const GInstrBlock *, vmpa_t);
 
+/* Etablit la liste de tous les allocations attendues. */
+static bool merge_all_awaited_regs(GInstrBlock *, BlockVisitOrder, GRAccessList *);
+
 /* Met en place un contexte adapté aux sous-blocs d'un bloc. */
-static GDecContext *create_new_context_for_sub_block(GDecContext *, GInstrBlock *);
+static GDecContext *create_new_context_for_sub_block(GDecContext *, GInstrBlock *, GHashTable *);
 
 
 
@@ -147,7 +150,7 @@ static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRA
 
             }
 
-
+            /*
             do
             {
                 vmpa_t start, end;
@@ -160,7 +163,7 @@ static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRA
 
             }
             while (0);
-
+            */
 
             break;
 
@@ -203,8 +206,38 @@ static void setup_awaited_regs_allocation(const GInstrBlock *list, vmpa_t start)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : ctx   = contexte de décompilation courant.                   *
-*                block = block regroupant les branches de division.           *
+*  Paramètres  : block = bloc d'instructions concerné par la visite.          *
+*                order = position dans la visite.                             *
+*                list  = liste à compléter.                                   *
+*                                                                             *
+*  Description : Etablit la liste de tous les allocations attendues.          *
+*                                                                             *
+*  Retour      : true pour parcourir tous les blocs.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool merge_all_awaited_regs(GInstrBlock *block, BlockVisitOrder order, GRAccessList *list)
+{
+    const GRAccessList *awaited;            /* Registres conséquents       */
+
+    if (G_IS_FLOW_BLOCK(block))
+    {
+        awaited = g_flow_block_list_regs_accesses(G_FLOW_BLOCK(block));
+        g_raccess_list_merge(list, awaited);
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx    = contexte de décompilation courant.                  *
+*                block  = block regroupant les branches de division.          *
+*                shared = liste des allocations passées de registres attendus.*
 *                                                                             *
 *  Description : Met en place un contexte adapté aux sous-blocs d'un bloc.    *
 *                                                                             *
@@ -214,17 +247,26 @@ static void setup_awaited_regs_allocation(const GInstrBlock *list, vmpa_t start)
 *                                                                             *
 ******************************************************************************/
 
-static GDecContext *create_new_context_for_sub_block(GDecContext *ctx, GInstrBlock *block)
+static GDecContext *create_new_context_for_sub_block(GDecContext *ctx, GInstrBlock *block, GHashTable *shared)
 {
+    GDecContext *result;                    /* Contexte à retourner        */
+    GRAccessList *list;                     /* Allocations attendues       */
 
+    result = g_dec_context_dup(ctx);
 
-    return g_dec_context_dup(ctx);
+    list = g_raccess_list_new();
+    g_instr_block_visit(block, (instr_block_visitor_cb)merge_all_awaited_regs, list);
+    g_dec_context_set_awaited(result, list);
+    g_object_unref(G_OBJECT(list));
 
+    g_dec_context_set_shared_allocs(result, shared);
 
+    return result;
 
 }
 
 
+
 /* ---------------------------------------------------------------------------------- */
 /*                            ENCADREMENT DES INSTRUCTIONS                            */
 /* ---------------------------------------------------------------------------------- */
@@ -282,8 +324,6 @@ static GDecInstruction *merge_decompiled_instructions(GDecInstruction *group, GD
 
 static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecContext *ctx)
 {
-    GDecInstruction *res;
-
     GArchInstruction *instrs;               /* Liste d'instructions natives*/
     GArchInstruction *first;                /* Première instruction du lot */
     GArchInstruction *last;                 /* Dernière instruction du lot */
@@ -291,12 +331,12 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
     GArchInstruction *iter;                 /* Boucle de parcours          */
     GDecInstruction *decomp;                /* Dernier résultat de décomp. */
     GInstrBlock *sub_parent;                /* Groupe des sous-branches    */
+    GHashTable *sub_shared;                 /* Allocations communes        */
     GDecContext *sub_ctx;                   /* Sous-contexte pour branche  */
     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_parent;               /* Bloc basique correspondant  */
     GInstrBlock *next_block;                /* Sous-bloc basique direct    */
 
     instrs = g_flow_block_get_all_instructions_list(block);
@@ -316,14 +356,13 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
 
     /* Post-traitement selon les types de lien */
 
-
-    //res = g_dec_context_get_decomp_instrs(ctx);
-
-
     /* if ... then ... else ... */
     if (G_IS_ITE_INSTRUCTION(decomp))
     {
         sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
+        sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash,
+                                           (GEqualFunc)g_arch_register_equal,
+                                           g_object_unref, g_object_unref);
 
         true_dinstr = NULL;
 
@@ -335,9 +374,9 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
 
             if (next_block != NULL)
             {
-                sub_ctx = create_new_context_for_sub_block(ctx, sub_parent);
+                sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared);
                 true_dinstr = decompiled_basic_block(next_block, sub_ctx);
-                /* TODO : merge awaited */
+                g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx);
                 g_object_unref(G_OBJECT(sub_ctx));
             }
 
@@ -353,29 +392,22 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
 
             if (next_block != NULL)
             {
-                sub_ctx = create_new_context_for_sub_block(ctx, sub_parent);
+                sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared);
                 false_dinstr = decompiled_basic_block(next_block, sub_ctx);
-                /* TODO : merge awaited */
+                g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx);
                 g_object_unref(G_OBJECT(sub_ctx));
             }
 
         }
 
-        printf(" -> ite : %p + %p\n", true_dinstr, false_dinstr);
-
-        printf(" -> ite : %s + %s\n",
-               true_dinstr ? g_type_name(G_TYPE_FROM_INSTANCE(true_dinstr)) : "none",
-               false_dinstr ? g_type_name(G_TYPE_FROM_INSTANCE(false_dinstr)) : "none");
-
-
         g_ite_instruction_set_branches(G_ITE_INSTRUCTION(decomp), true_dinstr, false_dinstr);
 
+        g_hash_table_unref(sub_shared);
+
     }
 
     /* Renvoi des instructions mises en place */
 
-    //return res;
-
     return g_dec_context_get_decomp_instrs(ctx);
 
 }
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index 8652b27..60d99da 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -655,14 +655,14 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines,
         end = start + g_binary_routine_get_size(routines[i]);
 
 
-        printf("==== %s ====\n", g_binary_routine_to_string(routines[i]));
+        //printf("==== %s ====\n", g_binary_routine_to_string(routines[i]));
 
 
         block = build_instruction_block(list, start, end, VMPA_MAX);
         g_binary_routine_set_basic_blocks(routines[i], block);
 
 
-        g_instr_block_visit(block, (instr_block_visitor_cb)print_blocks, (int []){ 0 });
+        //g_instr_block_visit(block, (instr_block_visitor_cb)print_blocks, (int []){ 0 });
 
         gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
 
diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c
index e80ead3..7918467 100644
--- a/src/arch/dalvik/context.c
+++ b/src/arch/dalvik/context.c
@@ -123,8 +123,11 @@ static void g_dalvik_dcontext_finalize(GDalvikDContext *);
 /* Duplique un contexte de compilation. */
 static GDalvikDContext *g_dalvik_dcontext_dup(GDalvikDContext *);
 
+/* Propage un registre alloué et attendu par la suite. */
+static void g_dalvik_context_spread_allocated_shared_reg(GDalvikDContext *, GDalvikRegister *, GDecInstruction *);
+
 /* Convertit un registre machine en un pseudo-registre. */
-static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *, GDalvikRegisterOperand *, bool);
+static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *, GDalvikRegisterOperand *, bool, vmpa_t);
 
 
 
@@ -335,6 +338,7 @@ static void g_dalvik_dcontext_init(GDalvikDContext *ctx)
     parent = G_DEC_CONTEXT(ctx);
 
     parent->dup = (dup_dec_context_fc)g_dalvik_dcontext_dup;
+    parent->spread = (spread_reg_fc)g_dalvik_context_spread_allocated_shared_reg;
     parent->convert_reg = (convert_register_fc)g_dalvik_dcontext_convert_register;
 
 }
@@ -443,9 +447,46 @@ static GDalvikDContext *g_dalvik_dcontext_dup(GDalvikDContext *orig)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : parent = instance à éventuellement compléter.                *
+*                child  = instance à venir consulter.                         *
+*                                                                             *
+*  Description : Propage un registre alloué et attendu par la suite.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dalvik_context_spread_allocated_shared_reg(GDalvikDContext *ctx, GDalvikRegister *reg, GDecInstruction *dinstr)
+{
+    GDexFormat *format;                     /* Recherche de méthode        */
+    GBinRoutine *routine;                   /* Objet des recherches        */
+    GDexMethod *method;                     /* Méthode décompilée          */
+    uint16_t index;                         /* Identifiant du registre     */
+    DexVariableIndex info;                  /* Nature du registre          */
+
+    format = G_DEX_FORMAT(G_DEC_CONTEXT(ctx)->format);
+    routine = G_DEC_CONTEXT(ctx)->routine;
+
+    method = g_dex_format_find_method_by_address(format, g_binary_routine_get_address(routine));
+
+    index = g_dalvik_register_get_index(reg);
+    info = g_dex_method_get_variable(method, index);
+
+    g_object_ref(G_OBJECT(dinstr));
+    g_hash_table_insert(ctx->locals, GUINT_TO_POINTER(DVI_INDEX(info)), dinstr);
+    ctx->locals_count++;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : ctx     = instance à consulter, voire mettre à jour.         *
 *                operand = opérande représentant un registre quelconque.      *
 *                assign  = précise le sort prochain du registre.              *
+*                addr    = adresse de l'instruction décompilée.               *
 *                                                                             *
 *  Description : Convertit un registre machine en un pseudo-registre.         *
 *                                                                             *
@@ -455,7 +496,7 @@ static GDalvikDContext *g_dalvik_dcontext_dup(GDalvikDContext *orig)
 *                                                                             *
 ******************************************************************************/
 
-static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *ctx, GDalvikRegisterOperand *operand, bool assign)
+static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *ctx, GDalvikRegisterOperand *operand, bool assign, vmpa_t addr)
 {
     GDecInstruction *result;                /* Instance à retourner        */
     GDexFormat *format;                     /* Recherche de méthode        */
@@ -522,17 +563,37 @@ static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *ctx,
     {
         found = g_hash_table_lookup(ctx->locals, GUINT_TO_POINTER(DVI_INDEX(info)));
 
-        if (/*!assign && */found != NULL)
+        if (!assign && found != NULL)
         {
             g_object_ref(G_OBJECT(found));
             result = G_DEC_INSTRUCTION(found);
         }
         else
         {
-            result = g_pseudo_register_new();
-            g_pseudo_register_set_basename(G_PSEUDO_REGISTER(result), "var");
-            g_pseudo_register_set_index(G_PSEUDO_REGISTER(result), ctx->locals_count);
+            /*
+            if (!assign)
+            {
+                printf("bug");
+                exit(0);
+            }
+            */
+
+            result = g_dec_context_get_awaited_alloc(G_DEC_CONTEXT(ctx), G_ARCH_REGISTER(reg), addr);
+
+            if (result == NULL)
+            {
+                result = g_pseudo_register_new();
+                g_pseudo_register_set_basename(G_PSEUDO_REGISTER(result), "var");
+                g_pseudo_register_set_index(G_PSEUDO_REGISTER(result), ctx->locals_count);
+
+                g_dec_context_notify_reg_alloc(G_DEC_CONTEXT(ctx), G_ARCH_REGISTER(reg),
+                                               result, addr);
+
+            }
+            else
+                g_object_ref(G_OBJECT(result));
 
+            g_object_ref(G_OBJECT(result));
             g_hash_table_insert(ctx->locals, GUINT_TO_POINTER(DVI_INDEX(info)), result);
             ctx->locals_count++;
 
diff --git a/src/arch/dalvik/decomp/aget.c b/src/arch/dalvik/decomp/aget.c
index 0fa66eb..4ca012b 100644
--- a/src/arch/dalvik/decomp/aget.c
+++ b/src/arch/dalvik/decomp/aget.c
@@ -45,20 +45,23 @@
 GDecInstruction *dalvik_decomp_instr_aget(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *array;                 /* Tableau accédé              */
     GDecInstruction *index;                 /* Indice de cellule considérée*/
     GDecInstruction *content;               /* Contenu de cellule visé     */
     GDecInstruction *access;                /* Représentation de l'accès   */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
-    array = g_dec_context_convert_register(ctx, operand, false);
+    array = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 2);
-    index = g_dec_context_convert_register(ctx, operand, false);
+    index = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    content = g_dec_context_convert_register(ctx, operand, true);
+    content = g_dec_context_convert_register(ctx, operand, true, addr);
 
     access = g_array_access_new(G_DEC_EXPRESSION(array), G_DEC_EXPRESSION(index));
     result = g_assign_expression_new(G_DEC_EXPRESSION(content), G_DEC_EXPRESSION(access));
diff --git a/src/arch/dalvik/decomp/aput.c b/src/arch/dalvik/decomp/aput.c
index 41bd89f..8d648e4 100644
--- a/src/arch/dalvik/decomp/aput.c
+++ b/src/arch/dalvik/decomp/aput.c
@@ -45,20 +45,23 @@
 GDecInstruction *dalvik_decomp_instr_aput(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *content;               /* Contenu de cellule visé     */
     GDecInstruction *array;                 /* Tableau accédé              */
     GDecInstruction *index;                 /* Indice de cellule considérée*/
     GDecInstruction *access;                /* Représentation de l'accès   */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 0);
-    content = g_dec_context_convert_register(ctx, operand, false);
+    content = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 1);
-    array = g_dec_context_convert_register(ctx, operand, false);
+    array = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 2);
-    index = g_dec_context_convert_register(ctx, operand, false);
+    index = g_dec_context_convert_register(ctx, operand, false, addr);
 
     access = g_array_access_new(G_DEC_EXPRESSION(array), G_DEC_EXPRESSION(index));
     result = g_assign_expression_new(G_DEC_EXPRESSION(access), G_DEC_EXPRESSION(content));
diff --git a/src/arch/dalvik/decomp/arithm.c b/src/arch/dalvik/decomp/arithm.c
index a217adf..464694f 100644
--- a/src/arch/dalvik/decomp/arithm.c
+++ b/src/arch/dalvik/decomp/arithm.c
@@ -48,6 +48,7 @@ GDecInstruction *dalvik_decomp_instr_arithm(const GArchInstruction *instr, GDecC
 {
     GDecInstruction *result;                /* Instruction à retourner     */
     ArithmOperationType type;               /* Type d'opération menée      */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *op1;                   /* Premier opérande utilisé    */
     GDecInstruction *op2;                   /* Second opérande utilisé     */
@@ -85,14 +86,16 @@ GDecInstruction *dalvik_decomp_instr_arithm(const GArchInstruction *instr, GDecC
             break;
     }
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
-    op1 = g_dec_context_convert_register(ctx, operand, false);
+    op1 = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 2);
-    op2 = g_dec_context_convert_register(ctx, operand, false);
+    op2 = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     arithm = g_arithm_expression_new(G_DEC_EXPRESSION(op1), type, G_DEC_EXPRESSION(op2));
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(arithm));
@@ -119,6 +122,7 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *instr,
 {
     GDecInstruction *result;                /* Instruction à retourner     */
     ArithmOperationType type;               /* Type d'opération menée      */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *op1;                   /* Premier opérande utilisé    */
     GDecInstruction *dest;                  /* Enregistrement du résultat  */
@@ -153,11 +157,13 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *instr,
             break;
     }
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
-    op1 = g_dec_context_convert_register(ctx, operand, false);
+    op1 = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     arithm = g_arithm_expression_new(G_DEC_EXPRESSION(dest), type, G_DEC_EXPRESSION(op1));
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(arithm));
@@ -184,6 +190,7 @@ GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *instr, G
 {
     GDecInstruction *result;                /* Instruction à retourner     */
     ArithmOperationType type;               /* Type d'opération menée      */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *op1;                   /* Premier opérande utilisé    */
     GDecInstruction *op2;                   /* Second opérande utilisé     */
@@ -225,14 +232,16 @@ GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *instr, G
             break;
     }
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
-    op1 = g_dec_context_convert_register(ctx, operand, false);
+    op1 = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 2);
     op2 = g_imm_expression_new(G_IMM_OPERAND(operand));
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     arithm = g_arithm_expression_new(G_DEC_EXPRESSION(op1), type, G_DEC_EXPRESSION(op2));
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(arithm));
diff --git a/src/arch/dalvik/decomp/array.c b/src/arch/dalvik/decomp/array.c
index 3422461..217cab3 100644
--- a/src/arch/dalvik/decomp/array.c
+++ b/src/arch/dalvik/decomp/array.c
@@ -45,17 +45,20 @@
 GDecInstruction *dalvik_decomp_instr_array_length(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *reg;                   /* Pseudo-registre redéfini    */
     GDecInstruction *len;                   /* Enregistrement de taille    */
     GDecInstruction *dest;                  /* Destination de la création  */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
-    reg = g_dec_context_convert_register(ctx, operand, false);
+    reg = g_dec_context_convert_register(ctx, operand, false, addr);
     len = g_dalvik_alength_new(G_DEC_EXPRESSION(reg));
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(len));
 
diff --git a/src/arch/dalvik/decomp/const.c b/src/arch/dalvik/decomp/const.c
index 98133ac..a451b55 100644
--- a/src/arch/dalvik/decomp/const.c
+++ b/src/arch/dalvik/decomp/const.c
@@ -47,12 +47,15 @@
 GDecInstruction *dalvik_decomp_instr_const(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *reg;                   /* Pseudo-registre redéfini    */
     GDecInstruction *imm;                   /* Valeur immédiate décompilée */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 0);
-    reg = g_dec_context_convert_register(ctx, operand, true);
+    reg = g_dec_context_convert_register(ctx, operand, true, addr);
 
     operand = g_arch_instruction_get_operand(instr, 1);
     imm = g_imm_expression_new(G_IMM_OPERAND(operand));
@@ -80,14 +83,17 @@ GDecInstruction *dalvik_decomp_instr_const(const GArchInstruction *instr, GDecCo
 GDecInstruction *dalvik_decomp_instr_const_str(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *reg;                   /* Pseudo-registre redéfini    */
     uint32_t index;                         /* Indice de la chaîne         */
     const char *value;                      /* Chaîne de caractères        */
     GDecInstruction *str;                   /* Chaîne décompilée           */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 0);
-    reg = g_dec_context_convert_register(ctx, operand, true);
+    reg = g_dec_context_convert_register(ctx, operand, true, addr);
 
     operand = g_arch_instruction_get_operand(instr, 1);
     index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand));
diff --git a/src/arch/dalvik/decomp/if.c b/src/arch/dalvik/decomp/if.c
index b274ead..6a156ec 100644
--- a/src/arch/dalvik/decomp/if.c
+++ b/src/arch/dalvik/decomp/if.c
@@ -47,6 +47,7 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte
 {
     GDecInstruction *result;                /* Instruction à retourner     */
     CompSignType sign;                      /* Type d'opération menée      */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *op1;                   /* Premier opérande utilisé    */
     GDecInstruction *op2;                   /* Second opérande utilisé     */
@@ -78,14 +79,16 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte
             break;
     }
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 0);
-    op1 = g_dec_context_convert_register(ctx, operand, false);
+    op1 = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 1);
-    op2 = g_dec_context_convert_register(ctx, operand, false);
+    op2 = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 2);
-    jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand);*/
+    jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand, addr);*/
 
     cond = g_cond_expression_new(G_DEC_EXPRESSION(op1), sign, G_DEC_EXPRESSION(op2));
     result = g_ite_instruction_new(G_DEC_EXPRESSION(cond), jmp, jmp);
@@ -113,6 +116,7 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec
 {
     GDecInstruction *result;                /* Instruction à retourner     */
     CompSignType sign;                      /* Type d'opération menée      */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *op1;                   /* Premier opérande utilisé    */
     GDecInstruction *op2;                   /* Second opérande utilisé     */
@@ -144,14 +148,16 @@ GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *instr, GDec
             break;
     }
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 0);
-    op1 = g_dec_context_convert_register(ctx, operand, false);
+    op1 = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, (unsigned int)0);
     op2 = g_imm_expression_new(operand);
 
     operand = g_arch_instruction_get_operand(instr, 2);
-    jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand);*/
+    jmp = 0x1234ull;/*g_dec_context_convert_register(ctx, operand, addr);*/
 
     cond = g_cond_expression_new(G_DEC_EXPRESSION(op1), sign, G_DEC_EXPRESSION(op2));
     result = g_ite_instruction_new(G_DEC_EXPRESSION(cond), jmp, jmp);
diff --git a/src/arch/dalvik/decomp/iget.c b/src/arch/dalvik/decomp/iget.c
index 5d1cf65..9cf603d 100644
--- a/src/arch/dalvik/decomp/iget.c
+++ b/src/arch/dalvik/decomp/iget.c
@@ -47,6 +47,7 @@
 GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *src;                   /* Registre de l'object        */
     uint32_t index;                         /* Indice dans la table        */
@@ -55,8 +56,10 @@ GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *instr, GDecCon
     GDecInstruction *dest;                  /* Registre de destination     */
     GDecInstruction *access;                /* Représentation de l'accès   */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
-    src = g_dec_context_convert_register(ctx, operand, false);
+    src = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 2);
     index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand));
@@ -66,7 +69,7 @@ GDecInstruction *dalvik_decomp_instr_iget(const GArchInstruction *instr, GDecCon
     g_pseudo_register_set_variable(G_PSEUDO_REGISTER(field), var);
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     access = g_access_expression_new(G_DEC_EXPRESSION(src), G_DEC_EXPRESSION(field));
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(access));
diff --git a/src/arch/dalvik/decomp/invoke.c b/src/arch/dalvik/decomp/invoke.c
index 7337ccc..4b2f20f 100644
--- a/src/arch/dalvik/decomp/invoke.c
+++ b/src/arch/dalvik/decomp/invoke.c
@@ -62,6 +62,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *instr
     const char *name;                       /* Chaîne à afficher           */
     GDecInstruction *src;                   /* Source de l'assignation     */
     GDecInstruction *dest;                  /* Destination de l'assignat°  */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     size_t i;                               /* Boucle de parcours #2       */
     GArchOperand *arg;                      /* Argument brut de l'appel    */
     GDecInstruction *reg;                   /* Argument converti           */
@@ -123,10 +124,12 @@ GDecInstruction *dalvik_decomp_instr_invoke_direct(const GArchInstruction *instr
     operand = g_arch_instruction_get_operand(instr, 0);
     count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand));
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     for (i = 1; i < count; i++)
     {
         arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), i);
-        reg = g_dec_context_convert_register(ctx, arg, false);
+        reg = g_dec_context_convert_register(ctx, arg, false, addr);
 
         g_routine_call_add_arg(G_ROUTINE_CALL(result), reg);
 
@@ -158,6 +161,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_static(const GArchInstruction *instr
     uint32_t index;                         /* Indice de l'élément visé    */
     GBinRoutine *routine;                   /* Routine visée par l'appel   */
     GDecInstruction *call;                  /* Représentation de l'appel   */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     size_t i;                               /* Boucle de parcours #2       */
     GArchOperand *arg;                      /* Argument brut de l'appel    */
     GDecInstruction *reg;                   /* Argument converti           */
@@ -181,10 +185,12 @@ GDecInstruction *dalvik_decomp_instr_invoke_static(const GArchInstruction *instr
     operand = g_arch_instruction_get_operand(instr, 0);
     count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand));
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     for (i = 0; i < count; i++)
     {
         arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), i);
-        reg = g_dec_context_convert_register(ctx, arg, false);
+        reg = g_dec_context_convert_register(ctx, arg, false, addr);
 
         g_routine_call_add_arg(G_ROUTINE_CALL(call), reg);
 
@@ -216,6 +222,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst
     uint32_t index;                         /* Indice de l'élément visé    */
     GBinRoutine *routine;                   /* Routine visée par l'appel   */
     GDecInstruction *call;                  /* Représentation de l'appel   */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     size_t i;                               /* Boucle de parcours #2       */
     GArchOperand *arg;                      /* Argument brut de l'appel    */
     GDecInstruction *reg;                   /* Argument converti           */
@@ -239,10 +246,12 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst
     operand = g_arch_instruction_get_operand(instr, 0);
     count = g_dalvik_args_count(G_DALVIK_ARGS_OPERAND(operand));
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     for (i = 1; i < count; i++)
     {
         arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), i);
-        reg = g_dec_context_convert_register(ctx, arg, false);
+        reg = g_dec_context_convert_register(ctx, arg, false, addr);
 
         g_routine_call_add_arg(G_ROUTINE_CALL(call), reg);
 
@@ -251,7 +260,7 @@ GDecInstruction *dalvik_decomp_instr_invoke_virtual(const GArchInstruction *inst
     /* Appel depuis le propriétaire */
 
     arg = g_dalvik_args_operand_get(G_DALVIK_ARGS_OPERAND(operand), 0);
-    reg = g_dec_context_convert_register(ctx, arg, false);
+    reg = g_dec_context_convert_register(ctx, arg, false, addr);
 
     result = g_access_expression_new(G_DEC_EXPRESSION(reg), G_DEC_EXPRESSION(call));
 
diff --git a/src/arch/dalvik/decomp/iput.c b/src/arch/dalvik/decomp/iput.c
index fedb00e..ed0830c 100644
--- a/src/arch/dalvik/decomp/iput.c
+++ b/src/arch/dalvik/decomp/iput.c
@@ -47,6 +47,7 @@
 GDecInstruction *dalvik_decomp_instr_iput(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *dest;                  /* Registre de destination     */
     GDecInstruction *src;                   /* Registre de l'object        */
@@ -55,11 +56,13 @@ GDecInstruction *dalvik_decomp_instr_iput(const GArchInstruction *instr, GDecCon
     GBinVariable *var;                      /* Variable / champ accédé     */
     GDecInstruction *access;                /* Représentation de l'accès   */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 0);
-    src = g_dec_context_convert_register(ctx, operand, false);
+    src = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 1);
-    dest = g_dec_context_convert_register(ctx, operand, false);
+    dest = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 2);
     index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand));
diff --git a/src/arch/dalvik/decomp/move.c b/src/arch/dalvik/decomp/move.c
index 9165447..a502952 100644
--- a/src/arch/dalvik/decomp/move.c
+++ b/src/arch/dalvik/decomp/move.c
@@ -44,15 +44,18 @@
 GDecInstruction *dalvik_decomp_instr_move(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *src;                   /* Registre de l'object        */
     GDecInstruction *dest;                  /* Registre de destination     */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
-    src = g_dec_context_convert_register(ctx, operand, false);
+    src = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(src));
 
@@ -77,15 +80,18 @@ GDecInstruction *dalvik_decomp_instr_move(const GArchInstruction *instr, GDecCon
 GDecInstruction *dalvik_decomp_instr_move_object(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *src;                   /* Registre de l'object        */
     GDecInstruction *dest;                  /* Registre de destination     */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
-    src = g_dec_context_convert_register(ctx, operand, false);
+    src = g_dec_context_convert_register(ctx, operand, false, addr);
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(src));
 
@@ -111,6 +117,7 @@ GDecInstruction *dalvik_decomp_instr_move_result(const GArchInstruction *instr,
 {
     GDecInstruction *result;                /* Instruction à retourner     */
     GDecInstruction *list;                  /* Instructions décompilées    */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *last;                  /* Instruction précédante      */
     GDecInstruction *dest;                  /* Registre de destination     */
@@ -122,8 +129,10 @@ GDecInstruction *dalvik_decomp_instr_move_result(const GArchInstruction *instr,
     g_dec_instruction_delete(&list, last);
     g_dec_context_set_decomp_instrs(ctx, list);
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(last));
 
diff --git a/src/arch/dalvik/decomp/new.c b/src/arch/dalvik/decomp/new.c
index 75dc259..e30feb2 100644
--- a/src/arch/dalvik/decomp/new.c
+++ b/src/arch/dalvik/decomp/new.c
@@ -46,6 +46,7 @@
 GDecInstruction *dalvik_decomp_instr_new_instance(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     uint32_t index;                         /* Indice dans la table        */
     GDataType *type;                        /* Type concerné par l'opérat° */
@@ -53,6 +54,8 @@ GDecInstruction *dalvik_decomp_instr_new_instance(const GArchInstruction *instr,
     GDecInstruction *call;                  /* Appel au constructeur       */
     GDecInstruction *dest;                  /* Registre de destination     */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 1);
     index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(operand));
     type = get_type_from_dex_pool(G_DEX_FORMAT(g_dec_context_get_format(ctx)), index);
@@ -61,7 +64,7 @@ GDecInstruction *dalvik_decomp_instr_new_instance(const GArchInstruction *instr,
     call = g_routine_call_new(constructor);
 
     operand = g_arch_instruction_get_operand(instr, 0);
-    dest = g_dec_context_convert_register(ctx, operand, true);
+    dest = g_dec_context_convert_register(ctx, operand, true, addr);
 
     result = g_assign_expression_new(G_DEC_EXPRESSION(dest), G_DEC_EXPRESSION(call));
 
diff --git a/src/arch/dalvik/decomp/ret.c b/src/arch/dalvik/decomp/ret.c
index b7c5414..47179f3 100644
--- a/src/arch/dalvik/decomp/ret.c
+++ b/src/arch/dalvik/decomp/ret.c
@@ -44,11 +44,14 @@
 GDecInstruction *dalvik_decomp_instr_return(const GArchInstruction *instr, GDecContext *ctx)
 {
     GDecInstruction *result;                /* Instruction à retourner     */
+    vmpa_t addr;                            /* Adresse de l'instruction    */
     GArchOperand *operand;                  /* Opérande de l'instruction   */
     GDecInstruction *reg;                   /* Pseudo-registre redéfini    */
 
+    g_arch_instruction_get_location(instr, NULL, NULL, &addr);
+
     operand = g_arch_instruction_get_operand(instr, 0);
-    reg = g_dec_context_convert_register(ctx, operand, false);
+    reg = g_dec_context_convert_register(ctx, operand, false, addr);
 
     result = g_return_expression_new(G_DEC_EXPRESSION(reg));
 
diff --git a/src/arch/dalvik/register.c b/src/arch/dalvik/register.c
index db4186a..4e91cd4 100644
--- a/src/arch/dalvik/register.c
+++ b/src/arch/dalvik/register.c
@@ -58,6 +58,9 @@ static void g_dalvik_register_class_init(GDalvikRegisterClass *);
 /* Initialise une instance de registre Dalvik. */
 static void g_dalvik_register_init(GDalvikRegister *);
 
+/* Produit une empreinte à partir d'un registre. */
+static guint g_dalvik_register_hash(const GDalvikRegister *);
+
 
 
 /* Indique le type défini pour une représentation d'un registre Dalvik. */
@@ -100,6 +103,7 @@ static void g_dalvik_register_init(GDalvikRegister *reg)
 
     base = G_ARCH_REGISTER(reg);
 
+    base->hash = (reg_hash_fc)g_dalvik_register_hash;
     base->compare = (reg_compare_fc)g_dalvik_register_compare;
     base->print = (reg_print_fc)g_dalvik_register_print;
 
@@ -152,6 +156,25 @@ uint16_t g_dalvik_register_get_index(const GDalvikRegister *reg)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : reg = opérande à consulter pour le calcul.                   *
+*                                                                             *
+*  Description : Produit une empreinte à partir d'un registre.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static guint g_dalvik_register_hash(const GDalvikRegister *reg)
+{
+    return reg->index;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : a = premier opérande à consulter.                            *
 *                b = second opérande à consulter.                             *
 *                                                                             *
diff --git a/src/arch/register-int.h b/src/arch/register-int.h
index 00773f3..8ff7a9a 100644
--- a/src/arch/register-int.h
+++ b/src/arch/register-int.h
@@ -29,6 +29,9 @@
 
 
 
+/* Produit une empreinte à partir d'un registre. */
+typedef guint (* reg_hash_fc) (const GArchRegister *);
+
 /* Compare un registre avec un autre. */
 typedef int (* reg_compare_fc) (const GArchRegister *, const GArchRegister *);
 
@@ -48,6 +51,7 @@ struct _GArchRegister
 {
     GObject parent;                         /* A laisser en premier        */
 
+    reg_hash_fc hash;                       /* Production d'empreinte      */
     reg_compare_fc compare;                 /* Comparaison de registres    */
     reg_print_fc print;                     /* Impression du registre      */
     reg_is_base_pointer_fc is_bp;           /* Correspondance avec ebp     */
diff --git a/src/arch/register.c b/src/arch/register.c
index 6631d4b..7c4f193 100644
--- a/src/arch/register.c
+++ b/src/arch/register.c
@@ -78,6 +78,25 @@ static void g_arch_register_init(GArchRegister *reg)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : reg = opérande à consulter pour le calcul.                   *
+*                                                                             *
+*  Description : Produit une empreinte à partir d'un registre.                *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+guint g_arch_register_hash(const GArchRegister *reg)
+{
+    return reg->hash(reg);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : a = premier opérande à consulter.                            *
 *                b = second opérande à consulter.                             *
 *                                                                             *
@@ -98,6 +117,30 @@ int g_arch_register_compare(const GArchRegister *a, const GArchRegister *b)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : a = premier opérande à consulter.                            *
+*                b = second opérande à consulter.                             *
+*                                                                             *
+*  Description : Détermine si un registre est égal à un autre.                *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+gboolean g_arch_register_equal(const GArchRegister *a, const GArchRegister *b)
+{
+    int ret;                                /* Comparaison détaillée       */
+
+    ret = g_arch_register_compare(a, b);
+
+    return (ret == 0 ? TRUE : FALSE);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : reg    = registre à transcrire.                              *
 *                line   = ligne tampon où imprimer l'opérande donné.          *
 *                syntax = type de représentation demandée.                    *
diff --git a/src/arch/register.h b/src/arch/register.h
index a163ad3..e3c95b4 100644
--- a/src/arch/register.h
+++ b/src/arch/register.h
@@ -52,9 +52,15 @@ typedef struct _GArchRegisterClass GArchRegisterClass;
 /* Indique le type défini pour une représentation d'un registre. */
 GType g_arch_register_get_type(void);
 
+/* Produit une empreinte à partir d'un registre. */
+guint g_arch_register_hash(const GArchRegister *);
+
 /* Compare un registre avec un autre. */
 int g_arch_register_compare(const GArchRegister *, const GArchRegister *);
 
+/* Détermine si un registre est égal à un autre. */
+gboolean g_arch_register_equal(const GArchRegister *, const GArchRegister *);
+
 /* Traduit un registre en version humainement lisible. */
 void g_arch_register_print(const GArchRegister *, GBufferLine *, AsmSyntax);
 
diff --git a/src/decomp/context-int.h b/src/decomp/context-int.h
index 7e5b1b0..974f5ae 100644
--- a/src/decomp/context-int.h
+++ b/src/decomp/context-int.h
@@ -36,8 +36,12 @@
 /* Duplique un contexte de compilation. */
 typedef GDecContext * (* dup_dec_context_fc) (GDecContext *);
 
+/* Propage un registre alloué et attendu par la suite. */
+typedef void (* spread_reg_fc) (GDecContext *, GArchRegister *, GDecInstruction *);
+
 /* Convertit un registre machine en un pseudo-registre. */
-typedef GDecInstruction * (* convert_register_fc) (GDecContext *, gpointer, bool);
+typedef GDecInstruction * (* convert_register_fc) (GDecContext *, gpointer, bool, vmpa_t);
+
 
 
 /* Définition d'une context décompilée (instance) */
@@ -46,11 +50,15 @@ struct _GDecContext
     GObject parent;                         /* A laisser en premier        */
 
     dup_dec_context_fc dup;                 /* Duplication de contexte     */
+    spread_reg_fc spread;                   /* Propagation des allocations */
     convert_register_fc convert_reg;        /* Traduction des registres    */
 
     GExeFormat *format;                     /* Format binaire concerné     */
     GBinRoutine *routine;                   /* Routine visée par l'opérat° */
 
+    GRAccessList *awaited;                  /* Allocations attendues       */
+    GHashTable *shared;                     /* Allocations à propager      */
+
     GDecInstruction *list;                  /* Chaîne décompilée           */
 
 };
@@ -67,6 +75,12 @@ struct _GDecContextClass
 /* Duplique partiellement un contexte de compilation. */
 void _g_dec_context_dup(GDecContext *, GDecContext *);
 
+/* Sauvegarde une conversion de registre si elle est attendue. */
+void g_dec_context_notify_reg_alloc(GDecContext *, GArchRegister *, GDecInstruction *, vmpa_t);
+
+/* Fournit une conversiond de registre déjà faite et attendue. */
+GDecInstruction *g_dec_context_get_awaited_alloc(GDecContext *, GArchRegister *, vmpa_t);
+
 
 
 #endif  /* _DECOMP_CONTEXT_INT_H */
diff --git a/src/decomp/context.c b/src/decomp/context.c
index 025c0d2..ef5c25e 100644
--- a/src/decomp/context.c
+++ b/src/decomp/context.c
@@ -89,6 +89,11 @@ static void g_dec_context_class_init(GDecContextClass *class)
 
 static void g_dec_context_init(GDecContext *ctx)
 {
+    ctx->awaited = g_raccess_list_new();
+
+    ctx->shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash,
+                                        (GEqualFunc)g_arch_register_equal,
+                                        g_object_unref, g_object_unref);
 
 }
 
@@ -113,6 +118,9 @@ static void g_dec_context_dispose(GDecContext *ctx)
     if (ctx->routine != NULL)
         g_object_unref(G_OBJECT(ctx->routine));
 
+    g_object_unref(G_OBJECT(ctx->awaited));
+    g_hash_table_unref(ctx->shared);
+
     G_OBJECT_CLASS(g_dec_context_parent_class)->dispose(G_OBJECT(ctx));
 
 }
@@ -227,6 +235,135 @@ GExeFormat *g_dec_context_get_format(const GDecContext *ctx)
 {
     return ctx->format;
 
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx     = instance à mettre à jour.                          *
+*                awaited = liste des registres impliqués dans plusieurs blocs.*
+*                                                                             *
+*  Description : Définit la liste des registrés utilisés dans plusieurs blocs.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_dec_context_set_awaited(GDecContext *ctx, GRAccessList *awaited)
+{
+    g_object_unref(G_OBJECT(ctx->awaited));
+
+    g_object_ref(G_OBJECT(awaited));
+    ctx->awaited = awaited;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx = instance à consulter.                                  *
+*                                                                             *
+*  Description : Fournit la liste des registrés utilisés dans plusieurs blocs.*
+*                                                                             *
+*  Retour      : Liste des registres impliqués dans plusieurs blocs.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const GRAccessList *g_dec_context_get_awaited(const GDecContext *ctx)
+{
+    return ctx->awaited;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx    = instance à mettre à jour.                           *
+*                shared = liste des allocations passées de registres attendus.*
+*                                                                             *
+*  Description : Définit la liste des registrés déjà alloués et attendus.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_dec_context_set_shared_allocs(GDecContext *ctx, GHashTable *shared)
+{
+    g_hash_table_unref(ctx->shared);
+
+    g_hash_table_ref(shared);
+    ctx->shared = shared;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx = instance à consulter.                                  *
+*                                                                             *
+*  Description : Fournit la liste des registrés déjà alloués et attendus.     *
+*                                                                             *
+*  Retour      : Liste des allocations passées de registres attendus.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GHashTable *g_dec_context_get_shared_allocs(const GDecContext *ctx)
+{
+    return ctx->shared;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = instance à éventuellement compléter.                *
+*                child  = instance à venir consulter.                         *
+*                                                                             *
+*  Description : Propage les registres alloués et attendus par la suite.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_dec_context_spread_allocated_shared_regs(GDecContext *parent, GDecContext *child)
+{
+    GHashTableIter iter;                    /* Boucle de parcours          */
+    GArchRegister *reg;                     /* Registre converti           */
+    GDecInstruction *dinstr;                /* Expression décompilée       */
+
+    g_hash_table_iter_init(&iter, child->shared);
+
+    while (g_hash_table_iter_next(&iter, (gpointer *)&reg, (gpointer *)&dinstr))
+    {
+        /**
+         * La liste des allocations attendues du bloc virtuel parent, et donc de
+         * son contexte associé, englobe les attentes des blocs contenus.
+         * Même si ce bloc parent n'est pas responsable directement de ces allocations,
+         * on fait remonter ces dernières pour la propagation dans les blocs suivants
+         * le bloc parent.
+         */
+        if (g_raccess_list_find(parent->awaited, reg) != NULL)
+        {
+            g_object_ref(G_OBJECT(reg));
+            g_object_ref(G_OBJECT(dinstr));
+
+            g_hash_table_insert(parent->shared, reg, dinstr);
+
+        }
+
+        parent->spread(parent, reg, dinstr);
+
+    }
 
 }
 
@@ -276,6 +413,7 @@ void g_dec_context_set_decomp_instrs(GDecContext *ctx, GDecInstruction *instr)
 *  Paramètres  : ctx     = instance à consulter, voire mettre à jour.         *
 *                operand = opérande représentant un registre quelconque.      *
 *                assign  = précise le sort prochain du registre.              *
+*                addr    = adresse de l'instruction décompilée.               *
 *                                                                             *
 *  Description : Convertit un registre machine en un pseudo-registre.         *
 *                                                                             *
@@ -285,8 +423,69 @@ void g_dec_context_set_decomp_instrs(GDecContext *ctx, GDecInstruction *instr)
 *                                                                             *
 ******************************************************************************/
 
-GDecInstruction *g_dec_context_convert_register(GDecContext *ctx, gpointer operand, bool assign)
+GDecInstruction *g_dec_context_convert_register(GDecContext *ctx, gpointer operand, bool assign, vmpa_t addr)
+{
+    return ctx->convert_reg(ctx, operand, assign, addr);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx    = instance à consulter, voire mettre à jour.          *
+*                reg    = registre à l'origine de l'allocation.               *
+*                dinstr = élément décompilé résultant.                        *
+*                addr   = adresse de l'instruction décompilée.                *
+*                                                                             *
+*  Description : Sauvegarde une conversion de registre si elle est attendue.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_dec_context_notify_reg_alloc(GDecContext *ctx, GArchRegister *reg, GDecInstruction *dinstr, vmpa_t addr)
+{
+    reg_access *access;                     /* Attente rélle si existante  */
+
+    access = g_raccess_list_find(ctx->awaited, reg);
+
+    if (access != NULL && access->last_write == addr)
+    {
+        g_object_ref(G_OBJECT(reg));
+        g_object_ref(G_OBJECT(dinstr));
+
+        g_hash_table_insert(ctx->shared, reg, dinstr);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx  = instance à consulter, voire mettre à jour.            *
+*                reg  = registre à convertir prochainement.                   *
+*                addr = adresse de l'instruction décompilée.                  *
+*                                                                             *
+*  Description : Fournit une conversiond de registre déjà faite et attendue.  *
+*                                                                             *
+*  Retour      : Elément déjà décompilé dans une autre branche.               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDecInstruction *g_dec_context_get_awaited_alloc(GDecContext *ctx, GArchRegister *reg, vmpa_t addr)
 {
-    return ctx->convert_reg(ctx, operand, assign);
+    reg_access *access;                     /* Attente rélle si existante  */
+
+    access = g_raccess_list_find(ctx->awaited, reg);
+    if (access == NULL) return NULL;
+
+    if (access->last_write != addr) return NULL;
+
+    return G_DEC_INSTRUCTION(g_hash_table_lookup(ctx->shared, reg));
 
 }
diff --git a/src/decomp/context.h b/src/decomp/context.h
index 94b3270..d1b1ac9 100644
--- a/src/decomp/context.h
+++ b/src/decomp/context.h
@@ -31,6 +31,7 @@
 #include "instruction.h"
 #include "../arch/archbase.h"
 #include "../format/executable.h"
+#include "../analysis/blocks/raccess.h"
 
 
 /**
@@ -74,6 +75,21 @@ void g_dec_context_set_info(GDecContext *, GBinRoutine *, GExeFormat *);
 /* Fournit le format binaire associé au contexte. */
 GExeFormat *g_dec_context_get_format(const GDecContext *);
 
+/* Définit la liste des registrés utilisés dans plusieurs blocs. */
+void g_dec_context_set_awaited(GDecContext *, GRAccessList *);
+
+/* Fournit la liste des registrés utilisés dans plusieurs blocs. */
+const GRAccessList *g_dec_context_get_awaited(const GDecContext *);
+
+/* Définit la liste des registrés déjà alloués et attendus. */
+void g_dec_context_set_shared_allocs(GDecContext *, GHashTable *);
+
+/* Fournit la liste des registrés déjà alloués et attendus. */
+GHashTable *g_dec_context_get_shared_allocs(const GDecContext *);
+
+/* Propage les registres alloués et attendus par la suite. */
+void g_dec_context_spread_allocated_shared_regs(GDecContext *, GDecContext *);
+
 /* Fournit le premier élément de la liste des instructions. */
 GDecInstruction *g_dec_context_get_decomp_instrs(const GDecContext *tx);
 
@@ -81,7 +97,7 @@ GDecInstruction *g_dec_context_get_decomp_instrs(const GDecContext *tx);
 void g_dec_context_set_decomp_instrs(GDecContext *, GDecInstruction *);
 
 /* Convertit un registre machine en un pseudo-registre. */
-GDecInstruction *g_dec_context_convert_register(GDecContext *, gpointer, bool);
+GDecInstruction *g_dec_context_convert_register(GDecContext *, gpointer, bool, vmpa_t);
 
 
 
-- 
cgit v0.11.2-87-g4458