From 46bcc7f122245f22772fd3e38d16e6afa7bd5881 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 11 May 2015 00:58:05 +0000
Subject: Provided a way to look for ROP gadgets in binary code.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@533 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                           |   55 +-
 configure.ac                        |    1 +
 plugins/Makefile.am                 |    2 +-
 plugins/mobicore/mobicore.c         |    6 +-
 plugins/mobicore/mobicore.h         |    4 +-
 plugins/ropgadgets/Makefile.am      |   15 +
 plugins/ropgadgets/finder.c         |  399 ++++++++
 plugins/ropgadgets/finder.h         |   53 +
 plugins/ropgadgets/helper_arm.c     |   76 ++
 plugins/ropgadgets/helper_arm.h     |   37 +
 plugins/ropgadgets/plugin.c         |   95 ++
 plugins/ropgadgets/plugin.h         |   37 +
 plugins/ropgadgets/select.c         | 1845 +++++++++++++++++++++++++++++++++++
 plugins/ropgadgets/select.h         |   40 +
 src/analysis/disass/area.c          |    2 +-
 src/arch/arm/v7/opdefs/pop_A88131.d |    4 +-
 src/arch/arm/v7/opdefs/pop_A88132.d |    4 +-
 src/arch/processor.h                |   12 +-
 src/arch/vmpa.c                     |   26 +
 src/arch/vmpa.h                     |    3 +
 src/gui/menus/Makefile.am           |    1 +
 src/gui/menus/menubar.c             |    7 +
 src/gui/menus/plugins.c             |   65 ++
 src/gui/menus/plugins.h             |   38 +
 src/plugins/pglist.c                |    2 +-
 src/plugins/plugin-int.h            |    2 +-
 src/plugins/plugin.c                |    7 +-
 src/plugins/plugin.h                |    2 +-
 28 files changed, 2821 insertions(+), 19 deletions(-)
 create mode 100644 plugins/ropgadgets/Makefile.am
 create mode 100644 plugins/ropgadgets/finder.c
 create mode 100644 plugins/ropgadgets/finder.h
 create mode 100644 plugins/ropgadgets/helper_arm.c
 create mode 100644 plugins/ropgadgets/helper_arm.h
 create mode 100644 plugins/ropgadgets/plugin.c
 create mode 100644 plugins/ropgadgets/plugin.h
 create mode 100644 plugins/ropgadgets/select.c
 create mode 100644 plugins/ropgadgets/select.h
 create mode 100644 src/gui/menus/plugins.c
 create mode 100644 src/gui/menus/plugins.h

diff --git a/ChangeLog b/ChangeLog
index 68a4cfb..22cd68e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+15-05-11  Cyrille Bagard <nocbos@gmail.com>
+
+	* configure.ac;
+	Add the new Makefile from the 'plugins/ropgadgets' directory.
+
+	* plugins/Makefile.am:
+	Add ropgadgets to SUBDIRS.
+
+	* plugins/mobicore/mobicore.c:
+	* plugins/mobicore/mobicore.h:
+	Update code for init/exit prototypes.
+
+	* plugins/ropgadgets/finder.c:
+	* plugins/ropgadgets/finder.h:
+	* plugins/ropgadgets/helper_arm.c:
+	* plugins/ropgadgets/helper_arm.h:
+	* plugins/ropgadgets/Makefile.am:
+	* plugins/ropgadgets/plugin.c:
+	* plugins/ropgadgets/plugin.h:
+	* plugins/ropgadgets/select.c:
+	* plugins/ropgadgets/select.h:
+	New entries: provide a way to look for ROP gadgets in binary code.
+
+	* src/analysis/disass/area.c:
+	Typo.
+
+	* src/arch/arm/v7/opdefs/pop_A88131.d:
+	* src/arch/arm/v7/opdefs/pop_A88132.d:
+	Define ARM instructions as return points if and only if it is the case.
+
+	* src/arch/processor.h:
+	Define the next way to disassemble binary code.
+
+	* src/arch/vmpa.c:
+	* src/arch/vmpa.h:
+	Provide one extra operation with vmpa_t structures.
+
+	* src/gui/menus/Makefile.am:
+	Add the 'plugins.[ch]' files to libguimenus_la_SOURCES.
+
+	* src/gui/menus/menubar.c:
+	Update code.
+
+	* src/gui/menus/plugins.c:
+	* src/gui/menus/plugins.h:
+	New entries: add a menu for plugins.
+
+	* src/plugins/pglist.c:
+	* src/plugins/plugin.c:
+	* src/plugins/plugin.h:
+	* src/plugins/plugin-int.h:
+	Provide a global reference to all plugins init/exit functions.
+
 15-05-06  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/arm/v7/post.c:
@@ -214,7 +267,7 @@
 15-04-25  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
-	Add the new Makefile from the 'plugins/libcsem directory.
+	Add the new Makefile from the 'plugins/libcsem' directory.
 
 	* plugins/libcsem/exit.c:
 	* plugins/libcsem/exit.h:
diff --git a/configure.ac b/configure.ac
index ef05fde..bd15448 100644
--- a/configure.ac
+++ b/configure.ac
@@ -287,6 +287,7 @@ AC_CONFIG_FILES([Makefile
                  plugins/python/exectracer/Makefile
                  plugins/python/samples/Makefile
                  plugins/readelf/Makefile
+                 plugins/ropgadgets/Makefile
                  plugins/stackvars/Makefile
                  src/Makefile
                  src/analysis/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 2fdd3ad..726534f 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,2 +1,2 @@
 
-SUBDIRS = androhelpers devdbg libcsem mobicore pychrysa python readelf stackvars
+SUBDIRS = androhelpers devdbg libcsem mobicore pychrysa python readelf ropgadgets stackvars
diff --git a/plugins/mobicore/mobicore.c b/plugins/mobicore/mobicore.c
index 9f7b8a4..15bc0a1 100644
--- a/plugins/mobicore/mobicore.c
+++ b/plugins/mobicore/mobicore.c
@@ -40,6 +40,7 @@ DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("Mobicore", "Support MobiCore file format for Tr
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : plugin = greffon à manipuler.                                *
+*                ref    = espace de référencement global.                     *
 *                                                                             *
 *  Description : Prend acte du chargement du greffon.                         *
 *                                                                             *
@@ -49,7 +50,7 @@ DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("Mobicore", "Support MobiCore file format for Tr
 *                                                                             *
 ******************************************************************************/
 
-G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref)
 {
     bool result;                            /* Bilan à retourner           */
 
@@ -65,6 +66,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : plugin = greffon à manipuler.                                *
+*                ref    = espace de référencement global.                     *
 *                                                                             *
 *  Description : Prend acte du déchargement du greffon.                       *
 *                                                                             *
@@ -74,7 +76,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
 *                                                                             *
 ******************************************************************************/
 
-G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin)
+G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin, GObject *ref)
 {
 
     printf("Unloaded !\n");
diff --git a/plugins/mobicore/mobicore.h b/plugins/mobicore/mobicore.h
index d8687a1..ea0cd15 100644
--- a/plugins/mobicore/mobicore.h
+++ b/plugins/mobicore/mobicore.h
@@ -31,10 +31,10 @@
 
 
 /* Prend acte du chargement du greffon. */
-G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *, GObject *);
 
 /* Prend acte du déchargement du greffon. */
-G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *);
+G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *, GObject *);
 
 
 
