diff options
Diffstat (limited to 'src/analysis/disass/block.c')
-rw-r--r-- | src/analysis/disass/block.c | 453 |
1 files changed, 116 insertions, 337 deletions
diff --git a/src/analysis/disass/block.c b/src/analysis/disass/block.c index 2d01d5d..5c97358 100644 --- a/src/analysis/disass/block.c +++ b/src/analysis/disass/block.c @@ -27,6 +27,10 @@ #include <assert.h> +#include "../block-int.h" +#include "../../glibext/gbinarycursor.h" + + /* ------------------------ MISE EN PLACE DES BLOCS BASIQUES ------------------------ */ @@ -34,21 +38,19 @@ /* Description d'un bloc basique d'instructions (instance) */ struct _GBasicBlock { - GObject parent; /* A laisser en premier */ + GCodeBlock parent; /* A laisser en premier */ + + GLoadedBinary *binary; /* Binaire chargé et associé */ GArchInstruction *first; /* Première instruction */ GArchInstruction *last; /* Dernière instruction */ - unsigned int rank; /* Rang dans l'exécution */ - - bitfield_t *domination; /* Blocs dominés de l'ensemble */ - }; /* Description d'un bloc basique d'instructions (classe) */ struct _GBasicBlockClass { - GObjectClass parent; /* A laisser en premier */ + GCodeBlockClass parent; /* A laisser en premier */ }; @@ -65,40 +67,14 @@ static void g_basic_block_dispose(GBasicBlock *); /* Procède à la libération totale de la mémoire. */ static void g_basic_block_finalize(GBasicBlock *); +/* Détermine si un bloc de code débute à une adresse donnée. */ +static bool g_basic_block_is_starting_with(const GBasicBlock *, const vmpa2t *); +/* Etablit les liens entre un bloc de code et ses voisins. */ +static void g_basic_block_resolve_links(GBasicBlock *, const GBlockList *); -/* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */ - - -/* Description d'une liste de blocs basiques (instance) */ -struct _GBlockList -{ - GObject parent; /* A laisser en premier */ - - GBasicBlock **blocks; /* Blocs basiques rassemblés */ - size_t count; /* Quantité de ces blocs */ - -}; - -/* Description d'une liste de blocs basiques (classe) */ -struct _GBlockListClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - -/* Initialise la classe des listes de blocs basiques. */ -static void g_block_list_class_init(GBlockListClass *); - -/* Initialise une liste de blocs basiques. */ -static void g_block_list_init(GBlockList *); - -/* Supprime toutes les références externes. */ -static void g_block_list_dispose(GBlockList *); - -/* Procède à la libération totale de la mémoire. */ -static void g_block_list_finalize(GBlockList *); +/* Fournit la représentation graphique d'un bloc de code. */ +static GBufferView *g_basic_block_build_view(const GBasicBlock *, segcnt_list *); @@ -108,7 +84,7 @@ static void g_block_list_finalize(GBlockList *); /* Indique le type défini pour un bloc d'instructions basique. */ -G_DEFINE_TYPE(GBasicBlock, g_basic_block, G_TYPE_OBJECT); +G_DEFINE_TYPE(GBasicBlock, g_basic_block, G_TYPE_CODE_BLOCK); /****************************************************************************** @@ -126,12 +102,19 @@ G_DEFINE_TYPE(GBasicBlock, g_basic_block, G_TYPE_OBJECT); static void g_basic_block_class_init(GBasicBlockClass *class) { GObjectClass *object; /* Autre version de la classe */ + GCodeBlockClass *block; /* Version parente de la classe*/ object = G_OBJECT_CLASS(class); object->dispose = (GObjectFinalizeFunc/* ! */)g_basic_block_dispose; object->finalize = (GObjectFinalizeFunc)g_basic_block_finalize; + block = G_CODE_BLOCK_CLASS(class); + + block->is_starting = (block_is_starting_fc)g_basic_block_is_starting_with; + block->link = (block_resolve_links_fc)g_basic_block_resolve_links; + block->build = (block_build_view_fc)g_basic_block_build_view; + } @@ -149,7 +132,6 @@ static void g_basic_block_class_init(GBasicBlockClass *class) static void g_basic_block_init(GBasicBlock *block) { - block->rank = -1; } @@ -168,8 +150,10 @@ static void g_basic_block_init(GBasicBlock *block) static void g_basic_block_dispose(GBasicBlock *block) { - g_object_ref(G_OBJECT(block->first)); - g_object_ref(G_OBJECT(block->last)); + g_object_unref(G_OBJECT(block->binary)); + + g_object_unref(G_OBJECT(block->first)); + g_object_unref(G_OBJECT(block->last)); G_OBJECT_CLASS(g_basic_block_parent_class)->dispose(G_OBJECT(block)); @@ -190,8 +174,6 @@ static void g_basic_block_dispose(GBasicBlock *block) static void g_basic_block_finalize(GBasicBlock *block) { - delete_bit_field(block->domination); - G_OBJECT_CLASS(g_basic_block_parent_class)->finalize(G_OBJECT(block)); } @@ -199,9 +181,10 @@ static void g_basic_block_finalize(GBasicBlock *block) /****************************************************************************** * * -* Paramètres : first = première instruction du bloc. * -* last = dernière instruction du bloc. * -* bits = liste des blocs dominés. * +* Paramètres : binary = binaire chargé contenant les instructions. * +* first = première instruction du bloc. * +* last = dernière instruction du bloc. * +* bits = liste des blocs dominés. * * * * Description : Crée un bloc basique d'exécution d'instructions. * * * @@ -211,57 +194,37 @@ static void g_basic_block_finalize(GBasicBlock *block) * * ******************************************************************************/ -GBasicBlock *g_basic_block_new(GArchInstruction *first, GArchInstruction *last, const bitfield_t *bits) +GCodeBlock *g_basic_block_new(GLoadedBinary *binary, GArchInstruction *first, GArchInstruction *last, const bitfield_t *bits) { - GBasicBlock *result; /* Structure à retourner */ + GBasicBlock *result; /* Structure à retourner */ + GCodeBlock *parent; /* Version parente d'instance */ result = g_object_new(G_TYPE_BASIC_BLOCK, NULL); + result->binary = binary; + g_object_ref(G_OBJECT(binary)); + result->first = first; result->last = last; - g_object_ref(G_OBJECT(result->first)); - g_object_ref(G_OBJECT(result->last)); + g_object_ref(G_OBJECT(first)); + g_object_ref(G_OBJECT(last)); - result->domination = dup_bit_field(bits); + parent = G_CODE_BLOCK(result); - return result; - -} + parent->domination = dup_bit_field(bits); - -/****************************************************************************** -* * -* Paramètres : block = bloc d'instructions à consulter. * -* first = instruction de départ du bloc. [OUT] * -* last = dernière instruction du bloc. [OUT] * -* * -* Description : Fournit les instructions limites d'un bloc basique. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_basic_block_get_boundary(const GBasicBlock *block, GArchInstruction **first, GArchInstruction **last) -{ - if (first != NULL) - *first = block->first; - - if (last != NULL) - *last = block->last; + return parent; } /****************************************************************************** * * -* Paramètres : block = bloc d'instructions à consulter. * -* start = adresse de départ du bloc. [OUT] * -* end = dernière adresse du bloc. [OUT] * +* Paramètres : block = bloc de code à consulter. * +* addr = localisation à comparer. * * * -* Description : Fournit les adresses limites d'un bloc basique. * +* Description : Détermine si un bloc de code débute à une adresse donnée. * * * * Retour : - * * * @@ -269,140 +232,26 @@ void g_basic_block_get_boundary(const GBasicBlock *block, GArchInstruction **fir * * ******************************************************************************/ -void g_basic_block_get_boundary_addresses(const GBasicBlock *block, vmpa2t *start, vmpa2t *end) +static bool g_basic_block_is_starting_with(const GBasicBlock *block, const vmpa2t *addr) { + bool result; /* Bilan à retourner */ const mrange_t *range; /* Couverture d'instruction */ - if (start != NULL) - { - range = g_arch_instruction_get_range(block->first); - copy_vmpa(start, get_mrange_addr(range)); - } + range = g_arch_instruction_get_range(block->first); - if (end != NULL) - { - range = g_arch_instruction_get_range(block->last); - copy_vmpa(end, get_mrange_addr(range)); - } + result = (cmp_vmpa(addr, get_mrange_addr(range)) == 0); -} - - -/****************************************************************************** -* * -* Paramètres : block = bloc d'instructions à consulter. * -* * -* Description : Fournit le rang du bloc basique dans le flot d'exécution. * -* * -* Retour : Indice supérieur ou égal à zéro. * -* * -* Remarques : - * -* * -******************************************************************************/ - -unsigned int g_basic_block_get_rank(const GBasicBlock *block) -{ - return block->rank; - -} - - -/****************************************************************************** -* * -* Paramètres : block = bloc d'instructions à consulter. * -* rank = Indice supérieur à zéro à prendre en compte. * -* * -* Description : Définit le rang du bloc basique dans le flot d'exécution. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_basic_block_set_rank(GBasicBlock *block, unsigned int rank) -{ - block->rank = rank; - -} - - -/****************************************************************************** -* * -* Paramètres : block = bloc d'instructions à consulter. * -* * -* Description : Indique la liste des blocs de code dominés. * -* * -* Retour : Champ de bits représentant des blocs. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const bitfield_t *g_basic_block_get_domination(const GBasicBlock *block) -{ - return block->domination; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* REGROUPEMENT EN LISTE DE BLOCS */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini pour une liste de blocs basiques. */ -G_DEFINE_TYPE(GBlockList, g_block_list, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : class = classe à initialiser. * -* * -* Description : Initialise la classe des listes de blocs basiques. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_block_list_class_init(GBlockListClass *class) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(class); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_block_list_dispose; - object->finalize = (GObjectFinalizeFunc)g_block_list_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : block = instance à initialiser. * -* * -* Description : Initialise une liste de blocs basiques. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_block_list_init(GBlockList *list) -{ + return result; } /****************************************************************************** * * -* Paramètres : block = instance d'objet GLib à traiter. * +* Paramètres : block = bloc de code à mettre à jour. * +* list = ensemble des blocs de code à disposition. * * * -* Description : Supprime toutes les références externes. * +* Description : Etablit les liens entre un bloc de code et ses voisins. * * * * Retour : - * * * @@ -410,150 +259,87 @@ static void g_block_list_init(GBlockList *list) * * ******************************************************************************/ -static void g_block_list_dispose(GBlockList *list) +static void g_basic_block_resolve_links(GBasicBlock *block, const GBlockList *list) { + size_t dcount; /* Nombre de liens de dest. */ size_t i; /* Boucle de parcours */ + const instr_link_t *dest; /* Instr. visée par une autre */ + const mrange_t *range; /* Couverture d'instruction */ + GCodeBlock *target; /* Bloc ciblé par un lien */ - for (i = 0; i < list->count; i++) - if (list->blocks[i] != NULL) - g_object_unref(G_OBJECT(list->blocks[i])); - - G_OBJECT_CLASS(g_block_list_parent_class)->dispose(G_OBJECT(list)); - -} - - -/****************************************************************************** -* * -* Paramètres : block = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_block_list_finalize(GBlockList *list) -{ - G_OBJECT_CLASS(g_block_list_parent_class)->finalize(G_OBJECT(list)); - -} - - -/****************************************************************************** -* * -* Paramètres : count = quantité finale de blocs présentie. * -* * -* Description : Crée une liste de blocs basiques. * -* * -* Retour : Adresse de la structure mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBlockList *g_block_list_new(size_t count) -{ - GBlockList *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_BASIC_BLOCK, NULL); - - result->blocks = (GBasicBlock **)calloc(count, sizeof(GBasicBlock *)); - - result->count = count; - - return result; - -} + g_arch_instruction_lock_dest(block->last); + dcount = g_arch_instruction_count_destinations(block->last); + for (i = 0; i < dcount; i++) + { + dest = g_arch_instruction_get_destination(block->last, i); -/****************************************************************************** -* * -* Paramètres : list = liste de blocs basiques à consulter. * -* * -* Description : Compte le nombre de blocs basiques représentés. * -* * -* Retour : Quantité de blocs basiques rassemblés. * -* * -* Remarques : - * -* * -******************************************************************************/ + range = g_arch_instruction_get_range(dest->linked); -size_t g_block_list_count_blocks(const GBlockList *list) -{ - return list->count; + target = g_block_list_find_by_starting_instr(list, get_mrange_addr(range)); -} + /** + * Les sauts ne se font pas toujours à l'intérieur d'une même fonction. + * Par exemple sous ARM : + * + * 00008358 <call_gmon_start>: + * .... + * 8362: f7ff bfcf b.w 8304 <_init+0x38> + * .... + * + */ + if (target != NULL) + { + g_code_block_link_with(G_CODE_BLOCK(block), target, dest->type); + g_object_unref(G_OBJECT(target)); + } -/****************************************************************************** -* * -* Paramètres : list = liste de blocs basiques à compléter. * -* block = bloc d'instructions basique à intégrer. * -* index = indice de la position d'insertion du bloc. * -* * -* Description : Ajoute un bloc basique à une liste définie. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + unref_instr_link(dest); -void g_block_list_add_block(GBlockList *list, GBasicBlock *block, size_t index) -{ - assert(index < list->count); - assert(list->blocks[index] == NULL); + } - list->blocks[index] = block; + g_arch_instruction_unlock_dest(block->last); } /****************************************************************************** * * -* Paramètres : list = liste de blocs basiques à consulter. * -* index = indice de la position du bloc recherché. * +* Paramètres : block = bloc de code à manipuler. * +* highlighted = gestionnaire de surbrillance pour segments. * * * -* Description : Fournit un bloc basique à d'une liste définie. * +* Description : Fournit la représentation graphique d'un bloc de code. * * * -* Retour : Bloc d'instructions basique trouvé. * +* Retour : Vue d'un cache de lignes. * * * * Remarques : - * * * ******************************************************************************/ -GBasicBlock *g_block_list_get_block(const GBlockList *list, size_t index) +static GBufferView *g_basic_block_build_view(const GBasicBlock *block, segcnt_list *highlighted) { - assert(index < list->count); + GBufferView *result; /* Instance à retourner */ + const mrange_t *first_range; /* Couverture d'instruction #1 */ + const mrange_t *last_range; /* Couverture d'instruction #2 */ + GLineCursor *start; /* Départ de zone couverture */ + GLineCursor *end; /* Fin de zone couverture */ + GBufferCache *cache; /* Tampon brut à découper */ - return list->blocks[index]; + first_range = g_arch_instruction_get_range(block->first); + last_range = g_arch_instruction_get_range(block->last); -} + start = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(start), get_mrange_addr(first_range)); + end = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(end), get_mrange_addr(last_range)); -/****************************************************************************** -* * -* Paramètres : list = liste de blocs basiques à consulter. * -* block = bloc d'instructions basique à considérer. * -* * -* Description : Fournit l'indice d'un bloc basique d'une liste de blocs. * -* * -* Retour : Indice de la position du bloc fourni en cas de succès. * -* * -* Remarques : - * -* * -******************************************************************************/ + cache = g_loaded_binary_get_disassembled_cache(block->binary); -size_t g_block_list_get_index(const GBlockList *list, GBasicBlock *block) -{ - size_t result; /* Indice trouvé à retourner */ + result = g_buffer_view_new(cache, highlighted); - for (result = 0; result < list->count; result++) - if (list->blocks[result] == block) - break; + g_buffer_view_restrict(result, start, end); return result; @@ -562,37 +348,30 @@ size_t g_block_list_get_index(const GBlockList *list, GBasicBlock *block) /****************************************************************************** * * -* Paramètres : list = liste de blocs basiques à consulter. * -* instr = instruction de début de bloc recherchée. * +* Paramètres : block = bloc d'instructions à consulter. * +* first = instruction de départ du bloc. [OUT] * +* last = dernière instruction du bloc. [OUT] * * * -* Description : Recherche un bloc basique selon une première instruction. * +* Description : Fournit les instructions limites d'un bloc basique. * * * -* Retour : Bloc basique trouvé ou NULL si aucun. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GBasicBlock *g_block_list_find_by_starting_instr(const GBlockList *list, GArchInstruction *instr) +void g_basic_block_get_boundary(const GBasicBlock *block, GArchInstruction **first, GArchInstruction **last) { - GBasicBlock *result; /* Trouvaille à retourner */ - size_t i; /* Boucle de parcours */ - GBasicBlock *block; /* Bloc basique analysé */ - GArchInstruction *first; /* Première instruction du bloc*/ - - result = NULL; - - for (i = 0; i < list->count && result == NULL; i++) + if (first != NULL) { - block = list->blocks[i]; - - g_basic_block_get_boundary(block, &first, NULL); - - if (instr == first) - result = block; - + *first = block->first; + g_object_ref(G_OBJECT(*first)); } - return result; + if (last != NULL) + { + *last = block->last; + g_object_ref(G_OBJECT(*last)); + } } |