From b639c1f4abca32152bf88f8fd47a9cd114da701b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 22 Feb 2015 11:35:09 +0000 Subject: Created a dialog box to select an entry point to display. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@476 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 35 ++++ plugins/pychrysa/glibext/bufferline.c | 2 +- src/arch/instruction.c | 2 + src/arch/vmpa.c | 41 ++++ src/arch/vmpa.h | 19 ++ src/dialogs/Makefile.am | 1 + src/dialogs/gotox.c | 367 ++++++++++++++++++++++++++++++++++ src/dialogs/gotox.h | 44 ++++ src/glibext/gbinportion.c | 15 +- src/glibext/gbufferline.c | 56 +++++- src/glibext/gbufferline.h | 10 +- src/glibext/gbuffersegment.c | 76 ++++++- src/glibext/gbuffersegment.h | 2 +- src/glibext/gcodebuffer.c | 90 ++++++++- src/glibext/gcodebuffer.h | 2 +- src/gui/menus/binary.c | 57 ++++++ 16 files changed, 790 insertions(+), 29 deletions(-) create mode 100644 src/dialogs/gotox.c create mode 100644 src/dialogs/gotox.h diff --git a/ChangeLog b/ChangeLog index 5949c37..6ebe5de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +15-02-22 Cyrille Bagard + + * plugins/pychrysa/glibext/bufferline.c: + Update code. + + * src/arch/instruction.c: + Mark buffer lines as containing code. + + * src/arch/vmpa.c: + * src/arch/vmpa.h: + Provide helpers for dealing with GLib. Convert locations into names and offsets. + + * src/dialogs/gotox.c: + * src/dialogs/gotox.h: + Nen entries: create a dialog box to select an entry point to display. + + * src/dialogs/Makefile.am: + Add the 'gotox.[ch]' files to libdialogs_la_SOURCES. + + * src/glibext/gbinportion.c: + Update code. + + * src/glibext/gbufferline.c: + * src/glibext/gbufferline.h: + * src/glibext/gbuffersegment.c: + * src/glibext/gbuffersegment.h: + Export parts of line content as text using optional markup. + + * src/glibext/gcodebuffer.c: + * src/glibext/gcodebuffer.h: + Look for the first code lines located at a given address. Update code. + + * src/gui/menus/binary.c: + Add a menu entry to select one binary entry. + 15-02-18 Cyrille Bagard * src/analysis/disass/area.c: diff --git a/plugins/pychrysa/glibext/bufferline.c b/plugins/pychrysa/glibext/bufferline.c index e4b7216..d5b8b13 100644 --- a/plugins/pychrysa/glibext/bufferline.c +++ b/plugins/pychrysa/glibext/bufferline.c @@ -61,7 +61,7 @@ static PyObject *py_buffer_line_get_text(PyObject *self, PyObject *args) char *text; /* Texte reconstruit à libérer */ line = G_BUFFER_LINE(pygobject_get(self)); - text = g_buffer_line_get_text(line); + text = "";//g_buffer_line_get_text(line); result = PyString_FromString(text); diff --git a/src/arch/instruction.c b/src/arch/instruction.c index 67fd184..c9811cf 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -792,6 +792,8 @@ static GBufferLine *_g_arch_instruction_print(const GArchInstruction *instr, GCo result = g_code_buffer_append_new_line(buffer, &instr->range); + g_buffer_line_add_flag(result, BLF_HAS_CODE); + g_buffer_line_fill_for_instr(result, msize/* TODO ! */, msize, content, get_mrange_length(&instr->range), true); diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c index c479319..67be9a9 100644 --- a/src/arch/vmpa.c +++ b/src/arch/vmpa.c @@ -641,6 +641,47 @@ bool prepare_vmpa_db_statement(const vmpa2t *addr, bool create, bound_value **va /* ---------------------------------------------------------------------------------- */ +/* AIDES FONCTIONNELLES AUXILIAIRES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : label = désignation humaine d'unn symbole de base. * +* offset = décalage déterminé à faie apparaître au besoin. * +* * +* Description : Construit une désignation de symbole avec décalage. * +* * +* Retour : Chaîne de caractères constituée à libérer après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *make_symbol_offset(const char *label, phys_t offset) +{ + char *result; /* Construction à retourner */ + size_t length; /* Taille de désignation créée */ + + if (offset == 0) + result = strdup(label); + + else + { + length = strlen(label) + 1 + VMPA_MAX_LEN + 1; + result = (char *)calloc(length, sizeof(char)); + + snprintf(result, length, "%s+0x%llx", label, (unsigned long long)offset); + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ /* DEFINITION D'UNE ZONE EN MEMOIRE */ /* ---------------------------------------------------------------------------------- */ diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index ec356c8..675d5cb 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -52,6 +52,17 @@ #define phys_t off_t #define virt_t uint64_t +/* Equivalents pour GLib */ +#define G_TYPE_PHYS uint64_t +#define G_TYPE_VIRT uint64_t +#define G_TYPE_PHYS_T G_TYPE_UINT64 +#define G_TYPE_VIRT_T G_TYPE_UINT64 + + +#define PHYS_CAST(v) ((uint64_t)v) +#define VIRT_CAST(v) ((uint64_t)v) + + #define VMPA_NO_PHYSICAL ((phys_t)-1) #define VMPA_NO_VIRTUAL ((virt_t)-2) @@ -137,6 +148,14 @@ bool prepare_vmpa_db_statement(const vmpa2t *, bool, bound_value **, size_t *); +/* ------------------------ AIDES FONCTIONNELLES AUXILIAIRES ------------------------ */ + + +/* Construit une désignation de symbole avec décalage. */ +char *make_symbol_offset(const char *, phys_t); + + + /* ------------------------ DEFINITION D'UNE ZONE EN MEMOIRE ------------------------ */ diff --git a/src/dialogs/Makefile.am b/src/dialogs/Makefile.am index 54b6fa2..1fe821a 100644 --- a/src/dialogs/Makefile.am +++ b/src/dialogs/Makefile.am @@ -6,6 +6,7 @@ libdialogs_la_SOURCES = \ bookmark.h bookmark.c \ export.h export.c \ goto.h goto.c \ + gotox.h gotox.c \ plugins.h plugins.c \ shellcode.h shellcode.c \ storage.h storage.c diff --git a/src/dialogs/gotox.c b/src/dialogs/gotox.c new file mode 100644 index 0000000..653a969 --- /dev/null +++ b/src/dialogs/gotox.c @@ -0,0 +1,367 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * goto.c - boîte de dialogue pour les sauts à une adresse donnée + * + * Copyright (C) 2012-2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include "gotox.h" + + +#include +#include + + +#include + + +#include "../gtkext/easygtk.h" +#include "../gtkext/support.h" + + + +/* Colonnes de la liste des symboles */ +typedef enum _GotoXColumn +{ + GXC_PHYSICAL, /* Correspondance physique */ + GXC_VIRTUAL, /* Correspondance virtuelle */ + + GXC_PICTURE, /* Image de représentation */ + GXC_ADDRESS, /* Adresse mémoire du symbole */ + GXC_NAME, /* Désignation humaine */ + GXC_CONTENT, /* Contenu de la ligne visée */ + + GXC_COUNT /* Nombre de colonnes */ + +} GotoXColumn; + + + +/* Ajoute une nouvelle localisation de destination. */ +static void add_new_location_to_list(GtkTreeStore *, GLoadedBinary *, const vmpa2t *, GBinSymbol *); + + + +/****************************************************************************** +* * +* Paramètres : parent = fenêtre parente à surpasser. * +* binary = binaire dont les points d'entrée sont à afficher. * +* * +* Description : Construit la fenêtre de sélection des sections. * +* * +* Retour : Adresse de la fenêtre mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *create_gotox_dialog(GtkWindow *parent, GLoadedBinary *binary) +{ + GtkWidget *result; /* Fenêtre à renvoyer */ + GtkWidget *dlgvbox; /* Zone principale de la boîte */ + GtkWidget *vbox; /* Support à construire #1 */ + GtkWidget *scrollwnd; /* Support défilant */ + GtkWidget *treeview; /* Affichage de la liste */ + GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ + GtkTreeViewColumn *column; /* Colonne de la liste */ + GtkTreeStore *store; /* Modèle de gestion */ + GBinFormat *format; /* Format associé au binaire */ + GBinSymbol **symbols; /* Symboles à représenter */ + size_t sym_count; /* Qté de symboles présents */ + size_t i; /* Boucle de parcours */ + vmpa2t addr; /* Localisation de symbole */ + + result = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(result), _("Binary's entry points")); + gtk_window_set_default_size(GTK_WINDOW(result), 600, 350); + gtk_window_set_position(GTK_WINDOW(result), GTK_WIN_POS_CENTER); + gtk_window_set_modal(GTK_WINDOW(result), TRUE); + gtk_window_set_type_hint(GTK_WINDOW(result), GDK_WINDOW_TYPE_HINT_DIALOG); + + dlgvbox = gtk_dialog_get_content_area(GTK_DIALOG(result)); + gtk_widget_show(dlgvbox); + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_widget_show(vbox); + gtk_box_pack_start(GTK_BOX(dlgvbox), vbox, TRUE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 8); + + /* Liste arborescente ou linéaire */ + + scrollwnd = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrollwnd); + gtk_box_pack_start(GTK_BOX(vbox), scrollwnd, TRUE, TRUE, 0); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN); + + store = gtk_tree_store_new(GXC_COUNT, + G_TYPE_UINT64, G_TYPE_UINT64, + CAIRO_GOBJECT_TYPE_SURFACE, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE); + gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(treeview), TRUE); + + g_object_set_data(G_OBJECT(result), "treeview", treeview); + + gtk_widget_show(treeview); + gtk_container_add(GTK_CONTAINER(scrollwnd), treeview); + + /* Cellules d'affichage */ + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Address"), renderer, + "markup", GXC_ADDRESS, + NULL); + gtk_tree_view_column_set_sort_column_id(column, GXC_ADDRESS); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + column = gtk_tree_view_column_new(); + + gtk_tree_view_column_set_title(column, _("Name")); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(column, renderer, FALSE); + gtk_tree_view_column_set_attributes(column, renderer, + "surface", GXC_PICTURE, + NULL); + + g_object_set(G_OBJECT(renderer), "xpad", 4, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(column, renderer, TRUE); + gtk_tree_view_column_set_attributes(column, renderer, + "text", GXC_NAME, + NULL); + + gtk_tree_view_column_set_sort_column_id(column, GXC_NAME); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Content"), renderer, + "markup", GXC_CONTENT, + NULL); + gtk_tree_view_column_set_sort_column_id(column, GXC_CONTENT); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + /* Zone de validation */ + + gtk_dialog_add_button(GTK_DIALOG(result), _("_Cancel"), GTK_RESPONSE_CANCEL); + gtk_dialog_add_button(GTK_DIALOG(result), _("_Go"), GTK_RESPONSE_OK); + + /* Affichage de tous les points d'entrées */ + + format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + + symbols = g_binary_format_get_symbols(format, &sym_count); + + for (i = 0; i < sym_count; i++) + { + if (g_binary_symbol_get_target_type(symbols[i]) != STP_ENTRY_POINT) + continue; + + copy_vmpa(&addr, get_mrange_addr(g_binary_symbol_get_range(symbols[i]))); + + add_new_location_to_list(store, binary, &addr, symbols[i]); + + } + + g_object_unref(G_OBJECT(store)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : store = modèle de gestionnaire pour la liste affichée. * +* binary = représentation du binaire chargé en mémoire. * +* addr = localisation à venir ajouter à la liste. * +* hint = éventuel symbole à venir retrouver à l'adresse. * +* * +* Description : Ajoute une nouvelle localisation de destination. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void add_new_location_to_list(GtkTreeStore *store, GLoadedBinary *binary, const vmpa2t *addr, GBinSymbol *hint) +{ + GCodeBuffer *buffer; /* Tampon de désassemblage */ + GBufferLine *line; /* Ligne présente à l'adresse */ + char *virtual; /* Transcription d'adresse */ + const char *label; /* Etiquette de symbole trouvé */ + GBinFormat *format; /* Format associé au binaire */ + GBinSymbol *symbol; /* Symbole associé à l'adresse */ + phys_t diff; /* Décalage vis à vis du début */ + char *name; /* Désignation humaine */ + gchar *filename; /* Chemin d'accès à utiliser */ + cairo_surface_t *icon; /* Image pour les symboles */ + char *content; /* Contenu de la ligne visée */ + GtkTreeIter iter; /* Point d'insertion */ + + /* Adresse en mémoire virtuelle */ + + buffer = g_loaded_binary_get_disassembled_buffer(binary); + line = g_code_buffer_find_line_by_addr(buffer, addr); + + if (line != NULL) + virtual = g_buffer_line_get_text(line, BLC_VIRTUAL, BLC_VIRTUAL + 1, true); + else + virtual = strdup(_("")); + + /* Désignation humaine de l'adresse */ + + if (hint != NULL) + { + symbol = hint; + g_object_ref(G_OBJECT(symbol)); + + label = g_binary_symbol_get_label(hint); + + name = make_symbol_offset(label, 0); + + } + else + { + format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + + if (g_binary_format_resolve_symbol(format, addr, &symbol, &diff)) + { + label = g_binary_symbol_get_label(symbol); + + name = make_symbol_offset(label, diff); + + } + else + { + symbol = NULL; + + name = strdup(_("")); + + } + + } + + /* Image de représentation */ + + switch (g_binary_symbol_get_target_type(symbol)) + { + case STP_ENTRY_POINT: + filename = find_pixmap_file("entrypoint.png"); + break; + + default: + filename = NULL; + break; + + } + + if (filename != NULL) + { + icon = cairo_image_surface_create_from_png(filename); + g_free(filename); + } + else + icon = NULL; + + /* Contenu d'assemblage */ + + if (line != NULL) + content = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true); + else + content = strdup(_("")); + + /* Insertion finale */ + + gtk_tree_store_append(store, &iter, NULL); + + gtk_tree_store_set(store, &iter, + GXC_PHYSICAL, PHYS_CAST(get_phy_addr(addr)), + GXC_VIRTUAL, VIRT_CAST(get_virt_addr(addr)), + GXC_PICTURE, icon, + GXC_ADDRESS, virtual, + GXC_NAME, name, + GXC_CONTENT, content, + -1); + + if (symbol != NULL) + g_object_unref(G_OBJECT(symbol)); + + if (virtual != NULL) free(virtual); + if (icon != NULL) cairo_surface_destroy(icon); + free(name); + if (content != NULL) free(content); + + if (line != NULL) + g_object_unref(G_OBJECT(line)); + +} + + +/****************************************************************************** +* * +* Paramètres : dialog = boîte de dialogue ayant reçu une validation. * +* * +* Description : Fournit l'adresse obtenue par la saisie de l'utilisateur. * +* * +* Retour : Adresse reccueillie par la boîte de dialogue ou NULL si rien.* +* * +* Remarques : - * +* * +******************************************************************************/ + +vmpa2t *get_address_from_gotox_dialog(GtkWidget *dialog) +{ + vmpa2t *result; /* Adresse à retourner */ + GtkTreeView *treeview; /* Liste d'adresses à lire */ + GtkTreeSelection *selection; /* Sélection courante */ + GtkTreeModel *model; /* Modèle de gestionnaire */ + GList *selected; /* Liste des sélections */ + GtkTreeIter iter; /* Tête de lecture */ + G_TYPE_PHYS phys; /* Position physique */ + G_TYPE_VIRT virt; /* Adresse virtuelle */ + + treeview = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(dialog), "treeview")); + + selection = gtk_tree_view_get_selection(treeview); + + selected = gtk_tree_selection_get_selected_rows(selection, &model); + if (selected == NULL) return NULL; + + if (!gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)selected->data)) + return NULL; + + gtk_tree_model_get(model, &iter, + GXC_PHYSICAL, &phys, + GXC_VIRTUAL, &virt, + -1); + + result = make_vmpa(phys, virt); + + g_list_free_full(selected, (GDestroyNotify)gtk_tree_path_free); + + return result; + +} diff --git a/src/dialogs/gotox.h b/src/dialogs/gotox.h new file mode 100644 index 0000000..1153478 --- /dev/null +++ b/src/dialogs/gotox.h @@ -0,0 +1,44 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * goto.h - prototypes pour la boîte de dialogue pour les sauts à une adresse donnée + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _DIALOGS_GOTOX_H +#define _DIALOGS_GOTOX_H + + +#include + + +#include "../analysis/binary.h" +#include "../arch/vmpa.h" + + + +/* Construit la fenêtre de saut à une adresse. */ +GtkWidget *create_gotox_dialog(GtkWindow *, GLoadedBinary *); + +/* Fournit l'adresse obtenue par la saisie de l'utilisateur. */ +vmpa2t *get_address_from_gotox_dialog(GtkWidget *); + + + +#endif /* _DIALOGS_GOTOX_H */ diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c index 1fbb460..16f4814 100644 --- a/src/glibext/gbinportion.c +++ b/src/glibext/gbinportion.c @@ -699,18 +699,21 @@ 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) { + mrange_t range; /* Couverture à fournir */ GBufferLine *line; /* Nouvelle ligne à éditer */ char rights[64]; /* Traduction en texte */ /* On ne traite pas les portions anonymes ! */ if (portion->desc == NULL) return; - line = g_code_buffer_append_new_line(buffer, &portion->range); + init_mrange(&range, get_mrange_addr(&portion->range), 0); + + line = g_code_buffer_append_new_line(buffer, &range); g_buffer_line_fill_mrange(line, msize, msize); /* Séparation */ - line = g_code_buffer_append_new_line(buffer, &portion->range); + 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); @@ -719,7 +722,7 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem /* Retour à la ligne */ - line = g_code_buffer_append_new_line(buffer, &portion->range); + 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); @@ -727,7 +730,7 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem /* Description */ - line = g_code_buffer_append_new_line(buffer, &portion->range); + 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); @@ -746,13 +749,13 @@ void g_binary_portion_print(const GBinPortion *portion, GCodeBuffer *buffer, Mem /* Retour à la ligne */ - line = g_code_buffer_append_new_line(buffer, &portion->range); + 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); - line = g_code_buffer_append_new_line(buffer, &portion->range); + line = g_code_buffer_append_new_line(buffer, &range); g_buffer_line_fill_mrange(line, msize, msize); } diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 824578d..ff64604 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -24,6 +24,7 @@ #include "gbufferline.h" +#include #include #include /* Récupération du langage par défaut ; FIXME ? */ @@ -834,7 +835,7 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *line, const gint if (result == NULL) printf(" -- get segment at -- found nothing...\n"); else - printf(" -- get segment at -- found %p '%s'...\n", result, g_buffer_segment_get_text(result)); + printf(" -- get segment at -- found %p '%s'...\n", result, g_buffer_segment_get_text(result, false)); @@ -1025,7 +1026,10 @@ void g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn column, const /****************************************************************************** * * -* Paramètres : line = ligne à venir consulter. * +* Paramètres : line = ligne à venir consulter. * +* first = première colonne à parcourir. * +* end = colonne de fin de parcours. * +* markup = indique si le texte doit être décoré ou non. * * * * Description : Donne le texte représenté par une ligne de tampon. * * * @@ -1035,23 +1039,38 @@ void g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn column, const * * ******************************************************************************/ -char *g_buffer_line_get_text(const GBufferLine *line) +char *g_buffer_line_get_text(const GBufferLine *line, BufferLineColumn first, BufferLineColumn end, bool markup) { char *result; /* Construction à retourner */ BufferLineColumn i; /* Boucle de parcours #1 */ size_t j; /* Boucle de parcours #2 */ + char *extra; /* Contenu à intégrer au texte */ result = NULL; - for (i = BLC_ASSEMBLY_HEAD; i < BLC_COUNT; i++) + assert(first < end); + + for (i = first; i < end; i++) + { + if (i > first && result != NULL) + result = stradd(result, " "); + for (j = 0; j < line->columns[i].count; j++) + { + extra = g_buffer_segment_get_text(line->columns[i].segments[j], markup); + if (result == NULL) + result = extra; + + else { - result = strdup(g_buffer_segment_get_text(line->columns[i].segments[j])); - result = stradd(result, " "); + result = stradd(result, extra); + free(extra); } - else - result = stradd(result, g_buffer_segment_get_text(line->columns[i].segments[j])); + + } + + } return result; @@ -1160,6 +1179,25 @@ void g_buffer_line_add_flag(GBufferLine *line, BufferLineFlags flag) /****************************************************************************** * * +* Paramètres : line = ligne à venir consulter. * +* * +* Description : Renseigne sur les propriétés particulières liées à une ligne.* +* * +* Retour : Propriétés intégrées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +BufferLineFlags g_buffer_line_get_flags(const GBufferLine *line) +{ + return line->flags; + +} + + +/****************************************************************************** +* * * Paramètres : line = ligne à venir compléter. * * flag = propriété à supprimer. * * * @@ -1201,7 +1239,7 @@ void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, const gint max_widths gint x; /* Point de départ d'impression*/ BufferLineColumn i; /* Boucle de parcours */ - if (line->flags != BLF_NONE) + if (line->flags != BLF_NONE && line->flags != BLF_HAS_CODE) { class = G_BUFFER_LINE_GET_CLASS(line); diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index 6984c37..bf703ab 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -87,8 +87,9 @@ typedef enum _BufferLineColumn typedef enum _BufferLineFlags { BLF_NONE = 0 << 0, /* Aucune */ - BLF_ENTRYPOINT = 1 << 0, /* Représentation d'une entrée */ - BLF_BOOKMARK = 1 << 1 /* Signet associé */ + BLF_HAS_CODE = 1 << 0, /* La ligne contient du code */ + BLF_ENTRYPOINT = 1 << 1, /* Représentation d'une entrée */ + BLF_BOOKMARK = 1 << 2 /* Signet associé */ } BufferLineFlags; @@ -124,7 +125,7 @@ GSList *g_buffer_line_highlight_all_same_segments(const GBufferLine *, GSList *, void g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType); /* Donne le texte représenté par une ligne de tampon. */ -char *g_buffer_line_get_text(const GBufferLine *); +char *g_buffer_line_get_text(const GBufferLine *, BufferLineColumn, BufferLineColumn, bool); /* Fournit la largeur requise pour une colonne de ligne donnée. */ gint g_buffer_line_get_column_width(GBufferLine *, BufferLineColumn); @@ -138,6 +139,9 @@ void g_buffer_line_start_merge_at(GBufferLine *, BufferLineColumn); /* Ajoute une propriété particulière à une ligne donnée. */ void g_buffer_line_add_flag(GBufferLine *, BufferLineFlags); +/* Renseigne sur les propriétés particulières liées à une ligne. */ +BufferLineFlags g_buffer_line_get_flags(const GBufferLine *); + /* Retire une propriété particulière à une ligne donnée. */ void g_buffer_line_remove_flag(GBufferLine *, BufferLineFlags); diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c index 1ebb543..27891a8 100644 --- a/src/glibext/gbuffersegment.c +++ b/src/glibext/gbuffersegment.c @@ -29,6 +29,7 @@ #include +#include "../common/extstr.h" #include "../common/fnv1a.h" #include "../gtkext/gtkblockview.h" #include "../gtkext/support.h" @@ -385,6 +386,7 @@ bool g_buffer_segment_compare(const GBufferSegment *segment, const GBufferSegmen /****************************************************************************** * * * Paramètres : segment = fragment de texte à consulter. * +* markup = indique si le texte doit être décoré ou non. * * * * Description : Fournit le texte brut conservé dans le segment. * * * @@ -394,9 +396,79 @@ bool g_buffer_segment_compare(const GBufferSegment *segment, const GBufferSegmen * * ******************************************************************************/ -const char *g_buffer_segment_get_text(const GBufferSegment *segment) +char *g_buffer_segment_get_text(const GBufferSegment *segment, bool markup) { - return segment->text; + char *result; /* Description à renvoyer */ + char color[7]; /* Couleur hexadécimale */ + + /* Résolution du cas simple */ + if (!markup) + return strdup(segment->text); + + result = strdup("pattern->foreground.color.red * 255), + (unsigned char)(segment->pattern->foreground.color.green * 255), + (unsigned char)(segment->pattern->foreground.color.blue * 255)); + + result = stradd(result, color); + + result = stradd(result, "\""); + + /* Style */ + + result = stradd(result, "style=\""); + + switch (segment->pattern->slant) + { + case CAIRO_FONT_SLANT_NORMAL: + result = stradd(result, "normal"); + break; + + case CAIRO_FONT_SLANT_ITALIC: + result = stradd(result, "italic"); + break; + + case CAIRO_FONT_SLANT_OBLIQUE: + result = stradd(result, "oblique"); + break; + + } + + result = stradd(result, "\""); + + /* Epaisseur */ + + result = stradd(result, "weight=\""); + + switch (segment->pattern->weight) + { + case CAIRO_FONT_WEIGHT_NORMAL: + result = stradd(result, "normal"); + break; + + case CAIRO_FONT_WEIGHT_BOLD: + result = stradd(result, "bold"); + break; + + } + + result = stradd(result, "\""); + + /* Conclusion */ + + result = stradd(result, ">"); + + result = stradd(result, segment->text); + + result = stradd(result, ""); + + return result; } diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h index 10ae374..ace4e42 100644 --- a/src/glibext/gbuffersegment.h +++ b/src/glibext/gbuffersegment.h @@ -110,7 +110,7 @@ GBufferSegment *g_buffer_segment_new(RenderingTagType, const char *, size_t); bool g_buffer_segment_compare(const GBufferSegment *, const GBufferSegment *); /* Fournit le texte brut conservé dans le segment. */ -const char *g_buffer_segment_get_text(const GBufferSegment *); +char *g_buffer_segment_get_text(const GBufferSegment *, bool); /* Fournit la quantité de pixels requise pour l'impression. */ gint g_buffer_segment_get_width(const GBufferSegment *); diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index d13c9d6..afad0f4 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -127,6 +127,9 @@ static void g_code_buffer_init(GCodeBuffer *); static size_t _g_code_buffer_get_index_from_address(const GCodeBuffer *, const vmpa2t *, bool); /* Convertit une adresse en indice de ligne. */ +static size_t _g_code_buffer_get_index_from_address_new(const GCodeBuffer *, const vmpa2t *, bool); + +/* Convertit une adresse en indice de ligne. */ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *, const vmpa2t *, bool); @@ -419,6 +422,66 @@ static size_t _g_code_buffer_get_index_from_address(const GCodeBuffer *buffer, c return (first ? 0 : buffer->used - 1); +#if 0 + + for (result = 0; result < buffer->used; result++) + if (g_buffer_line_get_address(buffer->lines[result]) == addr) + break; + + if (!first) + for (; result < (buffer->used - 1); result++) + if (g_buffer_line_get_address(buffer->lines[result + 1]) != addr) + break; + +#endif + + return result; + +} + +/****************************************************************************** +* * +* Paramètres : buffer = composant GTK à mettre à jour. * +* addr = adresse où va se situer la ligne. * +* first = indique si on l'arrête à la première ou la dernière.* +* * +* Description : Convertit une adresse en indice de ligne. * +* * +* Retour : Indice de l'adresse trouvée, ou 0 en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t _g_code_buffer_get_index_from_address_new(const GCodeBuffer *buffer, const vmpa2t *addr, bool first) +{ + size_t result; /* Indice à retourner */ + const mrange_t *range; /* Couverture d'une ligne */ + + + for (result = 0; result < buffer->used; result++) + { + range = g_buffer_line_get_range(buffer->lines[result]); + + if (mrange_contains_addr(range, addr)) + { + printf(":: STOP :: %x + %u // %x\n", + range->addr.virtual, range->length, addr->virtual); + break; + } + + } + +#if 0 + + size_t result; /* Indice à retourner */ + + if (addr == VMPA_MAX) + return (buffer->used > 0 ? buffer->used - 1 : 0); + + /* TODO : coder un parcours plus optimal ! */ + + return (first ? 0 : buffer->used - 1); #if 0 @@ -433,6 +496,8 @@ static size_t _g_code_buffer_get_index_from_address(const GCodeBuffer *buffer, c #endif +#endif + return result; } @@ -596,18 +661,31 @@ GBufferLine *g_code_buffer_insert_after(GCodeBuffer *buffer, GBufferLine *line) * * ******************************************************************************/ -GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, vmpa_t addr) +GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vmpa2t *addr) { GBufferLine *result; /* Instance à retourner */ size_t index; /* Indice de la ligne visée */ - index = _g_code_buffer_get_index_from_address(buffer, addr, true); + index = _g_code_buffer_get_index_from_address_new(buffer, addr, true); if (index == buffer->used) result = NULL; else + { result = buffer->lines[index]; + while ((g_buffer_line_get_flags(result) & BLF_HAS_CODE) == 0) + { + if ((index + 1) == buffer->used) break; + + result = buffer->lines[++index]; + + } + + g_object_ref(G_OBJECT(result)); + + } + return result; } @@ -1109,7 +1187,7 @@ const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, GBufferLine *line, x - tmp_x, tmp_x, g_buffer_segment_get_caret_position(segment, tmp_x), g_buffer_segment_get_width(segment)); - printf(" '%s'\n", g_buffer_segment_get_text(segment)); + printf(" '%s'\n", g_buffer_segment_get_text(segment, false)); caret->x = (x - tmp_x) + g_buffer_segment_get_caret_position(segment, tmp_x); @@ -1167,7 +1245,7 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line if (segment == NULL) return false; - printf(" ====== FIRST SEG :: %p ('%s')\n", segment, g_buffer_segment_get_text(segment)); + printf(" ====== FIRST SEG :: %p ('%s')\n", segment, g_buffer_segment_get_text(segment, false)); @@ -1190,7 +1268,7 @@ static bool _g_buffer_view_move_caret(GBufferView *view, const GBufferLine *line segment = g_buffer_line_find_near_segment(line, segment, view->max_widths, display, dir, &offset); - printf(" ====== NEAR SEG :: %p ('%s')\n", segment, segment ? g_buffer_segment_get_text(segment) : NULL); + printf(" ====== NEAR SEG :: %p ('%s')\n", segment, segment ? g_buffer_segment_get_text(segment, false) : NULL); if (segment != NULL) { @@ -1484,7 +1562,7 @@ void g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y) if (segment == NULL) return; - printf("text :: '%s'\n", g_buffer_segment_get_text(segment)); + printf("text :: '%s'\n", g_buffer_segment_get_text(segment, false)); if (view->highlighted != NULL) diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h index 62b725c..ddd45db 100644 --- a/src/glibext/gcodebuffer.h +++ b/src/glibext/gcodebuffer.h @@ -70,7 +70,7 @@ GBufferLine *g_code_buffer_insert_at(GCodeBuffer *, vmpa_t, bool); GBufferLine *g_code_buffer_insert_after(GCodeBuffer *, GBufferLine *); /* Retrouve une ligne au sein d'un tampon avec une adresse. */ -GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, vmpa_t); +GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, const vmpa2t *); /* Augmente l'indentation des prochaines lignes. */ void g_code_buffer_inc_indentation(GCodeBuffer *); diff --git a/src/gui/menus/binary.c b/src/gui/menus/binary.c index 9643663..c7c0347 100644 --- a/src/gui/menus/binary.c +++ b/src/gui/menus/binary.c @@ -30,11 +30,15 @@ #include "../editem-int.h" #include "../../dialogs/export.h" +#include "../../dialogs/gotox.h" #include "../../dialogs/storage.h" #include "../../gtkext/easygtk.h" +/* Réagit au menu "Binaire -> Points d'entrée". */ +static void mcb_binary_entry_points(GtkMenuItem *, GMenuBar *); + /* Réagit au menu "Binaire -> Enregistrements...". */ static void mcb_binary_storage(GtkMenuItem *, GMenuBar *); @@ -69,6 +73,14 @@ GtkWidget *build_menu_binary(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *ba menubar = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(result), menubar); + submenuitem = qck_create_menu_item(NULL, NULL, _("Entry points"), + G_CALLBACK(mcb_binary_entry_points), bar); + add_accelerator_to_menu_item(submenuitem, "E", accgroup); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + submenuitem = qck_create_menu_item(ref, "mnu_binary_storage", _("Storage..."), G_CALLBACK(mcb_binary_storage), bar); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); @@ -87,6 +99,51 @@ GtkWidget *build_menu_binary(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *ba * Paramètres : menuitem = élément de menu sélectionné. * * bar = barre de menu parente. * * * +* Description : Réagit au menu "Binaire -> Points d'entrée". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_binary_entry_points(GtkMenuItem *menuitem, GMenuBar *bar) +{ + GEditorItem *item; /* Elément d'éditeur graphique */ + GObject *ref; /* Espace de référencements */ + GLoadedBinary *binary; /* Binaire présenté à l'écran */ + GtkWidget *dialog; /* Boîte de dialogue à montrer */ + vmpa2t *addr; /* Adresse de destination */ + GtkViewPanel *vpanel; /* Afficheur effectif de code */ + + item = G_EDITOR_ITEM(bar); + + ref = g_editor_item_get_global_ref(item); + binary = g_editor_item_get_current_binary(item); + + dialog = create_gotox_dialog(GTK_WINDOW(ref), binary); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) + { + addr = get_address_from_gotox_dialog(dialog); + + vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar)); + gtk_view_panel_scroll_to_address(vpanel, addr); + + delete_vmpa(addr); + + } + + gtk_widget_destroy(dialog); + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* bar = barre de menu parente. * +* * * Description : Réagit au menu "Binaire -> Enregistrements...". * * * * Retour : - * -- cgit v0.11.2-87-g4458