summaryrefslogtreecommitdiff
path: root/src/analysis/disass/area.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass/area.c')
-rw-r--r--src/analysis/disass/area.c1085
1 files changed, 1082 insertions, 3 deletions
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 1d841be..355b716 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -27,6 +27,1087 @@
#include <assert.h>
+#include <i18n.h>
+
+
+#include "../../analysis/contents/restricted.h"
+#include "../../common/bits.h"
+#include "../../gui/panels/log.h"
+
+
+
+
+/* Zone mémoire bien bornée */
+typedef struct _mem_area_v2
+{
+ GBinFormat *format; /* Format du fichier binaire */
+ GBinContent *content; /* Données binaires à lire */
+ GArchProcessor *proc; /* Architecture du binaire */
+ SourceEndian endianness; /* Boutisme de cette machine */
+
+ mrange_t range; /* Couverture de la zone */
+
+ phys_t packing_size; /* Granularité des découpages */
+
+ bitfield_t *processed; /* Octets traités dans la zone */
+ GArchInstruction **instructions; /* Instructions en place */
+
+
+
+
+ bool is_exec; /* Zone exécutable ? */
+
+} mem_area_v2;
+
+
+
+/* Initialise une aire de données à partir d'une adresse donnée. */
+static void init_mem_area_from_addr_v2(mem_area_v2 *, const vmpa2t *, phys_t, const GLoadedBinary *);
+
+/* Libère d'une aire de données les ressources allouées. */
+static void fini_mem_area_v2(mem_area_v2 *);
+
+/* Indique si une zone donnée est intégralement vierge ou non. */
+static bool is_range_blank_in_mem_area_v2(mem_area_v2 *, phys_t, phys_t);
+
+/* Marque une série d'octets comme ayant été traités. */
+static bool mark_range_in_mem_area_as_processed_v2(mem_area_v2 *, GArchInstruction *, bool);
+
+
+
+
+/* Procède au désassemblage d'un contenu binaire non exécutable. */
+static void load_data_from_mem_area_v2(mem_area_v2 *, GProcContext *, const vmpa2t *, status_blob_info *);
+
+/* S'assure qu'une aire contient toutes ses instructions. */
+static void fill_mem_area_v2(mem_area_v2 *, mem_area_v2 *, size_t, GProcContext *, status_blob_info *);
+
+/* Rassemble les instructions conservées dans une zone donnée. */
+static GArchInstruction *get_instructions_from_mem_area_v2(const mem_area_v2 *);
+
+
+
+
+
+
+/* S'assure de la présence d'un début de routine à un point. */
+static void update_address_as_routine(GBinFormat *, const vmpa2t *);
+
+
+/**
+ * Content :: à passer en restricted.
+
+ * Les sections croisées : pas de sens de les traiter ici, car au final une instruction sera à cheval
+ * sur deux sections différentes -> incohérence au niveau de l'éditeur.
+ * => régler le périmètres de segments règle donc tous les soucis.
+
+ */
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* 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. *
+* binary = binaire analysé content quantités d'informations. *
+* *
+* Description : Initialise une aire de données à partir d'une adresse donnée.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void init_mem_area_from_addr_v2(mem_area_v2 *area, const vmpa2t *addr, phys_t len, const GLoadedBinary *binary)
+{
+ GBinContent *content; /* Données binaires à lire */
+
+ assert(len > 0);
+
+ area->format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+
+ content = g_binary_format_get_content(area->format);
+
+ area->proc = g_loaded_binary_get_processor(binary);
+ area->endianness = g_arch_processor_get_endianness(area->proc);
+
+ init_mrange(&area->range, addr, len);
+
+ area->content = g_restricted_content_new(content, &area->range);
+
+ area->packing_size = 2; /* FIXME */
+
+ area->processed = create_bit_field(len, false);
+ 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_v2(mem_area_v2 *area)
+{
+ phys_t len; /* Etendue du parcours total */
+ phys_t i; /* Boucle de parcours */
+
+ //g_object_unref(area->format); /* FIXME */
+ g_object_unref(area->content);
+ //g_object_unref(area->proc); /* FIXME */
+
+ delete_bit_field(area->processed);
+
+ len = get_mrange_length(&area->range);
+
+ for (i = 0; i < len; i++)
+ if (area->instructions[i] != NULL)
+ g_object_unref(G_OBJECT(area->instructions[i]));
+
+ free(area->instructions);
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* 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_v2(mem_area_v2 *area, phys_t start, phys_t len)
+{
+ bool result; /* Résultat à renvoyer */
+
+ if ((start + len) >= get_mrange_length(&area->range))
+ result = false;
+
+ else
+ result = !test_in_bit_field(area->processed, start, len);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* instr = instruction à mémoriser pour la suite. *
+* force = impose l'enregistrement de l'instruction. *
+* *
+* Description : Marque une série d'octets comme ayant été traités. *
+* *
+* Retour : true si l'enregistrement a bien été réalisé, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool mark_range_in_mem_area_as_processed_v2(mem_area_v2 *area, GArchInstruction *instr, bool force)
+{
+ bool result; /* Bilan d'action à renvoyer */
+ const vmpa2t *start; /* Adresse de départ de la zone*/
+ const mrange_t *range; /* Emplacement d'instruction */
+ const vmpa2t *addr; /* Début de la zone à traiter */
+ phys_t len; /* Taille de l'aire visée */
+ phys_t offset; /* Décallage de départ */
+
+ start = get_mrange_addr(&area->range);
+
+ range = g_arch_instruction_get_range(instr);
+ addr = get_mrange_addr(range);
+ len = get_mrange_length(range);
+
+ offset = compute_vmpa_diff(start, addr);
+
+ result = set_atomic_in_bit_field(area->processed, offset, len);
+
+ /* Si l'instruction était bien la première à s'inscrire... */
+
+ result |= force;
+
+ if (result)
+ area->instructions[offset] = instr;
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* list = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* index = indice de l'aire à considérer pendant l'opération. *
+* 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_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count, GProcContext *ctx, const vmpa2t *start, status_blob_info *info)
+{
+
+
+
+ GBinFormat *format; /* Format du fichier binaire */
+ GArchProcessor *proc; /* Architecture du binaire */
+ GBinContent *content; /* 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 */
+
+
+ bool done; /* Enregistrement effectué ? */
+
+
+ vmpa2t sym_addr; /* Adresse de nouveau symbole */
+ bool has_new_sym; /* Statut d'un dépilement */
+
+ GBinSymbol *symbol; /* Symbole créé en parallèle */
+
+
+
+
+
+ /* Récupération des informations de base */
+
+ format = area->format;
+ proc = area->proc;
+ content = area->content;
+
+ diff = compute_vmpa_diff(get_mrange_addr(&area->range), start);
+ alen = get_mrange_length(&area->range);
+
+ copy_vmpa(&pos, start);
+
+ /* Traitement de la zone */
+
+ printf("=== processing @ 0x%08x\n", (unsigned int)start->virtual);
+
+ for (i = diff; i < alen; i += diff)
+ {
+ /**
+ * On réalise un premier test informel (car non atomique) peu coûteux
+ * avant de se lancer dans un désassemblage d'instruction potentiellement
+ * inutile.
+ */
+
+ printf(" (%u) blank ? %d\n", (unsigned int)i, is_range_blank_in_mem_area_v2(area, i, 1));
+ printf(" +1 blank ? %d\n", is_range_blank_in_mem_area_v2(area, i + 1, 1));
+
+ if (!is_range_blank_in_mem_area_v2(area, i, 1))
+ break;
+
+ /* Décodage d'une nouvelle instruction */
+
+ copy_vmpa(&prev, &pos);
+
+ instr = g_arch_processor_disassemble(proc, ctx, content, &pos);
+ 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);
+
+ /* Progression dans les traitements */
+
+ done = mark_range_in_mem_area_as_processed_v2(area, instr, false);
+
+ if (!done)
+ {
+ g_object_unref(G_OBJECT(instr));
+ break;
+ }
+
+ inc_progessive_status(info, diff);
+
+ assert(!is_range_blank_in_mem_area_v2(area, i, diff));
+
+ /* Enregistrement d'un éventuel début de routine */
+
+ if (g_arch_instruction_get_flags(instr) & AIF_ROUTINE_START)
+ update_address_as_routine(format, &prev);
+
+ /* Eventuel renvoi vers d'autres adresses */
+
+ g_arch_instruction_call_hook(instr, IPH_FETCH, proc, ctx, format);
+
+ /* Insertion des symboles découverts en parallèle */
+
+ for (has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr);
+ has_new_sym;
+ has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr))
+ {
+ has_new_sym = g_binary_format_find_symbol_at(format, &sym_addr, &symbol);
+ assert(has_new_sym);
+
+ insert_extra_symbol_into_mem_areas_v2(list, count, symbol);
+
+ }
+
+ /* Rupture du flot d'exécution ? */
+ if (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT)
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = aire représentant à contenu à parcourir. *
+* 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_v2(mem_area_v2 *area, GProcContext *ctx, const vmpa2t *start, status_blob_info *info)
+{
+ GBinContent *content; /* Données binaires à lire */
+ SourceEndian endianness; /* Boutisme de cette machine */
+ phys_t diff; /* Volume de données traité */
+ phys_t alen; /* Taille de l'aire utilisée */
+ vmpa2t pos; /* Boucle de parcours */
+ phys_t i; /* Boucle de parcours */
+ vmpa2t prev; /* Boucle de parcours */
+ GArchInstruction *instr; /* Instruction décodée */
+ mrange_t range; /* Couverture de l'instruction */
+ bool done; /* Enregistrement effectué ? */
+
+ /* Récupération des informations de base */
+
+ content = area->content;
+ endianness = area->endianness;
+
+ diff = compute_vmpa_diff(get_mrange_addr(&area->range), start);
+ alen = get_mrange_length(&area->range);
+
+ copy_vmpa(&pos, start);
+
+ /* Traitement de la zone */
+
+ for (i = diff; i < alen; i += diff)
+ {
+ /* On cherche à obtenir l'assurance que le traitement n'a jamais été fait */
+
+ if (!is_range_blank_in_mem_area_v2(area, i, 1))
+ break;
+
+ instr = NULL;
+
+ copy_vmpa(&prev, &pos);
+
+ /* Décodage d'une nouvelle instruction, sur mesure puis minimale */
+
+ if (get_virt_addr(&pos) % area->packing_size == 0
+ && is_range_blank_in_mem_area_v2(area, i, area->packing_size))
+ {
+ diff = area->packing_size;
+
+ instr = g_raw_instruction_new_array(content, MDS_FROM_BYTES(diff), 1, &pos, endianness);
+
+ if (instr == NULL)
+ copy_vmpa(&pos, &prev);
+
+ }
+
+ if (instr == NULL)
+ {
+ diff = 1;
+
+ instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, &pos, endianness);
+
+ }
+
+ /* On rencontre ici un morceau déjà traité. */
+
+ if (instr == NULL) break;
+
+ /* Enregistrement des positions et adresses */
+
+ assert(diff == compute_vmpa_diff(&prev, &pos));
+
+ init_mrange(&range, &prev, diff);
+
+ g_arch_instruction_set_range(instr, &range);
+
+ /* Progression dans les traitements */
+
+ done = mark_range_in_mem_area_as_processed_v2(area, instr, false);
+
+ if (!done)
+ {
+ g_object_unref(G_OBJECT(instr));
+ break;
+ }
+
+ inc_progessive_status(info, diff);
+
+ assert(!is_range_blank_in_mem_area_v2(area, i, diff));
+
+ /* On laisse une chance au code pour se reprendre... */
+
+ if (area->is_exec) break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* 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_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count, GProcContext *ctx, status_blob_info *info)
+{
+ const vmpa2t *addr; /* Début de la zone à traiter */
+ phys_t len; /* Taille de la zone à remplir */
+ phys_t i; /* Boucle de parcours */
+ vmpa2t start; /* Adresse de départ de combles*/
+
+ addr = get_mrange_addr(&area->range);
+ len = get_mrange_length(&area->range);
+
+ for (i = 0; i < len; i++)
+ {
+ if (is_range_blank_in_mem_area_v2(area, i, 1))
+ {
+ copy_vmpa(&start, addr);
+ advance_vmpa(&start, i);
+
+ if (area->is_exec && get_virt_addr(&start) % area->packing_size == 0)
+ load_code_from_mem_area_v2(area, list, count, ctx, &start, info);
+
+ if (is_range_blank_in_mem_area_v2(area, i, 1))
+ load_data_from_mem_area_v2(area, ctx, &start, info);
+
+ }
+
+ assert(!is_range_blank_in_mem_area_v2(area, i, 1));
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* 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_v2(const mem_area_v2 *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;
+
+ 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 : 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 : Indice de la zone trouvée, ou nombre d'aires en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+mem_area_v2 *find_memory_area_by_addr_v2(mem_area_v2 *list, size_t count, const vmpa2t *addr)
+{
+ mem_area_v2 *result; /* Elément trouvé à renvoyer */
+
+ int find_mem_area(const vmpa2t *addr, const mem_area_v2 *area)
+ {
+ int status; /* Bilan à retourner */
+
+ if (mrange_contains_addr(&area->range, addr))
+ status = 0;
+
+ else
+ status = cmp_vmpa(addr, get_mrange_addr(&area->range));
+
+ return status;
+
+ }
+
+ result = bsearch(addr, list, count, sizeof(mem_area_v2), (__compar_fn_t)find_mem_area);
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = binaire analysé contenant quantités d'infos. *
+* 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_v2 *compute_memory_areas_v2(const GLoadedBinary *binary, phys_t bin_length, size_t *count)
+{
+ mem_area_v2 *result; /* Liste à renvoyer */
+ GExeFormat *format; /* Format de fichier associé */
+ 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 */
+ bool status; /* Bilan d'une conversion */
+ size_t i; /* Boucle de parcours #1 */
+ const vmpa2t *border; /* Nouvelle bordure rencontrée */
+ mem_area_v2 *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 */
+ SymbolType type; /* Nature d'un symbole */
+ const mrange_t *range; /* Couverture d'un symbole */
+ phys_t length; /* Taille de ce même symbole */
+ phys_t new_length; /* Nouvelle taille déterminée */
+
+ result = NULL;
+ *count = 0;
+
+ /**
+ * Le parcours n'est valide que si les zones exécutables sont triées !
+ */
+
+ format = g_loaded_binary_get_format(binary);
+
+ 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 ! */
+
+ status = g_exe_format_translate_offset_into_vmpa(format, 0, &last);
+ assert(status);
+
+ for (i = 0; i < exe_count; i++)
+ {
+ border = get_mrange_addr(&exe_ranges[i]);
+
+ /* Zone tampon à constituer */
+
+ if (cmp_vmpa(&last, border) < 0)
+ {
+ result = (mem_area_v2 *)realloc(result, ++(*count) * sizeof(mem_area_v2));
+
+ area = &result[*count - 1];
+
+ init_mem_area_from_addr_v2(area, &last, compute_vmpa_diff(&last, border), binary);
+ area->is_exec = false;
+
+ }
+
+ /* Insertion d'une zone exécutable déjà définie */
+
+ result = (mem_area_v2 *)realloc(result, ++(*count) * sizeof(mem_area_v2));
+
+ area = &result[*count - 1];
+
+ init_mem_area_from_addr_v2(area, get_mrange_addr(&exe_ranges[i]),
+ get_mrange_length(&exe_ranges[i]), binary);
+ area->is_exec = true;
+
+ /* Avancée du curseur */
+
+ compute_mrange_end_addr(&exe_ranges[i], &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_v2 *)realloc(result, ++(*count) * sizeof(mem_area_v2));
+
+ area = &result[*count - 1];
+
+ init_mem_area_from_addr_v2(area, &tmp, bin_length - get_phy_addr(&tmp), binary);
+ area->is_exec = false;
+
+ }
+
+
+
+
+
+
+
+
+ for (i = 0; i < *count; i++)
+ {
+ printf(" (init) AREA %zu :: 0x%x / 0x%x + 0x%x\n",
+ i,
+ (unsigned int)get_phy_addr(get_mrange_addr(&result[i].range)),
+ (unsigned int)get_virt_addr(get_mrange_addr(&result[i].range)),
+ (unsigned int)get_mrange_length(&result[i].range));
+
+ }
+
+ printf("--------------------\n");
+
+
+
+
+
+
+
+
+ /* Seconde étape : on s'assure du découpage autour des portions pour respecter l'alignement */
+
+ 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]));
+
+ printf(" [portion % 3zu] addr = 0x%x / 0x%x\n",
+ i,
+ (unsigned int)get_phy_addr(portion_start),
+ (unsigned int)get_virt_addr(portion_start));
+
+ 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_v2(&result[j]);
+
+ result = (mem_area_v2 *)realloc(result, ++(*count) * sizeof(mem_area_v2));
+
+ memmove(&result[j + 2], &result[j + 1], (*count - j - 2) * sizeof(mem_area_v2));
+
+ status = result[j].is_exec;
+
+ /* Première moitié */
+
+ area = &result[j];
+
+ copy_vmpa(&tmp, get_mrange_addr(&area->range));
+ length = get_mrange_length(&area->range);
+
+ new_length = compute_vmpa_diff(&tmp, portion_start);
+
+ init_mem_area_from_addr_v2(area, &tmp, new_length, binary);
+ area->is_exec = status;
+
+ /* Seconde moitié */
+
+ length -= get_mrange_length(&area->range);
+
+ area = &result[j + 1];
+
+ init_mem_area_from_addr_v2(area, portion_start, length, binary);
+ area->is_exec = status;
+
+ }
+
+ j = *count;
+
+ }
+
+ }
+
+
+
+
+
+
+
+
+ for (i = 0; i < *count; i++)
+ {
+ printf(" (fini) AREA %zu :: 0x%x / 0x%x + 0x%x\n",
+ i,
+ (unsigned int)get_phy_addr(get_mrange_addr(&result[i].range)),
+ (unsigned int)get_virt_addr(get_mrange_addr(&result[i].range)),
+ (unsigned int)get_mrange_length(&result[i].range));
+
+ }
+
+ printf("--------------------\n");
+
+
+
+
+
+
+
+
+ /* Troisième étape : on insère les symboles existants */
+
+ for (i = 0; i < sym_count; i++)
+ {
+ type = g_binary_symbol_get_target_type(symbols[i]);
+
+ /**
+ * On ne garde que les symboles renvoyant directement une ou
+ * plusieurs instructions, c'est à dire les symboles valides
+ * pour un appel à g_binary_symbol_get_instruction().
+ *
+ * Les instructions des autres symboles sont obtenues et mises
+ * en place durant la procédure de désassemblage.
+ */
+
+ if (type == STP_ROUTINE || type == STP_ENTRY_POINT || type == STP_CODE_LABEL)
+ continue;
+
+ range = g_binary_symbol_get_range(symbols[i]);
+
+ length = get_mrange_length(range);
+
+ if (length == 0)
+ continue;
+
+ insert_extra_symbol_into_mem_areas_v2(result, *count, symbols[i]);
+
+ }
+
+ /* Nettoyage final */
+
+ if (portions != NULL)
+ free(portions);
+
+ if (exe_ranges != NULL)
+ free(exe_ranges);
+
+ /// FIXME g_object_unref(G_OBJECT(format));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : areas = liste de zones délimitant des contenus à traiter. *
+* count = nombre de zones à disposition. *
+* symbol = élément nouveau à venir insérer dans les zones. *
+* *
+* Description : Insère un symbole dans un découpage en aires. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void insert_extra_symbol_into_mem_areas_v2(mem_area_v2 *areas, size_t count, const GBinSymbol *symbol)
+{
+ SymbolType type; /* Type de symbole */
+ GArchInstruction *list; /* Ensemble à insérer */
+ GArchInstruction *iter; /* Boucle de parcours */
+ const mrange_t *range; /* Emplacement d'instruction */
+ const vmpa2t *addr; /* Départ de cet emplacement */
+ mem_area_v2 *area; /* Zone d'accueil désignée */
+ VMPA_BUFFER(loc); /* Description d'un emplacement*/
+ phys_t start; /* Point de départ */
+
+ type = g_binary_symbol_get_target_type(symbol);
+
+ if (!HAS_DATA_INSTR(type))
+ return;
+
+ list = g_binary_symbol_get_instruction(symbol);
+
+ for (iter = list; iter != NULL; iter = g_arch_instruction_get_next_iter(list, iter, ~0))
+ {
+ range = g_arch_instruction_get_range(iter);
+ addr = get_mrange_addr(range);
+
+ /* Une aire d'accueil existe-t-elle ? */
+
+ area = find_memory_area_by_addr_v2(areas, count, addr);
+
+ if (area == NULL)
+ {
+ vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL);
+
+ log_variadic_message(LMT_WARNING, _("No place found for symbol located at %s."), loc);
+ continue;
+
+ }
+
+ /* L'instruction est-elle accueillie dans son intégralité ? */
+
+ start = compute_vmpa_diff(get_mrange_addr(&area->range), addr);
+
+ if (start + get_mrange_length(range) > get_mrange_length(&area->range))
+ {
+ vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL);
+
+ log_variadic_message(LMT_WARNING, _("The symbol located at %s is too big for one place only."), loc);
+ continue;
+
+ }
+
+ /* Inscription d'une instruction de symbole (sans retour arrière possible :/ ) */
+
+ mark_range_in_mem_area_as_processed_v2(area, iter, true);
+
+ g_object_ref(G_OBJECT(iter));
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* 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_v2 *list, size_t count, GProcContext *ctx, status_blob_info *info)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < count; i++)
+ fill_mem_area_v2(&list[i], list, count, 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_v2(const mem_area_v2 *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_v2(&list[i]);
+ g_arch_instruction_merge_lists(&result, &instr);
+ }
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+
+
+
/* Zone mémoire bien bornée */
typedef struct _mem_area
@@ -72,7 +1153,7 @@ static bool mark_range_in_mem_area_as_processed(mem_area *, phys_t, phys_t, GArc
/* S'assure de la présence d'un début de routine à un point. */
-static void update_address_as_routine(GBinFormat *, const vmpa2t *);
+//static void update_address_as_routine(GBinFormat *, const vmpa2t *);
@@ -1468,8 +2549,6 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, G
memmove(&(*list)[index + 1], &(*list)[index], (*count - index - 1) * sizeof(mem_area));
- /* Aire raccourcie */
-
copy_vmpa(&area_pos, get_mrange_addr(&area_range));
new_length = get_mrange_length(&area_range) - get_mrange_length(sym_range);