diff options
Diffstat (limited to 'src/analysis/disass')
-rw-r--r-- | src/analysis/disass/macro.c | 97 |
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) |