diff options
Diffstat (limited to 'src/analysis/decomp')
| -rw-r--r-- | src/analysis/decomp/decompiler.c | 16 | ||||
| -rw-r--r-- | src/analysis/decomp/il.c | 391 | 
2 files changed, 21 insertions, 386 deletions
| diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c index fff654f..71a9286 100644 --- a/src/analysis/decomp/decompiler.c +++ b/src/analysis/decomp/decompiler.c @@ -139,12 +139,12 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c      size_t i; -    GDecContext *context;                   /* Contexte pour la décompil.  */ +    //GDecContext *context;                   /* Contexte pour la décompil.  */      GDecInstruction *dinstrs; -    GArchInstruction *instrs;                /* Instructions natives        */ +    //GArchInstruction *instrs;                /* Instructions natives        */ -    vmpa_t max;                             /* Première adresse à écarter  */ +    //vmpa_t max;                             /* Première adresse à écarter  */      format = g_loaded_binary_get_format(binary);      proc = get_arch_processor_from_format(G_EXE_FORMAT(format)); @@ -156,17 +156,19 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c      for (i = 0; i < count; i++)      { +        /*          context = g_arch_processor_get_decomp_context(proc);          g_object_set_data(G_OBJECT(context), "format", format);          g_object_set_data(G_OBJECT(context), "routine", routines[i]);          g_dec_context_set_max_address(context, max); - +        */ +        /*          instrs = g_binary_routine_get_instructions(routines[i]);          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])); @@ -185,10 +187,10 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c          g_binary_routine_set_decomp_instructions(routines[i], dinstrs); - +        /*          if (context != NULL)              g_object_unref(context); - +        */      } diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c index 6333216..60e86b6 100644 --- a/src/analysis/decomp/il.c +++ b/src/analysis/decomp/il.c @@ -37,6 +37,8 @@  /* Détermine les registres utilisés avant leur initialisation. */  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); @@ -144,7 +146,7 @@ static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRA              } -            /* +              do              {                  vmpa_t start, end; @@ -157,7 +159,7 @@ static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRA              }              while (0); -            */ +              break; @@ -173,15 +175,15 @@ static bool track_used_registers(GFlowBlock *block, BlockFollowPosition pos, GRA  *  Paramètres  : list  = ensemble des instructions d'assemblage à traiter.    *  *                start = adresse de départ de la routine visée.               *  *                                                                             * -*  Description : Procède à la décompilation d'une routinée déterminée.        * +*  Description : Etablit le relévé des allocations de registre.               *  *                                                                             * -*  Retour      : Instructions créées ou NULL si erreur.                       * +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static GDecContext *init_decomp_context(const GInstrBlock *list, vmpa_t start) +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      */ @@ -303,7 +305,7 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon      {          next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_TRUE); -        //printf("@ 0x%08llx : true : %p\n", max, next); +        printf("@ 0x%08llx : true : %p\n", max, next);          true_dinstr = NULL; @@ -320,7 +322,7 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon          next = g_arch_instruction_get_given_destination(last, ILT_JUMP_IF_FALSE); -        //printf("@ 0x%08llx : false : %p\n", max, next); +        printf("@ 0x%08llx : false : %p\n", max, next);          false_dinstr = NULL; @@ -335,13 +337,12 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon          } -        /*          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); @@ -462,13 +463,11 @@ GDecInstruction *decompiled_routine_instructions(GBinRoutine *routine, GExeForma      GInstrBlock *blocks;                    /* Blocs basiques de routine   */      context = g_arch_processor_get_decomp_context(proc); - -    g_object_set_data(G_OBJECT(context), "format", format); -    g_object_set_data(G_OBJECT(context), "routine", routine); +    g_dec_context_set_info(context, routine, format);      blocks = g_binary_routine_get_basic_blocks(routine); -    init_decomp_context(blocks, g_binary_routine_get_address(routine)); +    setup_awaited_regs_allocation(blocks, g_binary_routine_get_address(routine));      result = decompiled_basic_block(blocks, context); @@ -477,369 +476,3 @@ GDecInstruction *decompiled_routine_instructions(GBinRoutine *routine, GExeForma      return result;  } - - - - - -#if 0 - - -#include <malloc.h> -#include <stdlib.h> -#include <string.h> - - -#include "../../decomp/expr/block.h" -#include "../../decomp/instr/ite.h" - - - -/* Indications sur une branche */ -typedef struct _branch_info -{ -    vmpa_t *jumps;                          /* Jalons de la branche        */ -    size_t count;                           /* Quantité de ces jalons      */ - -} branch_info; - - -/* Indique si une adresse est retenue comme point de passage. */ -static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool); - -/* Identifie les différents points de passage d'une branche. */ -static void find_next_jumps(GArchInstruction *, vmpa_t, vmpa_t, branch_info *); - -/* Retrouve le point de ralliement entre deux branches. */ -static vmpa_t compute_first_common_addr(branch_info *, branch_info *); - - - - - - - - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : info = informations à consulter.                             * -*                addr = adresse à rechercher.                                 * -*                fast = autorise une recherche rapide.                        * -*                                                                             * -*  Description : Indique si une adresse est retenue comme point de passage.   * -*                                                                             * -*  Retour      : true si le jalon est déjà dans la liste, false sinon.        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast) -{ -    bool result;                            /* Bilan à retourner           */ -    size_t i;                               /* Boucle de parcours          */ -    void *ptr;                              /* Résultat des recherches     */ - -    result = false; - -    if (!fast) -        for (i = 0; i < info->count && !result; i++) -            result = (info->jumps[i] == *addr); - -    else -    { -        ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); -        result = (ptr != NULL); -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : instrs = ensemble des instructions d'assemblage.             * -*                start  = adresse de début du bloc.                           * -*                end    = adresse de fin du bloc (exclusive).                 * -*                count  = nombre de sauts détectés. [OUT]                     * -*                                                                             * -*  Description : Identifie les différents points de passage d'une branche.    * -*                                                                             * -*  Retour      : Jalons dans le flot d'exécution.                             * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end, branch_info *info) -{ -    GArchInstruction *iter;                 /* Boucle de parcours #1       */ -    GArchInstruction **dests;               /* Instr. visée par une autre  */ -    InstructionLinkType *types;             /* Type de lien entre lignes   */ -    size_t dcount;                          /* Nombre de liens de dest.    */ -    size_t i;                               /* Boucle de parcours #2       */ -    vmpa_t addr;                            /* Adresse de la destination   */ - -    /* On évite de boucler... */ -    if (is_addr_in_branch(info, &start, false)) -        return; - -    info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t)); -    info->jumps[info->count - 1] = start; - -    /* On suit le flot jusqu'à la prochaine bifurcation */ -    for (iter = g_arch_instruction_find_by_address(instrs, start, true); -         iter != NULL; -         iter = g_arch_instruction_get_next_iter(instrs, iter, end)) -    { -        if (!g_arch_instruction_has_destinations(iter)) -            continue; - -        dcount = g_arch_instruction_get_destinations(iter, &dests, &types); - -        for (i = 0; i < dcount; i++) -            switch (types[i]) -            { -                case ILT_EXEC_FLOW: -                case ILT_JUMP: -                case ILT_JUMP_IF_TRUE: -                case ILT_JUMP_IF_FALSE: -                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); -                    find_next_jumps(instrs, addr, end, info); -                    break; - -                default: -                    break; - -            } - -        break; - -    } - -    /* Si on termine... */ -    if (iter != NULL && !is_addr_in_branch(info, &end, false)) -    { -        info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t)); -        info->jumps[info->count - 1] = end; -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : a = premier ensemble de jalons à parcourir.                  * -*                b = second ensemble de jalons à parcourir.                   * -*                                                                             * -*  Description : Retrouve le point de ralliement entre deux branches.         * -*                                                                             * -*  Retour      : Adresse commune à deux branches.                             * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b) -{ -    vmpa_t result;                          /* Adresse trouvée à retourner */ -    size_t i;                               /* Boucle de parcours          */ - -    /* Valeur conceptuellement impossible à renvoyer */ -    result = VMPA_MAX; - -    //qsort(a->jumps, a->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); -    //qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); - -    for (i = 0; i < a->count && result == VMPA_MAX; i++) -        if (is_addr_in_branch(b, &a->jumps[i], false)) -            result = a->jumps[i]; - -    return result; - -} - - - -#include "../../arch/processor.h" - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : instrs = ensemble des instructions d'assemblage.             * -*                start  = adresse de début du bloc.                           * -*                end    = adresse de fin du bloc (exclusive).                 * -*                stop   = adresse d'arrêt en cas de saut ou VMPA_MAX.         * -*                ctx    = contexte de soutien à associer à l'opération.       * -*                                                                             * -*  Description : Procède à la décompilation basique d'un bloc déterminé.      * -*                                                                             * -*  Retour      : Instructions créées et enregistrées, ou NULL si erreur.      * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop, GDecContext *ctx) -{ -    GDecInstruction *result;                /* Instructions décompilées    */ -    GArchInstruction *iter;                 /* Boucle de parcours          */ - -    GDecInstruction *pite;                  /* IfThenElse potientiel...    */ - -    GArchInstruction **dests;               /* Instr. visée par une autre  */ -    InstructionLinkType *types;             /* Type de lien entre lignes   */ -    size_t dcount;                          /* Nombre de liens de dest.    */ - -    size_t i;                               /* Boucle de parcours          */ -    vmpa_t addr;                            /* Adresse de la destination   */ - -    branch_info true_branch;                /* Branche 'condition vraie'   */ -    branch_info false_branch;               /* Branche 'condition fausse'  */ -    GDecInstruction *true_dinstr;           /* Décompilation 'cond vraie'  */ -    GDecInstruction *false_dinstr;          /* Décompilation 'cond fausse' */ - -    vmpa_t next_addr;                       /* Prochaine instruction visée */ - -    GDecInstruction *first;                 /* Première décompilation      */ -    GDecInstruction *dinstr;                /* Nouvelle décompilation      */ - - -    GExeFormat *format;                     /* Format du binaire fourni    */ -    GArchProcessor *proc;                   /* Architecture du binaire     */ -    GDecContext *context;                   /* Contexte pour la décompil.  */ - - -    result = NULL; - -    //printf("[+] processing 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop); - -    for (iter = g_arch_instruction_find_by_address(instrs, start, true); -         iter != NULL; -         ) -    { -        /* On s'arrêter si l'instruction est déjà décompilée */ -        if (g_object_get_data(G_OBJECT(iter), "decomp_done") != NULL) break; -        g_object_set_data(G_OBJECT(iter), "decomp_done", iter); - -        pite = g_arch_instruction_decompile(iter, ctx); - -        g_arch_instruction_get_location(iter, NULL, NULL, &addr); -        //printf(" --- decomp %p @ 0x%08llx\n", pite, addr); - -        /* On n'approfondit que les chemins qui se séparent */ -        if (!g_arch_instruction_has_destinations(iter)) -        { -            iter = g_arch_instruction_get_next_iter(instrs, iter, end); -            continue; -        } - -        /* Adaptations en fonction du type de bifurcation */ - -        dcount = g_arch_instruction_get_destinations(iter, &dests, &types); - -        next_addr = 0; -        memset(&true_branch, 0, sizeof(branch_info)); -        memset(&false_branch, 0, sizeof(branch_info)); - -        for (i = 0; i < dcount; i++) -            switch (types[i]) -            { -                case ILT_EXEC_FLOW: -                case ILT_JUMP: -                    g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr); -                    break; - -                case ILT_JUMP_IF_TRUE: -                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); -                    find_next_jumps(instrs, addr, end, &true_branch); -                    break; - -                case ILT_JUMP_IF_FALSE: -                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); -                    find_next_jumps(instrs, addr, end, &false_branch); -                    break; - -                default: -                    next_addr = VMPA_MAX; -                    break; - -            } - -        if (next_addr == VMPA_MAX) -        { -            iter = g_arch_instruction_get_next_iter(instrs, iter, end); -            continue; -        } - -        else if (true_branch.count > 0 || false_branch.count > 0) -        { -            next_addr = compute_first_common_addr(&true_branch, &false_branch); -            next_addr = MIN(next_addr, end); - -            format = g_object_get_data(G_OBJECT(ctx), "format"); -            proc = get_arch_processor_from_format(G_EXE_FORMAT(format)); - -            context = g_arch_processor_get_decomp_context(proc); - -            g_object_set_data(G_OBJECT(context), "format", g_object_get_data(G_OBJECT(ctx), "format")); -            g_object_set_data(G_OBJECT(context), "routine", g_object_get_data(G_OBJECT(ctx), "routine")); -            g_dec_context_set_max_address(context, next_addr); - -            true_dinstr = build_decompiled_block(instrs, true_branch.jumps[0], -                                                 end, next_addr, context); - - -            context = g_arch_processor_get_decomp_context(proc); - -            g_object_set_data(G_OBJECT(context), "format", g_object_get_data(G_OBJECT(ctx), "format")); -            g_object_set_data(G_OBJECT(context), "routine", g_object_get_data(G_OBJECT(ctx), "routine")); -            g_dec_context_set_max_address(context, next_addr); - -            false_dinstr = build_decompiled_block(instrs, false_branch.jumps[0], -                                                  end, next_addr, context); - -            /* -            printf("{branch : %p (0x%08llx) | %p (0x%08llx)\n", -                   true_dinstr, true_branch.jumps[0], -                   false_dinstr, false_branch.jumps[0]); -            */ -            g_ite_instruction_set_branches(G_ITE_INSTRUCTION(pite), true_dinstr, false_dinstr); - -            if (next_addr == end) break; - -        } - -        /* Détermination du prochain point de chute */ - -        if (next_addr == stop) break; - -        iter = g_arch_instruction_find_by_address(instrs, next_addr, true); - -    } - - - - -    first = g_dec_context_get_decomp_instrs(ctx); - -    //printf(" ... context instr : %p\n", first); - -    for (dinstr = first; -         dinstr != NULL; -         dinstr = g_dec_instruction_get_next_iter(first, dinstr)) -    { -        if (result == NULL) result = g_expr_block_new(dinstr); -        else g_expr_block_add_item(G_EXPR_BLOCK(result), dinstr); - -    } - -    //printf(" ... return %p\n", result); - -    return result; - -} - -#endif | 
