summaryrefslogtreecommitdiff
path: root/src/analysis/disass/macro.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2013-01-10 22:47:37 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2013-01-10 22:47:37 (GMT)
commit221bcaeeb06415d501f9abbb9bc4b7d8339af1fe (patch)
tree243a1709589d3733d6525b0a143ecf0c539caae7 /src/analysis/disass/macro.c
parentc455057e634b30c3214a49db009bad5fd0c631ff (diff)
Simplified the decompilation process by using links between basic blocks.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@322 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/disass/macro.c')
-rw-r--r--src/analysis/disass/macro.c121
1 files changed, 69 insertions, 52 deletions
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index 2e5c0ee..8652b27 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -288,6 +288,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
size_t dcount; /* Nombre de liens de dest. */
size_t i; /* Boucle de parcours #1 */
GInstrBlock *block; /* Nouveau bloc mis en place */
+ GInstrBlock *parent; /* Mémorisation pour les liens */
GInstrBlock *group; /* Regroupement de blocs */
branch_info *cases_branches; /* Branches d'un aiguillage */
size_t cases_count; /* Nombre d'aiguillages */
@@ -375,7 +376,6 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
case ILT_EXEC_FLOW:
case ILT_JUMP:
-
block = g_flow_block_new(instrs, first, iter);
MACRO_MARK_AS_PROCESSED(first);
first = NULL;
@@ -428,21 +428,23 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
/* Post-traitements de ILT_CASE_JUMP */
if (cases_count > 0)
{
- if (first != NULL)
- {
- block = g_flow_block_new(instrs, first, iter);
- MACRO_MARK_AS_PROCESSED(first);
- first = NULL;
-
- DELAYED_BLOCK_ADDING(result, result_cached, block);
+ /**
+ * On doit clôturer le bloc renvoyant vers les branches de cas ici.
+ * Les sauts conditionnels sont normalement présents de façon exclusive,
+ * sauf pour les exceptions, qui sont traitées après.
+ */
+ block = g_flow_block_new(instrs, first, iter);
+ MACRO_MARK_AS_PROCESSED(first);
+ first = NULL;
- }
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
//printf(" --- cases --- start\n");
next_addr = compute_first_common_addr_in_group(cases_branches, cases_count);
//printf(" stop :: 0x%08llx\n", next_addr);
+ parent = block;
group = g_virtual_block_new();
for (j = 0; j < cases_count; j++)
@@ -460,7 +462,10 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
}
if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0)
+ {
DELAYED_BLOCK_ADDING(result, result_cached, group);
+ g_instr_block_set_links_block(parent, group);
+ }
else
g_object_unref(G_OBJECT(group));
@@ -471,38 +476,6 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
}
- /* Post-traitements de ILT_CATCH_EXCEPTION */
- if (excep_count > 0)
- {
- if (first != NULL)
- {
- block = g_flow_block_new(instrs, first, iter);
- MACRO_MARK_AS_PROCESSED(first);
- first = NULL;
-
- DELAYED_BLOCK_ADDING(result, result_cached, block);
-
- }
-
- for (j = 0; j < excep_count; j++)
- {
- stop_addr = compute_first_common_addr(&main_branch, &excep_branches[j]);
- //next_addr = MIN(next_addr, end);
-
- block = build_instruction_block(instrs, excep_branches[j].jumps[0], end, stop_addr);
-
- if (block != NULL)
-
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
-
- free(excep_branches[j].jumps);
-
- }
-
- free(excep_branches);
-
- }
-
if (next_addr == VMPA_MAX)
{
iter = g_arch_instruction_get_next_iter(instrs, iter, end);
@@ -514,16 +487,18 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
next_addr = compute_first_common_addr(&true_branch, &false_branch);
next_addr = MIN(next_addr, end);
- if (first != NULL)
- {
- block = g_flow_block_new(instrs, first, iter);
- MACRO_MARK_AS_PROCESSED(first);
- first = NULL;
-
- DELAYED_BLOCK_ADDING(result, result_cached, block);
+ /**
+ * On doit clôturer le bloc renvoyant vers les branches 'true' et 'false' ici.
+ * Les sauts conditionnels sont normalement présents de façon exclusive,
+ * sauf pour les exceptions, qui sont traitées après.
+ */
+ block = g_flow_block_new(instrs, first, iter);
+ MACRO_MARK_AS_PROCESSED(first);
+ first = NULL;
- }
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
+ parent = block;
group = g_virtual_block_new();
block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr);
@@ -535,7 +510,10 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block);
if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0)
+ {
DELAYED_BLOCK_ADDING(result, result_cached, group);
+ g_instr_block_set_links_block(parent, group);
+ }
else
g_object_unref(G_OBJECT(group));
@@ -546,6 +524,38 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
}
+ /* Post-traitements de ILT_CATCH_EXCEPTION */
+ if (excep_count > 0)
+ {
+ if (first != NULL)
+ {
+ block = g_flow_block_new(instrs, first, iter);
+ MACRO_MARK_AS_PROCESSED(first);
+ first = NULL;
+
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
+
+ }
+
+ for (j = 0; j < excep_count; j++)
+ {
+ stop_addr = compute_first_common_addr(&main_branch, &excep_branches[j]);
+ //next_addr = MIN(next_addr, end);
+
+ block = build_instruction_block(instrs, excep_branches[j].jumps[0], end, stop_addr);
+
+ if (block != NULL)
+
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
+
+ free(excep_branches[j].jumps);
+
+ }
+
+ free(excep_branches);
+
+ }
+
/* Détermination du prochain point de chute */
iter = g_arch_instruction_find_by_address(instrs, next_addr, true);
@@ -581,6 +591,7 @@ static bool print_blocks(GInstrBlock *blk, BlockVisitOrder order, int *pad)
{
int i;
vmpa_t start, end;
+ GInstrBlock *links;
if (order != BVO_OUT)
for (i = 0; i < *pad; i++)
@@ -589,7 +600,13 @@ static bool print_blocks(GInstrBlock *blk, BlockVisitOrder order, int *pad)
if (G_IS_FLOW_BLOCK(blk))
{
g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blk), &start, &end);
- printf(" - flow %p : 0x%08lx -> 0x%08lx\n", blk, start, end);
+ links = g_instr_block_get_links_block(blk);
+
+ if (links != NULL)
+ printf(" - flow %p : 0x%08lx -> 0x%08lx (links = %p)\n", blk, start, end, links);
+ else
+ printf(" - flow %p : 0x%08lx -> 0x%08lx\n", blk, start, end);
+
}
else
{
@@ -638,14 +655,14 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines,
end = start + g_binary_routine_get_size(routines[i]);
- //printf("==== %s ====\n", g_binary_routine_to_string(routines[i]));
+ printf("==== %s ====\n", g_binary_routine_to_string(routines[i]));
block = build_instruction_block(list, start, end, VMPA_MAX);
g_binary_routine_set_basic_blocks(routines[i], block);
- //g_instr_block_visit(block, (instr_block_visitor_cb)print_blocks, (int []){ 0 });
+ g_instr_block_visit(block, (instr_block_visitor_cb)print_blocks, (int []){ 0 });
gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);