From 0b6e87de0d4313f8ef31907bc48ce4d7f7749738 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 9 Oct 2016 13:57:58 +0200
Subject: Loaded all Dex pool items using several threads.

---
 ChangeLog                           |  23 ++++
 src/format/dex/Makefile.am          |   1 +
 src/format/dex/dex.c                |   9 +-
 src/format/dex/loading.c            | 240 ++++++++++++++++++++++++++++++++++++
 src/format/dex/loading.h            |  61 +++++++++
 src/format/dex/pool.c               | 120 +++++++++++++-----
 src/format/dex/pool.h               |   6 +-
 src/format/elf/symbols.c            |   2 +-
 src/format/mangling/dex/type_gram.y |  32 +++--
 src/format/mangling/dex/type_tok.l  |  32 ++---
 10 files changed, 467 insertions(+), 59 deletions(-)
 create mode 100644 src/format/dex/loading.c
 create mode 100644 src/format/dex/loading.h

diff --git a/ChangeLog b/ChangeLog
index 7fd4ee5..338dec9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 16-10-09  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/format/dex/Makefile.am:
+	Add the 'loading.[ch]' files to libformatdex_la_SOURCES.
+
+	* src/format/dex/dex.c:
+	Update code.
+
+	* src/format/dex/loading.c:
+	* src/format/dex/loading.h:
+	New entries: load all Dex pool items using several threads.
+
+	* src/format/dex/pool.c:
+	* src/format/dex/pool.h:
+	Update code.
+
+	* src/format/elf/symbols.c:
+	Cosmetic.
+
+	* src/format/mangling/dex/type_gram.y:
+	* src/format/mangling/dex/type_tok.l:
+	Make the parser reentrant to deal with Dex types and threads.
+
+16-10-09  Cyrille Bagard <nocbos@gmail.com>
+
 	* configure.ac:
 	Remove the Makefile from the 'src/gtkext/graph/nodes' directory.
 
diff --git a/src/format/dex/Makefile.am b/src/format/dex/Makefile.am
index 7a2416f..28f8e73 100755
--- a/src/format/dex/Makefile.am
+++ b/src/format/dex/Makefile.am
@@ -6,6 +6,7 @@ libformatdex_la_SOURCES =				\
 	dex-int.h dex-int.c					\
 	dex.h dex.c							\
 	dex_def.h							\
+	loading.h loading.c					\
 	method.h method.c					\
 	pool.h pool.c
 
diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c
index 582390a..d02111c 100755
--- a/src/format/dex/dex.c
+++ b/src/format/dex/dex.c
@@ -248,6 +248,7 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatus
     GDexFormat *result;                     /* Structure à retourner       */
     GBinFormat *base;                       /* Version basique du format   */
     vmpa2t pos;                             /* Position de tête de lecture */
+    wgroup_id_t gid;                        /* Identifiant pour les tâches */
 
     result = g_object_new(G_TYPE_DEX_FORMAT, NULL);
 
@@ -265,13 +266,15 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatus
     /* TODO : vérifier que les *_id ne se chevauchent pas */
 
 
-    if (!load_all_dex_types(result, status))
+    gid = g_work_queue_define_work_group(get_work_queue());
+
+    if (!load_all_dex_types(result, gid, status))
         goto gdfn_error;
 
-    if (!load_all_dex_fields(result, status))
+    if (!load_all_dex_fields(result, gid, status))
         goto gdfn_error;
 
-    if (!load_all_dex_classes(result, status))
+    if (!load_all_dex_classes(result, gid, status))
         goto gdfn_error;
 
     if (!g_binary_format_complete_loading(base, status))