diff --git a/plugins/ropgadgets/Makefile.am b/plugins/ropgadgets/Makefile.am
new file mode 100644
index 0000000..5d11366
--- /dev/null
+++ b/plugins/ropgadgets/Makefile.am
@@ -0,0 +1,15 @@
+
+lib_LTLIBRARIES = libropgadgets.la
+
+libropgadgets_la_SOURCES =				\
+	finder.h finder.c					\
+	helper_arm.h helper_arm.c			\
+	plugin.h plugin.c					\
+	select.h select.c
+
+libropgadgets_la_CFLAGS = $(AM_CFLAGS)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I../../src
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/ropgadgets/finder.c b/plugins/ropgadgets/finder.c
new file mode 100644
index 0000000..ff0c6ad
--- /dev/null
+++ b/plugins/ropgadgets/finder.c
@@ -0,0 +1,399 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * finder.c - recherche de gadgets pour ROP
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "finder.h"
+
+
+#include <string.h>
+
+
+#include <core/processors.h>
+
+
+#include <i18n.h>
+
+
+#include "helper_arm.h"
+
+
+
+/* Données utiles à transmettre */
+typedef struct _search_domain
+{
+    GBinFormat *format;                     /* Format du fichier binaire   */
+    GBinContent *content;                   /* Contenu associé récupéré    */
+    GArchProcessor *proc;                   /* Processeur idéal en place   */
+    GProcContext *ctx;                      /* Contexte de désassemblage   */
+
+    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */
+    size_t exe_count;                       /* Nombre de ces zones         */
+
+    phys_t sum;                             /* Surface totale à parcourir  */
+    size_t runs_count;                      /* Nombre de passages à faire  */
+    size_t runs_done;                       /* Nombre de passages effectués*/
+
+} search_domain;
+
+
+/* Désassemble rapidement une instruction. */
+static GArchInstruction *disassemble_instruction_in_domain(const search_domain *, vmpa2t *);
+
+/* Désassemble en amont d'une position autant que possible. */
+static GArchInstruction *look_backward_for_gadgets(const search_domain *, const mrange_t *, const vmpa2t *, unsigned int);
+
+/* Etablit une liste de tous les gadgets présents. */
+static GArchInstruction **list_all_gadgets_in_domain(const search_domain *, unsigned int, update_search_progress_cb, GObject *, size_t *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : domain = ensemble d'auxiliaires à disposition.               *
+*                pos    = tête de lecture pour le désassemblage.              *
+*                                                                             *
+*  Description : Désassemble rapidement une instruction.                      *
+*                                                                             *
+*  Retour      : Instruction créée ou NULL en cas d'échec.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GArchInstruction *disassemble_instruction_in_domain(const search_domain *domain, vmpa2t *pos)
+{
+    GArchInstruction *result;               /* Instruction à retourner     */
+    GProcContext *ctx;                      /* Contexte de désassemblage   */
+
+    ctx = domain->ctx;  /* TODO : copie */
+
+    result = g_arch_processor_disassemble_nextgen(domain->proc, ctx, domain->content, pos);
+
+    if (result != NULL)
+    {
+        g_arch_instruction_call_hook(result, IPH_LINK, domain->proc, ctx, domain->format);
+        g_arch_instruction_call_hook(result, IPH_POST, domain->proc, ctx, domain->format);
+    }
+
+    //g_object_unref(G_OBJECT(ctx)); /* TODO */
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : domain    = ensemble d'auxiliaires à disposition.            *
+*                exe_range = couverture globale dont il ne faut pas sortir.   *
+*                ret       = point de retour final déjà trouvé.               *
+*                max_depth = profondeur maximale des recherches.              *
+*                                                                             *
+*  Description : Désassemble en amont d'une position autant que possible.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GArchInstruction *look_backward_for_gadgets(const search_domain *domain, const mrange_t *exe_range, const vmpa2t *ret, unsigned int max_depth)
+{
+    GArchInstruction *result;               /* Liste de gagdets trouvées   */
+    const phys_t *ins_sizes;                /* Tailles potentielles        */
+    size_t sizes_count;                     /* Quantité de tailles à tester*/
+    vmpa2t last;                            /* Dernier point de départ     */
+    unsigned int i;                         /* Boucle de parcours #1       */
+    GArchInstruction *instr;                /* Elément de gadget trouvé    */
+    size_t k;                               /* Boucle de parcours #2       */
+    vmpa2t start;                           /* Point de départ courant     */
+    vmpa2t end;                             /* Point d'arrivée obtenu      */
+    phys_t diff;                            /* Volume de données traité    */
+    mrange_t range;                         /* Couverture de l'instruction */
+
+    result = NULL;
+
+    ins_sizes = (phys_t []){ 2, 4 };    /* FIXME */
+    sizes_count = 2;
+
+    copy_vmpa(&last, ret);
+
+    /* On parcours jusqu'à la profondeur maximale */
+    for (i = 0; i < max_depth; i++)
+    {
+        instr = NULL;
+
+        for (k = 0; k < sizes_count && instr == NULL; k++)
+        {
+            copy_vmpa(&start, &last);
+            deminish_vmpa(&start, ins_sizes[k]);
+
+            /* Est-on toujours dans les clous ? */
+            if (!mrange_contains_addr(exe_range, &start)) break;
+
+            copy_vmpa(&end, &start);
+
+            instr = disassemble_instruction_in_domain(domain, &end);
+            if (instr == NULL) continue;
+
+            /* La jointure est-elle parfaite ? */
+
+            if (cmp_vmpa(&end, &last) != 0)
+            {
+                g_object_unref(G_OBJECT(instr));
+                instr = NULL;
+                continue;
+            }
+
+            /* S'il s'agit d'un point de retour, on laisse la main à une autre liste */
+
+            if (g_arch_instruction_is_return(instr))
+            {
+                g_object_unref(G_OBJECT(instr));
+                instr = NULL;
+                continue;
+            }
+
+        }
+
+        /* Aucune instruction n'a été trouvée à cette profondeur, on s'arrête donc */
+        if (instr == NULL) break;
+
+        copy_vmpa(&last, &start);
+
+        diff = compute_vmpa_diff(&end, &start);
+
+        init_mrange(&range, &start, diff);
+
+        g_arch_instruction_set_range(instr, &range);
+
+
+        g_arch_instruction_merge_lists(&result, &instr);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : domain    = ensemble d'auxiliaires à disposition.            *
+*                max_depth = profondeur maximale des recherches.              *
+*                update    = fonction de suivi mise à disposition.            *
+*                data      = données à associer à une phase d'actualisation.  *
+*                count     = nombre de gadgets trouvés. [OUT]                 *
+*                                                                             *
+*  Description : Etablit une liste de tous les gadgets présents.              *
+*                                                                             *
+*  Retour      : Liste de listes d'instructions, à libérer après usage.       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GArchInstruction **list_all_gadgets_in_domain(const search_domain *domain, unsigned int max_depth, update_search_progress_cb update, GObject *data, size_t *count)
+{
+    GArchInstruction **result;              /* Liste de listes à renvoyer  */
+    phys_t done;                            /* Accumulation des quantités  */
+    size_t i;                               /* Boucle de parcours #1       */
+    phys_t max;                             /* Borne d'un parcours         */
+    phys_t k;                               /* Boucle de parcours #2       */
+    gdouble fraction;                       /* Progression générale        */
+    vmpa2t ret;                             /* Emplacement du retour       */
+    vmpa2t tmp;                             /* Copie de travail modifiable */
+    GArchInstruction *gadget;               /* Nouveau gadget détecté      */
+    phys_t diff;                            /* Volume de données traité    */
+    mrange_t ins_range;                     /* Emplacement d'une instruct° */
+    vmpa2t end;                             /* Point d'arrivée obtenu      */
+    GArchInstruction *new;                  /* Nouvelle liste de gadgets   */
+
+    result = NULL;
+    *count = 0;
+
+    done = 0;
+
+    for (i = 0; i < domain->exe_count; i++)
+    {
+        max = get_mrange_length(&domain->exe_ranges[i]);
+
+        for (k = 0; k < max; k++)
+        {
+            /* Affichage de la progression */
+
+            fraction = 1.0 * (domain->runs_done * domain->sum + done + k);
+            fraction /= (domain->runs_count * domain->sum);
+
+            update(data, fraction);
+
+            /* Réception de la première / dernière instruction */
+
+            copy_vmpa(&ret, get_mrange_addr(&domain->exe_ranges[i]));
+            advance_vmpa(&ret, k);
+
+            copy_vmpa(&tmp, &ret);
+
+            gadget = disassemble_instruction_in_domain(domain, &tmp);
+            if (gadget == NULL) continue;
+
+            /* A-t-on bien affaire à une instruction de retour ? */
+
+            if (!g_arch_instruction_is_return(gadget))
+            {
+                g_object_unref(G_OBJECT(gadget));
+                continue;
+            }
+
+            /* Ne déborde-t-on pas dans une zone voisine ? */
+
+            diff = compute_vmpa_diff(&ret, &tmp);
+            init_mrange(&ins_range, &ret, diff);
+
+            compute_mrange_end_addr(&ins_range, &end);
+
+            if (!mrange_contains_mrange(&domain->exe_ranges[i], &ins_range))
+            {
+                g_object_unref(G_OBJECT(gadget));
+                continue;
+            }
+
+            /* Ajout d'un nouvel ensemble de gadgets */
+
+            g_arch_instruction_set_range(gadget, &ins_range);
+
+            //printf(" ROP @ 0x%08x / 0x%08x\n", gadget->range.addr.virtual, ret.virtual);
+
+            new = look_backward_for_gadgets(domain, &domain->exe_ranges[i], &ret, max_depth);
+
+            g_arch_instruction_merge_lists(&new, &gadget);
+
+            result = (GArchInstruction **)realloc(result, ++(*count) * sizeof(GArchInstruction *));
+            result[*count - 1] = new;
+
+        }
+
+        done += max;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary    = binaire dont le contenu est à traiter.           *
+*                max_depth = profondeur maximale des recherches.              *
+*                update    = fonction de suivi mise à disposition.            *
+*                data      = données à associer à une phase d'actualisation.  *
+*                count     = nombre de gadgets trouvés. [OUT]                 *
+*                                                                             *
+*  Description : Etablit une liste de tous les gadgets présents.              *
+*                                                                             *
+*  Retour      : Liste de listes d'instructions, à libérer après usage.       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+found_rop_list *list_all_gadgets(GBinFormat *format, unsigned int max_depth, update_search_progress_cb update, GObject *data, size_t *count)
+{
+    found_rop_list *result;                 /* Liste de listes à renvoyer  */
+    const char *target;                     /* Sous-traitance requise      */
+    search_domain domain;                   /* Outils pour la recherche    */
+    GProcContext **contexts;                /* Contextes pour recherches   */
+    char **names;                           /* Désignations humaines liées */
+    size_t i;                               /* Boucle de parcours          */
+
+    /* Constitution du socle commun */
+
+    g_object_ref(G_OBJECT(format));
+    domain.format = format;
+
+    domain.content = g_binary_format_get_conten_(format);
+
+    target = g_exe_format_get_target_machine(G_EXE_FORMAT(format));
+    domain.proc = get_arch_processor_for_type(target);
+
+    domain.exe_ranges = g_exe_format_get_x_ranges(G_EXE_FORMAT(format), &domain.exe_count);
+
+    /* Récupération des différents contextes */
+
+    if (strcmp(target, "armv7") == 0)
+        contexts = get_rop_contexts_for_arm(domain.proc, &names, count);
+
+    else
+    {
+        contexts = (GProcContext **)calloc(1, sizeof(GProcContext *));
+        names = (char **)calloc(1, sizeof(char *));
+        *count = 1;
+
+        contexts[0] = g_arch_processor_get_context(domain.proc);
+        names[0] = _("all");
+
+    }
+
+    /* Calcul de la surface totale à parcourir */
+
+    domain.sum = 0;
+
+    for (i = 0; i < domain.exe_count; i++)
+        domain.sum += get_mrange_length(&domain.exe_ranges[i]);
+
+    /* Détermination des différents parcours */
+
+    domain.runs_count = *count;
+
+    domain.runs_done = 0;
+
+    /* Parcours des différentes surfaces */
+
+    result = (found_rop_list *)calloc(*count, sizeof(found_rop_list));
+
+    for (i = 0; i < *count; i++)
+    {
+        result[i].category = names[i];
+
+        domain.ctx = contexts[i];
+
+        result[i].gadgets = list_all_gadgets_in_domain(&domain, max_depth, update, data, &result[i].count);
+
+        g_object_unref(G_OBJECT(domain.ctx));
+
+        domain.runs_done++;
+
+    }
+
+    free(names);
+    free(contexts);
+
+    free(domain.exe_ranges);
+
+    g_object_unref(G_OBJECT(domain.proc));
+    g_object_unref(G_OBJECT(domain.content));
+    g_object_unref(G_OBJECT(domain.format));
+
+    return result;
+
+}
diff --git a/plugins/ropgadgets/finder.h b/plugins/ropgadgets/finder.h
new file mode 100644
index 0000000..fe6dfe7
--- /dev/null
+++ b/plugins/ropgadgets/finder.h
@@ -0,0 +1,53 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * finder.h - prototypes pour la recherche de gadgets pour ROP
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ROPGADGETS_FINDER_H
+#define _PLUGINS_ROPGADGETS_FINDER_H
+
+
+#include <arch/instruction.h>
+#include <format/format.h>
+
+
+
+/* Actualise la barre de progression affichée. */
+typedef void (* update_search_progress_cb) (GObject *, gdouble);
+
+
+/* Catégorisation des résultats */
+typedef struct _found_rop_list
+{
+    const char *category;                   /* Désignation du groupe       */
+
+    GArchInstruction **gadgets;             /* Gadgets pour ROP trouvés    */
+    size_t count;                           /* Taille de cette liste       */
+
+} found_rop_list;
+
+
+/* Etablit une liste de tous les gadgets présents. */
+found_rop_list *list_all_gadgets(GBinFormat *, unsigned int, update_search_progress_cb, GObject *, size_t *);
+
+
+
+#endif  /* _PLUGINS_ROPGADGETS_FINDER_H */
diff --git a/plugins/ropgadgets/helper_arm.c b/plugins/ropgadgets/helper_arm.c
new file mode 100644
index 0000000..7288399
--- /dev/null
+++ b/plugins/ropgadgets/helper_arm.c
@@ -0,0 +1,76 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helper_arm.c - prise en compte des spécifités ARM pour la recherche de gadgets
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "helper_arm.h"
+
+
+#include <malloc.h>
+
+
+#include <arch/arm/v7/context.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc  = processeur lié à l'architecture visée.               *
+*                names = noms attribués aux différents contextes.             *
+*                count = nombre de gadgets trouvés. [OUT]                     *
+*                                                                             *
+*  Description : Etablit une liste des contextes utiles à la recherche.       *
+*                                                                             *
+*  Retour      : Liste de contextes mis en place.                             *
+*                                                                             *
+*  Remarques   : Toues les tableaux créés sont à libérer après usage.         *
+*                                                                             *
+******************************************************************************/
+
+GProcContext **get_rop_contexts_for_arm(const GArchProcessor *proc, char ***names, size_t *count)
+{
+    GProcContext **result;                  /* Contextes à retourner       */
+
+    result = (GProcContext **)calloc(2, sizeof(GProcContext *));
+
+    (*names) = (char **)calloc(2, sizeof(char *));
+
+    *count = 2;
+
+    /* Thumb */
+
+    result[0] = g_arch_processor_get_context(proc);
+
+    g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result[0]), 0, AV7IS_THUMB);
+
+    (*names)[0] = "Thumb";
+
+    /* ARMM */
+
+    result[1] = g_arch_processor_get_context(proc);
+
+    g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result[1]), 0, AV7IS_ARM);
+
+    (*names)[1] = "ARM";
+
+    return result;
+
+}
diff --git a/plugins/ropgadgets/helper_arm.h b/plugins/ropgadgets/helper_arm.h
new file mode 100644
index 0000000..afae191
--- /dev/null
+++ b/plugins/ropgadgets/helper_arm.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helper_arm.h - prototypes pour la prise en compte des spécifités ARM pour la recherche de gadgets
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ROPGADGETS_HELPER_ARM_H
+#define _PLUGINS_ROPGADGETS_HELPER_ARM_H
+
+
+#include <arch/processor.h>
+
+
+
+/* Etablit une liste des contextes utiles à la recherche. */
+GProcContext **get_rop_contexts_for_arm(const GArchProcessor *, char ***, size_t *);
+
+
+
+#endif  /* _PLUGINS_ROPGADGETS_HELPER_ARM_H */
diff --git a/plugins/ropgadgets/plugin.c b/plugins/ropgadgets/plugin.c
new file mode 100644
index 0000000..a243a74
--- /dev/null
+++ b/plugins/ropgadgets/plugin.c
@@ -0,0 +1,95 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plugin.c - description et intégration du présent greffon
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "plugin.h"
+
+
+#include <i18n.h>
+
+
+#include <gtkext/easygtk.h>
+#include <plugins/plugin-def.h>
+
+
+#include "select.h"
+
+
+
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("ROP gadgets", "Find available gadgets for a ROP chain", "0.1.0",
+                                PGA_PLUGIN_INIT);
+
+
+
+/* Réagit avec le menu "Greffons -> Lister les gadgets ROP". */
+static void mcb_plugins_list_rop_gadgets(GtkMenuItem *, GObject *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                ref    = espace de référencement global.                     *
+*                                                                             *
+*  Description : Prend acte du chargement du greffon.                         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref)
+{
+    GtkContainer *menubar;                  /* Support pour éléments       */
+    GtkWidget *submenuitem;                 /* Sous-élément de menu        */
+
+    menubar = GTK_CONTAINER(g_object_get_data(ref, "menubar_plugins"));
+    if (menubar == NULL) return false;
+
+    submenuitem = qck_create_menu_item(ref, "mnu_plugins_ropgadgets", _("List ROP gadgets"),
+                                       G_CALLBACK(mcb_plugins_list_rop_gadgets), ref);
+    gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : menuitem = élément de menu sélectionné.                      *
+*                ref      = adresse de l'espace de référencement global.      *
+*                                                                             *
+*  Description : Réagit avec le menu "Greffons -> Lister les gadgets ROP".    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void mcb_plugins_list_rop_gadgets(GtkMenuItem *menuitem, GObject *ref)
+{
+    run_rop_finder_assistant(ref, NULL);
+
+}
diff --git a/plugins/ropgadgets/plugin.h b/plugins/ropgadgets/plugin.h
new file mode 100644
index 0000000..67612de
--- /dev/null
+++ b/plugins/ropgadgets/plugin.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plugin.h - prototypes pour la description et intégration du présent greffon
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ROPGADGETS_PLUGIN_H
+#define _PLUGINS_ROPGADGETS_PLUGIN_H
+
+
+#include <plugins/plugin.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *, GObject *ref);
+
+
+
+#endif  /* _PLUGINS_ROPGADGETS_PLUGIN_H */
diff --git a/plugins/ropgadgets/select.c b/plugins/ropgadgets/select.c
new file mode 100644
index 0000000..2889eb5
--- /dev/null
+++ b/plugins/ropgadgets/select.c
@@ -0,0 +1,1845 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * goto.c - boîte de dialogue pour les sauts à une adresse donnée
+ *
+ * Copyright (C) 2012-2014 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "select.h"
+
+
+#include <fcntl.h>
+#include <malloc.h>
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+#include <i18n.h>
+
+
+#include <project.h>
+#include <common/cpp.h>
+#include <common/extstr.h>
+#include <core/formats.h>
+#include <core/processors.h>
+#include <gtkext/easygtk.h>
+
+
+#include "finder.h"
+
+
+
+/* ------------------------ PARTIE PRINCIPALE DE L'ASSISTANT ------------------------ */
+
+
+/* Colonnes de la liste des binaires */
+typedef enum _CurrentProjectBinaries
+{
+    CPB_BINARY,                             /* Instance GLib du bianire    */
+    CPB_FILENAME,                           /* Chemin d'accès au fichier   */
+
+    CPB_COUNT                               /* Nombre de colonnes          */
+
+} CurrentProjectBinaries;
+
+
+/* Ferme l'assistant sans dérouler la procédure. */
+static void rop_finder_assistant_cancel(GtkAssistant *, gpointer);
+
+/* Ferme l'assistant et déroule la procédure. */
+static void rop_finder_assistant_apply(GtkAssistant *, GObject *);
+
+/* Accompagne le chargement de certaines pages de l'assistant. */
+static void rop_finder_assistant_prepare(GtkAssistant *, GtkWidget *, GObject *);
+
+
+
+/* ------------------------ DEFINITION DES ENTREES / SORTIES ------------------------ */
+
+
+/* Ajoute le panneau de choix quant aux fichiers d'E/S. */
+static void register_input_output_panel(GtkAssistant *, GObject *);
+
+/* Construit la sélection d'un binaire déjà chargé. */
+static GtkWidget *load_and_populate_current_project_binaries(GObject *);
+
+/* Met à jour l'accès à la sélection du type d'entrée. */
+static void on_input_type_toggle(GtkToggleButton *, GObject *);
+
+/* Réagit à un changement de sélection du binaire d'entrée. */
+static void on_loaded_binary_selection_change(GtkComboBox *, GObject *);
+
+/* Réagit à un changement de fichier binaire d'entrée. */
+static void on_input_filename_change(GtkEditable *, GObject *);
+
+/* Sélectionne ou non un nouveau fichier d'entrée. */
+static void on_input_filename_browsing_clicked(GtkButton *, GObject *);
+
+/* Met à jour l'accès à la définition d'un fichier de sortie. */
+static void on_output_need_toggle(GtkToggleButton *, GObject *);
+
+/* Sélectionne ou non un nouveau fichier de sortie. */
+static void on_output_filename_browsing_clicked(GtkButton *, GObject *);
+
+
+
+/* ------------------------- SUIVI DE LA PHASE DE RECHERCHE ------------------------- */
+
+
+/* Ajoute le panneau de suivi des opérations de recherche. */
+static void register_search_display_panel(GtkAssistant *, GObject *);
+
+/* Initialise une ligne de rapport quant aux opérations menées. */
+static void init_rop_search_step(GtkGrid *, gint, GObject *, const char *, const char *, GtkWidget *);
+
+/* Réinitialise tous les rapports de recherches imprimés. */
+static void reset_rop_search_steps(GObject *);
+
+
+/* Description d'une évolution du processus */
+typedef struct _search_step
+{
+    GObject *ref;                           /* Espace de référencements    */
+
+    union
+    {
+        struct
+        {
+            const char *key;                /* Clef d'accès partielle      */
+            bool dynamic;                   /* Mémoire à libérer ?         */
+            union
+            {
+                const char *msg;            /* Message de conclusion       */
+                char *dmsg;                 /* Message de conclusion       */
+            };
+            bool success;                   /* Indication claire           */
+        };
+
+        gdouble fraction;                   /* Avancée du désasssemblage   */
+
+        struct
+        {
+            GBinFormat *format;             /* Format binaire chargé       */
+            found_rop_list *list;           /* Liste de gadgets ROP trouvés*/
+            size_t count;                   /* Nombre de gadgets trouvés   */
+        };
+
+    };
+
+} search_step;
+
+
+/* Affiche un message de statut quant aux recherches en cours. */
+static gboolean print_status_of_rop_search_step(search_step *);
+
+/* Affiche un message de statut quant aux recherches en cours. */
+static void push_status_printing_of_rop_search_step(GObject *, const char *, const char *, bool);
+
+/* Affiche un message de statut quant aux recherches en cours. */
+static void push_dyn_status_printing_of_rop_search_step(GObject *, const char *, char *, bool);
+
+/* Actualise la barre de progression affichée. */
+static gboolean update_progress_bar_fraction(search_step *);
+
+/* Lance l'actualisation de la barre de progression affichée. */
+static void push_new_progress_fraction(GObject *, gdouble);
+
+/* Enregistre une référence vers les gadgets trouvés. */
+static gboolean register_found_rop_gadgets(search_step *);
+
+/* Lance une conservation des gadgets trouvés. */
+static void push_found_rop_gadgets(GObject *, GBinFormat *, found_rop_list *, size_t);
+
+/* Charge un format binaire interne déjà chargé. */
+static GBinFormat *load_internal_format_for_rop_gadgets(GObject *);
+
+/* Charge un format binaire externe. */
+static GBinFormat *load_external_format_for_rop_gadgets(GObject *);
+
+/* Procède à la recherche de gadgets de façon séparée. */
+static gpointer look_for_rop_gadgets(GObject *);
+
+
+
+/* ----------------------- MISE EN FORME DES GADGETS PRESENTS ----------------------- */
+
+
+/* Colonnes de la liste des symboles */
+typedef enum _FoundROPGadget
+{
+    FRG_CATEGORY,                           /* Catégorie d'appartenance    */
+    FRG_RAW_VIRTUAL,                        /* Correspondance virtuelle    */
+    FRG_RAW,                                /* Brut pour recherche         */
+
+    FRG_VIRTUAL,                            /* Correspondance virtuelle    */
+    FRG_CONTENT,                            /* Contenu des lignes visées   */
+
+    FRG_COUNT                               /* Nombre de colonnes          */
+
+} FoundROPGadget;
+
+
+/* Ajoute le panneau de sélection des gadgets ROP identifiés. */
+static void register_rop_list_panel(GtkAssistant *, GObject *);
+
+/* Lance l'actualisation du filtrage des gadgets ROP. */
+static void on_rop_gadgets_category_changed(GtkComboBox *, GObject *);
+
+/* Lance l'actualisation du filtrage des gadgets ROP. */
+static void on_rop_gadgets_filter_changed(GtkSearchEntry *, GObject *);
+
+/* Détermine la visibilité de tel ou tel gadget ROP. */
+static gboolean filter_visible_rop_gadgets(GtkTreeModel *, GtkTreeIter *, GObject *);
+
+/* Ajoute de nouvelles chaînes de gadgets localisées. */
+static void add_new_gadgets_for_category(GBinFormat *, GtkComboBoxText *, GtkTreeStore *, const char *, GArchInstruction **, size_t);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          PARTIE PRINCIPALE DE L'ASSISTANT                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : global = espace de référencements global.                    *
+*                parent = fenêtre principale de l'éditeur.                    *
+*                                                                             *
+*  Description : Crée et affiche un assistant de sélection de gadgets ROP.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void run_rop_finder_assistant(GObject *global, GtkWindow *parent)
+{
+    GtkWidget *assistant;                   /* Fenêtre à afficher          */
+    GObject *ref;                           /* Espace de référencement     */
+
+    assistant = gtk_assistant_new();
+    gtk_widget_set_size_request(assistant, 900, 550);
+    gtk_window_set_position(GTK_WINDOW(assistant), GTK_WIN_POS_CENTER);
+    gtk_window_set_title(GTK_WINDOW(assistant), _("Export assistant"));
+
+    gtk_window_set_modal(GTK_WINDOW(assistant), TRUE);
+    gtk_window_set_transient_for(GTK_WINDOW(assistant), parent);
+
+    ref = G_OBJECT(assistant);
+    g_object_set_data(ref, "global", global);
+
+    register_input_output_panel(GTK_ASSISTANT(assistant), ref);
+    register_search_display_panel(GTK_ASSISTANT(assistant), ref);
+    register_rop_list_panel(GTK_ASSISTANT(assistant), ref);
+
+    g_signal_connect(G_OBJECT(assistant), "cancel", G_CALLBACK(rop_finder_assistant_cancel), NULL);
+    g_signal_connect(G_OBJECT(assistant), "close", G_CALLBACK(rop_finder_assistant_cancel), NULL);
+    g_signal_connect(G_OBJECT(assistant), "apply", G_CALLBACK(rop_finder_assistant_apply), ref);
+    g_signal_connect(G_OBJECT(assistant), "prepare", G_CALLBACK(rop_finder_assistant_prepare), ref);
+
+    gtk_widget_show_all(assistant);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : assistant = fenêtre d'assistance à traiter.                  *
+*                data      = adresse non utilisée ici.                        *
+*                                                                             *
+*  Description : Ferme l'assistant sans dérouler la procédure.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void rop_finder_assistant_cancel(GtkAssistant *assistant, gpointer data)
+{
+    gtk_widget_destroy(GTK_WIDGET(assistant));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : assistant = fenêtre d'assistance à traiter.                  *
+*                ref       = adresse de l'espace de référencement global.     *
+*                                                                             *
+*  Description : Ferme l'assistant et déroule la procédure.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void rop_finder_assistant_apply(GtkAssistant *assistant, GObject *ref)
+{
+    GtkEntry *entry;                        /* Zone de saisie              */
+    const gchar *filename;                  /* Chemin d'accès du fichier   */
+    int fd;                                 /* Flux ouvert en écriture     */
+    GtkTreeView *treeview;                  /* Arborescence à actualiser   */
+    GtkTreeModel *model;                    /* Modèle de gestion           */
+    GtkTreeIter iter;                       /* Boucle de parcours          */
+    gboolean loop;                          /* Poursuite de la boucle ?    */
+    gchar *virtual;                         /* Adresse correspondante      */
+    gchar *raw;                             /* ROP en format texte simple  */
+
+    /* Fichier de sortie */
+
+    entry = GTK_ENTRY(g_object_get_data(ref, "output_filename"));
+    filename = gtk_entry_get_text(entry);
+
+    fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
+    if (fd == -1)
+    {
+        perror("open");
+        return;
+    }
+
+    /* Boucle de parcours */
+
+    treeview = GTK_TREE_VIEW(g_object_get_data(ref, "treeview"));
+    model = gtk_tree_view_get_model(treeview);
+
+    for (loop = gtk_tree_model_get_iter_first(model, &iter);
+         loop;
+         loop = gtk_tree_model_iter_next(model, &iter))
+    {
+        gtk_tree_model_get(model, &iter, FRG_RAW_VIRTUAL, &virtual, FRG_RAW, &raw, -1);
+
+        dprintf(fd, "%s\t%s\n", virtual, raw);
+
+        g_free(virtual);
+        g_free(raw);
+
+    }
+
+    /* Conclusion */
+
+    close(fd);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : assistant = fenêtre d'assistance à traiter.                  *
+*                page      = élément de l'assistant à préparer.               *
+*                ref       = adresse de l'espace de référencement global.     *
+*                                                                             *
+*  Description : Accompagne le chargement de certaines pages de l'assistant.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void rop_finder_assistant_prepare(GtkAssistant *assistant, GtkWidget *page, GObject *ref)
+{
+    GtkWidget *test;                        /* Reconnaissance à l'aveugle  */
+    GThread *thread;                        /* Tâche de fond à programmer  */
+
+    test = gtk_assistant_get_nth_page(assistant, 1);
+
+    if (test == page)
+    {
+        reset_rop_search_steps(ref);
+
+        thread = g_thread_new("gadgets_finder", (GThreadFunc)look_for_rop_gadgets, ref);
+        g_thread_unref(thread);
+
+    }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                          DEFINITION DES ENTREES / SORTIES                          */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : assistant = fenêtre d'assistance à compléter.                *
+*                ref       = espace de référencements inter-panneaux.         *
+*                                                                             *
+*  Description : Ajoute le panneau de choix quant aux fichiers d'E/S.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void register_input_output_panel(GtkAssistant *assistant, GObject *ref)
+{
+    GtkWidget *vbox;                        /* Support principal           */
+    GtkWidget *frame;                       /* Support avec encadrement    */
+    GtkWidget *alignment;                   /* Disposition sur le support  */
+    GtkWidget *sub_vbox;                    /* Division verticale          */
+    GtkWidget *radio;                       /* Choix du type d'entrée      */
+    GtkWidget *combobox;                    /* Sélection du binaire interne*/
+    GtkWidget *sub_hbox;                    /* Division horizontale        */
+    GtkWidget *entry;                       /* Zone de saisie de texte     */
+    GtkWidget *button;                      /* Sélection de fichier        */
+    GtkWidget *checkbutton;                 /* Coche pour une option       */
+
+    vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 16);
+    gtk_widget_show(vbox);
+
+    /* Fichier de sortie */
+
+    frame = qck_create_frame(_("<b>Input binary</b>"), &alignment, 0, 0, 12, 8);
+    gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0);
+
+    sub_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+    gtk_widget_show(sub_vbox);
+    gtk_container_add(GTK_CONTAINER(alignment), sub_vbox);
+
+    radio = qck_create_radio_button(ref, "loaded_as_input", _("Use a binary from the current project:"),
+                                    NULL, G_CALLBACK(on_input_type_toggle), ref);
+    gtk_box_pack_start(GTK_BOX(sub_vbox), radio, FALSE, FALSE, 0);
+
+    combobox = load_and_populate_current_project_binaries(ref);
+    gtk_box_pack_start(GTK_BOX(sub_vbox), combobox, TRUE, TRUE, 0);
+
+    radio = qck_create_radio_button(ref, "extern_as_input", _("Open a new binary file:"),
+                                    GTK_RADIO_BUTTON(radio), G_CALLBACK(on_input_type_toggle), ref);
+    gtk_box_pack_start(GTK_BOX(sub_vbox), radio, FALSE, FALSE, 0);
+
+    sub_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+    gtk_widget_show(sub_hbox);
+    gtk_box_pack_start(GTK_BOX(sub_vbox), sub_hbox, FALSE, FALSE, 0);
+
+    entry = qck_create_entry(ref, "input_filename", NULL);
+    g_signal_connect(entry, "changed", G_CALLBACK(on_input_filename_change), ref);
+    gtk_box_pack_start(GTK_BOX(sub_hbox), entry, TRUE, TRUE, 0);
+
+    button = qck_create_button(ref, "input_browser", _("Browse..."),
+                               G_CALLBACK(on_input_filename_browsing_clicked), assistant);
+    gtk_box_pack_start(GTK_BOX(sub_hbox), button, FALSE, FALSE, 0);
+
+    /* Actualisation des accès */
+
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
+    on_input_type_toggle(GTK_TOGGLE_BUTTON(radio), ref);
+
+    /* Fichier de sortie */
+
+    frame = qck_create_frame(_("<b>Ouput results</b>"), &alignment, 0, 0, 12, 8);
+    gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0);
+
+    sub_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+    gtk_widget_show(sub_vbox);
+    gtk_container_add(GTK_CONTAINER(alignment), sub_vbox);
+
+    checkbutton = qck_create_check_button(ref, "use_output",
+                                          _("Save selected ROP gadgets in a file:"),
+                                          G_CALLBACK(on_output_need_toggle), ref);
+    gtk_widget_show(checkbutton);
+
+    gtk_box_pack_start(GTK_BOX(sub_vbox), checkbutton, FALSE, FALSE, 0);
+
+    sub_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+    gtk_widget_show(sub_hbox);
+    gtk_box_pack_start(GTK_BOX(sub_vbox), sub_hbox, FALSE, TRUE, 0);
+
+    entry = qck_create_entry(ref, "output_filename", NULL);
+    gtk_box_pack_start(GTK_BOX(sub_hbox), entry, TRUE, TRUE, 0);
+
+    button = qck_create_button(ref, "output_browser", _("Browse..."),
+                               G_CALLBACK(on_output_filename_browsing_clicked), assistant);
+    gtk_box_pack_start(GTK_BOX(sub_hbox), button, FALSE, FALSE, 0);
+
+    /* Actualisation des accès */
+
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), FALSE);
+    on_output_need_toggle(GTK_TOGGLE_BUTTON(checkbutton), ref);
+
+    /* Intégration */
+
+    gtk_assistant_append_page(assistant, vbox);
+    gtk_assistant_set_page_title(assistant, vbox, _("Input / output"));
+    gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_INTRO);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref = espace de référencements inter-panneaux.               *
+*                                                                             *
+*  Description : Construit la sélection d'un binaire déjà chargé.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GtkWidget *load_and_populate_current_project_binaries(GObject *ref)
+{
+    GtkWidget *result;                      /* Composant à retourner       */
+    GObject *global;                        /* Espace de référencements    */
+    GLoadedBinary *current;                 /* Binaire actif courant       */
+    gint selected;                          /* Indice à sélectionner       */
+    GtkListStore *store;                    /* Modèle de gestion en liste  */
+    GLoadedBinary **binaries;               /* Liste de binaires           */
+    size_t count;                           /* Taille de cette liste       */
+    size_t i;                               /* Boucle de parcours          */
+    GtkTreeIter iter;                       /* Point d'insertion           */
+    GtkCellRenderer *renderer;              /* Moteur de rendu de colonne  */
+
+    /* Récupération du binaire courant */
+
+    global = G_OBJECT(g_object_get_data(ref, "global"));
+
+    current = G_LOADED_BINARY(g_object_get_data(global, "current_binary"));
+
+    /* Constitution d'une liste de binaires courants */
+
+    selected = -1;
+
+    store = gtk_list_store_new(CPB_COUNT, G_TYPE_OBJECT, G_TYPE_STRING);
+
+    binaries = g_study_project_get_binaries(get_current_project(), &count);
+
+    if (binaries != NULL)
+    {
+        for (i = 0; i < count; i++)
+        {
+            gtk_list_store_append(store, &iter);
+            gtk_list_store_set(store, &iter,
+                               CPB_BINARY, binaries[i],
+                               CPB_FILENAME, g_loaded_binary_get_name(binaries[i], true),
+                               -1);
+
+            if (binaries[i] == current)
+                selected = i;
+
+            g_object_unref(G_OBJECT(binaries[i]));
+
+        }
+
+        free(binaries);
+
+    }
+
+    /* Mise en place d'un affichage graphique */
+
+    result = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
+    g_object_set_data(ref, "input_binary", result);
+
+    g_signal_connect(result, "changed", G_CALLBACK(on_loaded_binary_selection_change), ref);
+
+    gtk_widget_show(result);
+
+    gtk_combo_box_set_active(GTK_COMBO_BOX(result), selected);
+
+    renderer = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(result), renderer, TRUE);
+    gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(result), renderer,
+                                   "text", CPB_FILENAME,
+                                   NULL);
+
+    g_object_unref(G_OBJECT(store));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : button = oche dont le status vient de changer.               *
+*                ref    = espace de référencements inter-panneaux.            *
+*                                                                             *
+*  Description : Met à jour l'accès à la sélection du type d'entrée.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_input_type_toggle(GtkToggleButton *button, GObject *ref)
+{
+    GtkToggleButton *internal;              /* Bouton de sélection interne */
+    gboolean state;                         /* Etat du bouton courant      */
+    GtkWidget *widget;                      /* Element dont l'accès change */
+
+    internal = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "loaded_as_input"));
+    state = gtk_toggle_button_get_active(internal);
+
+    /* Elément de sélection interne */
+
+    widget = GTK_WIDGET(g_object_get_data(ref, "input_binary"));
+
+    if (widget != NULL)
+    {
+        gtk_widget_set_sensitive(widget, state);
+
+        if (state)
+            on_loaded_binary_selection_change(GTK_COMBO_BOX(widget), ref);
+
+    }
+
+    /* Elément de sélection externe */
+
+    widget = GTK_WIDGET(g_object_get_data(ref, "input_filename"));
+
+    if (widget != NULL)
+    {
+        gtk_widget_set_sensitive(widget, !state);
+
+        if (!state)
+            on_input_filename_change(GTK_EDITABLE(widget), ref);
+
+    }
+
+    widget = GTK_WIDGET(g_object_get_data(ref, "input_browser"));
+    if (widget != NULL)
+        gtk_widget_set_sensitive(widget, !state);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : combo = composant graphique de sélection concerné.           *
+*                ref   = espace de référencement principal.                   *
+*                                                                             *
+*  Description : Réagit à un changement de sélection du binaire d'entrée.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_loaded_binary_selection_change(GtkComboBox *combo, GObject *ref)
+{
+    gint selected;                          /* Indice sélectionné          */
+    GtkWidget *page;                        /* Page de la partie terminée  */
+
+    selected = gtk_combo_box_get_active(combo);
+
+    page = gtk_assistant_get_nth_page(GTK_ASSISTANT(ref), 0);
+
+    if (page != NULL)
+        gtk_assistant_set_page_complete(GTK_ASSISTANT(ref), page, selected != -1);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : editable = composant graphique d'édition concerné.           *
+*                ref      = espace de référencement principal.                *
+*                                                                             *
+*  Description : Réagit à un changement de fichier binaire d'entrée.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_input_filename_change(GtkEditable *editable, GObject *ref)
+{
+    guint16 length;                         /* Taille du texte fourni      */
+    GtkWidget *page;                        /* Page de la partie terminée  */
+
+    length = gtk_entry_get_text_length(GTK_ENTRY(editable));
+
+    page = gtk_assistant_get_nth_page(GTK_ASSISTANT(ref), 0);
+
+    if (page != NULL)
+        gtk_assistant_set_page_complete(GTK_ASSISTANT(ref), page, length > 0);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : button = bouton d'édition de la sélection.                   *
+*                ref    = espace de référencement principal.                  *
+*                                                                             *
+*  Description : Sélectionne ou non un nouveau fichier d'entrée.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_input_filename_browsing_clicked(GtkButton *button, GObject *ref)
+{
+    GtkWidget *dialog;                      /* Boîte à afficher            */
+    gchar *filename;                        /* Nom du fichier à intégrer   */
+    GtkEntry *entry;                        /* Zone de saisie à maj.       */
+
+    dialog = gtk_file_chooser_dialog_new(_("Choose an input filename"), GTK_WINDOW(ref),
+                                         GTK_FILE_CHOOSER_ACTION_OPEN,
+                                         _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                         _("_Open"), GTK_RESPONSE_ACCEPT,
+                                         NULL);
+
+    entry = GTK_ENTRY(g_object_get_data(ref, "input_filename"));
+    gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), gtk_entry_get_text(entry));
+
+    if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+        filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+
+        gtk_entry_set_text(GTK_ENTRY(entry), filename);
+
+        g_free(filename);
+
+    }
+
+    gtk_widget_destroy(dialog);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : button = coche dont le status vient de changer.              *
+*                ref    = espace de référencements inter-panneaux.            *
+*                                                                             *
+*  Description : Met à jour l'accès à la définition d'un fichier de sortie.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_output_need_toggle(GtkToggleButton *button, GObject *ref)
+{
+    gboolean state;                         /* Etat du bouton courant      */
+    GtkWidget *widget;                      /* Element dont l'accès change */
+
+    state = gtk_toggle_button_get_active(button);
+
+    widget = GTK_WIDGET(g_object_get_data(ref, "output_filename"));
+    if (widget != NULL)
+        gtk_widget_set_sensitive(widget, state);
+
+    widget = GTK_WIDGET(g_object_get_data(ref, "output_browser"));
+    if (widget != NULL)
+        gtk_widget_set_sensitive(widget, state);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : button = bouton d'édition de la sélection.                   *
+*                ref    = espace de référencement principal.                  *
+*                                                                             *
+*  Description : Sélectionne ou non un nouveau fichier de sortie.             *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_output_filename_browsing_clicked(GtkButton *button, GObject *ref)
+{
+    GtkWidget *dialog;                      /* Boîte à afficher            */
+    gchar *filename;                        /* Nom du fichier à intégrer   */
+    GtkEntry *entry;                        /* Zone de saisie à maj.       */
+
+    dialog = gtk_file_chooser_dialog_new(_("Choose an output filename"), GTK_WINDOW(ref),
+                                         GTK_FILE_CHOOSER_ACTION_SAVE,
+                                         _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                         _("_Save"), GTK_RESPONSE_ACCEPT,
+                                         NULL);
+
+    entry = GTK_ENTRY(g_object_get_data(ref, "output_filename"));
+    gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), gtk_entry_get_text(entry));
+
+    if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+        filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+
+        gtk_entry_set_text(GTK_ENTRY(entry), filename);
+
+        g_free(filename);
+
+    }
+
+    gtk_widget_destroy(dialog);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           SUIVI DE LA PHASE DE RECHERCHE                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : assistant = fenêtre d'assistance à compléter.                *
+*                ref       = espace de référencements inter-panneaux.         *
+*                                                                             *
+*  Description : Ajoute le panneau de suivi des opérations de recherche.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void register_search_display_panel(GtkAssistant *assistant, GObject *ref)
+{
+    GtkGrid *grid;                          /* Table de résumé             */
+    GtkWidget *pbar;                        /* barre de progression        */
+
+    grid = GTK_GRID(gtk_grid_new());
+    gtk_grid_set_column_spacing(grid, 8);
+    gtk_grid_set_row_spacing(grid, 8);
+
+    g_object_set(G_OBJECT(grid),
+                 "halign", GTK_ALIGN_CENTER,
+                 "valign", GTK_ALIGN_CENTER,
+                 "margin-bottom", 100, NULL);
+
+    /* Représentation des étapes */
+
+    init_rop_search_step(grid, 0, ref, "loading", _("Loading the input binary..."), NULL);
+
+    init_rop_search_step(grid, 1, ref, "format", _("Detecting the proper format..."), NULL);
+
+    pbar = gtk_progress_bar_new();
+    g_object_set(G_OBJECT(pbar), "valign", GTK_ALIGN_CENTER, NULL);
+    gtk_widget_show(pbar);
+
+    init_rop_search_step(grid, 2, ref, "gadgets", _("Looking for all ROP gadgets..."), pbar);
+
+    init_rop_search_step(grid, 3, ref, "final", _("Results:"), NULL);
+
+    /* Intégration */
+
+    gtk_assistant_append_page(assistant, GTK_WIDGET(grid));
+    gtk_assistant_set_page_title(assistant, GTK_WIDGET(grid), _("Search process"));
+    gtk_assistant_set_page_type(assistant, GTK_WIDGET(grid), GTK_ASSISTANT_PAGE_PROGRESS);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref  = espace de référencements inter-panneaux.              *
+*                key  = clef partielle d'accès aux composants concernés.      *
+*                info = message d'information annonçant la conclusion.        *
+*                pbar = éventuel composant de statut ou NULL.                 *
+*                                                                             *
+*  Description : Initialise une ligne de rapport quant aux opérations menées. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void init_rop_search_step(GtkGrid *grid, gint top, GObject *ref, const char *key, const char *info, GtkWidget *pbar)
+{
+    char *access;                           /* Chemin d'accès final        */
+    GtkWidget *render;                      /* Image de statut à afficher  */
+    GtkWidget *label;                       /* Etiquette d'indication      */
+
+    /* Icone de représentation */
+
+    access = strdup("process_");
+    access = stradd(access, key);
+    access = stradd(access, "_icon");
+
+    render = gtk_image_new_from_icon_name("dialog-question", GTK_ICON_SIZE_DND);
+    g_object_set_data(ref, access, render);
+    gtk_widget_show(render);
+    gtk_grid_attach(grid, render, 0, top, 1, 1);
+
+    free(access);
+
+    /* Désignation humaine d'indicatif */
+
+    access = strdup("process_");
+    access = stradd(access, key);
+    access = stradd(access, "_caption");
+
+    label = qck_create_label(ref, access, info);
+    gtk_grid_attach(grid, label, 1, top, 1, 1);
+
+    free(access);
+
+    /* Statut final */
+
+    access = strdup("process_");
+    access = stradd(access, key);
+    access = stradd(access, "_status");
+
+    if (pbar == NULL)
+    {
+        label = qck_create_label(ref, access, "done");
+        gtk_grid_attach(grid, label, 2, top, 1, 1);
+    }
+    else
+    {
+        g_object_set_data(ref, access, pbar);
+        gtk_grid_attach(grid, pbar, 2, top, 1, 1);
+    }
+
+    free(access);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref = espace de référencements inter-panneaux.               *
+*                                                                             *
+*  Description : Réinitialise tous les rapports de recherches imprimés.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void reset_rop_search_steps(GObject *ref)
+{
+    size_t i;                               /* Boucle de parcours          */
+    char *access;                           /* Chemin d'accès final        */
+    GObject *render;                        /* Image de statut à afficher  */
+    GtkLabel *label;                        /* Etiquette d'indication      */
+    GtkProgressBar *pbar;                   /* Barre à mettre à jour       */
+
+    static const char *icon_keys[] = { "loading", "format", "gadgets", "final" };
+    static const char *status_keys[] = { "loading", "format", "final" };
+
+    /* Réinitialisation des images */
+
+    for (i = 0; i < ARRAY_SIZE(icon_keys); i++)
+    {
+        access = strdup("process_");
+        access = stradd(access, icon_keys[i]);
+        access = stradd(access, "_icon");
+
+        render = G_OBJECT(g_object_get_data(ref, access));
+        g_object_set(render, "icon-name", "dialog-question", NULL);
+
+        free(access);
+
+    }
+
+    /* Statut final */
+
+    for (i = 0; i < ARRAY_SIZE(status_keys); i++)
+    {
+        access = strdup("process_");
+        access = stradd(access, status_keys[i]);
+        access = stradd(access, "_status");
+
+        label = GTK_LABEL(g_object_get_data(ref, access));
+        gtk_label_set_text(label, "");
+
+        free(access);
+
+    }
+
+    /* Progression des recherches */
+
+    pbar = GTK_PROGRESS_BAR(g_object_get_data(ref, "process_gadgets_status"));
+
+    gtk_progress_bar_set_fraction(pbar, 0.0);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : step = informations quant à l'étape avancée.                 *
+*                                                                             *
+*  Description : Affiche un message de statut quant aux recherches en cours.  *
+*                                                                             *
+*  Retour      : FALSE pour ne pas reprogrammer l'exécution de la tâche.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean print_status_of_rop_search_step(search_step *step)
+{
+    char *access;                           /* Chemin d'accès final        */
+    GObject *render;                        /* Image de statut à afficher  */
+    GtkLabel *status;                       /* Bilan à faire paraître      */
+
+    /* Icone de représentation */
+
+    access = strdup("process_");
+    access = stradd(access, step->key);
+    access = stradd(access, "_icon");
+
+    render = G_OBJECT(g_object_get_data(step->ref, access));
+    g_object_set(render, "icon-name", step->success ? "face-smile" : "face-sad", NULL);
+
+    free(access);
+
+    /* Mot de la fin */
+
+    if (step->msg != NULL)
+    {
+        access = strdup("process_");
+        access = stradd(access, step->key);
+        access = stradd(access, "_status");
+
+        status = GTK_LABEL(g_object_get_data(step->ref, access));
+        gtk_label_set_text(status, step->msg);
+
+        free(access);
+
+    }
+
+    /* Nettoyage final */
+
+    if (step->dynamic)
+        free(step->dmsg);
+
+    free(step);
+
+    return FALSE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref     = espace de référencements inter-panneaux.           *
+*                key     = clef partielle d'accès aux composants concernés.   *
+*                msg     = message d'information accompagnant la conclusion.  *
+*                success = indication quant à la réussite de l'opération.     *
+*                                                                             *
+*  Description : Affiche un message de statut quant aux recherches en cours.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void push_dyn_status_printing_of_rop_search_step(GObject *ref, const char *key, char *dmsg, bool success)
+{
+    search_step *step;                      /* Informations d'étape        */
+
+    step = (search_step *)calloc(1, sizeof(search_step));
+
+    step->ref = ref;
+
+    step->key = key;
+    step->dynamic = true;
+    step->dmsg = dmsg;
+    step->success = success;
+
+    g_idle_add((GSourceFunc)print_status_of_rop_search_step, step);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref     = espace de référencements inter-panneaux.           *
+*                key     = clef partielle d'accès aux composants concernés.   *
+*                msg     = message d'information accompagnant la conclusion.  *
+*                success = indication quant à la réussite de l'opération.     *
+*                                                                             *
+*  Description : Affiche un message de statut quant aux recherches en cours.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void push_status_printing_of_rop_search_step(GObject *ref, const char *key, const char *msg, bool success)
+{
+    search_step *step;                      /* Informations d'étape        */
+
+    step = (search_step *)calloc(1, sizeof(search_step));
+
+    step->ref = ref;
+
+    step->key = key;
+    step->dynamic = false;
+    step->msg = msg;
+    step->success = success;
+
+    g_idle_add((GSourceFunc)print_status_of_rop_search_step, step);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : step = informations quant à l'étape avancée.                 *
+*                                                                             *
+*  Description : Actualise la barre de progression affichée.                  *
+*                                                                             *
+*  Retour      : FALSE pour ne pas reprogrammer l'exécution de la tâche.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean update_progress_bar_fraction(search_step *step)
+{
+    GtkProgressBar *pbar;                   /* Barre à mettre à jour       */
+
+    pbar = GTK_PROGRESS_BAR(g_object_get_data(step->ref, "process_gadgets_status"));
+
+    gtk_progress_bar_set_fraction(pbar, step->fraction);
+
+    /* Nettoyage final */
+
+    free(step);
+
+    return FALSE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref      = espace de référencements inter-panneaux.          *
+*                fraction = avancée globale du désassemblage en cours.        *
+*                                                                             *
+*  Description : Lance l'actualisation de la barre de progression affichée.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void push_new_progress_fraction(GObject *ref, gdouble fraction)
+{
+    search_step *step;                      /* Informations d'étape        */
+
+    step = (search_step *)calloc(1, sizeof(search_step));
+
+    step->ref = ref;
+
+    step->fraction = fraction;
+
+    g_idle_add((GSourceFunc)update_progress_bar_fraction, step);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : step = informations quant à l'étape avancée.                 *
+*                                                                             *
+*  Description : Enregistre une référence vers les gadgets trouvés.           *
+*                                                                             *
+*  Retour      : FALSE pour ne pas reprogrammer l'exécution de la tâche.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean register_found_rop_gadgets(search_step *step)
+{
+    GtkComboBoxText *combo;                 /* Sélection d'une catégorie   */
+    GtkTreeView *treeview;                  /* Arborescence à actualiser   */
+    GtkTreeModelFilter *filter;             /* Modèle de gestion associé   */
+    size_t i;                               /* Boucle de parcours          */
+    GtkWidget *page;                        /* Page de la partie terminée  */
+
+    /* Affichage des résulats */
+
+    if (step->format != NULL)
+    {
+        combo = GTK_COMBO_BOX_TEXT(g_object_get_data(step->ref, "filter_cat"));
+
+        treeview = GTK_TREE_VIEW(g_object_get_data(step->ref, "treeview"));
+        filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(treeview));
+
+        for (i = 0; i < step->count; i++)
+            add_new_gadgets_for_category(step->format,
+                                         combo, GTK_TREE_STORE(gtk_tree_model_filter_get_model(filter)),
+                                         step->list[i].category, step->list[i].gadgets, step->list[i].count);
+
+        if (step->list != NULL)
+            free(step->list);
+
+    }
+
+    /* Déverrouillage des accès à la suite */
+
+    page = gtk_assistant_get_nth_page(GTK_ASSISTANT(step->ref), 1);
+
+    gtk_assistant_set_page_complete(GTK_ASSISTANT(step->ref), page, TRUE);
+
+    /* Nettoyage final */
+
+    free(step);
+
+    return FALSE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref    = espace de référencements inter-panneaux.            *
+*                format = format binaire chargé.                              *
+*                list   = liste de liste de gadgets pour ROP.                 *
+*                count  = taille de cette liste.                              *
+*                                                                             *
+*  Description : Lance une conservation des gadgets trouvés.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void push_found_rop_gadgets(GObject *ref, GBinFormat *format, found_rop_list *list, size_t count)
+{
+    search_step *step;                      /* Informations d'étape        */
+
+    step = (search_step *)calloc(1, sizeof(search_step));
+
+    step->ref = ref;
+
+    step->format = format;
+    step->list = list;
+    step->count = count;
+
+    g_idle_add((GSourceFunc)register_found_rop_gadgets, step);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref = espace de référencements inter-panneaux.               *
+*                                                                             *
+*  Description : Charge un format binaire interne déjà chargé.                *
+*                                                                             *
+*  Retour      : Nouveau format au contenu à fouiller ou NULL en cas d'échec. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBinFormat *load_internal_format_for_rop_gadgets(GObject *ref)
+{
+    GBinFormat *result;                     /* Format chargé à retourner   */
+    GtkComboBox *combo;                     /* Composant de sélection      */
+    GtkTreeIter iter;                       /* Tête de lecture à placer    */
+    GtkTreeModel *model;                    /* Modèle de gestion           */
+    GLoadedBinary *binary;                  /* Binaire chargé à utiliser   */
+
+    combo = GTK_COMBO_BOX(g_object_get_data(ref, "input_binary"));
+
+    if (!gtk_combo_box_get_active_iter(combo, &iter))
+    {
+        push_status_printing_of_rop_search_step(ref, "loading", _("unable to get the current binary"), false);
+        return NULL;
+    }
+
+    model = gtk_combo_box_get_model(combo);
+    gtk_tree_model_get(model, &iter, CPB_BINARY, &binary, -1);
+
+    push_status_printing_of_rop_search_step(ref, "loading", _("done"), true);
+
+    result = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+
+    push_status_printing_of_rop_search_step(ref, "format", _("already loaded"), true);
+
+    g_object_ref(G_OBJECT(result));
+    g_object_unref(G_OBJECT(binary));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref = espace de référencements inter-panneaux.               *
+*                                                                             *
+*  Description : Charge un format binaire externe.                            *
+*                                                                             *
+*  Retour      : Nouveau format au contenu à fouiller ou NULL en cas d'échec. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GBinFormat *load_external_format_for_rop_gadgets(GObject *ref)
+{
+    GBinFormat *result;                     /* Format chargé à retourner   */
+    GtkEntry *entry;                        /* Zone de saisie de texte     */
+    const gchar *filename;                  /* Nom du fichier à charger    */
+    GBinContent *content;                   /* Contenu binaire chargé      */
+    const char *target;                     /* Sous-traitance requise      */
+    const char *desc;                       /* Description humaine associée*/
+
+    /* Récupération du nom de fichier */
+
+    entry = GTK_ENTRY(g_object_get_data(ref, "input_filename"));
+
+    filename = gtk_entry_get_text(entry);
+
+    /* Récupération du contenu binaire */
+
+    content = g_binary_content_new_from_file(filename);
+    if (content == NULL)
+    {
+        push_status_printing_of_rop_search_step(ref, "loading", _("unable to get the binary content"), false);
+        goto leffrg_error;
+    }
+
+    push_status_printing_of_rop_search_step(ref, "loading", _("done"), true);
+
+    /* Récupération du format de fichier associé */
+
+    target = find_matching_format(content);
+    desc = get_binary_format_name(target);
+
+    if (desc == NULL)
+    {
+        g_object_unref(G_OBJECT(content));
+        push_status_printing_of_rop_search_step(ref, "format", _("unknown binary format"), false);
+        goto leffrg_error;
+    }
+
+    result = load_new_named_format(target, content);
+
+    if (result == NULL)
+    {
+        push_status_printing_of_rop_search_step(ref, "format", _("error while loading the binary"), false);
+        goto leffrg_error;
+    }
+
+    push_status_printing_of_rop_search_step(ref, "format", desc, true);
+
+    return result;
+
+ leffrg_error:
+
+    return NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref = espace de référencements inter-panneaux.               *
+*                                                                             *
+*  Description : Procède à la recherche de gadgets de façon séparée.          *
+*                                                                             *
+*  Retour      : ?                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gpointer look_for_rop_gadgets(GObject *ref)
+{
+    GtkToggleButton *internal;              /* Bouton de sélection interne */
+    gboolean state;                         /* Etat du bouton courant      */
+    GBinFormat *format;                     /* Format du binaire à traiter */
+    found_rop_list *list;                   /* Liste de gadgets ROP trouvés*/
+    size_t count;                           /* Nombre de ces listes        */
+    size_t found;                           /* Nombre de gadgets trouvés   */
+    size_t i;                               /* Boucle de parcours          */
+    char *msg;                              /* Message final à faire passer*/
+
+    internal = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "loaded_as_input"));
+    state = gtk_toggle_button_get_active(internal);
+
+    if (state)
+        format = load_internal_format_for_rop_gadgets(ref);
+    else
+        format = load_external_format_for_rop_gadgets(ref);
+
+    if (format == NULL) goto lfrg_unlock;
+
+    list = list_all_gadgets(format, 7, push_new_progress_fraction, ref, &count);
+
+    push_status_printing_of_rop_search_step(ref, "gadgets", NULL, true);
+
+    found = 0;
+
+    for (i = 0; i < count; i++)
+        found += list[i].count;
+
+    switch (found)
+    {
+        case 0:
+            msg = strdup(_("No ROP gadget has been found."));
+            break;
+
+        case 1:
+            msg = strdup(_("1 ROP gadget has been found."));
+            break;
+
+        default:
+            asprintf(&msg, _("%zu gadgets have been found."), found);
+            break;
+
+    }
+
+    push_dyn_status_printing_of_rop_search_step(ref, "final", msg, count > 0);
+
+ lfrg_unlock:
+
+    push_found_rop_gadgets(ref, format, list, count);
+
+    return NULL;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         MISE EN FORME DES GADGETS PRESENTS                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : assistant = fenêtre d'assistance à compléter.                *
+*                ref       = espace de référencements inter-panneaux.         *
+*                                                                             *
+*  Description : Ajoute le panneau de sélection des gadgets ROP identifiés.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void register_rop_list_panel(GtkAssistant *assistant, GObject *ref)
+{
+    GtkWidget *vbox;                        /* Support principal           */
+    GtkWidget *hbox;                        /* Petite barre supérieure     */
+    GtkWidget *label;                       /* Etiquette d'indication      */
+    GtkWidget *comboboxentry;               /* Liste de sélection simple   */
+    GtkWidget *vseparator;                  /* Barre de séparation         */
+    GtkWidget *filter;                      /* Zone de recherche           */
+    GtkWidget *scrollwnd;                   /* Support défilant            */
+    GtkTreeStore *store;                    /* Modèle de gestion           */
+    GtkTreeModel *model;                    /* Modèle de gestion supérieur */
+    GtkWidget *treeview;                    /* Affichage de la liste       */
+    GtkCellRenderer *renderer;              /* Moteur de rendu de colonne  */
+    GtkTreeViewColumn *column;              /* Colonne de la liste         */
+
+    vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+    gtk_widget_show(vbox);
+    gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+
+    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+    gtk_widget_show(hbox);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+
+    /* Choix de la catégorie */
+
+    label = gtk_label_new(_("ROP selection:"));
+    gtk_widget_show(label);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+    comboboxentry = qck_create_combobox(ref, "filter_cat", G_CALLBACK(on_rop_gadgets_category_changed), ref);
+    gtk_box_pack_start(GTK_BOX(hbox), comboboxentry, FALSE, TRUE, 0);
+
+    /* Séparation fine */
+
+    vseparator = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
+    gtk_widget_show(vseparator);
+    gtk_box_pack_start(GTK_BOX(hbox), vseparator, FALSE, FALSE, 0);
+
+    /* Espace de recherche */
+
+    label = gtk_label_new(_("Filter:"));
+    gtk_widget_show(label);
+    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+    filter = gtk_search_entry_new();
+    g_object_set_data(ref, "filter_rop", filter);
+    gtk_widget_set_tooltip_text(filter, _("Filter gadgets using POSIX extended regular expressions"));
+
+    g_signal_connect(filter, "search-changed", G_CALLBACK(on_rop_gadgets_filter_changed), ref);
+    gtk_widget_show(filter);
+    gtk_widget_set_hexpand(filter, TRUE);
+
+    gtk_box_pack_start(GTK_BOX(hbox), filter, TRUE, TRUE, 0);
+
+    /* Liste arborescente ou linéaire */
+
+    scrollwnd = gtk_scrolled_window_new(NULL, NULL);
+    gtk_widget_show(scrollwnd);
+    gtk_box_pack_start(GTK_BOX(vbox), scrollwnd, TRUE, TRUE, 0);
+
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN);
+
+    store = gtk_tree_store_new(FRG_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+                               G_TYPE_STRING, G_TYPE_STRING);
+
+    model = gtk_tree_model_filter_new(GTK_TREE_MODEL(store), NULL);
+
+    gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(model),
+                                           (GtkTreeModelFilterVisibleFunc)filter_visible_rop_gadgets,
+                                           ref, NULL);
+
+    treeview = gtk_tree_view_new_with_model(model);
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE);
+    gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(treeview), TRUE);
+
+    g_object_set_data(ref, "treeview", treeview);
+
+    gtk_widget_show(treeview);
+    gtk_container_add(GTK_CONTAINER(scrollwnd), treeview);
+
+    /* Cellules d'affichage */
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(_("Address"), renderer,
+                                                      "markup", FRG_VIRTUAL,
+                                                      NULL);
+    gtk_tree_view_column_set_sort_column_id(column, FRG_VIRTUAL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(_("Gadgets"), renderer,
+                                                      "markup", FRG_CONTENT,
+                                                      NULL);
+    gtk_tree_view_column_set_sort_column_id(column, FRG_CONTENT);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+    /* Intégration */
+
+    gtk_assistant_append_page(assistant, vbox);
+    gtk_assistant_set_page_title(assistant, vbox, _("ROP Gadgets"));
+    gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_CONFIRM);
+
+    gtk_assistant_set_page_complete(assistant, vbox, TRUE);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : combo = composant de choix contenant le filtre brut.         *
+*                ref   = espace de référencements inter-panneaux.             *
+*                                                                             *
+*  Description : Lance l'actualisation du filtrage des gadgets ROP.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_rop_gadgets_category_changed(GtkComboBox *combo, GObject *ref)
+{
+    GtkTreeView *treeview;                  /* Arborescence à actualiser   */
+    GtkTreeModelFilter *filter;             /* Modèle de gestion associé   */
+
+    treeview = GTK_TREE_VIEW(g_object_get_data(ref, "treeview"));
+
+    filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(treeview));
+
+    gtk_tree_model_filter_refilter(filter);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : entry = entrée de texte contenant le filtre brut.            *
+*                ref   = espace de référencements inter-panneaux.             *
+*                                                                             *
+*  Description : Lance l'actualisation du filtrage des gadgets ROP.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_rop_gadgets_filter_changed(GtkSearchEntry *entry, GObject *ref)
+{
+    regex_t preg;                           /* Expression régulière de test*/
+    const gchar *text;                      /* Texte de l'utilisateur      */
+    int ret;                                /* Bilan de mise en place      */
+    GdkRGBA error;                          /* Couleur d'erreur            */
+    GtkTreeView *treeview;                  /* Arborescence à actualiser   */
+    GtkTreeModelFilter *filter;             /* Modèle de gestion associé   */
+
+    text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+    if (text[0] != '\0')
+    {
+        ret = regcomp(&preg, text, REG_EXTENDED);
+
+        if (ret != 0)
+        {
+            error.red = 1.0;
+            error.green = 0.0;
+            error.blue = 0.0;
+            error.alpha = 1.0;
+            gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error);
+
+            return;
+
+        }
+
+        regfree(&preg);
+
+    }
+
+    gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL);
+
+    treeview = GTK_TREE_VIEW(g_object_get_data(ref, "treeview"));
+
+    filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(treeview));
+
+    gtk_tree_model_filter_refilter(filter);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : model = gestionnaire des lignes et colonnes affichées.       *
+*                iter  = ligne concernée par l'analyse à mener.               *
+*                ref   = espace de référencements inter-panneaux.             *
+*                                                                             *
+*  Description : Détermine la visibilité de tel ou tel gadget ROP.            *
+*                                                                             *
+*  Retour      : Indication d'affichage pour une ligne donnée.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean filter_visible_rop_gadgets(GtkTreeModel *model, GtkTreeIter *iter, GObject *ref)
+{
+    gboolean result;                        /* Visibilité à retourner      */
+    gchar *category;                        /* Catégorie d'appartenance    */
+    gchar *raw;                             /* Brut pour recherche         */
+    GtkComboBoxText *combo;                 /* Sélection à choix multiples */
+    gchar *selected;                        /* Texte de l'utilisateur #1   */
+    GtkEntry *entry;                        /* Zone de texte à utiliser    */
+    const gchar *text;                      /* Texte de l'utilisateur #2   */
+    regex_t preg;                           /* Expression régulière de test*/
+    int ret;                                /* Bilan de mise en place      */
+    regmatch_t match;                       /* Récupération des trouvailles*/
+
+    result = TRUE;
+
+    gtk_tree_model_get(model, iter, FRG_CATEGORY, &category, FRG_RAW, &raw, -1);
+
+    if (category == NULL || raw == NULL) return FALSE;
+
+    /* Filtre sur les catégories */
+
+    combo = g_object_get_data(ref, "filter_cat");
+
+ 	selected = gtk_combo_box_text_get_active_text(combo);
+
+    result &= (g_strcmp0(category, selected) == 0);
+
+    g_free(selected);
+
+    /* Filtre sur les gadgets ROP */
+
+    entry = g_object_get_data(ref, "filter_rop");
+
+    text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+    ret = regcomp(&preg, text, REG_EXTENDED);
+    result &= (ret == 0);
+
+    if (ret == 0)
+    {
+        ret = regexec(&preg, raw, 1, &match, 0);
+        result &= (ret != REG_NOMATCH);
+
+        regfree(&preg);
+
+    }
+
+    /* Nettoyages finaux */
+
+    g_free(category);
+    g_free(raw);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format   = format binaire chargé sur lequel se reposer.      *
+*                combo    = composant de sélection des catégories à compléter.*
+*                store    = modèle de gestionnaire pour la liste affichée.    *
+*                category = représentation du binaire chargé en mémoire.      *
+*                gadgets  = liste de listes d'instructions de ROP.            *
+*                count    = taille de cette liste.                            *
+*                                                                             *
+*  Description : Ajoute de nouvelles chaînes de gadgets localisées.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void add_new_gadgets_for_category(GBinFormat *format, GtkComboBoxText *combo, GtkTreeStore *store, const char *category, GArchInstruction **gadgets, size_t count)
+{
+    const char *target;                     /* Sous-traitance requise      */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    MemoryDataSize msize;                   /* Taille du bus d'adresses    */
+    const bin_t *content;                   /* Contenu binaire global      */
+    GCodeBuffer *buffer;                    /* Tampon de rassemblement     */
+    size_t i;                               /* Boucle de parcours          */
+    GArchInstruction *instr;                /* Elément de liste de gadgets */
+    GBufferLine *line;                      /* Ligne présente à l'adresse  */
+    char *raw_virtual;                      /* Transcription pour export   */
+    char *virtual;                          /* Transcription d'adresse     */
+    char *partial_raw;                      /* Contenu de la ligne visée   */
+    char *partial_markup;                   /* Contenu de la ligne visée   */
+    char *content_raw;                      /* Contenu assemblé de chaîne  */
+    char *content_markup;                   /* Contenu assemblé de chaîne  */
+    GtkTreeIter iter;                       /* Point d'insertion           */
+
+    /* Définition de l'écosystème nécessaire */
+
+    target = g_exe_format_get_target_machine(G_EXE_FORMAT(format));
+    proc = get_arch_processor_for_type(target);
+
+    msize = g_arch_processor_get_memory_size(proc);
+
+    g_object_unref(G_OBJECT(proc));
+
+    content = g_binary_format_get_content(G_BIN_FORMAT(format), NULL);
+
+    /* Conversion en contenu textuel */
+
+    buffer = g_code_buffer_new(BLC_ASSEMBLY);
+
+    for (i = 0; i < count; i++)
+    {
+        /* Parcours des différentes lignes */
+
+        content_raw = NULL;
+        content_markup = NULL;
+
+        for (instr = gadgets[i]; instr != NULL; instr = g_arch_instruction_get_next_iter(gadgets[i], instr, ~0))
+        {
+            line = g_arch_instruction_print(instr, buffer, msize, content, ASX_INTEL);
+            if (line == NULL) continue;
+
+            if (instr == gadgets[i])
+            {
+                raw_virtual = g_buffer_line_get_text(line, BLC_VIRTUAL, BLC_VIRTUAL + 1, false);
+                virtual = g_buffer_line_get_text(line, BLC_VIRTUAL, BLC_VIRTUAL + 1, true);
+            }
+
+            partial_raw = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, false);
+            partial_markup = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true);
+
+            if (content_raw != NULL)
+                content_raw = stradd(content_raw, " ; ");
+
+            content_raw = stradd(content_raw, partial_raw);
+
+            if (content_markup != NULL)
+                content_markup = stradd(content_markup, " ; ");
+
+            content_markup = stradd(content_markup, partial_markup);
+
+            free(partial_raw);
+            free(partial_markup);
+
+        }
+
+        /* Insertion finale */
+
+        gtk_tree_store_append(store, &iter, NULL);
+
+        gtk_tree_store_set(store, &iter,
+                           FRG_CATEGORY, category,
+                           FRG_RAW_VIRTUAL, raw_virtual,
+                           FRG_RAW, content_raw,
+                           FRG_VIRTUAL, virtual,
+                           FRG_CONTENT, content_markup,
+                           -1);
+
+        /* Nettoyage de la mémoire */
+
+        free(raw_virtual);
+        free(virtual);
+        free(content_raw);
+        free(content_markup);
+
+    }
+
+    g_object_unref(G_OBJECT(buffer));
+
+    /* Rajout de la catégorie et filtre au besoin */
+
+    gtk_combo_box_text_append_text(combo, category);
+
+    if (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)) == -1)
+        gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
+
+}
diff --git a/plugins/ropgadgets/select.h b/plugins/ropgadgets/select.h
new file mode 100644
index 0000000..9e18ddd
--- /dev/null
+++ b/plugins/ropgadgets/select.h
@@ -0,0 +1,40 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * goto.h - prototypes pour la boîte de dialogue pour les sauts à une adresse donnée
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _DIALOGS_GOTOX_H
+#define _DIALOGS_GOTOX_H
+
+
+#include <gtk/gtk.h>
+
+
+#include <analysis/binary.h>
+
+
+
+/* Crée et affiche un assistant de sélection de gadgets ROP. */
+void run_rop_finder_assistant(GObject *, GtkWindow *);
+
+
+
+#endif  /* _DIALOGS_GOTOX_H */
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 6ed6804..2e7b46d 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -490,7 +490,7 @@ bool load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons
 
 
 
-    mrange_t range;                             /* Couverture de l'instruction */
+    mrange_t range;                         /* Couverture de l'instruction */
 
 
     vmpa2t sym_addr;                        /* Adresse de nouveau symbole  */
diff --git a/src/arch/arm/v7/opdefs/pop_A88131.d b/src/arch/arm/v7/opdefs/pop_A88131.d
index ef5ab25..5229af9 100644
--- a/src/arch/arm/v7/opdefs/pop_A88131.d
+++ b/src/arch/arm/v7/opdefs/pop_A88131.d
@@ -39,7 +39,6 @@
 
         //if BitCount(registers) < 1 then UNPREDICTABLE;
         //if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        chk_call DefineAsReturn(1)
 
     }
 
@@ -61,7 +60,6 @@
 
         //if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
         //if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        chk_call DefineAsReturn(1)
 
     }
 
