diff options
Diffstat (limited to 'src/analysis')
| -rw-r--r-- | src/analysis/disass/loop.c | 14 | ||||
| -rw-r--r-- | src/analysis/disass/macro.c | 88 | 
2 files changed, 100 insertions, 2 deletions
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c index 44fa6d5..9a99bc4 100644 --- a/src/analysis/disass/loop.c +++ b/src/analysis/disass/loop.c @@ -227,6 +227,20 @@ static void track_loops_in_code(const GArchProcessor *proc, const mrange_t *rang          if (g_arch_instruction_is_return(iter))              break; +        /** +         * Afin de détecter les boucles le plus en aval possible, +         * on marque toutes les arrivées potentielles de boucles comme jalons. +         * Ainsi la détection se réalise sur l'ultime saut qui boucle effectivement. +         */ +        if (g_arch_instruction_has_sources(iter)) +        { +            addr = get_mrange_addr(irange); + +            if (is_new_exec_flow(flow, addr)) +                add_step_into_exec_flow(flow, addr); + +        } +          /* Analyse des destinations */          dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL); diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index 75032fa..96a3b25 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -877,7 +877,7 @@ static bool compute_first_common_addr_in_group(const branch_group *group, vmpa2t  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ - +#include "../../arch/instruction-int.h"  static GInstrBlock *build_instruction_block_simple(GArchInstruction *instrs, code_coverage *coverage, GArchInstruction **first, GArchInstruction *cur)  {      GInstrBlock *result;                    /* Regroupement à retourner    */ @@ -979,6 +979,59 @@ static GInstrBlock *build_instruction_blocks_ite(GArchInstruction *instrs, code_      GInstrBlock *block;                     /* Nouveau bloc mis en place   */      has_common = compute_first_common_addr(true_branch, false_branch, next); + + +    if (!has_common) +    { +        code_coverage *_sub_coverage;        /* Couverture pour les suivants*/ + + +        result = g_virtual_block_new(); + + +        /* Branche 'true' */ + +        _sub_coverage = dup_code_coverage(coverage, get_entry_to_branch(true_branch)); + +        block = build_instruction_blocks(instrs, _sub_coverage); + +        delete_code_coverage(_sub_coverage); + +        printf("===> !TRUE_BRANCH = %p\n", block); + +        if (block != NULL) +            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); + +        /* Branche 'false' */ + +        _sub_coverage = dup_code_coverage(coverage, get_entry_to_branch(false_branch)); + +        block = build_instruction_blocks(instrs, _sub_coverage); + +        delete_code_coverage(_sub_coverage); + +        printf("===> !FALSE_BRANCH = %p\n", block); + +        if (block != NULL) +            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); + +        /* Conclusion */ + +        if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(result)) == 0) +        { +            g_object_unref(G_OBJECT(result)); +            result = NULL; +        } + +        return result; + + + + +    } + +    assert(has_common); +      if (!has_common) printf("   === nothing in common\n");      if (!has_common) return NULL; @@ -1153,7 +1206,7 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove          if (code_coverage_stop_here(coverage, addr)) break; -        /* On s'arrêter si l'instruction est déjà décompilée */ +        /* On s'arrête si l'instruction est déjà décompilée */          if (is_range_processed_in_coverage(coverage, range)) break;          if (first == NULL) @@ -1161,6 +1214,13 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove          last = iter; +        /** +         * On s'arrête également en fin de procédure. +         * L'expérience montre qu'il peut y avoir plusieurs fins dans une routine, +         * et donc des fins en milieu de couverture de cette même routine. +         */ +        if (g_arch_instruction_is_return(iter)) break; +          /* On n'approfondit que les chemins qui se séparent */          if (!g_arch_instruction_has_destinations(iter))          { @@ -1211,6 +1271,30 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove                      break; +                case ILT_LOOP: +                    /** +                     * Lorsque l'on désassemble un flot d'instructions et que l'on rencontre +                     * une amorce de boucle, il y a deux cas de figure : +                     * +                     *    - soit il s'agit d'un ancien JUMP, et la reprise du désassemblage +                     *      se fera à partir de l'adresse ciblée. +                     * +                     *    - soit il s'agit d'un branchement conditionnel dont une des branches +                     *      conduit à un rebouclage. Le désassemblage s'arrête alors pour la +                     *      partie en boucle car il n'y a plus d'adresse commune pour la suite. +                     * +                     * Il reste donc à forcer une coupure dans le cas suivant : +                     * +                     *       ... +                     *       jmp xxxx +                     *    loc: +                     *       ... +                     * +                     * Il suffit de ne pas initialiser 'next_addr' et de laisser la main à d'éventuelles +                     * autres destinations voisines. +                     */ +                     break; +                  case ILT_CASE_JUMP:                      branch = extend_branch_group(&cases_branches);                      break;  | 
