diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2013-01-20 13:10:06 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2013-01-20 13:10:06 (GMT) |
commit | 37fd2f1329c56078bc8a8b2fc955aa001c109c01 (patch) | |
tree | 71bcce9a3eaf6b7569d1f1d3e057752ae517ebde /src/decomp | |
parent | a9bbd894bd25f7c2bb72fb7d4064b19377d90c6d (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.h | 16 | ||||
-rw-r--r-- | src/decomp/context.c | 203 | ||||
-rw-r--r-- | src/decomp/context.h | 18 |
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 *)®, (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); |