summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-08-08 19:59:34 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-08-08 19:59:34 (GMT)
commitb3b515ba37ef58751e5407bfcdff2dd67932b99a (patch)
tree88dabcde3d63e87e7ac0c7509629346dde066429 /src/analysis/disass
parent0442cf03782e65bd680449cc213ace9a21bb081b (diff)
Defined a new kind of code blocks.
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/block.c453
-rw-r--r--src/analysis/disass/block.h57
-rw-r--r--src/analysis/disass/disassembler.c25
-rw-r--r--src/analysis/disass/dragon.c10
-rw-r--r--src/analysis/disass/dragon.h5
-rw-r--r--src/analysis/disass/rank.c318
-rw-r--r--src/analysis/disass/routines.c23
-rw-r--r--src/analysis/disass/routines.h6
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);