diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2016-12-29 10:30:28 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2016-12-29 10:30:28 (GMT) | 
| commit | 9f9041e11efa71cb043425cd5e89daea0247e76c (patch) | |
| tree | 84d8704c291a5efef46af1e14a2aa3544dc29455 /src | |
| parent | 403a0519ec85a156a7f306b045d9cab619302473 (diff) | |
Cut binary data into several areas using all the available CPUs and less memory.
Diffstat (limited to 'src')
27 files changed, 907 insertions, 1105 deletions
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 71e2784..2bc7a53 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -35,6 +35,7 @@  #include "../../analysis/contents/restricted.h"  #include "../../arch/raw.h"  #include "../../common/bits.h" +#include "../../common/sort.h"  #include "../../format/format.h"  #include "../../glibext/delayed-int.h"  #include "../../gui/panels/log.h" @@ -115,11 +116,32 @@ typedef struct _GAreaCollector      mem_area *areas;                        /* Zone de productions         */ -    size_t begin;                           /* Début du parcours à mener   */ -    size_t end;                             /* Fin de ce même parcours     */ +    union +    { +        struct +        { +            size_t acount;                  /* Nombre de zones créées      */ + +            GLoadedBinary *binary;          /* Binaire à associer aux zones*/ -    GArchInstruction **collected;           /* Instructions collectées     */ -    size_t count;                           /* Quantité de ces instructions*/ +            phys_t first;                   /* Début de traitement         */ +            phys_t last;                    /* Fin de traitement           */ + +            bool closing;                   /* Tâche clôturant le parcours */ + +        }; + +        struct +        { +            size_t begin;                   /* Début du parcours à mener   */ +            size_t end;                     /* Fin de ce même parcours     */ + +            GArchInstruction **collected;   /* Instructions collectées     */ +            size_t ccount;                  /* Quantité de ces instructions*/ + +        }; + +    };  } GAreaCollector; @@ -149,6 +171,12 @@ static void g_area_collector_finalize(GAreaCollector *);  /* Assure un traitement particulier concernant les zones. */  static void g_area_collector_process(GAreaCollector *, GtkStatusStack *); +/* Crée une tâche de calcul des zones binaires à désassembler. */ +static GAreaCollector *g_area_collector_new_intro(activity_id_t, GLoadedBinary *, phys_t, phys_t, bool); + +/* Construit une liste bornée de zones contigües. */ +static void g_area_collector_do_compute(GAreaCollector *, GtkStatusStack *); +  /* Crée une tâche de récupération d'instructions différée. */  static GAreaCollector *g_area_collector_new_outro(activity_id_t, mem_area *, size_t, size_t); @@ -779,230 +807,6 @@ static GArchInstruction **get_instructions_from_mem_area(const mem_area *area, G  /******************************************************************************  *                                                                             * -*  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); - -    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.        * @@ -1212,6 +1016,9 @@ static void g_area_collector_init(GAreaCollector *collector)  static void g_area_collector_dispose(GAreaCollector *collector)  { +    if (collector->run == (run_task_fc)g_area_collector_do_compute) +        g_object_unref(G_OBJECT(collector->binary)); +      G_OBJECT_CLASS(g_area_collector_parent_class)->dispose(G_OBJECT(collector));  } @@ -1258,6 +1065,366 @@ static void g_area_collector_process(GAreaCollector *collector, GtkStatusStack *  /******************************************************************************  *                                                                             * +*  Paramètres  : id      = identifiant pour signaler la progression courante. * +*                binary  = binaire chargé à conserver dans les zones définies.* +*                first   = localisation du début de la portion à traiter.     * +*                last    = localisation de la fin de la portion à traiter.    * +*                closing = indique si la tâche doit terminer l'analyse.       * +*                                                                             * +*  Description : Crée une tâche de calcul des zones binaires à désassembler.  * +*                                                                             * +*  Retour      : Tâche créée.                                                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GAreaCollector *g_area_collector_new_intro(activity_id_t id, GLoadedBinary *binary, phys_t first, phys_t last, bool closing) +{ +    GAreaCollector *result;            /* Tâche à retourner           */ + +    result = g_object_new(G_TYPE_AREA_COLLECTOR, NULL); + +    result->id = id; +    result->run = (run_task_fc)g_area_collector_do_compute; + +    result->areas = NULL; + +    result->acount = 0; + +    result->binary = binary; +    g_object_ref(G_OBJECT(binary)); + +    result->first = first; +    result->last = last; + +    result->closing = closing; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : fetching = récupération à mener.                             * +*                status   = barre de statut à tenir informée.                 * +*                                                                             * +*  Description : Construit une liste bornée de zones contigües.               * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStack *status) +{ +    mem_area **list;                        /* Liste de zones à constituer */ +    size_t *count;                          /* Nombre d'éléments intégrés  */ +    vmpa2t first;                           /* Point de départ             */ +    vmpa2t last;                            /* Point d'arrivée             */ +    GExeFormat *format;                     /* Format du binaire           */ +    vmpa2t prev;                            /* Dernière bordure rencontrée */ +    bool state;                             /* Bilan d'une conversion      */ +    GBinSymbol **symbols;                   /* Symboles à représenter      */ +    size_t sym_count;                       /* Qté de symboles présents    */ +    bool has_sym_index;                     /* Détermine une validité      */ +    size_t sym_index;                       /* Prochain symbole non traité */ +    GBinPortion *portions;                  /* Couche première de portions */ + +    void populate_with_symbols(const vmpa2t *limit) +    { +        GBinSymbol *symbol;                 /* Symbole en cours d'analyse  */ +        SymbolType type;                    /* Nature d'un symbole         */ +        const mrange_t *range;              /* Couverture d'un symbole     */ +        vmpa2t end;                         /* Adresse de fin du symbole   */ + +        for (; sym_index < sym_count; sym_index++) +        { +            symbol = symbols[sym_index]; + +            type = g_binary_symbol_get_target_type(symbol); + +            /** +             * 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(symbol); + +            if (get_mrange_length(range) == 0) +                continue; + +            if (cmp_vmpa(get_mrange_addr(range), limit) >= 0) +                break; + +            compute_mrange_end_addr(range, &end); + +            /** +             * Si un symbole est à cheval entre deux zones, tant pis pour lui ! +             */ + +            if (cmp_vmpa(&end, limit) > 0) +                break; + +            insert_extra_symbol_into_mem_areas(*list, *count, symbol); + +        } + +    } + +    void fill_gap(vmpa2t *old, vmpa2t *new, bool exec) +    { +        phys_t diff;                        /* Espace entre bordures       */ +        mem_area *area;                     /* Zone avec valeurs à éditer  */ + +        diff = compute_vmpa_diff(old, new); + +        /** +         * S'il existe un écart entre la dernière bordure ajoutée et +         * l'extréminité de la portion courante, on le comble ! +         */ + +        if (diff > 0) +        { +            /* Zone tampon à constituer */ + +            *list = (mem_area *)realloc(*list, ++(*count) * sizeof(mem_area)); + +            area = &(*list)[*count - 1]; + +            init_mem_area_from_addr(area, old, diff, collector->binary); +            area->is_exec = exec; + +            /* Insertion des symboles existants */ + +            if (!has_sym_index) +            { +                int cmp_vmpa_with_symbol(const vmpa2t *a, const GBinSymbol **s) +                { +                    return g_binary_symbol_cmp_with_vmpa(*s, a); +                } + +                bsearch_index(old, symbols, sym_count, sizeof(GBinSymbol *), +                              (__compar_fn_t)cmp_vmpa_with_symbol, &sym_index); + +                has_sym_index = true; + +            } + +            populate_with_symbols(new); + +            /* Avancée du curseur */ + +            copy_vmpa(old, new); + +            gtk_status_stack_update_activity_value(status, collector->id, diff); + +        } + +    } + +    bool build_area_from_portion(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, void *unused) +    { +        const mrange_t *range;              /* Espace de portion à traiter */ +        vmpa2t border;                      /* Nouvelle bordure rencontrée */ +        bool on_track;                      /* Le tronçon courant est bon ?*/ +        PortionAccessRights rights;         /* Droits d'accès à analyser   */ + +        range = g_binary_portion_get_range(portion); + +        if (visit == BPV_ENTER) +        { +            copy_vmpa(&border, get_mrange_addr(range)); + +            on_track = cmp_vmpa(&first, &border) <= 0 && cmp_vmpa(&border, &last) < 0; + +            if (on_track) +            { +                rights = (parent != NULL ? g_binary_portion_get_rights(parent) : PAC_NONE); +                fill_gap(&prev, &border, rights & PAC_EXEC); +            } +            else +                copy_vmpa(&prev, &border); + +        } + +        else if (visit == BPV_SHOW) +        { +            copy_vmpa(&border, get_mrange_addr(range)); + +            on_track = cmp_vmpa(&first, &border) <= 0 && cmp_vmpa(&border, &last) < 0; + +            if (on_track) +            { +                rights = (parent != NULL ? g_binary_portion_get_rights(parent) : PAC_NONE); +                fill_gap(&prev, &border, rights & PAC_EXEC); + +                compute_mrange_end_addr(range, &border); + +                rights = g_binary_portion_get_rights(portion); +                fill_gap(&prev, &border, rights & PAC_EXEC); + +            } +            else +                compute_mrange_end_addr(range, &prev); + +        } + +        else if (visit == BPV_EXIT) +        { +            compute_mrange_end_addr(range, &border); + +            if (collector->closing) +                on_track = cmp_vmpa(&first, &border) <= 0 && cmp_vmpa(&border, &last) <= 0; +            else +                on_track = cmp_vmpa(&first, &border) <= 0 && cmp_vmpa(&border, &last) < 0; + +            if (on_track) +            { +                rights = (parent != NULL ? g_binary_portion_get_rights(parent) : PAC_NONE); +                fill_gap(&prev, &border, rights & PAC_EXEC); +            } +            else +                copy_vmpa(&prev, &border); + +        } + +#ifndef NDEBUG +        else +            assert(false); +#endif + +        return (cmp_vmpa(&prev, &last) < 0); + +    } + +    list = &collector->areas; +    count = &collector->acount; + +    init_vmpa(&first, collector->first, VMPA_NO_VIRTUAL); +    init_vmpa(&last, collector->last, VMPA_NO_VIRTUAL); + +    format = g_loaded_binary_get_format(collector->binary); + +#ifndef NDEBUG +    state = g_exe_format_translate_offset_into_vmpa(format, 0, &prev); +    assert(state); +#else +    g_exe_format_translate_offset_into_vmpa(format, 0, &prev); +#endif + +    symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); + +    has_sym_index = false; + +    portions = g_exe_format_get_portions(format); + +    g_binary_portion_visit(portions, (visit_portion_fc)build_area_from_portion, NULL); + +    g_object_unref(G_OBJECT(portions)); + +    g_object_unref(G_OBJECT(format)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : gid    = groupe de travail impliqué.                         * +*                status = barre de statut à tenir informée.                   * +*                binary = binaire analysé contenant quantités d'infos.        * +*                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 *collect_memory_areas(wgroup_id_t gid, GtkStatusStack *status, GLoadedBinary *binary, phys_t length, size_t *count) +{ +    mem_area *result;                       /* Liste finale à retourner    */ +    guint runs_count;                       /* Qté d'exécutions parallèles */ +    GAreaCollector **collectors;            /* Collecteurs à suivre        */ +    phys_t run_size;                        /* Volume réparti par exécution*/ +    GWorkQueue *queue;                      /* Gestionnaire de différés    */ +    activity_id_t id;                       /* Identifiant de progression  */ +    guint i;                                /* Boucle de parcours          */ +    phys_t first;                           /* Début de zone de traitement */ +    bool closing;                           /* Détection de fin en amont   */ +    phys_t last;                            /* Fin de zone de traitement   */ + +    runs_count = g_get_num_processors(); + +    collectors = (GAreaCollector **)calloc(runs_count, sizeof(GAreaCollector *)); + +    run_size = length / runs_count; + +    queue = get_work_queue(); + +    id = gtk_status_stack_add_activity(status, _("Computing memory areas to disassemble"), length); + +    for (i = 0; i < runs_count; i++) +    { +        first = i * run_size; + +        closing = ((i + 1) == runs_count); + +        if (closing) +            last = length; +        else +            last = first + run_size; + +        collectors[i] = g_area_collector_new_intro(id, binary, first, last, closing); + +        g_object_ref(G_OBJECT(collectors[i])); +        g_work_queue_schedule_work(queue, G_DELAYED_WORK(collectors[i]), gid); + +    } + +    g_work_queue_wait_for_completion(queue, gid); + +    /* Récupération des aires */ + +    result = NULL; +    *count = 0; + +    for (i = 0; i < runs_count; i++) +    { +        result = (mem_area *)realloc(result, (*count + collectors[i]->acount) * sizeof(mem_area)); + +        memcpy(&result[*count], collectors[i]->areas, collectors[i]->acount * sizeof(mem_area)); +        *count += collectors[i]->acount; + +        g_object_unref(G_OBJECT(collectors[i])); + +    } + +    /* Fin */ + +    free(collectors); + +    gtk_status_stack_remove_activity(status, id); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : id    = identifiant pour signaler la progression courante.   *  *                list  = liste des zones en place à parcourir.                *  *                begin = indice de la première zone à traiter.                * @@ -1286,7 +1453,7 @@ static GAreaCollector *g_area_collector_new_outro(activity_id_t id, mem_area *li      result->end = end;      result->collected = NULL; -    result->count = 0; +    result->ccount = 0;      return result; @@ -1313,7 +1480,7 @@ static void g_area_collector_do_collect(GAreaCollector *collector, GtkStatusStac      for (i = collector->begin; i < collector->end; i++)      {          collector->collected = get_instructions_from_mem_area(&collector->areas[i], -                                                              collector->collected, &collector->count); +                                                              collector->collected, &collector->ccount);          fini_mem_area(&collector->areas[i]); @@ -1326,8 +1493,8 @@ static void g_area_collector_do_collect(GAreaCollector *collector, GtkStatusStac  /******************************************************************************  *                                                                             * -*  Paramètres  : gid      = groupe de travail impliqué.                       * -*                status   = barre de statut à tenir informée.                 * +*  Paramètres  : gid    = groupe de travail impliqué.                         * +*                status = barre de statut à tenir informée.                   *  *                list   = liste des zones de données à relire puis libérer.   *  *                acount = taille de cette liste de zones.                     *  *                icount = nombre d'instructions récupérées. [OUT]             * @@ -1388,10 +1555,10 @@ GArchInstruction **collect_disassembled_instructions(wgroup_id_t gid, GtkStatusS      for (i = 0; i < runs_count; i++)      {          result = (GArchInstruction **)realloc(result, -                                              (*icount + collectors[i]->count) * sizeof(GArchInstruction *)); +                                              (*icount + collectors[i]->ccount) * sizeof(GArchInstruction *)); -        memcpy(&result[*icount], collectors[i]->collected, collectors[i]->count * sizeof(GArchInstruction *)); -        *icount += collectors[i]->count; +        memcpy(&result[*icount], collectors[i]->collected, collectors[i]->ccount * sizeof(GArchInstruction *)); +        *icount += collectors[i]->ccount;          g_object_unref(G_OBJECT(collectors[i])); diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h index 725b9a8..d5f910b 100644 --- a/src/analysis/disass/area.h +++ b/src/analysis/disass/area.h @@ -43,9 +43,6 @@ typedef struct _mem_area mem_area;  void load_code_from_mem_area(mem_area *, mem_area *, size_t, GProcContext *, const vmpa2t *, bool, GtkStatusStack *, activity_id_t);  /* Détermine une liste de zones contigües à traiter. */ -mem_area *compute_memory_areas(const GLoadedBinary *, phys_t, size_t *); - -/* Détermine une liste de zones contigües à traiter. */  mem_area *find_memory_area_by_addr(mem_area *, size_t, const vmpa2t *);  /* Insère un symbole dans un découpage en aires. */ @@ -58,6 +55,9 @@ void ensure_all_mem_areas_are_filled(mem_area *, size_t, GProcContext *, GtkStat  /* ----------------------- MANIPULATIONS PARALLELES DES ZONES ----------------------- */ +/* Détermine une liste de zones contigües à traiter. */ +mem_area *collect_memory_areas(wgroup_id_t, GtkStatusStack *, GLoadedBinary *, phys_t, size_t *); +  /* Rassemble les instructions conservées dans des zones données. */  GArchInstruction **collect_disassembled_instructions(wgroup_id_t, GtkStatusStack *, mem_area *, size_t, size_t *); diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 172ee1c..5326c36 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -312,8 +312,7 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co  static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback, GArchProcessor *proc, GExeFormat *format)  { -    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */ -    size_t exe_count;                       /* Nombre de ces zones         */ +    GBinPortion *portions;                  /* Couche première de portions */      GBinRoutine **routines;                 /* Liste des routines trouvées */      size_t routines_count;                  /* Nombre de ces routines      */      guint runs_count;                       /* Qté d'exécutions parallèles */ @@ -325,7 +324,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const      size_t end;                             /* Fin d'un bloc de traitement */      GRoutinesStudy *study;                  /* Tâche d'étude à programmer  */ -    exe_ranges = g_exe_format_get_x_ranges(format, &exe_count); +    portions = g_exe_format_get_portions(format);      routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count); @@ -346,7 +345,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const          else              end = begin + run_size; -        study = g_routines_study_new(proc, exe_ranges, exe_count, routines, routines_count, +        study = g_routines_study_new(proc, portions, routines, routines_count,                                       begin, end, id, fallback);          g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid); @@ -357,8 +356,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const      gtk_status_stack_remove_activity(status, id); -    if (exe_ranges != NULL) -        free(exe_ranges); +    g_object_unref(G_OBJECT(portions));  } diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index 784e103..ee0916b 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -392,7 +392,7 @@ static bool check_if_extra_wait_is_needed(GWorkQueue *queue, wgroup_id_t id, GPr  *                                                                             *  ******************************************************************************/ -GArchInstruction **disassemble_binary_content(const GLoadedBinary *binary, GProcContext *ctx, wgroup_id_t gid, GtkStatusStack *status, size_t *count) +GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContext *ctx, wgroup_id_t gid, GtkStatusStack *status, size_t *count)  {      GArchInstruction **result;               /* Instruction désassemblées   */      GDelayedFetching template;              /* Patron des tâches à venir   */ @@ -415,7 +415,7 @@ GArchInstruction **disassemble_binary_content(const GLoadedBinary *binary, GProc      length = g_binary_content_compute_size(content);      g_object_unref(G_OBJECT(content)); -    template.areas = compute_memory_areas(binary, length, &template.count); +    template.areas = collect_memory_areas(gid, status, binary, length, &template.count);      template.status = status; diff --git a/src/analysis/disass/fetch.h b/src/analysis/disass/fetch.h index bf2b52f..b36a999 100644 --- a/src/analysis/disass/fetch.h +++ b/src/analysis/disass/fetch.h @@ -32,7 +32,7 @@  /* Procède au désassemblage basique d'un contenu binaire. */ -GArchInstruction **disassemble_binary_content(const GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *, size_t *); +GArchInstruction **disassemble_binary_content(GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *, size_t *); diff --git a/src/analysis/disass/limit.c b/src/analysis/disass/limit.c index 28a8264..18d089a 100644 --- a/src/analysis/disass/limit.c +++ b/src/analysis/disass/limit.c @@ -25,48 +25,12 @@ -/* Recherche la zone correspond à une adresse donnée. */ -static const mrange_t *find_x_range_for_addr(const mrange_t *, size_t, const vmpa2t *); - - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranges = liste de zones offrant une exécution et disponibles.* -*                count  = taille de cette liste.                              * -*                                                                             * -*  Description : Recherche la zone correspond à une adresse donnée.           * -*                                                                             * -*  Retour      : Zone trouvée ou NULL si aucune ne correspond.                * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t count, const vmpa2t *addr) -{ -    const mrange_t *result;                 /* Zone à retourner            */ -    size_t i;                               /* Boucle de parcours          */ - -    result = NULL; - -    for (i = 0; i < count && result == NULL; i++) -        if (mrange_contains_addr(&ranges[i], addr)) -            result = &ranges[i]; - -    return result; - -} - -  /******************************************************************************  *                                                                             * -*  Paramètres  : proc     = ensemble d'instructions désassemblées.            * -*                routines = prototypes existants à insérer.                   * -*                count    = quantité de ces prototypes.                       * -*                begin    = point de départ du parcours de liste.             * -*                end      = point d'arrivée exclu du parcours.                * -*                id       = identifiant du message affiché à l'utilisateur.   * +*  Paramètres  : routine  = routine dont les frontières sont à fixer.         * +*                prev     = routine précédente dans les traitements.          * +*                proc     = ensemble d'instructions désassemblées.            * +*                portions = ensemble de couches binaires bornées.             *  *                                                                             *  *  Description : S'assure qu'une routine est bien bornée.                     *  *                                                                             * @@ -76,12 +40,13 @@ static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t coun  *                                                                             *  ******************************************************************************/ -void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count) +void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, GArchProcessor *proc, GBinPortion *portions)  {      const mrange_t *range;                  /* Emplacement courant         */      vmpa2t addr;                            /* Adresse à conserver         */      GArchInstruction *start;                /* Première instruction        */      phys_t diff;                            /* Taille définie par déduction*/ +    GBinPortion *portion;                   /* Conteneur avec limites      */      mrange_t new;                           /* Nouvel emplacement taillé   */      range = g_binary_routine_get_range(routine); @@ -114,12 +79,16 @@ void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, GArchProcess      /* Sinon on va jusqu'à la fin de la zone ! */      else      { -        range = find_x_range_for_addr(exe_ranges, exe_count, &addr); -        if (range == NULL) goto crl_skip; +        portion = g_binary_portion_find_at_addr(portions, &addr, (GdkRectangle []) { }); +        if (portion == NULL) goto crl_skip; + +        range = g_binary_portion_get_range(portion);          diff = compute_vmpa_diff(&addr, get_mrange_addr(range));          diff = get_mrange_length(range) - diff; +        g_object_unref(G_OBJECT(portion)); +      }      init_mrange(&new, &addr, diff); diff --git a/src/analysis/disass/limit.h b/src/analysis/disass/limit.h index 7aba8a6..ed53325 100644 --- a/src/analysis/disass/limit.h +++ b/src/analysis/disass/limit.h @@ -32,7 +32,7 @@  /* S'assure qu'une routine est bien bornée. */ -void compute_routine_limit(GBinRoutine *, GBinRoutine *, GArchProcessor *, mrange_t *, size_t); +void compute_routine_limit(GBinRoutine *, GBinRoutine *, GArchProcessor *, GBinPortion *); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index 0d85870..fe4d705 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -59,7 +59,7 @@  void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GArchProcessor *proc, GtkStatusStack *status)  { -    GPortionLayer *layer;                   /* Couche première de portions */ +    GBinPortion *root;                      /* Couche première de portions */      GBinPortion **portions;                 /* Morceaux d'encadrement      */      size_t portions_count;                  /* Taille de cette liste       */      size_t portion_index;                   /* Prochaine portion à traiter */ @@ -99,12 +99,29 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA +    bool collect_all_portions(GBinPortion *portion, GBinPortion *parent, BinaryPortionVisit visit, void *unused) +    { +        if (visit == BPV_ENTER || visit == BPV_SHOW) +        { +            portions = (GBinPortion **)realloc(portions, ++portions_count * sizeof(GBinPortion *)); +            portions[portions_count - 1] = portion; +        } + +        return true; + +    } -    layer = g_exe_format_get_main_layer(format); +    portions = NULL; +    portions_count = 0; -    portions = g_portion_layer_collect_all_portions(layer, &portions_count);      portion_index = 0; +    root = g_exe_format_get_portions(format); + +    g_binary_portion_visit(root, (visit_portion_fc)collect_all_portions, NULL); + +    g_object_unref(G_OBJECT(root)); +      symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);      sym_index = 0; @@ -339,9 +356,6 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA      if (portions != NULL)          free(portions); -    g_object_unref(G_OBJECT(layer)); - -      fprintf(stderr, "MISSING :: %u symbols\n", _missing); diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c index a9414fc..6fd9279 100644 --- a/src/analysis/disass/routines.c +++ b/src/analysis/disass/routines.c @@ -40,8 +40,7 @@ struct _GRoutinesStudy      GArchProcessor *proc;                   /* Processeurs avec ses instr. */ -    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */ -    size_t exe_count;                       /* Nombre de ces zones         */ +    GBinPortion *portions;                  /* Couches de binaire bornées  */      GBinRoutine **routines;                 /* Liste de routines à traiter */      size_t count;                           /* Taille de cette liste       */ @@ -147,6 +146,8 @@ static void g_routines_study_init(GRoutinesStudy *study)  static void g_routines_study_dispose(GRoutinesStudy *study)  { +    g_object_unref(G_OBJECT(study->portions)); +      G_OBJECT_CLASS(g_routines_study_parent_class)->dispose(G_OBJECT(study));  } @@ -174,6 +175,7 @@ static void g_routines_study_finalize(GRoutinesStudy *study)  /******************************************************************************  *                                                                             *  *  Paramètres  : proc     = ensemble d'instructions désassemblées.            * +*                portions = ensemble de couches binaires bornées.             *  *                routines = prototypes existants à insérer.                   *  *                count    = quantité de ces prototypes.                       *  *                begin    = point de départ du parcours de liste.             * @@ -189,7 +191,7 @@ static void g_routines_study_finalize(GRoutinesStudy *study)  *                                                                             *  ******************************************************************************/ -GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count, GBinRoutine **routines, size_t count, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback) +GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, GBinPortion *portions, GBinRoutine **routines, size_t count, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback)  {      GRoutinesStudy *result;                /* Tâche à retourner           */ @@ -197,8 +199,8 @@ GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, mrange_t *exe_ranges,      result->proc = proc; -    result->exe_ranges = exe_ranges; -    result->exe_count = exe_count; +    result->portions = portions; +    g_object_ref(G_OBJECT(portions));      result->routines = routines;      result->count = count; @@ -267,7 +269,7 @@ void g_routines_study_compute_limits(GRoutinesStudy *study, size_t index)      else          next = NULL; -    compute_routine_limit(routine, next, study->proc, study->exe_ranges, study->exe_count); +    compute_routine_limit(routine, next, study->proc, study->portions);  } diff --git a/src/analysis/disass/routines.h b/src/analysis/disass/routines.h index 72df309..b89f69a 100644 --- a/src/analysis/disass/routines.h +++ b/src/analysis/disass/routines.h @@ -52,7 +52,7 @@ typedef void (* rtn_fallback_cb) (GRoutinesStudy *, size_t);  /* Crée une tâche d'étude de routines différée. */ -GRoutinesStudy *g_routines_study_new(GArchProcessor *, mrange_t *, size_t, GBinRoutine **, size_t, size_t, size_t, activity_id_t, rtn_fallback_cb); +GRoutinesStudy *g_routines_study_new(GArchProcessor *, GBinPortion *, GBinRoutine **, size_t, size_t, size_t, activity_id_t, rtn_fallback_cb);  /* Détermine si besoin est les bornes des routines. */  void g_routines_study_compute_limits(GRoutinesStudy *, size_t); diff --git a/src/format/dex/class.c b/src/format/dex/class.c index 26907ed..c1ff62a 100644 --- a/src/format/dex/class.c +++ b/src/format/dex/class.c @@ -401,9 +401,8 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t  /******************************************************************************  *                                                                             * -*  Paramètres  : class = informations chargées à consulter.                   * +*  Paramètres  : class  = informations chargées à consulter.                  *  *                format = format permettant d'obtenir une adresse complète.   * -*                layer = couche de portions à raffiner.                       *  *                                                                             *  *  Description : Intègre la méthode en tant que portion de code.              *  *                                                                             * @@ -413,15 +412,15 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t  *                                                                             *  ******************************************************************************/ -void g_dex_class_include_as_portion(const GDexClass *class, const GDexFormat *format, GPortionLayer *layer) +void g_dex_class_include_as_portion(const GDexClass *class, GExeFormat *format)  {      size_t i;                               /* Boucle de parcours          */      for (i = 0; i < class->dmethods_count; i++) -        g_dex_method_include_as_portion(class->direct_methods[i], format, layer); +        g_dex_method_include_as_portion(class->direct_methods[i], format);      for (i = 0; i < class->vmethods_count; i++) -        g_dex_method_include_as_portion(class->virtual_methods[i], format, layer); +        g_dex_method_include_as_portion(class->virtual_methods[i], format);  } diff --git a/src/format/dex/class.h b/src/format/dex/class.h index 46529c3..ec2fa24 100644 --- a/src/format/dex/class.h +++ b/src/format/dex/class.h @@ -69,7 +69,7 @@ size_t g_dex_class_count_methods(const GDexClass *, bool);  GDexMethod *g_dex_class_get_method(const GDexClass *, bool, size_t);  /* Intègre la méthode en tant que portion de code. */ -void g_dex_class_include_as_portion(const GDexClass *, const GDexFormat *, GPortionLayer *); +void g_dex_class_include_as_portion(const GDexClass *, GExeFormat *);  /* Retrouve si possible la méthode associée à une adresse. */  GDexMethod *g_dex_class_find_method_by_address(const GDexClass *, vmpa_t); diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index c550375..df920b2 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -58,7 +58,7 @@ static void g_dex_format_finalize(GDexFormat *);  static const char *g_dex_format_get_target_machine(const GDexFormat *);  /* Etend la définition des portions au sein d'un binaire. */ -static void g_dex_format_refine_portions(const GDexFormat *, GPortionLayer *); +static void g_dex_format_refine_portions(GDexFormat *);  /* Fournit l'emplacement d'une section donnée. */  static bool g_dex_format_get_section_range_by_name(const GDexFormat *, const char *, mrange_t *); @@ -247,12 +247,14 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatus  {      GDexFormat *result;                     /* Structure à retourner       */      GBinFormat *base;                       /* Version basique du format   */ +    GExeFormat *exe_format;                 /* Autre version du format     */      vmpa2t pos;                             /* Position de tête de lecture */      wgroup_id_t gid;                        /* Identifiant pour les tâches */      result = g_object_new(G_TYPE_DEX_FORMAT, NULL);      base = G_BIN_FORMAT(result); +    exe_format = G_EXE_FORMAT(result);      g_binary_format_set_content(base, content); @@ -277,7 +279,7 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatus      if (!load_all_dex_classes(result, gid, status))          goto gdfn_error; -    if (!g_binary_format_complete_loading(base, status)) +    if (!g_executable_format_complete_loading(exe_format, status))          goto gdfn_error;      return base; @@ -322,20 +324,18 @@ static const char *g_dex_format_get_target_machine(const GDexFormat *format)  *                                                                             *  ******************************************************************************/ -static void g_dex_format_refine_portions(const GDexFormat *format, GPortionLayer *main) +static void g_dex_format_refine_portions(GDexFormat *format)  { -    GPortionLayer *layer;                   /* Couche à mettre en place    */ +    GExeFormat *exe_format;                 /* Autre version du format     */      size_t max;                             /* Nombre d'itérations prévues */      size_t i;                               /* Boucle de parcours          */ -    layer = g_portion_layer_new(NO_LENGTH_YET, _("Code")); - -    g_portion_layer_attach_sub(main, layer); +    exe_format = G_EXE_FORMAT(format);      max = g_dex_format_count_classes(format);      for (i = 0; i < max; i++) -        g_dex_class_include_as_portion(format->classes[i], format, layer); +        g_dex_class_include_as_portion(format->classes[i], exe_format);  } diff --git a/src/format/dex/method.c b/src/format/dex/method.c index 1223eb9..8659a73 100644 --- a/src/format/dex/method.c +++ b/src/format/dex/method.c @@ -338,7 +338,6 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method)  *                                                                             *  *  Paramètres  : method = représentation interne du format DEX à consulter.   *  *                format = format permettant d'obtenir une adresse complète.   * -*                layer  = couche de portions à raffiner.                      *  *                                                                             *  *  Description : Intègre la méthode en tant que portion de code.              *  *                                                                             * @@ -348,11 +347,10 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method)  *                                                                             *  ******************************************************************************/ -void g_dex_method_include_as_portion(const GDexMethod *method, const GDexFormat *format, GPortionLayer *layer) +void g_dex_method_include_as_portion(const GDexMethod *method, GExeFormat *format)  {      vmpa2t addr;                            /* Emplacement dans le binaire */      GBinPortion *new;                       /* Nouvelle portion définie    */ -    char *desc;                             /* Description d'une portion   */      /* Si la taille est nulle, on ne fait rien */      if (method->info.access_flags & ACC_NATIVE) @@ -361,22 +359,16 @@ void g_dex_method_include_as_portion(const GDexMethod *method, const GDexFormat      if (!method->has_body)          return; -    if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), method->offset, &addr)) +    if (!g_exe_format_translate_offset_into_vmpa(format, method->offset, &addr))          return; -    new = g_binary_portion_new(BPC_CODE); +    new = g_binary_portion_new(BPC_CODE, &addr, method->body.insns_size * sizeof(uint16_t)); -    asprintf(&desc, _("Dalvik code")); - -    g_binary_portion_set_desc(new, desc); - -    free(desc); - -    g_binary_portion_set_values(new, &addr, method->body.insns_size * sizeof(uint16_t)); +    g_binary_portion_set_desc(new, _("Dalvik code"));      g_binary_portion_set_rights(new, PAC_READ | PAC_EXEC); -    g_portion_layer_include(layer, new); +    g_exe_format_include_portion(format, new);  } diff --git a/src/format/dex/method.h b/src/format/dex/method.h index 41ddb4c..8836abb 100644 --- a/src/format/dex/method.h +++ b/src/format/dex/method.h @@ -82,7 +82,7 @@ const code_item *g_dex_method_get_dex_body(const GDexMethod *);  GBinRoutine *g_dex_method_get_routine(const GDexMethod *);  /* Intègre la méthode en tant que portion de code. */ -void g_dex_method_include_as_portion(const GDexMethod *, const GDexFormat *, GPortionLayer *); +void g_dex_method_include_as_portion(const GDexMethod *, GExeFormat *);  /* Indique la position de la méthode au sein du binaire. */  bool g_dex_method_get_offset(const GDexMethod *method, phys_t *); diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index 2dd41e1..a51fe33 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -69,7 +69,7 @@ static SourceEndian g_elf_format_get_endianness(const GElfFormat *);  static const char *g_elf_format_get_target_machine(const GElfFormat *);  /* Etend la définition des portions au sein d'un binaire. */ -static void g_elf_format_refine_portions(const GElfFormat *, GPortionLayer *); +static void g_elf_format_refine_portions(GElfFormat *);  /* Fournit l'emplacement correspondant à une position physique. */  static bool g_elf_format_translate_offset_into_vmpa(const GElfFormat *, phys_t, vmpa2t *); @@ -244,10 +244,12 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatus  {      GElfFormat *result;                     /* Structure à retourner       */      GBinFormat *base;                       /* Version basique du format   */ +    GExeFormat *exe_format;                 /* Autre version du format     */      result = g_object_new(G_TYPE_ELF_FORMAT, NULL);      base = G_BIN_FORMAT(result); +    exe_format = G_EXE_FORMAT(result);      g_binary_format_set_content(base, content); @@ -305,7 +307,7 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatus      } -    if (!g_binary_format_complete_loading(base, status)) +    if (!g_executable_format_complete_loading(exe_format, status))          goto gefn_error;      return base; @@ -383,7 +385,6 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format)  /******************************************************************************  *                                                                             *  *  Paramètres  : format = informations chargées à consulter.                  * -*                main   = couche de portions principale à raffiner.           *  *                                                                             *  *  Description : Etend la définition des portions au sein d'un binaire.       *  *                                                                             * @@ -393,14 +394,13 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format)  *                                                                             *  ******************************************************************************/ -static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer *main) +static void g_elf_format_refine_portions(GElfFormat *format)  { -    GPortionLayer *layer;                   /* Couche à mettre en place    */ +    GExeFormat *exe_format;                 /* Autre version du format     */      uint16_t max;                           /* Décompte d'éléments traités */ -    elf_phdr *sorted_phdrs;                 /* Liste de segments triée     */      uint16_t i;                             /* Boucle de parcours          */      off_t offset;                           /* Début de part de programme  */ -    elf_phdr *phdr;                         /* En-tête de programme ELF    */ +    elf_phdr phdr;                          /* En-tête de programme ELF    */      uint32_t p_flags;                       /* Droits associés à une partie*/      const char *background;                 /* Fond signigicatif           */      GBinPortion *new;                       /* Nouvelle portion définie    */ @@ -409,11 +409,12 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer      PortionAccessRights rights;             /* Droits d'une portion        */      elf_shdr strings;                       /* Section des descriptions    */      bool has_strings;                       /* Section trouvée ?           */ -    elf_shdr *sorted_shdrs;                 /* Liste de sections triée     */ -    elf_shdr *section;                      /* En-tête de section ELF      */ +    elf_shdr shdr;                          /* En-tête de section ELF      */      uint64_t sh_flags;                      /* Droits associés à une partie*/      const char *name;                       /* Nom trouvé ou NULL          */ +    exe_format = G_EXE_FORMAT(format); +      /**       * La copie des différents en-têtes cherche à reproduire l'inclusion native       * du format : @@ -429,83 +430,35 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer       * Côté segments basiques.       */ -    layer = g_portion_layer_new(NO_LENGTH_YET, _("Segment")); - -    g_portion_layer_attach_sub(main, layer); - -    /* Constitution d'une liste de travail */ -      max = ELF_HDR(format, format->header, e_phnum); -    sorted_phdrs = (elf_phdr *)calloc(max, sizeof(elf_phdr)); -      for (i = 0; i < max; i++)      {          offset = ELF_HDR(format, format->header, e_phoff)              + ELF_HDR(format, format->header, e_phentsize) * i; -        if (!read_elf_program_header(format, offset, &sorted_phdrs[i])) -        { -            if (format->is_32b) -                sorted_phdrs[i].phdr32.p_type = PT_NULL; -            else -                sorted_phdrs[i].phdr64.p_type = PT_NULL; -        } - -    } - -    /* Tri de cette liste */ - -    int sort_phdr(elf_phdr *a, elf_phdr *b) -    { -        uint64_t filesz_a;                  /* Taille de l'en-tête 'a'     */ -        uint64_t filesz_b;                  /* Taille de l'en-tête 'b'     */ -        int status;                         /* Bilan d'une comparaison     */ - -        filesz_a = ELF_PHDR(format, *a, p_filesz); -        filesz_b = ELF_PHDR(format, *b, p_filesz); - -        if (filesz_a < filesz_b) -            status = 1; - -        else if (filesz_a > filesz_b) -            status = -1; - -        else -            status = 0; - -        return status; - -    } - -    qsort(sorted_phdrs, max, sizeof(elf_phdr), (__compar_fn_t)sort_phdr); - -    /* Inclusion de ces en-têtes */ - -    for (i = 0; i < max; i++) -    { -        phdr = &sorted_phdrs[i]; +        if (!read_elf_program_header(format, offset, &phdr)) +            continue; -        if (ELF_PHDR(format, *phdr, p_type) == PT_NULL) +        if (ELF_PHDR(format, phdr, p_type) == PT_NULL)              continue; -        p_flags = ELF_PHDR(format, *phdr, p_flags); +        p_flags = ELF_PHDR(format, phdr, p_flags);          if (p_flags & PF_X) background = BPC_CODE;          else if (p_flags & PF_W) background = BPC_DATA;          else background = BPC_DATA_RO; -        new = g_binary_portion_new(background); +        init_vmpa(&addr, ELF_PHDR(format, phdr, p_offset), ELF_PHDR(format, phdr, p_vaddr)); + +        new = g_binary_portion_new(background, &addr, ELF_PHDR(format, phdr, p_filesz));          snprintf(desc, MAX_PORTION_DESC, "%s \"%s\"",                   _("Segment"), -                 get_elf_program_type_desc(ELF_PHDR(format, *phdr, p_type))); +                 get_elf_program_type_desc(ELF_PHDR(format, phdr, p_type)));          g_binary_portion_set_desc(new, desc); -        init_vmpa(&addr, ELF_PHDR(format, *phdr, p_offset), ELF_PHDR(format, *phdr, p_vaddr)); -        g_binary_portion_set_values(new, &addr, ELF_PHDR(format, *phdr, p_filesz)); -          rights = PAC_NONE;          if (p_flags & PF_R) rights |= PAC_READ;          if (p_flags & PF_W) rights |= PAC_WRITE; @@ -513,12 +466,10 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer          g_binary_portion_set_rights(new, rights); -        g_portion_layer_include(layer, new); +        g_exe_format_include_portion(exe_format, new);      } -    free(sorted_phdrs); -      /**       * Inclusion des sections, si possible...       */ @@ -527,64 +478,17 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer                                              ELF_HDR(format, format->header, e_shstrndx),                                              &strings); -    layer = g_portion_layer_new(NO_LENGTH_YET, _("Section")); - -    g_portion_layer_attach_sub(main, layer); - -    /* Constitution d'une liste de travail */ -      max = ELF_HDR(format, format->header, e_shnum); -    sorted_shdrs = (elf_shdr *)calloc(max, sizeof(elf_shdr)); - -    for (i = 0; i < max; i++) -    { -        if (!find_elf_section_by_index(format, i, &sorted_shdrs[i])) -        { -            if (format->is_32b) -                sorted_shdrs[i].shdr32.sh_offset = 0; -            else -                sorted_shdrs[i].shdr64.sh_offset = 0; -        } - -    } - -    /* Tri de cette liste */ - -    int sort_shdr(elf_shdr *a, elf_shdr *b) -    { -        uint64_t size_a;                    /* Taille de l'en-tête 'a'     */ -        uint64_t size_b;                    /* Taille de l'en-tête 'b'     */ -        int status;                         /* Bilan d'une comparaison     */ - -        size_a = ELF_SHDR(format, *a, sh_size); -        size_b = ELF_SHDR(format, *b, sh_size); - -        if (size_a < size_b) -            status = 1; - -        else if (size_a > size_b) -            status = -1; - -        else -            status = 0; - -        return status; - -    } - -    qsort(sorted_shdrs, max, sizeof(elf_shdr), (__compar_fn_t)sort_shdr); - -    /* Inclusion de ces en-têtes */ -      for (i = 0; i < max; i++)      { -        section = &sorted_shdrs[i]; +        if (!find_elf_section_by_index(format, i, &shdr)) +            continue; -        if (ELF_SHDR(format, *section, sh_offset) == 0) +        if (ELF_SHDR(format, shdr, sh_offset) == 0)              continue; -        sh_flags = ELF_SHDR(format, *section, sh_flags); +        sh_flags = ELF_SHDR(format, shdr, sh_flags);          if ((sh_flags & SHF_ALLOC) == 0)              continue; @@ -593,11 +497,13 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer          else if (sh_flags & SHF_WRITE) background = BPC_DATA;          else background = BPC_DATA_RO; -        new = g_binary_portion_new(background); +        init_vmpa(&addr, ELF_SHDR(format, shdr, sh_offset), ELF_SHDR(format, shdr, sh_addr)); + +        new = g_binary_portion_new(background, &addr, ELF_SHDR(format, shdr, sh_size));          if (has_strings)              name = extract_name_from_elf_string_section(format, &strings, -                                                        ELF_SHDR(format, *section, sh_name)); +                                                        ELF_SHDR(format, shdr, sh_name));          else name = NULL;          if (name != NULL) @@ -607,9 +513,6 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer          g_binary_portion_set_desc(new, desc); -        init_vmpa(&addr, ELF_SHDR(format, *section, sh_offset), ELF_SHDR(format, *section, sh_addr)); -        g_binary_portion_set_values(new, &addr, ELF_SHDR(format, *section, sh_size)); -          rights = PAC_NONE;          if (sh_flags & SHF_ALLOC) rights |= PAC_READ;          if (sh_flags & SHF_WRITE) rights |= PAC_WRITE; @@ -617,12 +520,10 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer          g_binary_portion_set_rights(new, rights); -        g_portion_layer_include(layer, new); +        g_exe_format_include_portion(exe_format, new);      } -    free(sorted_shdrs); -  } diff --git a/src/format/executable-int.h b/src/format/executable-int.h index a4d4b35..88527a5 100644 --- a/src/format/executable-int.h +++ b/src/format/executable-int.h @@ -36,7 +36,7 @@  typedef const char * (* get_target_machine_fc) (const GExeFormat *);  /* Etend la définition des portions au sein d'un binaire. */ -typedef void (* refine_portions_fc) (const GExeFormat *, GPortionLayer *); +typedef void (* refine_portions_fc) (GExeFormat *);  /* Fournit l'emplacement correspondant à une position physique. */  typedef bool (* translate_phys_fc) (const GExeFormat *, phys_t, vmpa2t *); @@ -57,7 +57,8 @@ struct _GExeFormat      GDbgFormat **debugs;                    /* Informations de débogage    */      size_t debugs_count;                    /* Nombre de ces informations  */ -    GPortionLayer *layers;                  /* Couches de morceaux binaires*/ +    GBinPortion *portions;                  /* Couches de morceaux binaires*/ +    GMutex mutex;                           /* Accès à l'arborescence      */  }; @@ -77,6 +78,9 @@ struct _GExeFormatClass  }; +/* Effectue les ultimes opérations de chargement d'un binaire. */ +bool g_executable_format_complete_loading(GExeFormat *, GtkStatusStack *); +  /* Fournit l'emplacement correspondant à une position physique. */  bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *, phys_t, vmpa2t *); diff --git a/src/format/executable.c b/src/format/executable.c index c1ff940..3e902cf 100644 --- a/src/format/executable.c +++ b/src/format/executable.c @@ -24,6 +24,7 @@  #include "executable.h" +#include <assert.h>  #include <malloc.h>  #include <stdlib.h> @@ -39,6 +40,12 @@ static void g_executable_format_class_init(GExeFormatClass *);  /* Initialise une instance de format d'exécutable générique. */  static void g_executable_format_init(GExeFormat *); +/* Supprime toutes les références externes. */ +static void g_executable_format_dispose(GExeFormat *); + +/* Procède à la libération totale de la mémoire. */ +static void g_executable_format_finalize(GExeFormat *); +  /* Indique le type défini pour un format d'exécutable générique. */ @@ -59,6 +66,12 @@ G_DEFINE_TYPE(GExeFormat, g_executable_format, G_TYPE_BIN_FORMAT);  static void g_executable_format_class_init(GExeFormatClass *klass)  { +    GObjectClass *object;                   /* Autre version de la classe  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_executable_format_dispose; +    object->finalize = (GObjectFinalizeFunc)g_executable_format_finalize;  } @@ -77,11 +90,57 @@ static void g_executable_format_class_init(GExeFormatClass *klass)  static void g_executable_format_init(GExeFormat *format)  { +    g_mutex_init(&format->mutex);  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_executable_format_dispose(GExeFormat *format) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < format->debugs_count; i++) +        g_object_unref(G_OBJECT(format->debugs[i])); + +    if (format->portions != NULL) +        g_object_unref(G_OBJECT(format->portions)); + +    g_mutex_clear(&format->mutex); +    G_OBJECT_CLASS(g_executable_format_parent_class)->dispose(G_OBJECT(format)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_executable_format_finalize(GExeFormat *format) +{ +    G_OBJECT_CLASS(g_executable_format_parent_class)->finalize(G_OBJECT(format)); + +}  /****************************************************************************** @@ -184,109 +243,95 @@ const char *g_exe_format_get_target_machine(const GExeFormat *format)  /******************************************************************************  *                                                                             * -*  Paramètres  : format = description de l'exécutable à consulter.            * +*  Paramètres  : format = instance à traiter.                                 * +*                status = barre de statut à tenir informée.                   *  *                                                                             * -*  Description : Fournit la première couche des portions composent le binaire.* +*  Description : Effectue les ultimes opérations de chargement d'un binaire.  *  *                                                                             * -*  Retour      : Couche brute des différentes portions.                       * +*  Retour      : Bilan de l'opération.                                        *  *                                                                             * -*  Remarques   : Le compteur de références de l'instance renvoyée doit être   * -*                décrémenté après usage.                                      * +*  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -GPortionLayer *g_exe_format_get_main_layer(GExeFormat *format) +bool g_executable_format_complete_loading(GExeFormat *format, GtkStatusStack *status)  { -    GBinPortion *portion;                   /* Portion brute globale       */ +    bool result;                            /* Bilan à faire remonter      */ +    GBinFormat *base;                       /* Version basique du format   */      vmpa2t addr;                            /* Emplacement vide de sens    */      phys_t length;                          /* Taille de portion globale   */ -    GPortionLayer *layer;                   /* Couche à mettre en place    */ - -    if (format->layers == NULL) -    { -        /* Création d'une portion globale */ - -        portion = g_binary_portion_new(BPC_RAW); -        init_vmpa(&addr, 0, VMPA_NO_VIRTUAL); -        length = g_binary_content_compute_size(G_BIN_FORMAT(format)->content); +    base = G_BIN_FORMAT(format); -        g_binary_portion_set_values(portion, &addr, length); +    result = g_binary_format_complete_loading(base, status); -        /* Création d'une couche de base brute */ - -        layer = g_portion_layer_new(length, NULL); - -        g_portion_layer_include(layer, portion); +    if (result) +    { +        result = g_exe_format_translate_offset_into_vmpa(format, 0, &addr); +        assert(result); -        /* Remplissage */ +        length = g_binary_content_compute_size(base->content); -        G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format, layer); +        format->portions = g_binary_portion_new(BPC_RAW, &addr, length); -        format->layers = layer; +        G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format);      } -    g_object_ref(G_OBJECT(format->layers)); - -    return format->layers; +    return result;  }  /******************************************************************************  *                                                                             * -*  Paramètres  : format = informations chargées à consulter.                  * -*                count  = quantité de zones listées. [OUT]                    * +*  Paramètres  : format  = description de l'exécutable à modifier.            * +*                portion = portion à inclure dans les définitions du format.  *  *                                                                             * -*  Description : Fournit les espaces mémoires des portions exécutables.       * +*  Description : Procède à l'enregistrement d'une portion dans un format.     *  *                                                                             * -*  Retour      : Liste de zones binaires exécutables à libérer après usage.   * +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count) +void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion)  { -    mrange_t *result;                       /* Liste à retourner           */ - -    typedef struct _x_ranges -    { -        mrange_t *list; -        size_t length; +    g_mutex_lock(&format->mutex); -    } x_ranges; +    g_binary_portion_include(format->portions, portion); -    x_ranges tmp;                           /* Sauvegarde de la liste      */ -    GPortionLayer *layer;                   /* Couche première de portions */ +    g_mutex_unlock(&format->mutex); -    bool visit_for_x(GBinPortion *portion, x_ranges *ranges) -    { -        const mrange_t *range; - -        if (g_binary_portion_get_rights(portion) & PAC_EXEC) -        { -            range = g_binary_portion_get_range(portion); +} -            ranges->list = (mrange_t *)realloc(ranges->list, ++ranges->length * sizeof(mrange_t)); -            copy_mrange(&ranges->list[ranges->length - 1], range); -        } +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = description de l'exécutable à consulter.            * +*                                                                             * +*  Description : Fournit la première couche des portions composent le binaire.* +*                                                                             * +*  Retour      : Arborescence des différentes portions binaires.              * +*                                                                             * +*  Remarques   : Le compteur de références de l'instance renvoyée doit être   * +*                décrémenté après usage.                                      * +*                                                                             * +******************************************************************************/ -        return true; +GBinPortion *g_exe_format_get_portions(GExeFormat *format) +{ +    GBinPortion *result;                    /* Instance à retourner        */ -    } +    g_mutex_lock(&format->mutex); -    tmp.list = NULL; -    tmp.length = 0; +    result = format->portions; -    layer = g_exe_format_get_main_layer(format); -    g_portion_layer_visit(format->layers, (visit_portion_fc)visit_for_x, &tmp); -    g_object_unref(G_OBJECT(layer)); +    if (result != NULL) +        g_object_ref(G_OBJECT(result)); -    result = tmp.list; -    *count = tmp.length; +    g_mutex_unlock(&format->mutex);      return result; diff --git a/src/format/executable.h b/src/format/executable.h index ad89948..6384851 100644 --- a/src/format/executable.h +++ b/src/format/executable.h @@ -52,7 +52,6 @@ typedef struct _GExeFormatClass GExeFormatClass;  /* Indique le type défini pour un format d'exécutable générique. */  GType g_executable_format_get_type(void); -  /* Rajoute des informations de débogage à un exécutable. */  void g_exe_format_add_debug_info(GExeFormat *, GDbgFormat *); @@ -65,8 +64,11 @@ GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *, size_t);  /* Indique le type d'architecture visée par le format. */  const char *g_exe_format_get_target_machine(const GExeFormat *); +/* Procède à l'enregistrement d'une portion dans un format. */ +void g_exe_format_include_portion(GExeFormat *, GBinPortion *); +  /* Fournit la première couche des portions composent le binaire. */ -GPortionLayer *g_exe_format_get_main_layer(GExeFormat *); +GBinPortion *g_exe_format_get_portions(GExeFormat *);  /* Fournit les espaces mémoires des portions exécutables. */  mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count); diff --git a/src/format/format.c b/src/format/format.c index bf4a0e1..516f882 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -137,7 +137,6 @@ bool g_binary_format_complete_loading(GBinFormat *format, GtkStatusStack *status  *                                                                             *  *  Paramètres  : format  = description de l'exécutable à consulter.           *  *                content = contenu binaire à parcourir.                       * -*                length  = taille du contenu fourni.                          *  *                                                                             *  *  Description : Définit le contenu binaire à analyser.                       *  *                                                                             * diff --git a/src/format/symbol.c b/src/format/symbol.c index 48f3dbb..97ff114 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -226,6 +226,37 @@ int g_binary_symbol_cmp(const GBinSymbol **a, const GBinSymbol **b)  /******************************************************************************  *                                                                             * +*  Paramètres  : symbol = symbole à analyser.                                 * +*                addr   = localisation à venir comparer à celle du symbole.   * +*                                                                             * +*  Description : Compare un symbole et une localisation.                      * +*                                                                             * +*  Retour      : Bilan de la comparaison : -1, 0 ou 1 (-1 par défaut).        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int g_binary_symbol_cmp_with_vmpa(const GBinSymbol *symbol, const vmpa2t *addr) +{ +    int result;                             /* Bilan à retourner           */ +    const mrange_t *range;                  /* Emplacement du symbole      */ + +    range = g_binary_symbol_get_range(symbol); + +    if (range == NULL) +        result = 1; + +    else +        result = cmp_mrange_with_vmpa(range, addr); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : symbol = symbole à venir consulter.                          *  *                                                                             *  *  Description : Fournit le type du symbole.                                  * diff --git a/src/format/symbol.h b/src/format/symbol.h index 8432d8d..78741cb 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -80,6 +80,9 @@ GBinSymbol *g_binary_symbol_new(SymbolType);  /* Compare deux symboles d'exécutable selon leurs propriétés. */  int g_binary_symbol_cmp(const GBinSymbol **, const GBinSymbol **); +/* Compare un symbole et une localisation. */ +int g_binary_symbol_cmp_with_vmpa(const GBinSymbol *, const vmpa2t *); +  /* Fournit le type du symbole. */  SymbolType g_binary_symbol_get_target_type(const GBinSymbol *); diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c index 8fc7805..4137763 100644 --- a/src/glibext/gbinportion.c +++ b/src/glibext/gbinportion.c @@ -34,6 +34,7 @@  #include "../common/extstr.h" +#include "../common/sort.h" @@ -45,8 +46,6 @@ struct _GBinPortion  {      GObject parent;                         /* A laisser en premier        */ -    const unsigned int *level;              /* Profondeur de la portion    */ -      char *code;                             /* Code de la couleur de fond  */      char *desc;                             /* Désignation humaine         */ @@ -55,6 +54,9 @@ struct _GBinPortion      PortionAccessRights rights;             /* Droits d'accès              */ +    GBinPortion **subs;                     /* Portions incluses           */ +    size_t count;                           /* Quantité d'inclusions       */ +  };  /* Portion de données binaires quelconques (classe) */ @@ -77,58 +79,16 @@ static void g_binary_portion_dispose(GBinPortion *);  /* Procède à la libération totale de la mémoire. */  static void g_binary_portion_finalize(GBinPortion *); -/* Définit le niveau de profondeur pour une branche de portions. */ -static void g_binary_portion_set_level(GBinPortion *, const unsigned int *); -  /* Détermine l'aire d'une sous-portion. */  static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const GdkRectangle *, GdkRectangle *); -/* Détermine si une portion contient une adresse donnée. */ -static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *); - - - -/* -------------------------- COUCHES DE PORTIONS BINAIRES -------------------------- */ - - -/* Couche de portions binaires quelconques (instance) */ -struct _GPortionLayer -{ -    GObject parent;                         /* A laisser en premier        */ - -    phys_t length;                          /* Taille de portion globale   */ -    const char *name;                       /* Désignation de la couche    */ - -    unsigned int level;                     /* Profondeur de la portion    */ - -    GPortionLayer *sub_layer;               /* Eventuelle couche inférieure*/ - -    GBinPortion **portions;                 /* Portions incluses           */ -    size_t count;                           /* Quantité d'inclusions       */ - -}; - -/* Couche de portions binaires quelconques (classe) */ -struct _GPortionLayerClass -{ -    GObjectClass parent;                    /* A laisser en premier        */ - -}; - - -/* Initialise la classe des couches de portions binaires. */ -static void g_portion_layer_class_init(GPortionLayerClass *); -/* Initialise une instance de couche de portions binaires. */ -static void g_portion_layer_init(GPortionLayer *); -/* Supprime toutes les références externes. */ -static void g_portion_layer_dispose(GPortionLayer *); - -/* Procède à la libération totale de la mémoire. */ -static void g_portion_layer_finalize(GPortionLayer *); +/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ +/* Détermine si une portion contient une adresse donnée. */ +static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *); @@ -180,7 +140,6 @@ static void g_binary_portion_class_init(GBinPortionClass *klass)  static void g_binary_portion_init(GBinPortion *portion)  { -    portion->level = NULL;  } @@ -231,6 +190,8 @@ static void g_binary_portion_finalize(GBinPortion *portion)  /******************************************************************************  *                                                                             *  *  Paramètres  : code = désignation humaine de la couleur de fond.            * +*                addr = emplacement de la section à conserver.                * +*                size = taille de la section à conserver.                     *  *                                                                             *  *  Description : Crée une description de partie de code vierge.               *  *                                                                             * @@ -240,7 +201,7 @@ static void g_binary_portion_finalize(GBinPortion *portion)  *                                                                             *  ******************************************************************************/ -GBinPortion *g_binary_portion_new(const char *code) +GBinPortion *g_binary_portion_new(const char *code, const vmpa2t *addr, phys_t size)  {      GBinPortion *result;                    /* Structure à retourner       */ @@ -248,27 +209,9 @@ GBinPortion *g_binary_portion_new(const char *code)      result->code = strdup(code); -    return result; - -} +    init_mrange(&result->range, addr, size); - -/****************************************************************************** -*                                                                             * -*  Paramètres  : portion = description de partie à mettre à jour.             * -*                level   = niveau de profondeur à associer.                   * -*                                                                             * -*  Description : Définit le niveau de profondeur pour une branche de portions.* -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_binary_portion_set_level(GBinPortion *portion, const unsigned int *level) -{ -    portion->level = level; +    return result;  } @@ -291,31 +234,12 @@ int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b)      int result;                             /* Bilan à retourner           */      const vmpa2t *addr_a;                   /* Adresse de la portion 'a'   */      const vmpa2t *addr_b;                   /* Adresse de la portion 'b'   */ -    const unsigned int *level_a;            /* Niveau de la portion 'a'    */ -    const unsigned int *level_b;            /* Niveau de la portion 'b'    */      addr_a = get_mrange_addr(&(*a)->range);      addr_b = get_mrange_addr(&(*b)->range);      result = cmp_vmpa(addr_a, addr_b); -    if (result == 0) -    { -        level_a = (*a)->level; -        level_b = (*b)->level; - -        if (level_a != NULL && level_b != NULL) -        { -            if (*level_a < *level_b) -                result = -1; - -            else if (*level_a > *level_b) -                result = 1; - -        } - -    } -      return result;  } @@ -365,27 +289,6 @@ const char *g_binary_portion_get_desc(const GBinPortion *portion)  /******************************************************************************  *                                                                             *  *  Paramètres  : portion = description de partie à mettre à jour.             * -*                addr    = emplacement de la section à conserver.             * -*                size    = taille de la section à conserver.                  * -*                                                                             * -*  Description : Définit les valeurs utiles d'une partie de code binaire.     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_binary_portion_set_values(GBinPortion *portion, const vmpa2t *addr, phys_t size) -{ -    init_mrange(&portion->range, addr, size); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : portion = description de partie à mettre à jour.             *  *                                                                             *  *  Description : Fournit l'emplacement d'une partie de code binaire.          *  *                                                                             * @@ -443,76 +346,6 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion)  /******************************************************************************  *                                                                             * -*  Paramètres  : portion  = portion mère à consulter.                         * -*                full     = taille totale de la couche parente.               * -*                area     = étendue de représentation de la portion mère.     * -*                sub_area = étendue de représentation de la portion fille.    * -*                                                                             * -*  Description : Détermine l'aire d'une sous-portion.                         * -*                                                                             * -*  Retour      : true si la sous-surface a été calculée correctement.         * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_binary_portion_compute_sub_area(const GBinPortion *portion, phys_t full, const GdkRectangle *area, GdkRectangle *sub_area) -{ -    phys_t length;                          /* Taille de la portion        */ -    phys_t start;                           /* Position de départ          */ - -    length = get_mrange_length(&portion->range); - -    /* On saute les portions comme le segment GNU_STACK... */ -    if (length == 0) return false; - -    start = get_phy_addr(get_mrange_addr(&portion->range)); - -    sub_area->y = area->y; -    sub_area->height = area->height; - -    sub_area->x = area->x + (start * area->width) / full; -    sub_area->width = (length * area->width) / full; - -    return true; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : portion = portion mère à consulter.                          * -*                addr    = adresse du point de recherche.                     * -*                                                                             * -*  Description : Détermine si une portion contient une adresse donnée.        * -*                                                                             * -*  Retour      : true ou false selon le résultat.                             * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_portion_layer_contains_addr(const GBinPortion *portion, const vmpa2t *addr) -{ -    bool result;                            /* Bilan à retourner           */ - -    result = false; - -    /* Portion non allouée en mémoire -> adresse nulle ; on écarte */ -    if (get_virt_addr(get_mrange_addr(&portion->range)) == 0) -        goto not_found; - -    result = mrange_contains_addr(&portion->range, addr); - - not_found: - -    return result; - -} - - -/****************************************************************************** -*                                                                             *  *  Paramètres  : portion = description de partie à consulter.                 *  *                buffer  = espace où placer ledit contenu.                    *  *                msize   = taille idéale des positions et adresses;           * @@ -686,52 +519,50 @@ void g_binary_portion_query_tooltip(GBinPortion *portion, GtkTooltip *tooltip)  /******************************************************************************  *                                                                             * -*  Paramètres  : portion = description de partie à consulter.                 * -*                cr      = contexte graphique pour le dessin.                 * -*                area    = étendue mise à disposition.                        * +*  Paramètres  : portion  = portion mère à consulter.                         * +*                full     = taille totale de la couche parente.               * +*                area     = étendue de représentation de la portion mère.     * +*                sub_area = étendue de représentation de la portion fille.    *  *                                                                             * -*  Description : Représente la portion sur une bande dédiée.                  * +*  Description : Détermine l'aire d'une sous-portion.                         *  *                                                                             * -*  Retour      : -                                                            * +*  Retour      : true si la sous-surface a été calculée correctement.         *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) +static bool g_binary_portion_compute_sub_area(const GBinPortion *portion, phys_t full, const GdkRectangle *area, GdkRectangle *sub_area)  { -    //cairo_set_line_width(cr, 1.0); +    phys_t length;                          /* Taille de la portion        */ +    phys_t start;                           /* Position de départ          */ -    cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); +    length = get_mrange_length(&portion->range); -    gtk_style_context_save(context); +    /* On saute les portions comme le segment GNU_STACK... */ +    if (length == 0) return false; -    gtk_style_context_add_class(context, portion->code); +    start = get_phy_addr(get_mrange_addr(&portion->range)); -    gtk_render_background(context, cr, area->x, area->y, area->width, area->height); +    sub_area->y = area->y; +    sub_area->height = area->height; -    gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); +    sub_area->x = area->x + (start * area->width) / full; +    sub_area->width = (length * area->width) / full; -    gtk_style_context_restore(context); +    return true;  } - -/* ---------------------------------------------------------------------------------- */ -/*                            COUCHES DE PORTIONS BINAIRES                            */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini par la GLib pour les couches de portions binaires. */ -G_DEFINE_TYPE(GPortionLayer, g_portion_layer, G_TYPE_OBJECT); - -  /******************************************************************************  *                                                                             * -*  Paramètres  : klass = classe à initialiser.                                * +*  Paramètres  : portion = description de partie à consulter.                 * +*                context = contexte graphique associé à la procédure.         * +*                cr      = contexte graphique pour le dessin.                 * +*                area    = étendue mise à disposition.                        *  *                                                                             * -*  Description : Initialise la classe des couches de portions binaires.       * +*  Description : Représente la portion sur une bande dédiée.                  *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -739,70 +570,51 @@ G_DEFINE_TYPE(GPortionLayer, g_portion_layer, G_TYPE_OBJECT);  *                                                                             *  ******************************************************************************/ -static void g_portion_layer_class_init(GPortionLayerClass *klass) +void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area)  { -    GObjectClass *object;                   /* Autre version de la classe  */ - -    object = G_OBJECT_CLASS(klass); +    phys_t full;                            /* Espace total représenté     */ +    size_t i;                               /* Boucle de parcours          */ +    GBinPortion *sub;                       /* Portion incluse à montrer   */ +    GdkRectangle sub_area;                  /* Etendue d'une sous-portion  */ -    object->dispose = (GObjectFinalizeFunc/* ! */)g_portion_layer_dispose; -    object->finalize = (GObjectFinalizeFunc)g_portion_layer_finalize; +    /* Dessin de la portion courante */ +    cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); -} +    gtk_style_context_save(context); +    gtk_style_context_add_class(context, portion->code); -/****************************************************************************** -*                                                                             * -*  Paramètres  : layer = instance à initialiser.                              * -*                                                                             * -*  Description : Initialise une instance de couche de portions binaires.      * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ +    gtk_render_background(context, cr, area->x, area->y, area->width, area->height); -static void g_portion_layer_init(GPortionLayer *layer) -{ -    layer->level = 0; +    gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); -} +    gtk_style_context_restore(context); +    /* Dessin des portions contenues */ -/****************************************************************************** -*                                                                             * -*  Paramètres  : layer = instance d'objet GLib à traiter.                     * -*                                                                             * -*  Description : Supprime toutes les références externes.                     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ +    full = get_mrange_length(&portion->range); -static void g_portion_layer_dispose(GPortionLayer *layer) -{ -    size_t i;                               /* Boucle de parcours          */ +    for (i = 0; i < portion->count; i++) +    { +        sub = portion->subs[i]; -    if (layer->sub_layer != NULL) -        g_object_unref(G_OBJECT(layer->sub_layer)); +        if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) +            continue; -    for (i = 0; i < layer->count; i++) -        g_object_unref(G_OBJECT(layer->portions[i])); +        g_binary_portion_draw(sub, context, cr, &sub_area); -    G_OBJECT_CLASS(g_portion_layer_parent_class)->dispose(G_OBJECT(layer)); +    }  }  /******************************************************************************  *                                                                             * -*  Paramètres  : layer = instance d'objet GLib à traiter.                     * +*  Paramètres  : portion = portion principale à compléter.                    * +*                sub     = portion à inclure dans la définition courante.     *  *                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * +*  Description : Procède à l'inclusion d'une portion dans une autre.          *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -810,204 +622,161 @@ static void g_portion_layer_dispose(GPortionLayer *layer)  *                                                                             *  ******************************************************************************/ -static void g_portion_layer_finalize(GPortionLayer *layer) +void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub)  { -    if (layer->portions != NULL) -        free(layer->portions); - -    G_OBJECT_CLASS(g_portion_layer_parent_class)->finalize(G_OBJECT(layer)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : length =  -*                name   = désignation pouvant servir de suffixe aux portions. * -*                                                                             * -*  Description : Crée une nouvelle couche de portions binaires.               * -*                                                                             * -*  Retour      : Instance mise en place.                                      * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GPortionLayer *g_portion_layer_new(phys_t length, const char *name) -{ -    GPortionLayer *result;                  /* Structure à retourner       */ - -    result = g_object_new(G_TYPE_BIN_PORTION, NULL); - -    result->length = length; -    result->name = name; - -    return result; - -} +    bool found;                             /* Zone d'accueil trouvée ?    */ +    size_t best;                            /* Meilleur point d'insertion  */ +    const mrange_t *prange;                 /* Emplacement de portion #1   */ +    const mrange_t *srange;                 /* Emplacement de portion #2   */ +    GBinPortion tmp;                        /* Sauvegarde temporaire       */ +    found = bsearch_index(sub, portion->subs, portion->count, sizeof(GBinPortion *), +                          (__compar_fn_t)g_binary_portion_compare, &best); -/****************************************************************************** -*                                                                             * -*  Paramètres  : layer = couche rassemblant des portions à modifier.          * -*  Paramètres  : sub   = couche inférieure à rattacher à la couche courante.  * -*                                                                             * -*  Description : Attache une couche à une autre en tant que couche inférieure.* -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ +    if (!found) +        portion->subs = qinsert(portion->subs, &portion->count, sizeof(GBinPortion *), +                                (__compar_fn_t)g_binary_portion_compare, &sub); -void g_portion_layer_attach_sub(GPortionLayer *layer, GPortionLayer *sub) -{ -    void set_layers_length(GPortionLayer *parent, GPortionLayer *child) +    else      { -        if (child->length == NO_LENGTH_YET) +        /** +         * On prend ici en compte le genre de situations suivantes : +         * +         *  [21] .bss                NOBITS          00088240 07823c 0018c8 00  WA  0   0  8 +         *  [22] __libc_freeres_ptrs NOBITS          00089b08 07823c 000018 00  WA  0   0  4 +         *  [23] .comment            PROGBITS        00000000 07823c 000022 01  MS  0   0  1 +         * +         * Pendant le désassemblage, la procédure n'aime pas trop les intersections +         * de zones mémoire. +         */ + +        prange = g_binary_portion_get_range(portion->subs[best]); +        srange = g_binary_portion_get_range(sub); + +        if (mrange_contains_mrange(prange, srange)) +            g_binary_portion_include(portion->subs[best], sub); + +        else          { -            assert(parent->length != NO_LENGTH_YET); +            assert(mrange_contains_mrange(srange, prange)); -            child->length = parent->length; +            memcpy(&tmp, portion->subs[best], sizeof(GBinPortion)); +            memcpy(portion->subs[best], sub, sizeof(GBinPortion)); +            memcpy(sub, &tmp, sizeof(GBinPortion)); -            if (child->sub_layer != NULL) -                set_layers_length(child, child->sub_layer); +            g_binary_portion_include(portion->subs[best], sub);          }      } -    void set_layers_depth(GPortionLayer *parent, GPortionLayer *child) -    { -        child->level = parent->level + 1; - -        if (child->sub_layer != NULL) -            set_layers_length(child, child->sub_layer); - -    } - -    set_layers_length(layer, sub); - -    set_layers_depth(layer, sub); - -    layer->sub_layer = sub; -  }  /******************************************************************************  *                                                                             * -*  Paramètres  : layer   = couche rassemblant les portions d'un même niveau.  * -*                portion = portion à inclure dans la définition courante.     * +*  Paramètres  : portion = première couche amorçant la visite.                * +*                visitor = fonction à appeler à chaque étape de la descente.  * +*                data    = adresse pointant vers des données de l'utilisateur.*  *                                                                             * -*  Description : Procède à l'inclusion d'une portion dans une couche.         * +*  Description : Parcourt un ensemble de portions binaires.                   *  *                                                                             * -*  Retour      : -                                                            * +*  Retour      : true si la visite a été jusqu'à son terme, false sinon.      *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -void g_portion_layer_include(GPortionLayer *layer, GBinPortion *portion) +bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void *data)  { -    GPortionLayer *sub;                     /* Sous couche indispensable   */ -    bool conflict;                          /* Conflit dû aux débordements */ -    const mrange_t *range;                  /* Emplacement de la portion   */ -    size_t i;                               /* Boucle de parcours          */ -    const mrange_t *other;                  /* Emplacements déjà occupés   */ - -    /** -     * On prend ici en compte le genre de situations suivantes : -     * -     *  [21] .bss                NOBITS          00088240 07823c 0018c8 00  WA  0   0  8 -     *  [22] __libc_freeres_ptrs NOBITS          00089b08 07823c 000018 00  WA  0   0  4 -     *  [23] .comment            PROGBITS        00000000 07823c 000022 01  MS  0   0  1 -     * -     * Pendant le désassemblage, la procédure n'aime pas trop les intersections -     * de zones mémoire. -     */ +    bool result;                            /* Etat à retourner            */ -    conflict = false; +    bool visit_portion(GBinPortion *p, GBinPortion *pp) +    { +        bool ret;                           /* Etat à retourner            */ +        size_t i;                           /* Boucle de parcours          */ -    range = g_binary_portion_get_range(portion); +        if (p->count == 0) +            ret = visitor(p, pp, BPV_SHOW, data); -    for (i = 0; i < layer->count && !conflict; i++) -    { -        other = g_binary_portion_get_range(layer->portions[i]); +        else +        { +            ret = visitor(p, pp, BPV_ENTER, data); -        conflict = mrange_intersects_mrange(range, other); +            for (i = 0; i < p->count && ret; i++) +                ret = visit_portion(p->subs[i], p); -    } +            if (ret) +                ret = visitor(p, pp, BPV_EXIT, data); -    /* La portion recouvre-t-elle une portion déjà existante ? */ -    if (conflict) -    { -        if (layer->sub_layer == NULL) -        { -            sub = g_portion_layer_new(layer->length, layer->name); -            g_portion_layer_attach_sub(layer, sub);          } -        g_portion_layer_include(layer->sub_layer, portion); +        return ret;      } -    /* Sinon on l'intègre dans la couche courante */ -    else -    { -        layer->portions = (GBinPortion **)realloc(layer->portions, -                                                  ++layer->count * sizeof(GBinPortion *)); +    result = visit_portion(portion, NULL); -        layer->portions[layer->count - 1] = portion; +    return result; -        g_binary_portion_set_level(portion, &layer->level); +} -        qsort(layer->portions, layer->count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); -    } -} +/* ---------------------------------------------------------------------------------- */ +/*                          PARCOURS D'ENSEMBLES DE PORTIONS                          */ +/* ---------------------------------------------------------------------------------- */  /******************************************************************************  *                                                                             * -*  Paramètres  : layer = couche première à parcourir intégralement.           * -*                count = nombre de portions trouvées et renvoyées. [OUT]      * +*  Paramètres  : portion = couche de portions à parcourir pour les recherches.* +*                x       = abscisse du point de recherche.                    * +*                area    = étendue de portion mère, puis celle trouvée. [OUT] *  *                                                                             * -*  Description : Fournit une liste triée de portions d'un binaire.            * +*  Description : Recherche la portion présente à un point donné.              *  *                                                                             * -*  Retour      : Liste de définitions de zones à libérer après usage.         * +*  Retour      : Portion trouvée à l'endroit indiqué.                         *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *layer, size_t *count) +GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRectangle *area)  { -    GBinPortion **result;                   /* Liste construite à renvoyer */ +    GBinPortion *result;                    /* Portion à retourner         */ +    phys_t full;                            /* Espace total représenté     */ +    size_t i;                               /* Boucle de parcours          */ +    GBinPortion *sub;                       /* Portion incluse à traiter   */ +    GdkRectangle sub_area;                  /* Etendue d'une sous-portion  */ -    GBinPortion **do_collect(const GPortionLayer *l, GBinPortion **lst, size_t *c) -    { -        size_t start;                       /* Indice de départ des ajouts */ -        size_t i;                           /* Boucle de parcours          */ +    result = NULL; -        start = *c; -        *c += l->count; +    full = get_mrange_length(&portion->range); -        lst = (GBinPortion **)realloc(lst, *c * sizeof(GBinPortion *)); +    for (i = 0; i < portion->count && result == NULL; i++) +    { +        sub = portion->subs[i]; -        for (i = 0; i < l->count; i++) -            lst[start + i] = l->portions[i]; +        if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) +            continue; -        return lst; +        if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) +        { +            result = g_binary_portion_find_at_pos(sub, x, &sub_area); -    } +            if (result != NULL) +                *area = sub_area; -    *count = 0; +        } -    result = do_collect(layer, NULL, count); +    } -    qsort(result, *count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); +    if (result == NULL) +    { +        result = portion; +        g_object_ref(G_OBJECT(result)); +    }      return result; @@ -1016,44 +785,30 @@ GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *layer, s  /******************************************************************************  *                                                                             * -*  Paramètres  : layer = couche de portions à parcourir pour les recherches.  * -*                x     = abscisse du point de recherche.                      * -*                area  = étendue de portion mère, puis celle trouvée. [OUT]   * +*  Paramètres  : portion = portion mère à consulter.                          * +*                addr    = adresse du point de recherche.                     *  *                                                                             * -*  Description : Recherche la portion présente à un point donné.              * +*  Description : Détermine si une portion contient une adresse donnée.        *  *                                                                             * -*  Retour      : Portion trouvée à l'endroit indiqué.                         * +*  Retour      : true ou false selon le résultat.                             *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *layer, gint x, GdkRectangle *area) +static bool g_portion_layer_contains_addr(const GBinPortion *portion, const vmpa2t *addr)  { -    GBinPortion *result;                    /* Portion à retourner         */ -    size_t i;                               /* Boucle de parcours          */ -    GBinPortion *sub;                       /* Portion incluse à traiter   */ -    GdkRectangle sub_area;                  /* Etendue d'une sous-portion  */ - -    if (layer->sub_layer != NULL) -        result = g_portion_layer_find_portion_at_pos(layer->sub_layer, x, area); -    else -        result = NULL; +    bool result;                            /* Bilan à retourner           */ -    for (i = 0; i < layer->count && result == NULL; i++) -    { -        sub = layer->portions[i]; +    result = false; -        if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) -            continue; +    /* Portion non allouée en mémoire -> adresse nulle ; on écarte */ +    if (get_virt_addr(get_mrange_addr(&portion->range)) == 0) +        goto not_found; -        if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) -        { -            result = sub; -            *area = sub_area; -        } +    result = mrange_contains_addr(&portion->range, addr); -    } + not_found:      return result; @@ -1062,9 +817,9 @@ GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *layer, gin  /******************************************************************************  *                                                                             * -*  Paramètres  : layer = couche de portions à parcourir pour les recherches.  * -*                addr  = adresse du point de recherche.                       * -*                area  = étendue de portion mère, puis celle trouvée. [OUT]   * +*  Paramètres  : portion = couche de portions à parcourir pour les recherches.* +*                addr    = adresse du point de recherche.                     * +*                area    = étendue de portion mère, puis celle trouvée. [OUT] *  *                                                                             *  *  Description : Recherche la portion présente à une adresse donnée.          *  *                                                                             * @@ -1074,31 +829,39 @@ GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *layer, gin  *                                                                             *  ******************************************************************************/ -GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *layer, const vmpa2t *addr, GdkRectangle *area) +GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *addr, GdkRectangle *area)  {      GBinPortion *result;                    /* Portion à retourner         */ +    phys_t full;                            /* Espace total représenté     */      size_t i;                               /* Boucle de parcours #1       */      GBinPortion *sub;                       /* Portion incluse à traiter   */      GdkRectangle sub_area;                  /* Etendue d'une sous-portion  */ -    if (layer->sub_layer != NULL) -        result = g_portion_layer_find_portion_at_addr(layer->sub_layer, addr, area); -    else -        result = NULL; +    result = NULL; + +    full = get_mrange_length(&portion->range); -    for (i = 0; i < layer->count && result == NULL; i++) +    for (i = 0; i < portion->count && result == NULL; i++)      { -        sub = layer->portions[i]; +        sub = portion->subs[i];          if (!g_portion_layer_contains_addr(sub, addr))              continue; -        if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) +        if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area))              continue; -        result = sub; -        *area = sub_area; +        result = g_binary_portion_find_at_addr(sub, addr, &sub_area); + +        if (result != NULL) +            *area = sub_area; + +    } +    if (result == NULL) +    { +        result = portion; +        g_object_ref(G_OBJECT(result));      }      return result; @@ -1108,10 +871,10 @@ GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *layer, co  /******************************************************************************  *                                                                             * -*  Paramètres  : layer = couche de portions à parcourir pour les recherches.  * -*                x     = abscisse du point de recherche.                      * -*                area  = étendue de représentation de la portion mère.        * -*                addr  = adresse correspondante. [OUT]                        * +*  Paramètres  : root = couche de portions à parcourir pour les recherches.   * +*                x    = abscisse du point de recherche.                       * +*                area = étendue de représentation de la portion mère.         * +*                addr = adresse correspondante. [OUT]                         *  *                                                                             *  *  Description : Fournit la position correspondant à une adresse donnée.      *  *                                                                             * @@ -1121,20 +884,22 @@ GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *layer, co  *                                                                             *  ******************************************************************************/ -bool g_portion_layer_get_addr_from_pos(GPortionLayer *layer, gint x, const GdkRectangle *area, vmpa2t *addr) +bool get_binary_portion_addr_from_pos(GBinPortion *root, gint x, const GdkRectangle *area, vmpa2t *addr)  {      GdkRectangle owner_area;                /* Aire de contenance          */      GBinPortion *owner;                     /* Conteneur propriétaire      */      owner_area = *area; -    owner = g_portion_layer_find_portion_at_pos(layer, x, &owner_area); +    owner = g_binary_portion_find_at_pos(root, x, &owner_area);      if (owner == NULL) return false;      copy_vmpa(addr, get_mrange_addr(&owner->range));      advance_vmpa(addr, (get_mrange_length(&owner->range) * (x - owner_area.x)) / owner_area.width); +    g_object_unref(G_OBJECT(owner)); +      return true;  } @@ -1142,10 +907,10 @@ bool g_portion_layer_get_addr_from_pos(GPortionLayer *layer, gint x, const GdkRe  /******************************************************************************  *                                                                             * -*  Paramètres  : layer = couche de portions à parcourir pour les recherches.  * -*                addr  = adresse du point de recherche.                       * -*                area  = étendue de représentation de la portion mère.        * -*                x     = position correspondante. [OUT]                       * +*  Paramètres  : root = couche de portions à parcourir pour les recherches.   * +*                addr = adresse du point de recherche.                        * +*                area = étendue de représentation de la portion mère.         * +*                x    = position correspondante. [OUT]                        *  *                                                                             *  *  Description : Fournit l'adresse correspondant à une position donnée.       *  *                                                                             * @@ -1155,7 +920,7 @@ bool g_portion_layer_get_addr_from_pos(GPortionLayer *layer, gint x, const GdkRe  *                                                                             *  ******************************************************************************/ -bool g_portion_layer_get_pos_from_addr(GPortionLayer *layer, const vmpa2t *addr, const GdkRectangle *area, gint *x) +bool get_binary_portion_pos_from_addr(GBinPortion *root, const vmpa2t *addr, const GdkRectangle *area, gint *x)  {      GdkRectangle owner_area;                /* Aire de contenance          */      GBinPortion *owner;                     /* Conteneur propriétaire      */ @@ -1163,46 +928,16 @@ bool g_portion_layer_get_pos_from_addr(GPortionLayer *layer, const vmpa2t *addr,      owner_area = *area; -    owner = g_portion_layer_find_portion_at_addr(layer, addr, &owner_area); +    owner = g_binary_portion_find_at_addr(root, addr, &owner_area);      if (owner == NULL) return false;      diff = compute_vmpa_diff(addr, get_mrange_addr(&owner->range));      *x = owner_area.x + (diff * owner_area.width) / get_mrange_length(&owner->range); -    return true; - -} - +    g_object_unref(G_OBJECT(owner)); -/****************************************************************************** -*                                                                             * -*  Paramètres  : layer   = première couche amorçant la visite.                * -*                visitor = fonction à appeler à chaque étape de la descente.  * -*                data    = adresse pointant vers des données de l'utilisateur.* -*                                                                             * -*  Description : Parcours un ensemble de portions binaires.                   * -*                                                                             * -*  Retour      : true si la visite a été jusqu'à son terme, false sinon.      * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -bool g_portion_layer_visit(const GPortionLayer *layer, visit_portion_fc visitor, void *data) -{ -    bool result;                            /* Etat à retourner            */ -    size_t i;                               /* Boucle de parcours          */ - -    if (layer->sub_layer != NULL) -        result = g_portion_layer_visit(layer->sub_layer, visitor, data); -    else -        result = true; - -    for (i = 0; i < layer->count && result; i++) -        result = visitor(layer->portions[i], data); - -    return result; +    return true;  } @@ -1223,52 +958,17 @@ bool g_portion_layer_visit(const GPortionLayer *layer, visit_portion_fc visitor,  *                                                                             *  ******************************************************************************/ -gboolean g_portion_layer_query_tooltip(const GPortionLayer *layer, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) +gboolean query_tooltip_for_binary_portion(GBinPortion *root, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip)  {      GBinPortion *selected;                  /* Portion à décrire ici       */ -    selected = g_portion_layer_find_portion_at_pos(layer, x, (GdkRectangle []) { *area }); +    selected = g_binary_portion_find_at_pos(root, x, (GdkRectangle []) { *area });      if (selected == NULL) return FALSE;      g_binary_portion_query_tooltip(selected, tooltip); -    return TRUE; - -} - +    g_object_unref(G_OBJECT(selected)); -/****************************************************************************** -*                                                                             * -*  Paramètres  : layer = couche de portions à consulter.                      * -*                cr    = contexte graphique pour le dessin.                   * -*                area  = étendue mise à disposition.                          * -*                                                                             * -*  Description : Représente une couche de portions sur une bande dédiée.      * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_portion_layer_draw(const GPortionLayer *layer, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) -{ -    size_t i;                               /* Boucle de parcours          */ -    GBinPortion *sub;                       /* Portion incluse à montrer   */ -    GdkRectangle sub_area;                  /* Etendue d'une sous-portion  */ - -    for (i = 0; i < layer->count; i++) -    { -        sub = layer->portions[i]; - -        if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) -            continue; - -        g_binary_portion_draw(sub, context, cr, &sub_area); - -    } - -    if (layer->sub_layer != NULL) -        g_portion_layer_draw(layer->sub_layer, context, cr, area); +    return TRUE;  } diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h index b91af05..2aa5e1a 100644 --- a/src/glibext/gbinportion.h +++ b/src/glibext/gbinportion.h @@ -80,7 +80,7 @@ typedef enum _PortionAccessRights  GType g_binary_portion_get_type(void);  /* Crée une description de partie de code vierge. */ -GBinPortion *g_binary_portion_new(const char *); +GBinPortion *g_binary_portion_new(const char *, const vmpa2t *, phys_t);  /* Etablit la comparaison ascendante entre deux portions. */  int g_binary_portion_compare(const GBinPortion **, const GBinPortion **); @@ -91,9 +91,6 @@ void g_binary_portion_set_desc(GBinPortion *, const char *);  /* Fournit la description attribuée à une partie de code. */  const char *g_binary_portion_get_desc(const GBinPortion *); -/* Définit les valeurs utiles d'une partie de code. */ -void g_binary_portion_set_values(GBinPortion *, const vmpa2t *, phys_t); -  /* Fournit l'emplacement d'une partie de code binaire. */  const mrange_t *g_binary_portion_get_range(const GBinPortion *); @@ -112,68 +109,44 @@ void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *);  /* Représente la portion sur une bande dédiée. */  void g_binary_portion_draw(const GBinPortion *, GtkStyleContext *, cairo_t *, const GdkRectangle *); +/* Procède à l'inclusion d'une portion dans une autre. */ +void g_binary_portion_include(GBinPortion *, GBinPortion *); +/* Sens des visites */ +typedef enum _BinaryPortionVisit +{ +    BPV_ENTER,                              /* Arrivée sur une branche     */ +    BPV_SHOW,                               /* Visite d'une feuille        */ +    BPV_EXIT                                /* Départ d'une branche        */ -/* -------------------------- COUCHES DE PORTIONS BINAIRES -------------------------- */ - - -#define G_TYPE_PORTION_LAYER                (g_portion_layer_get_type()) -#define G_PORTION_LAYER(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PORTION_LAYER, GPortionLayer)) -#define G_IS_PORTION_LAYER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PORTION_LAYER)) -#define G_PORTION_LAYER_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PORTION_LAYER, GPortionLayerClass)) -#define G_IS_PORTION_LAYER_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PORTION_LAYER)) -#define G_PORTION_LAYER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PORTION_LAYER, GPortionLayerClass)) - - -/* Couche de portions binaires quelconques (instance) */ -typedef struct _GPortionLayer GPortionLayer; - -/* Couche de portions binaires quelconques (classe) */ -typedef struct _GPortionLayerClass GPortionLayerClass; - +} BinaryPortionVisit; -/* Taille à définir lors d'un rattachement */ -#define NO_LENGTH_YET VMPA_NO_PHYSICAL +/* Fonction appelée à chaque visite de portion.*/ +typedef bool (* visit_portion_fc) (GBinPortion *, GBinPortion *, BinaryPortionVisit, void *); -/* Indique le type défini par la GLib pour les couches de portions binaires. */ -GType g_portion_layer_get_type(void); +/* Parcourt un ensemble de portions binaires. */ +bool g_binary_portion_visit(GBinPortion *, visit_portion_fc, void *); -/* Crée une nouvelle couche de portions binaires. */ -GPortionLayer *g_portion_layer_new(phys_t, const char *); -/* Attache une couche à une autre en tant que couche inférieure. */ -void g_portion_layer_attach_sub(GPortionLayer *, GPortionLayer *); -/* Procède à l'inclusion d'une portion dans une couche. */ -void g_portion_layer_include(GPortionLayer *, GBinPortion *); +/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ -/* Fournit une liste triée de portions d'un binaire. */ -GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *, size_t *);  /* Recherche la portion présente à un point donné. */ -GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *, gint, GdkRectangle *); +GBinPortion *g_binary_portion_find_at_pos(GBinPortion *, gint, GdkRectangle *);  /* Recherche la portion présente à une adresse donnée. */ -GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *, const vmpa2t *, GdkRectangle *); +GBinPortion *g_binary_portion_find_at_addr(GBinPortion *, const vmpa2t *, GdkRectangle *);  /* Fournit la position correspondant à une adresse donnée. */ -bool g_portion_layer_get_addr_from_pos(GPortionLayer *, gint, const GdkRectangle *, vmpa2t *); +bool get_binary_portion_addr_from_pos(GBinPortion *, gint, const GdkRectangle *, vmpa2t *);  /* Fournit l'adresse correspondant à une position donnée. */ -bool g_portion_layer_get_pos_from_addr(GPortionLayer *, const vmpa2t *, const GdkRectangle *, gint *); - -/* Fonction appelée à chaque visite de portion.*/ -typedef bool (* visit_portion_fc) (GBinPortion *, void *); - -/* Parcours un ensemble de portions binaires. */ -bool g_portion_layer_visit(const GPortionLayer *, visit_portion_fc, void *); +bool get_binary_portion_pos_from_addr(GBinPortion *, const vmpa2t *, const GdkRectangle *, gint *);  /* Prépare une astuce concernant une portion pour son affichage. */ -gboolean g_portion_layer_query_tooltip(const GPortionLayer *, gint, gint, const GdkRectangle *, GtkTooltip *); - -/* Représente une couche de portions sur une bande dédiée. */ -void g_portion_layer_draw(const GPortionLayer *, GtkStyleContext *, cairo_t *, const GdkRectangle *); +gboolean query_tooltip_for_binary_portion(GBinPortion *, gint, gint, const GdkRectangle *, GtkTooltip *); diff --git a/src/gtkext/gtkbinarystrip.c b/src/gtkext/gtkbinarystrip.c index fff6a78..d1638ed 100644 --- a/src/gtkext/gtkbinarystrip.c +++ b/src/gtkext/gtkbinarystrip.c @@ -211,7 +211,7 @@ static void gtk_binary_strip_size_allocate(GtkWidget *widget, GtkAllocation *all  {      GtkBinaryStrip *strip;                  /* Autre version du composant  */      GExeFormat *format;                     /* Format du binaire           */ -    GPortionLayer *layer;                   /* Couche première de portions */ +    GBinPortion *portions;                  /* Couche première de portions */      GdkRectangle area;                      /* Surface du composant        */      GTK_WIDGET_CLASS(gtk_binary_strip_parent_class)->size_allocate(widget, allocation); @@ -222,17 +222,17 @@ static void gtk_binary_strip_size_allocate(GtkWidget *widget, GtkAllocation *all          return;      format = g_loaded_binary_get_format(strip->binary); -    layer = g_exe_format_get_main_layer(format); +    portions = g_exe_format_get_portions(format);      area.x = 0;      area.y = 0;      area.width = allocation->width;      area.height = allocation->height; -    if (!g_portion_layer_get_pos_from_addr(layer, &strip->cursor_addr, &area, &strip->cursor_pos)) +    if (!get_binary_portion_pos_from_addr(portions, &strip->cursor_addr, &area, &strip->cursor_pos))          strip->cursor_pos = 0; -    g_object_unref(G_OBJECT(layer)); +    g_object_unref(G_OBJECT(portions));      g_object_unref(G_OBJECT(format));  } @@ -257,7 +257,7 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto      gint height;                            /* Hauteur du composant        */      GtkBinaryStrip *strip;                  /* Autre version du composant  */      GExeFormat *format;                     /* Format du binaire           */ -    GPortionLayer *layer;                   /* Couche première de portions */ +    GBinPortion *portions;                  /* Couche première de portions */      GdkRectangle area;                      /* Surface du composant        */      vmpa2t addr;                            /* Adresse à sélectionner      */ @@ -272,14 +272,14 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto      strip = GTK_BINARY_STRIP(widget);      format = g_loaded_binary_get_format(strip->binary); -    layer = g_exe_format_get_main_layer(format); +    portions = g_exe_format_get_portions(format);      area.x = 0;      area.y = 0;      area.width = width;      area.height = height; -    if (g_portion_layer_get_addr_from_pos(layer, event->x, &area, &addr)) +    if (get_binary_portion_addr_from_pos(portions, event->x, &area, &addr))      {          copy_vmpa(&strip->cursor_addr, &addr);          strip->cursor_pos = event->x; @@ -290,7 +290,7 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto      } -    g_object_unref(G_OBJECT(layer)); +    g_object_unref(G_OBJECT(portions));      g_object_unref(G_OBJECT(format));      return FALSE; @@ -314,10 +314,10 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto  static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr)  {      GtkBinaryStrip *strip;                  /* Autre vision du composant   */ +    GtkStyleContext *context;               /* Contexte du thème actuel    */      GExeFormat *format;                     /* Format du binaire           */ -    GPortionLayer *layer;                   /* Couche première de portions */ +    GBinPortion *portions;                  /* Portions de binaire         */      GdkRectangle full;                      /* Taille totale de la surface */ -    GtkStyleContext *context;               /* Contexte du thème actuel    */      GdkRGBA *color;                         /* Couleur du curseur          */      strip = GTK_BINARY_STRIP(widget); @@ -325,21 +325,21 @@ static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr)      if (strip->binary == NULL)          return FALSE; +    context = gtk_widget_get_style_context(widget); +      /* Dessin des portions de binaire */      format = g_loaded_binary_get_format(strip->binary); -    layer = g_exe_format_get_main_layer(format); +    portions = g_exe_format_get_portions(format);      full.x = 0;      full.y = 1;      full.width = gtk_widget_get_allocated_width(widget);      full.height = gtk_widget_get_allocated_height(widget) - 1; -    context = gtk_widget_get_style_context(widget); - -    g_portion_layer_draw(layer, context, cr, &full); +    g_binary_portion_draw(portions, context, cr, &full); -    g_object_unref(G_OBJECT(layer)); +    g_object_unref(G_OBJECT(portions));      g_object_unref(G_OBJECT(format));      /* Dessin de la position */ @@ -348,8 +348,8 @@ static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr)      {          cairo_set_line_width(cr, 1); -        gtk_style_context_get(gtk_widget_get_style_context(widget), GTK_STATE_FLAG_NORMAL, -                       GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &color, NULL); +        gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, +                              GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &color, NULL);          cairo_set_source_rgb(cr, color->red, color->green, color->blue); @@ -395,7 +395,7 @@ static gboolean gtk_binary_strip_query_tooltip(GtkWidget *widget, gint x, gint y      gboolean result;                        /* Bilan à retourner           */      GtkBinaryStrip *strip;                  /* Autre version du composant  */      GExeFormat *format;                     /* Format du binaire           */ -    GPortionLayer *layer;                   /* Couches binaires à consulter*/ +    GBinPortion *portions;                  /* Couches binaires à consulter*/      GdkRectangle area;                      /* Surface du composant        */      if (keyboard) return FALSE; @@ -405,16 +405,16 @@ static gboolean gtk_binary_strip_query_tooltip(GtkWidget *widget, gint x, gint y      if (strip->binary != NULL)      {          format = g_loaded_binary_get_format(strip->binary); -        layer = g_exe_format_get_main_layer(format); +        portions = g_exe_format_get_portions(format);          area.x = 0;          area.y = 0;          area.width = gtk_widget_get_allocated_width(widget);          area.height = gtk_widget_get_allocated_height(widget); -        result = g_portion_layer_query_tooltip(layer, x, y, &area, tooltip); +        result = query_tooltip_for_binary_portion(portions, x, y, &area, tooltip); -        g_object_unref(G_OBJECT(layer)); +        g_object_unref(G_OBJECT(portions));          g_object_unref(G_OBJECT(format));      } diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c index b5dc0e1..dba5145 100644 --- a/src/gtkext/gtkstatusstack.c +++ b/src/gtkext/gtkstatusstack.c @@ -527,7 +527,7 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL      GExeFormat *format;                     /* Format de binaire à traiter */      const mrange_t *range;                  /* Emplacement d'instruction   */      const vmpa2t *addr;                     /* Localisation de départ      */ -    GPortionLayer *layer;                   /* Couche première de portions */ +    GBinPortion *portions;                  /* Couche première de portions */      GBinPortion *portion;                   /* Zone mémoire d'appartenance */      const char *text;                       /* Texte au contenu à copier   */      GBinSymbol *symbol;                     /* Symbole présent à l'adresse */ @@ -556,9 +556,9 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL      /* Zone d'appartenance */ -    layer = g_exe_format_get_main_layer(format); +    portions = g_exe_format_get_portions(format); -    portion = g_portion_layer_find_portion_at_addr(layer, addr, (GdkRectangle []) { }); +    portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { });      text = g_binary_portion_get_desc(portion); @@ -567,7 +567,9 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL      else          info->segment = strdup(_("Binary")); -    g_object_unref(G_OBJECT(layer)); +    g_object_unref(G_OBJECT(portion)); + +    g_object_unref(G_OBJECT(portions));      /* Adresses de base */ diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c index b8631b6..38a17a2 100644 --- a/src/gui/panels/strings.c +++ b/src/gui/panels/strings.c @@ -465,7 +465,7 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin      GArchProcessor *proc;                   /* Architecture du binaire     */      MemoryDataSize msize;                   /* Taille par défaut           */      GExeFormat *format;                     /* Format de travail           */ -    GPortionLayer *layer;                   /* Couche première de portions */ +    GBinPortion *portions;                  /* Couche première de portions */      GBinContent *content;                   /* Contenu binaire en mémoire  */      size_t count;                           /* Nombre des chaînes          */      GBinSymbol **symbols;                   /* Liste des chaînes trouvées  */ @@ -505,7 +505,7 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin      g_object_unref(G_OBJECT(proc));      format = g_loaded_binary_get_format(binary); -    layer = g_exe_format_get_main_layer(format); +    portions = g_exe_format_get_portions(format);      content = g_binary_format_get_content(G_BIN_FORMAT(format));      symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &count); @@ -520,8 +520,9 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin          vmpa2_phys_to_string(addr, msize, phys, NULL);          vmpa2_virt_to_string(addr, msize, virt, NULL); -        portion = g_portion_layer_find_portion_at_addr(layer, addr, (GdkRectangle []) { }); +        portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { });          area = g_binary_portion_get_desc(portion); +        g_object_unref(G_OBJECT(portion));          label = g_binary_symbol_get_label(symbols[i]); @@ -562,7 +563,7 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin      }      g_object_unref(G_OBJECT(content)); -    g_object_unref(G_OBJECT(layer)); +    g_object_unref(G_OBJECT(portions));      g_object_unref(G_OBJECT(format));  }  | 
