From a9bbd894bd25f7c2bb72fb7d4064b19377d90c6d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 17 Jan 2013 22:21:03 +0000
Subject: Forked the decompilation context when needed.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@325 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                 |  9 ++++++
 src/analysis/decomp/il.c  | 79 ++++++++++++++++++++++++++++++-----------------
 src/arch/dalvik/context.c | 41 ++++++++++++++++++++++++
 src/decomp/context-int.h  | 12 +++++--
 src/decomp/context.c      | 34 +++++++++++++++++---
 src/decomp/context.h      |  4 +--
 6 files changed, 143 insertions(+), 36 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 38b8828..620779f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+13-01-17  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/decomp/il.c:
+	* src/arch/dalvik/context.c:
+	* src/decomp/context.c:
+	* src/decomp/context.h:
+	* src/decomp/context-int.h:
+	Fork the decompilation context when needed.
+
 13-01-14  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/decomp/decompiler.c:
diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c
index 60e86b6..642c921 100644
--- a/src/analysis/decomp/il.c
+++ b/src/analysis/decomp/il.c
@@ -40,7 +40,8 @@ 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);
 
-
+/* Met en place un contexte adapté aux sous-blocs d'un bloc. */
+static GDecContext *create_new_context_for_sub_block(GDecContext *, GInstrBlock *);
 
 
 
@@ -185,12 +186,9 @@ static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRA
 
 static void setup_awaited_regs_allocation(const GInstrBlock *list, vmpa_t start)
 {
-    GDecContext *result;                    /* Contexte pour la décompil.  */
     GInstrBlock *first;                     /* Bloc de départ du flot      */
     GRAccessList *needed;                   /* Registres inter-blocs       */
 
-    result = NULL;
-
     first = g_instr_block_find_by_addr(list, start, true);
 
     needed = g_raccess_list_new();
@@ -200,11 +198,31 @@ static void setup_awaited_regs_allocation(const GInstrBlock *list, vmpa_t start)
 
     g_object_unref(G_OBJECT(needed));
 
+}
 
-    return result;
 
-}
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx   = contexte de décompilation courant.                   *
+*                block = block regroupant les branches de division.           *
+*                                                                             *
+*  Description : Met en place un contexte adapté aux sous-blocs d'un bloc.    *
+*                                                                             *
+*  Retour      : Nouveau contexte près à emploi.                              *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDecContext *create_new_context_for_sub_block(GDecContext *ctx, GInstrBlock *block)
+{
+
 
+    return g_dec_context_dup(ctx);
+
+
+
+}
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -272,11 +290,13 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
     vmpa_t max;                             /* Adresse de fin du bloc      */
     GArchInstruction *iter;                 /* Boucle de parcours          */
     GDecInstruction *decomp;                /* Dernier résultat de décomp. */
+    GInstrBlock *sub_parent;                /* Groupe des sous-branches    */
+    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_parent;               /* Bloc basique correspondant  */
     GInstrBlock *next_block;                /* Sous-bloc basique direct    */
 
     instrs = g_flow_block_get_all_instructions_list(block);
@@ -297,43 +317,47 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
     /* Post-traitement selon les types de lien */
 
 
-    res = g_dec_context_get_decomp_instrs(ctx);
+    //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);
+        sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
 
         true_dinstr = NULL;
 
+        next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_TRUE);
         if (next != NULL)
         {
             g_arch_instruction_get_location(next, NULL, NULL, &next_addr);
-            next_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
-            next_block = g_instr_block_find_by_addr(next_parent, next_addr, false);
+            next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false);
 
             if (next_block != NULL)
-                true_dinstr = decompiled_basic_block(next_block, ctx);
+            {
+                sub_ctx = create_new_context_for_sub_block(ctx, sub_parent);
+                true_dinstr = decompiled_basic_block(next_block, sub_ctx);
+                /* TODO : merge awaited */
+                g_object_unref(G_OBJECT(sub_ctx));
+            }
 
         }
 
