summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/Makefile.am1
-rw-r--r--src/analysis/disass/area.c1289
-rw-r--r--src/analysis/disass/area.h96
-rw-r--r--src/analysis/disass/fetch.c552
4 files changed, 1450 insertions, 488 deletions
diff --git a/src/analysis/disass/Makefile.am b/src/analysis/disass/Makefile.am
index 65ed9c9..54b0fa5 100644
--- a/src/analysis/disass/Makefile.am
+++ b/src/analysis/disass/Makefile.am
@@ -2,6 +2,7 @@
noinst_LTLIBRARIES = libanalysisdisass.la
libanalysisdisass_la_SOURCES = \
+ area.h area.c \
disassembler.h disassembler.c \
fetch.h fetch.c \
limit.h limit.c \
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
new file mode 100644
index 0000000..9d8dcf5
--- /dev/null
+++ b/src/analysis/disass/area.c
@@ -0,0 +1,1289 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area.c - définition et manipulation des aires à désassembler
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "area.h"
+
+
+#include <assert.h>
+
+
+
+#if 0
+
+
+/* Zone mémoire bien bornée */
+struct _mem_area
+{
+ mrange_t range; /* Couverture de la zone */
+
+ unsigned long *processed; /* Octets traités dans la zone */
+
+ bool has_sym; /* Représentation via symbole ?*/
+
+ union
+ {
+ bool exec; /* Zone exécutable ? */
+ GBinSymbol *symbol; /* Symbole associé à la zone */
+ };
+
+};
+
+
+#endif
+
+
+
+/* Initialise une aire de données à partir d'une adresse donnée. */
+static void init_mem_area_from_addr(mem_area *, const vmpa2t *, phys_t);
+
+/* Initialise une aire de données à partir d'un espace donné. */
+static void init_mem_area_from_range(mem_area *, const mrange_t *);
+
+/* Copie certaines propriétés d'une aire à une autre. */
+static void copy_mem_area_properties(mem_area *, const mem_area *);
+
+/* Libère d'une aire de données les ressources allouées. */
+static void fini_mem_area(mem_area *);
+
+/* Indique si une zone donnée est intégralement vierge ou non. */
+static bool is_range_blank_in_mem_area(mem_area *, phys_t, phys_t, GArchInstruction *);
+
+/* Marque une série d'octets comme ayant été traités. */
+static bool mark_range_in_mem_area_as_processed(mem_area *, phys_t, phys_t, GArchInstruction *);
+
+
+
+
+
+/* Procède au désassemblage d'un contenu binaire non exécutable. */
+static void load_data_from_mem_area(mem_area *, mem_area *, size_t, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_info *);
+
+/* S'assure qu'une aire contient toutes ses instructions. */
+static void fill_mem_area(mem_area *, mem_area *, size_t, const GLoadedBinary *, GProcContext *, status_info *);
+
+
+
+/* Rassemble les instructions conservées dans une zone donnée. */
+static GArchInstruction *get_instructions_from_mem_area(const mem_area *);
+
+
+
+
+///////////////////////////////
+
+
+
+/* Manipule la cartographie des octets traités d'une zone. */
+typedef bool (* visit_bytes_map_fc) (mem_area *, phys_t, phys_t, GArchInstruction *);
+
+
+
+
+
+/* Manipule la cartographie des octets d'aires de données. */
+static bool handle_bytes_map_in_mem_area(mem_area *, size_t, const mrange_t *, GArchInstruction *, visit_bytes_map_fc);
+
+/* Indique si une zone donnée est intégralement vierge ou non. */
+static bool is_range_blank_in_mem_areas(mem_area *, size_t, const mrange_t *);
+
+/* Marque une série d'octets comme ayant été traités. */
+static bool mark_range_in_mem_areas_as_processed(mem_area *, size_t, GArchInstruction *);
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à initialiser. *
+* addr = adresse de départ de l'espace à mettre en place. *
+* len = longueur de l'espace à créer. *
+* *
+* Description : Initialise une aire de données à partir d'une adresse donnée.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void init_mem_area_from_addr(mem_area *area, const vmpa2t *addr, phys_t len)
+{
+ size_t requested; /* Nombre de mots à allouer */
+
+ init_mrange(&area->range, addr, len);
+
+ requested = len / sizeof(unsigned long);
+ if (len % sizeof(unsigned long) != 0) requested++;
+
+ area->processed = (unsigned long *)calloc(requested, sizeof(unsigned long));
+ area->instructions = (GArchInstruction **)calloc(len, sizeof(GArchInstruction *));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = aire délimitée représentant des données. *
+* src = aire délimitée contenant les informations à copier. *
+* *
+* Description : Copie certaines propriétés d'une aire à une autre. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void copy_mem_area_properties(mem_area *dest, const mem_area *src)
+{
+ dest->has_sym = src->has_sym;
+
+ if (src->has_sym)
+ dest->symbol = src->symbol;
+ else
+ dest->exec = src->exec;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à initialiser. *
+* range = espace limitant à associer à l'aire de données. *
+* *
+* Description : Initialise une aire de données à partir d'un espace donné. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void init_mem_area_from_range(mem_area *area, const mrange_t *range)
+{
+ phys_t len; /* Taille de la zone courante */
+ size_t requested; /* Nombre de mots à allouer */
+
+ copy_mrange(&area->range, range);
+
+ len = get_mrange_length(range);
+
+ requested = len / sizeof(unsigned long);
+ if (len % sizeof(unsigned long) != 0) requested++;
+
+ area->processed = (unsigned long *)calloc(requested, sizeof(unsigned long));
+ area->instructions = (GArchInstruction **)calloc(len, sizeof(GArchInstruction *));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à nettoyer en mémoire. *
+* *
+* Description : Libère d'une aire de données les ressources allouées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void fini_mem_area(mem_area *area)
+{
+ free(area->processed);
+
+ if (area->has_sym)
+ g_object_unref(area->symbol);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* start = début de la zone à manipuler. *
+* len = taille de cette même aire de données. *
+* instr = instruction à mémoriser pour la suite. *
+* *
+* Description : Indique si une zone donnée est intégralement vierge ou non. *
+* *
+* Retour : true si l'aire visée n'a jamais été traitée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool is_range_blank_in_mem_area(mem_area *area, phys_t start, phys_t len, GArchInstruction *instr)
+{
+ bool result; /* Bilan à renvoyer */
+ phys_t max; /* Point d'arrêt de la boucle */
+ phys_t i; /* Boucle de parcours */
+ size_t index; /* Cellule de tableau visée */
+ unsigned int remaining; /* Nombre de bits restants */
+
+ max = start + len;
+
+ assert(max <= get_mrange_length(&area->range));
+
+ result = true;
+
+ for (i = start; i < max && result; i++)
+ {
+ index = i / (sizeof(unsigned long) * 8);
+ remaining = i % (sizeof(unsigned long) * 8);
+
+ result &= ((area->processed[index] & (1ul << remaining)) == 0);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* start = début de la zone à manipuler. *
+* len = taille de cette même aire de données. *
+* instr = instruction à mémoriser pour la suite. *
+* *
+* Description : Marque une série d'octets comme ayant été traités. *
+* *
+* Retour : true. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool mark_range_in_mem_area_as_processed(mem_area *area, phys_t start, phys_t len, GArchInstruction *instr)
+{
+ phys_t max; /* Point d'arrêt de la boucle */
+ phys_t i; /* Boucle de parcours */
+ size_t index; /* Cellule de tableau visée */
+ unsigned int remaining; /* Nombre de bits restants */
+
+ max = start + len;
+
+ assert(max <= get_mrange_length(&area->range));
+
+ for (i = start; i < max; i++)
+ {
+ index = i / (sizeof(unsigned long) * 8);
+ remaining = i % (sizeof(unsigned long) * 8);
+
+ area->processed[index] |= (1ul << remaining);
+
+ }
+
+ area->instructions[start] = instr;
+
+ return true;
+
+}
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* list = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* binary = représentation de binaire chargé. *
+* ctx = contexte offert en soutien à un désassemblage. *
+* start = démarrage de l'exécution au sein de la zone. *
+* info = indications quant à la progression à afficher. *
+* *
+* Description : Procède au désassemblage d'un contenu binaire exécutable. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, const GLoadedBinary *binary, GProcContext *ctx, const vmpa2t *start, status_info *info)
+{
+
+
+ GBinFormat *format; /* Format du fichier binaire */
+ GArchProcessor *proc; /* Architecture du binaire */
+ off_t bin_length; /* Taille des données à lire */
+ bin_t *bin_data; /* Données binaires à lire */
+
+ phys_t diff; /* Volume de données traité */
+ phys_t alen; /* Taille de l'aire utilisée */
+
+ phys_t i; /* Boucle de parcours */
+
+
+ vmpa2t pos; /* Boucle de parcours */
+ vmpa2t prev; /* Boucle de parcours */
+
+ GArchInstruction *instr; /* Instruction décodée */
+
+
+
+ mrange_t range; /* Couverture de l'instruction */
+
+
+
+ /* On cherche à obtenir l'assurance que le traitement n'a jamais été fait */
+
+ init_mrange(&range, start, 1);
+ if (!is_range_blank_in_mem_areas(list, count, &range)) printf("CODE OK!!\n");;
+ if (!is_range_blank_in_mem_areas(list, count, &range)) return;
+
+ /* Récupération des informations de base */
+
+ format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+ proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
+ bin_data = g_loaded_binary_get_data(binary, &bin_length);
+
+ diff = compute_vmpa_diff(get_mrange_addr(&area->range), start);
+ alen = get_mrange_length(&area->range);
+
+ /**
+ * On copie la position courante à partir de l'aire plutôt que du
+ * point de départ car cette première est potentiellement plus complète.
+ */
+
+ copy_vmpa(&pos, get_mrange_addr(&area->range));
+ advance_vmpa(&pos, diff);
+
+ printf(" [%p] CODE start @ %u (len=%u)\n", area, (unsigned int)diff, (unsigned int)alen);
+
+ for (i = diff; i < alen; i += diff)
+ {
+ //il y a eu un point d'entrée... -> STOP
+
+ /* Décodage d'une nouvelle instruction */
+
+ copy_vmpa(&prev, &pos);
+
+ instr = g_arch_processor_disassemble(proc, ctx, bin_data, &pos, bin_length);
+
+ //printf(" @ 0x%08x -> %p\n", (uint32_t)get_virt_addr(&prev), instr);
+
+ if (instr == NULL) break;
+
+
+
+
+ /* Enregistrement des positions et adresses */
+
+ diff = compute_vmpa_diff(&prev, &pos);
+
+ init_mrange(&range, &prev, diff);
+
+ g_arch_instruction_set_range(instr, &range);
+
+ /* Eventuel renvoi vers d'autres adresses */
+
+ g_arch_instruction_call_hook(instr, IPH_LINK, ctx, format);
+
+ /* Progression dans les traitements */
+
+ mark_range_in_mem_areas_as_processed(list, count, instr);
+
+ //done += (new_phy - old_phy);
+ //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
+
+
+
+
+
+
+
+
+ }
+
+
+ printf("\n");
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* list = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* binary = représentation de binaire chargé. *
+* ctx = contexte offert en soutien à un désassemblage. *
+* start = démarrage de l'exécution au sein de la zone. *
+* info = indications quant à la progression à afficher. *
+* *
+* Description : Procède au désassemblage d'un contenu binaire non exécutable.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count, const GLoadedBinary *binary, GProcContext *ctx, const vmpa2t *start, status_info *info)
+{
+ GBinFormat *format; /* Format du fichier binaire */
+ GArchProcessor *proc; /* Architecture du binaire */
+ SourceEndian endianness; /* Boutisme de cette machine */
+ off_t bin_length; /* Taille des données à lire */
+ bin_t *bin_data; /* Données binaires à lire */
+ phys_t diff; /* Volume de données traité */
+ phys_t alen; /* Taille de l'aire utilisée */
+ phys_t i; /* Boucle de parcours */
+ vmpa2t pos; /* Boucle de parcours */
+ vmpa2t prev; /* Boucle de parcours */
+ GArchInstruction *instr; /* Instruction décodée */
+ mrange_t range; /* Couverture de l'instruction */
+
+ /* On cherche à obtenir l'assurance que le traitement n'a jamais été fait */
+
+ init_mrange(&range, start, 1);
+ if (!is_range_blank_in_mem_areas(list, count, &range)) printf("DATA OK!!\n");;
+ if (!is_range_blank_in_mem_areas(list, count, &range)) return;
+
+ /* Récupération des informations de base */
+
+ format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+ proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
+ endianness = g_arch_processor_get_endianness(proc);
+ bin_data = g_loaded_binary_get_data(binary, &bin_length);
+
+ diff = compute_vmpa_diff(get_mrange_addr(&area->range), start);
+ alen = get_mrange_length(&area->range);
+
+ /**
+ * On copie la position courante à partir de l'aire plutôt que du
+ * point de départ car cette première est potentiellement plus complète.
+ */
+
+ copy_vmpa(&pos, get_mrange_addr(&area->range));
+ advance_vmpa(&pos, diff);
+
+ printf(" [%p] DATA start @ 0x%08x -> %u (len=%u)\n",
+ area, (unsigned int)get_phy_addr(&pos), (unsigned int)diff, (unsigned int)alen);
+
+ for (i = diff; i < alen; i += diff)
+ {
+ /* Décodage d'une nouvelle instruction, sur mesure */
+
+ copy_vmpa(&prev, &pos);
+
+ instr = NULL;
+
+ if (instr == NULL && (i + 4) <= alen)
+ {
+ init_mrange(&range, &pos, 4);
+
+ if (is_range_blank_in_mem_areas(list, count, &range))
+ instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, bin_length, endianness);
+
+ }
+
+ if (instr == NULL && (i + 2) <= alen)
+ {
+ copy_vmpa(&pos, &prev);
+ init_mrange(&range, &pos, 2);
+
+ if (is_range_blank_in_mem_areas(list, count, &range))
+ instr = g_raw_instruction_new_array(bin_data, MDS_16_BITS, 1, &pos, bin_length, endianness);
+
+ }
+
+ if (instr == NULL/* && (i + 1) <= alen*/)
+ {
+ copy_vmpa(&pos, &prev);
+ init_mrange(&range, &pos, 1);
+
+ if (is_range_blank_in_mem_areas(list, count, &range))
+ instr = g_raw_instruction_new_array(bin_data, MDS_8_BITS, 1, &pos, bin_length, endianness);
+ else
+ {
+ printf(" break !! 0x%08x\n",
+ (unsigned int)get_phy_addr(&pos));
+ assert(0);
+ break;
+ }
+
+ }
+
+ assert(instr != NULL);
+
+ /* Enregistrement des positions et adresses */
+
+ diff = compute_vmpa_diff(&prev, &pos);
+
+ printf(" decomp @ 0x%08x -> ++ %u\n",
+ (unsigned int)get_phy_addr(&pos), (unsigned int)diff);
+
+ init_mrange(&range, &prev, diff);
+
+ g_arch_instruction_set_range(instr, &range);
+
+ /* Progression dans les traitements */
+
+ mark_range_in_mem_areas_as_processed(list, count, instr);
+
+ assert(!is_range_blank_in_mem_areas(list, count, &range));
+
+ //done += (new_phy - old_phy);
+ //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* list = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* binary = représentation de binaire chargé. *
+* ctx = contexte offert en soutien à un désassemblage. *
+* info = indications quant à la progression à afficher. *
+* *
+* Description : S'assure qu'une aire contient toutes ses instructions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void fill_mem_area(mem_area *area, mem_area *list, size_t count, const GLoadedBinary *binary, GProcContext *ctx, status_info *info)
+{
+ phys_t len; /* Taille de la zone à remplir */
+ phys_t i; /* Boucle de parcours */
+ vmpa2t start; /* Adresse de départ de combles*/
+
+
+ printf(" === FILLING | 0x%08x (%u)...\n",
+ (unsigned int)get_phy_addr(get_mrange_addr(&area->range)),
+ (unsigned int)get_phy_addr(get_mrange_addr(&area->range)));
+
+
+ /* Les symboles se doivent d'être indépendants ! */
+ if (area->has_sym) return;
+
+ len = get_mrange_length(&area->range);
+
+ for (i = 0; i < len; i++)
+ {
+ if (is_range_blank_in_mem_area(area, i, 1, NULL))
+ {
+ copy_vmpa(&start, get_mrange_addr(&area->range));
+ advance_vmpa(&start, i);
+
+ if (area->exec)
+ load_code_from_mem_area(area, list, count, binary, ctx, &start, info);
+
+ if (is_range_blank_in_mem_area(area, i, 1, NULL))
+ load_data_from_mem_area(area, list, count, binary, ctx, &start, info);
+
+ }
+
+ if (is_range_blank_in_mem_area(area, i, 1, NULL))
+ printf(" [%p] error with %u\n", area, (unsigned int)i);
+
+ assert(!is_range_blank_in_mem_area(area, i, 1, NULL));
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* *
+* Description : Rassemble les instructions conservées dans une zone donnée. *
+* *
+* Retour : Liste d'instructions prêtes à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchInstruction *get_instructions_from_mem_area(const mem_area *area)
+{
+ GArchInstruction *result; /* Liste d'instr. à renvoyer */
+ phys_t len; /* Nombre d'instructions au max*/
+ phys_t i; /* Boucle de parcours */
+ GArchInstruction *instr; /* Instruction décodée */
+
+ result = NULL;
+
+ if (area->has_sym)
+ switch (g_binary_symbol_get_target_type(area->symbol))
+ {
+ case STP_DATA:
+ result = g_binary_symbol_get_instruction(area->symbol);
+ g_object_ref(G_OBJECT(result));
+ break;
+
+ case STP_ROUTINE:
+ assert(false);
+ //instr = load_code_binary(binary, start, end, statusbar, id);
+ // + fill
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ else
+ {
+ len = get_mrange_length(&area->range);
+
+ for (i = 0; i < len; i++)
+ {
+ instr = area->instructions[i];
+
+ if (instr != NULL)
+ {
+ g_object_ref(G_OBJECT(instr));
+ g_arch_instruction_add_to_list(&result, instr);
+ }
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format d'un exécutable à consulter. *
+* bin_length = quantité d'octets à traiter au total. *
+* count = nombre de zones mises en place. [OUT] *
+* *
+* Description : Détermine une liste de zones contigües à traiter. *
+* *
+* Retour : Liste de zones mémoire à libérer après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+mem_area *compute_memory_areas(GExeFormat *format, phys_t bin_length, size_t *count)
+{
+ mem_area *result; /* Liste à renvoyer */
+ mrange_t *exe_ranges; /* Liste de zones exécutables */
+ size_t exe_count; /* Nombre de ces zones */
+ GBinSymbol **symbols; /* Symboles à représenter */
+ size_t sym_count; /* Qté de symboles présents */
+ vmpa2t *last; /* Dernière bordure rencontrée */
+ size_t i; /* Boucle de parcours #1 */
+ vmpa2t *border; /* Nouvelle bordure rencontrée */
+ mem_area *area; /* Zone avec valeurs à éditer */
+ vmpa2t tmp; /* Stockage temporaire */
+
+
+ GBinPortion **portions; /* Morceaux d'encadrement */
+ size_t portions_count; /* Taille de cette liste */
+ const vmpa2t *portion_start; /* Point de départ de portion */
+
+ size_t j; /* Boucle de parcours #2 */
+ const mrange_t *range; /* Couverture d'un symbole */
+ const vmpa2t *start; /* Point de départ du symbole */
+ phys_t length; /* Taille de ce même symbole */
+ bool included; /* Inclusion dans une zone ? */
+ mem_area orig; /* Copie de la zone réduite */
+ phys_t old_length; /* Taille de zone originelle */
+ phys_t new_length; /* Nouvelle taille déterminée */
+ size_t next; /* Indice de zone suivante */
+
+ result = NULL;
+ *count = 0;
+
+ /**
+ * Le parcours n'est valide que si les listes, symboles et zones exécutables,
+ * sont triées !
+ */
+
+ exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
+
+ symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);
+
+
+
+
+
+
+ for (i = 0; i < exe_count; i++)
+ {
+ printf(" (init) AREA %zu :: 0x%08x + %u\n",
+ i,
+ (unsigned int)get_phy_addr(get_mrange_addr(&exe_ranges[i])),
+ (unsigned int)get_mrange_length(&exe_ranges[i]));
+
+ }
+
+
+ printf("----------------\n");
+
+
+
+ /* Première étape : on comble les trous ! */
+
+ last = make_vmpa(0, VMPA_NO_VIRTUAL);
+
+ for (i = 0; i < exe_count; i++)
+ {
+ border = get_mrange_addr(&exe_ranges[i]);
+
+ /* Zone tampon à constituer */
+
+ if (cmp_vmpa_by_phy(last, border) < 0)
+ {
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ area = &result[*count - 1];
+
+ init_mem_area_from_addr(area, last, compute_vmpa_diff(last, border));
+ area->has_sym = false;
+ area->exec = false;
+
+ }
+
+ /* Insertion d'une zone exécutable déjà définie */
+
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ area = &result[*count - 1];
+
+ init_mem_area_from_range(area, &exe_ranges[i]);
+ area->has_sym = false;
+ area->exec = true;
+
+ /* Avancée du curseur */
+
+ copy_vmpa(last, border);
+
+ advance_vmpa(last, get_mrange_length(&exe_ranges[i]));
+
+ }
+
+ delete_vmpa(last);
+
+ /* Extension finale complémentaire ? */
+
+ area = &result[*count - 1];
+
+ copy_vmpa(&tmp, get_mrange_addr(&area->range));
+ advance_vmpa(&tmp, get_mrange_length(&area->range));
+
+ if (get_phy_addr(&tmp) < bin_length)
+ {
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ area = &result[*count - 1];
+
+ init_mem_area_from_addr(area, &tmp, bin_length - get_phy_addr(&tmp));
+ area->has_sym = false;
+ area->exec = false;
+
+ }
+
+ /* Seconde étape : on s'assure du découpage autour des portions pour respecter l'alignement */
+
+
+
+ for (i = 0; i < *count; i++)
+ {
+ printf(" (fini) AREA %zu :: 0x%08x + %u\n",
+ i,
+ (unsigned int)get_phy_addr(get_mrange_addr(&result[i].range)),
+ (unsigned int)get_mrange_length(&result[i].range));
+
+ }
+
+ printf("--------------------\n");
+
+ portions = g_exe_format_get_portions_at_level(format, -1, &portions_count);
+
+
+ for (i = 1; i < portions_count; i++)
+ {
+ portion_start = get_mrange_addr(g_binary_portion_get_range(portions[i]));
+
+ for (j = 0; j < *count; j++)
+ {
+ area = &result[j];
+
+ if (!mrange_contains_addr(&area->range, portion_start))
+ continue;
+
+ /* Si le déccoupage actuel ne correspond pas au besoin des portions... */
+ if (cmp_vmpa(get_mrange_addr(&area->range), portion_start) != 0)
+ {
+ fini_mem_area(&result[j]);
+
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ memmove(&result[j + 2], &result[j + 1], (*count - j - 2) * sizeof(mem_area));
+
+ copy_mem_area_properties(&result[j + 1], &result[j]);
+
+ /* Première moitié */
+
+ area = &result[j];
+
+ copy_vmpa(&tmp, get_mrange_addr(&area->range));
+ length = get_mrange_length(&area->range);
+
+ init_mem_area_from_addr(area, &tmp, compute_vmpa_diff(&tmp, portion_start));
+
+ /* Seconde moitié */
+
+ length -= get_mrange_length(&area->range);
+
+ area = &result[j + 1];
+
+ init_mem_area_from_addr(area, portion_start, length);
+
+ }
+
+ j = *count;
+
+ }
+
+ }
+
+
+
+
+
+
+ for (i = 0; i < *count; i++)
+ {
+ printf(" (sect) AREA %zu :: 0x%08x + %u\n",
+ i,
+ (unsigned int)get_phy_addr(get_mrange_addr(&result[i].range)),
+ (unsigned int)get_mrange_length(&result[i].range));
+
+ }
+
+
+ //exit(0);
+
+
+
+ /* Troisième étape : on insère les symboles existants */
+
+ j = 0;
+
+#define SKIP_EMPTY_SYMBOLS \
+ for (; j < sym_count; j++) \
+ { \
+ range = g_binary_symbol_get_range(symbols[j]); \
+ \
+ length = get_mrange_length(range); \
+ if (length > 0) break; \
+ \
+ } \
+
+ SKIP_EMPTY_SYMBOLS
+
+ for (i = 0; i < *count && j < sym_count; i++)
+ {
+ range = g_binary_symbol_get_range(symbols[j]);
+
+ start = get_mrange_addr(range);
+ length = get_mrange_length(range);
+
+ /* Si un découpage s'impose... */
+
+ if (mrange_contains_addr(&result[i].range, start))
+ {
+ copy_vmpa(&tmp, start);
+ advance_vmpa(&tmp, length);
+
+ included = mrange_contains_addr(&result[i].range, &tmp);
+
+ memcpy(&orig, &result[i], sizeof(mem_area));
+
+ fini_mem_area(&orig);
+
+ /* Réduction de la zone de départ */
+
+ copy_vmpa(&tmp, get_mrange_addr(&result[i].range));
+ old_length = get_mrange_length(&result[i].range);
+
+ new_length = compute_vmpa_diff(get_mrange_addr(&result[i].range), start);
+
+ if (new_length == 0)
+ {
+ memmove(&result[i], &result[i + 1], (*count - i - 1) * sizeof(mem_area));
+
+ (*count)--;
+ next = i;
+
+ }
+ else
+ {
+ init_mem_area_from_addr(&result[i], &tmp, new_length);
+ next = i + 1;
+ }
+
+ /* Insertion de la zone du symbole */
+
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ memmove(&result[next + 1], &result[next], (*count - next - 1) * sizeof(mem_area));
+
+ area = &result[next];
+
+ init_mem_area_from_range(area, range);
+
+ area->has_sym = true;
+ area->symbol = symbols[j];
+
+ /* Jointure finale... */
+
+ if (included)
+ {
+ /* Simple extension pour rattraper la fin originelle */
+
+ if ((old_length - new_length - length) > 0)
+ {
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ memmove(&result[next + 2], &result[next + 1], (*count - next - 2) * sizeof(mem_area));
+
+ area = &result[next + 1];
+
+ copy_vmpa(&tmp, start);
+ advance_vmpa(&tmp, length);
+
+ init_mem_area_from_addr(area, &tmp, old_length - new_length - length);
+
+ copy_mem_area_properties(area, &orig);
+
+ }
+
+ i = next;
+
+ }
+ else
+ {
+ /* Suppression des éventuelles zones totalement recouvertes */
+
+
+
+ /* Réduction de la zone d'arrivée */
+
+
+ }
+
+
+
+
+
+ j++;
+
+ SKIP_EMPTY_SYMBOLS
+
+ }
+
+ }
+
+
+
+ //free
+
+ //exit(0);
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : list = listes de zones utable à consulter. *
+* count = nombre de zones mises en place. *
+* addr = adresse à retrouver dans les aires présentes. *
+* *
+* Description : Détermine une liste de zones contigües à traiter. *
+* *
+* Retour : Liste de zones mémoire à libérer après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+mem_area *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *addr)
+{
+ mem_area *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ for (i = 0; i < count && result == NULL; i++)
+ if (mrange_contains_addr(&list[i].range, addr))
+ result = &list[i];
+
+ return result;
+
+}
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* range = aire des octets à manipuler. *
+* visitor = fonction opérationnelle finale à appeler. *
+* *
+* Description : Manipule la cartographie des octets d'aires de données. *
+* *
+* Retour : valeur retournée par le visiteur, voire false si erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool handle_bytes_map_in_mem_area(mem_area *list, size_t count, const mrange_t *range, GArchInstruction *instr, visit_bytes_map_fc visitor)
+{
+ bool result; /* Bilan à retourner */
+ mem_area *area; /* Aire à traiter trouvée */
+ phys_t offset; /* Point de départ dans l'aire */
+ phys_t remaining; /* Quantité restant à traiter */
+ phys_t processed; /* Quantité traitée */
+ vmpa2t start; /* Point de départ suivant */
+
+ result = false;
+
+ area = find_memory_area_by_addr(list, count, get_mrange_addr(range));
+ if (area == NULL) printf("NOT FOUND!\n");
+ if (area == NULL) return false;
+
+ offset = compute_vmpa_diff(get_mrange_addr(&area->range), get_mrange_addr(range));
+ remaining = get_mrange_length(range);
+
+ /* Traitement intégral dans la zone trouvée */
+
+ if ((offset + remaining) <= get_mrange_length(&area->range))
+ result = visitor(area, offset, remaining, instr);
+
+ else
+ {
+ assert(0);
+
+ /* Traitement de la fin de la première aire */
+
+ processed = get_mrange_length(&area->range) - offset;
+
+ result = visitor(area, offset, processed, instr);
+
+ /* Traitement des zones adjacentes suivantes */
+
+ copy_vmpa(&start, get_mrange_addr(range));
+
+ for (remaining -= processed; remaining > 0 && result; remaining -= processed)
+ {
+ advance_vmpa(&start, processed);
+
+ area = find_memory_area_by_addr(list, count, &start);
+ if (area == NULL)
+ {
+ result = false;
+ break;
+ }
+
+ processed = get_mrange_length(&area->range);
+ if (remaining < processed) processed = remaining;
+
+ result = visitor(area, 0, processed, instr);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* range = aire des octets à manipuler. *
+* *
+* Description : Indique si une zone donnée est intégralement vierge ou non. *
+* *
+* Retour : true si l'aire visée n'a jamais été traitée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool is_range_blank_in_mem_areas(mem_area *list, size_t count, const mrange_t *range)
+{
+ return handle_bytes_map_in_mem_area(list, count,
+ range, NULL,
+ is_range_blank_in_mem_area);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* instr = instruction désassemblée à conserver en mémoire. *
+* *
+* Description : Marque une série d'octets comme ayant été traités. *
+* *
+* Retour : true. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool mark_range_in_mem_areas_as_processed(mem_area *list, size_t count, GArchInstruction *instr)
+{
+ return handle_bytes_map_in_mem_area(list, count,
+ g_arch_instruction_get_range(instr), instr,
+ mark_range_in_mem_area_as_processed);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* binary = représentation de binaire chargé. *
+* ctx = contexte offert en soutien à un désassemblage. *
+* info = indications quant à la progression à afficher. *
+* *
+* Description : S'assure que l'ensemble des aires est entièrement décodé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void ensure_all_mem_areas_are_filled(mem_area *list, size_t count, const GLoadedBinary *binary, GProcContext *ctx, status_info *info)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < count; i++)
+ fill_mem_area(&list[i], list, count, binary, ctx, info);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : areas = série d'aires représentant à contenu à parcourir. *
+* count = nombre de ces zones présentes. *
+* *
+* Description : Rassemble les instructions conservées dans des zones données.*
+* *
+* Retour : Liste d'instructions prêtes à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchInstruction *collect_instructions_from_mem_areas(mem_area *list, size_t count)
+{
+ GArchInstruction *result; /* Liste d'instr. à renvoyer */
+ size_t i; /* Boucle de parcours */
+ GArchInstruction *instr; /* Instruction(s) à insérer */
+
+ result = NULL;
+
+ for (i = 0; i < count; i++)
+ {
+ instr = get_instructions_from_mem_area(&list[i]);
+ g_arch_instruction_merge_lists(&result, &instr);
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h
new file mode 100644
index 0000000..58539ca
--- /dev/null
+++ b/src/analysis/disass/area.h
@@ -0,0 +1,96 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area.h - prototypes pour la définition et la manipulation des aires à désassembler
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_DISASS_AREA_H
+#define _ANALYSIS_DISASS_AREA_H
+
+
+#include "../binary.h"
+#include "../../format/executable.h"
+#include "../../gtkext/gtkextstatusbar.h"
+
+
+//////
+#include "../../arch/raw.h"
+#include "../../arch/instruction.h"
+
+
+
+/* Zone mémoire bien bornée */
+typedef struct _mem_area
+{
+ mrange_t range; /* Couverture de la zone */
+
+ unsigned long *processed; /* Octets traités dans la zone */
+ GArchInstruction **instructions; /* Instructions en place */
+
+ bool has_sym; /* Représentation via symbole ?*/
+
+ union
+ {
+ bool exec; /* Zone exécutable ? */
+ GBinSymbol *symbol; /* Symbole associé à la zone */
+ };
+
+} mem_area;
+
+
+
+
+/* Zone mémoire bien bornée */
+//typedef struct _mem_area mem_area;
+
+
+
+
+/* Procède au désassemblage d'un contenu binaire exécutable. */
+void load_code_from_mem_area(mem_area *, mem_area *, size_t, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_info *);
+
+
+
+/* Détermine une liste de zones contigües à traiter. */
+mem_area *compute_memory_areas(GExeFormat *, phys_t, size_t *);
+
+
+
+
+
+
+
+
+
+/* Détermine une liste de zones contigües à traiter. */
+mem_area *find_memory_area_by_addr(mem_area *, size_t, const vmpa2t *);
+
+
+
+
+/* S'assure que l'ensemble des aires est entièrement décodé. */
+void ensure_all_mem_areas_are_filled(mem_area *, size_t, const GLoadedBinary *, GProcContext *, status_info *);
+
+/* Rassemble les instructions conservées dans des zones données. */
+GArchInstruction *collect_instructions_from_mem_areas(mem_area *, size_t);
+
+
+
+#endif /* _ANALYSIS_DISASS_AREA_H */
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 1fd5550..8bddaa1 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -24,429 +24,96 @@
#include "fetch.h"
-#include <assert.h>
+#include "area.h"
-#include "../../arch/raw.h"
-#include "../../arch/instruction.h"
+/* Suit un flot d'exécution pour désassembler du code. */
+static void follow_execution_flow(const GLoadedBinary *, GProcContext *, mem_area *, size_t, status_info *, virt_t);
-/* Zone mémoire bien bornée */
-typedef struct _mem_area
-{
- mrange_t range; /* Couverture de la zone */
-
- bool has_sym; /* Représentation via symbole ?*/
-
- union
- {
- bool exec; /* Zone exécutable ? */
- GBinSymbol *symbol; /* Symbole associé à la zone */
- };
-} mem_area;
-/* Détermine une liste de zones contigües à traiter. */
-static mem_area *compute_memory_areas(const GExeFormat *, phys_t, size_t *);
-/* Procède au désassemblage basique d'un contenu binaire. */
-static GArchInstruction *load_raw_binary(const GLoadedBinary *, const vmpa2t *, off_t, GtkExtStatusBar *, bstatus_id_t);
-/* Procède au désassemblage d'un contenu binaire exécutable. */
-static GArchInstruction *load_code_binary(const GLoadedBinary *, const vmpa2t *, off_t, GtkExtStatusBar *, bstatus_id_t);
/******************************************************************************
* *
-* Paramètres : format = format d'un exécutable à consulter. *
-* bin_length = quantité d'octets à traiter au total. *
-* count = nombre de zones mises en place. [OUT] *
+* Paramètres : binary = représentation de binaire chargé. *
+* ctx = contexte offert en soutien à un désassemblage. *
+* areas = liste de zones contenant des données à traiter. *
+* count = nombre de ces aires à disposition. *
+* info = informations liées à l'affichage de la progression. *
+* virt = adresse d'un point de départ d'un traitement. *
* *
-* Description : Détermine une liste de zones contigües à traiter. *
+* Description : Suit un flot d'exécution pour désassembler du code. *
* *
-* Retour : Liste de zones mémoire à libérer après usage. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static mem_area *compute_memory_areas(const GExeFormat *format, phys_t bin_length, size_t *count)
+static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx, mem_area *areas, size_t count, status_info *info, virt_t virt)
{
- mem_area *result; /* Liste à renvoyer */
- mrange_t *exe_ranges; /* Liste de zones exécutables */
- size_t exe_count; /* Nombre de ces zones */
- GBinSymbol **symbols; /* Symboles à représenter */
- size_t sym_count; /* Qté de symboles présents */
- vmpa2t *last; /* Dernière bordure rencontrée */
- size_t i; /* Boucle de parcours #1 */
- vmpa2t *border; /* Nouvelle bordure rencontrée */
- mem_area *area; /* Zone avec valeurs à éditer */
- vmpa2t tmp; /* Stockage temporaire */
- size_t j; /* Boucle de parcours #2 */
- const mrange_t *range; /* Couverture d'un symbole */
- const vmpa2t *start; /* Point de départ du symbole */
- phys_t length; /* Taille de ce même symbole */
- bool included; /* Inclusion dans une zone ? */
- mem_area orig; /* Copie de la zone réduite */
- phys_t old_length; /* Taille de zone originelle */
- phys_t new_length; /* Nouvelle taille déterminée */
- size_t next; /* Indice de zone suivante */
-
- result = NULL;
- *count = 0;
-
- /**
- * Le parcours n'est valide que si les listes, symboles et zones exécutables,
- * sont triées !
- */
-
- exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
-
- symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);
-
- /* Première étape : on comble les trous ! */
-
- last = make_vmpa(0, VMPA_NO_VIRTUAL);
-
- for (i = 0; i < exe_count; i++)
- {
- border = get_mrange_addr(&exe_ranges[i]);
-
- /* Zone tampon à constituer */
-
- if (cmp_vmpa_by_phy(last, border) < 0)
- {
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
- area = &result[*count - 1];
-
- init_mrange(&area->range, last, compute_vmpa_diff(last, border));
- area->has_sym = false;
- area->exec = false;
-
- }
-
- /* Insertion d'une zone exécutable déjà définie */
-
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
- area = &result[*count - 1];
- copy_mrange(&area->range, &exe_ranges[i]);
- area->has_sym = false;
- area->exec = true;
- /* Avancée du curseur */
- copy_vmpa(last, border);
- advance_vmpa(last, get_mrange_length(&exe_ranges[i]));
+ vmpa2t addr; /* Conversion en pleine adresse*/
- }
-
- delete_vmpa(last);
-
- /* Extension finale complémentaire ? */
-
- area = &result[*count - 1];
-
- copy_vmpa(&tmp, get_mrange_addr(&area->range));
- advance_vmpa(&tmp, get_mrange_length(&area->range));
-
- if (get_phy_addr(&tmp) < bin_length)
- {
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
- area = &result[*count - 1];
+ mem_area *area; /* Zone de désassemblage */
- init_mrange(&area->range, &tmp, bin_length - get_phy_addr(&tmp));
- area->has_sym = false;
- area->exec = false;
- }
- /* Seconde étape : on insère les symboles existants */
- j = 0;
-#define SKIP_EMPTY_SYMBOLS \
- for (; j < sym_count; j++) \
- { \
- range = g_binary_symbol_get_range(symbols[j]); \
- \
- length = get_mrange_length(range); \
- if (length > 0) break; \
- \
- } \
- SKIP_EMPTY_SYMBOLS
+ g_proc_context_push_drop_point(ctx, virt);
- for (i = 0; i < *count && j < sym_count; i++)
+ while (g_proc_context_has_drop_points(ctx))
{
- range = g_binary_symbol_get_range(symbols[j]);
-
- start = get_mrange_addr(range);
- length = get_mrange_length(range);
-
- /* Si un découpage s'impose... */
-
- if (mrange_contains_addr(&result[i].range, start))
- {
- copy_vmpa(&tmp, start);
- advance_vmpa(&tmp, length);
-
- included = mrange_contains_addr(&result[i].range, &tmp);
-
- memcpy(&orig, &result[i], sizeof(mem_area));
-
- /* Réduction de la zone de départ */
-
- copy_vmpa(&tmp, get_mrange_addr(&result[i].range));
- old_length = get_mrange_length(&result[i].range);
-
- new_length = compute_vmpa_diff(get_mrange_addr(&result[i].range), start);
-
- if (new_length == 0)
- {
- memmove(&result[i], &result[i + 1], (*count - i - 1) * sizeof(mem_area));
-
- (*count)--;
- next = i;
-
- }
- else
- {
- init_mrange(&result[i].range, &tmp, new_length);
- next = i + 1;
- }
-
- /* Insertion de la zone du symbole */
-
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
- memmove(&result[next + 1], &result[next], (*count - next - 1) * sizeof(mem_area));
-
- area = &result[next];
-
- copy_mrange(&area->range, range);
-
- area->has_sym = true;
- area->symbol = symbols[j];
-
- /* Jointure finale... */
-
- if (included)
- {
- /* Simple extension pour rattraper la fin originelle */
-
- if ((old_length - new_length - length) > 0)
- {
- result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
- memmove(&result[next + 2], &result[next + 1], (*count - next - 2) * sizeof(mem_area));
-
- area = &result[next + 1];
-
- copy_vmpa(&tmp, start);
- advance_vmpa(&tmp, length);
-
- memcpy(area, &orig, sizeof(mem_area));
-
- init_mrange(&area->range, &tmp, old_length - new_length - length);
-
- }
+ virt = g_proc_context_pop_drop_point(ctx);
+ init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
- i = next;
- }
- else
- {
- /* Suppression des éventuelles zones totalement recouvertes */
+ area = find_memory_area_by_addr(areas, count, &addr);
+ /*
+ printf("found area = %p\n", area);
+ printf(" ... 0x%08x - 0x%08x + %u\n",
+ area->range.addr.physical,
+ area->range.addr.virtual,
+ area->range.length);
+ */
- /* Réduction de la zone d'arrivée */
+ load_code_from_mem_area(area, areas, count, binary, ctx, &addr, info);
- }
-
-
-
- j++;
-
- SKIP_EMPTY_SYMBOLS
-
- }
+ //exit(0);
}
-
-
- //free
-
- //exit(0);
-
- return result;
-
}
-/******************************************************************************
-* *
-* Paramètres : binary = représentation de binaire chargé. *
-* parts = parties binaires à désassembler. *
-* count = nombre de parties à traiter. *
-* statusbar = barre de statut avec progression à mettre à jour.*
-* id = identifiant du message affiché à l'utilisateur. *
-* *
-* Description : Procède au désassemblage basique d'un contenu binaire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-static GArchInstruction *load_raw_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
- GArchInstruction *result; /* Liste d'instr. à renvoyer */
- GBinFormat *format; /* Format du fichier binaire */
- GArchProcessor *proc; /* Architecture du binaire */
- off_t bin_length; /* Taille des données à lire */
- bin_t *bin_data; /* Données binaires à lire */
- vmpa2t pos; /* Boucle de parcours */
- vmpa2t prev; /* Boucle de parcours */
- off_t old_phy; /* Ancienne position physique */
- GArchInstruction *instr; /* Instruction décodée */
- off_t new_phy; /* Nouvelle position physique */
- mrange_t range; /* Couverture de l'instruction */
- result = NULL;
- format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
- proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
- bin_data = g_loaded_binary_get_data(binary, &bin_length);
- copy_vmpa(&pos, base);
- copy_vmpa(&prev, base);
- old_phy = get_phy_addr(&prev);
- while (old_phy < end)
- {
- instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, end,
- g_arch_processor_get_endianness(proc));
- if (instr == NULL) printf(" Break !!!\n");
- if (instr == NULL) break;
- new_phy = get_phy_addr(&pos);
- init_mrange(&range, &prev, new_phy - old_phy);
- g_arch_instruction_set_range(instr, &range);
- g_arch_instruction_add_to_list(&result, instr);
-
- copy_vmpa(&prev, &pos);
- old_phy = get_phy_addr(&prev);
-
- //done += (new_phy - old_phy);
- //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : binary = représentation de binaire chargé. *
-* parts = parties binaires à désassembler. *
-* count = nombre de parties à traiter. *
-* statusbar = barre de statut avec progression à mettre à jour.*
-* id = identifiant du message affiché à l'utilisateur. *
-* *
-* Description : Procède au désassemblage d'un contenu binaire exécutable. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
- GArchInstruction *result; /* Liste d'instr. à renvoyer */
- GBinFormat *format; /* Format du fichier binaire */
- GArchProcessor *proc; /* Architecture du binaire */
- off_t bin_length; /* Taille des données à lire */
- bin_t *bin_data; /* Données binaires à lire */
- vmpa2t pos; /* Boucle de parcours */
- vmpa2t prev; /* Boucle de parcours */
- off_t old_phy; /* Ancienne position physique */
- GArchInstruction *instr; /* Instruction décodée */
- off_t new_phy; /* Nouvelle position physique */
- mrange_t range; /* Couverture de l'instruction */
-
- result = NULL;
-
- format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
- proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
- bin_data = g_loaded_binary_get_data(binary, &bin_length);
-
- copy_vmpa(&pos, base);
- copy_vmpa(&prev, base);
-
- old_phy = get_phy_addr(&prev);
-
- while (old_phy < end)
- {
- instr = g_arch_processor_disassemble(proc, NULL, bin_data, &pos, end);
-
- //if (!G_IS_RAW_INSTRUCTION(instr)) printf("GOT %p\n", instr);
-
- if (instr == NULL)
- instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, end,
- g_arch_processor_get_endianness(proc));
- if (instr == NULL) printf(" Break !!!\n");
- if (instr == NULL) break;
-
- new_phy = get_phy_addr(&pos);
- init_mrange(&range, &prev, new_phy - old_phy);
-
- g_arch_instruction_set_range(instr, &range);
-
- g_arch_instruction_add_to_list(&result, instr);
-
- copy_vmpa(&prev, &pos);
- old_phy = get_phy_addr(&prev);
-
- //done += (new_phy - old_phy);
- //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
-
-
-
-
-
- g_arch_instruction_call_hook(instr, IPH_LINK, NULL, format);
-
-
- g_arch_instruction_call_hook(instr, IPH_POST, NULL, format);
-
-
-
-
- }
-
- return result;
-
-}
@@ -467,83 +134,34 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
* *
******************************************************************************/
-static GArchInstruction *follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx, mem_area *areas, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
+GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
{
- GBinFormat *format; /* Format du fichier binaire */
-
- virt_t addr;
-
-
-
- mem_area *area; /* Zone de désassemblage */
-
-
- format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-
- /* Insertion du point de départ */
-
- addr = g_binary_format_get_entry_point(format);
-
- g_proc_context_push_drop_point(ctx, addr);
-
- /* Suivi de l'exécution autant que possible */
-
- while (g_proc_context_has_drop_points(ctx))
- {
- //virt = g_proc_context_pop_drop_point(ctx);
-
-
- area = NULL;
-
-
-
-
- }
-
-
-
-
- // ctx.add(entry_point)
-
- // while (ctx.has_pending_addresses)
-
- // virt = ctx.pop
- // find mem_area for virt
-
- // if area.limit < virt then continue
-
-
+ GArchInstruction *result; /* Instruction désassemblées */
+ GBinFormat *format; /* Format du fichier binaire */
+ GArchProcessor *proc; /* Architecture du binaire */
+ GProcContext *ctx; /* Contexte de désassemblage */
-}
+ status_info *info;
+ off_t length; /* Taille des données à lire */
+ mem_area *areas; /* Zone de productions */
+ size_t count; /* Nombre de ces zones */
+ virt_t virt; /* Point d'accroche virtuelle */
+ GBinSymbol **symbols; /* Symboles à représenter */
+ size_t sym_count; /* Qté de symboles présents */
+ size_t i; /* Boucle de parcours */
-/******************************************************************************
-* *
-* Paramètres : binary = représentation de binaire chargé. *
-* statusbar = barre de statut avec progression à mettre à jour.*
-* id = identifiant du message affiché à l'utilisateur. *
-* *
-* Description : Procède au désassemblage basique d'un contenu binaire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-GArchInstruction *disassemble_binary_content_new(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
- GBinFormat *format; /* Format du fichier binaire */
- GArchProcessor *proc; /* Architecture du binaire */
+ const mrange_t *range; /* Couverture d'un symbole */
+ const vmpa2t *addr; /* Point de départ du symbole */
- GProcContext *ctx; /* Contexte de désassemblage */
@@ -553,88 +171,46 @@ GArchInstruction *disassemble_binary_content_new(const GLoadedBinary *binary, Gt
ctx = g_arch_processor_get_context(proc);
+ info = NULL;
-}
-
+ /* Définition à la découpe des parties à traiter */
+ g_loaded_binary_get_data(binary, &length);
+ areas = compute_memory_areas(G_EXE_FORMAT(format), length, &count);
-/******************************************************************************
-* *
-* Paramètres : binary = représentation de binaire chargé. *
-* statusbar = barre de statut avec progression à mettre à jour.*
-* id = identifiant du message affiché à l'utilisateur. *
-* *
-* Description : Procède au désassemblage basique d'un contenu binaire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ /* Insertion du point de départ */
-GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
- GArchInstruction *result; /* Instruction désassemblées */
- GExeFormat *format; /* Format du fichier binaire */
- off_t length; /* Taille des données à lire */
- mem_area *areas; /* Zone de productions */
- size_t count; /* Nombre de ces zones */
- size_t i; /* Boucle de parcours */
- mem_area *iter; /* Zone parcourue */
- GArchInstruction *instr; /* Instruction(s) à insérer */
- const vmpa2t *start; /* Début d'une zone traitée */
- phys_t end; /* Fin d'une zone traitée */
+ virt = g_binary_format_get_entry_point(format);
- result = NULL;
+ follow_execution_flow(binary, ctx, areas, count, info, virt);
- format = g_loaded_binary_get_format(binary);
- g_loaded_binary_get_data(binary, &length);
+ /* Symboles exécutables présents et passés à travers les mailles */
- areas = compute_memory_areas(format, length, &count);
+ symbols = g_binary_format_get_symbols(format, &sym_count);
- for (i = 0; i < count; i++)
+ for (i = 0; i < sym_count; i++)
{
- iter = &areas[i];
-
- start = get_mrange_addr(&iter->range);
- end = get_phy_addr(start) + get_mrange_length(&iter->range);
+ if (g_binary_symbol_get_target_type(symbols[i]) != STP_FUNCTION)
+ continue;
- assert(get_mrange_length(&iter->range) > 0);
+ range = g_binary_symbol_get_range(symbols[i]);
+ addr = get_mrange_addr(range);
+ virt = get_virt_addr(addr);
- if (iter->has_sym)
- switch (g_binary_symbol_get_target_type(iter->symbol))
- {
- case STP_DATA:
- instr = g_binary_symbol_get_instruction(iter->symbol);
- g_object_ref(G_OBJECT(instr));
- break;
+ follow_execution_flow(binary, ctx, areas, count, info, virt);
- case STP_ROUTINE:
- instr = load_code_binary(binary, start, end, statusbar, id);
- break;
-
- default:
- assert(false);
- break;
+ }
- }
- else
- {
- if (iter->exec)
- instr = load_code_binary(binary, start, end, statusbar, id);
- else
- instr = load_raw_binary(binary, start, end, statusbar, id);
+ ensure_all_mem_areas_are_filled(areas, count, binary, ctx, info);
- }
- g_arch_instruction_merge_lists(&result, &instr);
- }
+ result = collect_instructions_from_mem_areas(areas, count);
- free(areas);
+ /* free */
- return result;
+ return result;
}