summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-04-04 13:31:33 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-04-04 13:31:33 (GMT)
commit46e46c2894ea92502734c7bbd1cbcc6cb2e46d17 (patch)
tree9b338348d6bd78e71746bfb25fa8c864dfe44d1e /src/analysis/disass
parentd65fbe084a91d180d17767314f4e34b7456e8436 (diff)
Updated the disassembling process order and defined ranks for basic routines.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@501 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/disassembler.c46
-rw-r--r--src/analysis/disass/limit.c12
-rw-r--r--src/analysis/disass/limit.h3
-rw-r--r--src/analysis/disass/rank.c414
-rw-r--r--src/analysis/disass/rank.h3
5 files changed, 145 insertions, 333 deletions
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index fcc41cb..50c71da 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -304,28 +304,24 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta
*/
+ /* Seconde étape */
+ routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count);
- /* Seconde étape */
- id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true);
- /**
- *
- * Lequel choisir ???
+ //id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true);
-G_BIN_FORMAT(disass->format)
-G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)
+ //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
- */
+ limit_all_routines(disass->format, proc, routines, routines_count, statusbar, id);
+ //gtk_extended_status_bar_remove(statusbar, id);
- establish_links_between_instructions(*disass->instrs, G_BIN_FORMAT(disass->format), statusbar, id);
+ //run_plugins_on_binary(disass->binary, PGA_BINARY_BOUNDED, true);
- gtk_extended_status_bar_remove(statusbar, id);
- //run_plugins_on_binary(disass->binary, PGA_BINARY_LINKED, true);
@@ -334,20 +330,24 @@ G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)
/* Troisième étape */
- routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count);
+ id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true);
+ /**
+ *
+ * Lequel choisir ???
+G_BIN_FORMAT(disass->format)
+G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)
- //id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true);
+ */
- //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
- limit_all_routines(disass->format, routines, routines_count, statusbar, id);
+ establish_links_between_instructions(*disass->instrs, G_BIN_FORMAT(disass->format), statusbar, id);
- //gtk_extended_status_bar_remove(statusbar, id);
+ gtk_extended_status_bar_remove(statusbar, id);
- //run_plugins_on_binary(disass->binary, PGA_BINARY_BOUNDED, true);
+ //run_plugins_on_binary(disass->binary, PGA_BINARY_LINKED, true);
@@ -372,6 +372,18 @@ G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)
+ /* Sixième étape */
+
+ id = gtk_extended_status_bar_push(statusbar, _("Ranking each instructions block..."), true);
+
+ //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
+
+ rank_routines_blocks(routines, routines_count, statusbar, id);
+
+ gtk_extended_status_bar_remove(statusbar, id);
+
+ //run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED, true);
+
diff --git a/src/analysis/disass/limit.c b/src/analysis/disass/limit.c
index 3810978..6705e1d 100644
--- a/src/analysis/disass/limit.c
+++ b/src/analysis/disass/limit.c
@@ -64,7 +64,8 @@ static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t coun
/******************************************************************************
* *
-* Paramètres : list = ensemble d'instructions désassemblées. *
+* Paramètres : format = format du binaire concerné par la procédure. *
+* proc = ensemble d'instructions désassemblées. *
* routines = prototypes existants à insérer. *
* count = quantité de ces prototypes. *
* statusbar = barre de statut avec progression à mettre à jour.*
@@ -78,13 +79,14 @@ static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t coun
* *
******************************************************************************/
-void limit_all_routines(GExeFormat *format, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
+void limit_all_routines(GExeFormat *format, const GArchProcessor *proc, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
{
mrange_t *exe_ranges; /* Liste de zones exécutables */
size_t exe_count; /* Nombre de ces zones */
size_t i; /* Boucle de parcours */
const mrange_t *range; /* Emplacement courant */
vmpa2t addr; /* Adresse à conserver */
+ GArchInstruction *start; /* Première instruction */
phys_t diff; /* Taille définie par déduction*/
mrange_t new; /* Nouvel emplacement taillé */
@@ -99,6 +101,12 @@ void limit_all_routines(GExeFormat *format, GBinRoutine **routines, size_t count
copy_vmpa(&addr, get_mrange_addr(range));
+ /* Marquage de la première instruction */
+
+ start = g_arch_processor_find_instr_by_address(proc, &addr);
+
+ g_arch_instruction_set_flag(start, AIF_ROUTINE_START);
+
/* Si on peut se raccrocher à la routine suivante... */
if ((i + 1) < count)
{
diff --git a/src/analysis/disass/limit.h b/src/analysis/disass/limit.h
index 92c7df4..eeffc71 100644
--- a/src/analysis/disass/limit.h
+++ b/src/analysis/disass/limit.h
@@ -26,13 +26,14 @@
#include "../routine.h"
+#include "../../arch/processor.h"
#include "../../format/executable.h"
#include "../../gtkext/gtkextstatusbar.h"
/* S'assure que toutes les routines ont une taille définie. */
-void limit_all_routines(GExeFormat *, GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t);
+void limit_all_routines(GExeFormat *, const GArchProcessor *, GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t);
diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c
index 9dfdb42..94494d5 100644
--- a/src/analysis/disass/rank.c
+++ b/src/analysis/disass/rank.c
@@ -24,365 +24,153 @@
#include "rank.h"
+#include <assert.h>
+#include <sys/param.h>
+
+
#include "../blocks/flow.h"
#include "../blocks/virtual.h"
-#if 0
-/* Marque la profondeur d'un bloc d'instructions. */
-static void rank_flow_block_content(GFlowBlock *, const GInstrBlock *);
+
+/* 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 démarrant la visite. *
+* Paramètres : block = bloc d'instructions concerné par la visite. *
+* order = indication quant au sens de visite. *
* list = ensemble des blocs basiques à parcourir. *
* *
-* Description : Marque la profondeur d'un bloc d'instructions. *
+* Description : Classe le contenu d'un bloc d'instructions exécutées. *
* *
-* Retour : - *
+* Retour : true pour continuer la visite. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void rank_flow_block_content(GFlowBlock *block, const GInstrBlock *list)
+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*/
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 k; /* Boucle de parcours #1 */
- size_t i; /* Boucle de parcours #2 */
- vmpa_t addr; /* Adresse de la destination */
- GInstrBlock *next; /* Bloc suivant à visiter */
- bool loop; /* Détection de rebouclage */
- //unsigned int old_rank; /* Rang avant intervention */
-
- g_flow_block_get_boundary(block, NULL, &last);
- dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);
-
- for (k = 0; k < 2; k++)
- 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:
-
- g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
- next = g_instr_block_find_by_addr(list, addr, true);
-
- /**
- * On traite en premier les liens qui conduisent à un rebouclage,
- * afin d'avoir des indices importants à offrir pour les autres liens
- * par la suite.
- */
- loop = g_flow_block_is_looping_to(G_FLOW_BLOCK(next), list, block);
- //if (loop != (k == 0)) continue;
-
- if (loop)
- printf("next :: %u (i=%zu k=%zu)\n", g_flow_block_get_next_rank(block), i, k);
-
-
- if (loop == (k == 0))
- {
- g_flow_block_set_rank(G_FLOW_BLOCK(next), g_flow_block_get_next_rank(block));
-
- rank_flow_block_content(G_FLOW_BLOCK(next), list);
- }
- break;
-
- case ILT_LOOP:
- g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
- next = g_instr_block_find_by_addr(list, addr, true);
-
-
- /**
- * On traite en premier les liens qui conduisent à un rebouclage,
- * afin d'avoir des indices importants à offrir pour les autres liens
- * par la suite.
- */
- loop = g_flow_block_is_looping_to(G_FLOW_BLOCK(next), list, block);
- //if (loop != (k == 0)) continue;
-
-
- if (loop == (k == 0))
- {
- printf("loop next :: %u (i=%zu k=%zu)\n", g_flow_block_get_next_rank(block), i, k);
-
-
- g_flow_block_set_next_rank(G_FLOW_BLOCK(next),
- g_flow_block_get_next_rank(block));
-
- }
-
- break;
-
- default:
- break;
-
- }
-
-
+ size_t i; /* Boucle de parcours */
+ 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);
+ dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);
-#if 0
- /**
- * Si un bloc contient un retour sur lui même, on définit l'indice pour les
- * blocs suivants découlant de cette boucle avant de traiter ces blocs suivants.
- */
for (i = 0; i < dcount; i++)
+ {
+ range = g_arch_instruction_get_range(dests[i]);
+
switch (types[i])
{
- case ILT_LOOP:
- g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
- next = g_instr_block_find_by_addr(list, addr, true);
- g_flow_block_set_next_rank(G_FLOW_BLOCK(next), g_flow_block_get_next_rank(block));
+ 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;
- default:
- 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;
- for (i = 0; i < dcount; i++)
- switch (types[i])
- {
- case ILT_EXEC_FLOW:
- case ILT_JUMP:
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:
- g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
- next = g_instr_block_find_by_addr(list, addr, true);
-
- old_rank = g_flow_block_get_rank(G_FLOW_BLOCK(next));
- g_flow_block_set_rank(G_FLOW_BLOCK(next), g_flow_block_get_next_rank(block));
+ /**
+ * 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);
- /* Si un traitement n'a pas déjà été fait... */
- if (old_rank == 0 || 1)
- rank_flow_block_content(G_FLOW_BLOCK(next), list);
+ break;
default:
+ target = NULL;
break;
}
-#endif
-
-}
-
-#endif
-
-
-
-
-/* Classe le contenu d'un bloc d'instructions exécutées. */
-static unsigned int rank_flow_block(GFlowBlock *, const GInstrBlock *, unsigned int);
-
-/* Classe le contenu d'un bloc d'instructions virtuel. */
-static unsigned int rank_virtual_block(GVirtualBlock *, const GInstrBlock *, unsigned int);
-
-/* Classe le contenu d'un bloc d'instructions quelconque. */
-static unsigned int rank_instructions_block(GInstrBlock *, const GInstrBlock *, unsigned int);
-
-
+ if (target != NULL)
+ {
+ rank = MAX(next, g_flow_block_get_rank(target));
+ g_flow_block_set_rank(target, rank);
-
-/******************************************************************************
-* *
-* Paramètres : block = bloc d'instructions concerné par la visite. *
-* list = ensemble des blocs basiques à parcourir. *
-* rank = rang courant du classement en courant. *
-* *
-* Description : Classe le contenu d'un bloc d'instructions exécutées. *
-* *
-* Retour : Rang pour les blocs suivants. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static unsigned int rank_flow_block(GFlowBlock *block, const GInstrBlock *list, unsigned int rank)
-{
- unsigned int result; /* Rang suivant à retourner */
- GInstrBlock *links; /* Blocs liés au bloc courant */
- GArchInstruction *last; /* Dernière instruction du bloc*/
- 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 k; /* Boucle de parcours #1 */
- size_t i; /* Boucle de parcours #2 */
- vmpa_t addr; /* Adresse de la destination */
- GInstrBlock *next; /* Bloc suivant à visiter */
- bool loop; /* Détection de rebouclage */
-
- /* On traite le bloc courant */
-
- result = rank;
- g_flow_block_set_rank(block, result++);
-
- /* Viennent ensuite les blocs rattachés */
-
- links = g_instr_block_get_links_block(G_INSTR_BLOCK(block));
-
- if (links != NULL)
- {
- g_flow_block_get_boundary(block, NULL, &last);
- dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);
-
- for (k = 0; k < 2; k++)
- for (i = 0; i < dcount; i++)
- switch (types[i])
- {
- 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(links, addr, true);
-
- /**
- * En cas d'une branche unique, l'adresse peut ne pas être trouvée
- * dans les sous-blocs ; logiquement, elle sera traitée plus tard,
- * dans la continuité de ce bloc.
- */
- if (next == NULL) break;
-
- /**
- * On traite en premier les liens qui conduisent à un rebouclage,
- * afin d'avoir des indices importants à offrir pour les autres liens
- * par la suite.
- */
- loop = g_flow_block_is_looping_to(G_FLOW_BLOCK(next), list, block);
- if (loop != (k == 0)) continue;
-
- next = g_instr_block_find_by_addr(links, addr, false);
- result = MAX(rank_instructions_block(next, list, rank + 1), result);
-
- break;
-
- default:
- break;
-
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : block = bloc d'instructions concerné par la visite. *
-* list = ensemble des blocs basiques à parcourir. *
-* rank = rang courant du classement en courant. *
-* *
-* Description : Classe le contenu d'un bloc d'instructions virtuel. *
-* *
-* Retour : Rang pour les blocs suivants. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static unsigned int rank_virtual_block(GVirtualBlock *block, const GInstrBlock *list, unsigned int rank)
-{
- unsigned int result; /* Rang suivant à retourner */
- size_t max; /* Borne du parcours */
- size_t i; /* Boucle de parcours */
- GInstrBlock *child; /* Sous-bloc à traiter */
-
- result = rank;
-
- max = g_virtual_block_count_children(block);
-
- for (i = 0; i < max; i++)
- {
- child = g_virtual_block_get_child(block, i);
- if (!G_IS_FLOW_BLOCK(child)) continue;
-
- result = rank_instructions_block(child, list, result);
+ }
}
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : block = bloc d'instructions concerné par la visite. *
-* list = ensemble des blocs basiques à parcourir. *
-* rank = rang courant du classement en courant. *
-* *
-* Description : Classe le contenu d'un bloc d'instructions quelconque. *
-* *
-* Retour : Rang pour les blocs suivants. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static unsigned int rank_instructions_block(GInstrBlock *block, const GInstrBlock *list, unsigned int rank)
-{
- unsigned int result; /* Rang suivant à retourner */
-
- if (G_IS_VIRTUAL_BLOCK(block))
- result = rank_virtual_block(G_VIRTUAL_BLOCK(block), list, rank);
-
- else if (G_FLOW_BLOCK(block))
- result = rank_flow_block(G_FLOW_BLOCK(block), list, rank);
-
- else
- result = rank;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : routine = routine à traiter. *
-* *
-* Description : Classe les blocs d'une routine donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void rank_routine_blocks(GBinRoutine *routine)
-{
- GInstrBlock *list; /* Ensemble des blocs d'instr. */
- //vmpa_t start; /* Adresse de départ */
- //GFlowBlock *first; /* Premier bloc de la routine */
-
- list = g_binary_routine_get_basic_blocks(routine);
-
- rank_instructions_block(list, list, 0);
-
- /*
- start = g_binary_routine_get_address(routine);
- first = G_FLOW_BLOCK(g_instr_block_find_by_addr(list, start, true));
-
- rank_flow_block_content(first, list);
- */
+ return true;
}
@@ -406,8 +194,14 @@ void rank_routine_blocks(GBinRoutine *routine)
void rank_routines_blocks(GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
{
size_t i; /* Boucle de parcours */
+ GInstrBlock *main_block; /* Ensemble des blocs d'instr. */
for (i = 0; i < count; i++)
- rank_routine_blocks(routines[i]);
+ {
+ main_block = g_binary_routine_get_basic_blocks(routines[i]);
+
+ g_instr_block_visit(main_block, (instr_block_visitor_cb)rank_flow_block, main_block);
+
+ }
}
diff --git a/src/analysis/disass/rank.h b/src/analysis/disass/rank.h
index 4252272..a4c62bb 100644
--- a/src/analysis/disass/rank.h
+++ b/src/analysis/disass/rank.h
@@ -30,9 +30,6 @@
-/* Classe les blocs d'une routine donnée. */
-void rank_routine_blocks(GBinRoutine *);
-
/* Classe les blocs des routines. */
void rank_routines_blocks(GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t);