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); | 
