diff options
Diffstat (limited to 'src/analysis/disass/macro.c')
-rw-r--r-- | src/analysis/disass/macro.c | 1542 |
1 files changed, 268 insertions, 1274 deletions
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index acb210a..d9d20ee 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -25,8 +25,6 @@ #include <assert.h> -#include <malloc.h> -#include <stdlib.h> #include "../blocks/flow.h" @@ -34,115 +32,6 @@ -/* ------------------------ COUVERTURE D'UNE ZONE A DECOUPER ------------------------ */ - - -/* Bornes d'une zone à couvrir */ -typedef struct _code_coverage -{ - bool initial; /* Couverture racine ? */ - - mrange_t range; /* Couverture totale */ - - vmpa2t start; /* Position butoir de début */ - - vmpa2t *ends; /* Positions butoir de fin */ - size_t ends_count; /* Quantité de fins possibles */ - - unsigned long *processed; /* Octets traités dans la zone */ - size_t allocated; /* Taille de la cartographie */ - -} code_coverage; - - -/* Met en place les délimitations d'une zone de code. */ -static code_coverage *create_code_coverage(const mrange_t *); - -/* Crée une copie d'une couverture de zone de code. */ -static code_coverage *dup_code_coverage(const code_coverage *, const vmpa2t *); - -/* Détruit des délimitations d'une zone de code. */ -static void delete_code_coverage(code_coverage *); - -/* Précise la position de départ courante pour une analyse. */ -static const vmpa2t *get_code_coverage_start_addr(const code_coverage *); - -/* Indique si une adresse est hors zone ou non. */ -static bool code_coverage_stop_here(const code_coverage *coverage, const vmpa2t *); - -/* Ajoute une adresse butoir pour la zone à couvrir. */ -static bool add_ending_address_code_coverage(code_coverage *, const vmpa2t *); - -/* Indique si une zone donnée n'a jamais été traitée ou non. */ -static bool is_range_processed_in_coverage(const code_coverage *, const mrange_t *); - -/* Marque une série d'octets comme ayant été traités. */ -static void mark_range_as_processed_in_coverage(code_coverage *, const GArchInstruction *); - - - -/* ------------------------- SUIVI DES FLOTS D'INSTRUCTIONS ------------------------- */ - - -/* Indications sur une branche */ -typedef struct _branch_info -{ - vmpa2t *hops; /* Jalons de la branche */ - size_t count; /* Quantité de ces jalons */ - - vmpa2t entry; /* Valeur du jalon d'entrée */ - -} branch_info; - - -/* Initialise le suivi d'une branche de flot d'exécution. */ -static void init_branch_info(branch_info *); - -/* Acte la fin d'un suivi d'une branche de flot d'exécution. */ -static void clean_branch_info(branch_info *); - -/* Indique si une adresse est retenue comme point de passage. */ -static bool is_addr_in_branch(const branch_info *, const vmpa2t *); - -/* Ajoute un nouveau jalon dans l'exécution d'une branche. */ -static bool add_hop_into_branch(branch_info *, const vmpa2t *); - -/* Retourne le premier point d'exécution d'une branche donnée. */ -static const vmpa2t *get_entry_to_branch(const branch_info *); - -/* Identifie les différents points de passage d'une branche. */ -static void find_next_hops(GArchProcessor *, const vmpa2t *, const code_coverage *, branch_info *); - -/* Retrouve le point de ralliement entre deux branches. */ -static bool compute_first_common_addr(const branch_info *, const branch_info *, vmpa2t *); - - -/* Groupement de branches et d'indications */ -typedef struct _branch_group -{ - branch_info *branches; /* Liste des branches */ - size_t count; /* Taille de cette liste */ - -} branch_group; - - -/* Initialise le suivi d'un ensemble de branches. */ -static void init_branch_group(branch_group *); - -/* Acte la fin d'un suivi d'un ensemble de branches. */ -static void clean_branch_group(branch_group *); - -/* Ajoute une branche à un ensemble de branches en place. */ -static branch_info *extend_branch_group(branch_group *); - -/* Retrouve le point de ralliement entre un groupe de branches. */ -static bool compute_first_common_addr_in_group(const branch_group *, vmpa2t *); - - - -/* --------------------------- DECOUPAGE EN BLOCS DE CODE --------------------------- */ - - /** * 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 @@ -169,389 +58,64 @@ static bool compute_first_common_addr_in_group(const branch_group *, vmpa2t *); while (0) -/* Procède à la création d'un bloc d'instructions simple. */ -static GInstrBlock *build_instruction_block_simple(GArchProcessor *, code_coverage *, GArchInstruction **, GArchInstruction *); - -/* Procède à la définition d'un bloc d'instructions selectif. */ -static GInstrBlock *build_instruction_blocks_case(GArchProcessor *, code_coverage *, const branch_group *, vmpa2t *); - -/* Procède à la définition d'un bloc d'instruction if/then/else. */ -static GInstrBlock *build_instruction_blocks_ite(GArchProcessor *, code_coverage *, const branch_info *, const branch_info *, vmpa2t *); - -/* Procède à la définition d'un bloc d'instructions d'exception. */ -static void add_instruction_blocks_except(GInstrBlock **, GInstrBlock **, GArchProcessor *, code_coverage *, const branch_group *, const branch_info *); +/* Détermine la couverture d'un ensemble de chemins. */ +static bitfield_t *compute_other_paths_mask(const dragon_knight *, GArchInstruction **, InstructionLinkType *, size_t, size_t); /* Procède à la définition de bloc regroupant des instructions. */ -static GInstrBlock *build_instruction_blocks(GArchProcessor *, code_coverage *); - - - -/* ---------------------------------------------------------------------------------- */ -/* COUVERTURE D'UNE ZONE A DECOUPER */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : range = définition de la zone à couvrir. * -* * -* Description : Met en place les délimitations d'une zone de code. * -* * -* Retour : Couverture d'une zone de code. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static code_coverage *create_code_coverage(const mrange_t *range) -{ - code_coverage *result; /* Couverture à retourner */ - phys_t length; /* Taille de la zone couverte */ - size_t requested; /* Nombre de mots à allouer */ +static GInstrBlock *build_instruction_blocks(GArchProcessor *, const dragon_knight *, dragon_node *, const bitfield_t *, bitfield_t *, size_t *); - result = (code_coverage *)calloc(1, sizeof(code_coverage)); - - result->initial = true; - - copy_mrange(&result->range, range); - - copy_vmpa(&result->start, get_mrange_addr(range)); - - result->ends = (vmpa2t *)calloc(1, sizeof(vmpa2t)); - result->ends_count = 1; - - compute_mrange_end_addr(range, &result->ends[0]); - - length = get_mrange_length(range); - - requested = length / sizeof(unsigned long); - if (length % sizeof(unsigned long) != 0) requested++; - - result->processed = (unsigned long *)calloc(requested, sizeof(unsigned long)); - result->allocated = requested; - - return result; - -} /****************************************************************************** * * -* Paramètres : src = informations de couverture à consulter. * -* new = nouvelle position de début, plus profonde. * +* Paramètres : knight = représentation de la complexité du code. * +* dests = instructions pointées à consulter. * +* types = types associés aux destinations. * +* dcount = nombre de destinations. * +* current = indice de la destionation courante. * * * -* Description : Crée une copie d'une couverture de zone de code. * +* Description : Détermine la couverture d'un ensemble de chemins. * * * -* Retour : Couverture d'une zone de code copiée. * +* Retour : Champ de bits mis en place. * * * * Remarques : - * * * ******************************************************************************/ -static code_coverage *dup_code_coverage(const code_coverage *src, const vmpa2t *new) +static bitfield_t *compute_other_paths_mask(const dragon_knight *knight, GArchInstruction **dests, InstructionLinkType *types, size_t dcount, size_t current) { - code_coverage *result; /* Couverture à retourner */ + bitfield_t *result; /* Couverture à retourner */ + size_t length; /* Taille du champ de bits */ + InstructionLinkType target; /* Type de noeud à cibler */ size_t i; /* Boucle de parcours */ + dragon_node *node; /* Noeud à considérer */ - result = (code_coverage *)calloc(1, sizeof(code_coverage)); - - result->initial = false; - - copy_mrange(&result->range, &src->range); - - copy_vmpa(&result->start, new); - - result->ends = (vmpa2t *)calloc(src->ends_count, sizeof(vmpa2t)); - result->ends_count = src->ends_count; - - for (i = 0; i < result->ends_count; i++) - copy_vmpa(&result->ends[i], &src->ends[i]); - - /** - * Les blocs produits par le découpage sont à accès global, et ne sont donc pas - * la propriété d'une branche particulière. - * Il ne faut donc pas créer deux blocs identiques à partir de deux chemins - * différents ; aussi on partage la couverture de code plutôt que la copier. - * Et, par ailleurs, c'est plus simple & efficace. - */ - - result->processed = src->processed; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : coverage = structure à libérer de la mémoire. * -* * -* Description : Détruit des délimitations d'une zone de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void delete_code_coverage(code_coverage *coverage) -{ - free(coverage->ends); - - if (coverage->initial) - free(coverage->processed); - - free(coverage); - -} - - -/****************************************************************************** -* * -* Paramètres : coverage = informations de couverture à consulter. * -* * -* Description : Précise la position de départ courante pour une analyse. * -* * -* Retour : Position de départ pour une analyse d'une portion de zone. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const vmpa2t *get_code_coverage_start_addr(const code_coverage *coverage) -{ - return &coverage->start; - -} - - -/****************************************************************************** -* * -* Paramètres : coverage = informations de couverture à consulter. * -* addr = localisation à tester. * -* * -* Description : Indique si une adresse est hors zone ou non. * -* * -* Retour : true si l'adresse ne doit pas être couverte, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool code_coverage_stop_here(const code_coverage *coverage, const vmpa2t *addr) -{ - void *ptr; /* Résultat des recherches */ - - if (!mrange_contains_addr(&coverage->range, addr)) - return true; - - ptr = bsearch(addr, coverage->ends, coverage->ends_count, - sizeof(vmpa2t), (__compar_fn_t)cmp_vmpa); - - return (ptr != NULL); - -} + get_dragon_knight_content(knight, NULL, &length); + result = create_bit_field(length, false); -/****************************************************************************** -* * -* Paramètres : coverage = informations de couverture à compléter. * -* addr = localisation à ajouter. * -* * -* Description : Ajoute une adresse butoir pour la zone à couvrir. * -* * -* Retour : true si une insertion a été effectuée, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ + target = types[current]; -static bool add_ending_address_code_coverage(code_coverage *coverage, const vmpa2t *addr) -{ - bool result; /* Bilan à retourner */ + if (target == ILT_JUMP_IF_TRUE) + target = ILT_JUMP_IF_FALSE; + else if (target == ILT_JUMP_IF_FALSE) + target = ILT_JUMP_IF_TRUE; - result = !code_coverage_stop_here(coverage, addr); + assert(target == ILT_CASE_JUMP || target == ILT_JUMP_IF_TRUE || target == ILT_JUMP_IF_FALSE); - if (result) + for (i = 0; i < dcount; i++) { - coverage->ends = (vmpa2t *)realloc(coverage->ends, ++coverage->ends_count * sizeof(vmpa2t)); - - copy_vmpa(&coverage->ends[coverage->ends_count - 1], addr); - - qsort(coverage->ends, coverage->ends_count, sizeof(vmpa2t), (__compar_fn_t)cmp_vmpa); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : coverage = informations de couverture à consulter. * -* range = zone à interroger. * -* * -* Description : Indique si une zone donnée n'a jamais été traitée ou non. * -* * -* Retour : true si l'aire visée est vierge, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool is_range_processed_in_coverage(const code_coverage *coverage, const mrange_t *range) -{ - bool result; /* Bilan à renvoyer */ - phys_t diff; /* Décalage à appliquer */ - size_t index; /* Cellule de tableau visée */ - unsigned int remaining; /* Nombre de bits restants */ - - diff = compute_vmpa_diff(get_mrange_addr(&coverage->range), get_mrange_addr(range)); - assert(diff < get_mrange_length(&coverage->range)); - - index = diff / (sizeof(unsigned long) * 8); - remaining = diff % (sizeof(unsigned long) * 8); - - result = ((coverage->processed[index] & (1ul << remaining)) != 0); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : coverage = informations de couverture à consulter. * -* instr = instruction couvrant la zone à interroger. * -* * -* Description : Marque une série d'octets comme ayant été traités. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void mark_range_as_processed_in_coverage(code_coverage *coverage, const GArchInstruction *instr) -{ - const mrange_t *range; /* Emplacement d'instruction */ - phys_t diff; /* Décalage à appliquer */ - size_t index; /* Cellule de tableau visée */ - unsigned int remaining; /* Nombre de bits restants */ - - range = g_arch_instruction_get_range(instr); - - diff = compute_vmpa_diff(get_mrange_addr(&coverage->range), get_mrange_addr(range)); - assert(diff < get_mrange_length(&coverage->range)); - - index = diff / (sizeof(unsigned long) * 8); - remaining = diff % (sizeof(unsigned long) * 8); - - coverage->processed[index] |= (1ul << remaining); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* SUIVI DES FLOTS D'INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : info = informations à initialiser. * -* * -* Description : Initialise le suivi d'une branche de flot d'exécution. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void init_branch_info(branch_info *info) -{ - memset(info, 0, sizeof(branch_info)); - -} - - -/****************************************************************************** -* * -* Paramètres : info = informations à nettoyer. * -* * -* Description : Acte la fin d'un suivi d'une branche de flot d'exécution. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void clean_branch_info(branch_info *info) -{ - if (info->hops != NULL) - free(info->hops); - -} - - -/****************************************************************************** -* * -* Paramètres : info = informations à consulter. * -* addr = position à rechercher. * -* * -* Description : Indique si une adresse est retenue comme point de passage. * -* * -* Retour : true si le jalon est déjà dans la liste, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool is_addr_in_branch(const branch_info *info, const vmpa2t *addr) -{ - void *ptr; /* Résultat des recherches */ - - ptr = bsearch(addr, info->hops, info->count, - sizeof(vmpa2t), (__compar_fn_t)cmp_vmpa); - - return (ptr != NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : info = informations de flot à compléter. * -* addr = localisation à ajouter. * -* * -* Description : Ajoute un nouveau jalon dans l'exécution d'une branche. * -* * -* Retour : true si une insertion a été effectuée, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool add_hop_into_branch(branch_info *info, const vmpa2t *addr) -{ - bool result; /* Bilan à retourner */ - - result = !is_addr_in_branch(info, addr); - - if (result) - { - if (info->count == 0) - copy_vmpa(&info->entry, addr); + if (i == current) + continue; - info->hops = (vmpa2t *)realloc(info->hops, ++info->count * sizeof(vmpa2t)); + if (types[i] == target) + { + node = find_knight_node_for_instruction(knight, false, dests[i]); + if (node == NULL) continue; - copy_vmpa(&info->hops[info->count - 1], addr); + or_bit_field(result, get_paths_bits(node)); - qsort(info->hops, info->count, sizeof(vmpa2t), (__compar_fn_t)cmp_vmpa); + } } @@ -562,983 +126,413 @@ static bool add_hop_into_branch(branch_info *info, const vmpa2t *addr) /****************************************************************************** * * -* Paramètres : info = informations de flot à consulter. * -* * -* Description : Retourne le premier point d'exécution d'une branche donnée. * -* * -* Retour : Point de départ d'une branche. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const vmpa2t *get_entry_to_branch(const branch_info *info) -{ - return &info->entry; - -} - - -/****************************************************************************** -* * * Paramètres : proc = ensemble des instructions d'assemblage. * -* start = position du début de bloc. * -* coverage = liste des adresses de fin butoir. * -* count = nombre de sauts détectés. [OUT] * +* coverage = délimitations de la zone à couvrir. * * * -* Description : Identifie les différents points de passage d'une branche. * +* Description : Procède à la définition de bloc regroupant des instructions. * * * -* Retour : Jalons dans le flot d'exécution. * +* Retour : Bloc créé et enregistré, ou NULL si erreur. * * * * Remarques : - * * * ******************************************************************************/ -static void find_next_hops(GArchProcessor *proc, const vmpa2t *start, const code_coverage *coverage, branch_info *info) +static GInstrBlock *build_instruction_blocks(GArchProcessor *proc, const dragon_knight *knight, dragon_node *node, const bitfield_t *stop, bitfield_t *converted, size_t *next) { - GArchInstruction *iter; /* Boucle de parcours #1 */ - const mrange_t *range; /* Emplacement d'instruction */ + GInstrBlock *result; /* Regroupement à retourner */ + GInstrBlock *result_cached; /* Temporisation pour unicité */ + size_t id; /* Indice du bit associé */ + GArchInstruction *first; /* Première instruction de bloc*/ + GArchInstruction *last; /* Dernière instruction de bloc*/ + GInstrBlock *block; /* Nouveau bloc mis en place */ + bitfield_t *local_stop; /* Arrêts pour les sous-blocs */ + bitfield_t *others; /* Couvertures des autres */ GArchInstruction **dests; /* Instr. visée par une autre */ InstructionLinkType *types; /* Type de lien entre lignes */ size_t dcount; /* Nombre de liens de dest. */ - size_t i; /* Boucle de parcours #2 */ - size_t not_handled; /* Nombre d'éléments écartés */ + size_t i; /* Boucle de parcours */ + dragon_node *target; /* Noeud suivant à traiter */ + GInstrBlock *group; /* Regroupement à retourner */ + GInstrBlock *group_cached ; /* Temporisation pour unicité */ - printf(" ---- FN [ %p ] ---------------------------\n", info); + result = NULL; + result_cached = NULL; - printf("CONTAINS ? %d\n", mrange_contains_addr(&coverage->range, start)); - /* Si la position est déjà présente, on évite de boucler... */ - if (!add_hop_into_branch(info, start)) - { - printf(" ++ !add 0x%08x\n", (unsigned int)start->virtual); - return; - } - else - printf(" ++ add 0x%08x\n", (unsigned int)start->virtual); - /* On suit le flot jusqu'à la prochaine bifurcation */ - for (iter = g_arch_processor_find_instr_by_address(proc, start); - iter != NULL; - iter = g_arch_processor_get_next_instr(proc, iter)) + while (1) { - range = g_arch_instruction_get_range(iter); + id = get_dragon_knight_node_index(knight, node); - - if (code_coverage_stop_here(coverage, get_mrange_addr(range))) - printf(" ++ stop here 0x%08x\n", (unsigned int)range->addr.virtual); - - if (code_coverage_stop_here(coverage, get_mrange_addr(range))) - break; + /** + * Si on traite une des branches Vrai/Faux et que cette branche est vide, + * on doit s'arrêter. + */ - if (g_arch_instruction_has_sources(iter)) - add_hop_into_branch(info, get_mrange_addr(range)); + //printf("=== [%d] PROCESSING NODE %u (0x%x) in 0x%08x\n", fff, id, 1 << id, gfw(stop)); + if (test_in_bit_field(stop, id, 1)) + { + //printf(" -- STOP\n"); + *next = id; + break; + } - if (g_arch_instruction_get_flags(iter) & AIF_RETURN_POINT) - printf(" ++ return 0x%08x\n", (unsigned int)range->addr.virtual); + /** + * Si le bloc a déjà été converti, on arrête la conversion pour la branche courante. + * + * Cela peut correspondre à la situation suivante quand on revient sur le bloc + * inférieur droit : + * + * ====== + * / \ + * === | + * / \ | + * | `.| + * | || + * === === + */ - if (g_arch_instruction_get_flags(iter) & AIF_RETURN_POINT) + if (test_in_bit_field(converted, id, 1)) { - iter = NULL; + //printf(" HALT\n"); + + *next = 0; break; } + /* Constitution et ajout d'un bloc */ + + get_dragon_node_bounding_instructions(node, &first, &last); + /* - if (!g_arch_instruction_has_destinations(iter)) - printf(" ++ no dest 0x%08x\n", (unsigned int)range->addr.virtual); + printf(" -- [%d] process block %u @ 0x%08x <-> 0x%08x\n", + fff, (unsigned int)id, + (unsigned int)first->range.addr.virtual, + (unsigned int)last->range.addr.virtual); */ - if (!g_arch_instruction_has_destinations(iter)) - continue; + block = g_flow_block_new(proc, first, last); + DELAYED_BLOCK_ADDING(result, result_cached, block); - printf(" ++ dcount 0x%08x\n", (unsigned int)range->addr.virtual); + set_in_bit_field(converted, id, 1); - dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL); + /* Détermination du prochain arrêt */ - not_handled = 0; + local_stop = create_bit_field_from(stop, true); - for (i = 0; i < dcount; i++) - { - range = g_arch_instruction_get_range(dests[i]); + others = NULL; + dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL); + + for (i = 0; i < dcount && others == NULL; i++) switch (types[i]) { case ILT_EXEC_FLOW: case ILT_JUMP: - case ILT_CASE_JUMP: - case ILT_JUMP_IF_TRUE: - case ILT_JUMP_IF_FALSE: - find_next_hops(proc, get_mrange_addr(range), coverage, info); break; case ILT_LOOP: - add_hop_into_branch(info, get_mrange_addr(range)); break; - default: - not_handled++; - break; - - } - - } - - if (not_handled < dcount) - break; + case ILT_CASE_JUMP: + case ILT_JUMP_IF_TRUE: + case ILT_JUMP_IF_FALSE: - } + target = find_knight_node_for_instruction(knight, false, dests[i]); + if (target == NULL) break; - /* Si on termine... */ - if (iter != NULL) add_hop_into_branch(info, get_mrange_addr(range)); + id = get_dragon_knight_node_index(knight, target); - printf(" ------- [ %p ] ---\n", info); + others = compute_other_paths_mask(knight, dests, types, dcount, i); -} + /** + * Si une patte est contenue dans une autre, on place la branche + * incluse comme borne de fin. + */ + if (test_in_bit_field(others, id, 1)) + { + reset_all_in_bit_field(others); + set_in_bit_field(others, id, 1); + } + /** + * Sinon la borne de fin est la sortie commune. + */ + else + { + delete_bit_field(others); + others = NULL; -/****************************************************************************** -* * -* Paramètres : a = premier ensemble de jalons à parcourir. * -* b = second ensemble de jalons à parcourir. * -* c = éventuelle adresse commune à deux branches. * -* * -* Description : Retrouve le point de ralliement entre deux branches. * -* * -* Retour : true si une position commune a pu être trouvée, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ + and_bit_field(local_stop, get_paths_bits(target)); -static bool compute_first_common_addr(const branch_info *a, const branch_info *b, vmpa2t *c) -{ - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - - result = false; + } + break; - printf("....................\n"); + case ILT_CATCH_EXCEPTION: + break; - printf(" A :: "); - for (i = 0; i < a->count; i++) - printf("0x%08x ", a->hops[i].virtual); - printf("\n"); + default: + //assert(false); + break; - printf(" B :: "); - for (i = 0; i < b->count; i++) - printf("0x%08x ", b->hops[i].virtual); - printf("\n"); + } - for (i = 0; i < a->count && !result; i++) - if (is_addr_in_branch(b, &a->hops[i])) + if (others != NULL) { - result = true; - copy_vmpa(c, &a->hops[i]); + //printf(" HO \n"); + delete_bit_field(local_stop); + local_stop = others; } - if (result) - printf(" N :: 0x%08x\n", (unsigned int)c->virtual); - else - printf(" N :: ----\n"); - - printf("....................\n"); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : group = informations à initialiser. * -* * -* Description : Initialise le suivi d'un ensemble de branches. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void init_branch_group(branch_group *group) -{ - memset(group, 0, sizeof(branch_group)); - -} - - -/****************************************************************************** -* * -* Paramètres : group = informations à nettoyer. * -* * -* Description : Acte la fin d'un suivi d'un ensemble de branches. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void clean_branch_group(branch_group *group) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < group->count; i++) - clean_branch_info(&group->branches[i]); - - if (group->branches != NULL) - free(group->branches); - -} - - -/****************************************************************************** -* * -* Paramètres : group = liste d'ensembles de jalons à agrandir. * -* * -* Description : Ajoute une branche à un ensemble de branches en place. * -* * -* Retour : Nouvel élément rajouté et initialisé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static branch_info *extend_branch_group(branch_group *group) -{ - branch_info *result; /* Nouveauté à retourner */ - group->branches = (branch_info *)realloc(group->branches, - ++group->count * sizeof(branch_info)); - result = &group->branches[group->count]; + //printf(" -- [%d] common :: 0x%08x\n", fff, gfw(local_stop)); - init_branch_info(result); - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : group = liste d'ensembles de jalons à parcourir. * -* common = éventuelle adresse commune à branches. * -* * -* Description : Retrouve le point de ralliement entre un groupe de branches. * -* * -* Retour : true si une position commune a pu être trouvée, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ + //or_bit_field(local_stop, stop); -static bool compute_first_common_addr_in_group(const branch_group *group, vmpa2t *common) -{ - vmpa_t result; /* Adresse trouvée à retourner */ - branch_info *list; /* Raccourci de confort */ - size_t i; /* Boucle de parcours #1 */ - bool keep; /* Candidate à garder ? */ - size_t j; /* Boucle de parcours #2 */ - result = false; + //printf(" -- [%d] common :: 0x%08x\n", fff, gfw(local_stop)); - list = group->branches; - for (i = 0; i < list[0].count && !result; i++) - { - keep = true; + /* Récupération des sous-blocs */ - for (j = 1; j < group->count && keep; j++) - keep = is_addr_in_branch(&list[j], &list[0].hops[i]); + *next = 0; - if (keep) - copy_vmpa(common, &list[0].hops[i]); + group = NULL; + group_cached = NULL; - } + for (i = 0; i < dcount; i++) + switch (types[i]) + { + case ILT_EXEC_FLOW: + case ILT_JUMP: - return result; + /* Il ne peut y en avoir qu'un ! */ + assert(*next == 0); -} + target = find_knight_node_for_instruction(knight, false, dests[i]); + if (target == NULL) break; + *next = get_dragon_knight_node_index(knight, target); + break; + case ILT_LOOP: + break; -/* ---------------------------------------------------------------------------------- */ -/* DECOUPAGE EN BLOCS DE CODE */ -/* ---------------------------------------------------------------------------------- */ + case ILT_CASE_JUMP: + case ILT_JUMP_IF_TRUE: + case ILT_JUMP_IF_FALSE: + target = find_knight_node_for_instruction(knight, false, dests[i]); + if (target == NULL) break; -/****************************************************************************** -* * -* Paramètres : proc = ensemble des instructions d'assemblage. * -* coverage = délimitations de la zone à couvrir. * -* first = première instruction d'un bloc préliminaire. * -* cur = instruction courante dans le traitement. * -* * -* Description : Procède à la création d'un bloc d'instructions simple. * -* * -* Retour : Bloc créé ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ -#include "../../arch/instruction-int.h" -static GInstrBlock *build_instruction_block_simple(GArchProcessor *proc, code_coverage *coverage, GArchInstruction **first, GArchInstruction *cur) -{ - GInstrBlock *result; /* Regroupement à retourner */ - - if (*first != NULL) - { - result = g_flow_block_new(proc, *first, cur); + /* + printf(" -- call %d -> %zu -> %zu\n", + fff, + get_dragon_knight_node_index(knight, node), + get_dragon_knight_node_index(knight, target)); + */ - mark_range_as_processed_in_coverage(coverage, *first); + block = build_instruction_blocks(proc, knight, target, local_stop, converted, &id); - *first = NULL; + //printf(" -> next id = %zu\n", id); - } - else result = NULL; - return result; -} + /* Le premier passage crée la référence */ + if (*next == 0) + *next = id; + /** + * Une patte, première ou nom, peut se terminer alors que + * ses voisines continuent. + * + * Il y a donc plusieurs valeurs pour l'indice suivant : + * un nul et un strictement positif. + * + * Le cas typique est le suivant : + * + * ====== + * / \ + * | | + * ret | + * | + * === + */ -/****************************************************************************** -* * -* Paramètres : proc = ensemble des instructions d'assemblage. * -* coverage = délimitations de la zone à couvrir. * -* cases = branches conditionnelles des situations. * -* next = localisation de l'instruction de reprise. * -* * -* Description : Procède à la définition d'un bloc d'instructions selectif. * -* * -* Retour : Bloc créé et enregistré, ou NULL si erreur. * -* * -* Remarques : - * -* * -******************************************************************************/ + else if (id > 0) + { + //printf(" NEXT :: %u vs %u\n", *next, id); + assert(*next == id); + } -static GInstrBlock *build_instruction_blocks_case(GArchProcessor *proc, code_coverage *coverage, const branch_group *cases, vmpa2t *next) -{ - GInstrBlock *result; /* Regroupement à retourner */ - bool has_common; /* Fin commune ? */ - size_t i; /* Boucle de parcours #1 */ - code_coverage *sub_coverage; /* Couverture pour les suivants*/ - size_t j; /* Boucle de parcours #2 */ - GInstrBlock *block; /* Nouveau bloc mis en place */ + if (block != NULL) + DELAYED_BLOCK_ADDING(group, group_cached, block); - has_common = compute_first_common_addr_in_group(cases, next); - if (!has_common) return NULL; + break; - result = g_virtual_block_new(); + case ILT_CATCH_EXCEPTION: + break; - for (i = 0; i < cases->count; i++) - { - sub_coverage = dup_code_coverage(coverage, get_entry_to_branch(&cases->branches[i])); + default: + //assert(false); + break; - add_ending_address_code_coverage(sub_coverage, next); + } - for (j = 0; j < cases->count; j++) - add_ending_address_code_coverage(sub_coverage, get_entry_to_branch(&cases->branches[j])); + if (/*group != NULL || */group_cached != NULL) + DELAYED_BLOCK_ADDING(result, result_cached, group != NULL ? group : group_cached); - block = build_instruction_blocks(proc, sub_coverage); + delete_bit_field(local_stop); - if (block != NULL) - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); + /* On passe au noeud suivant */ - delete_code_coverage(sub_coverage); + if (*next == 0) + break; - } + node = get_dragon_knight_node(knight, *next); - if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(result)) == 0) - { - g_object_unref(G_OBJECT(result)); - result = NULL; } - return result; + return (result != NULL ? result : result_cached); } /****************************************************************************** * * -* Paramètres : proc = ensemble des instructions d'assemblage. * -* coverage = délimitations de la zone à couvrir. * -* true_branch = branche conditionnelle correspondant à true. * -* false_branch = branche conditionnelle correspondant à false. * -* next = localisation de l'instruction de reprise. * +* Paramètres : routine = routine en code exécutable à traiter. * +* knight = rassemblement des complexités de code. * * * -* Description : Procède à la définition d'un bloc d'instruction if/then/else.* +* Description : Procède à la définition de blocs regroupant des instructions.* * * -* Retour : Bloc créé et enregistré, ou NULL si erreur. * +* Retour : Blocs créés et enregistrés, ou NULL si erreur. * * * * Remarques : - * * * ******************************************************************************/ -static GInstrBlock *build_instruction_blocks_ite(GArchProcessor *proc, code_coverage *coverage, const branch_info *true_branch, const branch_info *false_branch, vmpa2t *next) +void group_routine_instructions(GBinRoutine *routine, const dragon_knight *knight) { - GInstrBlock *result; /* Regroupement à retourner */ - bool has_common; /* Fin commune ? */ - 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(proc, _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(proc, _sub_coverage); - - delete_code_coverage(_sub_coverage); + dragon_node *nodes; /* Liste des noeuds détectés */ + size_t count; /* Taille de cette liste */ + dragon_node *node; /* Noeud à traiter */ + bitfield_t *stop; /* Bloc d'arrêt de l'analyse */ + bitfield_t *converted; /* Cartographie des traitements*/ + GInstrBlock *blocks; /* Blocs basiques construits */ - 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; + get_dragon_knight_content(knight, &nodes, &count); + compute_all_paths(nodes, count); - } - assert(has_common); +#if 0 + size_t k; - if (!has_common) printf(" === nothing in common\n"); - if (!has_common) return NULL; - - result = g_virtual_block_new(); - - /** - * Encapsulation des branches conditionnelles. - */ - - GInstrBlock *build_instr_block_bi(GArchProcessor *proc, const code_coverage *coverage, const branch_info *br0, const branch_info *br1, const vmpa2t *next) + for (k = 0; k < count; k++) { - GInstrBlock *result; /* Bloc construit à renvoyer */ - code_coverage *sub_coverage; /* Couverture pour les suivants*/ - - result = NULL; - - if (br0->count > 0) - { - sub_coverage = dup_code_coverage(coverage, get_entry_to_branch(br0)); - - add_ending_address_code_coverage(sub_coverage, next); + GArchInstruction *first; + GArchInstruction *last; + const bitfield_t *paths; - if (br1->count > 0) - add_ending_address_code_coverage(sub_coverage, get_entry_to_branch(br1)); + node = get_dragon_node(nodes, k); - result = build_instruction_blocks(proc, sub_coverage); + paths = get_paths_bits(node); - delete_code_coverage(sub_coverage); + get_dragon_node_bounding_instructions(node, &first, &last); - } - return result; + printf("#[ node %zu ]# @ 0x%08x / 0x%08x - mask = 0x%08lx\n", k, + (unsigned int)g_arch_instruction_get_range(first)->addr.virtual, + (unsigned int)g_arch_instruction_get_range(last)->addr.virtual, + gfw(paths)); } +#endif - /* Branche 'true' */ - - block = build_instr_block_bi(proc, coverage, true_branch, false_branch, next); - - printf("===> TRUE_BRANCH = %p\n", block); - - if (block != NULL) - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); - /* Branche 'false' */ - block = build_instr_block_bi(proc, coverage, false_branch, true_branch, next); - printf("===> FALSE_BRANCH = %p\n", block); + node = get_dragon_node(nodes, 0); - if (block != NULL) - g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); + stop = create_bit_field(count, false); + converted = create_bit_field(count, false); - /* Conclusion */ - - if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(result)) == 0) - { - g_object_unref(G_OBJECT(result)); - result = NULL; - } - - return result; + blocks = build_instruction_blocks(NULL, knight, node, stop, converted, (size_t []) { 0 }); -} + delete_bit_field(stop); -/****************************************************************************** -* * -* Paramètres : result = liste générale résultante du découpage. [OUT] * -* cached = emplacement pour le cache des résultats. [OUT] * -* proc = ensemble des instructions d'assemblage. * -* coverage = délimitations de la zone à couvrir. * -* exceptions = branche conditionnelle correspondant à true. * -* main_branch = branche principale avec son flot d'exécution. * -* * -* Description : Procède à la définition d'un bloc d'instructions d'exception.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ -static void add_instruction_blocks_except(GInstrBlock **result, GInstrBlock **cached, GArchProcessor *proc, code_coverage *coverage, const branch_group *exceptions, const branch_info *main_branch) -{ - size_t i; /* Boucle de parcours */ - vmpa2t stop_addr; /* Adresse de fin de bloc */ - bool has_stop; /* Fin commune ? */ - code_coverage *sub_coverage; /* Couverture pour les suivants*/ - GInstrBlock *block; /* Nouveau bloc mis en place */ - for (i = 0; i < exceptions->count; i++) +#if 0 + bool visit_block(GInstrBlock *blk, BlockVisitOrder order, int *indent) { - has_stop = compute_first_common_addr(main_branch, &exceptions->branches[i], &stop_addr); - if (!has_stop) continue; - - sub_coverage = dup_code_coverage(coverage, get_entry_to_branch(&exceptions->branches[i])); - add_ending_address_code_coverage(sub_coverage, &stop_addr); - - block = build_instruction_blocks(proc, sub_coverage); + int i; - if (block != NULL) - DELAYED_BLOCK_ADDING(*result, *cached, block); - - delete_code_coverage(sub_coverage); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : proc = ensemble des instructions d'assemblage. * -* coverage = délimitations de la zone à couvrir. * -* * -* Description : Procède à la définition de bloc regroupant des instructions. * -* * -* Retour : Bloc créé et enregistré, ou NULL si erreur. * -* * -* Remarques : - * -* * -******************************************************************************/ -#include "../../arch/instruction-int.h" -static GInstrBlock *build_instruction_blocks(GArchProcessor *proc, code_coverage *coverage) -{ - 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 */ - GArchInstruction *iter; /* Boucle de parcours */ - const mrange_t *range; /* Emplacement d'instruction */ - const vmpa2t *addr; /* Adresse de la destination */ - GArchInstruction **dests; /* Instr. visée par une autre */ - InstructionLinkType *types; /* Type de lien entre lignes */ - 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 */ - size_t not_handled; /* Quantité de liens non gérés */ - vmpa2t next_addr; /* Prochaine instruction visée */ - branch_group cases_branches; /* Branches d'un aiguillage */ - branch_info true_branch; /* Branche 'condition vraie' */ - branch_info false_branch; /* Branche 'condition fausse' */ - branch_group excep_branches; /* Branches d'exceptions */ - branch_info *branch; /* Branche à suivre */ - - result = NULL; - result_cached = NULL; - - first = NULL; - last = NULL; - - init_branch_info(&main_branch); - find_next_hops(proc, get_code_coverage_start_addr(coverage), coverage, &main_branch); - - - printf("//////////////////////////\n"); - printf("/// Cutting for 0x%08x -> %p\n", - get_code_coverage_start_addr(coverage)->virtual, - g_arch_processor_find_instr_by_address(proc, get_code_coverage_start_addr(coverage))); - printf("//////////////////////////\n"); - - - for (iter = g_arch_processor_find_instr_by_address(proc, get_code_coverage_start_addr(coverage)); - iter != NULL; - ) - { - range = g_arch_instruction_get_range(iter); - addr = get_mrange_addr(range); - - if (code_coverage_stop_here(coverage, addr)) break; - - /* 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) - first = iter; - - 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_get_flags(iter) & AIF_RETURN_POINT) break; - - /* On n'approfondit que les chemins qui se séparent */ - if (!g_arch_instruction_has_destinations(iter)) + switch (order) { - iter = g_arch_processor_get_next_instr(proc, iter); - continue; - } - - /* Adaptations en fonction du type de bifurcation */ + case BVO_IN: + case BVO_PENDING: - dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL); + for (i = 0; i < *indent; i++) + printf(" "); - not_handled = 0; - init_vmpa(&next_addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + printf("%p '%s'", blk, G_OBJECT_TYPE_NAME(blk)); - init_branch_group(&cases_branches); - init_branch_info(&true_branch); - init_branch_info(&false_branch); - init_branch_group(&excep_branches); - - for (i = 0; i < dcount; i++) - { - branch = NULL; - - switch (types[i]) + if (G_IS_FLOW_BLOCK(blk)) { - case ILT_EXEC_FLOW: - case ILT_JUMP: - - - //break; - { - GArchInstruction *_saved0; - - _saved0 = first; - - block = build_instruction_block_simple(proc, coverage, &first, iter); - printf(" -- simple block JMP -- @ 0x%08x <-> 0x%08x\n", - (unsigned int)(_saved0 ? _saved0->range.addr.virtual : ~0), - (unsigned int)iter->range.addr.virtual); - fflush(NULL); - } - DELAYED_BLOCK_ADDING(result, result_cached, block); - - /** - * La prochaine adresse d'analyse est celle visée par l'instruction ! - * Pour les sauts naturels, ça ne change rien ; ce n'est pas le cas - * pour les sauts explicites. - */ - range = g_arch_instruction_get_range(dests[i]); - copy_vmpa(&next_addr, get_mrange_addr(range)); - - first = NULL; - - 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; - - case ILT_JUMP_IF_TRUE: - printf("FIND TRUE BRANCH @ 0x%08x\n", (unsigned int)iter->range.addr.virtual); - branch = &true_branch; - break; - - case ILT_JUMP_IF_FALSE: - printf("FIND FALSE BRANCH @ 0x%08x\n", (unsigned int)iter->range.addr.virtual); - branch = &false_branch; - break; - - case ILT_CATCH_EXCEPTION: - branch = extend_branch_group(&excep_branches); - - /** - * Les deux cas sont les seuls à ne pas conduire à une définition de - * next_addr, donc on les comptabilise sur un pied d'égalité ! - */ - /* break; */ + vmpa2t start; + vmpa2t end; - default: - not_handled++; - break; + g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blk), &start, &end); - } - - /* Si on a une branche à compléter... */ - if (branch != NULL) - { - range = g_arch_instruction_get_range(dests[i]); - addr = get_mrange_addr(range); - - printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - printf("BUILD @ 0x%08x\n", (unsigned int)addr->virtual); - find_next_hops(proc, addr, coverage, branch); - printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); + printf(" 0x%08x -> 0x%08x", + (unsigned int)start.virtual, + (unsigned int)end.virtual); } - } - - /* Post-traitements de ILT_CASE_JUMP */ - if (cases_branches.count > 0) - { - block = build_instruction_block_simple(proc, coverage, &first, iter); - DELAYED_BLOCK_ADDING(result, result_cached, block); + printf("\n"); - group = build_instruction_blocks_case(proc, coverage, &cases_branches, &next_addr); - - if (group != NULL) - { - DELAYED_BLOCK_ADDING(result, result_cached, group); - g_instr_block_set_links_block(block, group); - } - - } - - /* Post-traitements de ILT_JUMP_IF_TRUE / ILT_JUMP_IF_FALSE */ - else if (true_branch.count > 0 || false_branch.count > 0) - { - block = build_instruction_block_simple(proc, coverage, &first, iter); - - GArchInstruction *_saved1; - - _saved1 = first; - - - - printf(" -- branches -- %d vs %d\n", (int)true_branch.count, (int)false_branch.count); - - printf(" -- simple block ITE -- @ 0x%08x <-> 0x%08x\n", - (unsigned int)(_saved1 ? _saved1->range.addr.virtual : ~0), - (unsigned int)iter->range.addr.virtual); - fflush(NULL); - DELAYED_BLOCK_ADDING(result, result_cached, block); - - group = build_instruction_blocks_ite(proc, coverage, &true_branch, &false_branch, &next_addr); - - printf(" --> group = %p - next = 0x%08x\n", group, next_addr.virtual); - - if (group != NULL) - { - DELAYED_BLOCK_ADDING(result, result_cached, group); - g_instr_block_set_links_block(block, group); - } - - } - - /* Post-traitements de ILT_CATCH_EXCEPTION */ - if (excep_branches.count > 0) - { - block = build_instruction_block_simple(proc, coverage, &first, iter); - if (block != NULL) DELAYED_BLOCK_ADDING(result, result_cached, block); + if (order == BVO_IN) (*indent)++; + break; - add_instruction_blocks_except(&result, &result_cached, proc, coverage, - &excep_branches, &main_branch); + case BVO_OUT: + (*indent)--; + break; } - clean_branch_group(&cases_branches); - clean_branch_info(&true_branch); - clean_branch_info(&false_branch); - clean_branch_group(&excep_branches); - - /* Détermination du prochain point de chute */ - - if (not_handled == dcount) - iter = g_arch_processor_get_next_instr(proc, iter); - else - iter = g_arch_processor_find_instr_by_address(proc, &next_addr); - - } - - if (first != NULL && last != NULL) - { - range = g_arch_instruction_get_range(first); - - if (!is_range_processed_in_coverage(coverage, range)) - { - block = build_instruction_block_simple(proc, coverage, &first, last); - DELAYED_BLOCK_ADDING(result, result_cached, block); - } + return true; } - clean_branch_info(&main_branch); - - return (result != NULL ? result : result_cached); - -} - - -/****************************************************************************** -* * -* Paramètres : proc = processeur rassemblant les instructions à relier.* -* routines = prototypes existants à insérer. * -* count = quantité de ces prototypes. * -* statusbar = barre de statut avec progression à mettre à jour.* -* id = identifiant du message affiché à l'utilisateur. * -* * -* Description : Regroupe les instructions par blocs. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void group_routines_instructions(GArchProcessor *proc, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id) -{ - size_t i; /* Boucle de parcours */ - const mrange_t *range; /* Emplacement de routine */ - code_coverage *coverage; /* Couverture de zone de code */ - GInstrBlock *block; /* Regroupement d'instructions */ - - for (i = 0; i < count; i++) - { - range = g_binary_routine_get_range(routines[i]); - - printf("===== BLOCK(S) for 0x%08x ======\n", range->addr.virtual); - - coverage = create_code_coverage(range); - - block = build_instruction_blocks(proc, coverage); - - - if (block == NULL) continue; - - - g_binary_routine_set_basic_blocks(routines[i], block); - - - bool visit_block(GInstrBlock *blk, BlockVisitOrder order, int *indent) - { - int i; - - switch (order) - { - case BVO_IN: - case BVO_PENDING: - - for (i = 0; i < *indent; i++) - printf(" "); - - printf("%p '%s'", blk, G_OBJECT_TYPE_NAME(blk)); - - if (G_IS_FLOW_BLOCK(blk)) - { - vmpa2t start; - vmpa2t end; - - g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blk), &start, &end); - - printf(" 0x%08x -> 0x%08x", - (unsigned int)start.virtual, - (unsigned int)end.virtual); - - } - - printf("\n"); - - if (order == BVO_IN) (*indent)++; - break; - - case BVO_OUT: - (*indent)--; - break; - - } - - return true; - - } - - g_instr_block_visit(block, (instr_block_visitor_cb)visit_block, (int []){ 0 }); - - printf("\n"); + g_instr_block_visit(blocks, (instr_block_visitor_cb)visit_block, (int []){ 0 }); + printf("\n"); +#endif - delete_code_coverage(coverage); + //if (blocks != NULL) - gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count); - } + g_binary_routine_set_basic_blocks(routine, blocks); } |