summaryrefslogtreecommitdiff
path: root/src/gtkext/gtkstatusstack.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-12-16 17:20:06 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-12-16 17:20:06 (GMT)
commit7c40b70d6c1e1e13dadf876c8dda60b525616d47 (patch)
tree743d0b1981a13fb2de0d2eaacc4f644cf84204c0 /src/gtkext/gtkstatusstack.c
parent4d313d845a60e908b9e2723cc1fe2bdbbdded315 (diff)
Built a new improved status bar for instructions information.
Diffstat (limited to 'src/gtkext/gtkstatusstack.c')
-rw-r--r--src/gtkext/gtkstatusstack.c609
1 files changed, 609 insertions, 0 deletions
diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c
new file mode 100644
index 0000000..e9a61d8
--- /dev/null
+++ b/src/gtkext/gtkstatusstack.c
@@ -0,0 +1,609 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * gtkstatusstack.c - empilement d'informations de statut
+ *
+ * Copyright (C) 2015 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 "gtkstatusstack.h"
+
+
+#include <inttypes.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "easygtk.h"
+#include "../common/extstr.h"
+
+
+
+/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
+
+
+/* Navigation au sein d'assemblage */
+typedef struct _assembly_info assembly_info;
+
+
+/* Abstration d'une gestion de barre de statut (instance) */
+struct _GtkStatusStack
+{
+ GtkBin parent; /* A laisser en premier */
+
+ GtkWidget *asm_status; /* Barre de status d'assemblage*/
+ assembly_info *asm_info; /* Informations courantes */
+
+};
+
+/* Abstration d'une gestion de barre de statut (classe) */
+struct _GtkStatusStackClass
+{
+ GtkBinClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des barres de statut améliorées. */
+static void gtk_status_stack_class_init(GtkStatusStackClass *);
+
+/* Initialise une instance de barre de statut améliorée. */
+static void gtk_status_stack_init(GtkStatusStack *);
+
+/* Supprime toutes les références externes. */
+static void gtk_status_stack_dispose(GtkStatusStack *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_status_stack_finalize(GtkStatusStack *);
+
+/* S'assure de l'affichage du niveau de pile attendu. */
+static void gtk_status_stack_switch(GtkStatusStack *, GtkWidget *);
+
+
+
+/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */
+
+
+/* Navigation au sein d'assemblage */
+struct _assembly_info
+{
+ mrange_t current; /* Emplacement correspondant */
+
+ char *segment; /* Segment d'appartenance */
+
+ VMPA_BUFFER(phys); /* Localisation physique */
+ VMPA_BUFFER(virt); /* Localisation virtuelle */
+
+ char *symbol; /* Eventuel symbole concerné */
+
+ const char *encoding; /* Encodage de l'instruction */
+ phys_t size; /* Taille de l'instruction */
+
+};
+
+
+/* Supprime l'empreinte mémoire d'informations d'assemblage. */
+static void reset_assembly_info(assembly_info *);
+
+/* Construit une barre d'état pour language d'assemblage. */
+static GtkWidget *build_assembly_status_stack(GtkStatusStack *);
+
+/* Réagit à un redimensionnement de la barre de désassemblage. */
+static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject *);
+
+/* Réagit à un clic sur l'icône de zoom. */
+static void on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GtkStatusStack *);
+
+/* S'assure de l'affichage à jour de la partie "assemblage". */
+static void gtk_status_stack_show_current_instruction(GtkStatusStack *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GESTION EXTERIEURE DE LA BARRE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type de la barre de statut améliorée. */
+G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BIN)
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des barres de statut améliorées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_class_init(GtkStatusStackClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = instance GTK à initialiser. *
+* *
+* Description : Initialise une instance de barre de statut améliorée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_init(GtkStatusStack *stack)
+{
+ stack->asm_status = build_assembly_status_stack(stack);
+ stack->asm_info = (assembly_info *)calloc(1, sizeof(assembly_info));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_dispose(GtkStatusStack *stack)
+{
+ g_object_unref(G_OBJECT(stack->asm_status));
+
+ G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_finalize(GtkStatusStack *stack)
+{
+ reset_assembly_info(stack->asm_info);
+
+ free(stack->asm_info);
+
+ G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une nouvelle instance de barre de statut. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *gtk_status_stack_new(void)
+{
+ return g_object_new(GTK_TYPE_STATUS_STACK, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = pile de statuts à considérer. *
+* next = niveau de pile à afficher désormais. *
+* *
+* Description : S'assure de l'affichage du niveau de pile attendu. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_switch(GtkStatusStack *stack, GtkWidget *next)
+{
+ GtkWidget *child; /* Support courant */
+
+ child = gtk_bin_get_child(GTK_BIN(stack));
+
+ if (child != next)
+ {
+ if (child != NULL)
+ gtk_container_remove(GTK_CONTAINER(stack), child);
+
+ g_object_ref(G_OBJECT(next));
+ gtk_container_add(GTK_CONTAINER(stack), next);
+
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à réinitialiser. *
+* *
+* Description : Supprime l'empreinte mémoire d'informations d'assemblage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void reset_assembly_info(assembly_info *info)
+{
+ if (info->segment != NULL)
+ {
+ free(info->segment);
+ info->segment = NULL;
+ }
+
+ if (info->symbol != NULL)
+ {
+ free(info->symbol);
+ info->symbol = NULL;
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = composant global en cours de construction. *
+* *
+* Description : Construit une barre d'état pour language d'assemblage. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack)
+{
+ GtkWidget *result; /* Support à retourner */
+ GObject *ref; /* Espace de référencements */
+ GtkWidget *hbox; /* Sous-division horizontale */
+ GtkWidget *label; /* Etiquette pour impression */
+ GtkWidget *zoom; /* Sélection du zoom courant */
+
+ result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_show(result);
+
+ ref = G_OBJECT(result);
+
+ g_signal_connect(result, "size-allocate", G_CALLBACK(on_size_allocate_for_asm_status), ref);
+
+ /* Première partie : navigation */
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16);
+ gtk_widget_show(hbox);
+ gtk_box_pack_start(GTK_BOX(result), hbox, TRUE, TRUE, 8);
+
+ label = qck_create_label(ref, "segment", NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ label = qck_create_label(ref, "phys", NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ label = qck_create_label(ref, "virt", NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ label = qck_create_label(ref, "offset", NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ /* Seconde partie : architecture */
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ g_object_set_data(ref, "arch_box", hbox);
+ gtk_widget_show(hbox);
+ gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, TRUE, 8);
+
+ label = qck_create_label(ref, "arch", NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ label = qck_create_label(ref, "size", NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ /* Troisième partie : affichage */
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_widget_show(hbox);
+ gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, FALSE, 8);
+
+ zoom = qck_create_entry(ref, "zoom", "100%");
+ gtk_entry_set_icon_from_icon_name(GTK_ENTRY(zoom), GTK_ENTRY_ICON_SECONDARY, "go-up-symbolic");
+
+ g_signal_connect(zoom, "icon-press", G_CALLBACK(on_zoom_icon_press), stack);
+
+ gtk_box_pack_start(GTK_BOX(hbox), zoom, FALSE, TRUE, 0);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : widget = composant graphique qui vient d'évoluer. *
+* allocation = espace réservé pour le composant visé. *
+* ref = espace de référencement global. *
+* *
+* Description : Réagit à un redimensionnement de la barre de désassemblage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *allocation, GObject *ref)
+{
+ GtkWidget *hbox; /* Sous-division horizontale */
+
+ hbox = GTK_WIDGET(g_object_get_data(ref, "arch_box"));
+
+ gtk_widget_set_size_request(hbox, (allocation->width * 40) / 100, -1);
+
+ /**
+ * On intervient après que le containeur soit passer collecter les tailles
+ * de ses enfants lors de son redimensionnement.
+ *
+ * Donc on force un prise en compte des changements.
+ */
+ gtk_container_check_resize(GTK_CONTAINER(widget));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = zone de texte visée par la procédure. *
+* icon_pos = position de l'image associée à l'entrée. *
+* event = informations liées à l'événement. *
+* stack = composant graphique de gestion des statuts. *
+* *
+* Description : Réagit à un clic sur l'icône de zoom. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GtkStatusStack *stack)
+{
+ GtkWidget *popup; /* Popup à faire surgir */
+ GdkRectangle rect; /* Zone précise à cibler */
+
+ if (event->button != GDK_BUTTON_PRIMARY)
+ return;
+
+ popup = gtk_popover_new(GTK_WIDGET(entry));
+
+ gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect);
+ gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect);
+
+ gtk_widget_show(popup);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* binary = binaire chargé rassemblant l'ensemble des infos. *
+* instr = instruction désassemblée ciblée graphiquement. *
+* *
+* Description : Actualise les informations liées une position d'assemblage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GLoadedBinary *binary, const GArchInstruction *instr)
+{
+ assembly_info *info; /* Informations à constituer */
+ GExeFormat *format; /* Format de binaire à traiter */
+ const mrange_t *range; /* Emplacement d'instruction */
+ const vmpa2t *addr; /* Localisation de départ */
+ GBinPortion *portions; /* Portions binaires existantes*/
+ GBinPortion *portion; /* Zone mémoire d'appartenance */
+ const char *text; /* Texte au contenu à copier */
+ GBinSymbol *symbol; /* Symbole présent à l'adresse */
+ phys_t diff; /* Décallage de l'adresse */
+ const char *label; /* Description d'un symbole */
+ vmpa2t tmp; /* Zone de construction temp. */
+ VMPA_BUFFER(offset); /* Décalage physique */
+
+ info = stack->asm_info;
+
+ format = g_loaded_binary_get_format(binary);
+
+ /* Bascule vers une zone courante nouvelle ? */
+
+ range = g_arch_instruction_get_range(instr);
+ addr = get_mrange_addr(range);
+
+ if (cmp_mrange(&info->current, range) == 0)
+ goto gssuci_useless;
+
+ /* Réinitialisation */
+
+ reset_assembly_info(info);
+
+ copy_mrange(&info->current, range);
+
+ /* Zone d'appartenance */
+
+ portions = g_exe_format_get_portions(format);
+
+ portion = g_binary_portion_find_at_addr(portions, addr, (GdkRectangle []) { });
+
+ text = g_binary_portion_get_desc(portion);
+
+ if (text != NULL)
+ info->segment = strdup(text);
+ else
+ info->segment = strdup(_("Binary"));
+
+ /* Adresses de base */
+
+ vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL);
+
+ vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL);
+
+ info->encoding = g_arch_instruction_get_encoding(instr);
+
+ info->size = get_mrange_length(range);
+
+ /* Symbole concerné */
+
+ if (g_binary_format_resolve_symbol(G_BIN_FORMAT(format), addr, &symbol, &diff))
+ {
+ label = g_binary_symbol_get_label(symbol);
+
+ if (label != NULL)
+ {
+ info->symbol = strdup(label);
+
+ info->symbol = stradd(info->symbol, "+");
+
+ init_vmpa(&tmp, diff, VMPA_NO_VIRTUAL);
+ vmpa2_phys_to_string(&tmp, MDS_UNDEFINED, offset, NULL);
+
+ info->symbol = stradd(info->symbol, offset);
+
+ }
+
+ g_object_unref(G_OBJECT(symbol));
+
+ }
+
+ /* Nettoyage et conclusion */
+
+ gtk_status_stack_show_current_instruction(stack);
+
+ gssuci_useless:
+
+ //g_object_unref(G_OBJECT(format));
+
+ ;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = pile de statuts à manipuler. *
+* *
+* Description : S'assure de l'affichage à jour de la partie "assemblage". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_show_current_instruction(GtkStatusStack *stack)
+{
+ GObject *ref; /* Espace de référencements */
+ assembly_info *info; /* Informations à consulter */
+ GtkLabel *label; /* Etiquette à actualiser */
+ char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */
+ char *content; /* Contenu dynamique */
+
+ gtk_status_stack_switch(stack, stack->asm_status);
+
+ ref = G_OBJECT(stack->asm_status);
+ info = stack->asm_info;
+
+ /* Première partie : navigation */
+
+ label = GTK_LABEL(g_object_get_data(ref, "segment"));
+ gtk_label_set_text(label, info->segment);
+
+ snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys);
+
+ label = GTK_LABEL(g_object_get_data(ref, "phys"));
+ gtk_label_set_text(label, raw_pos);
+
+ snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt);
+
+ label = GTK_LABEL(g_object_get_data(ref, "virt"));
+ gtk_label_set_text(label, raw_pos);
+
+ label = GTK_LABEL(g_object_get_data(ref, "offset"));
+ gtk_label_set_text(label, info->symbol != NULL ? info->symbol : "");
+
+ /* Seconde partie : architecture */
+
+ label = GTK_LABEL(g_object_get_data(ref, "arch"));
+ gtk_label_set_text(label, info->encoding);
+
+ if (info->size > 1)
+ asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("bytes"));
+ else
+ asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("byte"));
+
+ label = GTK_LABEL(g_object_get_data(ref, "size"));
+ gtk_label_set_text(label, content);
+
+ free(content);
+
+}