diff options
| -rw-r--r-- | src/analysis/binary.c | 10 | ||||
| -rw-r--r-- | src/glibext/gbuffercache.c | 10 | ||||
| -rw-r--r-- | src/glibext/gbuffercache.h | 2 | ||||
| -rw-r--r-- | src/glibext/gbufferview.c | 26 | ||||
| -rw-r--r-- | src/glibext/gwidthtracker.c | 361 | ||||
| -rw-r--r-- | src/glibext/gwidthtracker.h | 7 | 
6 files changed, 395 insertions, 21 deletions
diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 15ec403..54ad89b 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -1625,6 +1625,7 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, wgroup_id_t gid, GtkS      const char *arch;                       /* Architecture d'exécution    */      const char *desc;                       /* Description humaine associée*/      GProcContext *context;                  /* Contexte de suivi dédié     */ +    GWidthTracker *tracker;                 /* Gestionnaire de largeur     */      /* Interprétation du format associé */ @@ -1663,8 +1664,17 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, wgroup_id_t gid, GtkS      g_binary_format_complete_analysis(format, gid, status);      if (!is_batch_mode()) +    {          output_disassembly(binary, context, status, &binary->disass_cache); +        tracker = g_buffer_cache_get_width_tracker(binary->disass_cache); + +        g_width_tracker_build_initial_cache(tracker, gid, status); + +        g_object_unref(G_OBJECT(tracker)); + +    } +      result = true;   glba_exit: diff --git a/src/glibext/gbuffercache.c b/src/glibext/gbuffercache.c index a627238..66ecf27 100644 --- a/src/glibext/gbuffercache.c +++ b/src/glibext/gbuffercache.c @@ -784,9 +784,15 @@ size_t g_buffer_cache_count_lines(const GBufferCache *cache)  *                                                                             *  ******************************************************************************/ -const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache) +GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache)  { -    return cache->tracker; +    GWidthTracker *result;                  /* Instance à retourner    *   */ + +    result = cache->tracker; + +    g_object_ref(G_OBJECT(result)); + +    return result;  } diff --git a/src/glibext/gbuffercache.h b/src/glibext/gbuffercache.h index c00e0f2..dbd3237 100644 --- a/src/glibext/gbuffercache.h +++ b/src/glibext/gbuffercache.h @@ -72,7 +72,7 @@ gint g_buffer_cache_get_text_position(const GBufferCache *);  size_t g_buffer_cache_count_lines(const GBufferCache *);  /* Fournit un lien vers la structure de suivi de largeurs. */ -const GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *); +GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *);  /* Insère un générateur dans des lignes à une position donnée. */  void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, bool, bool); diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c index c212672..af7d7ac 100644 --- a/src/glibext/gbufferview.c +++ b/src/glibext/gbufferview.c @@ -45,12 +45,7 @@ struct _GBufferView      size_t first;                           /* Indice de la première ligne */      size_t last;                            /* Indice de la dernière ligne */ -    union -    { -        const GWidthTracker *ext_tracker;   /* Suivi externe des largeurs  */ -        GWidthTracker *int_tracker;         /* Suivi interne des largeurs  */ -        GWidthTracker *tracker;             /* Suivi pour usage interne    */ -    }; +    GWidthTracker *tracker;                 /* Suivi des largeurs          */  }; @@ -173,8 +168,7 @@ static void g_buffer_view_dispose(GBufferView *view)  {      g_object_unref(G_OBJECT(view->cache)); -    if (!view->unrestricted) -        g_object_unref(G_OBJECT(view->int_tracker)); +    g_object_unref(G_OBJECT(view->tracker));      G_OBJECT_CLASS(g_buffer_view_parent_class)->dispose(G_OBJECT(view)); @@ -400,7 +394,7 @@ GBufferCache *g_buffer_view_get_cache(const GBufferView *view)  void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t *end)  {      bool state;                             /* Nouvel état à proclamer     */ -    const GWidthTracker *template;          /* Suivi déjà en place         */ +    GWidthTracker *template;                /* Suivi déjà en place         */      state = (start == NULL || end == NULL); @@ -410,16 +404,16 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t          template = g_buffer_cache_get_width_tracker(view->cache); +        /* Vérification pour le cas particulier du démarrage */ +        if (view->tracker != NULL) +            g_object_unref(G_OBJECT(view->tracker)); +          if (view->unrestricted)          { -            /* Vérification pour le cas particulier du démarrage */ -            if (view->int_tracker != NULL) -                g_object_unref(G_OBJECT(view->int_tracker)); -              view->first = 0;              view->last = g_buffer_cache_count_lines(view->cache) - 1; -            view->ext_tracker = template; +            view->tracker = template;          } @@ -431,7 +425,9 @@ void g_buffer_view_restrict(GBufferView *view, const vmpa2t *start, const vmpa2t              view->first = g_buffer_cache_find_index_by_addr(view->cache, start, true);              view->last = g_buffer_cache_find_index_by_addr(view->cache, end, false); -            view->ext_tracker = g_width_tracker_new_restricted(template, view->first, view->last); +            view->tracker = g_width_tracker_new_restricted(template, view->first, view->last); + +            g_object_unref(G_OBJECT(template));          } diff --git a/src/glibext/gwidthtracker.c b/src/glibext/gwidthtracker.c index 82ae65b..181759c 100644 --- a/src/glibext/gwidthtracker.c +++ b/src/glibext/gwidthtracker.c @@ -30,8 +30,77 @@  #include <string.h> +#include <i18n.h> + + +#include "delayed-int.h"  #include "gbuffercache.h" +#include "../core/global.h" + + + +/* --------------------------- PRISE DE MESURES INITIALES --------------------------- */ + + +/* Procédure de mise à jour des mesures de largeurs (instance) */ +typedef struct _GWidthUpdate +{ +    GDelayedWork parent;                    /* A laisser en premier        */ + +    activity_id_t id;                       /* Groupe de progression       */ + +    GWidthTracker *tracker;                 /* Gestionnaire à manipuler    */ + +    size_t start;                           /* Premier indice à traiter    */ +    size_t end;                             /* Premier indice à écarter    */ + +    line_width_summary summary;             /* Largeurs requises suivies   */ + +} GWidthUpdate; + +/* Procédure de mise à jour des mesures de largeurs (classe) */ +typedef struct _GWidthUpdateClass +{ +    GDelayedWorkClass parent;               /* A laisser en premier        */ + +} GWidthUpdateClass; + + +#define G_TYPE_WIDTH_UPDATE            g_width_update_get_type() +#define G_WIDTH_UPDATE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_WIDTH_UPDATE, GWidthUpdate)) +#define G_IS_WIDTH_UPDATE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_WIDTH_UPDATE)) +#define G_WIDTH_UPDATE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_WIDTH_UPDATE, GWidthUpdateClass)) +#define G_IS_WIDTH_UPDATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_WIDTH_UPDATE)) +#define G_WIDTH_UPDATE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_WIDTH_UPDATE, GWidthUpdateClass)) + + +/* Initialise la classe des tâches de mesures de largeurs. */ +static void g_width_update_class_init(GWidthUpdateClass *); + +/* Initialise une tâche de mesures de largeurs. */ +static void g_width_update_init(GWidthUpdate *); + +/* Supprime toutes les références externes. */ +static void g_width_update_dispose(GWidthUpdate *); + +/* Procède à la libération totale de la mémoire. */ +static void g_width_update_finalize(GWidthUpdate *); + +/* Indique le type défini pour les tâches de mesures de largeurs. */ +GType g_width_update_get_type(void); + +/* Crée une tâche de mesures de largeurs. */ +static GWidthUpdate *g_width_update_new(activity_id_t, GWidthTracker *, size_t, size_t); +/* Assure les mesures initiales d'un ensemble de lignes. */ +static void g_width_update_process(GWidthUpdate *, GtkStatusStack *); + +/* Récupère les données obtenues lors d'une mesure globale. */ +static void g_width_update_collect(GWidthUpdate *, line_width_summary *); + + + +/* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */  /* Portions de largeurs communes */ @@ -98,6 +167,209 @@ static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *); +/* ---------------------------------------------------------------------------------- */ +/*                             PRISE DE MESURES INITIALES                             */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour les tâches de mesures de largeurs. */ +G_DEFINE_TYPE(GWidthUpdate, g_width_update, G_TYPE_DELAYED_WORK); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des tâches de mesures de largeurs.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_width_update_class_init(GWidthUpdateClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GDelayedWorkClass *work;                /* Version en classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_width_update_dispose; +    object->finalize = (GObjectFinalizeFunc)g_width_update_finalize; + +    work = G_DELAYED_WORK_CLASS(klass); + +    work->run = (run_task_fc)g_width_update_process; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : update = instance à initialiser.                             * +*                                                                             * +*  Description : Initialise une tâche de mesures de largeurs.                 * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_width_update_init(GWidthUpdate *update) +{ +    memset(&update->summary, 0, sizeof(line_width_summary)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : update = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_width_update_dispose(GWidthUpdate *update) +{ +    g_object_unref(G_OBJECT(update->tracker)); + +    G_OBJECT_CLASS(g_width_update_parent_class)->dispose(G_OBJECT(update)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : update = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_width_update_finalize(GWidthUpdate *update) +{ +    G_OBJECT_CLASS(g_width_update_parent_class)->finalize(G_OBJECT(update)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : id      = identifiant pour signaler la progression courante. * +*                tracker = gestionnaire de largeurs à consulter.              * +*                start   = indice de la première ligne à traiter.             * +*                end     = indice de la première ligne à éviter.              * +*                                                                             * +*  Description : Crée une tâche de mesures de largeurs.                       * +*                                                                             * +*  Retour      : Tâche créée.                                                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GWidthUpdate *g_width_update_new(activity_id_t id, GWidthTracker *tracker, size_t start, size_t end) +{ +    GWidthUpdate *result;                   /* Tâche à retourner           */ + +    result = g_object_new(G_TYPE_WIDTH_UPDATE, NULL); + +    result->id = id; + +    g_object_ref(G_OBJECT(tracker)); +    result->tracker = tracker; + +    result->start = start; +    result->end = end; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : update = opération de mesures à mener.                       * +*                status = barre de statut à tenir informée.                   * +*                                                                             * +*  Description : Assure les mesures initiales d'un ensemble de lignes.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_width_update_process(GWidthUpdate *update, GtkStatusStack *status) +{ +    line_width_summary *local;              /* Valeurs collectées          */ +    size_t i;                               /* Boucle de parcours #1       */ +    const line_width_summary *summary;      /* Valeurs à intégrer          */ +    BufferLineColumn k;                     /* Boucle de parcours #2       */ + +    local = &update->summary; + +    for (i = update->start; i < update->end; i++) +    { +        summary = g_width_tracker_get_up_to_date_widths(update->tracker, i); + +        for (k = 0; k < BLC_COUNT; k++) +            local->max_widths[k] = MAX(local->max_widths[k], summary->max_widths[k]); + +        local->merged_width = MAX(local->merged_width, summary->merged_width); + +        gtk_status_stack_update_activity_value(status, update->id, 1); + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : update = opération de mesures menée à bien.                  * +*                global = lieu de centralisation des données globales.        * +*                                                                             * +*  Description : Récupère les données obtenues lors d'une mesure globale.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_width_update_collect(GWidthUpdate *update, line_width_summary *global) +{ +    line_width_summary *local;              /* Valeurs collectées          */ +    BufferLineColumn i;                     /* Boucle de parcours          */ + +    local = &update->summary; + +    for (i = 0; i < BLC_COUNT; i++) +        global->max_widths[i] = MAX(global->max_widths[i], local->max_widths[i]); + +    global->merged_width = MAX(global->merged_width, local->merged_width); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                              RASSEMBLEMENT DE MESURES                              */ +/* ---------------------------------------------------------------------------------- */ + +  /* Détermine le type du gestionnaire de largeurs associées aux lignes. */  G_DEFINE_TYPE(GWidthTracker, g_width_tracker, G_TYPE_OBJECT); @@ -686,6 +958,89 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t  /******************************************************************************  *                                                                             * +*  Paramètres  : tracker = suivi de largeurs dont le cache est à construire.  * +*                gid     = groupe de travail impliqué.                        * +*                status  = barre de statut à tenir informée.                  * +*                                                                             * +*  Description : Calcule les largeurs requises par un ensemble de lignes.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_width_tracker_build_initial_cache(GWidthTracker *tracker, wgroup_id_t gid, GtkStatusStack *status) +{ +    guint runs_count;                       /* Qté d'exécutions parallèles */ +    GWidthUpdate **updates;                 /* Mesures à suivre            */ +    size_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          */ +    size_t start;                           /* Début de zone de traitement */ +    bool closing;                           /* Détection de fin en amont   */ +    size_t end;                             /* Fin de zone de traitement   */ + +    assert(!tracker->cached); + +    /* Lancement des traitements */ + +    runs_count = g_get_num_processors(); + +    updates = (GWidthUpdate **)calloc(runs_count, sizeof(GWidthUpdate *)); + +    run_size = tracker->count / runs_count; + +    queue = get_work_queue(); + +    id = gtk_status_stack_add_activity(status, _("Computing width of all lines for rendering"), tracker->count); + +    for (i = 0; i < runs_count; i++) +    { +        start = i * run_size; + +        closing = ((i + 1) == runs_count); + +        if (closing) +            end = tracker->count; +        else +            end = start + run_size; + +        updates[i] = g_width_update_new(id, tracker, start, end); + +        g_object_ref(G_OBJECT(updates[i])); +        g_work_queue_schedule_work(queue, G_DELAYED_WORK(updates[i]), gid); + +    } + +    g_work_queue_wait_for_completion(queue, gid); + +    /* Récupération des aires */ + +    memset(&tracker->summary, 0, sizeof(line_width_summary)); + +    for (i = 0; i < runs_count; i++) +    { +        g_width_update_collect(updates[i], &tracker->summary); + +        g_object_unref(G_OBJECT(updates[i])); + +    } + +    /* Fin */ + +    free(updates); + +    gtk_status_stack_remove_activity(status, id); + +    tracker->cached = true; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : tracker = suivi de largeurs à mettre à jour si besoin est.   *  *                                                                             *  *  Description : Calcule les largeurs requises par un ensemble de lignes.     * @@ -705,14 +1060,14 @@ static void g_width_tracker_ensure_valid_required_widths(GWidthTracker *tracker)      if (!tracker->cached)      { +        global = &tracker->summary; +          /* Réinitialisation */ -        memset(&tracker->summary, 0, sizeof(line_width_summary)); +        memset(global, 0, sizeof(line_width_summary));          /* Collecte */ -        global = &tracker->summary; -          for (i = 0; i < tracker->count; i++)          {              summary = g_width_tracker_get_up_to_date_widths(tracker, i); diff --git a/src/glibext/gwidthtracker.h b/src/glibext/gwidthtracker.h index 0832467..2d9aef6 100644 --- a/src/glibext/gwidthtracker.h +++ b/src/glibext/gwidthtracker.h @@ -29,10 +29,14 @@  #include <stdbool.h> +#include "delayed.h"  #include "gbufferline.h" +/* ---------------------------- RASSEMBLEMENT DE MESURES ---------------------------- */ + +  /* gbuffercache.h : Tampon pour gestion de lignes optimisée (instance) */  typedef struct _GBufferCache GBufferCache; @@ -70,6 +74,9 @@ void g_width_tracker_update_added(GWidthTracker *, size_t, size_t);  /* Prend acte de la suppression de lignes pour les largeurs. */  void g_width_tracker_update_deleted(GWidthTracker *, size_t, size_t); +/* Calcule les largeurs requises par un ensemble de lignes. */ +void g_width_tracker_build_initial_cache(GWidthTracker *, wgroup_id_t, GtkStatusStack *); +  /* Fournit un bon résumé des largeurs en vigueur. */  const line_width_summary *g_width_tracker_get_width_summary(GWidthTracker *);  | 
