From b57e8ef5522dcbe126157fc2c50fcf879aa7d743 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 29 Dec 2015 00:27:12 +0100 Subject: Defined layers to register all kinds of binary portions. --- ChangeLog | 24 + plugins/mobicore/mclf.c | 17 +- src/analysis/disass/area.c | 28 +- src/analysis/disass/output.c | 26 +- src/format/dex/class.c | 8 +- src/format/dex/class.h | 2 +- src/format/dex/dex.c | 16 +- src/format/dex/method.c | 6 +- src/format/dex/method.h | 2 +- src/format/elf/elf.c | 24 +- src/format/executable-int.h | 4 +- src/format/executable.c | 89 +--- src/format/executable.h | 8 +- src/glibext/gbinportion.c | 1010 +++++++++++++++++++++++++++--------------- src/glibext/gbinportion.h | 81 +++- src/gtkext/gtkbinarystrip.c | 39 +- src/gtkext/gtkstatusstack.c | 8 +- 17 files changed, 878 insertions(+), 514 deletions(-) diff --git a/ChangeLog b/ChangeLog index f1936bb..5d253fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +15-12-29 Cyrille Bagard + + * plugins/mobicore/mclf.c: + * src/analysis/disass/area.c: + * src/analysis/disass/output.c: + * src/format/dex/class.c: + * src/format/dex/class.h: + * src/format/dex/dex.c: + * src/format/dex/method.c: + * src/format/dex/method.h: + * src/format/elf/elf.c: + * src/format/executable-int.h: + * src/format/executable.c: + * src/format/executable.h: + Update code. + + * src/glibext/gbinportion.c: + * src/glibext/gbinportion.h: + Clean code. Define layers to register all kinds of binary portions. + + * src/gtkext/gtkbinarystrip.c: + * src/gtkext/gtkstatusstack.c: + Update code. + 15-12-28 Cyrille Bagard * src/arch/vmpa.c: diff --git a/plugins/mobicore/mclf.c b/plugins/mobicore/mclf.c index 7b1249c..8e99fc7 100644 --- a/plugins/mobicore/mclf.c +++ b/plugins/mobicore/mclf.c @@ -54,7 +54,7 @@ static void g_mclf_format_finalize(GMCLFFormat *); static const char *g_mclf_format_get_target_machine(const GMCLFFormat *); /* Etend la définition des portions au sein d'un binaire. */ -static void g_mclf_format_refine_portions(const GMCLFFormat *, GBinPortion *); +static void g_mclf_format_refine_portions(const GMCLFFormat *, GPortionLayer *); @@ -261,7 +261,7 @@ static const char *g_mclf_format_get_target_machine(const GMCLFFormat *format) /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * -* raw = portion de binaire brut à raffiner. * +* main = couche de portions principale à raffiner. * * * * Description : Etend la définition des portions au sein d'un binaire. * * * @@ -271,13 +271,18 @@ static const char *g_mclf_format_get_target_machine(const GMCLFFormat *format) * * ******************************************************************************/ -static void g_mclf_format_refine_portions(const GMCLFFormat *format, GBinPortion *raw) +static void g_mclf_format_refine_portions(const GMCLFFormat *format, GPortionLayer *main) { + GPortionLayer *layer; /* Couche à mettre en place */ GBinPortion *new; /* Nouvelle portion définie */ char desc[MAX_PORTION_DESC]; /* Description d'une portion */ phys_t length; /* Taille de portion globale */ vmpa2t addr; /* Emplacement dans le binaire */ + layer = g_portion_layer_new(NO_LENGTH_YET, _("Segment")); + + g_portion_layer_attach_sub(main, layer); + /* Segment de code */ new = g_binary_portion_new(BPC_CODE); @@ -290,7 +295,7 @@ static void g_mclf_format_refine_portions(const GMCLFFormat *format, GBinPortion g_binary_portion_set_rights(new, PAC_WRITE | PAC_EXEC); - g_binary_portion_include(raw, new); + g_portion_layer_include(layer, new); /* Segment de données */ @@ -304,7 +309,7 @@ static void g_mclf_format_refine_portions(const GMCLFFormat *format, GBinPortion g_binary_portion_set_rights(new, PAC_READ | PAC_WRITE); - g_binary_portion_include(raw, new); + g_portion_layer_include(layer, new); /* Signature finale */ @@ -319,6 +324,6 @@ static void g_mclf_format_refine_portions(const GMCLFFormat *format, GBinPortion g_binary_portion_set_rights(new, PAC_READ | PAC_WRITE); - g_binary_portion_include(raw, new); + g_portion_layer_include(layer, new); } diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index d2a03c6..c79b293 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -707,9 +707,11 @@ mem_area_v2 *compute_memory_areas_v2(const GLoadedBinary *binary, phys_t bin_len const vmpa2t *border; /* Nouvelle bordure rencontrée */ mem_area_v2 *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 */ @@ -813,7 +815,9 @@ mem_area_v2 *compute_memory_areas_v2(const GLoadedBinary *binary, phys_t bin_len /* Seconde étape : on s'assure du découpage autour des portions pour respecter l'alignement */ - portions = g_exe_format_get_portions_at_level(format, -1, &portions_count); + 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++) { @@ -824,6 +828,20 @@ mem_area_v2 *compute_memory_areas_v2(const GLoadedBinary *binary, phys_t bin_len (unsigned int)get_phy_addr(portion_start), (unsigned int)get_virt_addr(portion_start)); + + /** + * 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]; @@ -871,7 +889,10 @@ mem_area_v2 *compute_memory_areas_v2(const GLoadedBinary *binary, phys_t bin_len } + if (portions != NULL) + free(portions); + g_object_unref(G_OBJECT(layer)); @@ -928,9 +949,6 @@ mem_area_v2 *compute_memory_areas_v2(const GLoadedBinary *binary, phys_t bin_len /* Nettoyage final */ - if (portions != NULL) - free(portions); - if (exe_ranges != NULL) free(exe_ranges); @@ -2193,7 +2211,7 @@ mem_area *compute_memory_areas(GExeFormat *format, phys_t bin_length, size_t *co printf("--------------------\n"); - portions = g_exe_format_get_portions_at_level(format, -1, &portions_count); + portions = NULL;//g_exe_format_get_portions_at_level(format, -1, &portions_count); for (i = 1; i < portions_count; i++) diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index 727c34f..67a3ce8 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -56,6 +56,14 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *format, GArchProcessor *proc, const GArchInstruction *instrs, GBinRoutine * const *routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id) { GLangOutput *output; /* Modèle de sortie adéquat */ + GPortionLayer *layer; /* 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 */ + GBinSymbol **symbols; /* Symboles à représenter */ + size_t sym_count; /* Qté de symboles présents */ + size_t sym_index; /* Prochain symbole non traité */ + //GArchProcessor *proc; /* Architecture du binaire */ MemoryDataSize msize; /* Taille du bus d'adresses */ const GBinContent *content; /* Contenu binaire global */ @@ -74,13 +82,6 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form GBufferLine *line; - GBinPortion **portions; /* Morceaux d'encadrement */ - size_t portions_count; /* Taille de cette liste */ - size_t portion_index; /* Prochaine portion à traiter */ - - GBinSymbol **symbols; /* Symboles à représenter */ - size_t sym_count; /* Qté de symboles présents */ - size_t sym_index; /* Prochain symbole non traité */ const vmpa2t *paddr; /* Adresse de portion */ @@ -100,12 +101,12 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form output = g_asm_output_new(); + layer = g_exe_format_get_main_layer(format); - - portions = g_exe_format_get_portions_at_level(format, -1, &portions_count); + portions = g_portion_layer_collect_all_portions(layer, &portions_count); portion_index = 0; - symbols = g_binary_format_get_symbols(format, &sym_count); + symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); sym_index = 0; #if 0 @@ -294,7 +295,10 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form g_object_unref(G_OBJECT(content)); - /* free portions... */ + if (portions != NULL) + free(portions); + + g_object_unref(G_OBJECT(layer)); g_object_unref(G_OBJECT(output)); diff --git a/src/format/dex/class.c b/src/format/dex/class.c index 657461f..1dc3a40 100644 --- a/src/format/dex/class.c +++ b/src/format/dex/class.c @@ -309,7 +309,7 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t /****************************************************************************** * * * Paramètres : class = informations chargées à consulter. * -* raw = portion de binaire brut à raffiner. * +* layer = couche de portions à raffiner. * * * * Description : Intègre la méthode en tant que portion de code. * * * @@ -319,15 +319,15 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t * * ******************************************************************************/ -void g_dex_class_include_as_portion(const GDexClass *class, GBinPortion *raw) +void g_dex_class_include_as_portion(const GDexClass *class, GPortionLayer *layer) { size_t i; /* Boucle de parcours */ for (i = 0; i < class->dmethods_count; i++) - g_dex_method_include_as_portion(class->direct_methods[i], raw); + g_dex_method_include_as_portion(class->direct_methods[i], layer); for (i = 0; i < class->vmethods_count; i++) - g_dex_method_include_as_portion(class->virtual_methods[i], raw); + g_dex_method_include_as_portion(class->virtual_methods[i], layer); } diff --git a/src/format/dex/class.h b/src/format/dex/class.h index 77fa6ba..fb7cada 100644 --- a/src/format/dex/class.h +++ b/src/format/dex/class.h @@ -64,7 +64,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 *, GBinPortion *); +void g_dex_class_include_as_portion(const GDexClass *, GPortionLayer *); /* 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 afd9db1..ed2565f 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -27,6 +27,9 @@ #include +#include + + #include "dex-int.h" #include "pool.h" @@ -55,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 *, GBinPortion *); +static void g_dex_format_refine_portions(const GDexFormat *, GPortionLayer *); /* Fournit l'emplacement d'une section donnée. */ static bool g_dex_format_get_section_range_by_name(const GDexFormat *, const char *, mrange_t *); @@ -302,7 +305,7 @@ static const char *g_dex_format_get_target_machine(const GDexFormat *format) /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * -* raw = portion de binaire brut à raffiner. * +* main = couche de portions principale à raffiner. * * * * Description : Etend la définition des portions au sein d'un binaire. * * * @@ -312,15 +315,20 @@ static const char *g_dex_format_get_target_machine(const GDexFormat *format) * * ******************************************************************************/ -static void g_dex_format_refine_portions(const GDexFormat *format, GBinPortion *raw) +static void g_dex_format_refine_portions(const GDexFormat *format, GPortionLayer *main) { + GPortionLayer *layer; /* Couche à mettre en place */ 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); + max = g_dex_format_count_classes(format); for (i = 0; i < max; i++) - g_dex_class_include_as_portion(format->classes[i], raw); + g_dex_class_include_as_portion(format->classes[i], layer); } diff --git a/src/format/dex/method.c b/src/format/dex/method.c index c68e9e1..9c911d1 100644 --- a/src/format/dex/method.c +++ b/src/format/dex/method.c @@ -294,7 +294,7 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method) /****************************************************************************** * * * Paramètres : method = représentation interne du format DEX à consulter. * -* raw = portion de binaire brut à raffiner. * +* layer = couche de portions à raffiner. * * * * Description : Intègre la méthode en tant que portion de code. * * * @@ -304,7 +304,7 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method) * * ******************************************************************************/ -void g_dex_method_include_as_portion(const GDexMethod *method, GBinPortion *raw) +void g_dex_method_include_as_portion(const GDexMethod *method, GPortionLayer *layer) { GBinPortion *new; /* Nouvelle portion définie */ char *desc; /* Description d'une portion */ @@ -327,7 +327,7 @@ void g_dex_method_include_as_portion(const GDexMethod *method, GBinPortion *raw) g_binary_portion_set_rights(new, PAC_READ | PAC_EXEC); - g_binary_portion_include(raw, new); + g_portion_layer_include(layer, new); } diff --git a/src/format/dex/method.h b/src/format/dex/method.h index dee33cb..4d29bac 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 *, GBinPortion *); +void g_dex_method_include_as_portion(const GDexMethod *, GPortionLayer *); /* Indique la position de la méthode au sein du binaire. */ off_t g_dex_method_get_offset(const GDexMethod *); diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index 3dc5d64..3491c71 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -67,7 +67,7 @@ static void g_elf_format_finalize(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 *, GBinPortion *); +static void g_elf_format_refine_portions(const GElfFormat *, GPortionLayer *); /* Fournit l'emplacement correspondant à une position physique. */ static bool g_elf_format_translate_offset_into_vmpa(const GElfFormat *, phys_t, vmpa2t *); @@ -352,7 +352,7 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format) /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * -* raw = portion de binaire brut à raffiner. * +* main = couche de portions principale à raffiner. * * * * Description : Etend la définition des portions au sein d'un binaire. * * * @@ -362,8 +362,9 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format) * * ******************************************************************************/ -static void g_elf_format_refine_portions(const GElfFormat *format, GBinPortion *raw) +static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer *main) { + GPortionLayer *layer; /* Couche à mettre en place */ uint16_t i; /* Boucle de parcours */ off_t offset; /* Début de part de programme */ elf_phdr phdr; /* En-tête de programme ELF */ @@ -381,7 +382,10 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GBinPortion * /* Côté segments basiques */ -#if 0 + layer = g_portion_layer_new(NO_LENGTH_YET, _("Segment")); + + g_portion_layer_attach_sub(main, layer); + for (i = 0; i < ELF_HDR(format, format->header, e_phnum); i++) { offset = ELF_HDR(format, format->header, e_phoff) @@ -414,10 +418,9 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GBinPortion * g_binary_portion_set_rights(new, rights); - g_binary_portion_include(raw, new); + g_portion_layer_include(layer, new); } -#endif /* Inclusion des sections, si possible... */ @@ -425,6 +428,10 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GBinPortion * ELF_HDR(format, format->header, e_shstrndx), &strings); + layer = g_portion_layer_new(NO_LENGTH_YET, _("Section")); + + g_portion_layer_attach_sub(main, layer); + for (i = 0; i < ELF_HDR(format, format->header, e_shnum); i++) { if (!find_elf_section_by_index(format, i, §ion)) @@ -432,9 +439,6 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GBinPortion * sh_flags = ELF_SHDR(format, section, sh_flags); - printf("[section % 2hu] 0x%08x -> %x -> %d\n", i, sh_flags, - sh_flags & SHF_ALLOC, (sh_flags & SHF_ALLOC) == 0); - if ((sh_flags & SHF_ALLOC) == 0) continue; @@ -466,7 +470,7 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GBinPortion * g_binary_portion_set_rights(new, rights); - g_binary_portion_include(raw, new); + g_portion_layer_include(layer, new); } diff --git a/src/format/executable-int.h b/src/format/executable-int.h index 4b86092..5e57133 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 *, GBinPortion *); +typedef void (* refine_portions_fc) (const GExeFormat *, GPortionLayer *); /* Fournit l'emplacement correspondant à une position physique. */ typedef bool (* translate_phys_fc) (const GExeFormat *, phys_t, vmpa2t *); @@ -57,7 +57,7 @@ struct _GExeFormat GDbgFormat **debugs; /* Informations de débogage */ size_t debugs_count; /* Nombre de ces informations */ - GBinPortion *portions; /* Morceaux binaires distincts */ + GPortionLayer *layers; /* Couches de morceaux binaires*/ }; diff --git a/src/format/executable.c b/src/format/executable.c index 325dc8b..fc34fa0 100644 --- a/src/format/executable.c +++ b/src/format/executable.c @@ -163,11 +163,6 @@ GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index) } - - - - - /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * @@ -191,89 +186,50 @@ const char *g_exe_format_get_target_machine(const GExeFormat *format) * * * Paramètres : format = description de l'exécutable à consulter. * * * -* Description : Décrit les différentes portions qui composent le binaire. * +* Description : Fournit la première couche des portions composent le binaire.* * * -* Retour : Défintions de zones. * +* Retour : Couche brute des différentes portions. * * * -* Remarques : - * +* Remarques : Le compteur de références de l'instance renvoyée doit être * +* décrémenté après usage. * * * ******************************************************************************/ -GBinPortion *g_exe_format_get_portions(GExeFormat *format) +GPortionLayer *g_exe_format_get_main_layer(GExeFormat *format) { + GBinPortion *portion; /* Portion brute globale */ vmpa2t addr; /* Emplacement vide de sens */ phys_t length; /* Taille de portion globale */ + GPortionLayer *layer; /* Couche à mettre en place */ - if (format->portions == NULL) + if (format->layers == NULL) { - format->portions = g_binary_portion_new(BPC_RAW); + /* 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); - g_binary_portion_set_values(format->portions, &addr, length); + g_binary_portion_set_values(portion, &addr, length); - G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format, format->portions); + /* Création d'une couche de base brute */ - } + layer = g_portion_layer_new(length, NULL); - return format->portions; + g_portion_layer_include(layer, portion); -} + /* Remplissage */ + G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format, layer); -/****************************************************************************** -* * -* Paramètres : format = description de l'exécutable à consulter. * -* level = étage des portions à considérer ou -1 pour tous. * -* count = nombre de portions trouvées et renvoyées. [OUT] * -* * -* Description : Fournit une liste choisie de portions d'un binaire. * -* * -* Retour : Liste de définitins de zones à libérer après usage. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinPortion **g_exe_format_get_portions_at_level(GExeFormat *format, unsigned int level, size_t *count) -{ - GBinPortion **result; /* Liste à retourner */ - - typedef struct _portions_list - { - unsigned int required; - GBinPortion **portions; - size_t length; - - } portions_list; - - portions_list list; /* Sauvegarde de la liste */ - - bool visit_for_level(GBinPortion *portion, portions_list *list) - { - if (list->required == -1 || g_binary_portion_get_level(portion) == list->required) - { - list->portions = (GBinPortion **)realloc(list->portions, ++list->length * sizeof(GBinPortion *)); - list->portions[list->length - 1] = portion; - } - - return true; + format->layers = layer; } - list.required = level; - list.portions = NULL; - list.length = 0; + g_object_ref(G_OBJECT(format->layers)); - g_binary_portion_visit(g_exe_format_get_portions(format), (visit_portion_fc)visit_for_level, &list); - - result = list.portions; - *count = list.length; - - qsort(result, *count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); - - return result; + return format->layers; } @@ -303,6 +259,7 @@ mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count) } x_ranges; x_ranges tmp; /* Sauvegarde de la liste */ + GPortionLayer *layer; /* Couche première de portions */ bool visit_for_x(GBinPortion *portion, x_ranges *ranges) { @@ -324,7 +281,9 @@ mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count) tmp.list = NULL; tmp.length = 0; - g_binary_portion_visit(g_exe_format_get_portions(format), (visit_portion_fc)visit_for_x, &tmp); + 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)); result = tmp.list; *count = tmp.length; diff --git a/src/format/executable.h b/src/format/executable.h index 48a8139..4ca0194 100644 --- a/src/format/executable.h +++ b/src/format/executable.h @@ -62,15 +62,11 @@ size_t g_exe_format_count_debug_info(const GExeFormat *); /* Fournit un format de débogage attaché à l'exécutable. */ 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 *); -/* Décrit les différentes portions qui composent le binaire. */ -GBinPortion *g_exe_format_get_portions(GExeFormat *); - -/* Fournit une liste choisie de portions d'un binaire. */ -GBinPortion **g_exe_format_get_portions_at_level(GExeFormat *, unsigned int, size_t *); +/* Fournit la première couche des portions composent le binaire. */ +GPortionLayer *g_exe_format_get_main_layer(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/glibext/gbinportion.c b/src/glibext/gbinportion.c index 920fcfe..790614a 100644 --- a/src/glibext/gbinportion.c +++ b/src/glibext/gbinportion.c @@ -24,6 +24,7 @@ #include "gbinportion.h" +#include #include #include #include @@ -44,27 +45,16 @@ struct _GBinPortion { GObject parent; /* A laisser en premier */ - unsigned int level; /* Profondeur de la portion */ - GBinPortion *container; /* Portion parente ou racine */ + const unsigned int *level; /* Profondeur de la portion */ char *code; /* Code de la couleur de fond */ char *desc; /* Désignation humaine */ mrange_t range; /* Emplacement dans le code */ - vmpa2t addr; /* Emplacement dans le code */ /* TODO : clean */ - off_t size; /* Taille de la partie */ /* TODO : clean */ PortionAccessRights rights; /* Droits d'accès */ - GBinPortion **sub_portions; /* Portions incluses */ - size_t sub_count; /* Quantité d'inclusions */ - -#ifdef DEBUG - unsigned int valid; /* Instructions reconnues */ - unsigned int db; /* Instructions non traduites */ -#endif - }; /* Portion de données binaires quelconques (classe) */ @@ -75,10 +65,10 @@ struct _GBinPortionClass }; -/* Initialise la classe des blocs de données binaires. */ +/* Initialise la classe des portions de données binaires. */ static void g_binary_portion_class_init(GBinPortionClass *); -/* Initialise une instance de bloc de données binaires. */ +/* Initialise une instance de portion de données binaires. */ static void g_binary_portion_init(GBinPortion *); /* Supprime toutes les références externes. */ @@ -88,10 +78,57 @@ static void g_binary_portion_dispose(GBinPortion *); 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 *, unsigned int); +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(GBinPortion *, GBinPortion *, const GdkRectangle *, GdkRectangle *); +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 *); + + @@ -100,7 +137,7 @@ static bool g_binary_portion_compute_sub_area(GBinPortion *, GBinPortion *, cons /* ---------------------------------------------------------------------------------- */ -/* Indique le type défini par la GLib pour les blocs de données. */ +/* Indique le type défini par la GLib pour les portions de données binaires. */ G_DEFINE_TYPE(GBinPortion, g_binary_portion, G_TYPE_OBJECT); @@ -108,7 +145,7 @@ G_DEFINE_TYPE(GBinPortion, g_binary_portion, G_TYPE_OBJECT); * * * Paramètres : klass = classe à initialiser. * * * -* Description : Initialise la classe des blocs de données binaires. * +* Description : Initialise la classe des portions de données binaires. * * * * Retour : - * * * @@ -133,7 +170,7 @@ static void g_binary_portion_class_init(GBinPortionClass *klass) * * * Paramètres : portion = instance à initialiser. * * * -* Description : Initialise une instance de bloc de données binaires. * +* Description : Initialise une instance de portion de données binaires. * * * * Retour : - * * * @@ -143,7 +180,7 @@ static void g_binary_portion_class_init(GBinPortionClass *klass) static void g_binary_portion_init(GBinPortion *portion) { - portion->level = 0; + portion->level = NULL; } @@ -162,11 +199,6 @@ static void g_binary_portion_init(GBinPortion *portion) static void g_binary_portion_dispose(GBinPortion *portion) { - size_t i; /* Boucle de parcours */ - - for (i = 0; i < portion->sub_count; i++) - g_object_unref(G_OBJECT(portion->sub_portions[i])); - G_OBJECT_CLASS(g_binary_portion_parent_class)->dispose(G_OBJECT(portion)); } @@ -191,9 +223,6 @@ static void g_binary_portion_finalize(GBinPortion *portion) if (portion->desc != NULL) free(portion->desc); - if (portion->sub_portions != NULL) - free(portion->sub_portions); - G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion)); } @@ -205,7 +234,7 @@ static void g_binary_portion_finalize(GBinPortion *portion) * * * Description : Crée une description de partie de code vierge. * * * -* Retour : - * +* Retour : Instance mise en place. * * * * Remarques : - * * * @@ -226,6 +255,26 @@ GBinPortion *g_binary_portion_new(const char *code) /****************************************************************************** * * +* 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; + +} + + +/****************************************************************************** +* * * Paramètres : a = premières informations à consulter. * * b = secondes informations à consulter. * * * @@ -240,15 +289,32 @@ GBinPortion *g_binary_portion_new(const char *code) 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' */ - if ((*a)->level < (*b)->level) - result = -1; + addr_a = get_mrange_addr(&(*a)->range); + addr_b = get_mrange_addr(&(*b)->range); - else if ((*a)->level > (*b)->level) - result = 1; + result = cmp_vmpa(addr_a, addr_b); - else - result = cmp_mrange(&(*a)->range, &(*b)->range); + 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; @@ -312,9 +378,6 @@ const char *g_binary_portion_get_desc(const GBinPortion *portion) void g_binary_portion_set_values(GBinPortion *portion, const vmpa2t *addr, phys_t size) { - copy_vmpa(&portion->addr, addr); - portion->size = size; - init_mrange(&portion->range, addr, size); } @@ -380,77 +443,8 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* sub = portion à inclure dans la définition courante. * -* * -* Description : Procède à l'inclusion d'une portion dans une autre. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub) -{ - portion->sub_portions = (GBinPortion **)realloc(portion->sub_portions, - ++portion->sub_count * sizeof(GBinPortion *)); - - portion->sub_portions[portion->sub_count - 1] = sub; - - g_binary_portion_set_level(sub, portion->level + 1); - -} - - -/****************************************************************************** -* * -* 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, unsigned int level) -{ - size_t i; /* Boucle de parcours */ - - portion->level = level; - - for (i = 0; i < portion->sub_count; i++) - g_binary_portion_set_level(portion->sub_portions[i], level + 1); - -} - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* * -* Description : Indique le niveau de profondeur d'une portion donnée. * -* * -* Retour : Niveau de profondeur positif ou nul. * -* * -* Remarques : - * -* * -******************************************************************************/ - -unsigned int g_binary_portion_get_level(GBinPortion *portion) -{ - return portion->level; - -} - - -/****************************************************************************** -* * * Paramètres : portion = portion mère à consulter. * -* sub = portion fille à traiter. * +* 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. * * * @@ -462,16 +456,23 @@ unsigned int g_binary_portion_get_level(GBinPortion *portion) * * ******************************************************************************/ -static bool g_binary_portion_compute_sub_area(GBinPortion *portion, GBinPortion *sub, const GdkRectangle *area, GdkRectangle *sub_area) +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 (sub->size == 0) return false; + 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 + (get_phy_addr(&sub->addr) * area->width) / portion->size; - sub_area->width = (sub->size * area->width) / portion->size; + sub_area->x = area->x + (start * area->width) / full; + sub_area->width = (length * area->width) / full; return true; @@ -480,27 +481,30 @@ static bool g_binary_portion_compute_sub_area(GBinPortion *portion, GBinPortion /****************************************************************************** * * -* Paramètres : portion = première portion amorçant la visite. * -* visitor = fonction à appeler à chaque étape de la descente. * -* data = adresse pointant vers des données de l'utilisateur.* +* Paramètres : portion = portion mère à consulter. * +* addr = adresse du point de recherche. * * * -* Description : Parcours un ensemble de portions binaires. * +* Description : Détermine si une portion contient une adresse donnée. * * * -* Retour : true si la visite a été jusqu'à son terme, false sinon. * +* Retour : true ou false selon le résultat. * * * * Remarques : - * * * ******************************************************************************/ -bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void *data) +static bool g_portion_layer_contains_addr(const GBinPortion *portion, const vmpa2t *addr) { - bool result; /* Etat à retourner */ - size_t i; /* Boucle de parcours */ + bool result; /* Bilan à retourner */ + + result = false; - result = visitor(portion, data); + /* Portion non allouée en mémoire -> adresse nulle ; on écarte */ + if (get_virt_addr(get_mrange_addr(&portion->range)) == 0) + goto not_found; - for (i = 0; i < portion->sub_count && result; i++) - result = g_binary_portion_visit(portion->sub_portions[i], visitor, data); + result = mrange_contains_addr(&portion->range, addr); + + not_found: return result; @@ -509,107 +513,80 @@ bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* x = abscisse du point de recherche. * -* y = ordonnée du point de recherche. * -* area = étendue de portion mère, puis celle trouvée. [OUT] * +* Paramètres : portion = description de partie à consulter. * +* buffer = espace où placer ledit contenu. * +* msize = taille idéale des positions et adresses; * * * -* Description : Recherche la portion présente à un point donné. * +* Description : Insère dans un tampon une description de portion. * * * -* Retour : Portion trouvée à l'endroit indiqué. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRectangle *area) +void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, MemoryDataSize msize) { - GBinPortion *result; /* Portion à retourner */ - size_t i; /* Boucle de parcours */ - GBinPortion *sub; /* Portion incluse à traiter */ - GdkRectangle sub_area; /* Etendue d'une sous-portion */ - - result = NULL; + mrange_t range; /* Couverture à fournir */ + GBufferLine *line; /* Nouvelle ligne à éditer */ + char rights[64]; /* Traduction en texte */ - for (i = 0; i < portion->sub_count && !result; i++) - { - sub = portion->sub_portions[i]; + /* On ne traite pas les portions anonymes ! */ + if (portion->desc == NULL) return; - if (!g_binary_portion_compute_sub_area(portion, sub, area, &sub_area)) - continue; + init_mrange(&range, get_mrange_addr(&portion->range), 0); - if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) - { - result = sub; - *area = sub_area; - } + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); - } + g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); - if (result == NULL) - result = portion; + /* Séparation */ - return result; + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); -} + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, + "; ======================================================", 56, RTT_COMMENT); + /* Retour à la ligne */ -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* 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. * -* * -* Retour : Portion trouvée à l'endroit indiqué. * -* * -* Remarques : - * -* * -******************************************************************************/ + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); -GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *addr, GdkRectangle *area) -{ - GBinPortion *result; /* Portion à retourner */ - size_t i; /* Boucle de parcours #1 */ - GBinPortion *sub; /* Portion incluse à traiter */ - GdkRectangle sub_area; /* Etendue d'une sous-portion */ - size_t j; /* Boucle de parcours #2 */ + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); - result = NULL; + /* Description */ - for (i = 0; i < portion->sub_count && result == NULL; i++) - { - sub = portion->sub_portions[i]; + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); - /* FIXME : cmp ? */ + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - /* Portion non allouée en mémoire -> adresse nulle ; on écarte */ - if (get_virt_addr(&sub->addr) == 0) - continue; + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); - if (get_virt_addr(addr) < get_virt_addr(&sub->addr) - || get_virt_addr(addr) >= (get_virt_addr(&sub->addr) + sub->size)) - continue; + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT); - if (!g_binary_portion_compute_sub_area(portion, sub, area, &sub_area)) - continue; + snprintf(rights, sizeof(rights), " (%s%s%s%s)", + _("rights: "), + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); - for (j = 0; j < sub->sub_count && !result; j++) - result = g_binary_portion_find_at_addr(sub->sub_portions[j], addr, &sub_area); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT); - if (result == NULL) - { - result = sub; - *area = sub_area; - } + /* Retour à la ligne */ - } + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); - if (result == NULL) - result = portion; + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); - return result; + line = g_code_buffer_append_new_line(buffer, &range); + g_buffer_line_fill_mrange(line, msize, msize); } @@ -617,79 +594,132 @@ GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *a /****************************************************************************** * * * Paramètres : portion = description de partie à mettre à jour. * -* x = abscisse du point de recherche. * -* area = étendue de représentation de la portion mère. * -* addr = adresse correspondante. [OUT] * +* tooltip = astuce à compléter. [OUT] * * * -* Description : Fournit la position correspondant à une adresse donnée. * +* Description : Prépare une astuce concernant une portion pour son affichage.* * * -* Retour : Succès de la traduction. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_binary_portion_get_addr_from_pos(GBinPortion *portion, gint x, const GdkRectangle *area, vmpa2t *addr) +void g_binary_portion_query_tooltip(GBinPortion *portion, GtkTooltip *tooltip) { - GdkRectangle owner_area; /* Aire de contenance */ - GBinPortion *owner; /* Conteneur propriétaire */ + char *markup; /* Description à construire */ + VMPA_BUFFER(value); /* Traduction en texte */ - owner_area = *area; + /* Nom */ - owner = g_binary_portion_find_at_pos(portion, x, &owner_area); - if (owner == NULL) return false; + if (portion->desc != NULL) + { + markup = strdup(""); + markup = stradd(markup, portion->desc); + markup = stradd(markup, "\n"); + markup = stradd(markup, "\n"); - copy_vmpa(addr, &owner->addr); + } + else markup = strdup(""); - advance_vmpa(addr, (owner->size * (x - owner_area.x)) / owner_area.width); + markup = stradd(markup, "taille : "); + mrange_length_to_string(&portion->range, MDS_UNDEFINED, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, "\n"); - return true; + /* Localisation */ -} + markup = stradd(markup, ""); + markup = stradd(markup, _("Localisation")); + markup = stradd(markup, "\n"); + markup = stradd(markup, _("physical: from ")); -/****************************************************************************** + mrange_phys_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, _(" to ")); + mrange_phys_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, "\n"); + + markup = stradd(markup, _("memory: from ")); + + mrange_virt_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, _(" to ")); + mrange_virt_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); + markup = stradd(markup, value); + + markup = stradd(markup, "\n\n"); + + /* Droits d'accès */ + + markup = stradd(markup, ""); + markup = stradd(markup, _("Rights")); + markup = stradd(markup, "\n"); + + snprintf(value, 2 * VMPA_MAX_SIZE, "%s%s%s", + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); + + markup = stradd(markup, value); + + /* Impression finale */ + + gtk_tooltip_set_markup(tooltip, markup); + free(markup); + +} + + +/****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* addr = adresse du point de recherche. * -* area = étendue de représentation de la portion mère. * -* x = position correspondante. [OUT] * +* Paramètres : portion = description de partie à consulter. * +* cr = contexte graphique pour le dessin. * +* area = étendue mise à disposition. * * * -* Description : Fournit l'adresse correspondant à une position donnée. * +* Description : Représente la portion sur une bande dédiée. * * * -* Retour : Succès de la traduction. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_binary_portion_get_pos_from_addr(GBinPortion *portion, const vmpa2t *addr, const GdkRectangle *area, gint *x) +void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) { - GdkRectangle owner_area; /* Aire de contenance */ - GBinPortion *owner; /* Conteneur propriétaire */ - off_t diff; /* Décallage à appliquer */ + //cairo_set_line_width(cr, 1.0); - owner_area = *area; + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); - owner = g_binary_portion_find_at_addr(portion, addr, &owner_area); - if (owner == NULL) return false; + gtk_style_context_save(context); - diff = compute_vmpa_diff(addr, &owner->addr); + gtk_style_context_add_class(context, portion->code); - *x = owner_area.x + (diff * owner_area.width) / owner->size; + gtk_render_background(context, cr, area->x, area->y, area->width, area->height); - return true; + gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); + + gtk_style_context_restore(context); } + +/* ---------------------------------------------------------------------------------- */ +/* 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 : portion = description de partie à consulter. * -* buffer = espace où placer ledit contenu. * -* msize = taille idéale des positions et adresses; * +* Paramètres : klass = classe à initialiser. * * * -* Description : Insère dans un tampon une description de portion. * +* Description : Initialise la classe des couches de portions binaires. * * * * Retour : - * * * @@ -697,219 +727,487 @@ bool g_binary_portion_get_pos_from_addr(GBinPortion *portion, const vmpa2t *addr * * ******************************************************************************/ -void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, MemoryDataSize msize) +static void g_portion_layer_class_init(GPortionLayerClass *klass) { - mrange_t range; /* Couverture à fournir */ - GBufferLine *line; /* Nouvelle ligne à éditer */ - char rights[64]; /* Traduction en texte */ + GObjectClass *object; /* Autre version de la classe */ - /* On ne traite pas les portions anonymes ! */ - if (portion->desc == NULL) return; + object = G_OBJECT_CLASS(klass); - init_mrange(&range, get_mrange_addr(&portion->range), 0); + object->dispose = (GObjectFinalizeFunc/* ! */)g_portion_layer_dispose; + object->finalize = (GObjectFinalizeFunc)g_portion_layer_finalize; - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); +} - /* Séparation */ - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); +/****************************************************************************** +* * +* Paramètres : layer = instance à initialiser. * +* * +* Description : Initialise une instance de couche de portions binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, - "; ======================================================", 56, RTT_COMMENT); +static void g_portion_layer_init(GPortionLayer *layer) +{ + layer->level = 0; - /* Retour à la ligne */ +} - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); +/****************************************************************************** +* * +* Paramètres : layer = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - /* Description */ +static void g_portion_layer_dispose(GPortionLayer *layer) +{ + size_t i; /* Boucle de parcours */ - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); + if (layer->sub_layer != NULL) + g_object_unref(G_OBJECT(layer->sub_layer)); - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + for (i = 0; i < layer->count; i++) + g_object_unref(G_OBJECT(layer->portions[i])); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); + G_OBJECT_CLASS(g_portion_layer_parent_class)->dispose(G_OBJECT(layer)); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, portion->desc, strlen(portion->desc), RTT_COMMENT); +} - snprintf(rights, sizeof(rights), " (%s%s%s%s)", - _("rights: "), - portion->rights & PAC_READ ? "r" : "-", - portion->rights & PAC_WRITE ? "w" : "-", - portion->rights & PAC_EXEC ? "x" : "-"); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, rights, strlen(rights), RTT_COMMENT); +/****************************************************************************** +* * +* Paramètres : layer = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - /* Retour à la ligne */ +static void g_portion_layer_finalize(GPortionLayer *layer) +{ + if (layer->portions != NULL) + free(layer->portions); - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); + G_OBJECT_CLASS(g_portion_layer_parent_class)->finalize(G_OBJECT(layer)); - g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_COMMENT); +} - line = g_code_buffer_append_new_line(buffer, &range); - g_buffer_line_fill_mrange(line, msize, msize); + +/****************************************************************************** +* * +* 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; } /****************************************************************************** * * -* Paramètres : portion = description de partie à mettre à jour. * -* x = abscisse du point de recherche. * -* y = ordonnée du point de recherche. * -* area = étendue de représentation de la portion mère. * -* tooltip = astuce à compléter. [OUT] * +* Paramètres : layer = couche rassemblant des portions à modifier. * +* Paramètres : sub = couche inférieure à rattacher à la couche courante. * * * -* Description : Prépare une astuce concernant une portion pour son affichage.* +* Description : Attache une couche à une autre en tant que couche inférieure.* * * -* Retour : TRUE pour valider l'affichage. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -gboolean g_binary_portion_query_tooltip(GBinPortion *portion, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) +void g_portion_layer_attach_sub(GPortionLayer *layer, GPortionLayer *sub) { - GBinPortion *selected; /* Portion à décrire ici */ - char *markup; /* Description à construire */ - GBinPortion *iter; /* Remontée hiérarchique */ - char value[2 * VMPA_MAX_SIZE]; /* Traduction en texte */ + void set_layers_length(GPortionLayer *parent, GPortionLayer *child) + { + if (child->length == NO_LENGTH_YET) + { + assert(parent->length != NO_LENGTH_YET); - selected = g_binary_portion_find_at_pos(portion, x, (GdkRectangle []) { *area }); + child->length = parent->length; - /* Nom */ + if (child->sub_layer != NULL) + set_layers_length(child, child->sub_layer); - if (selected->desc != NULL) - { - markup = strdup(""); - markup = stradd(markup, selected->desc); - markup = stradd(markup, "\n"); + } - for (iter = selected->container; iter != NULL; iter = iter->container) - if (iter->desc != NULL) - { - markup = stradd(markup, selected->desc); - markup = stradd(markup, "\n"); - } + } - markup = stradd(markup, "\n"); + 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); } - else markup = strdup(""); - markup = stradd(markup, "taille : "); - snprintf(value, 2 * VMPA_MAX_SIZE, OFF_FMT, OFF_CAST(selected->size)); - markup = stradd(markup, value); - markup = stradd(markup, "\n"); + set_layers_length(layer, sub); - /* Localisation */ + set_layers_depth(layer, sub); - markup = stradd(markup, ""); - markup = stradd(markup, _("Localisation")); - markup = stradd(markup, "\n"); + layer->sub_layer = sub; - markup = stradd(markup, _("physical: from ")); - snprintf(value, 2 * VMPA_MAX_SIZE, OFF_FMT, OFF_CAST(get_phy_addr(&selected->addr))); - markup = stradd(markup, value); - markup = stradd(markup, _(" to ")); - snprintf(value, 2 * VMPA_MAX_SIZE, OFF_FMT, OFF_CAST(get_phy_addr(&selected->addr) + selected->size)); - markup = stradd(markup, value); - markup = stradd(markup, "\n"); +} - markup = stradd(markup, _("memory: from ")); -#if 0 - snprintf(value, 2 * VMPA_MAX_SIZE, VMPA_FMT_LONG, VMPA_CAST(selected->addr)); - markup = stradd(markup, value); - markup = stradd(markup, _(" to ")); - snprintf(value, 2 * VMPA_MAX_SIZE, VMPA_FMT_LONG, VMPA_CAST(selected->addr + selected->size)); - markup = stradd(markup, value); -#endif - markup = stradd(markup, "\n\n"); - /* Droits d'accès */ +/****************************************************************************** +* * +* Paramètres : layer = couche rassemblant les portions d'un même niveau. * +* portion = portion à inclure dans la définition courante. * +* * +* Description : Procède à l'inclusion d'une portion dans une couche. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - markup = stradd(markup, ""); - markup = stradd(markup, _("Rights")); - markup = stradd(markup, "\n"); +void g_portion_layer_include(GPortionLayer *layer, GBinPortion *portion) +{ + layer->portions = (GBinPortion **)realloc(layer->portions, + ++layer->count * sizeof(GBinPortion *)); - snprintf(value, 2 * VMPA_MAX_SIZE, "%s%s%s", - selected->rights & PAC_READ ? "r" : "-", - selected->rights & PAC_WRITE ? "w" : "-", - selected->rights & PAC_EXEC ? "x" : "-"); + layer->portions[layer->count - 1] = portion; - markup = stradd(markup, value); + g_binary_portion_set_level(portion, &layer->level); - /* Impression finale */ + qsort(layer->portions, layer->count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); - gtk_tooltip_set_markup(tooltip, markup); - free(markup); +} - return TRUE; + +/****************************************************************************** +* * +* Paramètres : layer = couche première à parcourir intégralement. * +* count = nombre de portions trouvées et renvoyées. [OUT] * +* * +* Description : Fournit une liste triée de portions d'un binaire. * +* * +* Retour : Liste de définitions de zones à libérer après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPortion **g_portion_layer_collect_all_portions(const GPortionLayer *layer, size_t *count) +{ + GBinPortion **result; /* Liste construite à renvoyer */ + + 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 */ + + start = *c; + *c += l->count; + + lst = (GBinPortion **)realloc(lst, *c * sizeof(GBinPortion *)); + + for (i = 0; i < l->count; i++) + lst[start + i] = l->portions[i]; + + return lst; + + } + + result = do_collect(layer, NULL, count); + + qsort(result, *count, sizeof(GBinPortion *), (__compar_fn_t)g_binary_portion_compare); + + return result; } /****************************************************************************** * * -* Paramètres : portion = description de partie à consulter. * -* cr = contexte graphique pour le dessin. * -* area = étendue mise à disposition. * +* 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] * * * -* Description : Représente la portion sur une bande dédiée. * +* Description : Recherche la portion présente à un point donné. * * * -* Retour : - * +* Retour : Portion trouvée à l'endroit indiqué. * * * * Remarques : - * * * ******************************************************************************/ -void g_binary_portion_draw(GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) +GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *layer, gint x, GdkRectangle *area) { + GBinPortion *result; /* Portion à retourner */ size_t i; /* Boucle de parcours */ - GBinPortion *sub; /* Portion incluse à montrer */ + GBinPortion *sub; /* Portion incluse à traiter */ GdkRectangle sub_area; /* Etendue d'une sous-portion */ - /* Dessin de la portion courante */ + if (layer->sub_layer != NULL) + result = g_portion_layer_find_portion_at_pos(layer->sub_layer, x, area); + else + result = NULL; - //cairo_set_line_width(cr, 1.0); + for (i = 0; i < layer->count && result == NULL; i++) + { + sub = layer->portions[i]; - cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) + continue; - gtk_style_context_save(context); + if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) + { + result = sub; + *area = sub_area; + } - gtk_style_context_add_class(context, portion->code); + } - gtk_render_background(context, cr, area->x, area->y, area->width, area->height); + return result; - gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); +} - gtk_style_context_restore(context); - /* Dessin des portions incluses */ +/****************************************************************************** +* * +* 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] * +* * +* Description : Recherche la portion présente à une adresse donnée. * +* * +* Retour : Portion trouvée à l'endroit indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ - sub_area.y = area->y; - sub_area.height = area->height; +GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *layer, const vmpa2t *addr, GdkRectangle *area) +{ + GBinPortion *result; /* Portion à retourner */ + 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; - for (i = 0; i < portion->sub_count; i++) + for (i = 0; i < layer->count && result == NULL; i++) { - sub = portion->sub_portions[i]; + sub = layer->portions[i]; - if (!g_binary_portion_compute_sub_area(portion, sub, area, &sub_area)) + if (!g_portion_layer_contains_addr(sub, addr)) + continue; + + if (!g_binary_portion_compute_sub_area(sub, layer->length, area, &sub_area)) + continue; + + result = sub; + *area = sub_area; + + } + + return result; + +} + + +/****************************************************************************** +* * +* 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] * +* * +* Description : Fournit la position correspondant à une adresse donnée. * +* * +* Retour : Succès de la traduction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_portion_layer_get_addr_from_pos(GPortionLayer *layer, 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); + 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); + + return true; + +} + + +/****************************************************************************** +* * +* 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] * +* * +* Description : Fournit l'adresse correspondant à une position donnée. * +* * +* Retour : Succès de la traduction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_portion_layer_get_pos_from_addr(GPortionLayer *layer, const vmpa2t *addr, const GdkRectangle *area, gint *x) +{ + GdkRectangle owner_area; /* Aire de contenance */ + GBinPortion *owner; /* Conteneur propriétaire */ + phys_t diff; /* Décallage à appliquer */ + + owner_area = *area; + + owner = g_portion_layer_find_portion_at_addr(layer, 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; + +} + + +/****************************************************************************** +* * +* 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; + +} + + +/****************************************************************************** +* * +* Paramètres : layer = couche de portions à consulter. * +* x = abscisse du point de recherche. * +* y = ordonnée du point de recherche. * +* area = étendue de représentation de la portion mère. * +* tooltip = astuce à compléter. [OUT] * +* * +* Description : Prépare une astuce concernant une portion pour son affichage.* +* * +* Retour : TRUE pour valider l'affichage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gboolean g_portion_layer_query_tooltip(const GPortionLayer *layer, 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 }); + if (selected == NULL) return FALSE; + + g_binary_portion_query_tooltip(selected, tooltip); + + return TRUE; + +} + + +/****************************************************************************** +* * +* 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); + } diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h index f92b87e..e5c7830 100644 --- a/src/glibext/gbinportion.h +++ b/src/glibext/gbinportion.h @@ -36,6 +36,9 @@ +/* ------------------------------- PORTION DE BINAIRE ------------------------------- */ + + /** * Couleurs de représentation. */ @@ -73,11 +76,7 @@ typedef enum _PortionAccessRights } PortionAccessRights; -/* Fonction appelée à chaque visite de portion.*/ -typedef bool (* visit_portion_fc) (GBinPortion *, void *); - - -/* Indique le type défini par la GLib pour les blocs de données. */ +/* Indique le type défini par la GLib pour les portions de données binaires. */ GType g_binary_portion_get_type(void); /* Crée une description de partie de code vierge. */ @@ -104,35 +103,77 @@ void g_binary_portion_set_rights(GBinPortion *, PortionAccessRights); /* Fournit les droits associés à une partie de code. */ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *); -/* Procède à l'inclusion d'une portion dans une autre. */ -void g_binary_portion_include(GBinPortion *, GBinPortion *); +/* Insère dans un tampon une description de portion. */ +void g_binary_portion_print(const GBinPortion *, GCodeBuffer *, MemoryDataSize); -/* Indique le niveau de profondeur d'une portion donnée. */ -unsigned int g_binary_portion_get_level(GBinPortion *); +/* Prépare une astuce concernant une portion pour son affichage. */ +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 *); + + + +/* -------------------------- 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)) -/* Parcours un ensemble de portions binaires. */ -bool g_binary_portion_visit(GBinPortion *, visit_portion_fc, void *); + +/* Couche de portions binaires quelconques (instance) */ +typedef struct _GPortionLayer GPortionLayer; + +/* Couche de portions binaires quelconques (classe) */ +typedef struct _GPortionLayerClass GPortionLayerClass; + + +/* Taille à définir lors d'un rattachement */ +#define NO_LENGTH_YET VMPA_NO_PHYSICAL + + +/* Indique le type défini par la GLib pour les couches de portions binaires. */ +GType g_portion_layer_get_type(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 *); + +/* 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_binary_portion_find_at_pos(GBinPortion *, gint, GdkRectangle *); +GBinPortion *g_portion_layer_find_portion_at_pos(const GPortionLayer *, gint, GdkRectangle *); /* Recherche la portion présente à une adresse donnée. */ -GBinPortion *g_binary_portion_find_at_addr(GBinPortion *, const vmpa2t *, GdkRectangle *); +GBinPortion *g_portion_layer_find_portion_at_addr(const GPortionLayer *, const vmpa2t *, GdkRectangle *); /* Fournit la position correspondant à une adresse donnée. */ -bool g_binary_portion_get_addr_from_pos(GBinPortion *, gint, const GdkRectangle *, vmpa2t *); +bool g_portion_layer_get_addr_from_pos(GPortionLayer *, gint, const GdkRectangle *, vmpa2t *); /* Fournit l'adresse correspondant à une position donnée. */ -bool g_binary_portion_get_pos_from_addr(GBinPortion *, const vmpa2t *, const GdkRectangle *, gint *); +bool g_portion_layer_get_pos_from_addr(GPortionLayer *, const vmpa2t *, const GdkRectangle *, gint *); -/* Insère dans un tampon une description de portion. */ -void g_binary_portion_print(const GBinPortion *, GCodeBuffer *, MemoryDataSize); +/* 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 *); /* Prépare une astuce concernant une portion pour son affichage. */ -gboolean g_binary_portion_query_tooltip(GBinPortion *, gint, gint, const GdkRectangle *, GtkTooltip *); +gboolean g_portion_layer_query_tooltip(const GPortionLayer *, gint, gint, const GdkRectangle *, GtkTooltip *); -/* Représente la portion sur une bande dédiée. */ -void g_binary_portion_draw(GBinPortion *, GtkStyleContext *, cairo_t *, const GdkRectangle *); +/* Représente une couche de portions sur une bande dédiée. */ +void g_portion_layer_draw(const GPortionLayer *, GtkStyleContext *, cairo_t *, const GdkRectangle *); diff --git a/src/gtkext/gtkbinarystrip.c b/src/gtkext/gtkbinarystrip.c index e0016d2..0ad0763 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 */ - GBinPortion *portions; /* Portions binaires à dessiner*/ + GPortionLayer *layer; /* Couche première de portions */ GdkRectangle area; /* Surface du composant */ GTK_WIDGET_CLASS(gtk_binary_strip_parent_class)->size_allocate(widget, allocation); @@ -222,16 +222,18 @@ static void gtk_binary_strip_size_allocate(GtkWidget *widget, GtkAllocation *all return; format = g_loaded_binary_get_format(strip->binary); - portions = g_exe_format_get_portions(format); + layer = g_exe_format_get_main_layer(format); area.x = 0; area.y = 0; area.width = allocation->width; area.height = allocation->height; - if (!g_binary_portion_get_pos_from_addr(portions, &strip->cursor_addr, &area, &strip->cursor_pos)) + if (!g_portion_layer_get_pos_from_addr(layer, &strip->cursor_addr, &area, &strip->cursor_pos)) strip->cursor_pos = 0; + g_object_unref(G_OBJECT(layer)); + } @@ -254,7 +256,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 */ - GBinPortion *portions; /* Portions binaires à dessiner*/ + GPortionLayer *layer; /* Couche première de portions */ GdkRectangle area; /* Surface du composant */ vmpa2t addr; /* Adresse à sélectionner */ @@ -269,27 +271,26 @@ static gboolean gtk_binary_strip_button_release(GtkWidget *widget, GdkEventButto strip = GTK_BINARY_STRIP(widget); format = g_loaded_binary_get_format(strip->binary); - portions = g_exe_format_get_portions(format); + layer = g_exe_format_get_main_layer(format); area.x = 0; area.y = 0; area.width = width; area.height = height; - if (g_binary_portion_get_addr_from_pos(portions, event->x, &area, &addr)) + if (g_portion_layer_get_addr_from_pos(layer, event->x, &area, &addr)) { copy_vmpa(&strip->cursor_addr, &addr); strip->cursor_pos = event->x; gtk_widget_queue_draw(GTK_WIDGET(strip)); - printf("got :: %p\n", &addr); - printf(" -> 0x%x 0x%x\n", (unsigned int)get_phy_addr(&addr), (unsigned int)get_virt_addr(&addr)); - g_signal_emit_by_name(strip, "select-address"); } + g_object_unref(G_OBJECT(layer)); + return FALSE; } @@ -312,7 +313,7 @@ static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr) { GtkBinaryStrip *strip; /* Autre vision du composant */ GExeFormat *format; /* Format du binaire */ - GBinPortion *portions; /* Portions binaires à dessiner*/ + GPortionLayer *layer; /* Couche première de portions */ GdkRectangle full; /* Taille totale de la surface */ GtkStyleContext *context; /* Contexte du thème actuel */ GdkRGBA *color; /* Couleur du curseur */ @@ -322,11 +323,11 @@ static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr) if (strip->binary == NULL) return FALSE; - format = g_loaded_binary_get_format(strip->binary); - portions = g_exe_format_get_portions(format); - /* Dessin des portions de binaire */ + format = g_loaded_binary_get_format(strip->binary); + layer = g_exe_format_get_main_layer(format); + full.x = 0; full.y = 1; full.width = gtk_widget_get_allocated_width(widget); @@ -334,7 +335,9 @@ static gboolean gtk_binary_strip_draw(GtkWidget *widget, cairo_t *cr) context = gtk_widget_get_style_context(widget); - g_binary_portion_draw(portions, context, cr, &full); + g_portion_layer_draw(layer, context, cr, &full); + + g_object_unref(G_OBJECT(layer)); /* Dessin de la position */ @@ -389,7 +392,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 */ - GBinPortion *portions; /* Portions binaires à dessiner*/ + GPortionLayer *layer; /* Couches binaires à consulter*/ GdkRectangle area; /* Surface du composant */ if (keyboard) return FALSE; @@ -399,14 +402,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); - portions = g_exe_format_get_portions(format); + layer = g_exe_format_get_main_layer(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_binary_portion_query_tooltip(portions, x, y, &area, tooltip); + result = g_portion_layer_query_tooltip(layer, x, y, &area, tooltip); + + g_object_unref(G_OBJECT(layer)); } else result = FALSE; diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c index e9a61d8..148dd03 100644 --- a/src/gtkext/gtkstatusstack.c +++ b/src/gtkext/gtkstatusstack.c @@ -462,7 +462,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 */ - GBinPortion *portions; /* Portions binaires existantes*/ + GPortionLayer *layer; /* 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 */ @@ -491,9 +491,9 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL /* Zone d'appartenance */ - portions = g_exe_format_get_portions(format); + layer = g_exe_format_get_main_layer(format); - portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { }); + portion = g_portion_layer_find_portion_at_addr(layer, addr, (GdkRectangle []) { }); text = g_binary_portion_get_desc(portion); @@ -502,6 +502,8 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL else info->segment = strdup(_("Binary")); + g_object_unref(G_OBJECT(layer)); + /* Adresses de base */ vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL); -- cgit v0.11.2-87-g4458