-        next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_FALSE);
-
-        printf("@ 0x%08llx : false : %p\n", max, next);
-
         false_dinstr = NULL;
 
+        next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_FALSE);
         if (next != NULL)
         {
             g_arch_instruction_get_location(next, NULL, NULL, &next_addr);
-            next_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
-            next_block = g_instr_block_find_by_addr(next_parent, next_addr, false);
+            next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false);
 
             if (next_block != NULL)
-                false_dinstr = decompiled_basic_block(next_block, ctx);
+            {
+                sub_ctx = create_new_context_for_sub_block(ctx, sub_parent);
+                false_dinstr = decompiled_basic_block(next_block, sub_ctx);
+                /* TODO : merge awaited */
+                g_object_unref(G_OBJECT(sub_ctx));
+            }
 
         }
 
@@ -350,9 +374,9 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon
 
     /* Renvoi des instructions mises en place */
 
-    return res;
+    //return res;
 
-    //return g_dec_context_get_decomp_instrs(ctx);
+    return g_dec_context_get_decomp_instrs(ctx);
 
 }
 
@@ -393,13 +417,15 @@ static GDecInstruction *decompiled_instructions_blocks(GVirtualBlock *block, GDe
         if (!G_IS_FLOW_BLOCK(sub_block)) continue;
 
         /* FIXME */
-        g_dec_context_set_decomp_instrs(ctx, NULL);
+        //g_dec_context_set_decomp_instrs(ctx, NULL);
 
         dinstrs = decompiled_instructions_block(G_FLOW_BLOCK(sub_block), ctx);
-        result = merge_decompiled_instructions(result, dinstrs);
+        //result = merge_decompiled_instructions(result, dinstrs);
 
     }
 
+    result = merge_decompiled_instructions(result, dinstrs);
+
     return result;
 
 }
@@ -422,9 +448,6 @@ static GDecInstruction *decompiled_basic_block(GInstrBlock *block, GDecContext *
 {
     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);
 
diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c
index f1af7e9..e80ead3 100644
--- a/src/arch/dalvik/context.c
+++ b/src/arch/dalvik/context.c
@@ -120,6 +120,9 @@ static void g_dalvik_dcontext_dispose(GDalvikDContext *);
 /* Procède à la libération totale de la mémoire. */
 static void g_dalvik_dcontext_finalize(GDalvikDContext *);
 
+/* Duplique un contexte de compilation. */
+static GDalvikDContext *g_dalvik_dcontext_dup(GDalvikDContext *);
+
 /* Convertit un registre machine en un pseudo-registre. */
 static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *, GDalvikRegisterOperand *, bool);
 
@@ -331,6 +334,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->convert_reg = (convert_register_fc)g_dalvik_dcontext_convert_register;
 
 }
@@ -402,6 +406,43 @@ GDalvikDContext *g_dalvik_dcontext_new(void)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : orig = contexte de compilation à copier.                     *
+*                                                                             *
+*  Description : Duplique un contexte de compilation.                         *
+*                                                                             *
+*  Retour      : Contexte de décompilation prêt à emploi.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDalvikDContext *g_dalvik_dcontext_dup(GDalvikDContext *orig)
+{
+    GDalvikDContext *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_DALVIK_DCONTEXT, NULL);
+
+    //g_object_unref(G_OBJECT(result->args));
+    //g_object_unref(G_OBJECT(result->locals));
+
+    _g_dec_context_dup(G_DEC_CONTEXT(result), G_DEC_CONTEXT(orig));
+
+    if (orig->this != NULL) g_object_ref(G_OBJECT(orig->this));
+    //g_object_ref(G_OBJECT(orig->args));
+    //g_object_ref(G_OBJECT(orig->locals));
+
+    result->this = orig->this;
+    result->args = orig->args;
+    result->locals = orig->locals;
+    result->locals_count = orig->locals_count;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : ctx     = instance à consulter, voire mettre à jour.         *
 *                operand = opérande représentant un registre quelconque.      *
 *                assign  = précise le sort prochain du registre.              *
