diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2019-01-13 23:44:21 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2019-01-13 23:44:21 (GMT) |
commit | 2a6d92e2d55c0a7826137b2cc2e3148bb298abb9 (patch) | |
tree | 55714d85528a4cbe15e802b8a7bc2cdbf861c744 /src/analysis | |
parent | 2ed3c9274c8dafb660bc25743a1aac7c72c12965 (diff) |
Provided uncached code block links.
Diffstat (limited to 'src/analysis')
-rw-r--r-- | src/analysis/block-int.h | 12 | ||||
-rw-r--r-- | src/analysis/block.c | 320 | ||||
-rw-r--r-- | src/analysis/block.h | 33 | ||||
-rw-r--r-- | src/analysis/disass/block.c | 114 | ||||
-rw-r--r-- | src/analysis/disass/rank.c | 13 |
5 files changed, 160 insertions, 332 deletions
diff --git a/src/analysis/block-int.h b/src/analysis/block-int.h index b9b90f0..ca38703 100644 --- a/src/analysis/block-int.h +++ b/src/analysis/block-int.h @@ -38,8 +38,8 @@ /* Détermine si un bloc de code débute à une adresse donnée. */ typedef bool (* block_is_starting_fc) (const GCodeBlock *, const vmpa2t *); -/* Etablit les liens entre un bloc de code et ses voisins. */ -typedef void (* block_resolve_links_fc) (GCodeBlock *, const GBlockList *); +/* Fournit les détails des origines d'un bloc de code donné. */ +typedef block_link_t * (* block_get_links_fc) (const GCodeBlock *, const GBlockList *, size_t *); /* Fournit la représentation graphique d'un bloc de code. */ typedef GBufferView * (* block_build_view_fc) (const GCodeBlock *, segcnt_list *); @@ -50,14 +50,13 @@ struct _GCodeBlock { GObject parent; /* A laisser en premier */ + GBlockList *list; /* Lien vers l'ensemble */ + bitfield_t *domination; /* Blocs dominés de l'ensemble */ size_t index; /* Indice dans une liste */ size_t rank; /* Rang dans l'exécution */ - flat_array_t *from; /* Origines des références */ - flat_array_t *to; /* Instructions visées */ - GBufferView *view; /* Représentation construite */ }; @@ -68,7 +67,8 @@ struct _GCodeBlockClass GObjectClass parent; /* A laisser en premier */ block_is_starting_fc is_starting; /* Analyse d'adresse initiale */ - block_resolve_links_fc link; /* Etablissement des liens */ + block_get_links_fc get_src; /* Obtention des origines */ + block_get_links_fc get_dest; /* Obtention des destinations */ block_build_view_fc build; /* Construction d'une vue */ }; diff --git a/src/analysis/block.c b/src/analysis/block.c index a23634c..7003ccd 100644 --- a/src/analysis/block.c +++ b/src/analysis/block.c @@ -50,9 +50,6 @@ static void g_code_block_finalize(GCodeBlock *); /* Indique l'indice d'intégration du bloc dans une liste. */ static void g_code_block_set_index(GCodeBlock *, size_t); -/* Etablit les liens entre un bloc de code et ses voisins. */ -static void g_code_block_resolve_links(GCodeBlock *, const GBlockList *); - /* ------------------------- REGROUPEMENT EN LISTE DE BLOCS ------------------------- */ @@ -137,12 +134,11 @@ static void g_code_block_class_init(GCodeBlockClass *class) static void g_code_block_init(GCodeBlock *block) { + block->list = NULL; + block->index = (size_t)-1; block->rank = (size_t)-1; - block->from = NULL; - block->to = NULL; - block->view = NULL; } @@ -162,17 +158,7 @@ static void g_code_block_init(GCodeBlock *block) static void g_code_block_dispose(GCodeBlock *block) { -#ifndef NDEBUG - g_code_block_lock_src(block); - assert(count_flat_array_items(block->from) == 0); - g_code_block_unlock_src(block); -#endif - -#ifndef NDEBUG - g_code_block_lock_dest(block); - assert(count_flat_array_items(block->to) == 0); - g_code_block_unlock_dest(block); -#endif + g_clear_object(&block->list); g_clear_object(&block->view); @@ -297,30 +283,6 @@ bool g_code_block_is_starting_with(const GCodeBlock *block, const vmpa2t *addr) /****************************************************************************** * * -* Paramètres : block = bloc de code à mettre à jour. * -* list = ensemble des blocs de code à disposition. * -* * -* Description : Etablit les liens entre un bloc de code et ses voisins. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_code_block_resolve_links(GCodeBlock *block, const GBlockList *list) -{ - GCodeBlockClass *class; /* Classe des blocs de code */ - - class = G_CODE_BLOCK_GET_CLASS(block); - - class->link(block, list); - -} - - -/****************************************************************************** -* * * Paramètres : block = bloc de code à consulter. * * * * Description : Fournit le rang du bloc de code dans le flot d'exécution. * @@ -405,205 +367,36 @@ GBufferView *g_code_block_get_view(GCodeBlock *block, segcnt_list *highlighted) /****************************************************************************** * * -* Paramètres : block = bloc de code à mettre à jour. * -* src = sélection de l'extrémité à traiter. * -* lock = indique le sens du verrouillage à mener. * -* * -* Description : Met à disposition un encadrement des accès aux liens. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_block_lock_unlock_links(GCodeBlock *block, bool src, bool lock) -{ - flat_array_t **array; /* Choix du tableau ciblé */ - - array = (src ? &block->from : &block->to); - - if (lock) - lock_flat_array(array); - else - unlock_flat_array(array); - -} - - -/****************************************************************************** -* * * Paramètres : block = bloc dont les informations sont à consulter. * -* dest = bloc de code visé par la liaison (côté destination). * -* type = type de lien à construire. * +* count = nombre de ces origines. [OUT] * * * -* Description : Etablit un lien entre deux blocs de code. * +* 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 : - * * * ******************************************************************************/ -void g_code_block_link_with(GCodeBlock *block, GCodeBlock *dest, InstructionLinkType type) +block_link_t *g_code_block_get_sources(const GCodeBlock *block, size_t *count) { - block_link_t new_src; /* Nouveau lien à définir #1 */ - block_link_t new_dst; /* Nouveau lien à définir #2 */ - - /* Côté destination */ - - new_src.linked = block; - new_src.type = type; - - ref_block_link((&new_src)); - - /* Côté point de départ */ - - new_dst.linked = dest; - new_dst.type = type; - - ref_block_link((&new_dst)); - - /* Ajout dans le respect d'une cohérence globale */ - - g_code_block_lock_src(dest); - g_code_block_lock_dest(block); - - add_item_to_flat_array(&dest->from, &new_src, sizeof(block_link_t)); - - add_item_to_flat_array(&block->to, &new_dst, sizeof(block_link_t)); - - g_code_block_unlock_dest(block); - g_code_block_unlock_src(dest); - -} - - -/****************************************************************************** -* * -* Paramètres : block = bloc de code dont les informations sont à traiter. * -* * -* Description : Supprime tous les liens établis avec d'autres blocs de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_code_block_delete_all_links(GCodeBlock *block) -{ - block_link_t *link_src; /* Lien à supprimer #2 */ - GCodeBlock *other; /* Bloc de l'autre bout */ - size_t count; /* Quantié de liens présents */ - size_t i; /* Boucle de parcours */ - block_link_t *link_dst; /* Lien à supprimer #1 */ - - /* Coté sources */ - - g_code_block_lock_src(block); + block_link_t *result; /* Détails présents à renvoyer */ + GCodeBlockClass *class; /* Classe des blocs de code */ - while (count_flat_array_items(block->from) > 0) + if (block->list == NULL) { - link_src = get_flat_array_item(block->from, 0, sizeof(block_link_t)); - - other = link_src->linked; - - g_code_block_lock_dest(other); - - count = count_flat_array_items(other->to); - - for (i = 0; i < count; i++) - { - link_dst = get_flat_array_item(other->to, i, sizeof(block_link_t)); - - if (link_dst->linked == block && link_dst->type == link_src->type) - { - unref_block_link(link_dst); - - rem_item_from_flat_array(&other->to, i, sizeof(block_link_t)); - - break; - - } - - } - - assert(i < count); - - g_code_block_unlock_dest(other); - - unref_block_link(link_src); - - rem_item_from_flat_array(&block->from, 0, sizeof(block_link_t)); - + result = NULL; + *count = 0; } - g_code_block_unlock_src(block); - - /* Coté destinations */ - - g_code_block_lock_dest(block); - - while (count_flat_array_items(block->to) > 0) + else { - link_dst = get_flat_array_item(block->to, 0, sizeof(block_link_t)); - - other = link_dst->linked; - - g_code_block_lock_src(other); - - count = count_flat_array_items(other->from); - - for (i = 0; i < count; i++) - { - link_src = get_flat_array_item(other->from, i, sizeof(block_link_t)); - - if (link_src->linked == block && link_src->type == link_dst->type) - { - unref_block_link(link_src); - - rem_item_from_flat_array(&other->from, i, sizeof(block_link_t)); - - break; - - } - - } - - assert(i < count); - - g_code_block_unlock_src(other); - - unref_block_link(link_dst); + class = G_CODE_BLOCK_GET_CLASS(block); - rem_item_from_flat_array(&block->to, 0, sizeof(block_link_t)); + result = class->get_src(block, block->list, count); } - g_code_block_unlock_dest(block); - -} - - -/****************************************************************************** -* * -* Paramètres : block = bloc dont les informations sont à consulter. * -* * -* Description : Fournit la quantité de blocs de code pointant vers un autre. * -* * -* Retour : Nombre de ces origines. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_code_block_count_sources(const GCodeBlock *block) -{ - size_t result; /* Nombre de liens à renvoyer */ - - result = count_flat_array_items(block->from); - return result; } @@ -612,72 +405,34 @@ size_t g_code_block_count_sources(const GCodeBlock *block) /****************************************************************************** * * * Paramètres : block = bloc dont les informations sont à consulter. * -* index = indice de l'élément à retrouver. * +* count = nombre de ces destinations. [OUT] * * * -* Description : Fournit les détails d'une origine d'un bloc de code donné. * +* Description : Fournit les détails des destinations de bloc de code. * * * -* Retour : Lien déterminé vers un bloc de code d'origine. * +* Retour : Liens déterminés vers des blocs de code de destination. * * * * Remarques : - * * * ******************************************************************************/ -const block_link_t *g_code_block_get_source(GCodeBlock *block, size_t index) +block_link_t *g_code_block_get_destinations(const GCodeBlock *block, size_t *count) { block_link_t *result; /* Détails présents à renvoyer */ + GCodeBlockClass *class; /* Classe des blocs de code */ - result = get_flat_array_item(block->from, index, sizeof(block_link_t)); - - ref_block_link(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : block = bloc dont les informations sont à consulter. * -* * -* Description : Donne le nombre de blocs de code suivants dans le flot. * -* * -* Retour : Nombre de ces destinations. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_code_block_count_destinations(const GCodeBlock *block) -{ - size_t result; /* Nombre de liens à renvoyer */ - - result = count_flat_array_items(block->to); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : block = bloc dont les informations sont à consulter. * -* index = indice de l'élément à retrouver. * -* * -* Description : Fournit les détails d'une destination de bloc de code. * -* * -* Retour : Lien déterminé vers un bloc de code de destination. * -* * -* Remarques : - * -* * -******************************************************************************/ + if (block->list == NULL) + { + result = NULL; + *count = 0; + } -const block_link_t *g_code_block_get_destination(GCodeBlock *block, size_t index) -{ - block_link_t *result; /* Détails présents à renvoyer */ + else + { + class = G_CODE_BLOCK_GET_CLASS(block); - result = get_flat_array_item(block->to, index, sizeof(block_link_t)); + result = class->get_dest(block, block->list, count); - ref_block_link(result); + } return result; @@ -755,11 +510,7 @@ static void g_block_list_dispose(GBlockList *list) size_t i; /* Boucle de parcours */ for (i = 0; i < list->count; i++) - if (list->blocks[i] != NULL) - { - g_code_block_delete_all_links(list->blocks[i]); - g_clear_object(&list->blocks[i]); - } + g_clear_object(&list->blocks[i]); G_OBJECT_CLASS(g_block_list_parent_class)->dispose(G_OBJECT(list)); @@ -806,7 +557,7 @@ GBlockList *g_block_list_new(size_t count) result = g_object_new(G_TYPE_BLOCK_LIST, NULL); - result->blocks = (GCodeBlock **)calloc(count, sizeof(GCodeBlock *)); + result->blocks = calloc(count, sizeof(GCodeBlock *)); result->count = count; @@ -859,6 +610,9 @@ void g_block_list_add_block(GBlockList *list, GCodeBlock *block, size_t index) list->blocks[index] = block; + block->list = list; + g_object_ref(G_OBJECT(list)); + g_code_block_set_index(block, index); } @@ -879,10 +633,6 @@ void g_block_list_add_block(GBlockList *list, GCodeBlock *block, size_t index) void g_block_list_resolve_links(const GBlockList *list) { - size_t i; /* Boucle de parcours */ - - for (i = 0; i < list->count; i++) - g_code_block_resolve_links(list->blocks[i], list); } diff --git a/src/analysis/block.h b/src/analysis/block.h index 21eaaa5..23637d7 100644 --- a/src/analysis/block.h +++ b/src/analysis/block.h @@ -88,36 +88,15 @@ typedef struct _block_link_t } block_link_t; -#define ref_block_link(l) g_object_ref(G_OBJECT(l->linked)); -#define unref_block_link(l) g_object_unref(G_OBJECT(l->linked)); +#define ref_block_link(l) g_object_ref(G_OBJECT((l)->linked)); +#define unref_block_link(l) g_object_unref(G_OBJECT((l)->linked)); -/* Met à disposition un encadrement des accès aux liens. */ -void g_code_block_lock_unlock_links(GCodeBlock *, bool, bool); +/* Fournit les détails des origines d'un bloc de code donné. */ +block_link_t *g_code_block_get_sources(const GCodeBlock *, size_t *); -/* Etablit un lien entre deux blocs de code. */ -void g_code_block_link_with(GCodeBlock *, GCodeBlock *, InstructionLinkType); - -/* Supprime tous les liens établis avec d'autres blocs de code. */ -void g_code_block_delete_all_links(GCodeBlock *block); - -#define g_code_block_lock_src(blk) g_code_block_lock_unlock_links(blk, true, true) -#define g_code_block_unlock_src(blk) g_code_block_lock_unlock_links(blk, true, false) - -/* Fournit la quantité de blocs de code pointant vers un autre. */ -size_t g_code_block_count_sources(const GCodeBlock *); - -/* Fournit les détails d'une origine d'un bloc de code donné. */ -const block_link_t *g_code_block_get_source(GCodeBlock *, size_t); - -#define g_code_block_lock_dest(blk) g_code_block_lock_unlock_links(blk, false, true) -#define g_code_block_unlock_dest(blk) g_code_block_lock_unlock_links(blk, false, false) - -/* Donne le nombre de blocs de code suivants dans le flot. */ -size_t g_code_block_count_destinations(const GCodeBlock *); - -/* Fournit les détails d'une destination de bloc de code. */ -const block_link_t *g_code_block_get_destination(GCodeBlock *, size_t); +/* Fournit les détails des destinations de bloc de code. */ +block_link_t *g_code_block_get_destinations(const GCodeBlock *, size_t *); 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); } |