summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/macro.c125
1 files changed, 96 insertions, 29 deletions
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index 46dc0d3..2e5c0ee 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -277,6 +277,7 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t
static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop)
{
GInstrBlock *result; /* Regroupement à retourner */
+ GInstrBlock *result_cached; /* Temporisation pour unicité */
branch_info main_branch; /* Flot d'exécution complet */
GArchInstruction *first; /* Première instruction */
GArchInstruction *last; /* Dernière instruction */
@@ -287,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 *group; /* Regroupement de blocs */
branch_info *cases_branches; /* Branches d'un aiguillage */
size_t cases_count; /* Nombre d'aiguillages */
branch_info true_branch; /* Branche 'condition vraie' */
@@ -298,6 +300,32 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
vmpa_t stop_addr; /* Adresse de fin de bloc */
result = NULL;
+ result_cached = NULL;
+
+ /**
+ * Procédure d'ajout de blocs : pour le premier, on conserve le bloc en mémoire
+ * et on attend. Si rien ne suit, il constitura l'unique retour. Sinon, on
+ * l'ajoute à partir de la sauvegarde, et le reste suit.
+ */
+#define DELAYED_BLOCK_ADDING(res, cache, blk) \
+ do \
+ { \
+ if (res == NULL) \
+ { \
+ if (cache == NULL) \
+ cache = blk; \
+ else \
+ { \
+ res = g_virtual_block_new(); \
+ g_virtual_block_add_child(G_VIRTUAL_BLOCK(res), cache); \
+ } \
+ } \
+ \
+ if (res != NULL) \
+ g_virtual_block_add_child(G_VIRTUAL_BLOCK(res), blk); \
+ \
+ } \
+ while (0)
first = NULL;
last = NULL;
@@ -347,14 +375,13 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
case ILT_EXEC_FLOW:
case ILT_JUMP:
- if (result == NULL)
- result = g_virtual_block_new();
block = g_flow_block_new(instrs, first, iter);
MACRO_MARK_AS_PROCESSED(first);
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
first = NULL;
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
+
g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr);
break;
@@ -401,15 +428,14 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
/* Post-traitements de ILT_CASE_JUMP */
if (cases_count > 0)
{
- if (result == NULL)
- result = g_virtual_block_new();
-
if (first != NULL)
{
block = g_flow_block_new(instrs, first, iter);
MACRO_MARK_AS_PROCESSED(first);
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
first = NULL;
+
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
+
}
//printf(" --- cases --- start\n");
@@ -417,6 +443,8 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
next_addr = compute_first_common_addr_in_group(cases_branches, cases_count);
//printf(" stop :: 0x%08llx\n", next_addr);
+ group = g_virtual_block_new();
+
for (j = 0; j < cases_count; j++)
{
//printf(" ## %zu\n", j);
@@ -425,12 +453,17 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
if (block != NULL)
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+ g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block);
free(cases_branches[j].jumps);
}
+ if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0)
+ DELAYED_BLOCK_ADDING(result, result_cached, group);
+ else
+ g_object_unref(G_OBJECT(group));
+
//printf(" --- cases --- end\n");
@@ -441,15 +474,14 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
/* Post-traitements de ILT_CATCH_EXCEPTION */
if (excep_count > 0)
{
- if (result == NULL)
- result = g_virtual_block_new();
-
if (first != NULL)
{
block = g_flow_block_new(instrs, first, iter);
MACRO_MARK_AS_PROCESSED(first);
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
first = NULL;
+
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
+
}
for (j = 0; j < excep_count; j++)
@@ -482,28 +514,30 @@ 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 (result == NULL)
- result = g_virtual_block_new();
-
if (first != NULL)
{
block = g_flow_block_new(instrs, first, iter);
MACRO_MARK_AS_PROCESSED(first);
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
first = NULL;
- }
- block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr);
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
- if (block != NULL)
+ }
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+ group = g_virtual_block_new();
- block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr);
+ block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr);
+ if (block != NULL)
+ g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block);
- if (block != NULL)
+ block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr);
+ if (block != NULL)
+ g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block);
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+ if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0)
+ DELAYED_BLOCK_ADDING(result, result_cached, group);
+ else
+ g_object_unref(G_OBJECT(group));
free(true_branch.jumps);
free(false_branch.jumps);
@@ -526,21 +560,51 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
MACRO_MARK_AS_PROCESSED(first);
//printf("--close!--\n");
- if (result == NULL)
- result = block;
- else
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+ DELAYED_BLOCK_ADDING(result, result_cached, block);
+
}
}
- if (result == NULL)
+ if ((result != NULL ? result : result_cached) == NULL)
{
//printf("WARNING :: null !\n");
//exit(0);
}
- return result;
+ return (result != NULL ? result : result_cached);
+
+}
+
+
+static bool print_blocks(GInstrBlock *blk, BlockVisitOrder order, int *pad)
+{
+ int i;
+ vmpa_t start, end;
+
+ if (order != BVO_OUT)
+ for (i = 0; i < *pad; i++)
+ printf(" ");
+
+ 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);
+ }
+ else
+ {
+ if (order != BVO_OUT)
+ {
+ printf(" - virtual %p\n", blk);
+ *pad += 1;
+ }
+ else *pad -= 1;
+
+ }
+
+ fflush(NULL);
+
+ return true;
}
@@ -580,6 +644,9 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines,
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 });
+
gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
}