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