diff --git a/src/format/dex/loading.c b/src/format/dex/loading.c
new file mode 100644
index 0000000..a5b675d
--- /dev/null
+++ b/src/format/dex/loading.c
@@ -0,0 +1,240 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * loading.c - chargements parallèles des éléments de la table globale du format Dex
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "loading.h"
+
+
+#include <i18n.h>
+
+
+#include "pool.h"
+#include "../../glibext/delayed-int.h"
+#include "../../gui/panels/log.h"
+
+
+
+/* Fraction de routines à limiter (instance) */
+struct _GDexLoading
+{
+    GDelayedWork parent;                    /* A laisser en premier        */
+
+    GDexFormat *format;                     /* Format à faire évoluer      */
+
+    dex_loading_cb callback;                /* Routine de traitement finale*/
+    uint32_t begin;                         /* Point de départ du parcours */
+    uint32_t end;                           /* Point d'arrivée exclu       */
+
+    activity_id_t id;                       /* Identifiant pour messages   */
+
+    bool *status;                           /* Bilan global constitué      */
+
+};
+
+/* Fraction de routines à limiter (classe) */
+struct _GDexLoadingClass
+{
+    GDelayedWorkClass parent;               /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des tâches des chargements pour DEX. */
+static void g_dex_loading_class_init(GDexLoadingClass *);
+
+/* Initialise une tâche de chargements pour DEX. */
+static void g_dex_loading_init(GDexLoading *);
+
+/* Supprime toutes les références externes. */
+static void g_dex_loading_dispose(GDexLoading *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dex_loading_finalize(GDexLoading *);
+
+/* Assure le chargement pour un format DEX en différé. */
+static void g_dex_loading_process(GDexLoading *, GtkStatusStack *);
+
+
+
+/* Indique le type défini pour les tâches de chargements pour format DEX. */
+G_DEFINE_TYPE(GDexLoading, g_dex_loading, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des tâches des chargements pour DEX.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dex_loading_class_init(GDexLoadingClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GDelayedWorkClass *work;                /* Version en classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_loading_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_dex_loading_finalize;
+
+    work = G_DELAYED_WORK_CLASS(klass);
+
+    work->run = (run_task_fc)g_dex_loading_process;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = instance à initialiser.                            *
+*                                                                             *
+*  Description : Initialise une tâche de chargements pour DEX.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dex_loading_init(GDexLoading *loading)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dex_loading_dispose(GDexLoading *loading)
+{
+    G_OBJECT_CLASS(g_dex_loading_parent_class)->dispose(G_OBJECT(loading));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = instance d'objet GLib à traiter.                   *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dex_loading_finalize(GDexLoading *loading)
+{
+    G_OBJECT_CLASS(g_dex_loading_parent_class)->finalize(G_OBJECT(loading));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = = ensemble d'instructions désassemblées.            *
+*                begin    = point de départ du parcours de liste.             *
+*                end      = point d'arrivée exclu du parcours.                *
+*                id       = identifiant du message affiché à l'utilisateur.   *
+*                callback = routine de traitements particuliers.              *
+*                status   = bilan final à constituer. [OUT]                   *
+*                                                                             *
+*  Description : Crée une tâche de chargement pour DEX différée.              *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GDexLoading *g_dex_loading_new(GDexFormat *format, uint32_t begin, uint32_t end, activity_id_t id, dex_loading_cb callback, bool *status)
+{
+    GDexLoading *result;                    /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_DEX_LOADING, NULL);
+
+    result->format = format;
+
+    result->callback = callback;
+    result->begin = begin;
+    result->end = end;
+
+    result->id = id;
+
+    result->status = status;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : study  = étude de routines à mener.                          *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Assure le chargement pour un format DEX en différé.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dex_loading_process(GDexLoading *loading, GtkStatusStack *status)
+{
+    uint32_t i;                             /* Boucle de parcours          */
+    GObject *obj;                           /* Object chargé en mémoire    */
+
+    for (i = loading->begin; i < loading->end && *(loading->status); i++)
+    {
+        obj = loading->callback(loading->format, i);
+
+        if (obj != NULL)
+            g_object_unref(obj);
+
+        else
+        {
+            *(loading->status) = false;
+            log_variadic_message(LMT_ERROR, _("Error while loading Dex pool item #%u!"), i);
+        }
+
+        gtk_status_stack_update_activity_value(status, loading->id, 1);
+
+    }
+
+}
diff --git a/src/format/dex/loading.h b/src/format/dex/loading.h
new file mode 100644
index 0000000..4c055ce
--- /dev/null
+++ b/src/format/dex/loading.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * loading.h - prototypes pour les chargements parallèles des éléments de la table globale du format Dex
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _FORMAT_DEX_LOADING_H
+#define _FORMAT_DEX_LOADING_H
+
+
+#include "dex.h"
+#include "../../gtkext/gtkstatusstack.h"
+
+
+
+#define G_TYPE_DEX_LOADING              g_dex_loading_get_type()
+#define G_DEX_LOADING(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dex_loading_get_type(), GDexLoading))
+#define G_IS_DEX_LOADING(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dex_loading_get_type()))
+#define G_DEX_LOADING_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_LOADING, GDexLoadingClass))
+#define G_IS_DEX_LOADING_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_LOADING))
+#define G_DEX_LOADING_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_LOADING, GDexLoadingClass))
+
+
+/* Fraction de loading à limiter (instance) */
+typedef struct _GDexLoading GDexLoading;
+
+/* Fraction de loading à limiter (classe) */
+typedef struct _GDexLoadingClass GDexLoadingClass;
+
+
+
+/* Extrait une représentation générique d'une table Dex. */
+typedef GObject * (* dex_loading_cb) (GDexFormat *, uint32_t);
+
+
+/* Indique le type défini pour les tâches de chargements pour format DEX. */
+GType g_dex_loading_get_type(void);
+
+/* Crée une tâche de chargement pour DEX différée. */
+GDexLoading *g_dex_loading_new(GDexFormat *, uint32_t, uint32_t, activity_id_t, dex_loading_cb, bool *);
+
+
+
+#endif  /* _FORMAT_DEX_LOADING_H */
diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c
index 7574638..769a4f1 100644
--- a/src/format/dex/pool.c
+++ b/src/format/dex/pool.c
@@ -32,6 +32,7 @@
 
 
 #include "dex-int.h"
+#include "loading.h"
 #include "../mangling/demangler.h"
 #include "../mangling/dex/context.h"
 
@@ -125,6 +126,7 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = description de l'exécutable à compléter.            *
+*                gid    = groupe de travail impliqué.                         *
                  status = barre de statut à tenir informée.                   *
 *                                                                             *
 *  Description : Charge en mémoire l'ensemble des types du format DEX.        *
@@ -135,33 +137,53 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index)
 *                                                                             *
 ******************************************************************************/
 
-bool load_all_dex_types(GDexFormat *format, GtkStatusStack *status)
+bool load_all_dex_types(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
+    guint runs_count;                       /* Qté d'exécutions parallèles */
+    uint32_t run_size;                      /* Volume réparti par exécution*/
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
     activity_id_t msg;                      /* Message de progression      */
-    uint32_t i;                             /* Boucle de parcours          */
-    GDataType *type;                        /* Type récupéré               */
+    guint i;                                /* Boucle de parcours          */
+    uint32_t begin;                         /* Début de bloc de traitement */
+    uint32_t end;                           /* Fin d'un bloc de traitement */
+    GDexLoading *loading;                   /* Tâche de chargement à lancer*/
 
     result = true;
 
+    /* Préparation du réceptacle */
+
     format->types = (GDataType **)calloc(format->header.type_ids_size, sizeof(GDataType *));
 
+    /* Lancement des chargements */
+
+    runs_count = g_get_num_processors();
+
+    run_size = format->header.type_ids_size / runs_count;
+
+    queue = get_work_queue();
+
     msg = gtk_status_stack_add_activity(status, _("Loading all types from the Dex pool..."),
                                         format->header.type_ids_size);
 
-    for (i = 0; i < format->header.type_ids_size && result; i++)
+    for (i = 0; i < runs_count; i++)
     {
-        type = get_type_from_dex_pool(format, i);
+        begin = i * run_size;
 
-        if (type != NULL)
-            g_object_unref(G_OBJECT(type));
+        if ((i + 1) == runs_count)
+            end = format->header.type_ids_size;
         else
-            result = false;
+            end = begin + run_size;
+
+        loading = g_dex_loading_new(format, begin, end, msg,
+                                    (dex_loading_cb)get_type_from_dex_pool, &result);
 
-        gtk_status_stack_update_activity_value(status, msg, 1);
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid);
 
     }
 
+    g_work_queue_wait_for_completion(queue, gid);
+
     gtk_status_stack_remove_activity(status, msg);
 
     return result;
@@ -235,6 +257,7 @@ GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = description de l'exécutable à compléter.            *
+*                gid    = groupe de travail impliqué.                         *
 *                status = barre de statut à tenir informée.                   *
 *                                                                             *
 *  Description : Charge en mémoire l'ensemble des champs du format DEX.       *
@@ -245,33 +268,53 @@ GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index)
 *                                                                             *
 ******************************************************************************/
 
-bool load_all_dex_fields(GDexFormat *format, GtkStatusStack *status)
+bool load_all_dex_fields(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
+    guint runs_count;                       /* Qté d'exécutions parallèles */
+    uint32_t run_size;                      /* Volume réparti par exécution*/
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
     activity_id_t msg;                      /* Message de progression      */
-    uint32_t i;                             /* Boucle de parcours          */
-    GBinVariable *field;                    /* Champ récupéré              */
+    guint i;                                /* Boucle de parcours          */
+    uint32_t begin;                         /* Début de bloc de traitement */
+    uint32_t end;                           /* Fin d'un bloc de traitement */
+    GDexLoading *loading;                   /* Tâche de chargement à lancer*/
 
     result = true;
 
+    /* Préparation du réceptacle */
+
     format->fields = (GBinVariable **)calloc(format->header.field_ids_size, sizeof(GBinVariable *));
 
+    /* Lancement des chargements */
+
+    runs_count = g_get_num_processors();
+
+    run_size = format->header.field_ids_size / runs_count;
+
+    queue = get_work_queue();
+
     msg = gtk_status_stack_add_activity(status, _("Loading all fields from the Dex pool..."),
                                         format->header.field_ids_size);
 
-    for (i = 0; i < format->header.field_ids_size && result; i++)
+    for (i = 0; i < runs_count; i++)
     {
-        field = get_field_from_dex_pool(format, i);
+        begin = i * run_size;
 
-        if (field != NULL)
-            g_object_unref(G_OBJECT(field));
+        if ((i + 1) == runs_count)
+            end = format->header.field_ids_size;
         else
-            result = false;
+            end = begin + run_size;
+
+        loading = g_dex_loading_new(format, begin, end, msg,
+                                    (dex_loading_cb)get_field_from_dex_pool, &result);
 
-        gtk_status_stack_update_activity_value(status, msg, 1);
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid);
 
     }
 
+    g_work_queue_wait_for_completion(queue, gid);
+
     gtk_status_stack_remove_activity(status, msg);
 
     return result;
@@ -506,7 +549,8 @@ GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = représentation interne du format DEX à compléter.   *
-*                status = barre de statut à tenir informée.                   *
+*                gid    = groupe de travail impliqué.                         *
+                 status = barre de statut à tenir informée.                   *
 *                                                                             *
 *  Description : Charge toutes les classes listées dans le contenu binaire.   *
 *                                                                             *
@@ -516,33 +560,53 @@ GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index)
 *                                                                             *
 ******************************************************************************/
 
