summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-01-13 23:44:21 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-01-13 23:44:21 (GMT)
commit2a6d92e2d55c0a7826137b2cc2e3148bb298abb9 (patch)
tree55714d85528a4cbe15e802b8a7bc2cdbf861c744 /src/analysis/disass
parent2ed3c9274c8dafb660bc25743a1aac7c72c12965 (diff)
Provided uncached code block links.
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/block.c114
-rw-r--r--src/analysis/disass/rank.c13
2 files changed, 113 insertions, 14 deletions
diff --git a/src/analysis/disass/block.c b/src/analysis/disass/block.c
index 6cf7c17..23393f6 100644
--- a/src/analysis/disass/block.c
+++ b/src/analysis/disass/block.c
@@ -25,6 +25,7 @@
#include <assert.h>
+#include <malloc.h>
#include "../block-int.h"
@@ -70,8 +71,11 @@ 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 *);
+/* Fournit les détails des origines d'un bloc de code donné. */
+static block_link_t *g_basic_block_get_sources(const GBasicBlock *, const GBlockList *, size_t *);
+
+/* Fournit les détails des destinations de bloc de code. */
+static block_link_t *g_basic_block_get_destinations(const GBasicBlock *, const GBlockList *, size_t *);
/* Fournit la représentation graphique d'un bloc de code. */
static GBufferView *g_basic_block_build_view(const GBasicBlock *, segcnt_list *);
@@ -112,7 +116,8 @@ static void g_basic_block_class_init(GBasicBlockClass *class)
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->get_src = (block_get_links_fc)g_basic_block_get_sources;
+ block->get_dest = (block_get_links_fc)g_basic_block_get_destinations;
block->build = (block_build_view_fc)g_basic_block_build_view;
}
@@ -248,24 +253,102 @@ static bool g_basic_block_is_starting_with(const GBasicBlock *block, const vmpa2
/******************************************************************************
* *
-* Paramètres : block = bloc de code à mettre à jour. *
+* Paramètres : block = bloc dont les informations sont à consulter. *
* list = ensemble des blocs de code à disposition. *
+* count = nombre de ces origines. [OUT] *
* *
-* Description : Etablit les liens entre un bloc de code et ses voisins. *
+* Description : Fournit les détails des origines d'un bloc de code donné. *
* *
-* Retour : - *
+* Retour : Liens déterminés vers des blocs de code d'origine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static block_link_t *g_basic_block_get_sources(const GBasicBlock *block, const GBlockList *list, size_t *count)
+{
+ block_link_t *result; /* Détails présents à renvoyer */
+ size_t scount; /* Nombre de liens d'origine */
+ size_t i; /* Boucle de parcours */
+ const instr_link_t *src; /* Instr. visée par une autre */
+ const mrange_t *range; /* Couverture d'instruction */
+ GCodeBlock *target; /* Bloc ciblé par un lien */
+ block_link_t *new; /* Nouvelle entrée à définir */
+
+ result = NULL;
+ *count = 0;
+
+ g_arch_instruction_lock_src(block->first);
+ scount = g_arch_instruction_count_sources(block->first);
+
+ for (i = 0; i < scount; i++)
+ {
+ src = g_arch_instruction_get_source(block->first, i);
+
+ range = g_arch_instruction_get_range(src->linked);
+
+ target = g_block_list_find_by_starting_addr(list, get_mrange_addr(range));
+
+ /**
+ * Les liens ne sont pas toujours internes !
+ */
+
+ if (target != NULL)
+ {
+ result = realloc(result, ++(*count) * sizeof(block_link_t));
+
+ new = &result[*count - 1];
+
+ new->linked = target;
+ new->type = src->type;
+
+ /**
+ * On pourrait par optimisation retirer les deux lignes suivantes...
+ */
+
+ ref_block_link(new);
+
+ g_object_unref(G_OBJECT(target));
+
+ }
+
+ unref_instr_link(src);
+
+ }
+
+ g_arch_instruction_unlock_src(block->first);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : block = bloc dont les informations sont à consulter. *
+* list = ensemble des blocs de code à disposition. *
+* count = nombre de ces destinations. [OUT] *
+* *
+* Description : Fournit les détails des destinations de bloc de code. *
+* *
+* Retour : Liens déterminés vers des blocs de code de destination. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_basic_block_resolve_links(GBasicBlock *block, const GBlockList *list)
+static block_link_t *g_basic_block_get_destinations(const GBasicBlock *block, const GBlockList *list, size_t *count)
{
+ block_link_t *result; /* Détails présents à renvoyer */
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 */
+ block_link_t *new; /* Nouvelle entrée à définir */
+
+ result = NULL;
+ *count = 0;
g_arch_instruction_lock_dest(block->last);
dcount = g_arch_instruction_count_destinations(block->last);
@@ -291,8 +374,21 @@ static void g_basic_block_resolve_links(GBasicBlock *block, const GBlockList *li
if (target != NULL)
{
- g_code_block_link_with(G_CODE_BLOCK(block), target, dest->type);
+ result = realloc(result, ++(*count) * sizeof(block_link_t));
+
+ new = &result[*count - 1];
+
+ new->linked = target;
+ new->type = dest->type;
+
+ /**
+ * On pourrait par optimisation retirer les deux lignes suivantes...
+ */
+
+ ref_block_link(new);
+
g_object_unref(G_OBJECT(target));
+
}
unref_instr_link(dest);
@@ -301,6 +397,8 @@ static void g_basic_block_resolve_links(GBasicBlock *block, const GBlockList *li
g_arch_instruction_unlock_dest(block->last);
+ return result;
+
}
diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c
index b6eb4c5..d703aee 100644
--- a/src/analysis/disass/rank.c
+++ b/src/analysis/disass/rank.c
@@ -50,19 +50,19 @@ void rank_routine_block(const GBlockList *list, GCodeBlock *block)
{
size_t next; /* Rang suivant obtenu */
size_t dcount; /* Nombre de liens de dest. */
+ block_link_t *links; /* Liens associés au bloc */
size_t i; /* Boucle de parcours */
- const block_link_t *dest; /* Instr. visée par une autre */
+ block_link_t *dest; /* Bloc visé par un autre */
InstructionLinkType type; /* Raccourci pour confort */
unsigned int rank; /* Rang à constituer */
next = g_code_block_get_rank(block) + 1;
- g_code_block_lock_dest(block);
- dcount = g_code_block_count_destinations(block);
+ links = g_code_block_get_destinations(block, &dcount);
for (i = 0; i < dcount; i++)
{
- dest = g_code_block_get_destination(block, i);
+ dest = &links[i];
type = dest->type;
@@ -93,11 +93,12 @@ void rank_routine_block(const GBlockList *list, GCodeBlock *block)
next_dest:
- unref_instr_link(dest);
+ unref_block_link(dest);
}
- g_code_block_unlock_dest(block);
+ if (links != NULL)
+ free(links);
}