summaryrefslogtreecommitdiff
path: root/src/analysis/disass/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass/block.c')
-rw-r--r--src/analysis/disass/block.c453
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));
+ }
}