-bool load_all_dex_classes(GDexFormat *format, GtkStatusStack *status)
+bool load_all_dex_classes(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
+    guint runs_count;                       /* Qté d'exécutions parallèles */
+    uint32_t run_size;                      /* Volume réparti par exécution*/
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
     activity_id_t msg;                      /* Message de progression      */
-    uint32_t i;                             /* Boucle de parcours          */
-    GDexClass *class;                       /* Classe récupérée            */
+    guint i;                                /* Boucle de parcours          */
+    uint32_t begin;                         /* Début de bloc de traitement */
+    uint32_t end;                           /* Fin d'un bloc de traitement */
+    GDexLoading *loading;                   /* Tâche de chargement à lancer*/
 
     result = true;
 
+    /* Préparation du réceptacle */
+
     format->classes = (GDexClass **)calloc(format->header.class_defs_size, sizeof(GDexClass *));
 
+    /* Lancement des chargements */
+
+    runs_count = g_get_num_processors();
+
+    run_size = format->header.class_defs_size / runs_count;
+
+    queue = get_work_queue();
+
     msg = gtk_status_stack_add_activity(status, _("Loading all classes from the Dex pool..."),
                                         format->header.class_defs_size);
 
-    for (i = 0; i < format->header.class_defs_size && result; i++)
+    for (i = 0; i < runs_count; i++)
     {
-        class = get_class_from_dex_pool(format, i);
+        begin = i * run_size;
 
-        if (class != NULL)
-            g_object_unref(G_OBJECT(class));
+        if ((i + 1) == runs_count)
+            end = format->header.class_defs_size;
         else
-            result = false;
+            end = begin + run_size;
+
+        loading = g_dex_loading_new(format, begin, end, msg,
+                                    (dex_loading_cb)get_class_from_dex_pool, &result);
 
-        gtk_status_stack_update_activity_value(status, msg, 1);
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid);
 
     }
 
