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;  } | 