diff --git a/src/decomp/context-int.h b/src/decomp/context-int.h
index 8139077..7e5b1b0 100644
--- a/src/decomp/context-int.h
+++ b/src/decomp/context-int.h
@@ -33,6 +33,9 @@
 
 
 
+/* Duplique un contexte de compilation. */
+typedef GDecContext * (* dup_dec_context_fc) (GDecContext *);
+
 /* Convertit un registre machine en un pseudo-registre. */
 typedef GDecInstruction * (* convert_register_fc) (GDecContext *, gpointer, bool);
 
@@ -42,13 +45,14 @@ struct _GDecContext
 {
     GObject parent;                         /* A laisser en premier        */
 
+    dup_dec_context_fc dup;                 /* Duplication de contexte     */
+    convert_register_fc convert_reg;        /* Traduction des registres    */
+
     GExeFormat *format;                     /* Format binaire concerné     */
     GBinRoutine *routine;                   /* Routine visée par l'opérat° */
 
     GDecInstruction *list;                  /* Chaîne décompilée           */
 
-    convert_register_fc convert_reg;        /* Traduction des registres    */
-
 };
 
 
@@ -60,5 +64,9 @@ struct _GDecContextClass
 };
 
 
+/* Duplique partiellement un contexte de compilation. */
+void _g_dec_context_dup(GDecContext *, GDecContext *);
+
+
 
 #endif  /* _DECOMP_CONTEXT_INT_H */
diff --git a/src/decomp/context.c b/src/decomp/context.c
index 6905505..025c0d2 100644
--- a/src/decomp/context.c
+++ b/src/decomp/context.c
@@ -139,9 +139,35 @@ static void g_dec_context_finalize(GDecContext *ctx)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : -                                                            *
+*  Paramètres  : dest = contexte de compilation à définir.                    *
+*                src  = contexte de compilation à copier.                     *
 *                                                                             *
-*  Description : Met en place un nouveau contexte de décompilation.           *
+*  Description : Duplique partiellement un contexte de compilation.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void _g_dec_context_dup(GDecContext *dest, GDecContext *src)
+{
+    if (src->routine != NULL)
+        g_object_ref(G_OBJECT(src->routine));
+    if (src->format != NULL)
+        g_object_ref(G_OBJECT(src->format));
+
+    dest->routine = src->routine;
+    dest->format = src->format;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : orig = contexte de compilation à copier.                     *
+*                                                                             *
+*  Description : Duplique un contexte de compilation.                         *
 *                                                                             *
 *  Retour      : Contexte de décompilation prêt à emploi.                     *
 *                                                                             *
@@ -149,11 +175,11 @@ static void g_dec_context_finalize(GDecContext *ctx)
 *                                                                             *
 ******************************************************************************/
 
-GDecContext *g_dec_context_new(void)
+GDecContext *g_dec_context_dup(GDecContext *orig)
 {
     GDecContext *result;                    /* Instance à retourner        */
 
-    result = g_object_new(G_TYPE_DEC_CONTEXT, NULL);
+    result = orig->dup(orig);
 
     return result;
 
diff --git a/src/decomp/context.h b/src/decomp/context.h
index 2daff91..94b3270 100644
--- a/src/decomp/context.h
+++ b/src/decomp/context.h
@@ -65,8 +65,8 @@ typedef struct _GDecContextClass GDecContextClass;
 /* Indique le type défini pour un contexte de décompilation. */
 GType g_dec_context_get_type(void);
 
-/* Met en place un nouveau contexte de décompilation. */
-GDecContext *g_dec_context_new(void);
+/* Duplique un contexte de compilation. */
+GDecContext *g_dec_context_dup(GDecContext *);
 
 /* Définit les informations essentielles à la décompilation. */
 void g_dec_context_set_info(GDecContext *, GBinRoutine *, GExeFormat *);
-- 
cgit v0.11.2-87-g4458