diff options
Diffstat (limited to 'src/analysis/disass/dragon.c')
-rw-r--r-- | src/analysis/disass/dragon.c | 214 |
1 files changed, 201 insertions, 13 deletions
diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c index 2fcf830..fbdecd8 100644 --- a/src/analysis/disass/dragon.c +++ b/src/analysis/disass/dragon.c @@ -38,6 +38,7 @@ struct _dragon_node GArchInstruction *first; /* Arrivée d'un lien (début) */ GArchInstruction *last; /* Départ d'un lien (fin) */ + bitfield_t *paths_bits; /* Masque de noeuds accessibles*/ bitfield_t *bits; /* Représentation par masque */ }; @@ -91,11 +92,12 @@ struct _dragon_knight * Remarques : - * * * ******************************************************************************/ - +#include "../../arch/instruction-int.h" static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start, size_t *count) { dragon_node *result; /* Liste à créer et renvoyer */ size_t allocated; /* Dimensionnement en mémoire */ + bool need_alloc; /* Besoin d'une extension ? */ GArchInstruction *last; /* Mémorisation du passé */ GArchInstruction *iter; /* Boucle de parcours */ const mrange_t *irange; /* Emplacement d'instruction */ @@ -108,6 +110,7 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ *count = 0; allocated = 0; + need_alloc = true; for (last = NULL, iter = g_arch_processor_find_covered_instr_by_address(proc, coverage, start); iter != NULL; @@ -122,8 +125,10 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ /* Analyse des sources */ - if (result == NULL) + if (need_alloc) { + need_alloc = false; + (*count)++; if (*count >= allocated) @@ -137,6 +142,8 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ new->first = iter; } + + else { scount = g_arch_instruction_get_sources(iter, NULL, &types); @@ -154,6 +161,15 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ if (*count > 0) result[*count - 1].last = last; + + /* + printf(" %% ?jmp? %% cut @ %zu ; last = 0x%08x ; iter = 0x%08x\n", *count - 1, + (unsigned int)last->range.addr.virtual, + (unsigned int)iter->range.addr.virtual); + fflush(NULL); + */ + + (*count)++; i = scount; @@ -176,6 +192,25 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ } + + + if (g_arch_instruction_get_flags(iter) & AIF_RETURN_POINT) + { + if (*count > 0) + result[*count - 1].last = iter; + + /* + printf(" %% return %% cut @ %zu ; addr = 0x%08x\n", *count - 1, + (unsigned int)iter->range.addr.virtual); + fflush(NULL); + */ + + need_alloc = true; + + } + + + } if (*count > 0) @@ -204,7 +239,10 @@ static void delete_dragon_nodes(dragon_node *nodes, size_t count) size_t i; /* Boucle de parcours */ for (i = 0; i < count; i++) + { + delete_bit_field(nodes[i].paths_bits); delete_bit_field(nodes[i].bits); + } free(nodes); @@ -229,7 +267,10 @@ static void init_mask_for_nodes(dragon_node *nodes, size_t count) size_t i; /* Boucle de parcours */ for (i = 0; i < count; i++) + { + nodes[i].paths_bits = create_bit_field(count, false); nodes[i].bits = create_bit_field(count, i > 0); + } set_in_bit_field(nodes[0].bits, 0, 1); @@ -347,6 +388,84 @@ dragon_node *find_node_for_instruction(dragon_node *nodes, size_t count, bool fi * Paramètres : nodes = liste de noeuds détectés dans une routine. * * count = taille de cette liste de noeuds à traiter. * * * +* Description : Marque tous les noeuds accessibles pour chaque noeud de code.* +* * +* Retour : - * +* * +* Remarques : Les chemins issus de boucles ne sont pas pris en compte. * +* On cherche à construire une hiérarchie, pas une réalité. * +* * +******************************************************************************/ + +void compute_all_paths(dragon_node *nodes, size_t count) +{ + void follow_flow_in_nodes(dragon_node *node) + { + 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 */ + dragon_node *next; /* Noeud suivant dans le code */ + size_t id; /* Indice du bit associé */ + + dcount = g_arch_instruction_get_destinations(node->last, &dests, &types, NULL); + + for (i = 0; i < dcount; 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: + + next = find_node_for_instruction(nodes, count, false, dests[i]); + if (next == NULL) break; + + id = get_dragon_node_index(nodes, next); + set_in_bit_field(node->paths_bits, id, 1); + + follow_flow_in_nodes(next); + or_bit_field(node->paths_bits, next->paths_bits); + + break; + + default: + break; + + } + + } + + follow_flow_in_nodes(&nodes[0]); + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud représentant une portion de code à consulter. * +* * +* Description : Fournit la liste des noeuds accessibles depuis un autre. * +* * +* Retour : Champ de bits en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const bitfield_t *get_paths_bits(const dragon_node *node) +{ + return node->paths_bits; + +} + + +/****************************************************************************** +* * +* Paramètres : nodes = liste de noeuds détectés dans une routine. * +* count = taille de cette liste de noeuds à traiter. * +* * * Description : Détermine toute la chaîne hiérarchique de domination. * * * * Retour : - * @@ -380,7 +499,7 @@ void compute_all_dominators(dragon_node *nodes, size_t count) set_all_in_bit_field(inter); scount = g_arch_instruction_get_sources(node->first, &srcs, &types); - assert(scount > 0); + //assert(scount > 0); // un 'ret' coupe, le suivant n'a pas de source for (i = 0; i < scount; i++) switch (types[i]) @@ -393,12 +512,12 @@ void compute_all_dominators(dragon_node *nodes, size_t count) predecessor = find_node_for_instruction(nodes, count, true, srcs[i]); - + /* printf(" -- finding pred @ 0x%08x -> 0x%08x :: %p\n", (unsigned int)g_arch_instruction_get_range(node->first)->addr.virtual, (unsigned int)g_arch_instruction_get_range(srcs[i])->addr.virtual, predecessor); - + */ if (predecessor == NULL) break; @@ -449,9 +568,6 @@ const bitfield_t *get_domination_bits(const dragon_node *node) - - - /* ---------------------------------------------------------------------------------- */ /* ENCAPSULATION DES NOEUDS */ /* ---------------------------------------------------------------------------------- */ @@ -522,8 +638,8 @@ void end_dragon_knight(dragon_knight *knight) /****************************************************************************** * * * Paramètres : knight = données représentant une complexité à considérer. * -* nodes = noeuds de code associés à récupérer. [OUT] * -* count = taille de cette liste de noeuds. [OUT] * +* nodes = noeuds de code associés à récupérer ou NULL. [OUT] * +* count = taille de cette liste de noeuds ou NULL. [OUT] * * * * Description : Fournit les éléments utiles à un traitement de blocs de code.* * * @@ -533,9 +649,81 @@ void end_dragon_knight(dragon_knight *knight) * * ******************************************************************************/ -void get_dragon_knight_content(dragon_knight *knight, dragon_node **nodes, size_t *count) +void get_dragon_knight_content(const dragon_knight *knight, dragon_node **nodes, size_t *count) +{ + if (nodes != NULL) *nodes = knight->nodes; + if (count != NULL) *count = knight->count; + +} + + +/****************************************************************************** +* * +* Paramètres : knight = données représentant une complexité à considérer. * +* * +* Description : Fournit un noeud particulier à partir d'une liste. * +* * +* Retour : Noeud ciblé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +dragon_node *get_dragon_knight_node(const dragon_knight *knight, size_t index) { - *nodes = knight->nodes; - *count = knight->count; + assert(index < knight->count); + + return knight->nodes + index; + +} + + +/****************************************************************************** +* * +* Paramètres : knight = données représentant une complexité à considérer. * +* node = noeud ciblé au sein de cette liste. * +* * +* Description : Fournit l'indice d'un noeud particulier à partir d'une liste.* +* * +* Retour : Indice du noeud ciblé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t get_dragon_knight_node_index(const dragon_knight *knight, dragon_node *node) +{ + size_t result; /* Indice à retourner */ + + result = (node - knight->nodes); + + assert(result < knight->count); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : knight = données représentant une complexité à considérer. * +* final = précise si l'instruction visée est la première. * +* instr = instruction à retrouver en tant que début de noeud. * +* * +* Description : Recherche un noeud selon son intruction de départ. * +* * +* Retour : Noeud trouvé ou NULL si aucune trouvaille. * +* * +* Remarques : - * +* * +******************************************************************************/ + +dragon_node *find_knight_node_for_instruction(const dragon_knight *knight, bool final, const GArchInstruction *instr) +{ + dragon_node *result; /* Résultat des recherches */ + + result = find_node_for_instruction(knight->nodes, knight->count, final, instr); + + return result; } |