summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog35
-rw-r--r--plugins/pychrysa/glibext/bufferline.c2
-rw-r--r--src/arch/instruction.c2
-rw-r--r--src/arch/vmpa.c41
-rw-r--r--src/arch/vmpa.h19
-rw-r--r--src/dialogs/Makefile.am1
-rw-r--r--src/dialogs/gotox.c367
-rw-r--r--src/dialogs/gotox.h44
-rw-r--r--src/glibext/gbinportion.c15
-rw-r--r--src/glibext/gbufferline.c56
-rw-r--r--src/glibext/gbufferline.h10
-rw-r--r--src/glibext/gbuffersegment.c76
-rw-r--r--src/glibext/gbuffersegment.h2
-rw-r--r--src/glibext/gcodebuffer.c90
-rw-r--r--src/glibext/gcodebuffer.h2
-rw-r--r--src/gui/menus/binary.c57
16 files changed, 790 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index 5949c37..6ebe5de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+15-02-22 Cyrille Bagard <nocbos@gmail.com>
+
+ * 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 <nocbos@gmail.com>
* 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "gotox.h"
+
+
+#include <cairo-gobject.h>
+#include <malloc.h>
+
+
+#include <i18n.h>
+
+
+#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(_("<line address not found>"));
+
+ /* 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(_("<no symbol found>"));
+
+ }
+
+ }
+
+ /* 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(_("<assembly line not found>"));
+
+ /* 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _DIALOGS_GOTOX_H
+#define _DIALOGS_GOTOX_H
+
+
+#include <gtk/gtk.h>
+
+
+#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 <assert.h>
#include <string.h>
#include <gtk/gtk.h> /* 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 <string.h>
+#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("<span ");
+
+ /* Couleur */
+
+ result = stradd(result, "foreground=\"#");
+
+ snprintf(color, sizeof(color), "%02hhx%02hhx%02hhx",
+ (unsigned char)(segment->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, "</span>");
+
+ 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, "<Ctrl>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 : - *