+    g_work_queue_wait_for_completion(queue, gid);
+
     gtk_status_stack_remove_activity(status, msg);
 
     return result;
diff --git a/src/format/dex/pool.h b/src/format/dex/pool.h
index 4b804cc..cd4c2de 100644
--- a/src/format/dex/pool.h
+++ b/src/format/dex/pool.h
@@ -43,13 +43,13 @@ const char *get_string_from_dex_pool(const GDexFormat *, uint32_t);
 
 
 /* Charge en mémoire l'ensemble des types du format DEX. */
-bool load_all_dex_types(GDexFormat *, GtkStatusStack *);
+bool load_all_dex_types(GDexFormat *, wgroup_id_t, GtkStatusStack *);
 
 /* Extrait une représentation de type d'une table DEX. */
 GDataType *get_type_from_dex_pool(GDexFormat *, uint32_t);
 
 /* Charge en mémoire l'ensemble des champs du format DEX. */
-bool load_all_dex_fields(GDexFormat *, GtkStatusStack *);
+bool load_all_dex_fields(GDexFormat *, wgroup_id_t, GtkStatusStack *);
 
 /* Extrait une représentation de champ d'une table DEX. */
 GBinVariable *get_field_from_dex_pool(GDexFormat *, uint32_t);
@@ -61,7 +61,7 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *, uint32_t);
 GDexMethod *get_method_from_dex_pool(GDexFormat *, uint32_t);
 
 /* Charge toutes les classes listées dans le contenu binaire. */
