diff options
Diffstat (limited to 'src/gtkext')
| -rw-r--r--[-rwxr-xr-x] | src/gtkext/graph/Makefile.am | 12 | ||||
| -rw-r--r-- | src/gtkext/graph/cluster.c | 1330 | ||||
| -rw-r--r-- | src/gtkext/graph/cluster.h | 71 | ||||
| -rw-r--r-- | src/gtkext/graph/edge.c | 287 | ||||
| -rw-r--r-- | src/gtkext/graph/edge.h | 31 | ||||
| -rw-r--r-- | src/gtkext/graph/layout.c | 491 | ||||
| -rw-r--r-- | src/gtkext/graph/layout.h | 73 | ||||
| -rw-r--r-- | src/gtkext/graph/node-int.h | 83 | ||||
| -rw-r--r-- | src/gtkext/graph/node.c | 634 | ||||
| -rw-r--r-- | src/gtkext/graph/node.h | 174 | ||||
| -rwxr-xr-x | src/gtkext/graph/nodes/Makefile.am | 15 | ||||
| -rw-r--r-- | src/gtkext/graph/nodes/flow.c | 1329 | ||||
| -rw-r--r-- | src/gtkext/graph/nodes/flow.h | 99 | ||||
| -rw-r--r-- | src/gtkext/graph/nodes/virtual.c | 990 | ||||
| -rw-r--r-- | src/gtkext/graph/nodes/virtual.h | 77 | ||||
| -rw-r--r-- | src/gtkext/graph/params.h | 84 | ||||
| -rw-r--r-- | src/gtkext/graph/ranks.c | 695 | ||||
| -rw-r--r-- | src/gtkext/graph/ranks.h | 82 | ||||
| -rw-r--r-- | src/gtkext/gtkgraphview.c | 206 | ||||
| -rw-r--r-- | src/gtkext/gtkgraphview.h | 6 | 
20 files changed, 1653 insertions, 5116 deletions
diff --git a/src/gtkext/graph/Makefile.am b/src/gtkext/graph/Makefile.am index f54a97b..706811b 100755..100644 --- a/src/gtkext/graph/Makefile.am +++ b/src/gtkext/graph/Makefile.am @@ -2,14 +2,10 @@  noinst_LTLIBRARIES  = libgtkextgraph.la  libgtkextgraph_la_SOURCES =				\ -	edge.h edge.c						\ -	layout.h layout.c					\ -	node.h node.c						\ -	params.h							\ -	ranks.h ranks.c +	cluster.h cluster.c					\ +	edge.h edge.c -libgtkextgraph_la_LIBADD = 				\ -	nodes/libgtkextgraphnodes.la +libgtkextgraph_la_LIBADD =  libgtkextgraph_la_LDFLAGS = @@ -18,4 +14,4 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)  AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = nodes +SUBDIRS = diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c new file mode 100644 index 0000000..4c92718 --- /dev/null +++ b/src/gtkext/graph/cluster.c @@ -0,0 +1,1330 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * cluster.c - mise en place de graphiques + * + * Copyright (C) 2016 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 "cluster.h" + + +#include <assert.h> +#include <malloc.h> +#include <string.h> + + +#include "../gtkblockview.h" +#include "../gtkbufferview.h" +#include "../gtkviewpanel.h" +#include "../../common/sort.h" + + + +/* Définition du tracé d'un lien */ +typedef struct _link_def +{ +    InstructionLinkType type;               /* Complexité du tracé         */ + +    GdkPoint y;                             /* Position des décrochages    */ + +    GdkPoint end;                           /* Point d'arrivée final       */ + +    GGraphEdge *edge;                       /* Lien complet en préparation */ + +} link_def; + +/* Découpage vertical */ +typedef struct _graph_rank +{ +    unsigned int level;                     /* Niveau des blocs            */ + +    GGraphCluster **clusters;               /* Ensembles de blocs          */ +    size_t count;                           /* Nombre de ces ensembles     */ + +} graph_rank; + +/* Mise en disposition de blocs en graphique (instance) */ +struct _GGraphCluster +{ +    GObject parent;                         /* A laisser en premier        */ + + +    //////////////////////////////////////// +    gint top_margin[2];                     /* Espaces gauches et droites  */ +    gint left_margin;                       /* Espaces remontant à gauche  */ +    gint right_margin;                      /* Espaces remontant à droite  */ +    //////////////////////////////////////// + + +    link_def **top_anchors;                 /* Accroches supérieures       */ +    size_t ta_count;                        /* Quantité de ces accroches   */ + +    GBasicBlock *block;                     /* Bloc d'origine représenté   */ +    GtkWidget *view;                        /* Vue graphique associée      */ +    GtkAllocation alloc;                    /* Emplacement final du bloc   */ + +    GdkPoint **bottom_anchors;              /* Accroches inférieures       */ +    size_t ba_count;                        /* Quantité de ces accroches   */ + +    graph_rank *ranks;                      /* Répartition verticale       */ +    size_t ranks_count;                     /* Nombre de divisions         */ + +}; + +/* Mise en disposition de blocs en graphique (classe) */ +struct _GGraphClusterClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ + +}; + + +/* Espace minimal horizontal entre les blocs */ +#define HORIZONTAL_MARGIN 20 + +/* Espace minimal vertical entre les blocs */ +#define VERTICAL_MARGIN 30 + +/* Espace minimal entre les liens */ +#define LINK_MARGIN 10 + + +/* Initialise la classe des mises en disposition graphique. */ +static void g_graph_cluster_class_init(GGraphClusterClass *); + +/* Initialise une mise en disposition de blocs en graphique. */ +static void g_graph_cluster_init(GGraphCluster *); + +/* Supprime toutes les références externes. */ +static void g_graph_cluster_dispose(GGraphCluster *); + +/* Procède à la libération totale de la mémoire. */ +static void g_graph_cluster_finalize(GGraphCluster *); + +/* Complète un graphique avec un sous-ensemble de blocs. */ +static void g_graph_cluster_add_sub(GGraphCluster *, GGraphCluster *, GBasicBlock *); + +/* Organisation la disposition d'un ensemble de blocs basiques. */ +static void g_graph_cluster_dispatch_x(GGraphCluster *); + +/* Détermine une position pour un ensemble de blocs basiques. */ +//static void g_graph_cluster_set_x(GGraphCluster *, gint); + +/* Décalle vers la droite un ensemble de blocs basiques. */ +static void g_graph_cluster_offset_x(GGraphCluster *, gint); + +/* Décalle vers le bas un ensemble de blocs basiques. */ +static void g_graph_cluster_set_y(GGraphCluster *, gint); + + + + + +/* Recherche le bloc basique à l'extrémité d'un lien. */ +//static GGraphCluster *g_graph_cluster_find_lower_dest_cluster(const GGraphCluster *, const GArchInstruction *); + +/* Met en place les embryons de liens nécessaires. */ +static void g_graph_cluster_define_links(GGraphCluster *, GHashTable *); + +/* Détermine les positions de tous les liens en place. */ +static void g_graph_cluster_compute_link_positions(GGraphCluster *); + +/* Applique les positions calculées pour chaque lien graphique. */ +static void g_graph_cluster_resolve_links(const GGraphCluster *); + + + + + + +/* Indique le type définit par la GLib pour les mises en disposition graphique. */ +G_DEFINE_TYPE(GGraphCluster, g_graph_cluster, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des mises en disposition graphique.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_class_init(GGraphClusterClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_graph_cluster_dispose; +    object->finalize = (GObjectFinalizeFunc)g_graph_cluster_finalize; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = instance à initialiser.                            * +*                                                                             * +*  Description : Initialise une mise en disposition de blocs en graphique.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_init(GGraphCluster *cluster) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = instance d'objet GLib à traiter.                   * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_dispose(GGraphCluster *cluster) +{ +    g_object_unref(G_OBJECT(cluster->block)); +    g_object_unref(G_OBJECT(cluster->view)); + +    G_OBJECT_CLASS(g_graph_cluster_parent_class)->dispose(G_OBJECT(cluster)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = instance d'objet GLib à traiter.                   * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_finalize(GGraphCluster *cluster) +{ +    G_OBJECT_CLASS(g_graph_cluster_parent_class)->finalize(G_OBJECT(cluster)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary      = binaire charger dont le code est à représenter.* +*                list        = ensemble de blocs basiques à manipuler.        * +*                index       = indice du bloc principal à mettre en place.    * +*                highlighted = gestionnaire de surbrillance pour segments.    * +*                                                                             * +*  Description : Construit un graphique à partir de blocs basiques.           * +*                                                                             * +*  Retour      : Adresse de la structure mise en place.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGraphCluster *g_graph_cluster_new(GLoadedBinary *binary, const GBlockList *list, size_t index, segcnt_list *highlighted) +{ +    GGraphCluster *result;                  /* Structure à retourner       */ +    vmpa2t first;                           /* Début d'un groupe de lignes */ +    vmpa2t last;                            /* Fin d'un groupe de lignes   */ +    GCodeBuffer *buffer;                    /* Tampon brut à découper      */ +    GBufferView *view;                      /* Partie affichée du tampon   */ +    GtkRequisition requisition;             /* Taille à l'écran actuelle   */ + +    result = g_object_new(G_TYPE_GRAPH_CLUSTER, NULL); + +    /* Encapsulation du bloc d'entrée */ + +    result->block = g_block_list_get_block(list, index); +    g_object_ref(G_OBJECT(result->block)); + +    result->view = gtk_block_view_new(); + +    gtk_widget_show(result->view); +    gtk_view_panel_attach_binary(GTK_VIEW_PANEL(result->view), binary, BVW_GRAPH); + +    gtk_view_panel_show_border(GTK_VIEW_PANEL(result->view), true); + +    /* Restriction au bloc basique */ + +    g_basic_block_get_boundary_addresses(result->block, &first, &last); + +    buffer = g_loaded_binary_get_disassembled_buffer(binary); + +    view = g_buffer_view_new(buffer, highlighted); +    g_buffer_view_restrict(view, &first, &last); +    gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(result->view), view); + +    /* Détermination d'une position initiale centrée */ + +    gtk_widget_get_preferred_size(result->view, NULL, &requisition); + +    result->alloc.x = -requisition.width / 2; +    result->alloc.y = 0; + +    result->alloc.width = requisition.width; +    result->alloc.height = requisition.height; + +    printf("BLOCK INIT :: %d <> %d\n", result->alloc.x, result->alloc.width); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à compléter.                    * +*                sub     = sous-ensemble à intégrer.                          * +*                block   = bloc basique de départ du sous-ensemble.           * +*                                                                             * +*  Description : Complète un graphique avec un sous-ensemble de blocs.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_add_sub(GGraphCluster *cluster, GGraphCluster *sub, GBasicBlock *block) +{ +    unsigned int level;                     /* Niveau du nouvel ensemble   */ +    size_t i;                               /* Boucle de parcours          */ +    graph_rank new;                         /* Nouvel étage à insérer      */ +    graph_rank *rank;                        /* Nouvel étage à compléter     */ + +    level = g_basic_block_get_rank(block); + +    for (i = 0; i < cluster->ranks_count; i++) +        if (cluster->ranks[i].level == level) +            break; + +    if (i == cluster->ranks_count) +    { +        new.level = level; + +        new.clusters = (GGraphCluster **)calloc(1, sizeof(GGraphCluster *)); +        new.count = 1; + +        new.clusters[0] = sub; + +        int cmp_graph_rank(const graph_rank *a, const graph_rank *b) +        { +            if (a->level < b->level) +                return -1; + +            else if (a->level > b->level) +                return 1; + +            else +                return 0; + +        } + +        cluster->ranks = qinsert(cluster->ranks, &cluster->ranks_count, +                                 sizeof(graph_rank), (__compar_fn_t)cmp_graph_rank, &new); + +    } + +    else +    { +        rank = &cluster->ranks[i]; + +        rank->count++; +        rank->clusters = (GGraphCluster **)realloc(rank->clusters, +                                                   sizeof(GGraphCluster *) * rank->count); + +        rank->clusters[rank->count - 1] = sub; + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à manipuler.                    * +*                                                                             * +*  Description : Organisation la disposition d'un ensemble de blocs basiques. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_dispatch_x(GGraphCluster *cluster) +{ +    size_t k;                               /* Boucle de parcours #1       */ +    size_t rcount;                          /* Nombre d'ensembles présents */ +    size_t mid;                             /* Position centrale de départ */ +    gint start;                             /* Position initiale de départ */ + +    void place_sub(GGraphCluster **iter, size_t loop, gint base, int dir) +    { +        size_t i;                           /* Boucle de parcours #2       */ +        GtkAllocation needed;               /* Taille requise              */ + +        assert(dir == -1 || dir == 1); + +        for (i = 0; i < loop; i++, iter += dir) +        { +            g_graph_cluster_dispatch_x(*iter); + +            g_graph_cluster_compute_needed_alloc(*iter, &needed); + +            if (dir > 0) +                g_graph_cluster_offset_x(*iter, base - needed.x); +            else +                g_graph_cluster_offset_x(*iter, base - needed.x - needed.width); + +            base += dir * (needed.width + HORIZONTAL_MARGIN); + +        } + +    } + + + + +    for (k = 0; k < cluster->ranks_count; k++) +    { +        rcount = cluster->ranks[k].count; + +        if (rcount % 2 == 1) +        { +            if (rcount > 1) +            { +                mid = rcount / 2; + +                start = cluster->ranks[k].clusters[mid]->alloc.x - HORIZONTAL_MARGIN; + +                place_sub(cluster->ranks[k].clusters + mid - 1, mid, start, -1); + +                start *= -1; + +                place_sub(cluster->ranks[k].clusters + mid + 1, mid, start, 1); + +            } + +        } + +        else +        { +            mid = rcount / 2 - 1; + +            start = - HORIZONTAL_MARGIN / 2; + +            place_sub(cluster->ranks[k].clusters + mid, mid + 1, start, -1); + +            start *= -1; + +            place_sub(cluster->ranks[k].clusters + mid + 1, mid + 1, start, 1); + +        } + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à actualiser.                   * +*                x       = position finale sur l'axe des abscisses.           * +*                                                                             * +*  Description : Détermine une position pour un ensemble de blocs basiques.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +/* +static void g_graph_cluster_set_x(GGraphCluster *cluster, gint x) +{ +    g_graph_cluster_offset_x(cluster, -cluster->alloc.x); + +    g_graph_cluster_offset_x(cluster, x); + +} +*/ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à actualiser.                   * +*                offset  = décallage à appliquer.                             * +*                                                                             * +*  Description : Décalle vers la droite un ensemble de blocs basiques.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_offset_x(GGraphCluster *cluster, gint offset) +{ +    size_t i;                               /* Boucle de parcours #1       */ +    size_t j;                               /* Boucle de parcours #2       */ + +    cluster->alloc.x += offset; + +    for (i = 0; i < cluster->ranks_count; i++) +        for (j = 0; j < cluster->ranks[i].count; j++) +            g_graph_cluster_offset_x(cluster->ranks[i].clusters[j], offset); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à actualiser.                   * +*                base    = position ordonnée à appliquer.                     * +*                                                                             * +*  Description : Décalle vers le bas un ensemble de blocs basiques.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_set_y(GGraphCluster *cluster, gint base) +{ +    size_t i;                               /* Boucle de parcours #1       */ +    gint max;                               /* Hauteur maximale rencontrée */ +    size_t j;                               /* Boucle de parcours #2       */ +    GGraphCluster *sub;                     /* Sous-ensemble traité        */ +    GtkAllocation alloc;                    /* Allocation courante         */ + +    cluster->alloc.y = base; + +    base += cluster->alloc.height; + +    for (i = 0; i < cluster->ranks_count; i++) +    { +        base += VERTICAL_MARGIN; + +        max = 0; + +        for (j = 0; j < cluster->ranks[i].count; j++) +        { +            sub = cluster->ranks[i].clusters[j]; + +            g_graph_cluster_set_y(sub, base); + +            g_graph_cluster_compute_needed_alloc(sub, &alloc); + +            if ((alloc.y + alloc.height) > max) +                max = alloc.y + alloc.height; + +        } + +        base = max; + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = encapsulation à consulter.                         * +*                alloc   = emplacement idéal pour l'affichage.                * +*                                                                             * +*  Description : Détermine l'emplacement requis d'un ensemble de blocs.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_graph_cluster_compute_needed_alloc(const GGraphCluster *cluster, GtkAllocation *alloc) +{ +    GtkAllocation needed;                   /* Taille requise              */ +    size_t i;                               /* Boucle de parcours          */ +    size_t rcount;                          /* Nombre d'ensembles présents */ + +    *alloc = cluster->alloc; + +    for (i = 0; i < cluster->ranks_count; i++) +    { +        rcount = cluster->ranks[i].count; + +        switch (rcount) +        { +            case 1: + +                g_graph_cluster_compute_needed_alloc(cluster->ranks[i].clusters[0], &needed); + +                if (needed.x < alloc->x) +                { +                    alloc->width += (alloc->x + needed.x); +                    alloc->x = needed.x; +                } + +                if ((needed.x + needed.width) > (alloc->x + alloc->width)) +                    alloc->width += needed.x + needed.width - alloc->x - alloc->width; + +                /* La hauteur maximale n'est présente qu'avec le dernier morceau */ +                if ((i + 1) == cluster->ranks_count) +                { +                    if ((needed.y + needed.height) > (alloc->y + alloc->height)) +                        alloc->height += needed.y + needed.height - alloc->y - alloc->height; +                } + +                break; + +            default: + +                assert(rcount >= 2); + +                g_graph_cluster_compute_needed_alloc(cluster->ranks[i].clusters[0], &needed); + +                if (needed.x < alloc->x) +                { +                    alloc->width += (alloc->x + needed.x); +                    alloc->x = needed.x; +                } + +                /* La hauteur maximale n'est présente qu'avec le dernier morceau */ +                if ((i + 1) == cluster->ranks_count) +                { +                    if ((needed.y + needed.height) > (alloc->y + alloc->height)) +                        alloc->height += needed.y + needed.height - alloc->y - alloc->height; +                } + +                g_graph_cluster_compute_needed_alloc(cluster->ranks[i].clusters[rcount - 1], &needed); + +                if ((needed.x + needed.width) > (alloc->x + alloc->width)) +                    alloc->width += needed.x + needed.width - alloc->x - alloc->width; + +                /* La hauteur maximale n'est présente qu'avec le dernier morceau */ +                if ((i + 1) == cluster->ranks_count) +                { +                    if ((needed.y + needed.height) > (alloc->y + alloc->height)) +                        alloc->height += needed.y + needed.height - alloc->y - alloc->height; +                } + +                break; + +        } + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = encapsulation à traiter.                           * +*                view    = support de destination finale.                     * +*                                                                             * +*  Description : Dispose chaque noeud sur la surface de destination donnée.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_graph_cluster_place(GGraphCluster *cluster, GtkGraphView *view) +{ +    size_t i;                               /* Boucle de parcours #1       */ +    size_t j;                               /* Boucle de parcours #2       */ + +    g_object_ref(G_OBJECT(cluster->view)); +    gtk_graph_view_put(view, cluster->view, &cluster->alloc); + +    for (i = 0; i < cluster->ta_count; i++) +    { +        g_object_ref(G_OBJECT(cluster->top_anchors[i]->edge)); +        gtk_graph_view_add_edge(view, cluster->top_anchors[i]->edge); +    } + +    for (i = 0; i < cluster->ranks_count; i++) +        for (j = 0; j < cluster->ranks[i].count; j++) +            g_graph_cluster_place(cluster->ranks[i].clusters[j], view); + +} + + + + + + + + +////////////////////////////////////////////////////////// + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à consulter ou remonter.        * +*                first   = première instruction du bloc basique recherché.    * +*                                                                             * +*  Description : Recherche le bloc basique à l'extrémité d'un lien.           * +*                                                                             * +*  Retour      : Bloc graphique de destination pour un lien ou NULL si échec. * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +#if 0 +static GGraphCluster *g_graph_cluster_find_lower_dest_cluster(const GGraphCluster *cluster, const GArchInstruction *first) +{ +    GGraphCluster *result;                  /* Trouvaille à retourner      */ +    size_t i;                               /* Boucle de parcours #1       */ +    const graph_rank *rank;                 /* Confort d'accès             */ +    size_t j;                               /* Boucle de parcours #2       */ +    GArchInstruction *instr;                /* Instruction à comparer      */ + +    result = NULL; + +    for (i = 0; i < cluster->ranks_count && result == NULL; i++) +    { +        rank = &cluster->ranks[i]; + +        for (j = 0; j < rank->count && result == NULL; j++) +        { +            g_basic_block_get_boundary(rank->clusters[j]->block, &instr, NULL); + +            if (instr == first) +                result = rank->clusters[j]; + +        } + +    } + +    return result; + +} +#endif + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à actualiser.                   * +*                all     = table regroupant tous les groupes créés.           * +*                                                                             * +*  Description : Met en place les embryons de liens nécessaires.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_define_links(GGraphCluster *cluster, GHashTable *all) +{ +    GArchInstruction *last;                 /* Dernière instruction du bloc*/ +    GArchInstruction **dests;               /* Instr. visée par une autre  */ +    InstructionLinkType *types;             /* Type de lien entre lignes   */ +    size_t dcount;                          /* Nombre de liens de dest.    */ +    size_t i;                               /* Boucle de parcours #1       */ +    GGraphCluster *target;                  /* Bloc ciblé par un lien      */ +    GdkPoint *start;                        /* Point de départ d'un lien   */ +    link_def *end;                          /* Définitions d'arrivée       */ +    size_t j;                               /* Boucle de parcours #2       */ + +    /* Au niveau du bloc courant */ + +    g_basic_block_get_boundary(cluster->block, NULL, &last); + +    g_arch_instruction_rlock_dest(last); +    dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL); + +    for (i = 0; i < dcount; i++) +        switch (types[i]) +        { +            case ILT_EXEC_FLOW: +            case ILT_JUMP: +            case ILT_CASE_JUMP: +            case ILT_JUMP_IF_TRUE: +            case ILT_JUMP_IF_FALSE: + +                target = G_GRAPH_CLUSTER(g_hash_table_lookup(all, dests[i])); +                assert(target != NULL); + +                /* Point de départ */ + +                start = (GdkPoint *)calloc(1, sizeof(GdkPoint)); + +                cluster->bottom_anchors = (GdkPoint **)realloc(cluster->bottom_anchors, +                                                               ++cluster->ba_count * sizeof(GdkPoint *)); +                cluster->bottom_anchors[cluster->ba_count - 1] = start; + +                /* Point d'arrivée */ + +                end = (link_def *)calloc(1, sizeof(link_def)); + +                target->top_anchors = (link_def **)realloc(target->top_anchors, +                                                           ++target->ta_count * sizeof(link_def *)); +                target->top_anchors[target->ta_count - 1] = end; + +                /* Etablissement d'un embryon de lien */ + +                end->type = types[i]; + +                if (types[i] == ILT_JUMP_IF_TRUE) +                    end->edge = g_graph_edge_new_true(start, &end->y, &end->end); + +                else if (types[i] == ILT_JUMP_IF_FALSE) +                    end->edge = g_graph_edge_new_false(start, &end->y, &end->end); + +                else +                    end->edge = g_graph_edge_new(start, &end->y, &end->end); + +                break; + + +            case ILT_LOOP: + +                /* TODO */ +                assert(false); + +                break; + +            default: +                break; + +        } + +    g_arch_instruction_runlock_dest(last); + +    /* Propagation de la mise en place */ + +    for (i = 0; i < cluster->ranks_count; i++) +        for (j = 0; j < cluster->ranks[i].count; j++) +            g_graph_cluster_define_links(cluster->ranks[i].clusters[j], all); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à actualiser.                   * +*                                                                             * +*  Description : Détermine les positions de tous les liens en place.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_compute_link_positions(GGraphCluster *cluster) +{ +    gint mid_x;                             /* Abscisse centrale           */ +    size_t half;                            /* Indice de répartition égale */ +    gint y;                                 /* Ordonnée d'application      */ + +    size_t i;                               /* Boucle de parcours #1       */ +    GdkPoint *pt;                           /* Point à actualiser          */ +    size_t j;                               /* Boucle de parcours #2       */ + + + +    mid_x = cluster->alloc.x + (cluster->alloc.width / 2); + +    /* Du côté des départs... */ + +    if (cluster->ba_count > 0) +    { +        half = cluster->ba_count / 2; + +        y = cluster->alloc.y + cluster->alloc.height; + +        if (cluster->ba_count % 2 == 1) +        { +            for (i = half; i > 0; i--) +            { +                pt = cluster->bottom_anchors[i - 1]; + +                pt->x = mid_x - (half - i + 1) * LINK_MARGIN; +                pt->y = y; + +            } + +            pt = cluster->bottom_anchors[half]; + +            pt->x = mid_x; +            pt->y = y; + +            for (i = half + 1; i < cluster->ba_count; i++) +            { +                pt = cluster->bottom_anchors[i]; + +                pt->x = mid_x + (i - half) * LINK_MARGIN; +                pt->y = y; + +            } + +        } + +        else +        { +            for (i = half; i > 0; i--) +            { +                pt = cluster->bottom_anchors[i - 1]; + +                pt->x = mid_x - LINK_MARGIN / 2 - (half - i) * LINK_MARGIN; +                pt->y = y; + +            } + +            for (i = half; i < cluster->ba_count; i++) +            { +                pt = cluster->bottom_anchors[i]; + +                pt->x = mid_x + LINK_MARGIN / 2 + (half - i) * LINK_MARGIN; +                pt->y = y; + +            } + +        } + +    } + +    /* Du côté des arrivées... */ + +    if (cluster->ta_count > 0) +    { +        half = cluster->ta_count / 2; + +        y = cluster->alloc.y; + +        if (cluster->ta_count % 2 == 1) +        { +            for (i = half; i > 0; i--) +            { +                pt = &cluster->top_anchors[i - 1]->end; + +                pt->x = mid_x - (half - i + 1) * LINK_MARGIN; +                pt->y = y; + +            } + +            pt = &cluster->top_anchors[half]->end; + +            pt->x = mid_x; +            pt->y = y; + +            for (i = half + 1; i < cluster->ta_count; i++) +            { +                pt = &cluster->top_anchors[i]->end; + +                pt->x = mid_x + (i - half) * LINK_MARGIN; +                pt->y = y; + +            } + +        } + +        else +        { +            for (i = half; i > 0; i--) +            { +                pt = &cluster->top_anchors[i - 1]->end; + +                pt->x = mid_x - LINK_MARGIN / 2 - (half - i) * LINK_MARGIN; +                pt->y = y; + +            } + +            for (i = half; i < cluster->ta_count; i++) +            { +                pt = &cluster->top_anchors[i]->end; + +                pt->x = mid_x + LINK_MARGIN / 2 + (half - i) * LINK_MARGIN; +                pt->y = y; + +            } + +        } + + + + + + + + +        for (i = 0; i < cluster->ta_count; i++) +            cluster->top_anchors[i]->y.y = cluster->top_anchors[i]->end.y - 18; + + + + + + + +    } + +    /* Propagation des déterminations */ + +    for (i = 0; i < cluster->ranks_count; i++) +        for (j = 0; j < cluster->ranks[i].count; j++) +            g_graph_cluster_compute_link_positions(cluster->ranks[i].clusters[j]); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : cluster = graphique de blocs à consulter.                    * +*                                                                             * +*  Description : Applique les positions calculées pour chaque lien graphique. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_graph_cluster_resolve_links(const GGraphCluster *cluster) +{ +    size_t i;                               /* Boucle de parcours #1       */ +    size_t j;                               /* Boucle de parcours #2       */ + +    for (i = 0; i < cluster->ta_count; i++) +        g_graph_edge_resolve(cluster->top_anchors[i]->edge); + +    for (i = 0; i < cluster->ranks_count; i++) +        for (j = 0; j < cluster->ranks[i].count; j++) +            g_graph_cluster_resolve_links(cluster->ranks[i].clusters[j]); + +} + + + + + + + + + + + + + + + + +/* Liste de blocs restants à traiter */ +typedef struct _pending_blocks +{ +    size_t count;                           /* Taille de la liste          */ +    GBasicBlock *list[0];                   /* Liste de blocs à traiter    */ + +} pending_blocks; + + + + + +/* Met en place un ensemble de blocs sous forme graphique. */ +static GGraphCluster *setup_graph_clusters(GLoadedBinary *, const GBlockList *, size_t , segcnt_list *, pending_blocks *, GHashTable *); + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary      = binaire charger dont le code est à représenter.* +*                list        = ensemble de blocs basiques à manipuler.        * +*                index       = indice du bloc principal à mettre en place.    * +*                highlighted = gestionnaire de surbrillance pour segments.    * +*                pending     = liste de blocs restant à traiter. [OUT]        * +*                all         = table regroupant tous les groupes créés.       * +*                                                                             * +*  Description : Met en place un ensemble de blocs sous forme graphique.      * +*                                                                             * +*  Retour      : Ensemble de blocs mis en place.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GGraphCluster *setup_graph_clusters(GLoadedBinary *binary, const GBlockList *list, size_t index, segcnt_list *highlighted, pending_blocks *pending, GHashTable *all) +{ +    GGraphCluster *result;                  /* Instance nouvelle à renvoyer*/ +    GBasicBlock *block;                     /* Bloc à manipuler            */ +    GArchInstruction *first;                /* Première instruction du bloc*/ +    GArchInstruction *last;                 /* Dernière instruction du bloc*/ +#ifndef NDEBUG +    gboolean new;                           /* Bloc déjà traité ?          */ +#endif +    GArchInstruction **dests;               /* Instr. visée par une autre  */ +    InstructionLinkType *types;             /* Type de lien entre lignes   */ +    size_t dcount;                          /* Nombre de liens de dest.    */ +    size_t i;                               /* Boucle de parcours #1       */ +    GBasicBlock *target;                    /* Bloc ciblé par un lien      */ +    size_t j;                               /* Boucle de parcours #2       */ +    bool changed;                           /* Un ajout a été effectué ?   */ +    const bitfield_t *dominators;           /* Blocs dominant ce même bloc */ +    size_t next;                            /* Indice du prochain bloc     */ +    GGraphCluster *sub;                     /* Sous-ensemble à intégrer    */ + +    result = g_graph_cluster_new(binary, list, index, highlighted); + +    block = g_block_list_get_block(list, index); + +    g_basic_block_get_boundary(block, &first, &last); + +#ifndef NDEBUG +    new = g_hash_table_insert(all, first, result); +    assert(new); +#else +    g_hash_table_insert(all, first, result); +#endif + +    /* Détermination des blocs suivants */ + +    g_arch_instruction_rlock_dest(last); +    dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL); + +    printf(" ... block=%p dest=%zu\n", block, dcount); + +    for (i = 0; i < dcount; i++) +        switch (types[i]) +        { +            case ILT_EXEC_FLOW: +            case ILT_JUMP: +            case ILT_CASE_JUMP: +            case ILT_JUMP_IF_TRUE: +            case ILT_JUMP_IF_FALSE: + +                target = g_block_list_find_by_starting_instr(list, dests[i]); + +                /** +                 * Les sauts ne se font pas toujours à l'intérieur d'une même fonction. +                 * Par exemple sous ARM : +                 * +                 *    00008358 <call_gmon_start>: +                 *        .... +                 *        8362:       f7ff bfcf       b.w     8304 <_init+0x38> +                 *        .... +                 * +                 */ + +                printf(" NEW BLK :: %d -> %p\n", types[i], target); + +                if (target != NULL) +                { +                    for (j = 0; j < pending->count; j++) +                        if (pending->list[j] == target) +                            break; + +                    if (j == pending->count) +                    { +                        assert((pending->count + 1) < g_block_list_count_blocks(list)); +                        pending->list[pending->count++] = target; +                        printf(" --push-- %d -> %p\n", types[i], target); +                    } + +                    do +                    { +                        size_t k; +                        printf(" --stack-- "); +                        for (k = 0; k < pending->count; k++) +                            printf("%p ", pending->list[k]); +                        printf("\n"); +                    } +                    while (0); + + + +                } + +                break; + +            default: +                break; + +        } + +    g_arch_instruction_runlock_dest(last); + +    /* Intégration de tous les blocs en attente */ + +    do +    { +        changed = false; + +        for (i = 0; i < pending->count && !changed; i++) +        { +            block = pending->list[i]; +            dominators = g_basic_block_get_domination(block); + +            if (test_in_bit_field(dominators, index, 1)) +            { +                /* Dépilement */ + +                changed = true; + +                if ((i + 1) < pending->count) +                    memmove(&pending->list[i], &pending->list[i + 1], +                            (pending->count - i - 1) * sizeof(GBasicBlock *)); + +                pending->count--; + +                /* Intégration */ + +                next = g_block_list_get_index(list, block); +                assert(next < g_block_list_count_blocks(list)); + +                printf(" --pop-- block=%p index=%zu\n", block, next); + +                sub = setup_graph_clusters(binary, list, next, highlighted, pending, all); + +                g_graph_cluster_add_sub(result, sub, block); + +            } + +        } + +    } +    while (changed); + +    return result; + +} + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : blocks = ensemble des blocs basiques déjà découpés.          * +*                views  = morceaux de code à afficher de façon organisée.     * +*                count  = quantité de ces morceaux de code.                   * +*                                                                             * +*  Description : Construit un graphique à partir de blocs basiques.           * +*                                                                             * +*  Retour      : Adresse de la structure mise en place.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGraphCluster *bootstrap_graph_cluster(GLoadedBinary *binary, const GBlockList *list, segcnt_list *highlighted) +{ +    GGraphCluster *result;                  /* Structure à retourner       */ +    GHashTable *all;                        /* Collection des créations    */ +    size_t count;                           /* Taille de la liste de blocs */ +    pending_blocks *pending;                /* Suivi des blocs à traiter   */ +    GtkAllocation needed;                   /* Taille requise              */ + + +    all = g_hash_table_new(NULL, NULL); + +    count = g_block_list_count_blocks(list); + +    pending = (pending_blocks *)calloc(1, sizeof(pending_blocks) + count * sizeof(GBasicBlock *)); + + + + +    do +    { +        size_t i; +        GBasicBlock *block; +        const bitfield_t *domination; + +        printf("DBG // count : %zu\n", count); + +        for (i = 0; i < count; i++) +        { +            block = g_block_list_get_block(list, i); +            domination = g_basic_block_get_domination(block); + +            printf("DBG // block [%zu] : 0x%08lx  --  rank = %u\n", +                   i, gfw(domination), g_basic_block_get_rank(block)); + +        } + +        fflush(NULL); + +    } +    while (0); + + + + + +    result = setup_graph_clusters(binary, list, 0, highlighted, pending, all); + +    free(pending); + +    g_graph_cluster_define_links(result, all); + +    /* Positionnements dans l'espace */ + +    g_graph_cluster_dispatch_x(result); + +    g_graph_cluster_set_y(result, 0); + +    /* Réajustement vers la droite */ + +    g_graph_cluster_compute_needed_alloc(result, &needed); + +    g_graph_cluster_offset_x(result, -needed.x); + +    /* Application finale sur les liens */ + +    g_graph_cluster_compute_link_positions(result); + +    g_graph_cluster_resolve_links(result); + + + + +    g_hash_table_unref(all); + + +    return result; + + +} diff --git a/src/gtkext/graph/cluster.h b/src/gtkext/graph/cluster.h new file mode 100644 index 0000000..a41adc7 --- /dev/null +++ b/src/gtkext/graph/cluster.h @@ -0,0 +1,71 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * cluster.h - prototypes pour la mise en place de graphiques + * + * Copyright (C) 2016 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _GTKEXT_GRAPH_CLUSTER_H +#define _GTKEXT_GRAPH_CLUSTER_H + + + +#include "../gtkgraphview.h" +#include "../../analysis/binary.h" +#include "../../analysis/disass/block.h" + + + +#define G_TYPE_GRAPH_CLUSTER            g_graph_cluster_get_type() +#define G_GRAPH_CLUSTER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GRAPH_CLUSTER, GGraphCluster)) +#define G_IS_GRAPH_CLUSTER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GRAPH_CLUSTER)) +#define G_GRAPH_CLUSTER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GRAPH_CLUSTER, GGraphClusterClass)) +#define G_IS_GRAPH_CLUSTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GRAPH_CLUSTER)) +#define G_GRAPH_CLUSTER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_CLUSTER, GGraphClusterClass)) + + +/* Mise en disposition de blocs en graphique (instance) */ +typedef struct _GGraphCluster GGraphCluster; + +/* Mise en disposition de blocs en graphique (classe) */ +typedef struct _GGraphClusterClass GGraphClusterClass; + + +/* Indique le type définit par la GLib pour les mises en disposition graphique. */ +GType g_graph_cluster_get_type(void); + +/* Construit un graphique à partir de blocs basiques. */ +GGraphCluster *g_graph_cluster_new(GLoadedBinary *, const GBlockList *, size_t, segcnt_list *); + +/* Détermine l'emplacement requis d'un ensemble de blocs. */ +void g_graph_cluster_compute_needed_alloc(const GGraphCluster *, GtkAllocation *); + +/* Dispose chaque noeud sur la surface de destination donnée. */ +void g_graph_cluster_place(GGraphCluster *, GtkGraphView *); + + + + + +GGraphCluster *bootstrap_graph_cluster(GLoadedBinary *binary, const GBlockList *list, segcnt_list *highlighted); + + + + +#endif  /* _GTKEXT_GRAPH_CLUSTER_H */ diff --git a/src/gtkext/graph/edge.c b/src/gtkext/graph/edge.c index 5750198..a917cc3 100644 --- a/src/gtkext/graph/edge.c +++ b/src/gtkext/graph/edge.c @@ -24,10 +24,10 @@  #include "edge.h" +#include <assert.h> +#include <malloc.h>  #include <math.h> - - -#include "nodes/virtual.h" +#include <string.h> @@ -36,18 +36,13 @@ struct _GGraphEdge  {      GObject parent;                         /* A laisser en premier        */ -    GFlowNode *src_node;                    /* Bloc de départ du lien      */ -    node_slot_t *src_slot;                  /* Numéro d'ancrage initial    */ -    GFlowNode *dest_node;                   /* Bloc d'arrivée du lien      */ -    node_slot_t *dest_slot;                 /* Numéro d'ancrage final      */ +    EdgeColor color;                        /* Couleur du rendu            */ -    hspan_slot_t top_step;                  /* Niveau sup. de destination  */ -    GVirtualNode *container;                /* Conteneur pour les tours    */ -    bool is_left;                           /* Tour par la gauche ?        */ -    vspan_slot_t vert_step;                 /* Position de contournement   */ -    hspan_slot_t bottom_step;               /* Niveau inf. de source       */ +    const GdkPoint *start;                  /* Point de départ du lien     */ +    GdkPoint *mid[2];                        /* Etapes intermédiaires       */ +    size_t m_count;                         /* Quantité de ces étapes      */ +    const GdkPoint *end;                    /* Point d'arrivée du lien     */ -    EdgeColor color;                        /* Couleur du rendu            */      GdkPoint *points;                       /* Points de la ligne dessinée */      size_t count;                           /* Quantité de ces points      */ @@ -61,6 +56,11 @@ struct _GGraphEdgeClass  }; +/* Dimensions des flêches */ +#define ARROW_LENGHT 10 +#define ARROW_DEGREES 10 + +  /* Initialise la classe des liens graphiques entre deux noeuds. */  static void g_graph_edge_class_init(GGraphEdgeClass *); @@ -120,8 +120,6 @@ static void g_graph_edge_class_init(GGraphEdgeClass *klass)  static void g_graph_edge_init(GGraphEdge *edge)  { -    edge->top_step = UNINITIALIZED_HSPAN_SLOT; -    edge->bottom_step = UNINITIALIZED_HSPAN_SLOT;  } @@ -140,12 +138,6 @@ static void g_graph_edge_init(GGraphEdge *edge)  static void g_graph_edge_dispose(GGraphEdge *edge)  { -    g_object_unref(G_OBJECT(edge->src_node)); -    g_object_unref(G_OBJECT(edge->dest_node)); - -    if (edge->container != NULL) -        g_object_unref(G_OBJECT(edge->container)); -      G_OBJECT_CLASS(g_graph_edge_parent_class)->dispose(G_OBJECT(edge));  } @@ -175,11 +167,11 @@ static void g_graph_edge_finalize(GGraphEdge *edge)  /******************************************************************************  *                                                                             * -*  Paramètres  : src_node  = bloc de départ du lien.                          * -*                src_slot  = point d'ancrage associé.                         * -*                dest_node = bloc d'arrivée du lien.                          * -*                dest_slot = point d'ancrage associé.                         * -*                color     = couleur de rendu à l'écran.                      * +*  Paramètres  : start = point de départ de la flêche.                        * +*                mid   = points intermédiares variables.                      * +*                count = nombre de ces points fournis.                        * +*                end   = point d'arrivée de la flêche.                        * +*                color = couleur de rendu à l'écran.                          *  *                                                                             *  *  Description : Etablit un lien graphique entre deux noeuds graphiques.      *  *                                                                             * @@ -189,84 +181,33 @@ static void g_graph_edge_finalize(GGraphEdge *edge)  *                                                                             *  ******************************************************************************/ -GGraphEdge *g_graph_edge_new(GFlowNode *src_node, node_slot_t *src_slot, GFlowNode *dest_node, node_slot_t *dest_slot, EdgeColor color) +GGraphEdge *_g_graph_edge_new(const GdkPoint *start, const GdkPoint **mid, size_t count, const GdkPoint *end, EdgeColor color)  {      GGraphEdge *result;                     /* Structure à retourner       */      result = g_object_new(G_TYPE_GRAPH_EDGE, NULL); -    g_object_ref(G_OBJECT(src_node)); -    g_object_ref(G_OBJECT(dest_node)); - -    result->src_node = src_node; -    result->src_slot = src_slot; -    result->dest_node = dest_node; -    result->dest_slot = dest_slot; -      result->color = color; -    return G_GRAPH_EDGE(result); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : a = premier lien à considérer.                               * -*                b = second lien à considérer.                                * -*                                                                             * -*  Description : Etablit la comparaison entre deux liens graphiques.          * -*                                                                             * -*  Retour      : Bilan de la comparaison : -1, 0 ou 1.                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -int g_graph_edge_compare(const GGraphEdge **a, const GGraphEdge **b) -{ -    int result;                             /* Bilan à retourner           */ -    const GGraphEdge *_a;                   /* Commodité d'accès #1        */ -    const GGraphEdge *_b;                   /* Commodité d'accès #2        */ -    GdkPoint start_a;                       /* Point de départ A           */ -    GdkPoint start_b;                       /* Point de départ B           */ - -    _a = *a; -    _b = *b; - -    /** -     * La comparaison s'établit sur le noeud d'arrivée. -     */ - -    if (_a->dest_node < _b->dest_node) -        result = -1; +    assert(count == 1 || count == 2); -    else if (_a->dest_node > _b->dest_node) -        result = 1; +    result->start = start; -    else -    { -        start_a = g_flow_node_get_point_from_slot(_a->src_node, false, _a->src_slot); -        start_b = g_flow_node_get_point_from_slot(_b->src_node, false, _b->src_slot); +    memcpy(result->mid, mid, count * sizeof(GdkPoint)); +    result->m_count = count; -        result = g_flow_node_compare_slots_for_edges(_a->dest_node, -                                                     _a->dest_slot, start_a.x, -                                                     _b->dest_slot, start_b.x); - -    } +    result->end = end; -    return result; +    return G_GRAPH_EDGE(result);  }  /******************************************************************************  *                                                                             * -*  Paramètres  : edge  = ligne de rendu à mettre à jour.                      * -*                nodes = noeud au sommet de la hiérarchie.                    * -*                ranks = classement global dans lequel s'intégrer.            * +*  Paramètres  : edge = ligne de rendu à définir dans les détails.            *  *                                                                             * -*  Description : Prend les dispositions nécessaires à l'insertion du lien.    * +*  Description : Détermine les positions finales d'un lien graphique.         *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -274,177 +215,31 @@ int g_graph_edge_compare(const GGraphEdge **a, const GGraphEdge **b)  *                                                                             *  ******************************************************************************/ -void g_graph_edge_reserve_vertical_space(GGraphEdge *edge, GGraphNode *nodes, GGraphRanks *ranks) +void g_graph_edge_resolve(GGraphEdge *edge)  { -    GGraphNode *container;                  /* Conteneur du lien de boucle */ -    unsigned int r1;                        /* Classement de départ        */ -    unsigned int r2;                        /* Classement d'arrivée        */ - -    switch (edge->color) -    { -        case EGC_BLUE: - -            container = g_graph_node_find_container(nodes, G_GRAPH_NODE(edge->dest_node)); -            g_object_ref(G_OBJECT(container)); -            edge->container = G_VIRTUAL_NODE(container); - -            edge->is_left = true;  /* TODO */ - -            r1 = g_graph_node_get_rank(G_GRAPH_NODE(edge->src_node)); -            r2 = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node)); - -            edge->vert_step = g_virtual_node_reserve_span(edge->container, r1, r2, edge->is_left); - -            break; - -        default: -            break; - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : edge  = ligne de rendu à mettre à jour.                      * -*                ranks = classement global dans lequel s'intégrer.            * -*                                                                             * -*  Description : Prend les dispositions nécessaires à l'insertion du lien.    * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ +    edge->count = 2 + 2 * edge->m_count; +    edge->points = (GdkPoint *)calloc(edge->count, sizeof(GdkPoint)); -void g_graph_edge_reserve_horizontal_space(GGraphEdge *edge, GGraphRanks *ranks) -{ -    GdkPoint x_src;                         /* Abscisse au niveau du départ*/ -    GdkPoint x_dest;                        /* Abscisse au niveau d'arrivée*/ -    gint x_step;                            /* Transition verticale        */ -    unsigned int rank;                      /* Indice de classement        */ +    edge->points[0] = *edge->start; -    x_src = g_flow_node_get_point_from_slot(edge->src_node, false, edge->src_slot); -    x_dest = g_flow_node_get_point_from_slot(edge->dest_node, true, edge->dest_slot); +    edge->points[1].x = edge->start->x; +    edge->points[1].y = edge->mid[0]->y; -    switch (edge->color) +    if (edge->m_count == 1)      { -        case EGC_BLUE: - -            x_step = g_virtual_node_get_x_for_vspan_slot(edge->container, -                                                         edge->vert_step, edge->is_left); - -            rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->src_node)); -            edge->bottom_step = g_graph_ranks_reserve_span(ranks, rank, x_src.x, x_step, false); - -            rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node)); -            edge->top_step = g_graph_ranks_reserve_span(ranks, rank, x_dest.x, x_step, true); - -            break; - -        default: -            rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node)); -            edge->top_step = g_graph_ranks_reserve_span(ranks, rank, x_src.x, x_dest.x, true); -            break; - +        edge->points[2].x = edge->end->x; +        edge->points[2].y = edge->mid[0]->y;      } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : edge  = ligne de rendu à mettre à jour.                      * -*                ranks = classement global dans lequel s'intégrer.            * -*                                                                             * -*  Description : Etablit le tracé du lien graphique entre deux noeuds.        * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_edge_compute(GGraphEdge *edge, GGraphRanks *ranks) -{ -    GdkPoint start;                         /* Point de départ             */ -    GdkPoint end;                           /* Point d'arrivée             */ -    gint x_step;                            /* Transition verticale        */ -    unsigned int rank;                      /* Indice de classement        */ - -    start = g_flow_node_get_point_from_slot(edge->src_node, false, edge->src_slot); -    end = g_flow_node_get_point_from_slot(edge->dest_node, true, edge->dest_slot); - -    /* Point de départ */ - -    edge->count = 2; -    edge->points = (GdkPoint *)calloc(edge->count, sizeof(GdkPoint)); - -    edge->points[0] = start; -    edge->points[1] = start; -    edge->points[1].y += SLOT_VERT_SEP; - -    /* Points de jonction */ - -    switch (edge->color) +    else      { -        case EGC_BLUE: - -            edge->count += 4; -            edge->points = (GdkPoint *)realloc(edge->points, edge->count * sizeof(GdkPoint)); - -            x_step = g_virtual_node_get_x_for_vspan_slot(edge->container, -                                                         edge->vert_step, edge->is_left); - -            rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->src_node)); - -            edge->points[edge->count - 4].x = start.x; -            edge->points[edge->count - 4].y = g_graph_ranks_get_y_for_hspan_slot(ranks, rank, -                                                                                 edge->bottom_step, -                                                                                 false); +        memcpy(&edge->points[2], edge->mid, edge->m_count * sizeof(GdkPoint)); -            edge->points[edge->count - 3].x = x_step; -            edge->points[edge->count - 3].y = edge->points[edge->count - 4].y; - -            rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node)); - -            edge->points[edge->count - 2].x = x_step; -            edge->points[edge->count - 2].y = g_graph_ranks_get_y_for_hspan_slot(ranks, rank, -                                                                                 edge->top_step, -                                                                                 true); -            edge->points[edge->count - 1].x = end.x; -            edge->points[edge->count - 1].y = edge->points[edge->count - 2].y; - -            break; - -        default: - -            edge->count += 2; -            edge->points = (GdkPoint *)realloc(edge->points, edge->count * sizeof(GdkPoint)); - -            rank = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node)); - -            edge->points[edge->count - 2].x = start.x; -            edge->points[edge->count - 2].y = g_graph_ranks_get_y_for_hspan_slot(ranks, rank, -                                                                                 edge->top_step, -                                                                                 true); - -            edge->points[edge->count - 1].x = end.x; -            edge->points[edge->count - 1].y = edge->points[edge->count - 2].y; - -            break; +        edge->points[4].x = edge->end->x; +        edge->points[4].y = edge->mid[3]->y;      } -    /* Point d'arrivée */ - -    edge->count += 2; -    edge->points = (GdkPoint *)realloc(edge->points, edge->count * sizeof(GdkPoint)); - -    edge->points[edge->count - 2] = end; -    edge->points[edge->count - 2].y -= SLOT_VERT_SEP; -    edge->points[edge->count - 1] = end; +    edge->points[edge->count - 1] = *edge->end;  } diff --git a/src/gtkext/graph/edge.h b/src/gtkext/graph/edge.h index 64d9658..602c559 100644 --- a/src/gtkext/graph/edge.h +++ b/src/gtkext/graph/edge.h @@ -26,17 +26,16 @@  #include <glib-object.h> - - -#include "ranks.h" -#include "nodes/flow.h" +#include <stdbool.h> +#include <gtk/gtk.h>  #define G_TYPE_GRAPH_EDGE               g_graph_edge_get_type() -#define G_GRAPH_EDGE(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_graph_edge_get_type(), GGraphEdge)) -#define G_IS_GRAPH_EDGE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_graph_edge_get_type())) -#define G_GRAPH_EDGE_GET_IFACE(inst)    (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_graph_edge_get_type(), GGraphEdgeIface)) +#define G_GRAPH_EDGE(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GRAPH_EDGE, GGraphEdge)) +#define G_IS_GRAPH_EDGE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GRAPH_EDGE)) +#define G_GRAPH_EDGE_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GRAPH_EDGE, GGraphEdgeClass)) +#define G_IS_GRAPH_EDGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GRAPH_EDGE))  #define G_GRAPH_EDGE_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_EDGE, GGraphEdgeClass)) @@ -65,19 +64,19 @@ typedef enum _EdgeColor  GType g_graph_edge_get_type(void);  /* Etablit un lien graphique entre deux noeuds graphiques. */ -GGraphEdge *g_graph_edge_new(GFlowNode *, node_slot_t *, GFlowNode *, node_slot_t *, EdgeColor); +GGraphEdge *_g_graph_edge_new(const GdkPoint *, const GdkPoint **, size_t, const GdkPoint *, EdgeColor); -/* Etablit la comparaison entre deux liens graphiques. */ -int g_graph_edge_compare(const GGraphEdge **, const GGraphEdge **); +#define g_graph_edge_new(start, y, end) \ +    _g_graph_edge_new(start, (const GdkPoint *[]) { y }, 1, end, EGC_DEFAULT) -/* Prend les dispositions nécessaires à l'insertion du lien. */ -void g_graph_edge_reserve_vertical_space(GGraphEdge *, GGraphNode *, GGraphRanks *); +#define g_graph_edge_new_true(start, y, end) \ +    _g_graph_edge_new(start, (const GdkPoint *[]) { y }, 1, end, EGC_GREEN) -/* Prend les dispositions nécessaires à l'insertion du lien. */ -void g_graph_edge_reserve_horizontal_space(GGraphEdge *, GGraphRanks *); +#define g_graph_edge_new_false(start, y, end) \ +    _g_graph_edge_new(start, (const GdkPoint *[]) { y }, 1, end, EGC_RED) -/* Etablit le tracé du lien graphique entre deux noeuds. */ -void g_graph_edge_compute(GGraphEdge *, GGraphRanks *); +/* Détermine les positions finales d'un lien graphique. */ +void g_graph_edge_resolve(GGraphEdge *);  /* Dessine les liens graphiques enregistrés dans le moteur. */  void g_graph_edge_draw(const GGraphEdge *, cairo_t *, bool); diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c deleted file mode 100644 index 13f6270..0000000 --- a/src/gtkext/graph/layout.c +++ /dev/null @@ -1,491 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * layout.c - mise en place de graphique - * - * Copyright (C) 2009-2014 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  OpenIDA is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 3 of the License, or - *  (at your option) any later version. - * - *  OpenIDA is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "layout.h" - - -#include <malloc.h> -#include <stdlib.h> - - -#include "node.h" -#include "ranks.h" -#include "nodes/flow.h" -#include "nodes/virtual.h" - - - -/* Mise en disposition de blocs en graphique (instance) */ -struct _GGraphLayout -{ -    GObject parent;                         /* A laisser en premier        */ - -    GGraphNode *nodes;                      /* Noeuds graphiques gérés     */ -    GGraphRanks *ranks;                     /* Classement en rangs         */ - -    GGraphEdge **edges;                     /* Liens entre les noeuds      */ -    size_t edges_count;                     /* Quantité de ces liens       */ - -}; - -/* Mise en disposition de blocs en graphique (classe) */ -struct _GGraphLayoutClass -{ -    GObjectClass parent;                    /* A laisser en premier        */ - -}; - - -/* Initialise la classe des mises en disposition graphique. */ -static void g_graph_layout_class_init(GGraphLayoutClass *); - -/* Initialise une mise en disposition de blocs en graphique. */ -static void g_graph_layout_init(GGraphLayout *); - -/* Supprime toutes les références externes. */ -static void g_graph_layout_dispose(GGraphLayout *); - -/* Procède à la libération totale de la mémoire. */ -static void g_graph_layout_finalize(GGraphLayout *); - - - -/* Indique le type définit par la GLib pour les mises en disposition graphique. */ -G_DEFINE_TYPE(GGraphLayout, g_graph_layout, G_TYPE_OBJECT); - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : klass = classe à initialiser.                                * -*                                                                             * -*  Description : Initialise la classe des mises en disposition graphique.     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_layout_class_init(GGraphLayoutClass *klass) -{ -    GObjectClass *object;                   /* Autre version de la classe  */ - -    object = G_OBJECT_CLASS(klass); - -    object->dispose = (GObjectFinalizeFunc/* ! */)g_graph_layout_dispose; -    object->finalize = (GObjectFinalizeFunc)g_graph_layout_finalize; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : layout = instance à initialiser.                             * -*                                                                             * -*  Description : Initialise une mise en disposition de blocs en graphique.    * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_layout_init(GGraphLayout *layout) -{ - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance d'objet GLib à traiter.                      * -*                                                                             * -*  Description : Supprime toutes les références externes.                     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_layout_dispose(GGraphLayout *layout) -{ -    g_object_unref(G_OBJECT(layout->nodes)); -    g_object_unref(G_OBJECT(layout->ranks)); - -    G_OBJECT_CLASS(g_graph_layout_parent_class)->dispose(G_OBJECT(layout)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : layout = instance d'objet GLib à traiter.                    * -*                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_layout_finalize(GGraphLayout *layout) -{ -    G_OBJECT_CLASS(g_graph_layout_parent_class)->finalize(G_OBJECT(layout)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : blocks = ensemble des blocs basiques déjà découpés.          * -*                views  = morceaux de code à afficher de façon organisée.     * -*                count  = quantité de ces morceaux de code.                   * -*                                                                             * -*  Description : Construit un graphique à partir de blocs basiques.           * -*                                                                             * -*  Retour      : Adresse de la structure mise en place.                       * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ -#include "../../arch/instruction-int.h" // REMME -#include "nodes/flow.h" -GGraphLayout *g_graph_layout_new(GInstrBlock *blocks, GtkBufferView **views, size_t count) -{ -    GGraphLayout *result;                   /* Structure à retourner       */ - -    result = g_object_new(G_TYPE_GRAPH_LAYOUT, NULL); - -    result->nodes = convert_blocks_into_nodes(blocks, views, count); - -    result->ranks = g_graph_ranks_new(count); - -    /* Situations verticales grossières */ - -    bool _register_cb(GFlowNode *node, GNodeVisitState state, GGraphLayout *layout) -    { -        if (state == GVS_NODE) -            g_flow_node_link(node, layout, layout->nodes); -        return true; -    } - -    g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_register_cb, result); - -    bool _print_dbg_cb(GFlowNode *node, GNodeVisitState state, int *depth) -    { -        int i; - -        if (state == GVS_ENTER || state == GVS_NODE) -        { -            for (i = 0; i < *depth; i++) -                printf("   "); - -            printf("- %p\n", node); - -        } - -        if (state == GVS_ENTER) (*depth)++; -        else if (state == GVS_EXIT) (*depth)--; - -        return true; - -    } - -    printf("==== graph ====\n"); -    g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_print_dbg_cb, (int []){ 0 }); -    printf("\n"); - -    /* Actualisation... */ - -    g_graph_layout_refresh(result); - -    bool _print_dbg_ext_cb(GGraphNode *node, GNodeVisitState state, int *depth) -    { -        int i; -        PendingPositionFlags pending_flag; -        char *flags; -        GtkAllocation alloc; -        GArchInstruction *first; -        GArchInstruction *last; - -        char *flags_list[] = { -            "NONE", -            "DIRECT_X", -            "LEFT_MARGIN", -            "RIGHT_MARGIN", -            "LEFT_NODE", -            "RIGHT_NODE" -        };   - - -        if (state == GVS_ENTER || state == GVS_NODE) -        { - - - -            for (i = 0; i < *depth; i++) -                printf("   "); - -            g_graph_node_get_pending_position(node, &pending_flag, NULL); -            flags = flags_list[pending_flag]; - -            alloc = g_graph_node_get_allocation(node); -            printf("- %p -  \"%s\"  -  (%d ; %d) - (%d ; %d)", node, -                   flags, -                   alloc.x, alloc.y, -                   alloc.width, alloc.height); - -            if (G_IS_FLOW_NODE(node)) -            { -                printf("  - rank = %u  -", g_graph_node_get_rank(node)); - -                g_flow_block_get_boundary(g_flow_node_get_block(G_FLOW_NODE(node)), &first, &last); -                printf("  - 0x%08x <-> 0x%08x", first->range.addr.virtual, last->range.addr.virtual); -            } - -            printf("\n"); - -        } - -        if (state == GVS_ENTER) (*depth)++; -        else if (state == GVS_EXIT) (*depth)--; - -        return true; - -    } - -    printf("==== graph ====\n"); -    g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_print_dbg_ext_cb, (int []){ 0 }); -    printf("\n"); - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : layout = disposition en graphique à compléter.               * -*                edge   = lien entre noeuds à conserver.                      * -*                                                                             * -*  Description : Ajoute un lien entre deux noeuds au graphique.               * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_layout_add_edge(GGraphLayout *layout, GGraphEdge *edge) -{ -    layout->edges = (GGraphEdge **)realloc(layout->edges, -                                           ++layout->edges_count * sizeof(GGraphEdge *)); - -    layout->edges[layout->edges_count - 1] = edge; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : layout = graphique à mettre à jour.                          * -*                                                                             * -*  Description : Met à jour les positions des différents noeuds.              * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ -#include "node-int.h" -void g_graph_layout_refresh(GGraphLayout *layout) -{ -    size_t i;                               /* Boucle de parcours          */ - - -    int counter = 0; - - - restart: - -    g_graph_ranks_reset_reservations(layout->ranks); - -    bool _reset_cb(GGraphNode *node, GNodeVisitState state, void *unused) -    { -        g_graph_node_reset_position(node); -        if (state == GVS_NODE) -            g_flow_node_register_rank(G_FLOW_NODE(node), layout->ranks); -        return true; -    } - -    g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_reset_cb, NULL); - -    /* Traitement des positions horizontales */ - -    for (i = 0; i < layout->edges_count; i++) -        g_graph_edge_reserve_vertical_space(layout->edges[i], layout->nodes, layout->ranks); - -    /* Traitement des positions horizontales */ - -    g_graph_node_set_x_position(layout->nodes, GRAPH_HORIZONTAL_MARGIN); - -    g_graph_node_prepare_x_line(layout->nodes, layout->nodes); -    g_graph_node_apply_position(layout->nodes); - - - -    bool _reorder_cb(GGraphNode *node, GNodeVisitState state, GGraphNode *nodes) -    { -        if (state == GVS_NODE) -            g_flow_node_reorder_slots(G_FLOW_NODE(node), nodes); -        return true; -    } - -    //qsort(layout->edges, layout->edges_count, sizeof(GGraphEdge *), (__compar_fn_t)g_graph_edge_compare); - - - -    if (counter++ == 0) -    { -    g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_reorder_cb, layout->nodes); -    goto restart; -    } - -    /* -    bool _rinint_cb(GGraphNode *node, GNodeVisitState state, GGraphNode *nodes) -    { -        node->alloc.x = UNINITIALIZED_NODE_POS; -        node->alloc.y = UNINITIALIZED_NODE_POS; -        return true; -    } - -    g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_rinint_cb, layout->nodes); - - -    g_graph_node_apply_position(layout->nodes); -    */ - -    qsort(layout->edges, layout->edges_count, sizeof(GGraphEdge *), (__compar_fn_t)g_graph_edge_compare); - - - -    for (i = 0; i < layout->edges_count; i++) -        g_graph_edge_reserve_horizontal_space(layout->edges[i], layout->ranks); - -    /* Traitement des positions verticales */ - -    g_graph_ranks_compute_y_line(layout->ranks); - -    bool _apply_cb(GFlowNode *node, GNodeVisitState state, GGraphRanks *ranks) -    { -        if (state == GVS_NODE) -            g_flow_node_apply_rank(node, ranks); -        return true; -    } - -    g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_apply_cb, layout->ranks); - -    /* Mise en place des liens */ - -    for (i = 0; i < layout->edges_count; i++) -        g_graph_edge_compute(layout->edges[i], layout->ranks); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : layout = disposition en graphique prête.                     * -*                view   = support de destination finale.                      * -*                                                                             * -*  Description : Dispose chaque noeud sur la surface de destination donnée.   * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_layout_place(GGraphLayout *layout, GtkGraphView *view) -{ -    bool _place_cb(GFlowNode *node, GNodeVisitState state, GtkGraphView *view) -    { -        if (state == GVS_NODE) -            g_flow_node_place(node, view); -        return true; -    } - -    g_graph_node_visit_nodes(layout->nodes, (graph_node_visitor_cb)_place_cb, view); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : layout      = graphique constitué à consulter.               * -*                requisition = dimensions souhaitées. [OUT]                   * -*                                                                             * -*  Description : Fournit la taille requise pour un plein rendu du graphique.  * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_layout_size_request(const GGraphLayout *layout, GtkRequisition *requisition) -{ -    GtkAllocation alloc;                    /* Largeur totale requise      */ - -    alloc = g_graph_node_get_allocation(layout->nodes); -    requisition->width = alloc.width + 2 * GRAPH_HORIZONTAL_MARGIN; - -    requisition->height = g_graph_ranks_get_height(layout->ranks); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : layout = graphique à représenter.                            * -*                cairo  = assistant pour le rendu graphique.                  * -*                arrow  = indique le besoin en flèche à l'arrivée.            * -*                                                                             * -*  Description : Dessine les liens graphiques enregistrés dans le moteur.     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_layout_draw(const GGraphLayout *layout, cairo_t *cairo, bool arrow) -{ -    size_t i;                               /* Boucle de parcours          */ - -    for (i = 0; i < layout->edges_count; i++) -        g_graph_edge_draw(layout->edges[i], cairo, arrow); - -} diff --git a/src/gtkext/graph/layout.h b/src/gtkext/graph/layout.h deleted file mode 100644 index 37598e8..0000000 --- a/src/gtkext/graph/layout.h +++ /dev/null @@ -1,73 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * layout.h - prototypes pour la mise en place de graphique - * - * Copyright (C) 2009-2014 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  OpenIDA is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 3 of the License, or - *  (at your option) any later version. - * - *  OpenIDA is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _GTKEXT_GRAPH_LAYOUT_H -#define _GTKEXT_GRAPH_LAYOUT_H - - -#include <stdbool.h> - - -#include "edge.h" -#include "../gtkbufferview.h" - - - -#define G_TYPE_GRAPH_LAYOUT               g_graph_layout_get_type() -#define G_GRAPH_LAYOUT(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_graph_layout_get_type(), GGraphLayout)) -#define G_IS_GRAPH_LAYOUT(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_graph_layout_get_type())) -#define G_GRAPH_LAYOUT_GET_IFACE(inst)    (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_graph_layout_get_type(), GGraphLayoutIface)) -#define G_GRAPH_LAYOUT_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_LAYOUT, GGraphLayoutClass)) - - -/* Mise en disposition de blocs en graphique (instance) */ -typedef struct _GGraphLayout GGraphLayout; - -/* Mise en disposition de blocs en graphique (classe) */ -typedef struct _GGraphLayoutClass GGraphLayoutClass; - - -/* Indique le type définit par la GLib pour les mises en disposition graphique. */ -GType g_graph_layout_get_type(void); - -/* Construit un graphique à partir de blocs basiques. */ -GGraphLayout *g_graph_layout_new(GInstrBlock *, GtkBufferView **, size_t); - -/* Ajoute un lien entre deux noeuds au graphique. */ -void g_graph_layout_add_edge(GGraphLayout *, GGraphEdge *); - -/* Met à jour les positions des différents noeuds. */ -void g_graph_layout_refresh(GGraphLayout *); - -/* Dispose chaque noeud sur la surface de destination donnée. */ -void g_graph_layout_place(GGraphLayout *, GtkGraphView *); - -/* Fournit la taille requise pour un plein rendu du graphique. */ -void g_graph_layout_size_request(const GGraphLayout *, GtkRequisition *); - -/* Dessine les liens graphiques enregistrés dans le moteur. */ -void g_graph_layout_draw(const GGraphLayout *, cairo_t *, bool); - - - -#endif  /* _GRAPH_LAYOUT_H */ diff --git a/src/gtkext/graph/node-int.h b/src/gtkext/graph/node-int.h deleted file mode 100644 index c052e0d..0000000 --- a/src/gtkext/graph/node-int.h +++ /dev/null @@ -1,83 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * node-int.h - prototypes pour la gestion élémentaire des blocs sous forme de noeuds - * - * Copyright (C) 2013 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  OpenIDA is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 3 of the License, or - *  (at your option) any later version. - * - *  OpenIDA is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _GTKEXT_GRAPH_NODE_INT_H -#define _GTKEXT_GRAPH_NODE_INT_H - - -#include "node.h" - - - -/* Fournit le rang du noeud dans le graphique. */ -typedef unsigned int (* get_node_rank_fc) (const GGraphNode *); - -/* Réinitialise la position d'un noeud d'encapsulation. */ -typedef void (* node_reset_pos_fc) (GGraphNode *); - -/* Définit les abscisses relatives du contenu d'un noeud. */ -typedef void (* node_prepare_x_fc) (GGraphNode *, GGraphNode *); - -/* Applique une position finale au noeud. */ -typedef void (* node_apply_pos_fc) (GGraphNode *); - -/* Altère la position du noeud d'encapsulation. */ -typedef void (* node_set_pos_fc) (GGraphNode *, gint); - -/* Parcourt tous les noeuds graphiques dans un ordre donné. */ -typedef bool (* visit_flow_nodes_fc) (GGraphNode *, graph_node_visitor_cb, void *); - -/* Recherche le noeud contenant un autre noeud. */ -typedef GGraphNode * (* find_container_fc) (GGraphNode *, GGraphNode *); - - -/* Intermédiaire entre le noeud dot et la bribe de code (instance) */ -struct _GGraphNode -{ -    GObject parent;                         /* A laisser en premier        */ - -    GtkAllocation alloc;                    /* Emplacement du bloc rattaché*/ -    PendingPositionFlags pending_flag;      /* Cible le champ valide       */ -    pending_position pending_pos;           /* Indication sur la position  */ - -}; - - -/* Intermédiaire entre le noeud dot et la bribe de code (classe) */ -struct _GGraphNodeClass -{ -    GObjectClass parent;                    /* A laisser en premier        */ - -    get_node_rank_fc get_rank;              /* Premier rang d'appartenance */ -    node_reset_pos_fc reset_pos;            /* Réinitialise l'emplacement  */ -    node_prepare_x_fc prepare_x;            /* Préparation des abscisses   */ -    node_apply_pos_fc apply_pos;            /* Applique une absisse finale */ -    node_set_pos_fc set_pos;                /* Définit l'emplacement       */ -    visit_flow_nodes_fc visit;              /* Visite des noeuds d'exécut° */ -    find_container_fc contain;              /* Retrouve un conteneur       */ - -}; - - - -#endif  /* _GTKEXT_GRAPH_NODE_INT_H */ diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c deleted file mode 100644 index 08dd970..0000000 --- a/src/gtkext/graph/node.c +++ /dev/null @@ -1,634 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * node.c - éléments de graphiques chez dot - * - * Copyright (C) 2009-2013 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 "node.h" - - -#include <assert.h> -#include <malloc.h> -#include <stdio.h> -#include <string.h> - - -#include "node-int.h" -#include "nodes/flow.h" -#include "nodes/virtual.h" -#include "../../common/extstr.h" - - - -/* -------------------------- GESTION DES NOEUDS A L'UNITE -------------------------- */ - - -/* Initialise la classe des intermédiaires avec les noeuds dot. */ -static void g_graph_node_class_init(GGraphNodeClass *); - -/* Initialise la classe des intermédiaires avec les noeuds dot. */ -static void g_graph_node_init(GGraphNode *); - -/* Supprime toutes les références externes. */ -static void g_graph_node_dispose(GGraphNode *); - -/* Procède à la libération totale de la mémoire. */ -static void g_graph_node_finalize(GGraphNode *); - - - -/* ---------------------------------------------------------------------------------- */ -/*                            GESTION DES NOEUDS A L'UNITE                            */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type définit par la GLib pour le noeud. */ -G_DEFINE_TYPE(GGraphNode, g_graph_node, G_TYPE_OBJECT); - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : klass = classe à initialiser.                                * -*                                                                             * -*  Description : Initialise la classe des intermédiaires avec les noeuds dot. * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_node_class_init(GGraphNodeClass *klass) -{ -    GObjectClass *object;                   /* Autre version de la classe  */ - -    object = G_OBJECT_CLASS(klass); - -    object->dispose = (GObjectFinalizeFunc/* ! */)g_graph_node_dispose; -    object->finalize = (GObjectFinalizeFunc)g_graph_node_finalize; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance à initialiser.                               * -*                                                                             * -*  Description : Initialise la classe des intermédiaires avec les noeuds dot. * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_node_init(GGraphNode *node) -{ -    node->alloc.x = UNINITIALIZED_NODE_POS; -    node->alloc.y = UNINITIALIZED_NODE_POS; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance d'objet GLib à traiter.                      * -*                                                                             * -*  Description : Supprime toutes les références externes.                     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_node_dispose(GGraphNode *node) -{ -    G_OBJECT_CLASS(g_graph_node_parent_class)->dispose(G_OBJECT(node)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance d'objet GLib à traiter.                      * -*                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_node_finalize(GGraphNode *node) -{ -    G_OBJECT_CLASS(g_graph_node_parent_class)->finalize(G_OBJECT(node)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à consulter.                          * -*                                                                             * -*  Description : Fournit le rang du noeud dans le graphique.                  * -*                                                                             * -*  Retour      : Indice supérieur ou égal à zéro.                             * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -unsigned int g_graph_node_get_rank(const GGraphNode *node) -{ -    return G_GRAPH_NODE_GET_CLASS(node)->get_rank(node); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à manipuler.                          * -*                                                                             * -*  Description : Réinitialise la position d'un noeud de graphique.            * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_node_reset_position(GGraphNode *node) -{ -    node->alloc.x = UNINITIALIZED_NODE_POS; -    node->alloc.y = UNINITIALIZED_NODE_POS; - -    node->pending_flag = PPF_NONE; - -    if (G_GRAPH_NODE_GET_CLASS(node)->reset_pos != NULL) -        G_GRAPH_NODE_GET_CLASS(node)->reset_pos(node); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud d'encapsulation à traiter.                     * -*                nodes = ensemble des noeuds en place.                        * -*                                                                             * -*  Description : Définit les abscisses relatives du contenu d'un noeud.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_node_prepare_x_line(GGraphNode *node, GGraphNode *nodes) -{ -    G_GRAPH_NODE_GET_CLASS(node)->prepare_x(node, nodes); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à manipuler.                          * -*                                                                             * -*  Description : Applique une position finale au noeud.                       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_node_apply_position(GGraphNode *node) -{ -    gint x_pos;                             /* Position de référence       */ -    GGraphNode *ref;                        /* Accès rapide                */ - -    if (G_GRAPH_NODE_GET_CLASS(node)->apply_pos != NULL) -        G_GRAPH_NODE_GET_CLASS(node)->apply_pos(node); - -    switch (node->pending_flag) -    { -        case PPF_DIRECT_X: -            assert(g_graph_node_has_x_position(node->pending_pos.relative_ref)); -            g_graph_node_get_position(node->pending_pos.relative_ref, &x_pos, NULL); -            x_pos += node->pending_pos.direct_x; -            g_graph_node_set_x_position(node, x_pos); -            break; - -        case PPF_LEFT_MARGIN: -            assert(g_graph_node_has_x_position(node->pending_pos.relative_ref)); -            g_graph_node_get_position(node->pending_pos.relative_ref, &x_pos, NULL); -            x_pos += EDGE_SLOT_HORIZ_MARGIN + node->pending_pos.left_margin; -            g_graph_node_set_x_position(node, x_pos); -            break; - -        case PPF_RIGHT_MARGIN: -            assert(g_graph_node_has_x_position(node->pending_pos.relative_ref)); -            g_graph_node_get_position(node->pending_pos.relative_ref, &x_pos, NULL); -            x_pos += node->pending_pos.right_margin; -            x_pos -= (EDGE_SLOT_HORIZ_MARGIN + node->alloc.width); -            g_graph_node_set_x_position(node, x_pos); -            break; - -        case PPF_LEFT_NODE: -            ref = node->pending_pos.left_node; -            x_pos = ref->alloc.x - NODE_HORIZONTAL_MARGIN - node->alloc.width; -            g_graph_node_set_x_position(node, x_pos); -            break; - -        case PPF_RIGHT_NODE: -            ref = node->pending_pos.right_node; -            x_pos = ref->alloc.x + ref->alloc.width - NODE_HORIZONTAL_MARGIN; -            g_graph_node_set_x_position(node, x_pos); -            break; - -        default: -            /* Position traitée par l'appelant */ -            break; - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à manipuler.                          * -*  Paramètres  : node   = noeud graphique à manipuler.                        * -*                x      = abscisse à intégrer.                                * -*                direct = indique un tracé direct éventuel.                   * -*                                                                             * -*  Description : Altère la position du noeud d'encapsulation.                 * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_node_set_x_position(GGraphNode *node, gint x) -{ -    if (G_GRAPH_NODE_GET_CLASS(node)->set_pos != NULL && x != GRAPH_HORIZONTAL_MARGIN) -        G_GRAPH_NODE_GET_CLASS(node)->set_pos(node, x); - -    node->alloc.x = x; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à manipuler.                          * -*                flag = nature de l'indication à intégrer.                    * -*                pos  = argument supplémentaire à venir chercher.             * -*                                                                             * -*  Description : Prépare la position du noeud pour l'alignement des liens.    * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_node_set_pending_position(GGraphNode *node, PendingPositionFlags flag, pending_position pos) -{ -    if (node->pending_flag != PPF_NONE && node->pending_flag != PPF_MIDDLE_OF) -        return; - -    node->pending_flag = flag; -    node->pending_pos = pos; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à manipuler.                          * -*                flag = nature de l'indication à intégrer. [OUT]              * -*                pos  = argument supplémentaire à venir chercher. [OUT]       * -*                                                                             * -*  Description : Indique la position du noeud pour l'alignement des liens.    * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_node_get_pending_position(GGraphNode *node, PendingPositionFlags *flag, pending_position *pos) -{ -    *flag = node->pending_flag; - -    if (pos != NULL) -        *pos = node->pending_pos; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à consulter.                          * -*                x    = éventuelle abscisse à recevoir ou NULL. [OUT]         * -*                y    = éventuelle ordonnée à recevoir ou NULL. [OUT]         * -*                                                                             * -*  Description : Fournit la position du noeud d'encapsulation.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_node_get_position(const GGraphNode *node, gint *x, gint *y) -{ -    if (x != NULL) *x = node->alloc.x; -    if (y != NULL) *y = node->alloc.y; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à consulter.                          * -*                                                                             * -*  Description : Indique l'espace requis pour un noeud d'encapsulation.       * -*                                                                             * -*  Retour      : Espace constitué, entièrement ou non.                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GtkAllocation g_graph_node_get_allocation(const GGraphNode *node) -{ -    return node->alloc; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node     = noeud graphique démarrant la visite.              * -*                callback = ensemble de blocs à parcourir.                    * -*                data     = donnée utilisateur à associer au parcours.        * -*                                                                             * -*  Description : Parcourt tous les noeuds graphiques dans un ordre donné.     * -*                                                                             * -*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -bool g_graph_node_visit_nodes(GGraphNode *node, graph_node_visitor_cb callback, void *data) -{ -    return G_GRAPH_NODE_GET_CLASS(node)->visit(node, callback, data); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : nodes  = noeud au sommet de la hiérarchie.                   * -*                target = élément à retrouver dans l'ensemble de noeuds.      * -*                                                                             * -*  Description : Recherche le noeud contenant un autre noeud.                 * -*                                                                             * -*  Retour      : Noeud trouvé ou NULL si aucun.                               * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GGraphNode *g_graph_node_find_container(GGraphNode *nodes, GGraphNode *target) -{ -    GGraphNode *result;                     /* Trouvaille à retourner      */ - -    result = NULL; - -    if (G_GRAPH_NODE_GET_CLASS(nodes)->contain != NULL) -        result = G_GRAPH_NODE_GET_CLASS(nodes)->contain(nodes, target); - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : nodes  = noeud au sommet de la hiérarchie.                   * -*                ref    = noeud indiquant le niveau de référence.             * -*                target = élément à retrouver dans l'ensemble de noeuds.      * -*                                                                             * -*  Description : Recherche le noeud contenant un autre noeud à un même niveau.* -*                                                                             * -*  Retour      : Noeud trouvé ou NULL si aucun.                               * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GGraphNode *g_graph_node_find_container_at_same_level(GGraphNode *nodes, GGraphNode *ref, GGraphNode *target) -{ -    GGraphNode *result;                     /* Trouvaille à retourner      */ -    GGraphNode *level;                      /* Niveau de référence         */ -    GGraphNode *container;                  /* Support de la cible         */ - -    result = NULL; - -    level = g_graph_node_find_container(nodes, ref); - -    container = g_graph_node_find_container(nodes, target); - -    if (container == level) -        result = target; -    else -    { -        if (container == NULL) -            result = NULL; -        else -            result = g_graph_node_find_container_at_same_level(nodes, ref, container); -    } - -    return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                         MANIPULATION D'ENSEMBLES DE NOEUDS                         */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : views = liste de vues à parcourir.                           * -*                count = taille de la liste.                                  * -*                addrt = adresse de début du noeud recherché.                 * -*                                                                             * -*  Description : Recherche une vue donnée dans une série de vues.             * -*                                                                             * -*  Retour      : Vue trouvée ou NULL si aucun.                                * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GtkBufferView *find_graph_view_by_start_address(GtkBufferView **views, size_t count, const vmpa2t *addr) -{ -    GtkBufferView *result;                  /* Trouvaille à remonter       */ -    size_t i;                               /* Boucle de parcours          */ -    GBufferView *buffer;                    /* Tampon d'une partie de code */ -    vmpa2t start;                           /* Adresse de départ du tampon */ - -    result = NULL; - -    for (i = 0; i < count && result == NULL; i++) -    { -        buffer = gtk_buffer_view_get_buffer(views[i]); -        g_buffer_view_get_restrictions(buffer, &start, NULL); - -        if (cmp_vmpa(&start, addr) == 0) -            result = views[i]; - -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = ensemble des blocs basiques déjà découpés.           * -*                views = morceaux de code à afficher de façon organisée.      * -*                count = quantité de ces morceaux de code.                    * -*                                                                             * -*  Description : Réalise une conversion de blocs en noeuds.                   * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GGraphNode *convert_blocks_into_nodes(GInstrBlock *block, GtkBufferView **views, size_t count) -{ -    GGraphNode *result;                     /* Instance nouvelle à renvoyer*/ -    vmpa2t start;                           /* Adresse de départ           */ -    GtkBufferView *view;                    /* Vue existante à retrouver   */ -    size_t max;                             /* Nombre de blocs à gérer     */ -    size_t i;                               /* Boucle de parcours          */ -    GInstrBlock *sub_block;                 /* Sous-bloc intégré           */ -    GGraphNode *child;                      /* Conversion à mémoriser      */ - -    result = NULL; - -    if (G_IS_FLOW_BLOCK(block)) -    { -        g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(block), &start, NULL); -        view = find_graph_view_by_start_address(views, count, &start); - -        result = g_flow_node_new(G_FLOW_BLOCK(block), view); - -    } -    else if (G_IS_VIRTUAL_BLOCK(block)) -    { -        result = g_virtual_node_new(G_VIRTUAL_BLOCK(block)); - -        max = g_virtual_block_count_children(G_VIRTUAL_BLOCK(block)); - -        for (i = 0; i < max; i++) -        { -            sub_block = g_virtual_block_get_child(G_VIRTUAL_BLOCK(block), i); -            child = convert_blocks_into_nodes(sub_block, views, count); - -            g_virtual_node_add_child(G_VIRTUAL_NODE(result), child); - -        } - -    } -    /*else BUG_ON(1); */ - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : nodes = noeud au sommet de la hiérarchie.                    * -*                instr = instruction à retrouver.                             * -*                entry = position de cette instruction : première ou dernière.* -*                                                                             * -*  Description : Recherche le noeud contenant une instruction donnée.         * -*                                                                             * -*  Retour      : Noeud trouvé ou NULL.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GGraphNode *_find_node_for_instruction(GGraphNode *nodes, GArchInstruction *instr, bool entry) -{ -    GGraphNode *result;                     /* Trouvaille à retourner      */ -    struct visit_params { -        GArchInstruction *instr;            /* Instruction recherchée      */ -        bool entry;                         /* Première ou dernière ?      */ -        GGraphNode *found;                  /* Remontée du noeud trouvé    */ -    } params;                               /* Paramètres pour le parcours */ - -    params.instr = instr; -    params.entry = entry; -    params.found = NULL; - -    bool _find_node_cb(GFlowNode *node, GNodeVisitState state, struct visit_params *params) -    { -        bool result; - -        if (state == GVS_NODE) -        { -            if ((params->entry && g_flow_node_start_with(node, params->instr)) -                || (!params->entry && g_flow_node_end_with(node, params->instr))) -            { -                params->found = G_GRAPH_NODE(node); -            } -            result = (params->found == NULL); -        } -        else result = true; - -        return result; - -    } - -    g_graph_node_visit_nodes(nodes, (graph_node_visitor_cb)_find_node_cb, ¶ms); - -    result = params.found; - -    return result; - -} diff --git a/src/gtkext/graph/node.h b/src/gtkext/graph/node.h deleted file mode 100644 index 6d3589a..0000000 --- a/src/gtkext/graph/node.h +++ /dev/null @@ -1,174 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * node.h - prototypes pour les éléments de graphiques chez dot - * - * Copyright (C) 2009-2013 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  OpenIDA is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 3 of the License, or - *  (at your option) any later version. - * - *  OpenIDA is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _GTKEXT_GRAPH_NODE_H -#define _GTKEXT_GRAPH_NODE_H - - -#include "params.h" -#include "ranks.h" -#include "../gtkbufferview.h" -#include "../gtkgraphview.h" -#include "../../arch/instruction.h" -#include "../../analysis/block.h" - - - -/* -------------------------- GESTION DES NOEUDS A L'UNITE -------------------------- */ - - -#define G_TYPE_GRAPH_NODE                  (g_graph_node_get_type()) -#define G_GRAPH_NODE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GRAPH_NODE, GGraphNode)) -#define G_GRAPH_NODE_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GRAPH_NODE, GGraphNodeClass)) -#define G_IS_GRAPH_NODE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GRAPH_NODE)) -#define G_IS_GRAPH_NODE_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GRAPH_NODE)) -#define G_GRAPH_NODE_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_NODE, GGraphNodeClass)) - - -/* Intermédiaire entre le noeud dot et la bribe de code (instance) */ -typedef struct _GGraphNode GGraphNode; - -/* Intermédiaire entre le noeud dot et la bribe de code (classe) */ -typedef struct _GGraphNodeClass GGraphNodeClass; - - -/* Indications sur l'abscisse idéale à adopter */ -typedef union _pending_position -{ -    /* PPF_DIRECT_X, PPF_LEFT_MARGIN, PPF_RIGHT_MARGIN */ -    struct -    { -        union -        { -            gint direct_x;                  /* Position strictement vert.  */ -            gint left_margin;               /* Limite à ne pas dépasser #1 */ -            gint right_margin;              /* Limite à ne pas dépasser #2 */ -        }; -        GGraphNode *relative_ref;           /* Eventuelle ref. relative    */ -    }; - -    /* PPF_LEFT_NODE, PPF_RIGHT_NODE, PPF_MIDDLE_OF */ -    struct -    { -        GGraphNode *left_node;              /* Noeud de référence à droite */ -        GGraphNode *right_node;             /* Noeud de référence à gauche */ -    }; - -} pending_position; - -/* Définition présente dans les indications */ -typedef enum _PendingPositionFlags -{ -    PPF_NONE,                               /* Aucune -> centrage          */ -    PPF_DIRECT_X,                           /* Position strictement vert.  */ -    PPF_LEFT_MARGIN,                        /* Limite à ne pas dépasser #1 */ -    PPF_RIGHT_MARGIN,                       /* Limite à ne pas dépasser #2 */ -    PPF_LEFT_NODE,                          /* Noeud de référence à droite */ -    PPF_RIGHT_NODE,                         /* Noeud de référence à gauche */ -    PPF_MIDDLE_OF                           /* Centré entre deux noeuds    */ - -} PendingPositionFlags; - -/* Détail sur une visite */ -typedef enum _GNodeVisitState -{ -    GVS_ENTER,                              /* Entrée dans un groupe       */ -    GVS_NODE,                               /* Traitement d'une feuille    */ -    GVS_EXIT                                /* Sortie d'un groupe          */ - -} GNodeVisitState; - -/* Rappel à chaque noeud visité */ -typedef bool (* graph_node_visitor_cb) (GGraphNode *, GNodeVisitState, void *); - - -/* Indique le type définit par la GLib pour le noeud. */ -GType g_graph_node_get_type(void); - -/* Fournit le rang du noeud dans le graphique. */ -unsigned int g_graph_node_get_rank(const GGraphNode *); - -/* Réinitialise la position d'un noeud de graphique. */ -void g_graph_node_reset_position(GGraphNode *); - -/* Définit les abscisses relatives du contenu d'un noeud. */ -void g_graph_node_prepare_x_line(GGraphNode *node, GGraphNode *nodes); - -/* Applique une position finale au noeud. */ -void g_graph_node_apply_position(GGraphNode *); - -/* Altère la position du noeud d'encapsulation. */ -void g_graph_node_set_x_position(GGraphNode *, gint); - -/* Prépare la position du noeud pour l'alignement des liens. */ -void g_graph_node_set_pending_position(GGraphNode *, PendingPositionFlags, pending_position); - -/* Indique la position du noeud pour l'alignement des liens. */ -void g_graph_node_get_pending_position(GGraphNode *, PendingPositionFlags *, pending_position *); - -/* Fournit la position du noeud d'encapsulation. */ -void g_graph_node_get_position(const GGraphNode *, gint *, gint *); - -#define g_graph_node_has_x_position(node)           \ -    ({                                              \ -        gint _x;                                    \ -        g_graph_node_get_position(node, &_x, NULL); \ -        _x != UNINITIALIZED_NODE_POS;               \ -    }) - -/* Espace constitué, entièrement ou non. */ -GtkAllocation g_graph_node_get_allocation(const GGraphNode *); - -/* Parcourt tous les noeuds graphiques dans un ordre donné. */ -bool g_graph_node_visit_nodes(GGraphNode *, graph_node_visitor_cb, void *); - -/* Recherche le noeud contenant un autre noeud. */ -GGraphNode *g_graph_node_find_container(GGraphNode *, GGraphNode *); - -/* Recherche le noeud contenant un autre noeud à un même niveau. */ -GGraphNode *g_graph_node_find_container_at_same_level(GGraphNode *, GGraphNode *, GGraphNode *); - - - -/* ----------------------- MANIPULATION D'ENSEMBLES DE NOEUDS ----------------------- */ - - -/* Recherche une vue donnée dans une série de vues. */ -GtkBufferView *find_graph_view_by_start_address(GtkBufferView **, size_t, const vmpa2t *); - -/* Réalise une conversion de blocs en noeuds. */ -GGraphNode *convert_blocks_into_nodes(GInstrBlock *, GtkBufferView **, size_t); - -/* Recherche le noeud contenant une instruction donnée. */ -GGraphNode *_find_node_for_instruction(GGraphNode *, GArchInstruction *, bool); - - -#define find_node_for_first_instruction(nds, ins)     \ -    _find_node_for_instruction(nds, ins, true) - -#define find_node_for_last_instruction(nds, ins) \ -    _find_node_for_instruction(nds, ins, false) - - - -#endif  /* _GRAPH_NODE_H */ diff --git a/src/gtkext/graph/nodes/Makefile.am b/src/gtkext/graph/nodes/Makefile.am deleted file mode 100755 index 50f26f1..0000000 --- a/src/gtkext/graph/nodes/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ - -noinst_LTLIBRARIES  = libgtkextgraphnodes.la - -libgtkextgraphnodes_la_SOURCES =		\ -	flow.h flow.c						\ -	virtual.h virtual.c - -libgtkextgraphnodes_la_LDFLAGS =  - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - -SUBDIRS =  diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c deleted file mode 100644 index e19cacb..0000000 --- a/src/gtkext/graph/nodes/flow.c +++ /dev/null @@ -1,1329 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * flow.c - encapsulation graphique des blocs d'exécution - * - * Copyright (C) 2013 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 "flow.h" - - -#include <assert.h> -#include <malloc.h> -#include <stdlib.h> - - -#include "../layout.h" -#include "../node-int.h" - - - -/* Type d'un accrochage pour lien */ -struct _node_slot_t -{ -    GArchInstruction *instr;                /* Instruction liée            */ -    size_t group_index;                     /* Rang dans le grp d'origine  */ - -    InstructionLinkType type;               /* Type de lien à représenter  */ -    size_t slot_index;                      /* Position dans l'accroche    */ -    gint x;                                 /* Abscisse graphique du rendu */ - -}; - -/* Encapsulation graphique d'un bloc d'exécution (instance) */ -struct _GFlowNode -{ -    GGraphNode parent;                      /* A laisser en premier        */ - -    GFlowBlock *block;                      /* Bloc d'exécution associé    */ -    GtkBufferView *view;                    /* Représentation graphique    */ - -    node_slot_t *entries;                   /* Positions des pts d'entrées */ -    size_t entries_count;                   /* Nombre de ces points        */ -    node_slot_t *exits;                     /* Positions des pts de sorties*/ -    size_t exits_count;                     /* Nombre de ces points        */ - -}; - -/* Encapsulation graphique d'un bloc d'exécution (classe) */ -struct _GFlowNodeClass -{ -    GGraphNodeClass parent;                 /* A laisser en premier        */ - -}; - - -#define SPACE_BETWEEN_SLOT 15 - - -/* Initialise la classe des encapsulations de bloc d'exécution. */ -static void g_flow_node_class_init(GFlowNodeClass *); - -/* Initialise une encapsulation de bloc d'exécution. */ -static void g_flow_node_init(GFlowNode *); - -/* Supprime toutes les références externes. */ -static void g_flow_node_dispose(GFlowNode *); - -/* Procède à la libération totale de la mémoire. */ -static void g_flow_node_finalize(GFlowNode *); - -/* Fournit le rang du noeud dans le graphique. */ -static unsigned int g_flow_node_get_rank(const GFlowNode *); - -/* Organise le contenu du noeud selon l'axe des abscisses. */ -static void g_flow_node_prepare_x_line(GFlowNode *, GGraphNode *); - -/* Parcourt tous les blocs d'instructions dans un ordre donné. */ -static bool g_flow_node_visit_flow_nodes(GFlowNode *, graph_node_visitor_cb, void *); - - - -/* ------------------------ GESTION DES ACCROCHES D'UN NOEUD ------------------------ */ - - -/* Prépare les points d'entrées du noeud. */ -static void g_flow_node_setup_entry_slots(GFlowNode *); - -/* Prépare les points de sorties du noeud. */ -static void g_flow_node_setup_exit_slots(GFlowNode *); - -/* Etablit un lien entre deux noeuds graphiques. */ -static node_slot_t *g_flow_node_get_slot(const GFlowNode *, bool, GArchInstruction *, size_t); - -/* Localise un point d'accroche à un noeud graphique. */ -static gint g_flow_node_get_slot_offset(const GFlowNode *, bool, const node_slot_t *); - - - - -/* Indique le type définit par la GLib pour l'encapsulation d'un bloc d'exécution. */ -G_DEFINE_TYPE(GFlowNode, g_flow_node, G_TYPE_GRAPH_NODE); - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : klass = classe à initialiser.                                * -*                                                                             * -*  Description : Initialise la classe des encapsulations de bloc d'exécution. * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_flow_node_class_init(GFlowNodeClass *klass) -{ -    GObjectClass *object;                   /* Autre version de la classe  */ -    GGraphNodeClass *node_class;            /* Version parente de la classe*/ - -    object = G_OBJECT_CLASS(klass); -    node_class = G_GRAPH_NODE_CLASS(klass); - -    object->dispose = (GObjectFinalizeFunc/* ! */)g_flow_node_dispose; -    object->finalize = (GObjectFinalizeFunc)g_flow_node_finalize; - -    node_class->get_rank = (get_node_rank_fc)g_flow_node_get_rank; -    node_class->prepare_x = (node_prepare_x_fc)g_flow_node_prepare_x_line; -    node_class->visit = (visit_flow_nodes_fc)g_flow_node_visit_flow_nodes; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance à initialiser.                               * -*                                                                             * -*  Description : Initialise une encapsulation de bloc d'exécution.            * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_flow_node_init(GFlowNode *node) -{ - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance d'objet GLib à traiter.                      * -*                                                                             * -*  Description : Supprime toutes les références externes.                     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_flow_node_dispose(GFlowNode *node) -{ -    size_t i;                               /* Boucle de parcours          */ - -    g_object_unref(G_OBJECT(node->block)); -    g_object_unref(G_OBJECT(node->view)); - -    for (i = 0; i < node->entries_count; i++) -        g_object_unref(G_OBJECT(node->entries[i].instr)); - -    for (i = 0; i < node->exits_count; i++) -        g_object_unref(G_OBJECT(node->exits[i].instr)); - -    G_OBJECT_CLASS(g_flow_node_parent_class)->dispose(G_OBJECT(node)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance d'objet GLib à traiter.                      * -*                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_flow_node_finalize(GFlowNode *node) -{ -    if (node->entries != NULL) -        free(node->entries); - -    if (node->exits != NULL) -        free(node->exits); - -    G_OBJECT_CLASS(g_flow_node_parent_class)->finalize(G_OBJECT(node)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = bloc d'exécution représenté graphiquement.           * -*                view  = morceau d'affichage à représenter.                   * -*                                                                             * -*  Description : Encapsule graphiquement un bloc d'exécution.                 * -*                                                                             * -*  Retour      : Adresse de la structure mise en place.                       * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GGraphNode *g_flow_node_new(GFlowBlock *block, GtkBufferView *view) -{ -    GFlowNode *result;                      /* Structure à retourner       */ -    GtkRequisition requisition;             /* Taille à l'écran actuelle   */ - -    result = g_object_new(G_TYPE_FLOW_NODE, NULL); - -    g_object_ref(G_OBJECT(block)); -    g_object_ref(G_OBJECT(view)); - -    result->block = block; -    result->view = view; - -    gtk_widget_show(GTK_WIDGET(result->view)); -    gtk_widget_size_allocate(GTK_WIDGET(result->view), (GtkAllocation []) { { 0, 0, 100, 100 } }); - -    gtk_widget_get_preferred_size(GTK_WIDGET(result->view), NULL, &requisition); - -    G_GRAPH_NODE(result)->alloc.width = requisition.width; -    G_GRAPH_NODE(result)->alloc.height = requisition.height; - -    g_flow_node_setup_entry_slots(result); -    g_flow_node_setup_exit_slots(result); - -    return G_GRAPH_NODE(result); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à consulter.                          * -*                                                                             * -*  Description : Fournit le rang du noeud dans le graphique.                  * -*                                                                             * -*  Retour      : Indice supérieur ou égal à zéro.                             * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static unsigned int g_flow_node_get_rank(const GFlowNode *node) -{ -    return g_flow_block_get_rank(node->block); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud d'encapsulation à traiter.                     * -*                nodes = ensemble des noeuds en place.                        * -*                                                                             * -*  Description : Organise le contenu du noeud selon l'axe des abscisses.      * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes) -{ -    GGraphNode *base;                       /* Autre vision de l'instance  */ -    GArchInstruction *last;                 /* Dernière instr. du noeud    */ -    size_t loop_index;                      /* Indice de sortie en boucle  */ -    GFlowNode *target;                      /* Bloc visé par le lien       */ -    node_slot_t *dest_slot;                 /* Accrochage d'arrivée        */ -    pending_position pos;                   /* Position à transmettre      */ -    GFlowNode *target_a;                    /* Bloc visé par le lien #a    */ -    GFlowNode *target_b;                    /* Bloc visé par le lien #b    */ -    unsigned int rank_a;                    /* Indice du rang associé #a   */ -    unsigned int rank_b;                    /* Indice du rang associé #b   */ -    GGraphNode *container;                  /* Conteneur à positionner     */ - -    base = G_GRAPH_NODE(node); - -    g_flow_block_get_boundary(node->block, NULL, &last); - -    for (loop_index = 0; loop_index < node->exits_count; loop_index++) -        if (node->exits[loop_index].type == ILT_LOOP) -            break; - -    switch (node->exits_count - (loop_index == node->exits_count ? 0 : 1)) -    { -        case 0: -            break; - -        case 1: - -            if (loop_index == node->exits_count) -            { -                target = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[0].instr)); - -                /* Cf. commentaire de g_flow_node_link() */ -                if (target == NULL) break; - -                dest_slot = g_flow_node_get_slot(target, true, -                                                 last, node->exits[0].group_index); - -            } -            else -            { -                target = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[1].instr)); - -                /* Cf. commentaire de g_flow_node_link() */ -                if (target == NULL) break; - -                dest_slot = g_flow_node_get_slot(target, true, -                                                 last, node->exits[1].group_index); - -            } - -            pos.direct_x = g_flow_node_get_slot_offset(target, true, dest_slot); -            pos.direct_x = (G_GRAPH_NODE(target)->alloc.width / 2) - pos.direct_x; - -            pos.direct_x -= (G_GRAPH_NODE(target)->alloc.width - G_GRAPH_NODE(node)->alloc.width) / 2; - -            pos.relative_ref = base; - -            size_t count_and_skip_loop(GFlowNode *n) -            { -                size_t counter; - -                for (counter = 0; counter < n->entries_count; counter++) -                    if (n->entries[counter].type == ILT_LOOP) -                        break; - -                return counter < n->entries_count ? n->entries_count - 1 : n->entries_count; - -            } - -            if (count_and_skip_loop(target) == 1) -                g_graph_node_set_pending_position(G_GRAPH_NODE(target), PPF_DIRECT_X, pos); - -            break; - -        case 2: - -            target_a = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[0].instr)); -            target_b = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[1].instr)); - -            rank_a = g_flow_node_get_rank(target_a); -            rank_b = g_flow_node_get_rank(target_b); - -            if (rank_a == rank_b) -            { -                /* On s'assure que le père est centré par rapport aux deux fils */ - -                pos.left_node = G_GRAPH_NODE(target_a); -                pos.right_node = G_GRAPH_NODE(target_b); - -                /** -                 * Un pré-condition pour pouvoir s'aligner est que les noeuds -                 * de références soient traités au préalables pour les positions. -                 * Sinon les assert() coincent dans g_virtual_node_apply_x_line(). -                 */ - -                if (g_graph_node_find_container_at_same_level(nodes, base, pos.left_node) != NULL -                    && g_graph_node_find_container_at_same_level(nodes, base, pos.right_node) != NULL) -                { -                    g_graph_node_set_pending_position(base, PPF_MIDDLE_OF, pos); -                } - -                break; - -            } - -            /* Alignement d'un bloc lié */ - -            if (rank_a > rank_b) -            { -                /* Seuil vertical pour un côté */ - -                container = g_graph_node_find_container_at_same_level(nodes, -                                                                      G_GRAPH_NODE(node), -                                                                      G_GRAPH_NODE(target_b)); - -                if (container == NULL) container = G_GRAPH_NODE(target_b); - -                pos.left_margin = g_flow_node_get_slot_offset(node, false, &node->exits[0]); -                pos.relative_ref = base; -                g_graph_node_set_pending_position(container, PPF_LEFT_MARGIN, pos); - -                /* Trait vertical de l'autre côté... */ - -                pos.direct_x = pos.left_margin; - -                dest_slot = g_flow_node_get_slot(target_a, true, -                                                 last, node->exits[0].group_index); - -                pos.direct_x -= g_flow_node_get_slot_offset(target_a, true, dest_slot); - -                pos.relative_ref = base; - -                g_graph_node_set_pending_position(G_GRAPH_NODE(target_a), PPF_DIRECT_X, pos); - -            } -            else -            { -                /* Seuil vertical pour un côté */ - -                container = g_graph_node_find_container_at_same_level(nodes, -                                                                      G_GRAPH_NODE(node), -                                                                      G_GRAPH_NODE(target_a)); - -                if (container == NULL) container = G_GRAPH_NODE(target_a); - -                pos.right_margin = g_flow_node_get_slot_offset(node, false, &node->exits[1]); -                pos.relative_ref = base; -                g_graph_node_set_pending_position(container, PPF_RIGHT_MARGIN, pos); - -                /* Trait vertical de l'autre côté... */ - -                pos.direct_x = pos.right_margin; - -                dest_slot = g_flow_node_get_slot(target_b, true, -                                                 last, node->exits[1].group_index); - -                pos.direct_x -= g_flow_node_get_slot_offset(target_b, true, dest_slot); - -                pos.relative_ref = base; - -                g_graph_node_set_pending_position(G_GRAPH_NODE(target_b), PPF_DIRECT_X, pos); - -            } - -            break; - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node     = noeud graphique démarrant la visite.              * -*                callback = ensemble de blocs à parcourir.                    * -*                data     = donnée utilisateur à associer au parcours.        * -*                                                                             * -*  Description : Parcourt tous les blocs d'instructions dans un ordre donné.  * -*                                                                             * -*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_flow_node_visit_flow_nodes(GFlowNode *node, graph_node_visitor_cb callback, void *data) -{ -    return callback(G_GRAPH_NODE(node), GVS_NODE, data); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à consulter.                          * -*                                                                             * -*  Description : Fournit le bloc basique à l'origine du bloc graphique.       * -*                                                                             * -*  Retour      : Bloc brut encapsulé.                                         * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GFlowBlock *g_flow_node_get_block(const GFlowNode *node) -{ -    return node->block; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud graphique à consulter.                         * -*                instr = instruction à considérer.                            * -*                                                                             * -*  Description : Précise si le noeud a pour première instruction celle donnée.* -*                                                                             * -*  Retour      : true si la première instruction du noeud est celle indiquée. * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -bool g_flow_node_start_with(const GFlowNode *node, GArchInstruction *instr) -{ -    GArchInstruction *first;                /* Première instr. du noeud    */ - -    g_flow_block_get_boundary(node->block, &first, NULL); - -    return (first == instr); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud graphique à consulter.                         * -*                instr = instruction à considérer.                            * -*                                                                             * -*  Description : Précise si le noeud a pour dernière instruction celle donnée.* -*                                                                             * -*  Retour      : true si la dernière instruction du noeud est celle indiquée. * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -bool g_flow_node_end_with(const GFlowNode *node, GArchInstruction *instr) -{ -    GArchInstruction *last;                 /* Dernière instr. du noeud    */ - -    g_flow_block_get_boundary(node->block, NULL, &last); - -    return (last == instr); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud graphique à consulter.                         * -*                ranks = classement à mettre à jour.                          * -*                                                                             * -*  Description : Précise la hauteur minimale requise pour un noeud.           * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_flow_node_register_rank(const GFlowNode *node, GGraphRanks *ranks) -{ -    unsigned int index;                     /* Indice du rang associé      */ - -    index = g_flow_node_get_rank(node); - -    g_graph_ranks_set_min_height(ranks, index, G_GRAPH_NODE(node)->alloc.height); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud graphique à mettre à jour.                     * -*                ranks = classement à consulter.                              * -*                                                                             * -*  Description : Définit l'ordonnée de l'espace attribué à un noeud.          * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_flow_node_apply_rank(GFlowNode *node, GGraphRanks *ranks) -{ -    unsigned int index;                     /* Indice du rang associé      */ - -    index = g_flow_node_get_rank(node); - -    G_GRAPH_NODE(node)->alloc.y = g_graph_ranks_get_y_for_rank(ranks, index); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node   = noeud graphique à mettre à jour.                    * -*                layout = disposition globale du graphique.                   * -*                nodes  = ensemble des noeuds en place.                       * -*                                                                             * -*  Description : Etablit les liaison entre un noeud et ses suivants.          * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_flow_node_link(GFlowNode *node, GGraphLayout *layout, GGraphNode *nodes) -{ -    GArchInstruction *last;                 /* Dernière instr. du noeud    */ -    size_t i;                               /* Boucle de parcours          */ -    GFlowNode *target;                      /* Bloc visé par le lien       */ -    node_slot_t *dest_slot;                 /* Accrochage d'arrivée        */ -    EdgeColor color;                        /* Couleur du lien à créer     */ -    GGraphEdge *edge;                       /* Lien à mettre en place      */ - -    g_flow_block_get_boundary(node->block, NULL, &last); - -    for (i = 0; i < node->exits_count; i++) -    { -        target = G_FLOW_NODE(find_node_for_first_instruction(nodes, node->exits[i].instr)); - -        /** -         * Il semblerait que l'adresse ciblée puisse ne correspondre à aucun bloc. -         * Ce serait le cas pour un saut avec __gmon_start__ sous ARM, à confirmer (TODO). -         * Référence. : http://stackoverflow.com/questions/12697081/what-is-gmon-start-symbol -         */ -        if (target == NULL) continue; - -        dest_slot = g_flow_node_get_slot(target, true, -                                         last, node->exits[i].group_index); - -        switch (node->exits[i].type) -        { -            case ILT_JUMP_IF_TRUE: -                color = EGC_GREEN; -                break; -            case ILT_JUMP_IF_FALSE: -                color = EGC_RED; -                break; -            case ILT_LOOP: -                color = EGC_BLUE; -                break; -            case ILT_CATCH_EXCEPTION: -                color = EGC_DASHED_GRAY; -                break; -            default: -                color = EGC_DEFAULT; -                break; - -        } - -        edge = g_graph_edge_new(node, &node->exits[i], target, dest_slot, color); -        g_graph_layout_add_edge(layout, edge); - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = intermédiaire à consulter.                            * -*                view = support de destination.                               * -*                                                                             * -*  Description : Place un noeud sur son support final.                        * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_flow_node_place(const GFlowNode *node, GtkGraphView *view) -{ -    gtk_graph_view_put(view, GTK_WIDGET(node->view), &G_GRAPH_NODE(node)->alloc); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                          GESTION DES ACCROCHES D'UN NOEUD                          */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique contenant les accrochées indiquées.   * -*                a    = première accroche à considérer.                       * -*                b    = seconde accroche à considérer.                        * -*                                                                             * -*  Description : Compare deux accroches pour liens entre noeuds.              * -*                                                                             * -*  Retour      : Bilan de la comparaison : -1, 0 ou 1.                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -int g_flow_node_compare_slots_for_edges(const GFlowNode *node, const node_slot_t *a, gint src_a, const node_slot_t *b, gint src_b) -{ -    int result;                             /* Bilan à retourner           */ -    GGraphNode *base;                       /* Accès rapides               */ -    gint middle;                            /* Milieu du noeud traité      */ -    gint diff_a;                            /* Distance A <-> centre       */ -    gint diff_b;                            /* Distance B <-> centre       */ - - -    /** -     * On place les extrémités en premier, afin de les traiter en premier. -     */ - -    int cmp_slot_indexes(const node_slot_t *a, const node_slot_t *b) -    { -        int result; - -        if (a->slot_index < b->slot_index) -            result = 1; - -        else if (a->slot_index > b->slot_index) -            result = -1; - -        else -            result = 0; - -        return result; - -    } - - -    switch (node->entries_count) -    { -        case 0: -        case 1: -            assert(0); -            break; - -        case 2: - -            /** -             * Le tri se fait simplement : un accroche à gauche, l'autre à droite. -             */ - -            result = cmp_slot_indexes(a, b); -            break; - -        default: - -            /** -             * On donne plus de poids aux accroches éloignées du centre. -             * Facile quand les accroches sont distribuées d'un même côté, centre -             * à utiliser dans les calculs sinon. -             */ - -            base = G_GRAPH_NODE(node); - -            middle = base->alloc.x + (base->alloc.width / 2); - - -            /* Les deux accroches sont à gauche */ -            if (src_a <= middle && src_b <= middle) -                result = cmp_slot_indexes(b, a); - -            /* Les deux accroches sont à droite */ -            else if (src_a > middle && src_b > middle) -                result = cmp_slot_indexes(a, b); - -            /* Les deux accroches sont de chaque côté */ -            else -            { -                diff_a = (middle > src_a ? middle - src_a : src_a - middle); -                diff_b = (middle > src_b ? middle - src_b : src_b - middle); - -                if (diff_a < diff_b) -                    result = 1; - -                else if (diff_a > diff_b) -                    result = -1; - -                else -                    result = 0; - -            } - -            break; - -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = intermédiaire à compléter.                            * -*                                                                             * -*  Description : Prépare les points d'entrées du noeud.                       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_flow_node_setup_entry_slots(GFlowNode *node) -{ -    GArchInstruction *first;                /* Première instr. du noeud    */ -    GArchInstruction **instrs;              /* Instr. visée par une autre  */ -    InstructionLinkType *types;             /* Type de lien entre lignes   */ -    size_t icount;                          /* Nombre de liens de dest.    */ -    size_t usable;                          /* Nombre de liens utiles ici  */ -    size_t i;                               /* Boucle de parcours          */ -    size_t used;                            /* Nombre de liens utilisés    */ - -    g_flow_block_get_boundary(node->block, &first, NULL); - -    g_arch_instruction_rlock_src(first); -    icount = g_arch_instruction_get_sources(first, &instrs, &types); - -    usable = 0; - -    for (i = 0; i < icount; i++) -        switch (types[i]) -        { -            case ILT_EXEC_FLOW: -            case ILT_JUMP: -            case ILT_CASE_JUMP: -            case ILT_JUMP_IF_TRUE: -            case ILT_JUMP_IF_FALSE: -            case ILT_LOOP: -            case ILT_CATCH_EXCEPTION: -                usable++; -                break; - -            default: -                break; - -        } - -    if (usable == 0) -    { -        node->entries = NULL; -        node->entries_count = 0; -    } -    else -    { -        node->entries = (node_slot_t *)calloc(usable, sizeof(node_slot_t)); -        node->entries_count = usable; -    } - -    used = 0; - -    for (i = 0; i < icount; i++) -        switch (types[i]) -        { -            case ILT_EXEC_FLOW: -            case ILT_JUMP: -            case ILT_CASE_JUMP: -            case ILT_JUMP_IF_TRUE: -            case ILT_JUMP_IF_FALSE: -            case ILT_LOOP: -            case ILT_CATCH_EXCEPTION: - -                g_object_ref(instrs[i]); -                node->entries[used].instr = instrs[i]; - -                node->entries[used].type = types[i]; -                node->entries[used].group_index = g_arch_instruction_compute_group_index(&instrs[i], -                                                                                         instrs, icount); -                node->entries[used].slot_index = used; - -                used++; - -                break; - -            default: -                break; - -        } - -    assert(used == usable); - -    g_arch_instruction_runlock_src(first); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = intermédiaire à compléter.                            * -*                                                                             * -*  Description : Prépare les points de sorties du noeud.                      * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_flow_node_setup_exit_slots(GFlowNode *node) -{ -    GArchInstruction *last;                 /* Dernière instr. du noeud    */ -    GArchInstruction **instrs;              /* Instr. visée par une autre  */ -    InstructionLinkType *types;             /* Type de lien entre lignes   */ -    size_t icount;                          /* Nombre de liens de dest.    */ -    size_t usable;                          /* Nombre de liens utiles ici  */ -    size_t i;                               /* Boucle de parcours          */ -    size_t used;                            /* Nombre de liens utilisés    */ - -    g_flow_block_get_boundary(node->block, NULL, &last); - -    g_arch_instruction_rlock_dest(last); -    icount = g_arch_instruction_get_destinations(last, &instrs, &types, NULL); - -    usable = 0; - -    for (i = 0; i < icount; i++) -        switch (types[i]) -        { -            case ILT_EXEC_FLOW: -            case ILT_JUMP: -            case ILT_CASE_JUMP: -            case ILT_JUMP_IF_TRUE: -            case ILT_JUMP_IF_FALSE: -            case ILT_LOOP: -            case ILT_CATCH_EXCEPTION: -                usable++; -                break; - -            default: -                break; - -        } - -    if (usable == 0) -    { -        node->exits = NULL; -        node->exits_count = 0; -    } -    else -    { -        node->exits = (node_slot_t *)calloc(usable, sizeof(node_slot_t)); -        node->exits_count = usable; -    } - -    used = 0; - -    for (i = 0; i < icount; i++) -        switch (types[i]) -        { -            case ILT_EXEC_FLOW: -            case ILT_JUMP: -            case ILT_CASE_JUMP: -            case ILT_JUMP_IF_TRUE: -            case ILT_JUMP_IF_FALSE: -            case ILT_LOOP: -            case ILT_CATCH_EXCEPTION: - -                g_object_ref(instrs[i]); -                node->exits[used].instr = instrs[i]; - -                node->exits[used].type = types[i]; -                node->exits[used].group_index = g_arch_instruction_compute_group_index(&instrs[i], -                                                                                       instrs, icount); -                node->exits[used].slot_index = used; - -                used++; - -                break; - -            default: -                break; - -        } - -    assert(used == usable); - -    g_arch_instruction_runlock_dest(last); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud graphique à consulter.                         * -*                entry = indique le type d'accrochage recherché.              * -*                instr = instruction visée.                                   * -*                index = indice de groupe pour départager au besoin.          * -*                                                                             * -*  Description : Etablit un lien entre deux noeuds graphiques.                * -*                                                                             * -*  Retour      : Lien graphique mis en place.                                 * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static node_slot_t *g_flow_node_get_slot(const GFlowNode *node, bool entry, GArchInstruction *instr, size_t index) -{ -    node_slot_t *result;                    /* Emplacement à retourner     */ -    node_slot_t *list;                      /* Liste à parcourir           */ -    size_t count;                           /* Taille de cette liste       */ -    size_t i;                               /* Boucle de parcours          */ - -    if (entry) -    { -        list = node->entries; -        count = node->entries_count; -    } -    else -    { -        list = node->exits; -        count = node->exits_count; -    } - -    for (i = 0; i < count; i++) -    { -        result = list + i; - -        if (result->instr == instr/* && result->group_index == index*/) -            break; - -    } - -    return (i == count ? NULL : result); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud graphique à consulter.                         * -*                entry = indique le type d'accrochage recherché.              * -*                slot  = accroche dont l'emplacement est à définir.           * -*                                                                             * -*  Description : Localise un point d'accroche à un noeud graphique.           * -*                                                                             * -*  Retour      : Décallage relatif pour l'accroche fournie.                   * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static gint g_flow_node_get_slot_offset(const GFlowNode *node, bool entry, const node_slot_t *slot) -{ -    gint result;                            /* Valeur à retourner          */ -    node_slot_t *slots;                     /* Accroches à parcourir       */ -    size_t count;                           /* Nombre de ces points        */ -    gint slots_width;                       /* Largeur des accroches       */ -    gint slots_left;                        /* Abscisse de la première     */ -    size_t index;                           /* Indice de l'accroche visée  */ - -    if (entry) -    { -        slots = node->entries; -        count = node->entries_count; -    } -    else -    { -        slots = node->exits; -        count = node->exits_count; -    } - -    slots_width = (count - 1) * SPACE_BETWEEN_SLOT; -    slots_left = (G_GRAPH_NODE(node)->alloc.width - slots_width) / 2; - -    index = (slot - slots); -    /* BUG_ON(index >= count); */ - -    index = slot->slot_index; - -    result = slots_left + index * SPACE_BETWEEN_SLOT; - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = intermédiaire à consulter.                            * -*                nodes = ensemble des noeuds en place.                        * -*                                                                             * -*  Description : Réorganise au mieux les points d'accroche d'un noeud.        * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ -#include "../../../arch/instruction-int.h" -void g_flow_node_reorder_slots(const GFlowNode *node, GGraphNode *nodes) -{ - -    typedef struct _reordering_params -    { -        GdkPoint middle;                    /* Milieu du noeud traité      */ -        bool down_first;                    /* Liens descendants aux bords */ - -        bool entry;                         /* Zone d'accrochage aux bouts */ -        GArchInstruction *instr;            /* Instruction du bloc courant */ - -    } reordering_params; - -    typedef struct _reordered_slot -    { -        const reordering_params *params;    /* Informations partagées      */ - -        GdkPoint dest;                      /* Position à l'extrémité      */ - -        size_t orig_index;                  /* Indice d'accroche d'origine */ - -    } reordered_slot; - - -    GGraphNode *base;                       /* Accès rapides               */ -    reordering_params params;               /* Directives générales        */ - - -    int cmp_slots_for_reordering(const reordered_slot *a, const reordered_slot *b) -    { -        const reordering_params *params;    /* Informations partagées      */ -        bool on_left_a;                     /* Lien A vers la gauche ?     */ -        bool on_left_b;                     /* Lien B vers la gauche ?     */ -        bool go_down_a;                     /* Lien A vers le bas ?        */ -        bool go_down_b;                     /* Lien B vers le bas ?        */ - -        params = a->params; - -        /* Première distinction : côté par rapport au centre */ - -        on_left_a = (a->dest.x <= params->middle.x); -        on_left_b = (b->dest.x <= params->middle.x); - -        if (on_left_a && !on_left_b) return -1; -        else if (!on_left_a && on_left_b) return 1; - -        /* On évite les recoupements entre montées et descentes */ - -        go_down_a = (a->dest.y >= params->middle.y); -        go_down_b = (b->dest.y >= params->middle.y); - -        if (go_down_a && !go_down_b) return (params->down_first ? -1 : 1); -        else if (!go_down_a && go_down_b) return (params->down_first ? -1 : 1); - -        /* Au sein d'une même catégorie, on se base uniquement sur la position */ - -        return (a->dest.x <= b->dest.x ? -1 : 1); - -    } - -    void reorder_slots(node_slot_t *slots, size_t count, __compar_fn_t cmp, const reordering_params *params, GGraphNode *nodes) -    { -        reordered_slot *rslots;             /* Créneaux réorganisés        */ -        reordered_slot *iter;               /* Boucle de parcours #1       */ -        size_t used;                        /* Nombre de liens valides     */ -        size_t i;                           /* Boucle de parcours #2       */ -        GFlowNode *target;                  /* Bloc visé par le lien       */ -        node_slot_t *dest_slot;             /* Accrochage associé          */ - -        rslots = (reordered_slot *)calloc(count, sizeof(reordered_slot)); - -        /* Constitution d'une liste triée */ - -        iter = rslots; -        used = 0; - -        for (i = 0; i < count; i++) -        { -            iter->params = params; - -            target = G_FLOW_NODE(_find_node_for_instruction(nodes, slots[i].instr, params->entry)); - -            /* Cf. commentaire de g_flow_node_link() */ -            if (target == NULL) continue; - -            dest_slot = g_flow_node_get_slot(target, params->entry, -                                             params->instr, slots[i].group_index); - -            iter->dest = g_flow_node_get_point_from_slot(target, params->entry, dest_slot); - -            iter->orig_index = i; - -            iter++; -            used++; - -        } - -        /* TODO : utiliser qsort_r, avec params en argument ? */ -        qsort(rslots, used, sizeof(reordered_slot), cmp); - - - - -        for (i = 0; i < used; i++) -        { - - -            if (rslots[i].orig_index != i) -                printf("Could reorder %zu -> %zu\n", rslots[i].orig_index, i); - -            if (rslots[i].orig_index != i) -                slots[rslots[i].orig_index].slot_index = i; - - - -        } - -        free(rslots); - -    } - - -    base = G_GRAPH_NODE(node); - -    /* Régorganise les accroches d'entrée */ - -    if (node->entries_count > 1) -    { -        params.middle.x = base->alloc.x + (base->alloc.width / 2); -        params.middle.y = base->alloc.y; - -        params.down_first = true; - -        params.entry = false; -        g_flow_block_get_boundary(node->block, ¶ms.instr, NULL); - -        printf(" ### REORDERING ENTRIES OF 0x%08x\n", (unsigned int)params.instr->range.addr.virtual); - -        reorder_slots(node->entries, node->entries_count, (__compar_fn_t)cmp_slots_for_reordering, ¶ms, nodes); - -    } - -    /* Régorganise les accroches de sortie */ - -    if (node->exits_count > 1) -    { -        params.middle.x = base->alloc.x + (base->alloc.width / 2); -        params.middle.y = base->alloc.y + base->alloc.height; - -        params.down_first = false; - -        params.entry = true; -        g_flow_block_get_boundary(node->block, NULL, ¶ms.instr); - -        printf(" ### REORDERING EXITS OF 0x%08x\n", (unsigned int)params.instr->range.addr.virtual); - -        reorder_slots(node->exits, node->exits_count, (__compar_fn_t)cmp_slots_for_reordering, ¶ms, nodes); - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud graphique à consulter.                         * -*                entry = indique le type d'accrochage recherché.              * -*                slot  = accroche dont l'emplacement est à définir.           * -*                                                                             * -*  Description : Localise un point d'accroche à un noeud graphique.           * -*                                                                             * -*  Retour      : Emplacement réservé pour l'accroche fournie.                 * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *node, bool entry, const node_slot_t *slot) -{ -    GGraphNode *base;                       /* Accès rapides               */ -    GdkPoint result;                        /* Position à retourner        */ -    node_slot_t *slots;                     /* Accroches à parcourir       */ -    size_t count;                           /* Nombre de ces points        */ -    gint slots_width;                       /* Largeur des accroches       */ -    gint slots_left;                        /* Abscisse de la première     */ -    size_t index;                           /* Indice de l'accroche visée  */ - -    base = G_GRAPH_NODE(node); - -    if (entry) -    { -        result.y = base->alloc.y; - -        slots = node->entries; -        count = node->entries_count; - -    } -    else -    { -        result.y = base->alloc.y + base->alloc.height; - -        slots = node->exits; -        count = node->exits_count; - -    } - -    slots_width = (count - 1) * SPACE_BETWEEN_SLOT; -    slots_left = base->alloc.x + (base->alloc.width - slots_width) / 2; - -    index = (slot - slots)/* / sizeof(node_slot_t)*/; -    /* BUG_ON(index >= count); */ - - -    if (count > 1 && entry) -        printf("  -->> index = %zu vs %zu (max = %zu)\n", index, slot->slot_index, count); - -    index = slot->slot_index; - - -    result.x = slots_left + index * SPACE_BETWEEN_SLOT; - -    return result; - -} diff --git a/src/gtkext/graph/nodes/flow.h b/src/gtkext/graph/nodes/flow.h deleted file mode 100644 index 76d0a03..0000000 --- a/src/gtkext/graph/nodes/flow.h +++ /dev/null @@ -1,99 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * flow.h - prototypes pour l'encapsulation graphique des blocs d'exécution - * - * Copyright (C) 2013 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  OpenIDA is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 3 of the License, or - *  (at your option) any later version. - * - *  OpenIDA is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _GTKEXT_GRAPH_NODES_FLOW_H -#define _GTKEXT_GRAPH_NODES_FLOW_H - - -#include "../node.h" -#include "../../../analysis/blocks/flow.h" - - - -/* Redéfinition depuis layout.h pour contourner une boucle. */ -typedef struct _GGraphLayout GGraphLayout; - - - -#define G_TYPE_FLOW_NODE                  (g_flow_node_get_type()) -#define G_FLOW_NODE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_FLOW_NODE, GFlowNode)) -#define G_FLOW_NODE_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_FLOW_NODE, GFlowNodeClass)) -#define G_IS_FLOW_NODE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_FLOW_NODE)) -#define G_IS_FLOW_NODE_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_FLOW_NODE)) -#define G_FLOW_NODE_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_FLOW_NODE, GFlowNodeClass)) - - -/* Type d'un accrochage pour lien */ -typedef struct _node_slot_t node_slot_t; - -/* Encapsulation graphique d'un bloc d'exécution (instance) */ -typedef struct _GFlowNode GFlowNode; - -/* Encapsulation graphique d'un bloc d'exécution (classe) */ -typedef struct _GFlowNodeClass GFlowNodeClass; - - -/* Indique le type définit par la GLib pour l'encapsulation d'un bloc d'exécution. */ -GType g_flow_node_get_type(void); - -/* Encapsule graphiquement un bloc d'exécution. */ -GGraphNode *g_flow_node_new(GFlowBlock *, GtkBufferView *); - -/* Fournit le bloc basique à l'origine du bloc graphique. */ -GFlowBlock *g_flow_node_get_block(const GFlowNode *); - -/* Précise si le noeud a pour première instruction celle donnée. */ -bool g_flow_node_start_with(const GFlowNode *, GArchInstruction *); - -/* Précise si le noeud a pour dernière instruction celle donnée. */ -bool g_flow_node_end_with(const GFlowNode *, GArchInstruction *); - -/* Précise la hauteur minimale requise pour un noeud. */ -void g_flow_node_register_rank(const GFlowNode *, GGraphRanks *); - -/* Définit l'ordonnée de l'espace attribué à un noeud. */ -void g_flow_node_apply_rank(GFlowNode *, GGraphRanks *); - -/* Etablit les liaison entre un noeud et ses suivants. */ -void g_flow_node_link(GFlowNode *, GGraphLayout *, GGraphNode *); - -/* Place un noeud sur son support final. */ -void g_flow_node_place(const GFlowNode *, GtkGraphView *); - - - -/* ------------------------ GESTION DES ACCROCHES D'UN NOEUD ------------------------ */ - - -/* Compare deux accroches pour liens entre noeuds. */ -int g_flow_node_compare_slots_for_edges(const GFlowNode *, const node_slot_t *, gint, const node_slot_t *, gint); - -/* Réorganise au mieux les points d'accroche d'un noeud. */ -void g_flow_node_reorder_slots(const GFlowNode *, GGraphNode *); - -/* Localise un point d'accroche à un noeud graphique. */ -GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *, bool, const node_slot_t *); - - - -#endif  /* _GTKEXT_GRAPH_NODES_FLOW_H */ diff --git a/src/gtkext/graph/nodes/virtual.c b/src/gtkext/graph/nodes/virtual.c deleted file mode 100644 index 62f5b42..0000000 --- a/src/gtkext/graph/nodes/virtual.c +++ /dev/null @@ -1,990 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * virtual.c - encapsulation graphique des blocs virtuels - * - * Copyright (C) 2013 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 "virtual.h" - - -#include <assert.h> -#include <malloc.h> -#include <sys/param.h> - - -#include "flow.h" -#include "../node-int.h" - - - -/* ----------------------- MANIPULATION DES PORTES VERTICALES ----------------------- */ - - -/* Etendue verticale d'un lien */ -typedef struct _reserved_vspan -{ -    unsigned int r1;                        /* Départ d'une ligne          */ -    unsigned int r2;                        /* Arrivée de cette même ligne */ - -} reserved_vspan; - -/* Lignes de liens verticales au sein d'un même groupe */ -typedef struct _vert_links -{ -    reserved_vspan *vspans;                 /* Lignes sans chevauchement   */ -    size_t count;                           /* Nombre de ces lignes        */ - -} vert_links; - - -/* Initialise les futures portées d'un même niveau. */ -static void init_vertical_links(vert_links *); - -/* Regarde si des portées verticales se chevauchent ou non. */ -static bool is_intersection_with_vertical_spans(const vert_links *, const reserved_vspan *); - -/* Ajoute une réservation à un ensemble de portées verticales. */ -static void extend_vertical_links_spans(vert_links *, const reserved_vspan *); - - - -/* ---------------------- REPRESENTATIONS DES GROUPES LOGIQUES ---------------------- */ - - -/* Représentation d'un étage */ -typedef struct _virtual_level -{ -    unsigned int rank;                      /* Rang associé à l'étage      */ - -    GGraphNode **children;                  /* Noeuds englobés             */ -    size_t count;                           /* Quantité de ces noeuds      */ - -} virtual_level; - -/* Encapsulation graphique d'un bloc virtuel (instance) */ -struct _GVirtualNode -{ -    GGraphNode parent;                      /* A laisser en premier        */ - -    GVirtualBlock *block;                   /* Bloc virtuel associé        */ - -    GGraphNode **children;                  /* Noeuds englobés             */ -    size_t count;                           /* Quantité de ces noeuds      */ -    virtual_level *levels;                  /* Différents étages de noeuds */ -    size_t lcount;                          /* Nombre de ces étages        */ - -    vert_links *left_padding;               /* Espace à gauche pour liens  */ -    vspan_slot_t left_count;                /* Nombre de largeurs réservées*/ -    vert_links *right_padding;              /* Espace à droite pour liens  */ -    vspan_slot_t right_count;               /* Nombre de largeurs réservées*/ - -}; - -/* Encapsulation graphique d'un bloc virtuel (classe) */ -struct _GVirtualNodeClass -{ -    GGraphNodeClass parent;                 /* A laisser en premier        */ - -}; - - -/* Initialise la classe des encapsulations de blocs virtuels. */ -static void g_virtual_node_class_init(GVirtualNodeClass *); - -/* Initialise une encapsulation de bloc virtuel. */ -static void g_virtual_node_init(GVirtualNode *); - -/* Supprime toutes les références externes. */ -static void g_virtual_node_dispose(GVirtualNode *); - -/* Procède à la libération totale de la mémoire. */ -static void g_virtual_node_finalize(GVirtualNode *); - -/* Fournit le rang du noeud dans le graphique. */ -static unsigned int g_virtual_node_get_rank(const GVirtualNode *); - -/* Réinitialise la position d'un noeud d'encapsulation. */ -static void g_virtual_node_reset_position(GVirtualNode *); - -/* Définit les abscisses relatives du contenu d'un noeud. */ -static void g_virtual_node_prepare_x_line(GVirtualNode *, GGraphNode *); - -/* Applique une position finale au noeud. */ -static void g_virtual_node_apply_position(GVirtualNode *); - -/* Définit les abscisses relatives du contenu d'un noeud. */ -static void g_virtual_node_apply_x_line(GVirtualNode *); - -/* Met à jour la largeur interne du noeud. */ -static void g_virtual_node_compute_width(GVirtualNode *); - -/* Altère la position du noeud d'encapsulation. */ -static void g_virtual_node_set_position(GVirtualNode *, gint); - -/* Parcourt tous les blocs d'instructions dans un ordre donné. */ -static bool g_virtual_node_visit_flow_nodes(GVirtualNode *, graph_node_visitor_cb, void *); - -/* Recherche le noeud contenant un autre noeud. */ -static GGraphNode *g_virtual_node_find_container(GVirtualNode *, GGraphNode *); - - - -/* ---------------------------------------------------------------------------------- */ -/*                         MANIPULATION DES PORTES VERTICALES                         */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : links = liste à initialiser.                                 * -*                                                                             * -*  Description : Initialise les futures portées d'un même niveau.             * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void init_vertical_links(vert_links *links) -{ -    links->vspans = NULL; -    links->count = 0; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : links = liste de portées déjà en place.                      * -*                vspan = nouvelle portée à insérer quelque part.              * -*                                                                             * -*  Description : Regarde si des portées verticales se chevauchent ou non.     * -*                                                                             * -*  Retour      : true si les portées peuvent cohabiter, false sinon.          * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool is_intersection_with_vertical_spans(const vert_links *links, const reserved_vspan *vspan) -{ -    bool result;                            /* Bilan d'analyse à retourner */ -    size_t i;                               /* Boucle de parcours          */ - -    result = false; - -    for (i = 0; i < links->count && !result; i++) -    { -        if (vspan->r1 < links->vspans[i].r1) -            result = vspan->r2 >= links->vspans[i].r1; - -        else if (vspan->r1 > links->vspans[i].r2) -            result = vspan->r2 <= links->vspans[i].r2; - -        else -        { -            result = links->vspans[i].r1 < vspan->r1 && vspan->r1 < links->vspans[i].r2; -            result |= links->vspans[i].r1 < vspan->r2 && vspan->r2 < links->vspans[i].r2; -        } - -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : spans = liste de portées déjà en place.                      * -*                vspan = nouvelle portée à insérer quelque part.              * -*                                                                             * -*  Description : Ajoute une réservation à un ensemble de portées verticales.  * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void extend_vertical_links_spans(vert_links *links, const reserved_vspan *new) -{ -    links->vspans = (reserved_vspan *)realloc(links->vspans, -                                              ++links->count * sizeof(reserved_vspan)); - -    if (new->r1 <= new->r2) -        links->vspans[links->count - 1] = *new; -    else -    { -        links->vspans[links->count - 1].r1 = new->r2; -        links->vspans[links->count - 1].r2 = new->r1; -    } - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                        REPRESENTATIONS DES GROUPES LOGIQUES                        */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type définit par la GLib pour l'encapsulation d'un bloc virtuel. */ -G_DEFINE_TYPE(GVirtualNode, g_virtual_node, G_TYPE_GRAPH_NODE); - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : klass = classe à initialiser.                                * -*                                                                             * -*  Description : Initialise la classe des encapsulations de blocs virtuels.   * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_class_init(GVirtualNodeClass *klass) -{ -    GObjectClass *object;                   /* Autre version de la classe  */ -    GGraphNodeClass *node_class;            /* Version parente de la classe*/ - -    object = G_OBJECT_CLASS(klass); -    node_class = G_GRAPH_NODE_CLASS(klass); - -    object->dispose = (GObjectFinalizeFunc/* ! */)g_virtual_node_dispose; -    object->finalize = (GObjectFinalizeFunc)g_virtual_node_finalize; - -    node_class->get_rank = (get_node_rank_fc)g_virtual_node_get_rank; -    node_class->reset_pos = (node_reset_pos_fc)g_virtual_node_reset_position; -    node_class->prepare_x = (node_prepare_x_fc)g_virtual_node_prepare_x_line; -    node_class->apply_pos = (node_apply_pos_fc)g_virtual_node_apply_position; -    node_class->set_pos = (node_set_pos_fc)g_virtual_node_set_position; -    node_class->visit = (visit_flow_nodes_fc)g_virtual_node_visit_flow_nodes; -    node_class->contain = (find_container_fc)g_virtual_node_find_container; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance à initialiser.                               * -*                                                                             * -*  Description : Initialise une encapsulation de bloc virtuel.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_init(GVirtualNode *node) -{ - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance d'objet GLib à traiter.                      * -*                                                                             * -*  Description : Supprime toutes les références externes.                     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_dispose(GVirtualNode *node) -{ -    size_t i;                               /* Boucle de parcours          */ - -    g_object_unref(G_OBJECT(node->block)); - -    for (i = 0; i < node->count; i++) -        g_object_unref(G_OBJECT(node->children[i])); - -    if (node->children != NULL) -        free(node->children); - -    G_OBJECT_CLASS(g_virtual_node_parent_class)->dispose(G_OBJECT(node)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance d'objet GLib à traiter.                      * -*                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_finalize(GVirtualNode *node) -{ -    G_OBJECT_CLASS(g_virtual_node_parent_class)->finalize(G_OBJECT(node)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : block = bloc virtuel représenté graphiquement.               * -*                                                                             * -*  Description : Encapsule graphiquement un bloc virtuel.                     * -*                                                                             * -*  Retour      : Adresse de la structure mise en place.                       * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GGraphNode *g_virtual_node_new(GVirtualBlock *block) -{ -    GVirtualNode *result;                   /* Structure à retourner       */ - -    result = g_object_new(G_TYPE_VIRTUAL_NODE, NULL); - -    g_object_ref(G_OBJECT(block)); - -    result->block = block; - -    return G_GRAPH_NODE(result); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à consulter.                          * -*                                                                             * -*  Description : Fournit le rang du noeud dans le graphique.                  * -*                                                                             * -*  Retour      : Indice supérieur ou égal à zéro.                             * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static unsigned int g_virtual_node_get_rank(const GVirtualNode *node) -{ -    /* BUG_ON(node->count == 0) */ - -    return g_graph_node_get_rank(node->children[0]); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à manipuler.                          * -*                                                                             * -*  Description : Réinitialise la position d'un noeud d'encapsulation.         * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_reset_position(GVirtualNode *node) -{ -    size_t i;                               /* Boucle de parcours          */ - -    for (i = 0; i < node->count; i++) -        g_graph_node_reset_position(node->children[i]); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud d'encapsulation à traiter.                     * -*                nodes = ensemble des noeuds en place.                        * -*                                                                             * -*  Description : Définit les abscisses relatives du contenu d'un noeud.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_prepare_x_line(GVirtualNode *node, GGraphNode *nodes) -{ -    size_t i;                               /* Boucle de parcours          */ - -    for (i = 0; i < node->count; i++) -        g_graph_node_prepare_x_line(node->children[i], nodes); - -} - - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud d'encapsulation à traiter.                     * -*                                                                             * -*  Description : Applique une position finale au noeud.                       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_apply_position(GVirtualNode *node) -{ -    gint min;                               /* Valeur minimale rencontrée  */ -    size_t i;                               /* Boucle de parcours          */ -    gint x_pos;                             /* Nouvelle position #1        */ -    gint offset;                            /* Décallage à faire suivre    */ - -    g_virtual_node_apply_x_line(node); - -    /* Collecte de l'ensemble des positions */ - -    min = 0; - -    for (i = 0; i < node->count; i++) -    { -        g_graph_node_get_position(node->children[i], &x_pos, NULL); -        min = MIN(min, x_pos); -    } - -    /* Espace pour les liens remontants */ - -    if (node->left_count > 0) -        offset = EDGE_SLOT_HORIZ_MARGIN + EDGE_HORIZONTAL_MIN_SEP * (node->left_count - 1); -    else -        offset = 0; - -    /* Ajout du décallage le plus grand */ - -    offset += -min; - -    /* Traitement des sous-noeuds */ - -    for (i = 0; i < node->count; i++) -    { -        /* BUG_ON(node->children[i]->alloc.x != UNINITIALIZED_NODE_POS); */ - -        g_graph_node_get_position(node->children[i], &x_pos, NULL); - -        printf(" == vapply ==  %p : %d + %d -> %d\n", -               node->children[i], x_pos, offset, (int)(x_pos + offset)); - -        x_pos += offset; - -        g_graph_node_set_x_position(node->children[i], x_pos); - -    } - -    g_virtual_node_compute_width(node); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud d'encapsulation à traiter.                      * -*                                                                             * -*  Description : Définit les abscisses relatives du contenu d'un noeud.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_apply_x_line(GVirtualNode *node) -{ -    size_t i;                               /* Boucle de parcours #1       */ -    virtual_level *level;                   /* Accès rapide                */ -    size_t j;                               /* Boucle de parcours #2       */ -    gint width_sum;                         /* Largeur d'un étage traité   */ -    gint x_pos;                             /* Abscisse à attribuer        */ -    GGraphNode *ref_a;                      /* Accès rapide #1             */ -    GGraphNode *ref_b;                      /* Accès rapide #2             */ - -    for (i = 0; i < node->lcount; i++) -    { -        level = &node->levels[i]; - -        /* Si l'ensemble de l'étage doit être centré */ -        if (level->children[0]->pending_flag == PPF_NONE) -        { -            width_sum = 0; - -            for (j = 0; j < level->count; j++) -            { -                assert(level->children[j]->pending_flag == PPF_NONE); - -                g_graph_node_apply_position(level->children[j]); -                width_sum += level->children[j]->alloc.width; - -            } - -            width_sum += NODE_HORIZONTAL_MARGIN * (level->count - 1); - -            x_pos = - width_sum / 2; - -            for (j = 0; j < level->count; j++) -            { -                g_graph_node_set_x_position(level->children[j], x_pos); -                x_pos += level->children[j]->alloc.width + NODE_HORIZONTAL_MARGIN; -            } - -        } - -        else if (level->children[0]->pending_flag == PPF_MIDDLE_OF) -            continue; - -        /* On traite les noeuds individuellement */ -        else -        { -            void _apply_rel_position(GGraphNode *child) -            { -                switch (node->children[0]->pending_flag) -                { -                    case PPF_LEFT_NODE: -                        if (!g_graph_node_has_x_position(child->pending_pos.left_node)) -                            _apply_rel_position(child->pending_pos.left_node); -                        break; - -                    case PPF_RIGHT_NODE: -                        if (!g_graph_node_has_x_position(child->pending_pos.right_node)) -                            _apply_rel_position(child->pending_pos.right_node); -                        break; - -                    default: -                        break; - -                } - -                g_graph_node_apply_position(child); - -            } - -            for (j = 0; j < level->count; j++) -                if (!g_graph_node_has_x_position(level->children[j])) -                    _apply_rel_position(level->children[j]); - -        } - -    } - -    for (i = 0; i < node->lcount; i++) -    { -        level = &node->levels[i]; - -        /* Si l'ensemble de l'étage doit être centré */ -        if (level->children[0]->pending_flag == PPF_MIDDLE_OF) -        { -            ref_a = level->children[0]->pending_pos.left_node; -            ref_b = level->children[0]->pending_pos.right_node; - -            assert(g_graph_node_has_x_position(ref_a)); -            assert(g_graph_node_has_x_position(ref_b)); - -            if (ref_a->alloc.x < ref_b->alloc.x) -            { -                ref_b = level->children[0]->pending_pos.left_node; -                ref_a = level->children[0]->pending_pos.right_node; -            } - -            x_pos = ref_a->alloc.x; -            x_pos += (ref_b->alloc.x + ref_b->alloc.width - ref_a->alloc.x) / 2; -            x_pos -= level->children[0]->alloc.width / 2; - -            g_graph_node_set_x_position(level->children[0], x_pos); - -        } - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à mettre à jour.                      * -*                                                                             * -*  Description : Met à jour la largeur interne du noeud.                      * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_compute_width(GVirtualNode *node) -{ -    GGraphNode *base;                       /* Accès rapides               */ -    size_t i;                               /* Boucle de parcours          */ -    GGraphNode *child;                      /* Raccourci confortable       */ - -    base = G_GRAPH_NODE(node); - -    /* Largeur maximale des niveaux */ - -    base->alloc.width = 0; - -    for (i = 0; i < node->lcount; i++) -    { -        child = node->levels[i].children[node->levels[i].count - 1]; - -        base->alloc.width = MAX(base->alloc.width, child->alloc.x + child->alloc.width); - -    } - -    /* Bordures gauche et droite   */ - -    if (node->left_count > 0) -    { -        base->alloc.width += EDGE_SLOT_HORIZ_MARGIN; -        base->alloc.width += (node->left_count - 1) * EDGE_HORIZONTAL_MIN_SEP; -    } - -    if (node->right_count > 0) -    { -        base->alloc.width += EDGE_SLOT_HORIZ_MARGIN; -        base->alloc.width += (node->right_count - 1) * EDGE_HORIZONTAL_MIN_SEP; -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = noeud graphique à manipuler.                          * -*                x    = éventuelle abscisse à intégrer.                       * -*                                                                             * -*  Description : Altère la position du noeud d'encapsulation.                 * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_virtual_node_set_position(GVirtualNode *node, gint x) -{ -    GGraphNode *base;                       /* Autre version de l'instance */ -    gint offset;                            /* Décallage à faire suivre    */ -    size_t i;                               /* Boucle de parcours          */ -    gint x_pos;                             /* Nouvelle position #1        */ - -    base = G_GRAPH_NODE(node); - -    if (base->alloc.x == UNINITIALIZED_NODE_POS) -        offset = x; -    else -        offset = x - base->alloc.x; - -    for (i = 0; i < node->count; i++) -    { -        /* BUG_ON(node->children[i]->alloc.x != UNINITIALIZED_NODE_POS); */ - -        g_graph_node_get_position(node->children[i], &x_pos, NULL); -        x_pos += offset; - -        g_graph_node_set_x_position(node->children[i], x_pos); - -    } - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node     = noeud graphique démarrant la visite.              * -*                callback = ensemble de blocs à parcourir.                    * -*                data     = donnée utilisateur à associer au parcours.        * -*                                                                             * -*  Description : Parcourt tous les blocs d'instructions dans un ordre donné.  * -*                                                                             * -*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_virtual_node_visit_flow_nodes(GVirtualNode *node, graph_node_visitor_cb callback, void *data) -{ -    bool result;                            /* Bilan à retourner           */ -    size_t i;                               /* Boucle de parcours          */ - -    result = callback(G_GRAPH_NODE(node), GVS_ENTER, data); - -    for (i = 0; i < node->count && result; i++) -        result = g_graph_node_visit_nodes(node->children[i], callback, data); - -    if (result) -        result = callback(G_GRAPH_NODE(node), GVS_EXIT, data); - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : nodes  = noeud à consulter.                                  * -*                target = élément à retrouver dans l'ensemble de noeuds.      * -*                                                                             * -*  Description : Recherche le noeud contenant un autre noeud.                 * -*                                                                             * -*  Retour      : Noeud trouvé ou NULL si aucun.                               * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static GGraphNode *g_virtual_node_find_container(GVirtualNode *node, GGraphNode *target) -{ -    GGraphNode *result;                     /* Trouvaille à retourner      */ -    size_t i;                               /* Boucle de parcours          */ - -    result = NULL; - -    for (i = 0; i < node->count && result == NULL; i++) -    { -        if (node->children[i] == target) -            result = G_GRAPH_NODE(node); -        else -            result = g_graph_node_find_container(node->children[i], target); -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud d'encapsulation à compléter.                   * -*                child = sous-noeud à insérer.                                * -*                                                                             * -*  Description : Ajoute un noeud au groupe courant.                           * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_virtual_node_add_child(GVirtualNode *node, GGraphNode *child) -{ -    unsigned int rank;                      /* Rang de l'enfant            */ -    virtual_level *level;                   /* Niveau d'intégration        */ -    size_t i;                               /* Boucle de parcours          */ - -    /* Liste globale */ - -    node->children = (GGraphNode **)realloc(node->children, -                                              ++node->count * sizeof(GGraphNode *)); - -    node->children[node->count - 1] = child; - -    g_object_ref(G_OBJECT(child)); - -    /* Intégration dans l'étage correspondant */ - -    rank = g_graph_node_get_rank(child); - -    level = NULL; - -    for (i = 0; i < node->lcount && level == NULL; i++) -        if (node->levels[i].rank == rank) -            level = &node->levels[i]; - -    if (level == NULL) -    { -        node->levels = (virtual_level *)realloc(node->levels, -                                                ++node->lcount * sizeof(virtual_level)); -        level = &node->levels[node->lcount - 1]; - -        level->rank = rank; -        level->children = NULL; -        level->count = 0; - -    } - -    level->children = (GGraphNode **)realloc(level->children, -                                             ++level->count * sizeof(GGraphNode *)); - -    level->children[level->count - 1] = child; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud d'encapsulation à consulter.                   * -*                                                                             * -*  Description : Compte le nombre de noeuds contenus dans le groupe courant.  * -*                                                                             * -*  Retour      : Quantité normalement non nulle.                              * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -size_t g_virtual_node_count_children(const GVirtualNode *node) -{ -    return node->count; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node  = noeud d'encapsulation à consulter.                   * -*                index = indice du sous-bloc recherché.                       * -*                                                                             * -*  Description : Renvoie un des noeuds contenus dans le groupe courant.       * -*                                                                             * -*  Retour      : Un des blocs du groupe.                                      * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GGraphNode *g_virtual_node_get_child(const GVirtualNode *node, size_t index) -{ -    if (index >= node->count) -        return NULL; - -    else -        return node->children[index]; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = groupe de noeuds à mettre à jour.                     * -*                r1   = début de la portée à réserver.                        * -*                r2   = fin de la portée à réserver.                          * -*                left = désignation de la zone à traiter.                     * -*                                                                             * -*  Description : Réserve une portion de largeur pour un lien.                 * -*                                                                             * -*  Retour      : Indice de la largeur adaptée et réservée.                    * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -vspan_slot_t g_virtual_node_reserve_span(GVirtualNode *node, unsigned int r1, unsigned int r2, bool left) -{ -    vspan_slot_t result;                    /* Identifiant à retourner     */ -    reserved_vspan vspan;                   /* Portée à constituer         */ -    vert_links **list;                      /* Liste à parcourir           */ -    vspan_slot_t *count;                    /* Taille de cette liste       */ - -    vspan.r1 = r1; -    vspan.r2 = r2; - -    if (left) -    { -        list = &node->left_padding; -        count = &node->left_count; -    } -    else -    { -        list = &node->right_padding; -        count = &node->right_count; -    } - -    for (result = 0; result < *count; result++) -        if (!is_intersection_with_vertical_spans(&(*list)[result], &vspan)) -            break; - -    if (result == *count) -    { -        *list = (vert_links *)realloc(*list, ++(*count) * sizeof(vert_links)); -        init_vertical_links(&(*list)[result]); -    } - -    extend_vertical_links_spans(&(*list)[result], &vspan); - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = conteneur de noeuds à consulter.                      * -*                slot = numérod de la réservation.                            * -*                left = désignation de la zone à traiter.                     * -*                                                                             * -*  Description : Fournit la position horizontale obtenue par réservation.     * -*                                                                             * -*  Retour      : Abscisse à utiliser.                                         * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -gint g_virtual_node_get_x_for_vspan_slot(const GVirtualNode *node, vspan_slot_t slot, bool left) -{ -    gint result;                            /* Position à retourner        */ -    GtkAllocation alloc;                    /* Taille totale requise       */ - -    alloc = G_GRAPH_NODE(node)->alloc; - -    if (left) -    { -        /*BUG_ON(slot >= node->left_count) */ - -        result = -(node->left_count - 1) * EDGE_HORIZONTAL_MIN_SEP/* + EDGE_SLOT_HORIZ_MARGIN*/; -        result += (slot * EDGE_HORIZONTAL_MIN_SEP/* + EDGE_SLOT_HORIZ_MARGIN*/); - -        result += alloc.x; - -    } -    else -    { -        /*BUG_ON(slot >= node->right_count) */ - -        result = /*EDGE_SLOT_HORIZ_MARGIN + */slot * EDGE_HORIZONTAL_MIN_SEP; - -        result += alloc.x + alloc.width/* - EDGE_SLOT_HORIZ_MARGIN*/; -        if (node->right_count > 0) -            result -= (node->right_count - 1) * EDGE_HORIZONTAL_MIN_SEP; - -        /* On pense à la largeur du trait... */ -        result -= 2; - -    } - -    return result; - -} diff --git a/src/gtkext/graph/nodes/virtual.h b/src/gtkext/graph/nodes/virtual.h deleted file mode 100644 index 7f32591..0000000 --- a/src/gtkext/graph/nodes/virtual.h +++ /dev/null @@ -1,77 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * virtual.h - prototypes pour l'encapsulation graphique des blocs virtuels - * - * Copyright (C) 2013 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  OpenIDA is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 3 of the License, or - *  (at your option) any later version. - * - *  OpenIDA is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _GTKEXT_GRAPH_NODES_VIRTUAL_H -#define _GTKEXT_GRAPH_NODES_VIRTUAL_H - - -#include "../node.h" -#include "../../../analysis/blocks/virtual.h" - - -/* Indice d'une hauteur au sein des rangs */ -typedef size_t vspan_slot_t; - -/* Indice non initilisé */ -#define UNINITIALIZED_VSPAN_SLOT (~((vspan_slot_t)0)) - - -#define G_TYPE_VIRTUAL_NODE                  (g_virtual_node_get_type()) -#define G_VIRTUAL_NODE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_VIRTUAL_NODE, GVirtualNode)) -#define G_VIRTUAL_NODE_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_VIRTUAL_NODE, GVirtualNodeClass)) -#define G_IS_VIRTUAL_NODE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_VIRTUAL_NODE)) -#define G_IS_VIRTUAL_NODE_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_VIRTUAL_NODE)) -#define G_VIRTUAL_NODE_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_VIRTUAL_NODE, GVirtualNodeClass)) - - -/* Encapsulation graphique d'un bloc virtuel (instance) */ -typedef struct _GVirtualNode GVirtualNode; - -/* Encapsulation graphique d'un bloc virtuel (classe) */ -typedef struct _GVirtualNodeClass GVirtualNodeClass; - - -/* Indique le type définit par la GLib pour l'encapsulation d'un bloc virtuel. */ -GType g_virtual_node_get_type(void); - -/* Encapsule graphiquement un bloc virtuel. */ -GGraphNode *g_virtual_node_new(GVirtualBlock *); - -/* Ajoute un noeud au groupe courant. */ -void g_virtual_node_add_child(GVirtualNode *, GGraphNode *); - -/* Compte le nombre de noeuds contenus dans le groupe courant. */ -size_t g_virtual_node_count_children(const GVirtualNode *); - -/* Renvoie un des noeuds contenus dans le groupe courant. */ -GGraphNode *g_virtual_node_get_child(const GVirtualNode *, size_t); - -/* Réserve une portion de largeur pour un lien. */ -vspan_slot_t g_virtual_node_reserve_span(GVirtualNode *, unsigned int, unsigned int, bool); - -/* Fournit la position horizontale obtenue par réservation. */ -gint g_virtual_node_get_x_for_vspan_slot(const GVirtualNode *, vspan_slot_t, bool); - - - -#endif  /* _GTKEXT_GRAPH_NODES_VIRTUAL_H */ diff --git a/src/gtkext/graph/params.h b/src/gtkext/graph/params.h deleted file mode 100644 index 9d26426..0000000 --- a/src/gtkext/graph/params.h +++ /dev/null @@ -1,84 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * params.h - prototypes pour la modulation des paramètres de rendu - * - * Copyright (C) 2013 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  OpenIDA is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 3 of the License, or - *  (at your option) any later version. - * - *  OpenIDA is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _GTKEXT_GRAPH_PARAMS_H -#define _GTKEXT_GRAPH_PARAMS_H - - - - -/* Coordonnés d'un noeud non initialisées */ -#define UNINITIALIZED_NODE_POS G_MININT - - -/** - * Paramètres à l'échelle du graphique. - */ - -/* Bordures supérieure et inférieure des graphiques */ -#define GRAPH_VERTICAL_MARGIN 15 - -/* Bordures gauche et droite des graphiques */ -#define GRAPH_HORIZONTAL_MARGIN 15 - - -/** - * Paramètres à l'échelle du noeud. - */ - - - - - -#define NODE_LEFT_MARGIN 25 -#define NODE_TOP_MARGIN 55      /* TODO : supprimer */ - - - - - - -/* Séparations minimales entre deux liens */ -#define EDGE_HORIZONTAL_MIN_SEP 10 -#define EDGE_VERTICAL_MIN_SEP 10 - -/* Séparations minimales entre un lien et un noeud */ -#define EDGE_SLOT_HORIZ_MARGIN 20 -#define EDGE_SLOT_VERT_MARGIN 20 - -/* Séparations minimales entre un noeud et un autre */ -#define NODE_HORIZONTAL_MARGIN 20 -#define NODE_VERTICAL_MARGIN 35 - - - - -#define SLOT_VERT_SEP EDGE_SLOT_VERT_MARGIN   /* TODO : remplacer */ - -#define ARROW_LENGHT 10 -#define ARROW_DEGREES 10 - - - - -#endif  /* _GTKEXT_GRAPH_PARAMS_H */ diff --git a/src/gtkext/graph/ranks.c b/src/gtkext/graph/ranks.c deleted file mode 100644 index e1f6688..0000000 --- a/src/gtkext/graph/ranks.c +++ /dev/null @@ -1,695 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * ranks.c - calcul de l'ordonnée des différents classements - * - * Copyright (C) 2013 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 "ranks.h" - - -#include <malloc.h> -#include <sys/param.h> - - -#include "params.h" - - - -/* ---------------------- MANIPULATION DES PORTES HORIZONTALES ---------------------- */ - - -/* Etendue horizontale d'un lien */ -typedef struct _reserved_hspan -{ -    gint x1;                                /* Départ d'une ligne          */ -    gint x2;                                /* Arrivée de cette même ligne */ - -} reserved_hspan; - -/* Lignes de liens d'un même niveau */ -typedef struct _links_spans -{ -    reserved_hspan *hspans;                 /* Lignes sans chevauchement   */ -    size_t count;                           /* Nombre de ces lignes        */ - -} links_spans; - - -/* Initialise les futures portées d'un même niveau. */ -static void init_links_spans(links_spans *); - -/* Regarde si des portées horizontales se chevauchent ou non. */ -static bool is_intersection_with_spans(const links_spans *, const reserved_hspan *); - -/* Ajoute une réservation à un ensemble de portées horizontales. */ -static void extend_links_spans(links_spans *, const reserved_hspan *); - - - -/* ------------------------ GESTION D'UN ETAGE DE CLASSEMENT ------------------------ */ - - -/* Information relatives à un rang de classement */ -typedef struct _rank_props -{ -    links_spans *top_spans;                 /* Niveaux de lignes supérieurs*/ -    hspan_slot_t top_count;                 /* Nbre des niveaux de lignes  */ -    links_spans *bottom_spans;              /* Niveaux de lignes inférieurs*/ -    hspan_slot_t bottom_count;              /* Nbre des niveaux de lignes  */ - -    gint height;                            /* Hauteur minimale            */ -    gint y;                                 /* Ordonnée finale             */ - -} rank_props; - - -/* Réserve une portion de hauteur pour un lien. */ -static hspan_slot_t reserve_span_in_rank_props(rank_props *, gint, gint, bool); - -/*  Calcule la position verticale du rang de classement. */ -static gint compute_rank_props_y_pos(rank_props *, gint *, gint); - -/* Fournit la position verticale obtenue par réservation. */ -static gint get_y_for_rank_props_hspan_slot(const rank_props *, hspan_slot_t, bool); - - - -/* ------------------------- CLASSEMENT VERTICAL DES NOEUDS ------------------------- */ - - -/* Calcul de l'ordonnée des différents classements (instance) */ -struct _GGraphRanks -{ -    GObject parent;                         /* A laisser en premier        */ - -    rank_props *props;                      /* Propriétés des rangs        */ -    unsigned int count;                     /* Nombre de rangs présents    */ - -    gint height;                            /* Hauteur totale du graphique */ - -}; - -/* Calcul de l'ordonnée des différents classements (classe) */ -struct _GGraphRanksClass -{ -    GObjectClass parent;                    /* A laisser en premier        */ - -}; - - -/* Initialise la classe de calcul de l'ordonnée des classements. */ -static void g_graph_ranks_class_init(GGraphRanksClass *); - -/* Initialise un calcul de l'ordonnée des classements. */ -static void g_graph_ranks_init(GGraphRanks *); - -/* Supprime toutes les références externes. */ -static void g_graph_ranks_dispose(GGraphRanks *); - -/* Procède à la libération totale de la mémoire. */ -static void g_graph_ranks_finalize(GGraphRanks *); - - - -/* ---------------------------------------------------------------------------------- */ -/*                        MANIPULATION DES PORTES HORIZONTALES                        */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : spans = liste à initialiser.                                 * -*                                                                             * -*  Description : Initialise les futures portées d'un même niveau.             * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void init_links_spans(links_spans *spans) -{ -    spans->hspans = NULL; -    spans->count = 0; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : spans = liste de portées déjà en place.                      * -*                hspan = nouvelle portée à insérer quelque part.              * -*                                                                             * -*  Description : Regarde si des portées horizontales se chevauchent ou non.   * -*                                                                             * -*  Retour      : true si les portées peuvent cohabiter, false sinon.          * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool is_intersection_with_spans(const links_spans *spans, const reserved_hspan *hspan) -{ -    bool result;                            /* Bilan d'analyse à retourner */ -    size_t i;                               /* Boucle de parcours          */ - -    result = false; - -    for (i = 0; i < spans->count && !result; i++) -    { -        if (hspan->x1 < spans->hspans[i].x1) -            result = hspan->x2 >= spans->hspans[i].x1; - -        else if (hspan->x1 > spans->hspans[i].x2) -            result = hspan->x2 <= spans->hspans[i].x2; - -        else -        { -            result = spans->hspans[i].x1 < hspan->x1 && hspan->x1 < spans->hspans[i].x2; -            result |= spans->hspans[i].x1 < hspan->x2 && hspan->x2 < spans->hspans[i].x2; -        } - -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : spans = liste de portées déjà en place.                      * -*                hspan = nouvelle portée à insérer quelque part.              * -*                                                                             * -*  Description : Ajoute une réservation à un ensemble de portées horizontales.* -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void extend_links_spans(links_spans *spans, const reserved_hspan *new) -{ -    spans->hspans = (reserved_hspan *)realloc(spans->hspans, -                                              ++spans->count * sizeof(reserved_hspan)); - -    if (new->x1 <= new->x2) -        spans->hspans[spans->count - 1] = *new; -    else -    { -        spans->hspans[spans->count - 1].x1 = new->x2; -        spans->hspans[spans->count - 1].x2 = new->x1; -    } - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                          GESTION D'UN ETAGE DE CLASSEMENT                          */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : props = propriétés de rang à mettre à jour.                  * -*                                                                             * -*  Description : Supprime les portions de hauteur pour un lien.               * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void reset_spans_in_rank_props(rank_props *props) -{ -    hspan_slot_t i;                         /* Boucle de parcours          */ - -    for (i = 0; i < props->top_count; i++) -        if (props->top_spans[i].hspans != NULL) -            free(props->top_spans[i].hspans); - -    if (props->top_spans != NULL) -    { -        free(props->top_spans); -        props->top_spans = NULL; -        props->top_count = 0; -    } - -    for (i = 0; i < props->bottom_count; i++) -        if (props->bottom_spans[i].hspans != NULL) -            free(props->bottom_spans[i].hspans); - -    if (props->bottom_spans != NULL) -    { -        free(props->bottom_spans); -        props->bottom_spans = NULL; -        props->bottom_count = 0; -    } - -    props->y = 0; -    props->height = 0; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : props = propriétés de rang à mettre à jour.                  * -*                x1    = début de la portée à réserver.                       * -*                x2    = fin de la portée à réserver.                         * -*                top   = désignation de la zone à traiter.                    * -*                                                                             * -*  Description : Réserve une portion de hauteur pour un lien.                 * -*                                                                             * -*  Retour      : Indice de la hauteur adaptée et réservée.                    * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static hspan_slot_t reserve_span_in_rank_props(rank_props *props, gint x1, gint x2, bool top) -{ -    hspan_slot_t result;                    /* Indice à retourner          */ -    reserved_hspan hspan;                   /* Portée à constituer         */ -    links_spans **list;                     /* Liste à parcourir           */ -    hspan_slot_t *count;                    /* Taille de cette liste       */ - -    hspan.x1 = x1; -    hspan.x2 = x2; - -    if (top) -    { -        list = &props->top_spans; -        count = &props->top_count; -    } -    else -    { -        list = &props->bottom_spans; -        count = &props->bottom_count; -    } - -    for (result = 0; result < *count; result++) -        if (!is_intersection_with_spans(&(*list)[result], &hspan)) -            break; - -    if (result == *count) -    { -        *list = (links_spans *)realloc(*list, ++(*count) * sizeof(links_spans)); -        init_links_spans(&(*list)[result]); -    } - -    extend_links_spans(&(*list)[result], &hspan); - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : props       = propriétés de rang à mettre à jour.            * -*                y           = ordonnée courante à faire évoluer.             * -*                last_bottom = espace inférieur requis du niveau précédent.   * -*                                                                             * -*  Description : Calcule la position verticale du rang de classement.         * -*                                                                             * -*  Retour      : Espace inférieur nécessaire au niveau de classement.         * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static gint compute_rank_props_y_pos(rank_props *props, gint *y, gint last_bottom) -{ -    gint result;                            /* Espace Sud à retourner      */ -    gint top_margin;                        /* Espace Nord nécessaire      */ - -    /* Espace supérieur pour les liens */ - -    top_margin = last_bottom; - -    if (props->top_count > 0) -    { -        top_margin += props->top_count * EDGE_VERTICAL_MIN_SEP; -        top_margin += EDGE_SLOT_VERT_MARGIN; -    } - -    /** -     * L'espace vertical entre les noeuds n'a lieu d'être qu'en présence de noeuds ! -     */ -    top_margin = MAX(top_margin, (*y > 0 && props->height > 0 ? NODE_VERTICAL_MARGIN : 0)); - -    /* Position des noeuds */ - -    props->y = *y + top_margin; -    *y = props->y + props->height; - -    /* Espace inférieur pour les liens */ - -    /** -     * Fournit une marge minimum : si des liens autres que boucles partent de ce rang, -     * il ne sont pas enregistrés à ce niveau, mais ont besoin d'espace quand même. -     * On prend néanmoins garde aux rangs terminaux, potentiellement vides. -     */ -    result = (props->height > 0 ? EDGE_SLOT_VERT_MARGIN : 0); - -    if (props->bottom_count > 0) -        result += props->bottom_count * EDGE_VERTICAL_MIN_SEP; - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : props = propriétés de rang à consulter.                      * -*                slot  = numérod de la réservation.                           * -*                top   = désignation de la zone à traiter.                    * -*                                                                             * -*  Description : Fournit la position verticale obtenue par réservation.       * -*                                                                             * -*  Retour      : Ordonnée à utiliser.                                         * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static gint get_y_for_rank_props_hspan_slot(const rank_props *props, hspan_slot_t slot, bool top) -{ -    gint result;                            /* Ordonnée à retourner        */ - -    result = EDGE_SLOT_VERT_MARGIN + slot * EDGE_VERTICAL_MIN_SEP; - -    if (top) -        result = props->y - result; -    else -        result += props->y + props->height; - -    return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                           CLASSEMENT VERTICAL DES NOEUDS                           */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type définit par la GLib pour le calcul de l'ordonnée des classements. */ -G_DEFINE_TYPE(GGraphRanks, g_graph_ranks, G_TYPE_OBJECT); - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : klass = classe à initialiser.                                * -*                                                                             * -*  Description : Initialise la classe de calcul de l'ordonnée des classements.* -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_ranks_class_init(GGraphRanksClass *klass) -{ -    GObjectClass *object;                   /* Autre version de la classe  */ - -    object = G_OBJECT_CLASS(klass); - -    object->dispose = (GObjectFinalizeFunc/* ! */)g_graph_ranks_dispose; -    object->finalize = (GObjectFinalizeFunc)g_graph_ranks_finalize; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks = instance à initialiser.                              * -*                                                                             * -*  Description : Initialise un calcul de l'ordonnée des classements.          * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_ranks_init(GGraphRanks *ranks) -{ - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : node = instance d'objet GLib à traiter.                      * -*                                                                             * -*  Description : Supprime toutes les références externes.                     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_ranks_dispose(GGraphRanks *ranks) -{ -    G_OBJECT_CLASS(g_graph_ranks_parent_class)->dispose(G_OBJECT(ranks)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks = instance d'objet GLib à traiter.                     * -*                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_graph_ranks_finalize(GGraphRanks *ranks) -{ -    if (ranks->props != NULL) -        free(ranks->props); - -    G_OBJECT_CLASS(g_graph_ranks_parent_class)->finalize(G_OBJECT(ranks)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : count = nombre de rangs dans le classement au total.         * -*                                                                             * -*  Description : Prépare de quoi se définir au mieux les ordonnées des noeuds.* -*                                                                             * -*  Retour      : Adresse de la structure mise en place.                       * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -GGraphRanks *g_graph_ranks_new(unsigned int count) -{ -    GGraphRanks *result;                    /* Structure à retourner       */ - -    result = g_object_new(G_TYPE_GRAPH_RANKS, NULL); - -    result->count = count; -    result->props = (rank_props *)calloc(count, sizeof(rank_props)); - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks  = ensemble des rangs de classement à manipuler.       * -*                index  = indice du rang visé.                                * -*                height = hauteur minimale requise pour le rang donné.        * -*                                                                             * -*  Description : Note une hauteur minimale requise pour un rang du classement.* -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_ranks_set_min_height(GGraphRanks *ranks, unsigned int index, gint height) -{ -    /*BUG_ON(index >= ranks->count) */ - -    ranks->props[index].height = MAX(ranks->props[index].height, height); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks = ensemble des rangs de classement à consulter.        * -*                                                                             * -*  Description : Fournit la hauteur requise pour l'affichage des rangs.       * -*                                                                             * -*  Retour      : Hauteur nécessaire en pixel.                                 * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -gint g_graph_ranks_get_height(const GGraphRanks *ranks) -{ -    return ranks->height; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks = ensemble des rangs à mettre à jour.                  * -*                                                                             * -*  Description : Supprime toutes les réservations faites pour les liens.      * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_ranks_reset_reservations(GGraphRanks *ranks) -{ -    unsigned int i;                         /* Boucle de parcours          */ - -    for (i = 0; i < ranks->count; i++) -        reset_spans_in_rank_props(&ranks->props[i]); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks = ensemble des rangs à mettre à jour.                  * -*                index = indice du rang visé.                                 * -*                x1    = début de la portée à réserver.                       * -*                x2    = fin de la portée à réserver.                         * -*                top   = désignation de la zone à traiter.                    * -*                                                                             * -*  Description : Réserve une portion de hauteur pour un lien.                 * -*                                                                             * -*  Retour      : Indice de la hauteur adaptée et réservée.                    * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -hspan_slot_t g_graph_ranks_reserve_span(GGraphRanks *ranks, unsigned int index, gint x1, gint x2, bool top) -{ -    /*BUG_ON(index >= ranks->count) */ - -    return reserve_span_in_rank_props(&ranks->props[index], x1, x2, top); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks = ensemble des rangs de classement à manipuler.        * -*                                                                             * -*  Description : Calcule l'ordonnée finale de chaque rang du classement.      * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void g_graph_ranks_compute_y_line(GGraphRanks *ranks) -{ -    gint last_bottom;                       /* Espace minimal à transmettre*/ -    gint y;                                 /* Ordonnée courante à proposer*/ -    size_t i;                               /* Boucle de parcours          */ - -    last_bottom = GRAPH_VERTICAL_MARGIN; -    y = 0; - -    for (i = 0; i < ranks->count; i++) -        last_bottom = compute_rank_props_y_pos(&ranks->props[i], &y, last_bottom); - -    ranks->height = y + last_bottom + GRAPH_VERTICAL_MARGIN; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks  = ensemble des rangs de classement à consulter.       * -*                index  = indice du rang visé.                                * -*                                                                             * -*  Description : Fournit la position verticale correspondant à un rang donné. * -*                                                                             * -*  Retour      : Ordonnée à utiliser.                                         * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -gint g_graph_ranks_get_y_for_rank(const GGraphRanks *ranks, unsigned int index) -{ -    /*BUG_ON(index >= ranks->count) */ - -    return ranks->props[index].y; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : ranks = ensemble des rangs de classement à consulter.        * -*                index = indice du rang visé.                                 * -*                slot  = numérod de la réservation.                           * -*                top   = désignation de la zone à traiter.                    * -*                                                                             * -*  Description : Fournit la position verticale obtenue par réservation.       * -*                                                                             * -*  Retour      : Ordonnée à utiliser.                                         * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -gint g_graph_ranks_get_y_for_hspan_slot(const GGraphRanks *ranks, unsigned int index, hspan_slot_t slot, bool top) -{ -    /*BUG_ON(index >= ranks->count) */ - -    return get_y_for_rank_props_hspan_slot(&ranks->props[index], slot, top); - -} diff --git a/src/gtkext/graph/ranks.h b/src/gtkext/graph/ranks.h deleted file mode 100644 index da7e54f..0000000 --- a/src/gtkext/graph/ranks.h +++ /dev/null @@ -1,82 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * ranks.h - prototypes pour le calcul de l'ordonnée des différents classements - * - * Copyright (C) 2013 Cyrille Bagard - * - *  This file is part of Chrysalide. - * - *  OpenIDA is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 3 of the License, or - *  (at your option) any later version. - * - *  OpenIDA is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _GTKEXT_GRAPH_RANKS_H -#define _GTKEXT_GRAPH_RANKS_H - - -#include <glib-object.h> -#include <stdbool.h> - - -/* Indice d'une hauteur au sein des rangs */ -typedef size_t hspan_slot_t; - -/* Indice non initilisé */ -#define UNINITIALIZED_HSPAN_SLOT (~((hspan_slot_t)0)) - - -#define G_TYPE_GRAPH_RANKS               g_graph_ranks_get_type() -#define G_GRAPH_RANKS(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_graph_ranks_get_type(), GGraphRanks)) -#define G_IS_GRAPH_RANKS(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_graph_ranks_get_type())) -#define G_GRAPH_RANKS_GET_IFACE(inst)    (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_graph_ranks_get_type(), GGraphRanksIface)) -#define G_GRAPH_RANKS_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_RANKS, GGraphRanksClass)) - - -/* Calcul de l'ordonnée des différents classements (instance) */ -typedef struct _GGraphRanks GGraphRanks; - -/* Calcul de l'ordonnée des différents classements (classe) */ -typedef struct _GGraphRanksClass GGraphRanksClass; - - -/* Indique le type définit par la GLib pour le calcul de l'ordonnée des classements. */ -GType g_graph_ranks_get_type(void); - -/* Prépare de quoi se définir au mieux les ordonnées des noeuds. */ -GGraphRanks *g_graph_ranks_new(unsigned int); - -/* Note une hauteur minimale requise pour un rang du classement. */ -void g_graph_ranks_set_min_height(GGraphRanks *, unsigned int, gint); - -/* Fournit la hauteur requise pour l'affichage des rangs. */ -gint g_graph_ranks_get_height(const GGraphRanks *); - -/* Supprime toutes les réservations faites pour les liens. */ -void g_graph_ranks_reset_reservations(GGraphRanks *); - -/* Réserve une portion de hauteur pour un lien. */ -hspan_slot_t g_graph_ranks_reserve_span(GGraphRanks *, unsigned int, gint, gint, bool); - -/* Calcule l'ordonnée finale de chaque rang du classement. */ -void g_graph_ranks_compute_y_line(GGraphRanks *); - -/* Fournit la position verticale correspondant à un rang donné. */ -gint g_graph_ranks_get_y_for_rank(const GGraphRanks *, unsigned int); - -/* Fournit la position verticale obtenue par réservation. */ -gint g_graph_ranks_get_y_for_hspan_slot(const GGraphRanks *, unsigned int, hspan_slot_t, bool); - - - -#endif  /* _GTKEXT_GRAPH_RANKS_H */ diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c index 368792b..6255602 100644 --- a/src/gtkext/gtkgraphview.c +++ b/src/gtkext/gtkgraphview.c @@ -30,7 +30,7 @@  #include "gtkblockview.h"  #include "gtkbufferview.h"  #include "gtkviewpanel-int.h" -#include "graph/layout.h" +#include "graph/cluster.h"  #include "../analysis/blocks/flow.h"  #include "../gui/editem.h" @@ -49,7 +49,11 @@ struct _GtkGraphView      GtkAllocation *allocs;                  /* Emplacements prévisibles    */      size_t children_count;                  /* Taille de cette liste       */ -    GGraphLayout *layout;                   /* Disposition en graphique    */ +    //GGraphLayout *layout;                   /* Disposition en graphique    */ +    GGraphCluster *cluster;                 /* Disposition en graphique    */ + +    GGraphEdge **edges;                     /* Liens entre les noeuds      */ +    size_t edges_count;                     /* Quantité de ces liens       */      gdouble start_x;                        /* Abscisse du point de souris */      gdouble start_y;                        /* Ordonnée du point de souris */ @@ -74,6 +78,12 @@ static void gtk_graph_view_class_init(GtkGraphViewClass *);  /* Initialise une instance d'afficheur de code en graphique. */  static void gtk_graph_view_init(GtkGraphView *); +/* Supprime toutes les références externes. */ +static void gtk_graph_view_dispose(GtkGraphView *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_graph_view_finalize(GtkGraphView *); +  /* Indique les dimensions de travail du composant d'affichage. */  static void gtk_graph_view_compute_requested_size(GtkGraphView *, gint *, gint *); @@ -210,9 +220,66 @@ static void gtk_graph_view_init(GtkGraphView *view)      //view->mutex = g_mutex_new();      //view->cond = g_cond_new(); + + +    view->cluster = NULL; + + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : view = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void gtk_graph_view_dispose(GtkGraphView *view) +{ +    if (view->cluster != NULL) +    { +        g_object_unref(G_OBJECT(view->cluster)); +        view->cluster = NULL; +    } + +    G_OBJECT_CLASS(gtk_graph_view_parent_class)->dispose(G_OBJECT(view)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : view = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void gtk_graph_view_finalize(GtkGraphView *view) +{ +    G_OBJECT_CLASS(gtk_graph_view_parent_class)->finalize(G_OBJECT(view)); +  } + + + + + + + +  /******************************************************************************  *                                                                             *  *  Paramètres  : view   = composant GTK à consulter.                          * @@ -229,30 +296,27 @@ static void gtk_graph_view_init(GtkGraphView *view)  static void gtk_graph_view_compute_requested_size(GtkGraphView *view, gint *width, gint *height)  { -    GtkRequisition requisition;             /* Taille requise              */ +    GtkAllocation needed;                   /* Taille requise              */ +    gint rwidth;                            /* Largeur demandée            */ +    gint rheight;                           /* Hauteur demandée            */ -    if (width != NULL) +    if (view->cluster != NULL)      { -        if (view->layout != NULL) -        { -            g_graph_layout_size_request(view->layout, &requisition); -            *width = requisition.width; -        } -        else -            *width = 0; -    } +        g_graph_cluster_compute_needed_alloc(view->cluster, &needed); +        assert(needed.x == 0 && needed.y == 0); -    if (height != NULL) +        /* TODO : marges ou centrage */ + +    } +    else      { -        if (view->layout != NULL) -        { -            g_graph_layout_size_request(view->layout, &requisition); -            *height = requisition.height; -        } -        else -            *height = 0; +        needed.width = 0; +        needed.height = 0;      } +    if (width != NULL) *width = needed.width; +    if (height != NULL) *height = needed.height; +  } @@ -300,8 +364,16 @@ static void gtk_graph_view_adjust_scroll_value(GtkGraphView *view, GtkAdjustment  static gboolean gtk_graph_view_draw(GtkWidget *widget, cairo_t *cr, GtkGraphView *view)  { +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < view->edges_count; i++) +        g_graph_edge_draw(view->edges[i], cr, true); + + +    /*      if (view->layout != NULL)          g_graph_layout_draw(view->layout, cr, true); +    */      return FALSE; @@ -458,8 +530,10 @@ static void gtk_graph_view_prepare_resize(GtkGraphView *view)          for (i = 0; i < view->children_count; i++)              gtk_widget_queue_resize(GTK_WIDGET(view->children[i])); +        /*          g_graph_layout_refresh(view->layout);          g_graph_layout_place(view->layout, view); +        */          change_editor_items_current_view_content(GTK_VIEW_PANEL(view)); @@ -518,6 +592,7 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, const vmpa2t                  view->highlighted = init_segment_content_list(); +                /*                  view->children = gtk_graph_view_load_nodes(view, GTK_VIEW_PANEL(view)->binary,                                                             routines[i]); @@ -528,6 +603,33 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, const vmpa2t                                                    view->children, view->children_count);                  g_graph_layout_place(view->layout, view); +                */ + +                do +                { + +                    GBlockList *list; + +                    list = g_binary_routine_get_basic_blocks(routines[i]); + +#if 0 +                    view->cluster = g_graph_cluster_new(GTK_VIEW_PANEL(view)->binary, +                                                  list, 0/* FIXME */, view->highlighted); +#endif + + +                    view->cluster = bootstrap_graph_cluster(GTK_VIEW_PANEL(view)->binary, +                                                            list, view->highlighted); + + + +                    g_graph_cluster_place(view->cluster, view); + + +                } +                while (0); + +                  break; @@ -668,8 +770,10 @@ static void gtk_graph_view_cache_glance(GtkGraphView *view, cairo_t *cairo, cons      cairo_scale(cairo, scale, scale); +    /*      if (view->layout != NULL)          g_graph_layout_draw(view->layout, cairo, false); +    */  } @@ -714,6 +818,7 @@ void gtk_graph_view_put(GtkGraphView *view, GtkWidget *widget, const GtkAllocati      size_t i;                               /* Boucle de parcours          */      GtkWidget *parent;                      /* Parent en cas de réajustemt.*/ +    /*      for (i = 0; i < view->children_count; i++)          if (GTK_WIDGET(view->children[i]) == widget)          { @@ -728,11 +833,38 @@ void gtk_graph_view_put(GtkGraphView *view, GtkWidget *widget, const GtkAllocati          g_object_ref(G_OBJECT(widget));          gtk_container_remove(GTK_CONTAINER(parent), widget);      } +    */      gtk_fixed_put(GTK_FIXED(view->support), widget, alloc->x, alloc->y); +    /*      if (parent != NULL)          g_object_unref(G_OBJECT(widget)); +    */ + +} + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : view = composant GTK à mettre à jour.                        * +*                edge = lien entre noeuds à conserver.                        * +*                                                                             * +*  Description : Intègre un lien entre blocs graphiques dans l'afficheur.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void gtk_graph_view_add_edge(GtkGraphView *view, GGraphEdge *edge) +{ +    view->edges = (GGraphEdge **)realloc(view->edges, +                                         ++view->edges_count * sizeof(GGraphEdge *)); + +    view->edges[view->edges_count - 1] = edge;  } @@ -753,6 +885,40 @@ static void gtk_graph_view_reset(GtkGraphView *view)  {      size_t i;                               /* Boucle de parcours          */ + +    void detach_all_blocks(GtkWidget *widget, GtkContainer *container) +    { + + + +        gtk_container_remove(container, widget); + + +    } + + +    gtk_container_foreach(GTK_CONTAINER(view->support), (GtkCallback)detach_all_blocks, view->support); + + +    if (view->cluster != NULL) +    { +        g_object_unref(G_OBJECT(view->cluster)); +        view->cluster = NULL; +    } + +    for (i = 0; i < view->edges_count; i++) +        g_object_unref(G_OBJECT(view->edges[i])); + +    if (view->edges_count > 0) +    { +        free(view->edges); +        view->edges = NULL; + +        view->edges_count = 0; + +    } + +      /*      for (i = 0; i < view->links_count; i++)          gtk_object_destroy(GTK_OBJECT(view->links[i])); diff --git a/src/gtkext/gtkgraphview.h b/src/gtkext/gtkgraphview.h index 7f841be..5e0f994 100644 --- a/src/gtkext/gtkgraphview.h +++ b/src/gtkext/gtkgraphview.h @@ -28,6 +28,9 @@  #include <gtk/gtk.h> +#include "graph/edge.h" + +  #define GTK_TYPE_GRAPH_VIEW                  (gtk_graph_view_get_type())  #define GTK_GRAPH_VIEW(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_GRAPH_VIEW, GtkGraphView)) @@ -53,6 +56,9 @@ GtkWidget *gtk_graph_view_new(void);  /* Place une vue sous forme de bloc dans le graphique. */  void gtk_graph_view_put(GtkGraphView *, GtkWidget *, const GtkAllocation *); +/* Intègre un lien entre blocs graphiques dans l'afficheur. */ +void gtk_graph_view_add_edge(GtkGraphView *, GGraphEdge *); +  #endif  /* _GTKEXT_GTKGRAPHVIEW_H */  | 
