From 0b6e87de0d4313f8ef31907bc48ce4d7f7749738 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard 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 + * 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 + * 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 . + */ + + +#include "loading.h" + + +#include + + +#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 . + */ + + +#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; } "/" { return SLASH; } ";" { BEGIN(INITIAL); return SEMICOLON; } -{SIMPLE}* { type_lval.text = yytext; return TEXT; } +{SIMPLE}* { yylval->text = yytext; return TEXT; } . { 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