-bool load_all_dex_classes(GDexFormat *, GtkStatusStack *);
+bool load_all_dex_classes(GDexFormat *, wgroup_id_t, GtkStatusStack *);
 
 /* Extrait une représentation de classe d'une table DEX. */
 GDexClass *get_class_from_dex_pool(GDexFormat *, uint32_t);
diff --git a/src/format/elf/symbols.c b/src/format/elf/symbols.c
index cfd0a09..57fb3c1 100644
--- a/src/format/elf/symbols.c
+++ b/src/format/elf/symbols.c
@@ -763,7 +763,7 @@ static bool load_elf_internal_symbols(GElfFormat *format, wgroup_id_t gid, GtkSt
         for (i = 0; i < count; i++)
             add_all_symbols_from_section(&symtab_sections[i], no_name, queue, msg);
 
-    g_work_queue_wait_for_completion(get_work_queue(), gid);
+    g_work_queue_wait_for_completion(queue, gid);
 
     gtk_status_stack_remove_activity(status, msg);
 
diff --git a/src/format/mangling/dex/type_gram.y b/src/format/mangling/dex/type_gram.y
index d5c3f26..506eb9b 100644
--- a/src/format/mangling/dex/type_gram.y
+++ b/src/format/mangling/dex/type_gram.y
@@ -7,10 +7,10 @@
 #include "context.h"
 #include "../context-int.h"
 
-
+typedef void *yyscan_t;
 
 /* Affiche un message d'erreur concernant l'analyse. */
-static int type_error(GDexDemangler *, char *);
+static int type_error(GDexDemangler *, yyscan_t, char *);
 
 /* Procède au décodage d'une chaîne de caractères. */
 bool demangle_dex_type(GDexDemangler *, const char *);
@@ -36,7 +36,11 @@ bool demangle_dex_type(GDexDemangler *, const char *);
 }
 
 
