summaryrefslogtreecommitdiff
path: root/src/decomp
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2013-01-20 13:10:06 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2013-01-20 13:10:06 (GMT)
commit37fd2f1329c56078bc8a8b2fc955aa001c109c01 (patch)
tree71bcce9a3eaf6b7569d1f1d3e057752ae517ebde /src/decomp
parenta9bbd894bd25f7c2bb72fb7d4064b19377d90c6d (diff)
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
Diffstat (limited to 'src/decomp')
-rw-r--r--src/decomp/context-int.h16
-rw-r--r--src/decomp/context.c203
-rw-r--r--src/decomp/context.h18
3 files changed, 233 insertions, 4 deletions
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);