From f21c18a6933036bd4cfec25446ac363c63997c13 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 16 Apr 2015 21:51:10 +0000 Subject: Fixed some bugs in the basic blocks building. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@512 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 6 ++++ src/analysis/disass/loop.c | 14 ++++++++ src/analysis/disass/macro.c | 88 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05c70ad..6830213 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +15-04-16 Cyrille Bagard + + * src/analysis/disass/loop.c: + * src/analysis/disass/macro.c: + Fix some bugs in the basic blocks building. + 15-04-12 Cyrille Bagard * src/glibext/gbufferline.c: 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; -- cgit v0.11.2-87-g4458