-%parse-param { GDexDemangler *demangler }
+
+%define api.pure full
+%parse-param { GDexDemangler *demangler } { yyscan_t scanner }
+%lex-param { yyscan_t scanner }
+
 
 %token V Z B S C I J F D
 %token ARRAY
@@ -55,9 +59,11 @@ bool demangle_dex_type(GDexDemangler *, const char *);
 
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
 
-extern YY_BUFFER_STATE type__scan_string(const char *);
-extern void type__delete_buffer(YY_BUFFER_STATE);
-extern int type_lex(void);
+extern int type_lex_init(yyscan_t *scanner);
+extern YY_BUFFER_STATE type__scan_string(const char *, yyscan_t);
+extern void type__delete_buffer(YY_BUFFER_STATE, yyscan_t);
+extern int type_lex(YYSTYPE *, yyscan_t);
+extern int type_lex_destroy(yyscan_t);
 
 %}
 
@@ -104,6 +110,7 @@ simple_name:
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : demangler = contexte associé à la procédure de décodage.     *
+*                scanner   = données internes aux analyseurs.                 *
 *                msg       = indications humaines sur l'événement.            *
 *                                                                             *
 *  Description : Affiche un message d'erreur concernant l'analyse.            *
@@ -113,7 +120,7 @@ simple_name:
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-static int type_error(GDexDemangler *demangler, char *msg)
+static int type_error(GDexDemangler *demangler, yyscan_t scanner, char *msg)
 {
 	return -1;
 
@@ -135,12 +142,17 @@ static int type_error(GDexDemangler *demangler, char *msg)
 
 bool demangle_dex_type(GDexDemangler *demangler, const char *desc)
 {
+    yyscan_t scanner;                       /* Données internes            */
 	YY_BUFFER_STATE buffer;                 /* Tampon pour bison           */
 	int ret;                                /* Bilan de l'appel            */
 
-	buffer = type__scan_string(desc);
-	ret = yyparse(demangler);
-	type__delete_buffer(buffer);
+    type_lex_init(&scanner);
+
+    buffer = type__scan_string(desc, scanner);
+	ret = yyparse(demangler, scanner);
+	type__delete_buffer(buffer, scanner);
+
+    type_lex_destroy(scanner);
 
     return (ret == 0);
 
diff --git a/src/format/mangling/dex/type_tok.l b/src/format/mangling/dex/type_tok.l
index 9c24085..918846a 100644
--- a/src/format/mangling/dex/type_tok.l
+++ b/src/format/mangling/dex/type_tok.l
@@ -4,13 +4,17 @@
 #include "context.h"
 #include "libformatmanglingdextype_la-type_gram.h"
 
+/* See lemoda.net/c/reentrant-parser */
+
 %}
 
 
 %option noyywrap
 %option yylineno
 %option nounput
- /*%option noinput*/
+/*%option noinput*/
+%option reentrant
+%option bison-bridge
 
 %x string
 
@@ -29,11 +33,11 @@ SIMPLE      {ASCII}|"$"|"-"|"_"
 "F"                     { return F; }
 "D"                     { return D; }
 "L"                     { BEGIN(string); return L; }
-"["*                    { type_lval.adeep = strlen(yytext); return ARRAY; }
+"["*                    { yylval->adeep = strlen(yytext); return ARRAY; }
 <string>"/"             { return SLASH; }
 <string>";"             { BEGIN(INITIAL); return SEMICOLON; }
 
-<string>{SIMPLE}*       { type_lval.text = yytext; return TEXT; }
+<string>{SIMPLE}*       { yylval->text = yytext; return TEXT; }
 
 <string>.               {
                             unsigned char next;
@@ -44,7 +48,7 @@ SIMPLE      {ASCII}|"$"|"-"|"_"
                                 /* U+00a1 ... U+1fff */
                                 case 0x00 ... 0x1f:
 
-                                    next = input();
+                                    next = input(yyscanner);
 
                                     if (yytext[0] == 0x00 && next < 0xa1)
                                     {
@@ -57,7 +61,7 @@ SIMPLE      {ASCII}|"$"|"-"|"_"
                                         mutf8[1] = next;
                                         mutf8[2] = '\0';
 
-                                        strcpy(type_lval.text, mutf8); return TEXT;
+                                        strcpy(yylval->text, mutf8); return TEXT;
 
                                     }
 
@@ -66,7 +70,7 @@ SIMPLE      {ASCII}|"$"|"-"|"_"
                                 /* U+2010 ... U+2027 / U+2030 ... U+d7ff */
                                 case 0x20:
 
-                                    next = input();
+                                    next = input(yyscanner);
 
                                     switch (next)
                                     {
@@ -77,7 +81,7 @@ SIMPLE      {ASCII}|"$"|"-"|"_"
                                             mutf8[1] = next;
                                             mutf8[2] = '\0';
 
-                                            strcpy(type_lval.text, mutf8); return TEXT;
+                                            strcpy(yylval->text, mutf8); return TEXT;
                                             break;
 
                                         default:
@@ -91,19 +95,19 @@ SIMPLE      {ASCII}|"$"|"-"|"_"
                                 /* ~ U+2030 ... U+d7ff */
                                 case 0x21 ... 0xd7:
 
-                                    next = input();
+                                    next = input(yyscanner);
 
                                     mutf8[0] = yytext[0];
                                     mutf8[1] = next;
                                     mutf8[2] = '\0';
 
-                                    strcpy(type_lval.text, mutf8); return TEXT;
+                                    strcpy(yylval->text, mutf8); return TEXT;
                                     break;
 
                                 /* U+e000 ... U+ffef */
                                 case 0xe0 ... 0xff:
 
-                                    next = input();
+                                    next = input(yyscanner);
 
                                     if (yytext[0] == 0xff && next > 0xef)
                                     {
@@ -116,7 +120,7 @@ SIMPLE      {ASCII}|"$"|"-"|"_"
                                         mutf8[1] = next;
                                         mutf8[2] = '\0';
 
-                                        strcpy(type_lval.text, mutf8); return TEXT;
+                                        strcpy(yylval->text, mutf8); return TEXT;
 
                                     }
 
@@ -127,11 +131,11 @@ SIMPLE      {ASCII}|"$"|"-"|"_"
                                 case 0x10:
 
                                     mutf8[0] = yytext[0];
-                                    mutf8[1] = input();
-                                    mutf8[2] = input();
+                                    mutf8[1] = input(yyscanner);
+                                    mutf8[2] = input(yyscanner);
                                     mutf8[3] = '\0';
 
-                                    strcpy(type_lval.text, mutf8); return TEXT;
+                                    strcpy(yylval->text, mutf8); return TEXT;
                                     break;
                                 */
 
-- 
cgit v0.11.2-87-g4458