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/glibext | |
parent | 403a0519ec85a156a7f306b045d9cab619302473 (diff) |
Cut binary data into several areas using all the available CPUs and less memory.
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/gbinportion.c | 708 | ||||
-rw-r--r-- | src/glibext/gbinportion.h | 67 |
2 files changed, 224 insertions, 551 deletions
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 *); |