summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-04-16 21:51:10 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-04-16 21:51:10 (GMT)
commitf21c18a6933036bd4cfec25446ac363c63997c13 (patch)
tree0f31a44028ed0892684c6485a598b3c672c1ca72 /src
parent90923fccb863075722d2ed17360e2c330b262e04 (diff)
Fixed some bugs in the basic blocks building.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@512 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src')
-rw-r--r--src/analysis/disass/loop.c14
-rw-r--r--src/analysis/disass/macro.c88
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;