summaryrefslogtreecommitdiff
path: root/src/analysis/blocks/flow.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2013-01-13 20:23:05 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2013-01-13 20:23:05 (GMT)
commit35a6cd881528b5f77ce09476eccb39d02d9cc634 (patch)
tree13e0f080a277eb0647b6917f18fbe2cb84a67369 /src/analysis/blocks/flow.c
parent221bcaeeb06415d501f9abbb9bc4b7d8339af1fe (diff)
Defined the registers allocation needs for each basic block.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@323 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/blocks/flow.c')
-rw-r--r--src/analysis/blocks/flow.c200
1 files changed, 131 insertions, 69 deletions
diff --git a/src/analysis/blocks/flow.c b/src/analysis/blocks/flow.c
index 6fb5849..6f56f9d 100644
--- a/src/analysis/blocks/flow.c
+++ b/src/analysis/blocks/flow.c
@@ -40,8 +40,8 @@ struct _GFlowBlock
GArchInstruction *first; /* Première instruction */
GArchInstruction *last; /* Dernière instruction */
- reg_access *accesses; /* Commodités d'accès #1 */
- size_t count; /* Commodités d'accès #2 */
+ GRAccessList *regs; /* Accès aux registres */
+ GRAccessList *awaited; /* Registres définis pour après*/
};
@@ -66,7 +66,7 @@ static void g_flow_block_dispose(GFlowBlock *);
static void g_flow_block_finalize(GFlowBlock *);
/* Recherche le bloc contenant une adresse donnée. */
-static GInstrBlock *g_flow_block_find_by_addr(const GFlowBlock *, vmpa_t);
+static GInstrBlock *g_flow_block_find_by_addr(const GFlowBlock *, vmpa_t, bool);
/* Parcours le bloc d'instructions dans un ordre donné. */
static bool g_flow_block_visit(GFlowBlock *, instr_block_visitor_cb, void *);
@@ -81,7 +81,7 @@ static void g_flow_block_memorize_access(GFlowBlock *, GArchRegister *, RegAcces
static void g_flow_block_compute_regs_access(GFlowBlock *);
/* Fournit les différents accès aux registres. */
-static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *, size_t *);
+//static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *, size_t *);
@@ -134,7 +134,10 @@ static void g_flow_block_init(GFlowBlock *block)
parent->find_by_addr = (find_by_addr_fc)g_flow_block_find_by_addr;
parent->visit_blocks = (visit_all_blocks_fc)g_flow_block_visit;
parent->list_blocks = (list_all_blocks_fc)g_flow_block_list_all_blocks;
- parent->list_regs = (list_regs_accesses_fc)g_flow_block_list_regs_accesses;
+ //parent->list_regs = (list_regs_accesses_fc)g_flow_block_list_regs_accesses;
+
+ block->regs = g_raccess_list_new();
+ block->awaited = g_raccess_list_new();
}
@@ -153,14 +156,12 @@ static void g_flow_block_init(GFlowBlock *block)
static void g_flow_block_dispose(GFlowBlock *block)
{
- size_t i; /* Boucle de parcours */
-
g_object_unref(G_OBJECT(block->instrs));
g_object_unref(G_OBJECT(block->first));
g_object_unref(G_OBJECT(block->last));
- for (i = 0; i < block->count; i++)
- g_object_unref(G_OBJECT(block->accesses[i].reg));
+ g_object_unref(G_OBJECT(block->regs));
+ g_object_unref(G_OBJECT(block->awaited));
G_OBJECT_CLASS(g_flow_block_parent_class)->dispose(G_OBJECT(block));
@@ -181,9 +182,6 @@ static void g_flow_block_dispose(GFlowBlock *block)
static void g_flow_block_finalize(GFlowBlock *block)
{
- if (block->accesses != NULL)
- free(block->accesses);
-
G_OBJECT_CLASS(g_flow_block_parent_class)->finalize(G_OBJECT(block));
}
@@ -242,6 +240,7 @@ GInstrBlock *g_flow_block_new(GArchInstruction *instrs, GArchInstruction *first,
* *
* Paramètres : block = bloc de départ des recherches. *
* addr = ensemble de blocs à parcourir. *
+* final = indique si la cible ou le conteneur est renvoyée. *
* *
* Description : Recherche le bloc contenant une adresse donnée. *
* *
@@ -251,7 +250,7 @@ GInstrBlock *g_flow_block_new(GArchInstruction *instrs, GArchInstruction *first,
* *
******************************************************************************/
-static GInstrBlock *g_flow_block_find_by_addr(const GFlowBlock *block, vmpa_t addr)
+static GInstrBlock *g_flow_block_find_by_addr(const GFlowBlock *block, vmpa_t addr, bool final)
{
GInstrBlock *result; /* Resultat à retourner */
vmpa_t start; /* Adresse de début du bloc */
@@ -331,47 +330,28 @@ static void g_flow_block_list_all_blocks(const GFlowBlock *block, GInstrBlock **
static void g_flow_block_memorize_access(GFlowBlock *block, GArchRegister *reg, RegAccessType type, vmpa_t addr)
{
- reg_access **accesses; /* Commodités d'accès #1 */
- size_t *count; /* Commodités d'accès #2 */
- reg_access *access; /* Accès à manipuler */
- bool need_sort; /* Insertion donc tri à faire */
-
- accesses = &block->accesses;
- count = &block->count;
-
- /* Recherche de l'élément à mettre à jour */
+ reg_access *found; /* Accès à mettre à jour */
+ reg_access access; /* Accès à mettre en place */
- access = bsearch((reg_access []) { { .reg = reg } }, *accesses, *count, sizeof(reg_access),
- (__compar_fn_t)compare_reg_accesses);
+ found = g_raccess_list_find(block->regs, reg);
- if (access == NULL)
+ /* Simpple mise à jour ? */
+ if (found != NULL)
{
- *accesses = (reg_access *)realloc(*accesses, ++(*count) * sizeof(reg_access));
- access = &(*accesses)[*count - 1];
-
- g_object_ref(G_OBJECT(reg));
-
- access->reg = reg;
- access->first_access = RAT_NONE;
- access->last_write = VMPA_MAX;
-
- need_sort = true;
-
+ if (type == RAT_WRITE)
+ found->last_write = addr;
}
- else need_sort = false;
-
- /* Mise à jour */
-
- if (access->first_access == RAT_NONE)
- access->first_access = type;
- if (type == RAT_WRITE)
- access->last_write = addr;
+ /* Ou ajout pur et simple ? */
+ else
+ {
+ access.reg = reg;
+ access.first_access = type;
+ access.last_write = (type == RAT_WRITE ? addr : VMPA_MAX);
- /* Remise en conditions éventuelle */
+ g_raccess_list_add(block->regs, &access);
- if (need_sort)
- qsort(*accesses, *count, sizeof(reg_access), (__compar_fn_t)compare_reg_accesses);
+ }
}
@@ -433,28 +413,6 @@ static void g_flow_block_compute_regs_access(GFlowBlock *block)
/******************************************************************************
* *
* Paramètres : block = bloc d'instructions à consulter. *
-* count = nombre de registres consignés. [OUT] *
-* *
-* Description : Fournit les différents accès aux registres. *
-* *
-* Retour : Liste des accès aux registres. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *block, size_t *count)
-{
- *count = block->count;
-
- return block->accesses;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : block = bloc d'instructions à consulter. *
* *
* Description : Fournit la liste d'appartenance des instructions du bloc. *
* *
@@ -519,3 +477,107 @@ void g_flow_block_get_boundary_addresses(const GFlowBlock *block, vmpa_t *start,
g_arch_instruction_get_location(block->last, NULL, NULL, end);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : block = bloc d'instructions démarrant la visite. *
+* list = ensemble des blocs basiques à parcourir. *
+* mask = points de passage à marquer. *
+* callback = ensemble de blocs à parcourir. *
+* data = donnée utilisateur à associer au parcours. *
+* *
+* Description : Suit le flot d'excution bloc par bloc. *
+* *
+* Retour : true si le parcours a été jusqu'à son terme, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_flow_block_follow(GFlowBlock *block, const GInstrBlock *list, BlockFollowPosition mask, flow_block_follow_cb callback, void *data)
+{
+ bool result; /* Bilan à retourner */
+ 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 */
+ vmpa_t addr; /* Adresse de la destination */
+ GInstrBlock *next; /* Bloc suivant à visiter */
+
+ result = true;
+
+ if (mask & BFP_ENTER)
+ result = callback(block, BFP_ENTER, data);
+
+ dcount = g_arch_instruction_get_destinations(block->last, &dests, &types);
+
+ for (i = 0; i < dcount && result; 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:
+
+ g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
+ next = g_instr_block_find_by_addr(list, addr, true);
+
+ if (next)
+ {
+ result = callback(block, BFP_FOLLOW, data);
+ result &= g_flow_block_follow(G_FLOW_BLOCK(next), list, mask, callback, data);
+ result &= callback(block, BFP_BACK, data);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (mask & BFP_EXIT)
+ result &= callback(block, BFP_EXIT, data);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : block = bloc d'instructions à consulter. *
+* *
+* Description : Fournit les différents accès aux registres. *
+* *
+* Retour : Liste des accès aux registres. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const GRAccessList *g_flow_block_list_regs_accesses(const GFlowBlock *block)
+{
+ return block->regs;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : block = bloc d'instructions à consulter. *
+* *
+* Description : Fournit les registres écrits par le bloc et utilisées après. *
+* *
+* Retour : Liste des accès aux registres. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRAccessList *g_flow_block_list_awaited_regs(const GFlowBlock *block)
+{
+ return block->awaited;
+
+}