@@ -83,7 +81,7 @@
     @rules {
 
         //if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
-        chk_call DefineAsReturn(1)
+        if (Rt == '1111') ; chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/pop_A88132.d b/src/arch/arm/v7/opdefs/pop_A88132.d
index 89c51c9..1762b45 100644
--- a/src/arch/arm/v7/opdefs/pop_A88132.d
+++ b/src/arch/arm/v7/opdefs/pop_A88132.d
@@ -40,7 +40,7 @@
 
         //if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
         //if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
-        chk_call DefineAsReturn(1)
+        if (register_list & 0x8000) ; chk_call DefineAsReturn(1)
 
     }
 
@@ -63,7 +63,7 @@
     @rules {
 
         //if t == 13 then UNPREDICTABLE;
-        chk_call DefineAsReturn(1)
+        if (Rt == '1111') ; chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/processor.h b/src/arch/processor.h
index d650266..a856942 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -74,7 +74,17 @@ MemoryDataSize g_arch_processor_get_instruction_size(const GArchProcessor *);
 GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *, GProcContext *, const bin_t *, off_t *, off_t, vmpa_t, GBinFormat *) __attribute__ ((deprecated));
 
 /* Désassemble une instruction dans un flux de données. */
-GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *, GProcContext *, const bin_t *, vmpa2t *, phys_t);
+GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *, GProcContext *, const bin_t *, vmpa2t *, phys_t) __attribute__ ((deprecated));
+
+
+
+#define g_arch_processor_disassemble_nextgen(_proc, _ctx, _cnt, _pos)               \
+    ({                                                                              \
+        const bin_t *_bin_data;                                                     \
+        off_t _bin_length;                                                          \
+        _bin_data = g_binary_content_get(_cnt, &_bin_length);                       \
+        g_arch_processor_disassemble(_proc, _ctx, _bin_data, _pos, _bin_length);    \
+    })
 
 
 
diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c
index ad4c078..b10b007 100644
--- a/src/arch/vmpa.c
+++ b/src/arch/vmpa.c
@@ -247,6 +247,32 @@ void advance_vmpa(vmpa2t *addr, phys_t qty)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : addr = élément à modifier.                                   *
+*                qty  = quantité d'unités de décallage.                       *
+*                                                                             *
+*  Description : Décalle une position d'une certaine quantité.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void deminish_vmpa(vmpa2t *addr, phys_t qty)
+{
+    /* On choisit de ne pas vérifier les débordements */
+
+    if (addr->physical != VMPA_NO_PHYSICAL)
+        addr->physical -= qty;
+
+    if (addr->virtual != VMPA_NO_VIRTUAL)
+        addr->virtual -= qty;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : a = première élément à venir consulter.                      *
 *                b = second élément à traiter en parallèle.                   *
 *                                                                             *
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index 3e0d35c..4611ebf 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -111,6 +111,9 @@ int cmp_vmpa(const vmpa2t *, const vmpa2t *);
 /* Décalle une position d'une certaine quantité. */
 void advance_vmpa(vmpa2t *, phys_t);
 
+/* Décalle une position d'une certaine quantité. */
+void deminish_vmpa(vmpa2t *, phys_t);
+
 /* Calcule au mieux la distance entre deux coordonnées. */
 phys_t compute_vmpa_diff(const vmpa2t *, const vmpa2t *);
 
diff --git a/src/gui/menus/Makefile.am b/src/gui/menus/Makefile.am
index fcebcf2..d932141 100644
--- a/src/gui/menus/Makefile.am
+++ b/src/gui/menus/Makefile.am
@@ -8,6 +8,7 @@ libguimenus_la_SOURCES =				\
 	file.h file.c						\
 	help.h help.c						\
 	menubar.h menubar.c					\
+	plugins.h plugins.c					\
 	project.h project.c					\
 	view.h view.c
 
diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c
index cc69e0d..1fc1b6f 100644
--- a/src/gui/menus/menubar.c
+++ b/src/gui/menus/menubar.c
@@ -30,6 +30,7 @@
 #include "edition.h"
 #include "file.h"
 #include "help.h"
+#include "plugins.h"
 #include "project.h"
 #include "view.h"
 #include "../editem-int.h"
@@ -47,6 +48,7 @@ struct _GMenuBar
     GtkWidget *project;                     /* Menu "Projet"               */
     GtkWidget *binary;                      /* Menu "Binaire"              */
     GtkWidget *debug;                       /* Menu "Débogage"             */
+    GtkWidget *plugins;                     /* Menu "Greffons"             */
     GtkWidget *help;                        /* Menu "Aide"                 */
 
 };
