/* 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. * * Chrysalide 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. * * Chrysalide 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 . */ #include "area.h" #include #include #include "../../analysis/contents/restricted.h" #include "../../arch/raw.h" #include "../../common/bits.h" #include "../../gui/panels/log.h" /* Zone mémoire bien bornée */ typedef struct _mem_area { 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; /* 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, const GLoadedBinary *); /* 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); /* Marque une série d'octets comme ayant été traités. */ static bool mark_range_in_mem_area_as_processed(mem_area *, GArchInstruction *, bool); /* Crée une instruction issue d'un désassemblage brut. */ static GArchInstruction *load_raw_instruction_from_mem_area(mem_area *, phys_t, vmpa2t *, phys_t *); /* S'assure de la présence d'un début de routine à un point. */ static void update_address_as_routine(GBinFormat *, const vmpa2t *); /* Procède au désassemblage d'un contenu binaire non exécutable. */ static void load_data_from_mem_area(mem_area *, GProcContext *, const vmpa2t *, GtkStatusStack *, activity_id_t); /* S'assure qu'une aire contient toutes ses instructions. */ static void fill_mem_area(mem_area *, mem_area *, size_t, GProcContext *, GtkStatusStack *, activity_id_t); /* Rassemble les instructions conservées dans une zone donnée. */ static GArchInstruction *get_instructions_from_mem_area(const mem_area *); /****************************************************************************** * * * 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(mem_area *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(mem_area *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(mem_area *area, phys_t start, phys_t len) { bool result; /* Résultat à renvoyer */ assert((start + len) <= get_mrange_length(&area->range)); 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(mem_area *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. * * offset = point de départ au sein de l'aire en question. * * pos = tête de lecture dans l'espace global. * * size = taille de l'instruction mise en place. [OUT] * * * * Description : Crée une instruction issue d'un désassemblage brut. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *load_raw_instruction_from_mem_area(mem_area *area, phys_t offset, vmpa2t *pos, phys_t *size) { GArchInstruction *result; /* Instruction à retourner */ GBinContent *content; /* Données binaires à lire */ SourceEndian endianness; /* Boutisme de cette machine */ phys_t sz; /* Volume de données traité */ vmpa2t prev; /* Boucle de parcours */ result = NULL; content = area->content; endianness = area->endianness; sz = area->packing_size; if (get_virt_addr(pos) % sz == 0 && is_range_blank_in_mem_area(area, offset, sz)) { *size = sz; copy_vmpa(&prev, pos); result = g_raw_instruction_new_array(content, MDS_FROM_BYTES(sz), 1, pos, endianness); if (result == NULL) copy_vmpa(pos, &prev); } if (result == NULL) { *size = 1; result = g_raw_instruction_new_array(content, MDS_8_BITS, 1, pos, endianness); } return result; } /****************************************************************************** * * * Paramètres : format = format binaire en cours de traitement. * * addr = adresse d'une instruction présentée comme première. * * * * Description : S'assure de la présence d'un début de routine à un point. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void update_address_as_routine(GBinFormat *format, const vmpa2t *addr) { GBinSymbol *symbol; /* Symbole présent ou créé */ bool found; /* Détection de symbole */ SymbolType sym_type; /* Type de symbole en place */ bool wrong_type; /* Analyse plus fine de ce type*/ mrange_t range; /* Etendue du symbole à créer */ VMPA_BUFFER(loc); /* Traduction de l'adresse */ char name[5 + VMPA_MAX_LEN]; /* Nom de symbole nouveau */ GBinRoutine *routine; /* Nouvelle routine trouvée */ found = g_binary_format_find_symbol_at(format, addr, &symbol); if (found) { sym_type = g_binary_symbol_get_target_type(symbol); wrong_type = (sym_type != STP_ROUTINE && sym_type != STP_ENTRY_POINT); } if (!found || (found && wrong_type)) { init_mrange(&range, addr, 0); vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL); snprintf(name, sizeof(name), "sub_%s", loc + 2); routine = g_binary_routine_new(); g_binary_routine_set_name(routine, strdup(name)); g_binary_routine_set_range(routine, &range); if (!found) { symbol = g_binary_symbol_new(STP_ROUTINE); g_binary_symbol_attach_routine(symbol, routine); g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); } else _g_binary_symbol_attach_routine(symbol, routine, STP_ROUTINE); } } /****************************************************************************** * * * 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. * * force = force la création d'au moins une instruction. * * status = barre de statut à actualiser. * * id = identifiant du groupe de progression à l'affichage. * * * * 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, GProcContext *ctx, const vmpa2t *start, bool force, GtkStatusStack *status, activity_id_t id) { GBinFormat *format; /* Format du fichier binaire */ GArchProcessor *proc; /* Architecture du binaire */ GBinContent *content; /* Données binaires à lire */ phys_t init_diff; /* Position initiale de lecture*/ phys_t alen; /* Taille de l'aire utilisée */ bool forced_once; /* Préfigure une sortie rapide */ phys_t i; /* Boucle de parcours */ vmpa2t pos; /* Boucle de parcours */ vmpa2t prev; /* Boucle de parcours */ GArchInstruction *instr; /* Instruction décodée */ phys_t diff; /* Volume de données traité */ 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; init_diff = compute_vmpa_diff(get_mrange_addr(&area->range), start); alen = get_mrange_length(&area->range); copy_vmpa(&pos, start); /* Traitement de la zone */ forced_once = false; for (i = init_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. */ if (!is_range_blank_in_mem_area(area, i, 1)) break; /* Décodage d'une nouvelle instruction */ copy_vmpa(&prev, &pos); instr = g_arch_processor_disassemble(proc, ctx, content, &pos, G_EXE_FORMAT(format)); if (instr != NULL) diff = compute_vmpa_diff(&prev, &pos); else { if (i == init_diff && force) { instr = load_raw_instruction_from_mem_area(area, i, &pos, &diff); forced_once = true; } if (instr == NULL) break; } /* Enregistrement des positions et adresses */ init_mrange(&range, &prev, diff); g_arch_instruction_set_range(instr, &range); /* Progression dans les traitements */ done = mark_range_in_mem_area_as_processed(area, instr, false); if (!done) { g_object_unref(G_OBJECT(instr)); break; } gtk_status_stack_update_activity_value(status, id, diff); assert(!is_range_blank_in_mem_area(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); if (has_new_sym) insert_extra_symbol_into_mem_areas(list, count, symbol); } /* Rupture du flot d'exécution ? */ if (forced_once || 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. * * status = barre de statut à actualiser. * * id = identifiant du groupe de progression à l'affichage. * * * * 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, GProcContext *ctx, const vmpa2t *start, GtkStatusStack *status, activity_id_t id) { 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 */ 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(area, i, 1)) break; instr = NULL; copy_vmpa(&prev, &pos); /* Décodage d'une nouvelle instruction, sur mesure puis minimale */ instr = load_raw_instruction_from_mem_area(area, i, &pos, &diff); /* 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(area, instr, false); if (!done) { g_object_unref(G_OBJECT(instr)); break; } gtk_status_stack_update_activity_value(status, id, diff); assert(!is_range_blank_in_mem_area(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. * * status = barre de statut à actualiser. * * id = identifiant du groupe de progression à l'affichage. * * * * 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, GProcContext *ctx, GtkStatusStack *status, activity_id_t id) { 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(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(area, list, count, ctx, &start, false, status, id); if (is_range_blank_in_mem_area(area, i, 1)) load_data_from_mem_area(area, ctx, &start, status, id); } assert(!is_range_blank_in_mem_area(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(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; 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 : 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 *compute_memory_areas(const GLoadedBinary *binary, phys_t bin_length, size_t *count) { mem_area *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 *area; /* Zone avec valeurs à éditer */ vmpa2t tmp; /* Stockage temporaire */ GPortionLayer *layer; /* Couche première de portions */ GBinPortion **portions; /* Morceaux d'encadrement */ size_t portions_count; /* Taille de cette liste */ const vmpa2t *portion_start; /* Point de départ de portion */ const vmpa2t *portion_next; /* Départ de portion suivante */ 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 *)realloc(result, ++(*count) * sizeof(mem_area)); area = &result[*count - 1]; init_mem_area_from_addr(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 *)realloc(result, ++(*count) * sizeof(mem_area)); area = &result[*count - 1]; init_mem_area_from_addr(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 *)realloc(result, ++(*count) * sizeof(mem_area)); area = &result[*count - 1]; init_mem_area_from_addr(area, &tmp, bin_length - get_phy_addr(&tmp), binary); area->is_exec = false; } /* Seconde étape : on s'assure du découpage autour des portions pour respecter l'alignement */ layer = g_exe_format_get_main_layer(format); portions = g_portion_layer_collect_all_portions(layer, &portions_count); for (i = 1; i < portions_count; i++) { portion_start = get_mrange_addr(g_binary_portion_get_range(portions[i])); /** * Si plusieurs portions débutent au même endroit, il ne sert * à rien de découper plusieurs fois. */ if ((i + 1) < portions_count) { portion_next = get_mrange_addr(g_binary_portion_get_range(portions[i + 1])); if (cmp_vmpa(portion_start, portion_next) == 0) continue; } 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)); 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(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(area, portion_start, length, binary); area->is_exec = status; } j = *count; } } if (portions != NULL) free(portions); g_object_unref(G_OBJECT(layer)); /* 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(result, *count, symbols[i]); } /* Nettoyage final */ if (exe_ranges != NULL) free(exe_ranges); /// FIXME g_object_unref(G_OBJECT(format)); 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 *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *addr) { mem_area *result; /* Elément trouvé à renvoyer */ int find_mem_area(const vmpa2t *_addr, const mem_area *_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), (__compar_fn_t)find_mem_area); 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(mem_area *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 *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(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(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. * * status = barre de statut à actualiser. * * id = identifiant du groupe de progression à l'affichage. * * * * 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, GProcContext *ctx, GtkStatusStack *status, activity_id_t id) { size_t i; /* Boucle de parcours */ for (i = 0; i < count; i++) fill_mem_area(&list[i], list, count, ctx, status, id); } /****************************************************************************** * * * Paramètres : list = série d'aires représentant du 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(const 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; } /****************************************************************************** * * * Paramètres : list = série d'aires représentant du contenu à libérer. * * count = nombre de ces zones présentes. * * * * Description : Libère la mémoire occupée par des zones de données. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void release_mem_areas(mem_area *list, size_t count) { size_t i; /* Boucle de parcours */ for (i = 0; i < count; i++) fini_mem_area(&list[i]); free(list); }