summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/macro.c97
1 files changed, 88 insertions, 9 deletions
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index 14dad95..993f70f 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -52,7 +52,7 @@ typedef struct _branch_info
/* Indique si une adresse est retenue comme point de passage. */
-static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool);
+static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool, size_t *);
/* Identifie les différents points de passage d'une branche. */
static void find_next_jumps(GArchInstruction *, vmpa_t, vmpa_t, branch_info *);
@@ -73,6 +73,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t,
* Paramètres : info = informations à consulter. *
* addr = adresse à rechercher. *
* fast = autorise une recherche rapide. *
+* pos = enregistrement de la position de la trouvaille. [OUT] *
* *
* Description : Indique si une adresse est retenue comme point de passage. *
* *
@@ -82,7 +83,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t,
* *
******************************************************************************/
-static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast)
+static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast, size_t *pos)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
@@ -92,12 +93,20 @@ static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool
if (!fast)
for (i = 0; i < info->count && !result; i++)
+ {
result = (info->jumps[i] == *addr);
+ if (result && pos != NULL)
+ *pos = i;
+ }
else
{
ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
result = (ptr != NULL);
+
+ if (result && pos != NULL)
+ *pos = (ptr - ((void *)info->jumps)) / sizeof(vmpa_t);
+
}
return result;
@@ -130,7 +139,7 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,
vmpa_t addr; /* Adresse de la destination */
/* On évite de boucler... */
- if (is_addr_in_branch(info, &start, false))
+ if (is_addr_in_branch(info, &start, false, NULL))
return;
info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
@@ -174,7 +183,7 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,
}
/* Si on termine... */
- if (iter != NULL && !is_addr_in_branch(info, &end, false))
+ if (iter != NULL && !is_addr_in_branch(info, &end, false, NULL))
{
info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
info->jumps[info->count - 1] = end;
@@ -208,7 +217,7 @@ static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b)
//qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
for (i = 0; i < a->count && result == VMPA_MAX; i++)
- if (is_addr_in_branch(b, &a->jumps[i], false))
+ if (is_addr_in_branch(b, &a->jumps[i], false, NULL))
result = a->jumps[i];
return result;
@@ -247,7 +256,7 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t
keep = true;
for (j = 1; j < count && keep; j++)
- keep = is_addr_in_branch(&list[j], &list[0].jumps[i], false);
+ keep = is_addr_in_branch(&list[j], &list[0].jumps[i], false, NULL);
if (keep)
result = list[0].jumps[i];
@@ -259,6 +268,51 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t
}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste d'ensembles de jalons à parcourir. *
+* count = taille de cette liste. *
+* *
+* Description : Retrouve le point de ralliement entre un groupe de branches. *
+* *
+* Retour : Adresse commune aux branches. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static vmpa_t avoid_cases_common_part(const branch_info *list, size_t cur, size_t count, vmpa_t max)
+{
+ vmpa_t result; /* Adresse trouvée à retourner */
+ size_t found_pos; /* Plus petit tronc commun */
+ size_t i; /* Boucle de parcours */
+ size_t pos; /* Emplacement du cas commun */
+
+ result = max;
+
+ found_pos = list[cur].count;
+
+ for (i = 0; i < count; i++)
+ {
+ if (i == cur) continue;
+
+ if (is_addr_in_branch(&list[cur], &list[i].jumps[0], false, &pos))
+ {
+ if (pos < found_pos)
+ result = list[i].jumps[0];
+ }
+
+ }
+
+ return result;
+
+}
+
+
+
/******************************************************************************
* *
* Paramètres : instrs = ensemble des instructions d'assemblage. *
@@ -447,13 +501,38 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta
parent = block;
group = g_virtual_block_new();
+ do
+ {
+ size_t _i, _j;
+
+ for (_i = 0; _i < cases_count; _i++)
+ {
+ printf(" [case %d] : ", _i);
+
+ for (_j = 0; _j < cases_branches[_i].count; _j++)
+ printf("0x%08lx ", cases_branches[_i].jumps[_j]);
+
+ printf("\n");
+
+ }
+
+ } while (0);
+
+
for (j = 0; j < cases_count; j++)
{
- printf(" ## %zu...", j);
+ printf(" ## %zu start=0x%08lx (0x%08lx)...\n", j, cases_branches[j].jumps[0],
+ next_addr);
+
+ //block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, next_addr);
+
+ //next_addr = avoid_cases_common_part(cases_branches, j, cases_count, next_addr);
- block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, next_addr);
+ block = build_instruction_block(instrs, cases_branches[j].jumps[0], end,
+ avoid_cases_common_part(cases_branches, j, cases_count, next_addr));
- printf(" %p\n", block);
+ printf(" %p (0x%08lx)\n", block,
+ avoid_cases_common_part(cases_branches, j, cases_count, next_addr));
if (block != NULL)