@@ -239,6 +241,11 @@ GEditorItem *g_menu_bar_new(GObject *ref, GtkAccelGroup *accgroup)
     result->debug = build_menu_debug(ref, accgroup);
     gtk_container_add(GTK_CONTAINER(item->widget), result->debug);
 
+    /* Greffons */
+
+    result->plugins = build_menu_plugins(ref, accgroup);
+    gtk_container_add(GTK_CONTAINER(item->widget), result->plugins);
+
     /* Aide */
 
     result->help = build_menu_help(ref, accgroup);
diff --git a/src/gui/menus/plugins.c b/src/gui/menus/plugins.c
new file mode 100644
index 0000000..6967665
--- /dev/null
+++ b/src/gui/menus/plugins.c
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plugins.c - gestion du menu 'Greffons'
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "plugins.h"
+
+
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "../../gtkext/easygtk.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref      = espace de référencement global.                   *
+*                accgroup = groupe d'accélérateurs pour les menus.            *
+*                                                                             *
+*  Description : Construit le menu "Aide".                                    *
+*                                                                             *
+*  Retour      : Panneau de menus mis en place.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkWidget *build_menu_plugins(GObject *ref, GtkAccelGroup *accgroup)
+{
+    GtkWidget *result;                      /* Support à retourner         */
+    GtkWidget *menubar;                     /* Support pour éléments       */
+
+    result = gtk_menu_item_new_with_mnemonic(_("_Plugins"));
+    gtk_widget_show(result);
+
+    menubar = gtk_menu_new();
+    g_object_set_data(ref, "menubar_plugins", G_OBJECT(menubar));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(result), menubar);
+
+    return result;
+
+}
diff --git a/src/gui/menus/plugins.h b/src/gui/menus/plugins.h
new file mode 100644
index 0000000..9d83f4d
--- /dev/null
+++ b/src/gui/menus/plugins.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plugins.h - prototypes pour la gestion du menu 'Greffons'
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _GUI_MENUS_PLUGINS_H
+#define _GUI_MENUS_PLUGINS_H
+
+
+#include <gtk/gtk.h>
+
+
+
+/* Construit le menu "Aide". */
+GtkWidget *build_menu_plugins(GObject *, GtkAccelGroup *);
+
+
+
+#endif  /* _GUI_MENUS_PLUGINS_H */
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c
index 70fc66a..f85eee7 100644
--- a/src/plugins/pglist.c
+++ b/src/plugins/pglist.c
@@ -197,7 +197,7 @@ void browse_directory_for_plugins(plugins_list *list, const char *dir)
 
         else
         {
-            plugin = g_plugin_module_new(filename);
+            plugin = g_plugin_module_new(filename, _list.ref);
 
             if (plugin != NULL)
                 add_plugin_to_main_list(plugin);
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 41cc535..1f4e17e 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -37,7 +37,7 @@
 
 
 /* Prend acte du [dé]chargement du greffon. */
-typedef bool (* pg_management_fc) (GPluginModule *);
+typedef bool (* pg_management_fc) (GPluginModule *, GObject *);
 
 /* Indique si le format peut être pris en charge ici. */
 typedef bool (* pg_format_is_matching) (const GPluginModule *, GBinContent **);
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 89a8040..65f3cc6 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -113,7 +113,7 @@ static void g_plugin_module_init(GPluginModule *plugin)
 static void g_plugin_module_dispose(GPluginModule *plugin)
 {
     if (plugin->exit != NULL)
-        plugin->exit(plugin);
+        plugin->exit(plugin, NULL /* FIXME */);
 
     if (plugin->module != NULL)
         g_module_close(plugin->module);
@@ -147,6 +147,7 @@ static void g_plugin_module_finalize(GPluginModule *plugin)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : filename = nom du fichier à charger.                         *
+*                ref      = espace de référencement global.                   *
 *                                                                             *
 *  Description : Crée un module pour un greffon donné.                        *
 *                                                                             *
@@ -156,7 +157,7 @@ static void g_plugin_module_finalize(GPluginModule *plugin)
 *                                                                             *
 ******************************************************************************/
 
-GPluginModule *g_plugin_module_new(const gchar *filename)
+GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 {
     GPluginModule *result;                  /* Structure à retourner       */
     plugin_abi_version_t current;           /* Version de l'ABI actuelle   */
@@ -304,7 +305,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
     if (result->init != NULL)
     {
-        if (!result->init(result))
+        if (!result->init(result, ref))
         {
             log_variadic_message(LMT_ERROR,
                                  _("Plugin '%s' failed to load itself..."), filename);
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index d571659..b974ca8 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -53,7 +53,7 @@ typedef struct _GPluginModuleClass GPluginModuleClass;
 GType g_plugin_module_get_type(void);
 
 /* Crée un module pour un greffon donné. */
-GPluginModule *g_plugin_module_new(const gchar *);
+GPluginModule *g_plugin_module_new(const gchar *, GObject *);
 
 /* Fournit la description du greffon dans son intégralité. */
 const plugin_interface *g_plugin_module_get_interface(const GPluginModule *);
-- 
cgit v0.11.2-87-g4458