diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2014-10-11 20:50:03 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2014-10-11 20:50:03 (GMT) |
commit | ffc49de3b424d3daf08b5fdeefd4a3ede6defd02 (patch) | |
tree | cf1a96860e922715bcab55126f8095b7f562d2a1 /src/analysis/disass | |
parent | a5e162d47a574f334b172dfee3128a40e8d52fb3 (diff) |
Improved the disassembling process using memory ranges.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@411 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/disass')
-rw-r--r-- | src/analysis/disass/fetch.c | 547 |
1 files changed, 290 insertions, 257 deletions
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index eee2eb6..f10178a 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -24,18 +24,33 @@ #include "fetch.h" -#include "../../arch/artificial.h" +#include <assert.h> +#include "../../arch/raw.h" +#include "../../arch/instruction.h" -#include "../../arch/raw.h" -#include "../../arch/instruction-int.h" +/* 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); @@ -44,6 +59,241 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *, const vmpa2t *, +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +static mem_area *compute_memory_areas(const 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 */ + 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])); + + } + + 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_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 + + 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)); + + /* 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); + + } + + 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; + +} /****************************************************************************** @@ -159,7 +409,7 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp { instr = g_arch_processor_disassemble(proc, NULL, bin_data, &pos, end); - if (!G_IS_RAW_INSTRUCTION(instr)) printf("GOT %p\n", instr); + //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, @@ -187,12 +437,6 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp } - - - - - - /****************************************************************************** * * * Paramètres : binary = représentation de binaire chargé. * @@ -209,277 +453,66 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id) { - GArchInstruction *result; /* Instruction désassemblées */ - - - GBinFormat *format; /* Format du fichier binaire */ - - - - vmpa2t *last; /* Dernière bordure rencontrée */ - - - - GBinSymbol **symbols; /* Symboles à représenter */ - size_t sym_count; /* Qté de symboles présents */ - - + 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 */ - - - const mrange_t *range; /* Couverture d'un symbole */ - const vmpa2t *border; /* Nouvelle bordure rencontrée */ - off_t length; /* Taille d'une partie traitée */ - - - GArchInstruction *instr; /* Instruction à insérer */ - - - - GArchInstruction *joint; /* Jointure entre deux lots */ - - - - off_t max_length; /* Taille des données à lire */ - - - - - result = NULL; - - - - format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); - - last = make_vmpa(0, VMPA_NO_VIRTUAL); - - symbols = g_binary_format_get_symbols(format, &sym_count); - - - //sym_count = 0; - - - for (i = 0; i < sym_count; i++) - { - - - - - range = g_binary_symbol_get_range(symbols[i]); - - border = get_mrange_addr(range); - length = get_mrange_length(range); - - - - - switch (g_binary_symbol_get_target_type(symbols[i])) - { - case STP_DATA: - instr = g_binary_symbol_get_instruction(symbols[i]); - g_object_ref(G_OBJECT(instr)); - break; - - case STP_ROUTINE: - instr = load_code_binary(binary, border, - get_phy_addr(border) + length, - statusbar, id); - break; - - default: - printf("BADDD !\n"); - exit(0); - break; - - } - - /* Traiter la diff */ - - if (0 && cmp_vmpa_by_phy(last, border) < 0) - { - joint = load_raw_binary(binary, last, - get_phy_addr(last) + compute_vmpa_diff(border, last), - statusbar, id); - - ainstr_list_merge(&result, &joint); - - } - - /* Ajout des instructions déjà établies */ - - ainstr_list_merge(&result, &instr); - - /* Marquage de la nouvelle dernière bordure */ - - copy_vmpa(last, border); - - advance_vmpa(last, length); - - } - - /* Raccord final ? */ - - g_loaded_binary_get_data(binary, &max_length); - - if (get_phy_addr(last) < max_length) - { - joint = load_raw_binary(binary, last, max_length, statusbar, id); - ainstr_list_merge(&result, &joint); - } - - - - - printf("COUNT :: %zu\n", sym_count); - - //exit(0); - - - return result; - - - -} - - - - - - - - - - - - - - - -#ifdef DEBUG -# include "../../arch/artificial.h" -#endif - - - -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ - -GArchInstruction *disassemble_binary_parts(const GLoadedBinary *binary, GBinPart **parts, size_t count, 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 */ - size_t i; /* Boucle de parcours #1 */ - off_t sum; /* Somme de toutes les tailles */ - off_t done; /* Quantité déjà traitée */ -#ifdef DEBUG - unsigned int valid; /* Instructions traduites */ - unsigned int db; /* Instructions non décodées */ -#endif - off_t pos; /* Début d'une zone binaire */ - off_t len; /* Taille de cette même zone */ - vmpa_t base; /* Adresse de la zone binaire */ - off_t start; /* Conservation du pt de départ*/ - GProcContext *context; /* Contexte pour le décodage */ - vmpa_t addr; /* Adresse d'une instruction */ - GArchInstruction *instr; /* Instruction décodée */ + 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 */ 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); - - /* Préparation du suivi de la progression */ + format = g_loaded_binary_get_format(binary); + g_loaded_binary_get_data(binary, &length); - sum = 0; + areas = compute_memory_areas(format, length, &count); for (i = 0; i < count; i++) { - g_binary_part_get_values(parts[i], NULL, &len, NULL); - if (len > bin_length) continue; - sum += len; - } - - done = 0; + iter = &areas[i]; - for (i = 0; i < count; i++) - { - g_binary_part_get_values(parts[i], &pos, &len, &base); + start = get_mrange_addr(&iter->range); + end = get_phy_addr(start) + get_mrange_length(&iter->range); - if (len > bin_length) continue; + assert(get_mrange_length(&iter->range) > 0); - context = g_arch_processor_get_context(proc); + 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; - /* Décodage des instructions */ + case STP_ROUTINE: + instr = load_code_binary(binary, start, end, statusbar, id); + break; -#ifdef DEBUG - valid = 0; - db = 0; -#endif + default: + assert(false); + break; - start = pos; - len += start; + } - while (pos < len) + else { - addr = base + (pos - start); - - instr = g_arch_processor_decode_instruction(proc, context, bin_data, - &pos, len, addr, format); - g_arch_instruction_add_to_list(&result, instr); - -#ifdef DEBUG - if (G_IS_DB_INSTRUCTION(instr) && !g_db_instruction_is_skipped(G_DB_INSTRUCTION(instr))) - db++; + if (iter->exec) + instr = load_code_binary(binary, start, end, statusbar, id); else - valid++; -#endif - - if (pos < len) - gtk_extended_status_bar_update_activity(statusbar, id, (done + pos - start) * 1.0 / sum); + instr = load_raw_binary(binary, start, end, statusbar, id); } - if (context != NULL) - g_object_unref(context); - -#ifdef DEBUG - g_binary_part_set_checkup(parts[i], valid, db); -#endif - - done += (len - start); - gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum); + g_arch_instruction_merge_lists(&result, &instr); } + free(areas); + return result; } - - - - - - - - - - - |