diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-08-08 19:59:34 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-08-08 19:59:34 (GMT) |
commit | b3b515ba37ef58751e5407bfcdff2dd67932b99a (patch) | |
tree | 88dabcde3d63e87e7ac0c7509629346dde066429 /src/analysis/disass | |
parent | 0442cf03782e65bd680449cc213ace9a21bb081b (diff) |
Defined a new kind of code blocks.
Diffstat (limited to 'src/analysis/disass')
-rw-r--r-- | src/analysis/disass/block.c | 453 | ||||
-rw-r--r-- | src/analysis/disass/block.h | 57 | ||||
-rw-r--r-- | src/analysis/disass/disassembler.c | 25 | ||||
-rw-r--r-- | src/analysis/disass/dragon.c | 10 | ||||
-rw-r--r-- | src/analysis/disass/dragon.h | 5 | ||||
-rw-r--r-- | src/analysis/disass/rank.c | 318 | ||||
-rw-r--r-- | src/analysis/disass/routines.c | 23 | ||||
-rw-r--r-- | src/analysis/disass/routines.h | 6 |
8 files changed, 175 insertions, 722 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)); + } } diff --git a/src/analysis/disass/block.h b/src/analysis/disass/block.h index 68cade7..eab0b27 100644 --- a/src/analysis/disass/block.h +++ b/src/analysis/disass/block.h @@ -28,6 +28,8 @@ #include <glib-object.h> +#include "../binary.h" +#include "../block.h" #include "../../arch/instruction.h" #include "../../common/bits.h" @@ -55,64 +57,11 @@ typedef struct _GBasicBlockClass GBasicBlockClass; GType g_basic_block_get_type(void); /* Crée un bloc basique d'exécution d'instructions. */ -GBasicBlock *g_basic_block_new(GArchInstruction *, GArchInstruction *, const bitfield_t *); +GCodeBlock *g_basic_block_new(GLoadedBinary *, GArchInstruction *, GArchInstruction *, const bitfield_t *); /* Fournit les instructions limites d'un bloc basique. */ void g_basic_block_get_boundary(const GBasicBlock *, GArchInstruction **, GArchInstruction **); -/* Fournit les adresses limites d'un bloc basique. */ -void g_basic_block_get_boundary_addresses(const GBasicBlock *, vmpa2t *, vmpa2t *); - -/* Fournit le rang du bloc basique dans le flot d'exécution. */ -unsigned int g_basic_block_get_rank(const GBasicBlock *); - -/* Définit le rang du bloc basique dans le flot d'exécution. */ -void g_basic_block_set_rank(GBasicBlock *, unsigned int); - -/* Indique la liste des blocs de code dominés. */ -const bitfield_t *g_basic_block_get_domination(const GBasicBlock *); - - - -/* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */ - - -#define G_TYPE_BLOCK_LIST g_block_list_get_type() -#define G_BLOCK_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_block_list_get_type(), GBlockList)) -#define G_IS_BLOCK_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_block_list_get_type())) -#define G_BLOCK_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BLOCK_LIST, GBlockListClass)) -#define G_IS_BLOCK_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BLOCK_LIST)) -#define G_BLOCK_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BLOCK_LIST, GBlockListClass)) - - -/* Description d'une liste de blocs basiques (instance) */ -typedef struct _GBlockList GBlockList; - -/* Description d'une liste de blocs basiques (classe) */ -typedef struct _GBlockListClass GBlockListClass; - - -/* Indique le type défini pour une liste de blocs basiques. */ -GType g_block_list_get_type(void); - -/* Crée une liste de blocs basiques. */ -GBlockList *g_block_list_new(size_t); - -/* Compte le nombre de blocs basiques représentés. */ -size_t g_block_list_count_blocks(const GBlockList *); - -/* Ajoute un bloc basique à une liste définie. */ -void g_block_list_add_block(GBlockList *, GBasicBlock *, size_t); - -/* Fournit un bloc basique à d'une liste définie. */ -GBasicBlock *g_block_list_get_block(const GBlockList *, size_t ); - -/* Fournit l'indice d'un bloc basique d'une liste de blocs. */ -size_t g_block_list_get_index(const GBlockList *, GBasicBlock *); - -/* Recherche un bloc basique selon une première instruction. */ -GBasicBlock *g_block_list_find_by_starting_instr(const GBlockList *, GArchInstruction *); - #endif /* _ANALYSIS_DISASS_BLOCK_H */ diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 6e71ed6..f229af3 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -52,7 +52,7 @@ static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GProcContext *, GExeFormat *); /* Opère sur toutes les routines. */ -static void process_all_routines(wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb, GArchProcessor *, GBinFormat *); +static void process_all_routines(GLoadedBinary *, wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb); /* Réalise un désassemblage effectif. */ static void compute_disassembly(GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *); @@ -127,12 +127,11 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co /****************************************************************************** * * -* Paramètres : gid = groupe de travail impliqué. * +* Paramètres : binary = binaire chargé comprenant les routines à traiter. * +* gid = groupe de travail impliqué. * status = barre de statut à tenir informée. * * msg = message à faire paraître pour la patience. * * fallback = routine de traitements particuliers. * -* proc = ensemble d'instructions désassemblées. * -* format = accès aux données du binaire d'origine. * * * * Description : Opère sur toutes les routines. * * * @@ -142,8 +141,9 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co * * ******************************************************************************/ -static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback, GArchProcessor *proc, GBinFormat *format) +static void process_all_routines(GLoadedBinary *binary, wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback) { + GBinFormat *format; /* Format associé au binaire */ GBinPortion *portions; /* Couche première de portions */ size_t sym_count; /* Nombre de ces symboles */ guint runs_count; /* Qté d'exécutions parallèles */ @@ -155,6 +155,8 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const size_t end; /* Fin d'un bloc de traitement */ GRoutinesStudy *study; /* Tâche d'étude à programmer */ + format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + portions = g_exe_format_get_portions(G_EXE_FORMAT(format)); g_binary_format_lock_symbols_rd(format); @@ -178,8 +180,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const else end = begin + run_size; - study = g_routines_study_new(proc, format, portions, - begin, end, id, fallback); + study = g_routines_study_new(binary, portions, begin, end, id, fallback); g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid); @@ -193,6 +194,8 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const g_object_unref(G_OBJECT(portions)); + g_object_unref(G_OBJECT(format)); + } @@ -293,9 +296,9 @@ static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wg * Quatrième étape : établissement des couvertures de routines restantes. */ - process_all_routines(gid, status, + process_all_routines(binary, gid, status, _("Finding remaining limits..."), - g_routines_study_compute_limits, proc, G_BIN_FORMAT(format)); + g_routines_study_compute_limits); process_disassembly_event(PGA_DISASSEMBLY_LIMITED, binary, status, context); @@ -317,9 +320,9 @@ static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wg * Sixième étape : regroupement en blocs basiques. */ - process_all_routines(gid, status, + process_all_routines(binary, gid, status, _("Control-flow analysis for routines..."), - g_routines_study_handle_blocks, proc, G_BIN_FORMAT(format)); + g_routines_study_handle_blocks); process_disassembly_event(PGA_DISASSEMBLY_GROUPED, binary, status, context); diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c index 04f5190..ad20b24 100644 --- a/src/analysis/disass/dragon.c +++ b/src/analysis/disass/dragon.c @@ -28,6 +28,9 @@ #include <malloc.h> +#include "block.h" + + /* ---------------------------- ENCAPSULATION DES NOEUDS ---------------------------- */ @@ -801,6 +804,7 @@ dragon_node *find_knight_node_for_instruction(const dragon_knight *knight, bool /****************************************************************************** * * * Paramètres : knight = rassemblement des complexités de code. * +* binary = binaire contenant l'ensemble des instructions. * * * * Description : Traduit une complexité de noeuds en liste de blocs basiques. * * * @@ -810,7 +814,7 @@ dragon_node *find_knight_node_for_instruction(const dragon_knight *knight, bool * * ******************************************************************************/ -GBlockList *translate_dragon_knight(const dragon_knight *knight) +GBlockList *translate_dragon_knight(const dragon_knight *knight, GLoadedBinary *binary) { GBlockList *result; /* Liste à retourner */ dragon_node *nodes; /* Liste des noeuds détectés */ @@ -819,7 +823,7 @@ GBlockList *translate_dragon_knight(const dragon_knight *knight) dragon_node *node; /* Noeud à traiter */ GArchInstruction *first; /* Première instruction */ GArchInstruction *last; /* Dernière instruction */ - GBasicBlock *block; /* Nouveau bloc basique */ + GCodeBlock *block; /* Nouveau bloc basique */ get_dragon_knight_content(knight, &nodes, &count); @@ -831,7 +835,7 @@ GBlockList *translate_dragon_knight(const dragon_knight *knight) get_dragon_node_bounding_instructions(node, &first, &last); - block = g_basic_block_new(first, last, node->bits); + block = g_basic_block_new(binary, first, last, node->bits); g_block_list_add_block(result, block, i); diff --git a/src/analysis/disass/dragon.h b/src/analysis/disass/dragon.h index dfef39f..584f43a 100644 --- a/src/analysis/disass/dragon.h +++ b/src/analysis/disass/dragon.h @@ -25,7 +25,8 @@ #define _ANALYSIS_DISASS_DRAGON_H -#include "block.h" +#include "../binary.h" +#include "../block.h" #include "../../arch/processor.h" #include "../../common/bits.h" @@ -90,7 +91,7 @@ size_t get_dragon_knight_node_index(const dragon_knight *, dragon_node *); dragon_node *find_knight_node_for_instruction(const dragon_knight *, bool, const GArchInstruction *); /* Traduit une complexité de noeuds en liste de blocs basiques. */ -GBlockList *translate_dragon_knight(const dragon_knight *); +GBlockList *translate_dragon_knight(const dragon_knight *, GLoadedBinary *); diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c index 6e737a5..b4a8f92 100644 --- a/src/analysis/disass/rank.c +++ b/src/analysis/disass/rank.c @@ -24,270 +24,12 @@ #include "rank.h" - - -#if 0 - -#include <assert.h> -#include <sys/param.h> - - -#include "../blocks/flow.h" -#include "../blocks/virtual.h" - - - -/* Classe le contenu d'un bloc d'instructions exécutées. */ -static bool rank_flow_block(GFlowBlock *, BlockVisitOrder, const GInstrBlock *); - - - -/****************************************************************************** -* * -* Paramètres : block = bloc d'instructions concerné par la visite. * -* order = indication quant au sens de visite. * -* list = ensemble des blocs basiques à parcourir. * -* * -* Description : Classe le contenu d'un bloc d'instructions exécutées. * -* * -* Retour : true pour continuer la visite. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool rank_flow_block(GFlowBlock *block, BlockVisitOrder order, const GInstrBlock *list) -{ - unsigned int next; /* Rang suivant obtenu */ - GInstrBlock *links; /* Blocs liés au bloc courant */ - GArchInstruction *last; /* Dernière instruction du bloc*/ - 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; /* Emplacement d'une cible */ - GFlowBlock *target; /* Bloc ciblé par un lien */ - unsigned int rank; /* Rang à constituer */ - - /* Si le bloc visité n'est pas basique... */ - if (order != BVO_PENDING) return true; - - next = g_flow_block_get_rank(block) + 1; - - links = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); - - g_flow_block_get_boundary(block, NULL, &last); - - g_arch_instruction_lock_dest(last); - dcount = g_arch_instruction_count_destinations(last); - - for (i = 0; i < dcount; i++) - { - dest = g_arch_instruction_get_destination(last, i); - - range = g_arch_instruction_get_range(dest->linked); - - switch (dest->type) - { - case ILT_EXEC_FLOW: - case ILT_CATCH_EXCEPTION: - target = G_FLOW_BLOCK(g_instr_block_find_by_addr(list, get_mrange_addr(range), true)); - //assert(target != NULL); - break; - - case ILT_JUMP: - target = G_FLOW_BLOCK(g_instr_block_find_by_addr(list, get_mrange_addr(range), true)); - - /** - * 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> - * .... - * - */ - /* assert(target != NULL);*/ - - break; - - case ILT_CASE_JUMP: - target = G_FLOW_BLOCK(g_instr_block_find_by_addr(links, get_mrange_addr(range), true)); - //assert(target != NULL); - break; - - case ILT_JUMP_IF_TRUE: - case ILT_JUMP_IF_FALSE: - - /** - * Même dans les branches if/then/else, il n'y a pas forcément de groupe de blocs - * associé. C'est par exemple le cas dans des constructions telles que celle de - * la fonction __libc_csu_init() : - * - * if (...) - * do - * { - * ... - * } - * while (...) - * - * ... - * - * Le code final est étiquetté comme étant le 'else' de la première condition, - * donc au niveau de la condition de bouclage, il appartient déjà à un autre - * et n'est donc pas réattribué une seconde fois. - * - */ - - if (links != NULL) - target = G_FLOW_BLOCK(g_instr_block_find_by_addr(links, get_mrange_addr(range), true)); - else - target = NULL; - - /** - * Le bloc visé ne se trouve pas toujours dans les blocs attachés : - * - * { bloc IF } - * { bloc THEN } - * { block NEXT } - * - * Le bloc NEXT est ici à rechercher dans la liste globale. - */ - - if (target == NULL) - target = G_FLOW_BLOCK(g_instr_block_find_by_addr(list, get_mrange_addr(range), true)); - - //assert(target != NULL); - - break; - - default: - target = NULL; - break; - - } - - unref_instr_link(dest); - - if (target != NULL) - { - rank = MAX(next, g_flow_block_get_rank(target)); - - g_flow_block_set_rank(target, rank); - - } - - } - - g_arch_instruction_unlock_dest(last); - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : routine = routine regroupant les blocs à traiter. * -* * -* Description : Classe les blocs des routines. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void rank_routine_blocks(GBinRoutine *routine) -{ - GInstrBlock *main_block; /* Ensemble des blocs d'instr. */ - - main_block = g_binary_routine_get_basic_blocks(routine); - - - if (main_block == NULL) return; - - - g_instr_block_visit(main_block, (instr_block_visitor_cb)rank_flow_block, main_block); - - -#if 0 - - printf("===== BLOCK(S) xXXx ======\n"); - - - bool visit_ranked_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 (rank = %u)", - (unsigned int)start.virtual, - (unsigned int)end.virtual, - g_flow_block_get_rank(G_FLOW_BLOCK(blk))); - - } - - printf("\n"); - - if (order == BVO_IN) (*indent)++; - break; - - case BVO_OUT: - (*indent)--; - break; - - } - - return true; - - } - - g_instr_block_visit(main_block, (instr_block_visitor_cb)visit_ranked_block, (int []){ 0 }); - - printf("\n"); - - -#endif - - - - -} - - - -#endif - - - - - - - #include <assert.h> /* Classe les blocs basiques d'une routine. */ -void rank_routine_block(const GBlockList *, GBasicBlock *); - +void rank_routine_block(const GBlockList *, GCodeBlock *); @@ -304,27 +46,23 @@ void rank_routine_block(const GBlockList *, GBasicBlock *); * * ******************************************************************************/ -void rank_routine_block(const GBlockList *list, GBasicBlock *block) +void rank_routine_block(const GBlockList *list, GCodeBlock *block) { - unsigned int next; /* Rang suivant obtenu */ - GArchInstruction *last; /* Dernière instruction du bloc*/ + size_t next; /* Rang suivant obtenu */ 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 block_link_t *dest; /* Instr. visée par une autre */ InstructionLinkType type; /* Raccourci pour confort */ - GBasicBlock *target; /* Bloc ciblé par un lien */ unsigned int rank; /* Rang à constituer */ - next = g_basic_block_get_rank(block) + 1; - - g_basic_block_get_boundary(block, NULL, &last); + next = g_code_block_get_rank(block) + 1; - g_arch_instruction_lock_dest(last); - dcount = g_arch_instruction_count_destinations(last); + g_code_block_lock_dest(block); + dcount = g_code_block_count_destinations(block); for (i = 0; i < dcount; i++) { - dest = g_arch_instruction_get_destination(last, i); + dest = g_code_block_get_destination(block, i); type = dest->type; @@ -343,30 +81,13 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block) && type != ILT_JUMP_IF_FALSE) goto next_dest; - target = g_block_list_find_by_starting_instr(list, dest->linked); + rank = g_code_block_get_rank(dest->linked); - /** - * 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) + if (next > rank || rank == -1) { - rank = g_basic_block_get_rank(target); - - if (next > rank || rank == -1) - { - g_basic_block_set_rank(target, next); + g_code_block_set_rank(dest->linked, next); - rank_routine_block(list, target); - - } + rank_routine_block(list, dest->linked); } @@ -376,7 +97,7 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block) } - g_arch_instruction_unlock_dest(last); + g_code_block_unlock_dest(block); } @@ -396,22 +117,17 @@ void rank_routine_block(const GBlockList *list, GBasicBlock *block) void rank_routine_blocks(GBinRoutine *routine) { GBlockList *blocks; /* Ensemble des blocs d'instr. */ - GBasicBlock *start; /* Bloc basique de départ */ + GCodeBlock *start; /* Bloc basique de départ */ blocks = g_binary_routine_get_basic_blocks(routine); - start = g_block_list_get_block(blocks, 0 /* FIXME */); + start = g_block_list_get_block(blocks, 0); assert(start != NULL); - - g_basic_block_set_rank(start, 0); - + g_code_block_set_rank(start, 0); rank_routine_block(blocks, start); - - - - + g_object_unref(G_OBJECT(start)); } diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c index f04611f..4e65b77 100644 --- a/src/analysis/disass/routines.c +++ b/src/analysis/disass/routines.c @@ -41,6 +41,8 @@ struct _GRoutinesStudy { GDelayedWork parent; /* A laisser en premier */ + GLoadedBinary *binary; /* Binaire en cours d'analyse */ + GArchProcessor *proc; /* Processeur avec ses instr. */ GBinFormat *format; /* Format de fichier manipulé */ GBinPortion *portions; /* Couches de binaire bornées */ @@ -155,6 +157,8 @@ static void g_routines_study_dispose(GRoutinesStudy *study) g_object_unref(G_OBJECT(study->format)); g_object_unref(G_OBJECT(study->proc)); + g_object_unref(G_OBJECT(study->binary)); + G_OBJECT_CLASS(g_routines_study_parent_class)->dispose(G_OBJECT(study)); } @@ -181,8 +185,7 @@ static void g_routines_study_finalize(GRoutinesStudy *study) /****************************************************************************** * * -* Paramètres : proc = ensemble d'instructions désassemblées. * -* format = format de fichier à manipuler. * +* Paramètres : binary = binaire chargé comprenant les routines à traiter. * * portions = ensemble de couches binaires bornées. * * begin = point de départ du parcours de liste. * * end = point d'arrivée exclu du parcours. * @@ -197,24 +200,24 @@ static void g_routines_study_finalize(GRoutinesStudy *study) * * ******************************************************************************/ -GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, GBinFormat *format, GBinPortion *portions, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback) +GRoutinesStudy *g_routines_study_new(GLoadedBinary *binary, GBinPortion *portions, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback) { GRoutinesStudy *result; /* Tâche à retourner */ result = g_object_new(G_TYPE_ROUTINES_STUDY, NULL); - result->proc = proc; - g_object_ref(G_OBJECT(proc)); + result->binary = binary; + g_object_ref(G_OBJECT(binary)); - result->format = format; - g_object_ref(G_OBJECT(format)); + result->proc = g_loaded_binary_get_processor(binary); + result->format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); result->portions = portions; g_object_ref(G_OBJECT(portions)); - g_binary_format_lock_symbols_rd(format); + g_binary_format_lock_symbols_rd(result->format); - result->count = g_binary_format_count_symbols(format); + result->count = g_binary_format_count_symbols(result->format); result->fallback = fallback; result->begin = begin; @@ -397,7 +400,7 @@ void g_routines_study_handle_blocks(GRoutinesStudy *study, GBinRoutine *routine, detect_loops_in_code(knight); - blocks = translate_dragon_knight(knight); + blocks = translate_dragon_knight(knight, study->binary); g_binary_routine_set_basic_blocks(routine, blocks); diff --git a/src/analysis/disass/routines.h b/src/analysis/disass/routines.h index d6fd76b..ce44fec 100644 --- a/src/analysis/disass/routines.h +++ b/src/analysis/disass/routines.h @@ -25,10 +25,8 @@ #define _ANALYSIS_DISASS_ROUTINES_H +#include "../binary.h" #include "../routine.h" -#include "../../arch/processor.h" -#include "../../format/executable.h" -#include "../../format/format.h" #include "../../gtkext/gtkstatusstack.h" @@ -53,7 +51,7 @@ typedef void (* rtn_fallback_cb) (GRoutinesStudy *, GBinRoutine *, size_t); /* Crée une tâche d'étude de routines différée. */ -GRoutinesStudy *g_routines_study_new(GArchProcessor *, GBinFormat *, GBinPortion *, size_t, size_t, activity_id_t, rtn_fallback_cb); +GRoutinesStudy *g_routines_study_new(GLoadedBinary *, GBinPortion *, size_t, size_t, activity_id_t, rtn_fallback_cb); /* Détermine si besoin est les bornes des routines. */ void g_routines_study_compute_limits(GRoutinesStudy *, GBinRoutine *, size_t); |