diff options
Diffstat (limited to 'src/analysis/disass/fetch.c')
-rw-r--r-- | src/analysis/disass/fetch.c | 552 |
1 files changed, 64 insertions, 488 deletions
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; } |