diff options
Diffstat (limited to 'src/gui/panels')
| -rw-r--r-- | src/gui/panels/Makefile.am | 2 | ||||
| -rw-r--r-- | src/gui/panels/bintree.c | 2 | ||||
| -rw-r--r-- | src/gui/panels/bintree.ui | 4 | ||||
| -rw-r--r-- | src/gui/panels/errors.c | 956 | ||||
| -rw-r--r-- | src/gui/panels/errors.h | 62 | ||||
| -rw-r--r-- | src/gui/panels/errors.ui | 132 | ||||
| -rw-r--r-- | src/gui/panels/gresource.xml | 1 | 
7 files changed, 1156 insertions, 3 deletions
| diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am index 7dc1cc5..506ae38 100644 --- a/src/gui/panels/Makefile.am +++ b/src/gui/panels/Makefile.am @@ -5,11 +5,13 @@ noinst_LTLIBRARIES  = libguipanels.la  UI_FILES =								\  	bintree.ui							\ +	errors.ui							\  	welcome.ui  libguipanels_la_SOURCES =				\  	bintree.h bintree.c					\  	bookmarks.h bookmarks.c				\ +	errors.h errors.c					\  	glance.h glance.c					\  	history.h history.c					\  	log.h log.c							\ diff --git a/src/gui/panels/bintree.c b/src/gui/panels/bintree.c index 9963f94..1fa0cfe 100644 --- a/src/gui/panels/bintree.c +++ b/src/gui/panels/bintree.c @@ -199,7 +199,7 @@ static void g_bintree_panel_init(GBintreePanel *panel)      g_object_ref(G_OBJECT(base->widget));      gtk_widget_unparent(base->widget); -    /* Liste des projets récents */ +    /* Liste des portions binaires */      treeview = GTK_TREE_VIEW(gtk_builder_get_object(panel->builder, "treeview")); diff --git a/src/gui/panels/bintree.ui b/src/gui/panels/bintree.ui index 678cc56..aa5a112 100644 --- a/src/gui/panels/bintree.ui +++ b/src/gui/panels/bintree.ui @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.18.3 --> +<!-- Generated with glade 3.20.0 -->  <interface>    <requires lib="gtk+" version="3.12"/>    <object class="GtkAdjustment" id="adjustment1"> @@ -10,7 +10,7 @@    <object class="GtkImage" id="collapse_img">      <property name="visible">True</property>      <property name="can_focus">False</property> -    <property name="pixbuf">../../../pixmaps/tbutton_collapse.png</property> +    <property name="pixbuf">../../../pixmaps/tbutton_expand.png</property>    </object>    <object class="GtkImage" id="expand_img">      <property name="visible">True</property> diff --git a/src/gui/panels/errors.c b/src/gui/panels/errors.c new file mode 100644 index 0000000..7d7226f --- /dev/null +++ b/src/gui/panels/errors.c @@ -0,0 +1,956 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * errors.c - panneau listant les erreurs au désassemblage + * + * Copyright (C) 2017 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide 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. + * + *  Chrysalide 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 this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "errors.h" + + +#include <assert.h> +#include <malloc.h> +#include <stdio.h> + + +#include <i18n.h> + + +#include "panel-int.h" +#include "../../format/format.h" +#include "../../gtkext/support.h" + + + +/* Origine de la dernière ouverture/fermeture reproductible */ +typedef enum _UserActionType +{ +    UAT_COLLAPSE,                           /* Fermeture totale            */ +    UAT_EXPAND,                             /* Ouverture totale            */ +    UAT_DEPTH,                              /* Descente contrôlée          */ + +} UserActionType; + + +/* Panneau de présentation des erreurs recontrées (instance) */ +struct _GErrorPanel +{ +    GPanelItem parent;                      /* A laisser en premier        */ + +    GtkBuilder *builder;                    /* Constructeur utilisé        */ + +    GLoadedBinary *binary;                  /* Binaire représenté          */ + +    size_t count;                           /* Nombre de soucis présents   */ +    size_t kept;                            /* Nombre d'éléments affichés  */ + +}; + +/* Panneau de présentation des erreurs recontrées (classe) */ +struct _GErrorPanelClass +{ +    GPanelItemClass parent;                 /* A laisser en premier        */ + +    cairo_surface_t *format_img;            /* Image pour les formats      */ +    cairo_surface_t *disass_img;            /* Image pour les architectures*/ +    cairo_surface_t *output_img;            /* Image pour les impressions  */ + +}; + + +/* Colonnes de la liste des messages */ +typedef enum _ErrorTreeColumn +{ +    ETC_ICON,                               /* Image de représentation     */ +    ETC_PHYS,                               /* Position physique           */ +    ETC_VIRT,                               /* Position virtuelle          */ +    ETC_DESC,                               /* Description humaine         */ + +    ETC_VISIBLE,                            /* Correspondance établie ?    */ +    ETC_ORIGIN,                             /* Source du soucis remonté    */ +    ETC_ERRNO,                              /* Code d'erreur associé       */ +    ETC_ADDR                                /* Position représentée        */ + +} BinaryTreeColumn; + + +/* Manipulation des erreurs de façon générique */ +typedef struct _error_desc_t +{ +    union +    { +        unsigned int type;                  /* Type de soucis #0           */ +        BinaryFormatError ftype;            /* Type de soucis #1           */ +        ArchProcessingError ptype;          /* Type de soucis #2           */ + +    }; + +    vmpa2t addr;                            /* Localisation d'un problème  */ +    char *desc;                             /* Description dudit problème  */ + +} error_desc_t; + + +/* Initialise la classe des panneaux d'affichage des erreurs. */ +static void g_error_panel_class_init(GErrorPanelClass *); + +/* Initialise une instance de panneau d'affichage des erreurs. */ +static void g_error_panel_init(GErrorPanel *); + +/* Supprime toutes les références externes. */ +static void g_error_panel_dispose(GErrorPanel *); + +/* Procède à la libération totale de la mémoire. */ +static void g_error_panel_finalize(GErrorPanel *); + +/* Organise le tri des erreurs présentées. */ +static gint sort_errors_in_panel(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *, gpointer); + +/* Réagit à un changement d'affichage principal de contenu. */ +static void update_panel_with_binary_errors(GErrorPanel *, GLoadedBinary *); + +/* Effectue la mise à jour du contenu du panneau d'erreurs. */ +static void update_error_panel(GErrorPanel *, GtkStatusStack *, activity_id_t); + +/* Actualise l'affichage des erreurs sur la base des filtres. */ +static void on_error_filter_toggled(GtkToggleButton *, GErrorPanel *); + +/* Filtre l'affichage du contenu du panneau d'erreurs. */ +static void filter_error_panel(GErrorPanel *, GtkStatusStack *, activity_id_t); + +/* Affiche un petit résumé concis des soucis remontés. */ +static void update_error_panel_summary(GPanelUpdate *, GErrorPanel *); + +/* Réagit au changement de sélection des portions. */ +static void on_error_selection_changed(GtkTreeSelection *, GErrorPanel *); + + + +/* Indique le type défini pour un panneau d'affichage des erreurs. */ +G_DEFINE_TYPE(GErrorPanel, g_error_panel, G_TYPE_PANEL_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des panneaux d'affichage des erreurs.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_error_panel_class_init(GErrorPanelClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GEditorItemClass *editem;               /* Encore une autre vision...  */ +    gchar *filename;                        /* Chemin d'accès à utiliser   */ +    GPanelItemClass *panel;                 /* Version parente de la classe*/ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_error_panel_dispose; +    object->finalize = (GObjectFinalizeFunc)g_error_panel_finalize; + +    editem = G_EDITOR_ITEM_CLASS(klass); + +    editem->update_binary = (update_item_binary_fc)update_panel_with_binary_errors; + +    filename = find_pixmap_file("error_file.png"); +    assert(filename != NULL); + +    klass->format_img = cairo_image_surface_create_from_png(filename); + +    filename = find_pixmap_file("error_cpu.png"); +    assert(filename != NULL); + +    klass->disass_img = cairo_image_surface_create_from_png(filename); + +    filename = find_pixmap_file("error_display.png"); +    assert(filename != NULL); + +    klass->output_img = cairo_image_surface_create_from_png(filename); + +    g_free(filename); + +    panel = G_PANEL_ITEM_CLASS(klass); + +    panel->unique = true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : panel = instance à initialiser.                              * +*                                                                             * +*  Description : Initialise une instance de panneau d'affichage des erreurs.  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_error_panel_init(GErrorPanel *panel) +{ +    GEditorItem *base;                      /* Version basique d'instance  */ +    GPanelItem *pitem;                      /* Version parente du panneau  */ +    GtkTreeSortable *store;                 /* Gestionnaire des données    */ +    GtkTreeModelFilter *filter;             /* Filtre pour l'arborescence  */ +    GtkTreeView *treeview;                  /* Affichage de la liste       */ +    GtkCellRenderer *renderer;              /* Moteur de rendu de colonne  */ +    GtkTreeViewColumn *column;              /* Colonne de la liste         */ + +    /* Eléments de base */ + +    base = G_EDITOR_ITEM(panel); + +    base->name = PANEL_ERRORS_ID; + +    pitem = G_PANEL_ITEM(panel); + +    pitem->personality = PIP_SINGLETON; +    pitem->lname = _("Disassembling errors"); +    pitem->dock_at_startup = true; +    pitem->path = strdup("S"); + +    /* Compléments propres */ + +    panel->binary = NULL; + +    /* Représentation graphique */ + +    panel->builder = gtk_builder_new_from_resource("/org/chrysalide/gui/panels/errors.ui"); + +    base->widget = GTK_WIDGET(gtk_builder_get_object(panel->builder, "box")); +    g_object_ref(G_OBJECT(base->widget)); +    gtk_widget_unparent(base->widget); + +    store = GTK_TREE_SORTABLE(gtk_builder_get_object(panel->builder, "store")); +    gtk_tree_sortable_set_sort_func(store, ETC_ADDR, sort_errors_in_panel, NULL, NULL); +    gtk_tree_sortable_set_sort_column_id(store, ETC_ADDR, GTK_SORT_ASCENDING); + +    filter = GTK_TREE_MODEL_FILTER(gtk_builder_get_object(panel->builder, "filter")); +    gtk_tree_model_filter_set_visible_column(filter, ETC_VISIBLE); + +    /* Liste des erreurs relevées */ + +    treeview = GTK_TREE_VIEW(gtk_builder_get_object(panel->builder, "treeview")); + +    column = gtk_tree_view_column_new(); +    gtk_tree_view_append_column(treeview, column); + +    renderer = gtk_cell_renderer_text_new(); +    g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); +    gtk_tree_view_column_pack_start(column, renderer, TRUE); +    gtk_tree_view_column_add_attribute(column, renderer, "markup", ETC_PHYS); + +    column = gtk_tree_view_column_new(); +    gtk_tree_view_append_column(treeview, column); + +    renderer = gtk_cell_renderer_text_new(); +    g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); +    gtk_tree_view_column_pack_start(column, renderer, TRUE); +    gtk_tree_view_column_add_attribute(column, renderer, "markup", ETC_VIRT); + +    column = gtk_tree_view_column_new(); +    gtk_tree_view_append_column(treeview, column); + +    renderer = gtk_cell_renderer_pixbuf_new(); +    gtk_tree_view_column_pack_start(column, renderer, FALSE); +    gtk_tree_view_column_add_attribute(column, renderer, "surface", ETC_ICON); + +    renderer = gtk_cell_renderer_text_new(); +    gtk_tree_view_column_pack_end(column, renderer, TRUE); +    gtk_tree_view_column_add_attribute(column, renderer, "markup", ETC_DESC); + +    /* Connexion des signaux */ + +    gtk_builder_add_callback_symbols(panel->builder, +                                     "gtk_tree_view_collapse_all", G_CALLBACK(gtk_tree_view_collapse_all), +                                     "gtk_tree_view_expand_all", G_CALLBACK(gtk_tree_view_expand_all), +                                     "on_error_filter_toggled", G_CALLBACK(on_error_filter_toggled), +                                     "on_error_selection_changed", G_CALLBACK(on_error_selection_changed), +                                     NULL); + +    gtk_builder_connect_signals(panel->builder, panel); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : panel = instance d'objet GLib à traiter.                     * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_error_panel_dispose(GErrorPanel *panel) +{ +    g_object_unref(G_OBJECT(panel->builder)); + +    if (panel->binary != NULL) +        g_object_unref(G_OBJECT(panel->binary)); + +    G_OBJECT_CLASS(g_error_panel_parent_class)->dispose(G_OBJECT(panel)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : panel = instance d'objet GLib à traiter.                     * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_error_panel_finalize(GErrorPanel *panel) +{ +    G_OBJECT_CLASS(g_error_panel_parent_class)->finalize(G_OBJECT(panel)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Crée un panneau présentant la liste des erreurs rencontrées. * +*                                                                             * +*  Retour      : Adresse de la structure mise en place.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GPanelItem *g_error_panel_new(void) +{ +    GErrorPanel *result;                    /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_ERROR_PANEL, NULL); + +    return G_PANEL_ITEM(result); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : model = gestionnaire de données.                             * +*                a     = premier élément à traiter.                           * +*                b     = second élément à traiter.                            * +*                data  = donnée non utilisée ici.                             * +*                                                                             * +*  Description : Organise le tri des erreurs présentées.                      * +*                                                                             * +*  Retour      : Bilan de comparaison.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static gint sort_errors_in_panel(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data) +{ +    gint result;                            /* Bilan à faire remonter      */ +    vmpa2t *addr_a;                         /* Localisation de A           */ +    vmpa2t *addr_b;                         /* Localisation de B           */ + +    gtk_tree_model_get(model, a, ETC_ADDR, &addr_a, -1); +    gtk_tree_model_get(model, b, ETC_ADDR, &addr_b, -1); + +    result = cmp_vmpa(addr_a, addr_b); + +    delete_vmpa(addr_a); +    delete_vmpa(addr_b); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : panel  = panneau à mettre à jour.                            * +*                binary = nouvelle instance de binaire analysé.               * +*                                                                             * +*  Description : Réagit à un changement d'affichage principal de contenu.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void update_panel_with_binary_errors(GErrorPanel *panel, GLoadedBinary *binary) +{ +    GtkListStore *store;                    /* Modèle de gestion           */ +    GBinFormat *format;                     /* Format du binaire           */ +    size_t fcount;                          /* Quantité d'erreurs #1       */ +    GArchProcessor *proc;                   /* Architecture du binaire     */ +    size_t pcount;                          /* Quantité d'erreurs #2       */ +    GPanelUpdate *update;                   /* Procédure de mise à jour    */ + +    /* Réinitialisation */ + +    if (panel->binary != NULL) +        g_object_unref(G_OBJECT(panel->binary)); + +    panel->binary = binary; + +    if (panel->binary != NULL) +        g_object_ref(G_OBJECT(panel->binary)); + +    store = GTK_LIST_STORE(gtk_builder_get_object(panel->builder, "store")); + +    gtk_list_store_clear(store); + +    /* Actualisation de l'affichage */ + +    if (binary != NULL) +    { +        format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + +        g_binary_format_lock_errors(format); +        fcount = g_binary_format_count_errors(format); +        g_binary_format_unlock_errors(format); + +        g_object_unref(G_OBJECT(format)); + +        proc = g_loaded_binary_get_processor(binary); + +        g_arch_processor_lock_errors(proc); +        pcount = g_arch_processor_count_errors(proc); +        g_arch_processor_unlock_errors(proc); + +        g_object_unref(G_OBJECT(proc)); + +    } + +    else +    { +        fcount = 0; +        pcount = 0; +    } + +    update = g_panel_update_new(G_PANEL_ITEM(panel), +                                _("Loading errors occurred during the disassembling process..."), +                                fcount + pcount, +                                (pu_fallback_cb)update_error_panel); + +    g_signal_connect(update, "work-completed", G_CALLBACK(update_error_panel_summary), panel); + +    if (get_work_queue() != NULL) /* FIXME */ +    g_work_queue_schedule_work(get_work_queue(), G_DELAYED_WORK(update), DEFAULT_WORK_GROUP); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : panel  = panneau à mettre à jour.                            * +*                status = barre de statut à tenir informée.                   * +*                id     = identifiant pour le suivi de la progression.        * +*                                                                             * +*  Description : Effectue la mise à jour du contenu du panneau d'erreurs.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void update_error_panel(GErrorPanel *panel, GtkStatusStack *status, activity_id_t id) +{ +    GtkTreeView *treeview;                  /* Arborescence graphique      */ +    GtkTreeModel *model;                    /* Source de données associée  */ +    GtkListStore *store;                    /* Modèle de gestion           */ +    GBinFormat *format;                     /* Format du binaire           */ +    size_t fcount;                          /* Quantité d'erreurs #1       */ +    GArchProcessor *proc;                   /* Architecture du binaire     */ +    size_t pcount;                          /* Quantité d'erreurs #2       */ +    GtkToggleButton *button;                /* Bouton à manipuler          */ +    gboolean show_format;                   /* Affichages liés au format   */ +    gboolean show_disass;                   /* Affichages liés à l'arch.   */ +    gboolean show_output;                   /* Affichages liés à la sortie */ +    size_t count;                           /* Nombre de soucis présents   */ +    size_t kept;                            /* Nombre d'éléments affichés  */ +    GtkTreeIter iter;                       /* Point d'insertion           */ +    size_t i;                               /* Boucle de parcours          */ +    error_desc_t error;                     /* Description de soucis       */ +#ifndef NDEBUG +    bool ret;                               /* Bilan d'une récupération    */ +#endif + +    /* Basculement de l'affichage hors ligne */ + +    treeview = GTK_TREE_VIEW(gtk_builder_get_object(panel->builder, "treeview")); + +    model = gtk_tree_view_get_model(treeview); +    g_object_ref(G_OBJECT(model)); + +    gtk_tree_view_set_model(treeview, NULL); + +    store = GTK_LIST_STORE(gtk_builder_get_object(panel->builder, "store")); + +    /* Recensement initial */ + +    if (panel->binary != NULL) +    { +        format = G_BIN_FORMAT(g_loaded_binary_get_format(panel->binary)); + +        g_binary_format_lock_errors(format); + +        fcount = g_binary_format_count_errors(format); + +        proc = g_loaded_binary_get_processor(panel->binary); + +        g_arch_processor_lock_errors(proc); + +        pcount = g_arch_processor_count_errors(proc); + +    } + +    /* S'il n'y a aucun soucis à remonter... */ + +    if (panel->binary == NULL || (fcount + pcount) == 0) +    { +        button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "format")); +        gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); +        show_format = gtk_toggle_button_get_active(button); + +        button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "disass")); +        gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); +        show_disass = gtk_toggle_button_get_active(button); + +        button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "output")); +        gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); +        show_output = gtk_toggle_button_get_active(button); + +        gtk_list_store_append(store, &iter); + +        gtk_list_store_set(store, &iter, +                           ETC_ICON, NULL, +                           ETC_PHYS, _("<i>There is no error to display here.</i>"), +                           ETC_VIRT, NULL, +                           ETC_DESC, NULL, +                           ETC_VISIBLE, TRUE, +                           -1); + +        count = 0; +        kept = 0; + +    } + +    /* Sinon on dresse la liste des doléances ! */ + +    else +    { +        button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "format")); +        gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE); +        show_format = gtk_toggle_button_get_active(button); + +        button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "disass")); +        gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE); +        show_disass = gtk_toggle_button_get_active(button); + +        button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "output")); +        gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE); +        show_output = gtk_toggle_button_get_active(button); + + +        gboolean is_error_visible(const error_desc_t *e, bool fmt) +        { +            gboolean visible;               /* Etat à retourner            */ + +            visible = FALSE; + +            if (fmt) +            { +                if (show_format && e->ftype == BFE_STRUCTURE) +                    visible = TRUE; + +            } + +            else +            { +                if (show_disass && e->ptype == APE_DISASSEMBLY) +                    visible = TRUE; + +                else if (show_output && e->ptype == APE_LABEL) +                    visible = TRUE; + +            } + +            return visible; + +        } + +        cairo_surface_t *get_error_icon(const error_desc_t *e, bool fmt) +        { +            cairo_surface_t *icon;          /* Image associée à renvoyer   */ + +            icon = NULL; + +            if (fmt) +            { +                if (show_format && e->ftype == BFE_STRUCTURE) +                    icon = G_ERROR_PANEL_GET_CLASS(panel)->format_img; + +            } + +            else +            { +                if (show_disass && e->ptype == APE_DISASSEMBLY) +                    icon = G_ERROR_PANEL_GET_CLASS(panel)->disass_img; + +                else if (show_output && e->ptype == APE_LABEL) +                    icon = G_ERROR_PANEL_GET_CLASS(panel)->output_img; + +            } + +            return icon; + +        } + +        void add_error(const error_desc_t *e, bool fmt) +        { +            VMPA_BUFFER(phys);              /* Décalage physique           */ +            VMPA_BUFFER(virt);              /* Position virtuelle          */ +            gboolean state;                 /* Bilan d'un filtrage         */ + +            vmpa2_phys_to_string(&e->addr, MDS_UNDEFINED, phys, NULL); +            vmpa2_virt_to_string(&e->addr, MDS_UNDEFINED, virt, NULL); + +            state = is_error_visible(e, fmt); + +            gtk_list_store_append(store, &iter); + +            gtk_list_store_set(store, &iter, +                               ETC_ICON, get_error_icon(e, fmt), +                               ETC_PHYS, phys, +                               ETC_VIRT, virt, +                               ETC_DESC, e->desc, +                               ETC_VISIBLE, state, +                               ETC_ORIGIN, fmt, +                               ETC_ERRNO, e->type, +                               ETC_ADDR, &e->addr, +                               -1); + +            count++; + +            if (state) +                kept++; + +        } + + +        count = 0; +        kept = 0; + +        for (i = 0; i < fcount; i++) +        { +            /* On remet à zéro tous les octets de l'union ! */ +            error.type = 0; + +#ifndef NDEBUG +            ret = g_binary_format_get_error(format, i, &error.ftype, &error.addr, &error.desc); +            assert(ret); +#else +            g_binary_format_get_error(format, i, &error.ftype, &error.addr, &error.desc); +#endif + +            add_error(&error, true); + +            free(error.desc); + +            gtk_status_stack_update_activity_value(status, id, 1); + +        } + +        for (i = 0; i < pcount; i++) +        { +            /* On remet à zéro tous les octets de l'union ! */ +            error.type = 0; + +#ifndef NDEBUG +            ret = g_arch_processor_get_error(proc, i, &error.ptype, &error.addr, &error.desc); +            assert(ret); +#else +            g_arch_processor_get_error(proc, i, &error.ptype, &error.addr, &error.desc); +#endif + +            add_error(&error, false); + +            free(error.desc); + +            gtk_status_stack_update_activity_value(status, id, 1); + +        } + +    } + +    if (panel->binary != NULL) +    { +        g_arch_processor_unlock_errors(proc); + +        g_object_unref(G_OBJECT(proc)); + +        g_binary_format_unlock_errors(format); + +        g_object_unref(G_OBJECT(format)); + +    } + +    panel->count = count; +    panel->kept = kept; + +    /* Basculement de l'affichage en ligne */ + +    gtk_tree_view_set_model(treeview, model); + +    g_object_unref(G_OBJECT(model)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : button = bouton à l'origine de l'opération.                  * +*                panel  = panneau contenant les informations globales.        * +*                                                                             * +*  Description : Actualise l'affichage des erreurs sur la base des filtres.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void on_error_filter_toggled(GtkToggleButton *button, GErrorPanel *panel) +{ +    GPanelUpdate *update;                   /* Procédure de mise à jour    */ + +    update = g_panel_update_new(G_PANEL_ITEM(panel), +                                _("Filtering errors occurred during the disassembling process..."), +                                panel->count, +                                (pu_fallback_cb)filter_error_panel); + +    g_signal_connect(update, "work-completed", G_CALLBACK(update_error_panel_summary), panel); + +    g_work_queue_schedule_work(get_work_queue(), G_DELAYED_WORK(update), DEFAULT_WORK_GROUP); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : panel  = panneau à mettre à jour.                            * +*                status = barre de statut à tenir informée.                   * +*                id     = identifiant pour le suivi de la progression.        * +*                                                                             * +*  Description : Filtre l'affichage du contenu du panneau d'erreurs.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void filter_error_panel(GErrorPanel *panel, GtkStatusStack *status, activity_id_t id) +{ +    GtkTreeView *treeview;                  /* Arborescence graphique      */ +    GtkTreeModel *model;                    /* Source de données associée  */ +    GtkTreeModel *store;                    /* Modèle de gestion           */ +    GtkToggleButton *button;                /* Bouton à manipuler          */ +    gboolean show_format;                   /* Affichages liés au format   */ +    gboolean show_disass;                   /* Affichages liés à l'arch.   */ +    gboolean show_output;                   /* Affichages liés à la sortie */ +    size_t kept;                            /* Nombre d'éléments affichés  */ +    GtkTreeIter iter;                       /* Boucle de parcours          */ +    gboolean valid;                         /* Validité du point courant   */ +    gboolean format;                        /* Origine du soucis remonté   */ +    guint errno;                            /* Code d'erreur associé       */ +    gboolean state;                         /* Bilan d'un filtrage         */ + +    /* Basculement de l'affichage hors ligne */ + +    treeview = GTK_TREE_VIEW(gtk_builder_get_object(panel->builder, "treeview")); + +    model = gtk_tree_view_get_model(treeview); +    g_object_ref(G_OBJECT(model)); + +    gtk_tree_view_set_model(treeview, NULL); + +    store = GTK_TREE_MODEL(gtk_builder_get_object(panel->builder, "store")); + +    /* Actualisation des données */ + +    button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "format")); +    show_format = gtk_toggle_button_get_active(button); + +    button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "disass")); +    show_disass = gtk_toggle_button_get_active(button); + +    button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "output")); +    show_output = gtk_toggle_button_get_active(button); + + +    gboolean is_error_visible(bool fmt, unsigned int type) +    { +        gboolean visible;                   /* Etat à retourner            */ + +        visible = FALSE; + +        if (fmt) +        { +            if (show_format && type == BFE_STRUCTURE) +                visible = TRUE; + +        } + +        else +        { +            if (show_disass && type == APE_DISASSEMBLY) +                visible = TRUE; + +            else if (show_output && type == APE_LABEL) +                visible = TRUE; + +        } + +        return visible; + +    } + + +    kept = 0; + +    for (valid = gtk_tree_model_get_iter_first(store, &iter); +         valid; +         valid = gtk_tree_model_iter_next(store, &iter)) +    { +        gtk_tree_model_get(store, &iter, ETC_ORIGIN, &format, ETC_ERRNO, &errno, -1); + +        state = is_error_visible(format, errno); + +        gtk_list_store_set(GTK_LIST_STORE(store), &iter, +                           ETC_VISIBLE, state, +                           -1); + +        if (state) +            kept++; + +        gtk_status_stack_update_activity_value(status, id, 1); + +    } + +    panel->kept = kept; + +    /* Basculement de l'affichage en ligne */ + +    gtk_tree_view_set_model(treeview, model); + +    g_object_unref(G_OBJECT(model)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : update = tâche venant de se terminer.                        * +*                panel  = structure contenant les informations maîtresses.    * +*                                                                             * +*  Description : Affiche un petit résumé concis des soucis remontés.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void update_error_panel_summary(GPanelUpdate *update, GErrorPanel *panel) +{ +    GtkLabel *summary;                      /* Etiquette à mettre à jour   */ +    char *msg;                              /* Bilan à faire afficher      */ + +    summary = GTK_LABEL(gtk_builder_get_object(panel->builder, "summary")); + +    if (panel->count == 0) +        gtk_label_set_markup(summary, NULL); + +    else +    { +        asprintf(&msg, _("<b>%zu</b> registered error%s, <b>%zu</b> displayed"), +                 panel->count, panel->count > 1 ? "s" : "", panel->kept); + +        gtk_label_set_markup(summary, msg); + +    } + +    free(msg); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : selection = sélection modifiée.                              * +*                panel     = structure contenant les informations maîtresses. * +*                                                                             * +*  Description : Réagit au changement de sélection des portions.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void on_error_selection_changed(GtkTreeSelection *selection, GErrorPanel *panel) +{ +    GtkTreeIter iter;                       /* Point de sélection          */ +    GtkTreeModel *model;                    /* Modèle de gestion           */ +    vmpa2t *addr;                           /* Localisation à suivre       */ +    GtkDisplayPanel *display;               /* Afficheur effectif de code  */ + +    if (gtk_tree_selection_get_selected(selection, &model, &iter)) +    { +        gtk_tree_model_get(model, &iter, ETC_ADDR, &addr, -1); + +        display = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); +        gtk_display_panel_request_move(display, addr); + +        delete_vmpa(addr); + +    } + +} diff --git a/src/gui/panels/errors.h b/src/gui/panels/errors.h new file mode 100644 index 0000000..02451ee --- /dev/null +++ b/src/gui/panels/errors.h @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * errors.h - prototypes pour le panneau listant les erreurs au désassemblage + * + * Copyright (C) 2017 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide 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. + * + *  Chrysalide 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 this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _GUI_PANELS_ERRORS_H +#define _GUI_PANELS_ERRORS_H + + +#include <i18n.h> + + +#include "panel.h" + + + +#define PANEL_ERRORS_ID _("Errors") + + +#define G_TYPE_ERROR_PANEL               g_error_panel_get_type() +#define G_ERROR_PANEL(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ERROR_PANEL, GErrorPanel)) +#define G_IS_ERROR_PANEL(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ERROR_PANEL)) +#define G_ERROR_PANEL_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ERROR_PANEL, GErrorPanelClass)) +#define G_IS_ERROR_PANEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ERROR_PANEL)) +#define G_ERROR_PANEL_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ERROR_PANEL, GErrorPanelClass)) + + +/* Panneau de présentation des erreurs recontrées (instance) */ +typedef struct _GErrorPanel GErrorPanel; + +/* Panneau de présentation des erreurs recontrées (classe) */ +typedef struct _GErrorPanelClass GErrorPanelClass; + + +/* Indique le type défini pour un panneau d'affichage des erreurs. */ +GType g_error_panel_get_type(void); + +/* Crée un panneau présentant la liste des erreurs rencontrées. */ +GPanelItem *g_error_panel_new(void); + + + +#endif  /* _GUI_PANELS_ERRORS_H */ diff --git a/src/gui/panels/errors.ui b/src/gui/panels/errors.ui new file mode 100644 index 0000000..82a1a05 --- /dev/null +++ b/src/gui/panels/errors.ui @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.20.0 --> +<interface> +  <requires lib="gtk+" version="3.20"/> +  <object class="GtkListStore" id="store"> +    <columns> +      <!-- column-name icon --> +      <column type="CairoSurface"/> +      <!-- column-name phys --> +      <column type="gchararray"/> +      <!-- column-name virt --> +      <column type="gchararray"/> +      <!-- column-name desc --> +      <column type="gchararray"/> +      <!-- column-name visible --> +      <column type="gboolean"/> +      <!-- column-name origin --> +      <column type="gboolean"/> +      <!-- column-name errno --> +      <column type="guint"/> +      <!-- column-name addr --> +      <column type="vmpa_t"/> +    </columns> +  </object> +  <object class="GtkTreeModelFilter" id="filter"> +    <property name="child_model">store</property> +  </object> +  <object class="GtkOffscreenWindow"> +    <property name="can_focus">False</property> +    <child> +      <object class="GtkBox" id="box"> +        <property name="visible">True</property> +        <property name="can_focus">False</property> +        <property name="orientation">vertical</property> +        <child> +          <object class="GtkBox"> +            <property name="visible">True</property> +            <property name="can_focus">False</property> +            <property name="spacing">8</property> +            <child> +              <object class="GtkToggleButton" id="format"> +                <property name="label" translatable="yes">Format</property> +                <property name="visible">True</property> +                <property name="can_focus">True</property> +                <property name="receives_default">True</property> +                <property name="active">True</property> +                <signal name="toggled" handler="on_error_filter_toggled" swapped="no"/> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="fill">True</property> +                <property name="position">0</property> +              </packing> +            </child> +            <child> +              <object class="GtkToggleButton" id="disass"> +                <property name="label" translatable="yes">Assembly</property> +                <property name="visible">True</property> +                <property name="can_focus">True</property> +                <property name="receives_default">True</property> +                <property name="active">True</property> +                <signal name="toggled" handler="on_error_filter_toggled" swapped="no"/> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="fill">True</property> +                <property name="position">1</property> +              </packing> +            </child> +            <child> +              <object class="GtkToggleButton" id="output"> +                <property name="label" translatable="yes">Output</property> +                <property name="visible">True</property> +                <property name="can_focus">True</property> +                <property name="receives_default">True</property> +                <property name="active">True</property> +                <signal name="toggled" handler="on_error_filter_toggled" swapped="no"/> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="fill">True</property> +                <property name="position">2</property> +              </packing> +            </child> +            <child> +              <object class="GtkLabel" id="summary"> +                <property name="visible">True</property> +                <property name="can_focus">False</property> +                <property name="opacity">0.5</property> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="fill">True</property> +                <property name="position">3</property> +              </packing> +            </child> +          </object> +          <packing> +            <property name="expand">False</property> +            <property name="fill">True</property> +            <property name="position">0</property> +          </packing> +        </child> +        <child> +          <object class="GtkScrolledWindow"> +            <property name="visible">True</property> +            <property name="can_focus">True</property> +            <property name="shadow_type">in</property> +            <child> +              <object class="GtkTreeView" id="treeview"> +                <property name="visible">True</property> +                <property name="can_focus">True</property> +                <property name="model">filter</property> +                <property name="headers_visible">False</property> +                <child internal-child="selection"> +                  <object class="GtkTreeSelection"> +                    <signal name="changed" handler="on_error_selection_changed" swapped="no"/> +                  </object> +                </child> +              </object> +            </child> +          </object> +          <packing> +            <property name="expand">True</property> +            <property name="fill">True</property> +            <property name="position">1</property> +          </packing> +        </child> +      </object> +    </child> +  </object> +</interface> diff --git a/src/gui/panels/gresource.xml b/src/gui/panels/gresource.xml index a14b8ae..64a6036 100644 --- a/src/gui/panels/gresource.xml +++ b/src/gui/panels/gresource.xml @@ -4,6 +4,7 @@          <file compressed="true">../../../pixmaps/tbutton_collapse.png</file>          <file compressed="true">../../../pixmaps/tbutton_expand.png</file>          <file compressed="true">bintree.ui</file> +        <file compressed="true">errors.ui</file>          <file compressed="true">welcome.ui</file>      </gresource>  </gresources> | 
