summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog58
-rw-r--r--src/analysis/disass/disassembler.c37
-rw-r--r--src/analysis/disass/links.c147
-rw-r--r--src/analysis/disass/links.h14
-rw-r--r--src/arch/immediate.c31
-rw-r--r--src/arch/immediate.h3
-rw-r--r--src/arch/instruction.c40
-rw-r--r--src/arch/instruction.h5
-rw-r--r--src/arch/target.c13
-rw-r--r--src/dialogs/gotox.c136
-rw-r--r--src/dialogs/gotox.h7
-rw-r--r--src/glibext/gbufferline.c12
-rw-r--r--src/glibext/gbufferline.h2
-rw-r--r--src/glibext/gbuffersegment.c101
-rw-r--r--src/glibext/gbuffersegment.h6
-rw-r--r--src/glibext/gcodebuffer.c121
-rw-r--r--src/glibext/gcodebuffer.h10
-rw-r--r--src/gtkext/gtkbufferview-int.h2
-rw-r--r--src/gtkext/gtkbufferview.c41
-rw-r--r--src/gtkext/gtkviewpanel-int.h4
-rw-r--r--src/gtkext/gtkviewpanel.c37
-rw-r--r--src/gtkext/gtkviewpanel.h3
-rw-r--r--src/gui/editem-int.h4
-rw-r--r--src/gui/editem.c31
-rw-r--r--src/gui/editem.h3
-rw-r--r--src/gui/menus/binary.c2
-rw-r--r--src/gui/menus/edition.c246
-rw-r--r--src/gui/menus/menubar.c71
-rw-r--r--src/project.c5
29 files changed, 1088 insertions, 104 deletions
diff --git a/ChangeLog b/ChangeLog
index ed1a6f7..d832495 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,61 @@
+15-03-08 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/analysis/disass/disassembler.c:
+ Update code.
+
+ * src/analysis/disass/links.c:
+ * src/analysis/disass/links.h:
+ Restore the code establishing links between instructions.
+
+ * src/arch/immediate.c:
+ * src/arch/immediate.h:
+ Attach the operand to output segments. Export values to virt_t types.
+
+ * src/arch/instruction.c:
+ * src/arch/instruction.h:
+ Find instructions by ranges or adreses in a given list.
+
+ * src/arch/target.c:
+ Attach the operand to output segments.
+
+ * src/dialogs/gotox.c:
+ * src/dialogs/gotox.h:
+ Handle cross references as well as entry points.
+
+ * src/glibext/gbufferline.c:
+ * src/glibext/gbufferline.h:
+ * src/glibext/gbuffersegment.c:
+ * src/glibext/gbuffersegment.h:
+ Memorize GLib instances as creator of lines or segments.
+
+ * src/glibext/gcodebuffer.c:
+ * src/glibext/gcodebuffer.h:
+ Find the line and its segment located at a given position.
+
+ * src/gtkext/gtkbufferview.c:
+ * src/gtkext/gtkbufferview-int.h:
+ * src/gtkext/gtkviewpanel.c:
+ * src/gtkext/gtkviewpanel.h:
+ * src/gtkext/gtkviewpanel-int.h:
+ Update code to get the current position in a view.
+
+ * src/gui/editem.c:
+ * src/gui/editem.h:
+ * src/gui/editem-int.h:
+ Allow to be notified when a view is created or destroyed.
+
+ * src/gui/menus/binary.c:
+ Update code.
+
+ * src/gui/menus/edition.c:
+ Add menu entries to follow addresses or cross references.
+
+ * src/gui/menus/menubar.c:
+ Manage views and track focus to enable/disable some menu items.
+
+ * src/project.c:
+ Update code.
+
15-03-04 Cyrille Bagard <nocbos@gmail.com>
* src/arch/arm/v7/post.c:
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index de9830c..37e6996 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -262,6 +262,43 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta
+
+
+ /**
+ * TODO : établir les couvertures de fonctions,
+ * pour être en mesure de disposer de résolution de type XXX+yyy lors
+ * de l'établissement des liens.
+ */
+
+
+
+
+ /* Seconde étape */
+
+ id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true);
+
+
+ /**
+ *
+ * Lequel choisir ???
+
+G_BIN_FORMAT(disass->format)
+G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)
+
+ */
+
+
+ establish_links_between_instructions(*disass->instrs, G_BIN_FORMAT(disass->format), statusbar, id);
+
+ gtk_extended_status_bar_remove(statusbar, id);
+
+ //run_plugins_on_binary(disass->binary, PGA_BINARY_LINKED, true);
+
+
+
+
+
+
/* Septième étape */
//id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true);
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c
index dc870fc..022ace3 100644
--- a/src/analysis/disass/links.c
+++ b/src/analysis/disass/links.c
@@ -26,9 +26,150 @@
#include "../../arch/instruction.h"
+#include "../../arch/target.h"
+/* Complète un désassemblage accompli pour une instruction. */
+static void convert_immediate_into_target(GArchInstruction *, size_t, GBinFormat *);
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instruction désassemblée à traiter. *
+* index = indice de l'opérande à traiter. *
+* format = accès aux données du binaire d'origine. *
+* *
+* Description : Complète un désassemblage accompli pour une instruction. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void convert_immediate_into_target(GArchInstruction *instr, size_t index, GBinFormat *format)
+{
+ GArchOperand *op; /* Opérande numérique en place */
+ virt_t addr; /* Adresse visée par le saut */
+ MemoryDataSize msize; /* Taille de l'opérande */
+ GArchOperand *new; /* Instruction de ciblage */
+
+ op = g_arch_instruction_get_operand(instr, index);
+ if (!G_IS_IMM_OPERAND(op)) return;
+
+ if (g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &addr))
+ {
+ msize = g_imm_operand_get_size(G_IMM_OPERAND(op));
+
+ new = g_target_operand_new(msize, addr);
+
+ if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format))
+ g_object_unref(G_OBJECT(new));
+ else
+ g_arch_instruction_replace_operand(instr, new, op);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instruction désassemblée à traiter. *
+* list = ensemble d'instructions à relier. *
+* format = accès aux données du binaire d'origine. *
+* *
+* Description : Complète un désassemblage accompli pour une instruction. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void establish_links_for_instruction(GArchInstruction *instr, GArchInstruction *list, GBinFormat *format)
+{
+ size_t count; /* Nombre d'opérandes présents */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande numérique en place */
+ virt_t virt; /* Adresse liée à une cible */
+ vmpa2t addr; /* Localisation plus complète */
+ GArchInstruction *target; /* Instruction visée au final */
+
+ count = g_arch_instruction_count_operands(instr);
+
+ for (i = 0; i < count; i++)
+ {
+ convert_immediate_into_target(instr, i, format);
+
+ op = g_arch_instruction_get_operand(instr, i);
+ if (!G_IS_TARGET_OPERAND(op)) continue;
+
+ virt = g_target_operand_get_addr(G_TARGET_OPERAND(op));
+ init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
+
+ target = g_arch_instruction_find_by_address(list, &addr, true);
+
+ if (target != NULL)
+ g_arch_instruction_link_with(instr, target, ILT_JUMP /* FIXME */);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble d'instructions à relier. *
+* format = accès aux données du binaire d'origine. *
+* statusbar = barre de statut avec progression à mettre à jour.*
+* id = identifiant du message affiché à l'utilisateur. *
+* *
+* Description : Etablit les liens entres les différentes lignes de code. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void establish_links_between_instructions(GArchInstruction *list, GBinFormat *format, GtkExtStatusBar *statusbar, bstatus_id_t id)
+{
+ GArchInstruction *iter; /* Boucle de parcours */
+
+ for (iter = list;
+ iter != NULL;
+ iter = g_arch_instruction_get_next_iter(list, iter, ~0/* FIXME */))
+ {
+
+
+ establish_links_for_instruction(iter, list, format);
+
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
/******************************************************************************
* *
* Paramètres : list = ensemble d'instructions à relier. *
@@ -153,3 +294,9 @@ void establish_links_between_lines(GArchInstruction *list, GBinRoutine **routine
}
}
+
+
+
+
+#endif
+
diff --git a/src/analysis/disass/links.h b/src/analysis/disass/links.h
index 2522e74..f4092f9 100644
--- a/src/analysis/disass/links.h
+++ b/src/analysis/disass/links.h
@@ -25,12 +25,22 @@
#define _ANALYSIS_DISASS_LINKS_H
-#include "../routine.h"
+//#include "../routine.h"
+#include "../../arch/instruction.h"
+#include "../../format/format.h"
#include "../../gtkext/gtkextstatusbar.h"
+
+
+/* Etablit les liens entres les différentes lignes de code. */
+void establish_links_between_instructions(GArchInstruction *, GBinFormat *, GtkExtStatusBar *, bstatus_id_t);
+
+
+
+
/* Etablit les liens entres les différentes lignes de code. */
-void establish_links_between_lines(GArchInstruction *, GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t);
+//void establish_links_between_lines(GArchInstruction *, GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t);
diff --git a/src/arch/immediate.c b/src/arch/immediate.c
index 3a3e64c..fc8e40d 100644
--- a/src/arch/immediate.c
+++ b/src/arch/immediate.c
@@ -858,10 +858,39 @@ static void g_imm_operand_print(const GImmOperand *operand, GBufferLine *line, A
{
char value[VMPA_MAX_SIZE]; /* Chaîne à imprimer */
size_t len; /* Taille de l'élément inséré */
+ GBufferSegment *segment; /* Nouveau segment mis en place*/
len = g_imm_operand_to_string(operand, syntax, value);
- g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_IMMEDIATE);
+ segment = g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_IMMEDIATE);
+ g_buffer_segment_set_creator(segment, G_OBJECT(operand));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* addr = valeur résultante. [OUT] *
+* *
+* Description : Convertit une valeur immédiate en adresse de type virt_t. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_imm_operand_to_virt_t(const GImmOperand *operand, virt_t *addr)
+{
+ bool result; /* Bilan à renvoyer */
+
+ result = !MDS_IS_SIGNED(operand->size);
+
+ if (result)
+ *addr = operand->raw;
+
+ return result;
}
diff --git a/src/arch/immediate.h b/src/arch/immediate.h
index a0721b2..6d1d62e 100644
--- a/src/arch/immediate.h
+++ b/src/arch/immediate.h
@@ -108,6 +108,9 @@ bool g_imm_operand_is_negative(const GImmOperand *);
/* Indique si une valeur immédiate est nulle ou non. */
bool g_imm_operand_is_null(const GImmOperand *);
+/* Convertit une valeur immédiate en adresse de type virt_t. */
+bool g_imm_operand_to_virt_t(const GImmOperand *, virt_t *);
+
/* Convertit une valeur immédiate en adresse de type vmpa_t. */
bool g_imm_operand_to_vmpa_t(const GImmOperand *, vmpa_t *) __attribute__ ((deprecated));
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index c9811cf..aced77e 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -1011,6 +1011,35 @@ GArchInstruction *g_arch_instruction_get_next_iter(const GArchInstruction *list,
/******************************************************************************
* *
+* Paramètres : list = liste de lignes à parcourir. *
+* range = emplacement mémoire à comparer. *
+* *
+* Description : Recherche une instruction d'après son emplacement mémoire. *
+* *
+* Retour : Instruction trouvée à l'adresse donnée, NULL si aucune. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchInstruction *g_arch_instruction_find_by_range(GArchInstruction *list, const mrange_t *range)
+{
+ GArchInstruction *result; /* Trouvaille à retourner */
+
+ ainstr_list_for_each(result, list)
+ {
+ if (cmp_mrange(&result->range, range) == 0)
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : list = liste de lignes à parcourir. *
* addr = position en mémoire ou physique à chercher. *
* strict = définit la considération à porter à l'adresse. *
@@ -1023,16 +1052,19 @@ GArchInstruction *g_arch_instruction_get_next_iter(const GArchInstruction *list,
* *
******************************************************************************/
-GArchInstruction *g_arch_instruction_find_by_address(GArchInstruction *list, vmpa_t addr, bool strict)
+GArchInstruction *g_arch_instruction_find_by_address(GArchInstruction *list, const vmpa2t *addr, bool strict)
{
GArchInstruction *result; /* Trouvaille à retourner */
+ bool found; /* Bilan de comparaisons */
ainstr_list_for_each(result, list)
{
- if (strict && result->offset == addr) break;
+ if (strict)
+ found = (cmp_vmpa(get_mrange_addr(&result->range), addr) == 0);
+ else
+ found = mrange_contains_addr(&result->range, addr);
- else if (!strict && result->offset < addr
- && addr < (result->offset + result->length)) break;
+ if (found) break;
}
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index f1ce67f..12cfbb9 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -218,8 +218,11 @@ GArchInstruction *g_arch_instruction_get_prev_iter(const GArchInstruction *, con
/* Fournit l'élement suivant un autre pour un parcours. */
GArchInstruction *g_arch_instruction_get_next_iter(const GArchInstruction *, const GArchInstruction *, vmpa_t);
+/* Recherche une instruction d'après son emplacement mémoire. */
+GArchInstruction *g_arch_instruction_find_by_range(GArchInstruction *, const mrange_t *);
+
/* Recherche une instruction d'après son adresse. */
-GArchInstruction *g_arch_instruction_find_by_address(GArchInstruction *, vmpa_t, bool);
+GArchInstruction *g_arch_instruction_find_by_address(GArchInstruction *, const vmpa2t *, bool);
diff --git a/src/arch/target.c b/src/arch/target.c
index 40e9598..7509711 100644
--- a/src/arch/target.c
+++ b/src/arch/target.c
@@ -212,6 +212,7 @@ GArchOperand *g_target_operand_new(MemoryDataSize size, virt_t addr)
static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *line, AsmSyntax syntax)
{
const char *label; /* Etiquette liée à un symbole */
+ GBufferSegment *segment; /* Nouveau segment mis en place*/
vmpa2t tmp; /* Coquille vide pour argument */
VMPA_BUFFER(value); /* Adresse brute à imprimer */
size_t len; /* Taille de l'élément inséré */
@@ -222,16 +223,19 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l
g_buffer_line_insert_text(line, BLC_MAIN, "<", 1, RTT_LTGT);
label = g_binary_symbol_get_label(operand->symbol);
- g_buffer_line_insert_text(line, BLC_MAIN, label, strlen(label), RTT_LABEL);
+ segment = g_buffer_line_insert_text(line, BLC_MAIN, label, strlen(label), RTT_LABEL);
+ g_buffer_segment_set_creator(segment, G_OBJECT(operand));
if (operand->diff > 0)
{
- g_buffer_line_insert_text(line, BLC_MAIN, "+", 1, RTT_SIGNS);
+ segment = g_buffer_line_insert_text(line, BLC_MAIN, "+", 1, RTT_SIGNS);
+ g_buffer_segment_set_creator(segment, G_OBJECT(operand));
init_vmpa(&tmp, operand->diff, VMPA_NO_VIRTUAL);
vmpa2_phys_to_string(&tmp, MDS_4_BITS, value, &len);
- g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_LABEL);
+ segment = g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_LABEL);
+ g_buffer_segment_set_creator(segment, G_OBJECT(operand));
g_buffer_line_insert_text(line, BLC_MAIN, ">", 1, RTT_LTGT);
@@ -243,7 +247,8 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l
init_vmpa(&tmp, VMPA_NO_PHYSICAL, operand->addr);
vmpa2_virt_to_string(&tmp, operand->size, value, &len);
- g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_LABEL);
+ segment = g_buffer_line_insert_text(line, BLC_MAIN, value, len, RTT_LABEL);
+ g_buffer_segment_set_creator(segment, G_OBJECT(operand));
}
diff --git a/src/dialogs/gotox.c b/src/dialogs/gotox.c
index 653a969..33664d7 100644
--- a/src/dialogs/gotox.c
+++ b/src/dialogs/gotox.c
@@ -52,6 +52,8 @@ typedef enum _GotoXColumn
} GotoXColumn;
+/* Construit la fenêtre de sélection d'adresses. */
+static GtkWidget *create_gotox_dialog(GtkWindow *, GtkTreeStore **);
/* Ajoute une nouvelle localisation de destination. */
static void add_new_location_to_list(GtkTreeStore *, GLoadedBinary *, const vmpa2t *, GBinSymbol *);
@@ -61,9 +63,9 @@ static void add_new_location_to_list(GtkTreeStore *, GLoadedBinary *, const vmpa
/******************************************************************************
* *
* Paramètres : parent = fenêtre parente à surpasser. *
-* binary = binaire dont les points d'entrée sont à afficher. *
+* store = modèle de gestion pour les éléments de liste. [OUT] *
* *
-* Description : Construit la fenêtre de sélection des sections. *
+* Description : Construit la fenêtre de sélection d'adresses. *
* *
* Retour : Adresse de la fenêtre mise en place. *
* *
@@ -71,7 +73,7 @@ static void add_new_location_to_list(GtkTreeStore *, GLoadedBinary *, const vmpa
* *
******************************************************************************/
-GtkWidget *create_gotox_dialog(GtkWindow *parent, GLoadedBinary *binary)
+static GtkWidget *create_gotox_dialog(GtkWindow *parent, GtkTreeStore **store)
{
GtkWidget *result; /* Fenêtre à renvoyer */
GtkWidget *dlgvbox; /* Zone principale de la boîte */
@@ -80,15 +82,8 @@ GtkWidget *create_gotox_dialog(GtkWindow *parent, GLoadedBinary *binary)
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);
@@ -111,12 +106,12 @@ GtkWidget *create_gotox_dialog(GtkWindow *parent, GLoadedBinary *binary)
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);
+ *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));
+ 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);
@@ -167,6 +162,40 @@ GtkWidget *create_gotox_dialog(GtkWindow *parent, GLoadedBinary *binary)
gtk_dialog_add_button(GTK_DIALOG(result), _("_Cancel"), GTK_RESPONSE_CANCEL);
gtk_dialog_add_button(GTK_DIALOG(result), _("_Go"), GTK_RESPONSE_OK);
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 points d'entrée. *
+* *
+* Retour : Adresse de la fenêtre mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *create_gotox_dialog_for_entry_points(GtkWindow *parent, GLoadedBinary *binary)
+{
+ GtkWidget *result; /* Fenêtre à renvoyer */
+ 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 */
+
+ /* Mise en place de la boîte de dialogue */
+
+ result = create_gotox_dialog(parent, &store);
+
+ gtk_window_set_title(GTK_WINDOW(result), _("Binary's entry points"));
+
/* Affichage de tous les points d'entrées */
format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
@@ -193,6 +222,61 @@ GtkWidget *create_gotox_dialog(GtkWindow *parent, GLoadedBinary *binary)
/******************************************************************************
* *
+* Paramètres : parent = fenêtre parente à surpasser. *
+* binary = binaire dont les points d'entrée sont à afficher. *
+* instr = instruction de référence sur laquelle s'appuyer. *
+* back = sens de la récupérations des instructions visées. *
+* *
+* Description : Construit la fenêtre de sélection des références croisées. *
+* *
+* Retour : Adresse de la fenêtre mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *parent, GLoadedBinary *binary, const GArchInstruction *instr, bool back)
+{
+ GtkWidget *result; /* Fenêtre à renvoyer */
+ GtkTreeStore *store; /* Modèle de gestion */
+ GArchInstruction **list; /* Liste d'instructions */
+ size_t count; /* Nombre d'éléments présents */
+ size_t i; /* Boucle de parcours */
+ const vmpa2t *addr; /* Adresse à considérer */
+
+ /* Mise en place de la boîte de dialogue */
+
+ result = create_gotox_dialog(parent, &store);
+
+ if (back)
+ gtk_window_set_title(GTK_WINDOW(result), _("List of backward cross references"));
+ else
+ gtk_window_set_title(GTK_WINDOW(result), _("List of forward cross references"));
+
+ /* Affichage de toutes les instructions référencées */
+
+ if (back)
+ count = g_arch_instruction_get_sources(instr, &list, NULL);
+ else
+ count = g_arch_instruction_get_destinations(instr, &list, NULL, NULL);
+
+ for (i = 0; i < count; i++)
+ {
+ addr = get_mrange_addr(g_arch_instruction_get_range(list[i]));
+
+ add_new_location_to_list(store, binary, addr, NULL);
+
+ }
+
+ 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. *
@@ -266,17 +350,21 @@ static void add_new_location_to_list(GtkTreeStore *store, GLoadedBinary *binary,
/* Image de représentation */
- switch (g_binary_symbol_get_target_type(symbol))
- {
- case STP_ENTRY_POINT:
- filename = find_pixmap_file("entrypoint.png");
- break;
+ if (symbol == NULL)
+ filename = NULL;
- default:
- filename = NULL;
- break;
+ else
+ 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)
{
diff --git a/src/dialogs/gotox.h b/src/dialogs/gotox.h
index 1153478..88d1fc9 100644
--- a/src/dialogs/gotox.h
+++ b/src/dialogs/gotox.h
@@ -33,8 +33,11 @@
-/* Construit la fenêtre de saut à une adresse. */
-GtkWidget *create_gotox_dialog(GtkWindow *, GLoadedBinary *);
+/* Construit la fenêtre de sélection des points d'entrée. */
+GtkWidget *create_gotox_dialog_for_entry_points(GtkWindow *, GLoadedBinary *);
+
+/* Construit la fenêtre de sélection des références croisées. */
+GtkWidget *create_gotox_dialog_for_cross_references(GtkWindow *, GLoadedBinary *, const GArchInstruction *, bool);
/* Fournit l'adresse obtenue par la saisie de l'utilisateur. */
vmpa2t *get_address_from_gotox_dialog(GtkWidget *);
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index ac838b8..0422af5 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -1010,15 +1010,15 @@ GSList *g_buffer_line_highlight_all_same_segments(const GBufferLine *line, GSLis
* *
* Description : Ajoute du texte à formater dans une ligne donnée. *
* *
-* Retour : - *
+* Retour : Portion de texte mis en place, voire NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn column, const char *text, size_t length, RenderingTagType type)
+GBufferSegment *g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn column, const char *text, size_t length, RenderingTagType type)
{
- GBufferSegment *segment; /* Portion de texte à ajouter */
+ GBufferSegment *result; /* Portion de texte à renvoyer */
if (length == 0)
return;
@@ -1031,8 +1031,10 @@ void g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn column, const
else
line->last_used = column;
- segment = g_buffer_segment_new(type, text, length);
- g_buffer_line_add_segment(line, column, segment);
+ result = g_buffer_segment_new(type, text, length);
+ g_buffer_line_add_segment(line, column, result);
+
+ return result;
}
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index bf703ab..3a00ce0 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -122,7 +122,7 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *, GBufferSegm
GSList *g_buffer_line_highlight_all_same_segments(const GBufferLine *, GSList *, const GBufferSegment *);
/* Ajoute du texte à formater dans une ligne donnée. */
-void g_buffer_line_insert_text(GBufferLine *, BufferLineColumn, const char *, size_t, RenderingTagType);
+GBufferSegment *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 *, BufferLineColumn, BufferLineColumn, bool);
diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c
index 27891a8..d25d728 100644
--- a/src/glibext/gbuffersegment.c
+++ b/src/glibext/gbuffersegment.c
@@ -98,6 +98,8 @@ struct _GBufferSegment
{
GObject parent; /* A laisser en premier */
+ GObject *creator; /* Objet à l'origine du segment*/
+
char *text; /* Texte brut conservé */
fnv64_t hash; /* Empreinte pour comparaisons */
@@ -131,6 +133,12 @@ static void g_buffer_segment_class_init(GBufferSegmentClass *);
/* Procède à l'initialisation d'un fragment de texte. */
static void g_buffer_segment_init(GBufferSegment *);
+/* Supprime toutes les références externes. */
+static void g_buffer_segment_dispose(GBufferSegment *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_buffer_segment_finalize(GBufferSegment *);
+
/* Définit les dernières propriétés de rendu restantes. */
static void g_buffer_segment_prepare(GBufferSegment *, size_t);
@@ -154,6 +162,7 @@ G_DEFINE_TYPE(GBufferSegment, g_buffer_segment, G_TYPE_OBJECT);
static void g_buffer_segment_class_init(GBufferSegmentClass *class)
{
+ GObjectClass *object; /* Autre version de la classe */
GtkStyleContext *context; /* Contexte pour les styles */
GtkWidgetPath *path; /* Chemin d'accès aux thèmes */
gchar *filename; /* Accès à une image 1x1 */
@@ -164,6 +173,11 @@ static void g_buffer_segment_class_init(GBufferSegmentClass *class)
cairo_text_extents_t extents; /* Couverture des caractères */
RenderingTagType i; /* Boucle de parcours */
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_buffer_segment_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_buffer_segment_finalize;
+
/* Création d'un contexte d'accès */
path = gtk_widget_path_new();
@@ -285,6 +299,47 @@ static void g_buffer_segment_init(GBufferSegment *segment)
/******************************************************************************
* *
+* Paramètres : segment = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_buffer_segment_dispose(GBufferSegment *segment)
+{
+ if (segment->creator != NULL)
+ g_object_unref(segment->creator);
+
+ G_OBJECT_CLASS(g_buffer_segment_parent_class)->dispose(G_OBJECT(segment));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : segment = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_buffer_segment_finalize(GBufferSegment *segment)
+{
+ G_OBJECT_CLASS(g_buffer_segment_parent_class)->finalize(G_OBJECT(segment));
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : type = propriétés de la zone de texte. *
* text = chaîne de caractères à traiter. *
* length = quantité de ces caractères. *
@@ -359,6 +414,52 @@ static void g_buffer_segment_prepare(GBufferSegment *segment, size_t length)
/******************************************************************************
* *
+* Paramètres : segment = instance de segment à compléter. *
+* obj = instance GLib quelconque à mémoriser. *
+* *
+* Description : Associe à un segment un objet GLib identifié comme créateur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_segment_set_creator(GBufferSegment *segment, GObject *obj)
+{
+ if (segment->creator != NULL)
+ g_object_unref(segment->creator);
+
+ segment->creator = obj;
+ g_object_ref(obj);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : segment = instance de segment à compléter. *
+* *
+* Description : Renvoie vers un éventuel objet lié en tant que créateur. *
+* *
+* Retour : Instance GLib quelconque ou NULL si aucune référencée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GObject *g_buffer_segment_get_creator(const GBufferSegment *segment)
+{
+ if (segment->creator != NULL)
+ g_object_ref(segment->creator);
+
+ return segment->creator;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : segment = fragment de texte à consulter. *
* ref = segment de référence servant à la comparaison. *
* *
diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h
index ace4e42..51bfb2a 100644
--- a/src/glibext/gbuffersegment.h
+++ b/src/glibext/gbuffersegment.h
@@ -106,6 +106,12 @@ GType g_buffer_segment_get_type(void);
/* Crée un nouveau fragment de texte avec des propriétés. */
GBufferSegment *g_buffer_segment_new(RenderingTagType, const char *, size_t);
+/* Associe à un segment un objet GLib identifié comme créateur. */
+void g_buffer_segment_set_creator(GBufferSegment *, GObject *);
+
+/* Renvoie vers un éventuel objet lié en tant que créateur. */
+GObject *g_buffer_segment_get_creator(const GBufferSegment *);
+
/* Indique si les textes de deux segments sont identiques. */
bool g_buffer_segment_compare(const GBufferSegment *, const GBufferSegment *);
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 4b5378d..ac6e807 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -145,6 +145,7 @@ struct _GBufferView
GCodeBuffer *buffer; /* Tampon de code visualisé */
vmpa_t start; /* Première ligne intégrée */
vmpa_t end; /* Dernière ligne intégrée */
+ size_t first_index; /* Indice de la première ligne */
gint line_height; /* Hauteur maximale des lignes */
gint max_widths[BLC_COUNT]; /* Taille cachée des colonnes */
@@ -813,6 +814,8 @@ static void g_buffer_view_class_init(GBufferViewClass *class)
static void g_buffer_view_init(GBufferView *buffer)
{
+ buffer->first_index = 0;
+
g_buffer_view_reset_required_height(buffer);
g_buffer_view_reset_required_widths(buffer);
@@ -1156,6 +1159,112 @@ gint g_buffer_view_get_height(const GBufferView *view)
/******************************************************************************
* *
+* Paramètres : view = visualisation à consulter. *
+* x = abscisse comprise dans le segment recherché. [OUT] *
+* y = ordonnée comprise dans la ligne recherchée. *
+* idx = indice de la ligne trouvée ou NULL. [OUT] *
+* display = règles d'affichage des colonnes modulables. *
+* segment = portion de texte recherchée ou NULL. [OUT] *
+* *
+* Description : Fournit la ligne et son segment présents à une position. *
+* *
+* Retour : Ligne retrouvée ou NULL si aucune. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *view, gint *x, gint y, size_t *idx, const bool *display, GBufferSegment **segment)
+{
+ GBufferLine *result; /* Ligne trouvée à retourner */
+ gint lheight; /* Hauteur d'une ligne */
+ size_t index; /* Indice attendu */
+
+ /* Recherche d'une ligne correspondante */
+
+ lheight = g_buffer_view_get_line_height(view);
+ index = view->first_index + y / lheight;
+
+ if (idx != NULL)
+ *idx = index;
+
+ result = (index < view->buffer->used ? view->buffer->lines[index] : NULL);
+
+ /* Recherche du segment visé éventuel */
+
+ if (result != NULL && segment != NULL)
+ {
+ if (*x < view->left_text)
+ *segment = NULL;
+
+ else
+ *segment = g_buffer_line_get_segment_at(result, view->max_widths, display, x, GDK_SCROLL_LEFT, true);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = vue de tampon à mettre à jour. *
+* x = abscisse de la zone principale à traiter. *
+* y = ordonnée de la zone principale à traiter. *
+* display = règles d'affichage des colonnes modulables. *
+* caret = position du curseur à construire. [OUT] *
+* *
+* Description : Calcule la position idéale de curseur pour un point donné. *
+* *
+* Retour : Adresse si une a pu être déterminée, NULL sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, gint x, gint y, const bool *display, GdkRectangle *caret)
+{
+ gint remaining; /* Copie de travail modifiable */
+ size_t index; /* Indice de ligne de tampon */
+ GBufferLine *line; /* Ligne à la position courante*/
+ GBufferSegment *segment; /* Segment présent sur la place*/
+
+ remaining = x;
+
+ line = g_buffer_view_find_line_and_segment_at(view, &remaining, y, &index, display, &segment);
+
+ if (line == NULL) return NULL;
+ if (segment == NULL) printf(" -- no segment\n");
+ if (segment == NULL) return NULL;
+
+
+
+
+
+ printf("\n[BASE] tronc = %d reste = %d dernier = %d largeur = %d\n",
+ x - remaining, remaining, g_buffer_segment_get_caret_position(segment, remaining),
+ g_buffer_segment_get_width(segment));
+
+ printf(" '%s'\n", g_buffer_segment_get_text(segment, false));
+
+
+
+
+ caret->x = (x - remaining) + g_buffer_segment_get_caret_position(segment, remaining);
+
+ caret->y = (index - view->first_index) * view->line_height;
+
+ caret->width = 2;
+ caret->height = view->line_height;
+
+ return get_mrange_addr(g_buffer_line_get_range(line));
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : view = vue de tampon à mettre à jour. *
* line = ligne correspondant à la position. *
* index = indice de cette même ligne dans le tampon. *
@@ -1171,7 +1280,7 @@ gint g_buffer_view_get_height(const GBufferView *view)
* *
******************************************************************************/
-const vmpa2t *g_buffer_view_compute_caret(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret)
+const vmpa2t *g_buffer_view_compute_caret_old(GBufferView *view, GBufferLine *line, size_t index, gint x, const bool *display, GdkRectangle *caret)
{
gint tmp_x; /* Copie de travail modifiable */
GBufferSegment *segment; /* Segment visé par le pointeur*/
@@ -1428,7 +1537,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
if (index > first)
{
line = view->buffer->lines[index - 1];
- result = g_buffer_view_compute_caret(view, line, index - 1, caret->x, display, caret);
+ result = g_buffer_view_compute_caret_old(view, line, index - 1, caret->x, display, caret);
}
break;
@@ -1438,7 +1547,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
if (index < last)
{
line = view->buffer->lines[index + 1];
- result = g_buffer_view_compute_caret(view, line, index + 1, caret->x, display, caret);
+ result = g_buffer_view_compute_caret_old(view, line, index + 1, caret->x, display, caret);
}
break;
@@ -1453,7 +1562,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
if (!moved && index > first)
{
line = view->buffer->lines[index - 1];
- result = g_buffer_view_compute_caret(view, line, index - 1, INT_MAX, display, caret);
+ result = g_buffer_view_compute_caret_old(view, line, index - 1, INT_MAX, display, caret);
}
break;
@@ -1468,7 +1577,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
if (!moved && index < last)
{
line = view->buffer->lines[index + 1];
- result = g_buffer_view_compute_caret(view, line, index + 1, left_pos, display, caret);
+ result = g_buffer_view_compute_caret_old(view, line, index + 1, left_pos, display, caret);
}
break;
@@ -1486,7 +1595,7 @@ const vmpa2t *g_buffer_view_move_caret(GBufferView *view, GdkRectangle *caret, b
/*
if (result && !computed)
- result = g_buffer_view_compute_caret(view, caret->x, caret->y, caret, display, NULL);
+ result = g_buffer_view_compute_caret_old(view, caret->x, caret->y, caret, display, NULL);
*/
return result;
diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h
index 5fd4e7b..e607b9c 100644
--- a/src/glibext/gcodebuffer.h
+++ b/src/glibext/gcodebuffer.h
@@ -128,8 +128,14 @@ gint g_buffer_view_get_width(GBufferView *, const bool *);
/* Fournit la hauteur requise par une visualisation. */
gint g_buffer_view_get_height(const GBufferView *);
+/* Fournit la ligne et son segment présents à une position. */
+GBufferLine *g_buffer_view_find_line_and_segment_at(GBufferView *, gint *, gint, size_t *, const bool *, GBufferSegment **);
+
+/* Calcule la position idéale de curseur pour un point donné. */
+const vmpa2t *g_buffer_view_compute_caret(GBufferView *, gint, gint, const bool *, GdkRectangle *);
+
/* Calcule la position idéale de curseur pour un point donné. */
-const vmpa2t *g_buffer_view_compute_caret(GBufferView *, GBufferLine *, size_t, gint, const bool *, GdkRectangle *);
+const vmpa2t *g_buffer_view_compute_caret_old(GBufferView *, GBufferLine *, size_t, gint, const bool *, GdkRectangle *) __attribute__ ((deprecated));
/* Déplace le curseur au sein d'une vue de tampon. */
const vmpa2t *g_buffer_view_move_caret(GBufferView *, GdkRectangle *, bool, GdkScrollDirection, const bool *);
@@ -147,7 +153,7 @@ void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, gint, const cairo_
void g_buffer_view_export(const GBufferView *, buffer_export_context *, BufferExportType, const bool *);
/* Fournit la ligne présente à une ordonnée donnée. */
-GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *);
+GBufferLine *g_buffer_view_find_line_at(GBufferView *, gint, size_t *) __attribute__ ((deprecated));
/* Indique la position d'affichage d'une adresse donnée. */
bool g_buffer_view_get_address_coordinates(GBufferView *, const vmpa2t *, gint *, gint *, bool);
diff --git a/src/gtkext/gtkbufferview-int.h b/src/gtkext/gtkbufferview-int.h
index 4f82757..a6d937b 100644
--- a/src/gtkext/gtkbufferview-int.h
+++ b/src/gtkext/gtkbufferview-int.h
@@ -45,7 +45,7 @@ struct _GtkBufferView
gint left_text; /* Début d'impression du code */
GdkRectangle caret; /* Emplacement du curseur */
- const vmpa2t *caret_addr; /* Position mémoire du curseur */
+ const vmpa2t *caret_addr; /* Position mémoire du curseur */ /* FIXME : REMME */
guint caret_timer; /* Identifiant du chronomètre */
bool show_caret; /* Bascule entre les affichages*/
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index 30cf075..c7c0267 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -61,6 +61,9 @@ static void gtk_buffer_view_compute_scroll_inc(GtkBufferView *, gint, GtkOrienta
/* Indique la position d'affichage d'une adresse donnée. */
static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *, const vmpa2t *, gint *, gint *, ScrollPositionTweak);
+/* Fournit des éléments liés à la position courante dans la vue. */
+static bool gtk_buffer_view_get_position(const GtkBufferView *, GBufferLine **, GBufferSegment **);
+
/* Place en cache un rendu destiné à l'aperçu graphique rapide. */
static void gtk_buffer_view_cache_glance(GtkBufferView *, cairo_t *, const GtkAllocation *, double);
@@ -117,6 +120,7 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
panel_class->compute_size = (compute_requested_size)gtk_buffer_view_compute_requested_size;
panel_class->compute_inc = (compute_scroll_inc)gtk_buffer_view_compute_scroll_inc;
panel_class->get_coordinates = (get_addr_coordinates_fc)gtk_buffer_view_get_address_coordinates;
+ panel_class->get_position = (get_view_position_fc)gtk_buffer_view_get_position;
g_signal_new("caret-moved",
GTK_TYPE_BUFFER_VIEW,
@@ -255,7 +259,8 @@ static gboolean gtk_buffer_view_button_press(GtkWidget *widget, GdkEventButton *
}
else
{
- addr = g_buffer_view_compute_caret(view->buffer_view, line, index, real_x, pview->display, &new);
+ //addr = g_buffer_view_compute_caret_old(view->buffer_view, line, index, real_x, pview->display, &new);
+ addr = g_buffer_view_compute_caret(view->buffer_view, real_x, real_y, pview->display, &new);
gtk_buffer_view_relocate_caret(view, &new, addr);
}
@@ -608,6 +613,40 @@ static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *view, c
/******************************************************************************
* *
+* Paramètres : view = composant GTK à consulter. *
+* line = ligne de tampon où se trouve le curseur. [OUT] *
+* segment = eventuel segment de ligne actif. [OUT] *
+* *
+* Description : Fournit des éléments liés à la position courante dans la vue.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool gtk_buffer_view_get_position(const GtkBufferView *view, GBufferLine **line, GBufferSegment **segment)
+{
+ GBufferSegment *seg; /* Segment à récupérer */
+
+ /* Si aucune position n'est définie... */
+ if (view->caret_addr == NULL)
+ return false;
+
+ *line = g_buffer_view_find_line_and_segment_at(view->buffer_view,
+ (gint []){ view->caret.x }, view->caret.y, NULL,
+ GTK_VIEW_PANEL(view)->display, &seg);
+
+ if (segment != NULL)
+ *segment = seg;
+
+ return (line != NULL);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : view = composant GTK à manipuler. *
* cairo = assistant pour la création de rendus. *
* area = taille de la surface réduite à disposition. *
diff --git a/src/gtkext/gtkviewpanel-int.h b/src/gtkext/gtkviewpanel-int.h
index 90bd141..220b253 100644
--- a/src/gtkext/gtkviewpanel-int.h
+++ b/src/gtkext/gtkviewpanel-int.h
@@ -51,6 +51,9 @@ typedef void (* prepare_resize_fc) (GtkViewPanel *);
/* Indique la position d'affichage d'une adresse donnée. */
typedef bool (* get_addr_coordinates_fc) (const GtkViewPanel *, const vmpa2t *, gint *, gint *, ScrollPositionTweak);
+/* Fournit des éléments liés à la position courante dans la vue. */
+typedef bool (* get_view_position_fc) (const GtkViewPanel *, GBufferLine **, GBufferSegment **);
+
/* Place en cache un rendu destiné à l'aperçu graphique rapide. */
typedef void (* cache_glance_fc) (GtkViewPanel *, cairo_t *, const GtkAllocation *, double);
@@ -87,6 +90,7 @@ struct _GtkViewPanelClass
compute_requested_size compute_size; /* Calcul de la taille requise */
compute_scroll_inc compute_inc; /* Calcul des bonds */
get_addr_coordinates_fc get_coordinates;/* Conversion adresse <-> pos. */
+ get_view_position_fc get_position; /* Indications sur la position */
};
diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c
index 40ae038..d434f1e 100644
--- a/src/gtkext/gtkviewpanel.c
+++ b/src/gtkext/gtkviewpanel.c
@@ -822,6 +822,43 @@ void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr, S
/******************************************************************************
* *
+* Paramètres : panel = composant GTK à consulter. *
+* line = ligne de tampon où se trouve le curseur. [OUT] *
+* segment = eventuel segment de ligne actif. [OUT] *
+* *
+* Description : Fournit des éléments liés à la position courante dans la vue.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_view_panel_get_position(const GtkViewPanel *panel, GBufferLine **line, GBufferSegment **segment)
+{
+ bool result; /* Bilan de l'opération */
+
+ if (GTK_VIEW_PANEL_GET_CLASS(panel)->get_position == NULL)
+ return false;
+
+ result = GTK_VIEW_PANEL_GET_CLASS(panel)->get_position(panel, line, segment);
+
+ if (result)
+ {
+ g_object_ref(G_OBJECT(*line));
+
+ if (segment != NULL && *segment != NULL)
+ g_object_ref(G_OBJECT(*segment));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : panel = composant GTK à manipuler. *
* cairo = assistant pour la création de rendus. *
* area = taille de la surface réduite à disposition. *
diff --git a/src/gtkext/gtkviewpanel.h b/src/gtkext/gtkviewpanel.h
index c733314..080ad97 100644
--- a/src/gtkext/gtkviewpanel.h
+++ b/src/gtkext/gtkviewpanel.h
@@ -84,6 +84,9 @@ typedef enum _ScrollPositionTweak
/* S'assure qu'une adresse donnée est visible à l'écran. */
void gtk_view_panel_scroll_to_address(GtkViewPanel *, const vmpa2t *, ScrollPositionTweak);
+/* Fournit des éléments liés à la position courante dans la vue. */
+bool gtk_view_panel_get_position(const GtkViewPanel *, GBufferLine **, GBufferSegment **);
+
/* Place en cache un rendu destiné à l'aperçu graphique rapide. */
void gtk_view_panel_cache_glance(GtkViewPanel *, cairo_t *, const GtkAllocation *, double);
diff --git a/src/gui/editem-int.h b/src/gui/editem-int.h
index 7dc3ad4..b76769f 100644
--- a/src/gui/editem-int.h
+++ b/src/gui/editem-int.h
@@ -40,6 +40,9 @@
typedef void (* update_item_binary_fc) (GEditorItem *, GLoadedBinary *);
/* Réagit à un changement d'affichage principal de contenu. */
+typedef void (* manage_item_view_fc) (GEditorItem *, GtkViewPanel *, bool);
+
+/* Réagit à un changement d'affichage principal de contenu. */
typedef void (* update_item_view_fc) (GEditorItem *, GtkViewPanel *);
/* Concentre l'attention de l'ensemble sur une adresse donnée. */
@@ -70,6 +73,7 @@ struct _GEditorItemClass
GObjectClass parent; /* A laisser en premier */
update_item_binary_fc update_binary; /* Changement de binaire */
+ manage_item_view_fc manage_view; /* Gestion des vues manipulées */
update_item_view_fc update_view; /* Rechargement dû à une vue */
update_item_view_fc update_content; /* Rechargement dû à un contenu*/
focus_addr_fc focus_addr; /* Prête attention à une addr. */
diff --git a/src/gui/editem.c b/src/gui/editem.c
index cde5d7f..e4c74a9 100644
--- a/src/gui/editem.c
+++ b/src/gui/editem.c
@@ -229,6 +229,37 @@ void change_editor_items_current_binary(GObject *ref, GLoadedBinary *binary)
/******************************************************************************
* *
+* Paramètres : view = nouveau panneau d'affichage nouveau. *
+* created = fait état d'une création ou d'une destruction. *
+* *
+* Description : Lance une actualisation liée à une modification du cheptel. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void manage_editor_items_view(GtkViewPanel *view, bool created)
+{
+ GEditorItem *iter; /* Boucle de parcours */
+ GEditorItemClass *klass; /* Classe correspondante */
+
+ editem_list_for_each(iter, _editem_list)
+ {
+ klass = G_EDITOR_ITEM_GET_CLASS(iter);
+
+ if (klass->manage_view != NULL)
+ klass->manage_view(iter, view, created);
+
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : ref = espace de référencement global. *
* view = nouveau panneau d'affichage actif. *
* *
diff --git a/src/gui/editem.h b/src/gui/editem.h
index d1b91a5..827c752 100644
--- a/src/gui/editem.h
+++ b/src/gui/editem.h
@@ -79,6 +79,9 @@ void register_editor_item(GEditorItem *);
/* Lance une actualisation du fait d'un changement de binaire. */
void change_editor_items_current_binary(GObject *, GLoadedBinary *);
+/* Lance une actualisation liée à une modification du cheptel. */
+void manage_editor_items_view(GtkViewPanel *, bool);
+
/* Lance une actualisation du fait d'un changement de vue. */
void change_editor_items_current_view(GObject *, GtkViewPanel *);
diff --git a/src/gui/menus/binary.c b/src/gui/menus/binary.c
index 50a9143..c93ad57 100644
--- a/src/gui/menus/binary.c
+++ b/src/gui/menus/binary.c
@@ -121,7 +121,7 @@ static void mcb_binary_entry_points(GtkMenuItem *menuitem, GMenuBar *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);
+ dialog = create_gotox_dialog_for_entry_points(GTK_WINDOW(ref), binary);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
{
diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c
index 8893ce9..3c1d6ac 100644
--- a/src/gui/menus/edition.c
+++ b/src/gui/menus/edition.c
@@ -28,19 +28,27 @@
#include <i18n.h>
+#include "../../arch/target.h"
#include "../../dialogs/bookmark.h"
#include "../../dialogs/goto.h"
+#include "../../dialogs/gotox.h"
#include "../../gtkext/easygtk.h"
#include "../../gtkext/gtkbufferview.h"
-/* Réagit avec le menu "Edition -> Signets -> Basculer...". */
-static void mcb_edition_bookmarks_toggle(GtkMenuItem *, GMenuBar *);
-
/* Réagit avec le menu "Edition -> Aller à l'adresse...". */
static void mcb_edition_goto(GtkMenuItem *, GMenuBar *);
+/* Réagit avec le menu "Edition -> Suivre la référence". */
+static void mcb_edition_follow_ref(GtkMenuItem *, GMenuBar *);
+
+/* Réagit avec le menu "Edition -> Lister toutes les réfs...". */
+static void mcb_edition_list_xrefs(GtkMenuItem *, GMenuBar *);
+
+/* Réagit avec le menu "Edition -> Signets -> Basculer...". */
+static void mcb_edition_bookmarks_toggle(GtkMenuItem *, GMenuBar *);
+
/******************************************************************************
@@ -71,6 +79,27 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b
menubar = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(result), menubar);
+ submenuitem = qck_create_menu_item(NULL, NULL, _("Go to address..."),
+ G_CALLBACK(mcb_edition_goto), bar);
+ add_accelerator_to_menu_item(submenuitem, "<Ctrl>G", 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_edit_follow_ref", _("Follow the reference"),
+ G_CALLBACK(mcb_edition_follow_ref), bar);
+ add_accelerator_to_menu_item(submenuitem, "Return", accgroup);
+ gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
+
+ submenuitem = qck_create_menu_item(ref, "mnu_edit_list_xrefs", _("List all references leading to..."),
+ G_CALLBACK(mcb_edition_list_xrefs), bar);
+ add_accelerator_to_menu_item(submenuitem, "X", 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(NULL, NULL, _("Bookmarks"), NULL, NULL);
gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
@@ -82,13 +111,6 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b
add_accelerator_to_menu_item(deepmenuitem, "<Ctrl>D", accgroup);
gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem);
- submenuitem = qck_create_menu_separator();
- gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
-
- submenuitem = qck_create_menu_item(NULL, NULL, _("Go to address..."),
- G_CALLBACK(mcb_edition_goto), bar);
- add_accelerator_to_menu_item(submenuitem, "<Ctrl>G", accgroup);
- gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
return result;
@@ -100,6 +122,171 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b
* Paramètres : menuitem = élément de menu sélectionné. *
* bar = barre de menu parente. *
* *
+* Description : Réagit avec le menu "Edition -> Aller à l'adresse...". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void mcb_edition_goto(GtkMenuItem *menuitem, GMenuBar *bar)
+{
+ GObject *ref; /* Espace de référencements */
+ GtkWidget *dialog; /* Boîte de dialogue à montrer */
+ vmpa2t *addr; /* Adresse de destination */
+ GtkViewPanel *vpanel; /* Afficheur effectif de code */
+
+ ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar));
+ dialog = create_goto_dialog(GTK_WINDOW(ref));
+
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
+ {
+ addr = get_address_from_goto_dialog(dialog);
+
+ vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
+ gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER);
+
+ delete_vmpa(addr);
+
+ }
+
+ gtk_widget_destroy(dialog);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : menuitem = élément de menu sélectionné. *
+* bar = barre de menu parente. *
+* *
+* Description : Réagit avec le menu "Edition -> Suivre la référence". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void mcb_edition_follow_ref(GtkMenuItem *menuitem, GMenuBar *bar)
+{
+ GtkViewPanel *vpanel; /* Afficheur effectif de code */
+ GBufferLine *line; /* Ligne de position courante */
+ GBufferSegment *segment; /* Segment actif s'il existe */
+ GObject *creator; /* Créateur à l'orgine du seg. */
+ virt_t virt; /* Adresse virtuelle */
+ vmpa2t addr; /* Adresse de destination */
+
+ vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
+
+ if (gtk_view_panel_get_position(vpanel, &line, &segment))
+ {
+ if (segment != NULL)
+ creator = g_buffer_segment_get_creator(segment);
+ else
+ creator = NULL;
+
+ if (creator != NULL)
+ {
+ /**
+ * On fait le pari de reposer uniquement sur des adresses virtuelles !
+ * A changer dans un futur ?
+ */
+
+ virt = VMPA_NO_VIRTUAL;
+
+ if (G_IS_TARGET_OPERAND(creator))
+ virt = g_target_operand_get_addr(G_TARGET_OPERAND(creator));
+
+ else if (G_IS_IMM_OPERAND(creator))
+ {
+ if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(creator), &virt))
+ virt = VMPA_NO_VIRTUAL;
+ }
+
+ if (virt != VMPA_NO_VIRTUAL)
+ {
+ init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
+ gtk_view_panel_scroll_to_address(vpanel, &addr, SPT_CENTER);
+ }
+
+ g_object_unref(creator);
+
+ }
+
+ if (segment != NULL) g_object_unref(G_OBJECT(segment));
+ g_object_unref(G_OBJECT(line));
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : menuitem = élément de menu sélectionné. *
+* bar = barre de menu parente. *
+* *
+* Description : Réagit avec le menu "Edition -> Lister toutes les réfs...". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void mcb_edition_list_xrefs(GtkMenuItem *menuitem, GMenuBar *bar)
+{
+ GtkViewPanel *vpanel; /* Afficheur effectif de code */
+ GBufferLine *line; /* Ligne de position courante */
+ const mrange_t *range; /* Couverture en mémoire */
+ GLoadedBinary *binary; /* Représentation binaire */
+ GArchInstruction *list; /* Ensemble des instructions */
+ GArchInstruction *instr; /* Point de croisements */
+ GObject *ref; /* Espace de référencements */
+ GtkWidget *dialog; /* Boîte de dialogue à montrer */
+ vmpa2t *addr; /* Adresse de destination */
+
+ vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
+
+ if (gtk_view_panel_get_position(vpanel, &line, NULL))
+ {
+ range = g_buffer_line_get_range(line);
+
+ binary = g_editor_item_get_current_binary(G_EDITOR_ITEM(bar));
+ list = g_loaded_binary_get_instructions(binary);
+
+ instr = g_arch_instruction_find_by_range(list, range);
+
+ ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar));
+
+ dialog = create_gotox_dialog_for_cross_references(GTK_WINDOW(ref), binary, instr, true);
+
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
+ {
+ addr = get_address_from_gotox_dialog(dialog);
+
+ gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER);
+
+ delete_vmpa(addr);
+
+ }
+
+ gtk_widget_destroy(dialog);
+
+ g_object_unref(G_OBJECT(line));
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : menuitem = élément de menu sélectionné. *
+* bar = barre de menu parente. *
+* *
* Description : Réagit avec le menu "Edition -> Signets -> Basculer...". *
* *
* Retour : - *
@@ -192,42 +379,3 @@ static void mcb_edition_bookmarks_toggle(GtkMenuItem *menuitem, GMenuBar *bar)
g_object_unref(G_OBJECT(collec));
}
-
-
-/******************************************************************************
-* *
-* Paramètres : menuitem = élément de menu sélectionné. *
-* bar = barre de menu parente. *
-* *
-* Description : Réagit avec le menu "Edition -> Aller à l'adresse...". *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void mcb_edition_goto(GtkMenuItem *menuitem, GMenuBar *bar)
-{
- GObject *ref; /* Espace de référencements */
- GtkWidget *dialog; /* Boîte de dialogue à montrer */
- vmpa2t *addr; /* Adresse de destination */
- GtkViewPanel *vpanel; /* Afficheur effectif de code */
-
- ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar));
- dialog = create_goto_dialog(GTK_WINDOW(ref));
-
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
- {
- addr = get_address_from_goto_dialog(dialog);
-
- vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
- gtk_view_panel_scroll_to_address(vpanel, addr, SPT_CENTER);
-
- delete_vmpa(addr);
-
- }
-
- gtk_widget_destroy(dialog);
-
-}
diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c
index 77ff7cd..cc69e0d 100644
--- a/src/gui/menus/menubar.c
+++ b/src/gui/menus/menubar.c
@@ -72,6 +72,9 @@ static void g_menu_bar_dispose(GMenuBar *);
/* Procède à la libération totale de la mémoire. */
static void g_menu_bar_finalize(GMenuBar *);
+/* Lance une actualisation liée à une modification du cheptel. */
+static void manage_view_in_menu_bar(GMenuBar *, GtkViewPanel *, bool);
+
/* Lance une actualisation du fait d'un changement de vue. */
static void update_menu_bar_for_view(GMenuBar *, GtkViewPanel *);
@@ -108,6 +111,7 @@ static void g_menu_bar_class_init(GMenuBarClass *klass)
editem = G_EDITOR_ITEM_CLASS(klass);
+ editem->manage_view = (manage_item_view_fc)manage_view_in_menu_bar;
editem->update_view = (update_item_view_fc)update_menu_bar_for_view;
editem->update_project = (update_project_fc)update_menu_bar_for_project;
@@ -247,6 +251,73 @@ GEditorItem *g_menu_bar_new(GObject *ref, GtkAccelGroup *accgroup)
/******************************************************************************
* *
+* Paramètres : bar = barre de menus à actualiser. *
+* view = nouveau panneau d'affichage nouveau. *
+* created = fait état d'une création ou d'une destruction. *
+* *
+* Description : Lance une actualisation liée à une modification du cheptel. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void manage_view_in_menu_bar(GMenuBar *bar, GtkViewPanel *view, bool created)
+{
+
+ gboolean view_got_focus(GtkWidget *widget, GtkDirectionType dir, GObject *ref)
+ {
+ GtkWidget *item;
+
+ item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_follow_ref"));
+
+ gtk_widget_set_sensitive(item, TRUE);
+
+ item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_list_xrefs"));
+
+ gtk_widget_set_sensitive(item, TRUE);
+
+ return FALSE;
+
+ }
+
+ gboolean view_lost_focus(GtkWidget *widget, GtkDirectionType dir, GObject *ref)
+ {
+ GtkWidget *item;
+
+ item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_follow_ref"));
+
+ gtk_widget_set_sensitive(item, FALSE);
+
+ item = GTK_WIDGET(g_object_get_data(ref, "mnu_edit_list_xrefs"));
+
+ gtk_widget_set_sensitive(item, FALSE);
+
+ return FALSE;
+
+ }
+
+
+ if (created)
+ {
+ g_signal_connect(view, "focus-in-event", G_CALLBACK(view_got_focus), G_EDITOR_ITEM(bar)->ref);
+ g_signal_connect(view, "focus-out-event", G_CALLBACK(view_lost_focus), G_EDITOR_ITEM(bar)->ref);
+ }
+ else
+ {
+ g_signal_handlers_disconnect_by_func(view, G_CALLBACK(view_got_focus), G_EDITOR_ITEM(bar)->ref);
+ g_signal_handlers_disconnect_by_func(view, G_CALLBACK(view_lost_focus), G_EDITOR_ITEM(bar)->ref);
+ }
+
+
+ // update_menu_view_for_view(bar->view, view, bar);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : bar = barre de menus à actualiser. *
* view = nouveau panneau d'affichage actif. *
* *
diff --git a/src/project.c b/src/project.c
index c8d23f7..5786532 100644
--- a/src/project.c
+++ b/src/project.c
@@ -403,6 +403,8 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina
break;
}
+ manage_editor_items_view(GTK_VIEW_PANEL(view), true);
+
gtk_widget_show(view);
loaded->views[i] = GTK_VIEW_PANEL(view);
@@ -470,6 +472,9 @@ void g_study_project_detach_binary(GStudyProject *project, GLoadedBinary *binary
//gtk_dock_panel_remove_item(dpanel, ditem);
+
+ //manage_editor_items_view(GObject *ref, GtkViewPanel *view, bool created)
+
for (i = 0; i < project->binaries_count; i++)
if (project->binaries[i]->binary == binary) break;