summaryrefslogtreecommitdiff
path: root/plugins/dex
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-10-18 20:50:10 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-10-18 20:50:10 (GMT)
commitdce9d9cdfef1d37ef11a987a21f36e83b6b1944f (patch)
tree830623ade20e892954fcbddd3b7b05d09aac1dd7 /plugins/dex
parent1e7c7de85438749d3faf7b76984b86a9c088fbc1 (diff)
Created plugins for the Dex and Dalvik support.
Diffstat (limited to 'plugins/dex')
-rwxr-xr-xplugins/dex/Makefile.am25
-rw-r--r--plugins/dex/class.c576
-rw-r--r--plugins/dex/class.h89
-rw-r--r--plugins/dex/core.c68
-rw-r--r--plugins/dex/core.h38
-rw-r--r--plugins/dex/dex-int.c1115
-rwxr-xr-xplugins/dex/dex-int.h177
-rwxr-xr-xplugins/dex/dex_def.h327
-rwxr-xr-xplugins/dex/format.c611
-rwxr-xr-xplugins/dex/format.h77
-rw-r--r--plugins/dex/loading.c240
-rw-r--r--plugins/dex/loading.h63
-rw-r--r--plugins/dex/method.c489
-rw-r--r--plugins/dex/method.h104
-rw-r--r--plugins/dex/pool.c686
-rw-r--r--plugins/dex/pool.h74
-rw-r--r--plugins/dex/python/Makefile.am16
-rw-r--r--plugins/dex/python/class.c107
-rw-r--r--plugins/dex/python/class.h42
-rw-r--r--plugins/dex/python/format.c287
-rw-r--r--plugins/dex/python/format.h42
-rw-r--r--plugins/dex/python/module.c95
-rw-r--r--plugins/dex/python/module.h38
23 files changed, 5386 insertions, 0 deletions
diff --git a/plugins/dex/Makefile.am b/plugins/dex/Makefile.am
new file mode 100755
index 0000000..a17b0f2
--- /dev/null
+++ b/plugins/dex/Makefile.am
@@ -0,0 +1,25 @@
+
+lib_LTLIBRARIES = libdex.la
+
+libdex_la_SOURCES = \
+ core.h core.c \
+ class.h class.c \
+ dex-int.h dex-int.c \
+ dex_def.h \
+ format.h format.c \
+ loading.h loading.c \
+ method.h method.c \
+ pool.h pool.c
+
+libdex_la_LIBADD = \
+ python/libdexpython.la
+
+libdex_la_LDFLAGS = \
+ $(LIBPYTHON_LIBS) $(LIBPYGOBJECT_LIBS)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS = python
diff --git a/plugins/dex/class.c b/plugins/dex/class.c
new file mode 100644
index 0000000..bb2ae71
--- /dev/null
+++ b/plugins/dex/class.c
@@ -0,0 +1,576 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * class.c - manipulation des classes du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "class.h"
+
+
+#include <malloc.h>
+
+
+#include "dex-int.h"
+#include "method.h"
+#include "pool.h"
+
+
+
+/* Classe issue du code source (instance) */
+struct _GDexClass
+{
+ GObject parent; /* A laisser en premier */
+
+ class_def_item definition; /* Définition de la classe */
+ bool has_data; /* Indicateur de présence */
+ class_data_item data; /* Contenu de la classe */
+
+ GDexMethod **direct_methods; /* Méthodes propres */
+ size_t dmethods_count; /* Quantité de ces méthodes */
+ GDexMethod **virtual_methods; /* Méthodes virtuelles */
+ size_t vmethods_count; /* Quantité de ces méthodes */
+
+};
+
+/* Classe issue du code source (classe) */
+struct _GDexClassClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Procède à l'initialisation d'une classe issue du code source. */
+static void g_dex_class_class_init(GDexClassClass *);
+
+/* Procède à l'initialisation d'une classe issue du code source. */
+static void g_dex_class_init(GDexClass *);
+
+/* Supprime toutes les références externes. */
+static void g_dex_class_dispose(GDexClass *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dex_class_finalize(GDexClass *);
+
+/* Inscrit les méthodes d'une classe en tant que routines. */
+//static void g_dex_class_register_method(const GDexClass *, GBinFormat *);
+
+
+
+/* Détermine le type d'une classe issue du code source. */
+G_DEFINE_TYPE(GDexClass, g_dex_class, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe de composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'une classe issue du code source.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_class_class_init(GDexClassClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_class_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_dex_class_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'une classe issue du code source.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_class_init(GDexClass *class)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_class_dispose(GDexClass *class)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (class->direct_methods != NULL)
+ for (i = 0; i < class->dmethods_count; i++)
+ if (class->direct_methods[i] != NULL)
+ g_object_unref(G_OBJECT(class->direct_methods[i]));
+
+ if (class->virtual_methods != NULL)
+ for (i = 0; i < class->vmethods_count; i++)
+ if (class->virtual_methods[i] != NULL)
+ g_object_unref(G_OBJECT(class->virtual_methods[i]));
+
+ G_OBJECT_CLASS(g_dex_class_parent_class)->dispose(G_OBJECT(class));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_class_finalize(GDexClass *class)
+{
+ if (class->direct_methods != NULL)
+ free(class->direct_methods);
+
+ if (class->virtual_methods != NULL)
+ free(class->virtual_methods);
+
+ G_OBJECT_CLASS(g_dex_class_parent_class)->finalize(G_OBJECT(class));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter. *
+* def = définitions générales associées à la classe. *
+* *
+* Description : Crée une nouvelle représentation de classe issue de code. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
+{
+ GDexClass *result; /* Composant à retourner */
+ vmpa2t addr; /* Tête de lecture générique */
+ class_data_item data; /* Contenu de la classe */
+ GDataType *ctype; /* Type créé par la classe */
+ GBinFormat *base; /* Autre version du format */
+ uleb128_t index; /* Conservation du dernier id */
+ uleb128_t i; /* Boucle de parcours */
+ GDexMethod *method; /* Méthode chargée */
+ GBinRoutine *routine; /* Version interne de méthode */
+
+ result = g_object_new(G_TYPE_DEX_CLASS, NULL);
+
+ result->definition = *def;
+ result->has_data = (def->class_data_off != 0);
+
+ /* Interface vide ? */
+ if (!result->has_data)
+ {
+ result->dmethods_count = 0;
+ result->direct_methods = NULL;
+
+ result->vmethods_count = 0;
+ result->virtual_methods = NULL;
+
+ goto gdcn_done;
+
+ }
+
+ init_vmpa(&addr, def->class_data_off, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_class_data_item(format, &addr, &data))
+ goto gdcn_bad_item;
+
+ result->data = data;
+
+ /**
+ * On évite ici les méthodes (virtuelles) non définies.
+ */
+ if (def->access_flags & ACC_ANNOTATION) goto gdcn_done;
+
+ ctype = get_type_from_dex_pool(format, def->class_idx);
+ if (ctype == NULL) goto gdcn_unknown_type;
+
+ base = G_BIN_FORMAT(format);
+
+ index = 0;
+
+ result->dmethods_count = data.direct_methods_size;
+ result->direct_methods = (GDexMethod **)calloc(result->dmethods_count, sizeof(GDexMethod *));
+
+ for (i = 0; i < data.direct_methods_size; i++)
+ {
+ method = g_dex_method_new_defined(format, &data.direct_methods[i], &index);
+ if (method == NULL) goto gdcn_bad_method;
+
+ result->direct_methods[i] = method;
+
+ /* Ajout à la liste des symboles */
+ if (g_dex_method_has_dex_body(method))
+ {
+ routine = g_dex_method_get_routine(method);
+
+ g_object_ref(G_OBJECT(ctype));
+ g_binary_routine_set_namespace(routine, ctype, ".");
+
+ g_binary_format_add_symbol(base, G_BIN_SYMBOL(routine));
+
+ }
+
+ }
+
+ index = 0;
+
+ result->vmethods_count = data.virtual_methods_size;
+ result->virtual_methods = (GDexMethod **)calloc(result->vmethods_count, sizeof(GDexMethod *));
+
+ for (i = 0; i < data.virtual_methods_size; i++)
+ {
+ method = g_dex_method_new_defined(format, &data.virtual_methods[i], &index);
+ if (method == NULL) goto gdcn_bad_method;
+
+ result->virtual_methods[i] = method;
+
+ /* Ajout à la liste des symboles */
+ if (g_dex_method_has_dex_body(method))
+ {
+ routine = g_dex_method_get_routine(method);
+
+ g_object_ref(G_OBJECT(ctype));
+ g_binary_routine_set_namespace(routine, ctype, ".");
+
+ g_binary_format_add_symbol(base, G_BIN_SYMBOL(routine));
+
+ }
+
+ }
+
+ g_object_unref(G_OBJECT(ctype));
+
+ gdcn_done:
+
+ return result;
+
+ gdcn_bad_method:
+
+ g_object_unref(G_OBJECT(ctype));
+
+ gdcn_unknown_type:
+
+ gdcn_bad_item:
+
+ g_object_unref(G_OBJECT(result));
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* *
+* Description : Fournit la définition brute d'une classe. *
+* *
+* Retour : Données brutes issues du binaire chargé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const class_def_item *g_dex_class_get_definition(const GDexClass *class)
+{
+ return &class->definition;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* *
+* Description : Fournit la définition brute des données d'une classe. *
+* *
+* Retour : Données brutes issues du binaire chargé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const class_data_item *g_dex_class_get_data(const GDexClass *class)
+{
+ return (class->has_data ? &class->data : NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* virtual = précise la nature des méthodes ciblées. *
+* *
+* Description : Dénombre les méthodes chargées d'un type donné. *
+* *
+* Retour : Quantité de méthodes trouvées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_dex_class_count_methods(const GDexClass *class, bool virtual)
+{
+ size_t result; /* Compte à retourner */
+
+ if (virtual)
+ result = class->vmethods_count;
+ else
+ result = class->dmethods_count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* virtual = précise la nature des méthodes ciblées. *
+* index = indique l'indice de la méthode désirée. *
+* *
+* Description : Fournit une méthode chargée correspondant à un type donné. *
+* *
+* Retour : Quantité de méthodes trouvées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t index)
+{
+ GDexMethod *result; /* Instance à renvoyer */
+
+ if (virtual)
+ result = class->virtual_methods[index];
+ else
+ result = class->direct_methods[index];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* format = format permettant d'obtenir une adresse complète. *
+* *
+* Description : Intègre la méthode en tant que portion de code. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_dex_class_include_as_portion(const GDexClass *class, GExeFormat *format)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < class->dmethods_count; i++)
+ g_dex_method_include_as_portion(class->direct_methods[i], format);
+
+ for (i = 0; i < class->vmethods_count; i++)
+ g_dex_method_include_as_portion(class->virtual_methods[i], format);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* addr = adresse de la routine à retrouver. *
+* *
+* Description : Retrouve si possible la méthode associée à une adresse. *
+* *
+* Retour : Méthde retrouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexMethod *g_dex_class_find_method_by_address(const GDexClass *class, vmpa_t addr)
+{
+ GDexMethod *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
+ phys_t offset; /* Emplacement de méthode */
+
+ result = NULL;
+
+#if 0 /* FIXME */
+ /*
+
+bool g_dex_method_get_offset(const GDexMethod *method, phys_t *offset)
+
+ if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), method->offset, &addr))
+ return;
+
+ */
+
+ for (i = 0; i < class->dmethods_count && result == NULL; i++)
+ if (addr == (vmpa_t)g_dex_method_get_offset(class->direct_methods[i]))
+ result = class->direct_methods[i];
+
+ for (i = 0; i < class->vmethods_count && result == NULL; i++)
+ if (addr == (vmpa_t)g_dex_method_get_offset(class->virtual_methods[i]))
+ result = class->virtual_methods[i];
+#endif
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* format = représentation interne du format DEX à compléter. *
+* *
+* Description : Retrouve si possible le nom du fichier source d'une classe. *
+* *
+* Retour : Nom du fichier trouvé ou NULL si aucun. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_dex_class_get_source_file(const GDexClass *class, const GDexFormat *format)
+{
+ const char *result; /* Trouvaille à renvoyer */
+
+ result = get_string_from_dex_pool(format, class->definition.source_file_idx, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* lang = langage à utiliser pour la sortie humaine. *
+* buffer = tampon mis à disposition pour la sortie. *
+* format = informations chargées à consulter. *
+* *
+* Description : Procède à la décompilation complète d'une classe donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#if 0
+void g_dex_class_decompile(const GDexClass *class, GLangOutput *lang, GCodeBuffer *buffer, const GDexFormat *format)
+{
+
+#if 0
+ GDataType *type;
+
+
+ size_t i; /* Boucle de parcours */
+
+
+ /*
+GBufferLine *line, GLangOutput *output)
+
+ for (i = 0; i < block->count; i++)
+ {
+ if (i > 0)
+ line = g_code_buffer_append_new_line(buffer);
+
+*/
+
+
+
+ type = get_type_from_dex_pool(format, class->definition.class_idx);
+
+ //g_buffer_line_append_text(line, BLC_ASSEMBLY, "{", 3, RTT_SIGNS, NULL);
+
+ //printf("Output :: %s\n", _g_data_type_to_string(type, true));
+
+
+
+ g_lang_output_start_class(lang, buffer, type);
+
+
+
+ for (i = 0; i < class->vmethods_count; i++)
+ {
+ g_dex_method_decompile(class->virtual_methods[i], lang, buffer);
+ g_code_buffer_append_new_line_fixme(buffer);
+ }
+
+ for (i = 0; i < class->dmethods_count; i++)
+ {
+ g_dex_method_decompile(class->direct_methods[i], lang, buffer);
+ g_code_buffer_append_new_line_fixme(buffer);
+ }
+
+
+
+
+
+
+
+
+ g_lang_output_end_class(lang, buffer);
+
+
+
+#endif
+
+
+}
+#endif
diff --git a/plugins/dex/class.h b/plugins/dex/class.h
new file mode 100644
index 0000000..73dd5df
--- /dev/null
+++ b/plugins/dex/class.h
@@ -0,0 +1,89 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * class.h - prototypes pour la manipulation des classes du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DEX_CLASS_H
+#define _PLUGINS_DEX_CLASS_H
+
+
+#include <glib-object.h>
+
+
+#include "format.h"
+#include "method.h"
+
+
+
+#define G_TYPE_DEX_CLASS (g_dex_class_get_type())
+#define G_DEX_CLASS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_CLASS, GDexClass))
+#define G_DEX_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_CLASS, GDexClassClass))
+#define G_IS_DEX_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_CLASS))
+#define G_IS_DEX_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_CLASS))
+#define G_DEX_CLASS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_CLASS, GDexClassClass))
+
+
+
+/* Classe issue du code source (instance) */
+typedef struct _GDexClass GDexClass;
+
+/* Classe issue du code source (classe) */
+typedef struct _GDexClassClass GDexClassClass;
+
+
+
+/* Détermine le type d'une classe issue du code source. */
+GType g_dex_class_get_type(void);
+
+/* Crée une nouvelle représentation de classe issue de code. */
+GDexClass *g_dex_class_new(GDexFormat *, const class_def_item *);
+
+/* Fournit la définition brute d'une classe. */
+const class_def_item *g_dex_class_get_definition(const GDexClass *);
+
+/* Fournit la définition brute des données d'une classe. */
+const class_data_item *g_dex_class_get_data(const GDexClass *);
+
+/* Dénombre les méthodes chargées d'un type donné. */
+size_t g_dex_class_count_methods(const GDexClass *, bool);
+
+/* Fournit une méthode chargée correspondant à un type donné. */
+GDexMethod *g_dex_class_get_method(const GDexClass *, bool, size_t);
+
+/* Intègre la méthode en tant que portion de code. */
+void g_dex_class_include_as_portion(const GDexClass *, GExeFormat *);
+
+/* Retrouve si possible la méthode associée à une adresse. */
+GDexMethod *g_dex_class_find_method_by_address(const GDexClass *, vmpa_t);
+
+/* Retrouve si possible le nom du fichier source d'une classe. */
+const char *g_dex_class_get_source_file(const GDexClass *, const GDexFormat *);
+
+/* Procède à la décompilation complète d'une classe donnée. */
+//void g_dex_class_decompile(const GDexClass *, GLangOutput *, GCodeBuffer *, const GDexFormat *);
+
+
+
+
+
+
+
+#endif /* _PLUGINS_DEX_CLASS_H */
diff --git a/plugins/dex/core.c b/plugins/dex/core.c
new file mode 100644
index 0000000..c69904c
--- /dev/null
+++ b/plugins/dex/core.c
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - intégration du support du format ELF
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <core/formats.h>
+#include <plugins/plugin-def.h>
+
+
+#include "format.h"
+#include "python/module.h"
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("dex", "Add suport for the DEX format", "0.1.0",
+ RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
+
+
+
+/******************************************************************************
+* *
+* 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)
+{
+ bool result; /* Bilan à retourner */
+
+ result = register_format_matcher(dex_is_matching, NULL);
+
+ if (result)
+ result = register_format_loader("dex", "Dalvik Executable format", g_dex_format_new);
+
+ if (result)
+ result = add_format_dex_module_to_python_module();
+
+ return result;
+
+}
diff --git a/plugins/dex/core.h b/plugins/dex/core.h
new file mode 100644
index 0000000..9852948
--- /dev/null
+++ b/plugins/dex/core.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'intégration du support du format ELF
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DEX_CORE_H
+#define _PLUGINS_DEX_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);
+
+
+
+#endif /* _PLUGINS_DEX_CORE_H */
diff --git a/plugins/dex/dex-int.c b/plugins/dex/dex-int.c
new file mode 100644
index 0000000..3f3eccb
--- /dev/null
+++ b/plugins/dex/dex-int.c
@@ -0,0 +1,1115 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dex-int.c - structures internes du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "dex-int.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include <i18n.h>
+
+
+#include <common/endianness.h>
+#include <plugins/dalvik/instruction-def.h>
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DESCRIPTION DU FORMAT DALVIK */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* header = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une en-tête de programme DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_header(const GDexFormat *format, vmpa2t *pos, dex_header *header)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++)
+ result = g_binary_content_read_u8(content, pos, &header->magic[i]);
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->checksum);
+
+ for (i = 0; i < 20 && result; i++)
+ result = g_binary_content_read_u8(content, pos, &header->signature[i]);
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->file_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->header_size);
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->endian_tag);
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->link_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->link_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->map_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->string_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->string_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->type_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->type_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->proto_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->proto_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->field_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->field_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->method_ids_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->method_ids_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->class_defs_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->class_defs_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->data_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->data_off);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ELEMENTS DE TABLE DES CONSTANTES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* str_id = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un identifiant de chaîne DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_string_id_item(const GDexFormat *format, vmpa2t *pos, string_id_item *str_id)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &str_id->string_data_off);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* str_data = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture de proriétés de chaîne DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_string_data_item(const GDexFormat *format, vmpa2t *pos, string_data_item *str_data)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_uleb128(content, pos, &str_data->utf16_size);
+
+ if (result)
+ {
+ str_data->data = g_binary_content_get_raw_access(content, pos, str_data->utf16_size);
+ result = (str_data->data != NULL);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un identifiant de type DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_type_id_item(const GDexFormat *format, vmpa2t *pos, type_id_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->descriptor_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* proto_id = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une description de prototype. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_proto_id_item(const GDexFormat *format, vmpa2t *pos, proto_id_item *proto_id)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->shorty_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->return_type_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->parameters_off);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* field_id = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une description de champ. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_field_id_item(const GDexFormat *format, vmpa2t *pos, field_id_item *field_id)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &field_id->class_idx);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &field_id->type_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &field_id->name_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* meth_id = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une description de méthode. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_method_id_item(const GDexFormat *format, vmpa2t *pos, method_id_item *meth_id)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &meth_id->class_idx);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &meth_id->proto_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &meth_id->name_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* class_def = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture des propriétés d'une classe DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_class_def_item(const GDexFormat *format, vmpa2t *pos, class_def_item *class_def)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->class_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->access_flags);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->superclass_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->interfaces_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->source_file_idx);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->annotations_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->class_data_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->static_values_off);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DESCRIPTION DE CLASSES DEX */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* field = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un champ quelconque DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_field(const GDexFormat *format, vmpa2t *pos, encoded_field *field)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_uleb128(content, pos, &field->field_idx_diff);
+ result &= g_binary_content_read_uleb128(content, pos, &field->access_flags);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* method = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une méthode quelconque DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_method(const GDexFormat *format, vmpa2t *pos, encoded_method *method)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ copy_vmpa(&method->origin, pos);
+
+ result &= g_binary_content_read_uleb128(content, pos, &method->method_idx_diff);
+ result &= g_binary_content_read_uleb128(content, pos, &method->access_flags);
+ result &= g_binary_content_read_uleb128(content, pos, &method->code_off);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un type DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_type_item(const GDexFormat *format, vmpa2t *pos, type_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->type_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* list = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une liste de types DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_type_list(const GDexFormat *format, vmpa2t *pos, type_list *list)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &list->size);
+
+ list->list = (type_item *)g_binary_content_get_raw_access(content, pos, list->size * sizeof(type_item));
+ result &= (list->list != NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un contenu de classe DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_class_data_item(const GDexFormat *format, vmpa2t *pos, class_data_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ uleb128_t i; /* Boucle de parcours */
+
+ result = true;
+
+ item->static_fields = NULL;
+ item->instance_fields = NULL;
+ item->direct_methods = NULL;
+ item->virtual_methods = NULL;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_uleb128(content, pos, &item->static_fields_size);
+ result &= g_binary_content_read_uleb128(content, pos, &item->instance_fields_size);
+ result &= g_binary_content_read_uleb128(content, pos, &item->direct_methods_size);
+ result &= g_binary_content_read_uleb128(content, pos, &item->virtual_methods_size);
+
+ if (result && item->static_fields_size > 0)
+ {
+ item->static_fields = (encoded_field *)calloc(item->static_fields_size, sizeof(encoded_field));
+ if (item->static_fields == NULL) item->static_fields_size = 0;
+
+ for (i = 0; i < item->static_fields_size && result; i++)
+ result = read_dex_encoded_field(format, pos, &item->static_fields[i]);
+
+ }
+
+ if (result && item->instance_fields_size > 0)
+ {
+ item->instance_fields = (encoded_field *)calloc(item->instance_fields_size, sizeof(encoded_field));
+ if (item->instance_fields == NULL) item->instance_fields_size = 0;
+
+ for (i = 0; i < item->instance_fields_size && result; i++)
+ result = read_dex_encoded_field(format, pos, &item->instance_fields[i]);
+
+ }
+
+ if (result && item->direct_methods_size > 0)
+ {
+ item->direct_methods = (encoded_method *)calloc(item->direct_methods_size, sizeof(encoded_method));
+ if (item->direct_methods == NULL) item->direct_methods_size = 0;
+
+ for (i = 0; i < item->direct_methods_size && result; i++)
+ result = read_dex_encoded_method(format, pos, &item->direct_methods[i]);
+
+ }
+
+ if (result && item->virtual_methods_size > 0)
+ {
+ item->virtual_methods = (encoded_method *)calloc(item->virtual_methods_size, sizeof(encoded_method));
+ if (item->virtual_methods == NULL) item->virtual_methods_size = 0;
+
+ for (i = 0; i < item->virtual_methods_size && result; i++)
+ result = read_dex_encoded_method(format, pos, &item->virtual_methods[i]);
+
+ }
+
+ if (!result)
+ reset_dex_class_data_item(item);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_class_data_item(class_data_item *item)
+{
+ if (item->static_fields != NULL)
+ free(item->static_fields);
+
+ if (item->instance_fields != NULL)
+ free(item->instance_fields);
+
+ if (item->direct_methods != NULL)
+ free(item->direct_methods);
+
+ if (item->virtual_methods != NULL)
+ free(item->virtual_methods);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PORTION DE CODE EXECUTABLE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* pair = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une association exception <-> code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_type_addr_pair(const GDexFormat *format, vmpa2t *pos, encoded_type_addr_pair *pair)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_uleb128(content, pos, &pair->type_idx);
+ result &= g_binary_content_read_uleb128(content, pos, &pair->addr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* handler = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une association exception <-> code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_catch_handler(const GDexFormat *format, vmpa2t *pos, encoded_catch_handler *handler)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ leb128_t count; /* Nombre de gestionnaires */
+ leb128_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ handler->offset = get_phy_addr(pos);
+
+ result &= g_binary_content_read_leb128(content, pos, &handler->size);
+
+ count = leb128_abs(handler->size);
+
+ if (count > 0 && result)
+ {
+ handler->handlers = (encoded_type_addr_pair *)calloc(count, sizeof(encoded_type_addr_pair));
+
+ for (i = 0; i < count && result; i++)
+ result &= read_dex_encoded_type_addr_pair(format, pos, &handler->handlers[i]);
+
+ }
+ else handler->handlers = NULL;
+
+ if (handler->size <= 0)
+ result &= g_binary_content_read_uleb128(content, pos, &handler->catch_all_addr);
+
+ else
+ handler->catch_all_addr = ULEB128_MAX;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_encoded_catch_handler(encoded_catch_handler *handler)
+{
+ if (handler->handlers != NULL)
+ free(handler->handlers);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* list = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une association exception <-> code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_encoded_catch_handler_list(const GDexFormat *format, vmpa2t *pos, encoded_catch_handler_list *list)
+{
+ bool result; /* Bilan à retourner */
+ off_t saved_off; /* Sauvegarde de position */
+ GBinContent *content; /* Contenu binaire à lire */
+ uleb128_t i; /* Boucle de parcours */
+
+ result = true;
+
+ saved_off = get_phy_addr(pos);
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_uleb128(content, pos, &list->size);
+
+ if (list->size > 0 && result)
+ {
+ list->list = (encoded_catch_handler *)calloc(list->size, sizeof(encoded_catch_handler));
+
+ for (i = 0; i < list->size && result; i++)
+ {
+ result &= read_dex_encoded_catch_handler(format, pos, &list->list[i]);
+ if (result) list->list[i].offset -= saved_off;
+ }
+
+ }
+ else list->list = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_encoded_catch_handler_list(encoded_catch_handler_list *list)
+{
+ uleb128_t i; /* Boucle de parcours */
+
+ if (list->list != NULL)
+ {
+ for (i = 0; i < list->size; i++)
+ reset_dex_encoded_catch_handler(&list->list[i]);
+
+ free(list->list);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une association exception <-> code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_try_item(const GDexFormat *format, vmpa2t *pos, try_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->start_addr);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->insn_count);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->handler_off);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* item = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'une portion de code DEX. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_code_item(const GDexFormat *format, vmpa2t *pos, code_item *item)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ vmpa2t origin; /* Mémorisation d'une position */
+ uint16_t padding; /* Eventuel alignement */
+ uint16_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->registers_size);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->ins_size);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->outs_size);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->tries_size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->debug_info_off);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->insns_size);
+
+ item->insns = (uint16_t *)g_binary_content_get_raw_access(content, pos, item->insns_size * sizeof(uint16_t));
+ if (item->insns == NULL) goto rdci_bad_insns;
+
+ /* Padding ? */
+ if (item->tries_size > 0 && item->insns_size % 2 == 1)
+ {
+ copy_vmpa(&origin, pos);
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &padding);
+
+ if (padding != 0)
+ g_binary_format_add_error(G_BIN_FORMAT(format), BFE_SPECIFICATION, &origin,
+ _("Expected a null value as padding."));
+
+ }
+
+ if (item->tries_size > 0 && result)
+ {
+ assert(get_phy_addr(pos) % 4 == 0);
+
+ item->tries = (try_item *)calloc(item->tries_size, sizeof(try_item));
+ if (item->tries == NULL) goto rdci_bad_tries;
+
+ for (i = 0; i < item->tries_size && result; i++)
+ result &= read_dex_try_item(format, pos, &item->tries[i]);
+
+ if (result)
+ {
+ item->handlers = (encoded_catch_handler_list *)calloc(1, sizeof(encoded_catch_handler_list));
+ result &= read_dex_encoded_catch_handler_list(format, pos, item->handlers);
+ }
+
+ else
+ item->handlers = NULL;
+
+ }
+
+ else
+ {
+ item->tries = NULL;
+ item->handlers = NULL;
+ }
+
+ return result;
+
+ rdci_bad_insns:
+
+ item->tries = NULL;
+
+ rdci_bad_tries:
+
+ item->handlers = NULL;
+
+ return false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_code_item(code_item *item)
+{
+ if (item->tries != NULL)
+ free(item->tries);
+
+ if (item->handlers != NULL)
+ {
+ reset_dex_encoded_catch_handler_list(item->handlers);
+ free(item->handlers);
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* AIGUILLAGES DIVERS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* packed = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un contenu d'aiguillage compact. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_packed_switch(const GDexFormat *format, vmpa2t *pos, packed_switch *packed)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ uint16_t i; /* Boucle de parcours */
+
+ result = true;
+
+ packed->targets = NULL;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &packed->ident);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &packed->size);
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &packed->first_key);
+
+ if (result && packed->size > 0)
+ {
+ packed->targets = (uint32_t *)calloc(packed->size, sizeof(uint32_t));
+
+ for (i = 0; i < packed->size && result; i++)
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &packed->targets[i]);
+
+ }
+
+ if (!result)
+ reset_dex_packed_switch(packed);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : packed = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_packed_switch(packed_switch *packed)
+{
+ if (packed->targets != NULL)
+ free(packed->targets);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* sparse = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un contenu d'aiguillage dispersé. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_sparse_switch(const GDexFormat *format, vmpa2t *pos, sparse_switch *sparse)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ uint16_t i; /* Boucle de parcours */
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ sparse->keys = NULL;
+ sparse->targets = NULL;
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &sparse->ident);
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &sparse->size);
+
+ if (result && sparse->size > 0)
+ {
+ sparse->keys = (uint32_t *)calloc(sparse->size, sizeof(uint32_t));
+ sparse->targets = (uint32_t *)calloc(sparse->size, sizeof(uint32_t));
+
+ for (i = 0; i < sparse->size && result; i++)
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &sparse->keys[i]);
+
+ for (i = 0; i < sparse->size && result; i++)
+ result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &sparse->targets[i]);
+
+ }
+
+ if (!result)
+ reset_dex_sparse_switch(sparse);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : sparse = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_sparse_switch(sparse_switch *sparse)
+{
+ if (sparse->keys != NULL)
+ free(sparse->keys);
+
+ if (sparse->targets != NULL)
+ free(sparse->targets);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* pos = position de début de lecture. [OUT] *
+* dsxitch = structure lue à retourner. [OUT] *
+* *
+* Description : Procède à la lecture d'un contenu d'aiguillage Dex interne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool read_dex_switch(const GDexFormat *format, vmpa2t *pos, dex_switch *dswitch)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire à lire */
+ uint16_t ident; /* Pseudo-code d'identification*/
+
+ result = true;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &ident);
+
+ /**
+ * La tête de lecture n'est pas mise à jour volontairement !
+ */
+
+ if (result)
+ {
+ if (ident == DPO_PACKED_SWITCH)
+ result = read_dex_packed_switch(format, pos, (packed_switch *)dswitch);
+
+ else if (ident == DPO_SPARSE_SWITCH)
+ result = read_dex_sparse_switch(format, pos, (sparse_switch *)dswitch);
+
+ else
+ result = false;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dswitch = structure à nettoyer. *
+* *
+* Description : Supprime tous les éléments chargés en mémoire à la lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_dex_switch(dex_switch *dswitch)
+{
+ if (dswitch->packed.ident == DPO_PACKED_SWITCH)
+ reset_dex_packed_switch((packed_switch *)dswitch);
+ else
+ reset_dex_sparse_switch((sparse_switch *)dswitch);
+
+}
diff --git a/plugins/dex/dex-int.h b/plugins/dex/dex-int.h
new file mode 100755
index 0000000..60d2f4d
--- /dev/null
+++ b/plugins/dex/dex-int.h
@@ -0,0 +1,177 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dex-int.h - prototypes pour les structures internes du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DEX_DEX_INT_H
+#define _PLUGINS_DEX_DEX_INT_H
+
+
+#include <format/executable-int.h>
+
+
+#include "class.h"
+#include "dex_def.h"
+#include "format.h"
+
+
+
+/* Format d'exécutable DEX (instance) */
+struct _GDexFormat
+{
+ GExeFormat parent; /* A laisser en premier */
+
+ dex_header header; /* En-tête du programme */
+
+ GDataType **types; /* Types partagés pour Dalvik */
+ GBinVariable **fields; /* Champs de données partagés */
+ GDexClass **classes; /* Classes retrouvées */
+
+};
+
+/* Format d'exécutable DEX (classe) */
+struct _GDexFormatClass
+{
+ GExeFormatClass parent; /* A laisser en premier */
+
+};
+
+
+/* Retrouve si possible la méthode associée à une adresse. */
+GDexMethod *g_dex_format_find_method_by_address(const GDexFormat *, vmpa_t);
+
+/* Dénombre le nombre de classes trouvées. */
+size_t g_dex_format_count_classes(const GDexFormat *);
+
+/* Fournit une classe du format chargée en mémoire. */
+GDexClass *g_dex_format_get_class(const GDexFormat *, size_t);
+
+
+/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */
+
+
+/* Procède à la lecture d'une en-tête de programme DEX. */
+bool read_dex_header(const GDexFormat *, vmpa2t *, dex_header *);
+
+
+
+/* ------------------------ ELEMENTS DE TABLE DES CONSTANTES ------------------------ */
+
+
+/* Procède à la lecture d'un identifiant de chaîne DEX. */
+bool read_dex_string_id_item(const GDexFormat *, vmpa2t *, string_id_item *);
+
+/* Procède à la lecture de proriétés de chaîne DEX. */
+bool read_dex_string_data_item(const GDexFormat *, vmpa2t *, string_data_item *);
+
+/* Procède à la lecture d'un identifiant de type DEX. */
+bool read_dex_type_id_item(const GDexFormat *, vmpa2t *, type_id_item *);
+
+/* Procède à la lecture d'une description de prototype. */
+bool read_dex_proto_id_item(const GDexFormat *, vmpa2t *, proto_id_item *);
+
+/* Procède à la lecture d'une description de champ. */
+bool read_dex_field_id_item(const GDexFormat *, vmpa2t *, field_id_item *);
+
+/* Procède à la lecture d'une description de méthode. */
+bool read_dex_method_id_item(const GDexFormat *, vmpa2t *, method_id_item *);
+
+/* Procède à la lecture des propriétés d'une classe DEX. */
+bool read_dex_class_def_item(const GDexFormat *, vmpa2t *, class_def_item *);
+
+
+
+/* --------------------------- DESCRIPTION DE CLASSES DEX --------------------------- */
+
+
+/* Procède à la lecture d'un champ quelconque DEX. */
+bool read_dex_encoded_field(const GDexFormat *, vmpa2t *, encoded_field *);
+
+/* Procède à la lecture d'une méthode quelconque DEX. */
+bool read_dex_encoded_method(const GDexFormat *, vmpa2t *, encoded_method *);
+
+/* Procède à la lecture d'un type DEX. */
+bool read_dex_type_item(const GDexFormat *, vmpa2t *, type_item *);
+
+/* Procède à la lecture d'une liste de types DEX. */
+bool read_dex_type_list(const GDexFormat *, vmpa2t *, type_list *);
+
+/* Procède à la lecture d'un contenu de classe DEX. */
+bool read_dex_class_data_item(const GDexFormat *, vmpa2t *, class_data_item *);
+
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_class_data_item(class_data_item *);
+
+
+
+/* --------------------------- PORTION DE CODE EXECUTABLE --------------------------- */
+
+
+/* Procède à la lecture d'une association exception <-> code. */
+bool read_dex_encoded_type_addr_pair(const GDexFormat *, vmpa2t *, encoded_type_addr_pair *);
+
+/* Procède à la lecture d'une association exception <-> code. */
+bool read_dex_encoded_catch_handler(const GDexFormat *, vmpa2t *, encoded_catch_handler *);
+
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_encoded_catch_handler(encoded_catch_handler *);
+
+/* Procède à la lecture d'une association exception <-> code. */
+bool read_dex_encoded_catch_handler_list(const GDexFormat *, vmpa2t *, encoded_catch_handler_list *);
+
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_encoded_catch_handler_list(encoded_catch_handler_list *);
+
+/* Procède à la lecture d'une association exception <-> code. */
+bool read_dex_try_item(const GDexFormat *, vmpa2t *, try_item *);
+
+/* Procède à la lecture d'une portion de code DEX. */
+bool read_dex_code_item(const GDexFormat *, vmpa2t *, code_item *);
+
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_code_item(code_item *);
+
+
+
+/* ------------------------------- AIGUILLAGES DIVERS ------------------------------- */
+
+
+/* Procède à la lecture d'un contenu d'aiguillage compact. */
+bool read_dex_packed_switch(const GDexFormat *, vmpa2t *, packed_switch *);
+
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_packed_switch(packed_switch *);
+
+/* Procède à la lecture d'un contenu d'aiguillage dispersé. */
+bool read_dex_sparse_switch(const GDexFormat *, vmpa2t *, sparse_switch *);
+
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_sparse_switch(sparse_switch *);
+
+/* Procède à la lecture d'un contenu d'aiguillage Dex interne. */
+bool read_dex_switch(const GDexFormat *, vmpa2t *, dex_switch *);
+
+/* Supprime tous les éléments chargés en mémoire à la lecture. */
+void reset_dex_switch(dex_switch *);
+
+
+
+#endif /* _PLUGINS_DEX_DEX_INT_H */
diff --git a/plugins/dex/dex_def.h b/plugins/dex/dex_def.h
new file mode 100755
index 0000000..1d2e0d7
--- /dev/null
+++ b/plugins/dex/dex_def.h
@@ -0,0 +1,327 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dex_def.h - liste des structures et constantes utilisées par le format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DEX_DEX_DEF_H
+#define _PLUGINS_DEX_DEX_DEF_H
+
+
+#include <common/leb128.h>
+
+
+
+/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */
+
+
+/* Identifiant magique "dex\n035\0" */
+#define DEX_FILE_MAGIC "\x64\x65\x78\x0a\x30\x33\x35\x00"
+#define DEX_FILE_MAGIC_LEN 8
+
+/* Types de boutisme */
+#define ENDIAN_CONSTANT 0x12345678
+#define REVERSE_ENDIAN_CONSTANT 0x78563412
+
+/* Indice non valide */
+#define NO_INDEX 0xffffffff
+
+
+/* En-tête de tout programe Dex */
+typedef struct _dex_header
+{
+ uint8_t magic[DEX_FILE_MAGIC_LEN]; /* Valeur magique du format */
+
+ uint32_t checksum; /* Somme de contrôle adler32 */
+ uint8_t signature[20]; /* Emprunte SHA-1 du reste */
+ uint32_t file_size; /* Taille du fichier */
+ uint32_t header_size; /* Taille de cette en-tête */
+
+ uint32_t endian_tag; /* Boutisme du fichier */
+
+ uint32_t link_size; /* Taille de section 'liaisons'*/
+ uint32_t link_off; /* Position de ladite section */
+ uint32_t map_off; /* Position de la cartographie */
+ uint32_t string_ids_size; /* Nombre de chaînes de carac. */
+ uint32_t string_ids_off; /* Position de cette liste */
+ uint32_t type_ids_size; /* Nom d'identifiant de type */
+ uint32_t type_ids_off; /* Position de la liste */
+ uint32_t proto_ids_size; /* Nombre de prototypes */
+ uint32_t proto_ids_off; /* Position de la liste */
+ uint32_t field_ids_size; /* Nombre de champs */
+ uint32_t field_ids_off; /* Position de la liste */
+ uint32_t method_ids_size; /* Nombre de méthodes */
+ uint32_t method_ids_off; /* Position de la liste */
+ uint32_t class_defs_size; /* Nombre de classes déclarées */
+ uint32_t class_defs_off; /* Position de la liste */
+ uint32_t data_size; /* Taille des données */
+ uint32_t data_off; /* Début des données */
+
+} dex_header;
+
+
+
+/* -------------------------- CONSTANTES POUR DEX DIVERSES -------------------------- */
+
+
+/* Définition des drapeaux d'accès */
+
+#define ACC_PUBLIC 0x00001 /* Elément publique */
+#define ACC_PRIVATE 0x00002 /* Elément privé */
+#define ACC_PROTECTED 0x00004 /* Elément protégé */
+#define ACC_STATIC 0x00008 /* Elément statique */
+#define ACC_FINAL 0x00010 /* Non dérivable / modifiable */
+#define ACC_SYNCHRONIZED 0x00020 /* Pose de verrou automatique */
+#define ACC_VOLATILE 0x00040 /* Accès spécial threads */
+#define ACC_BRIDGE 0x00040 /* Méthode pont */
+#define ACC_TRANSIENT 0x00080 /* Pas de sérialisation */
+#define ACC_VARARGS 0x00080 /* Arguments variables */
+#define ACC_NATIVE 0x00100 /* Implémentation en code natif*/
+#define ACC_INTERFACE 0x00200 /* Interface */
+#define ACC_ABSTRACT 0x00400 /* Non instanciable directement*/
+#define ACC_STRICT 0x00800 /* Règle pour les flottants */
+#define ACC_SYNTHETIC 0x01000 /* Non défini dans le code */
+#define ACC_ANNOTATION 0x02000 /* Annotation */
+#define ACC_ENUM 0x04000 /* Enumération */
+#define ACC_CONSTRUCTOR 0x10000 /* Constructeur */
+#define ACC_DECLARED_SYNCHRONIZED 0x20000 /* Pose de verrou automatique */
+
+
+
+/* ------------------------ ELEMENTS DE TABLE DES CONSTANTES ------------------------ */
+
+
+/* Chaîne de caractères */
+
+typedef struct _string_id_item
+{
+ uint32_t string_data_off; /* Propriétés de la chaîne */
+
+} string_id_item;
+
+typedef struct _string_data_item
+{
+ uleb128_t utf16_size; /* Taille du décodage */
+ const uint8_t *data; /* Caractères terminés par '\0'*/
+
+} string_data_item;
+
+/* Description d'un type */
+typedef struct _type_id_item
+{
+ uint32_t descriptor_idx; /* Description du type */
+
+} type_id_item;
+
+/* Description d'un prototype */
+typedef struct _proto_id_item
+{
+ uint32_t shorty_idx; /* Description version courte */
+ uint32_t return_type_idx; /* Type de retour */
+ uint32_t parameters_off; /* Position des arguments */
+
+} proto_id_item;
+
+/* Description d'un champ */
+typedef struct _field_id_item
+{
+ uint16_t class_idx; /* Classe d'appartenance */
+ uint16_t type_idx; /* Type du champ */
+ uint32_t name_idx; /* Nom du champ */
+
+} field_id_item;
+
+/* Description d'une méthode */
+typedef struct _method_id_item
+{
+ uint16_t class_idx; /* Classe d'appartenance */
+ uint16_t proto_idx; /* Prototype de la méthode */
+ uint32_t name_idx; /* Nom de la méthode */
+
+} method_id_item;
+
+/* Description d'une classe */
+typedef struct _class_def_item
+{
+ uint32_t class_idx; /* Type de la classe */
+ uint32_t access_flags; /* Drapeaux d'accès déclarés */
+ uint32_t superclass_idx; /* Type de la classe parente */
+ uint32_t interfaces_off; /* Liste des interfaces */
+ uint32_t source_file_idx; /* Fichier source d'origine */
+ uint32_t annotations_off; /* Eventuelles annotations */
+ uint32_t class_data_off; /* Données de la classe */
+ uint32_t static_values_off; /* Initialisations statiques */
+
+} class_def_item;
+
+
+
+/* --------------------------- DESCRIPTION DE CLASSES DEX --------------------------- */
+
+
+/* Propriétés d'une champ */
+typedef struct _encoded_field
+{
+ uleb128_t field_idx_diff; /* Description du champ */
+ uleb128_t access_flags; /* Conditions d'accès */
+
+} encoded_field;
+
+/* Propriétés d'une méthode */
+typedef struct _encoded_method
+{
+ uleb128_t method_idx_diff; /* Description de la méthode */
+ uleb128_t access_flags; /* Conditions d'accès */
+ uleb128_t code_off; /* Position du code associé */
+
+ vmpa2t origin; /* Rajout pour suivi interne */
+
+} encoded_method;
+
+/* Type quelconque */
+typedef struct _type_item
+{
+ uint16_t type_idx; /* Indice dans la table adaptée*/
+
+} type_item;
+
+/* Liste de types */
+typedef struct _type_list
+{
+ uint32_t size; /* Nombre d'éléments présents */
+ type_item *list; /* Liste des éléments inscrits */
+
+} type_list;
+
+/* Données de fonctionnement pour classe */
+typedef struct _class_data_item
+{
+ uleb128_t static_fields_size; /* Quantité de champs statiques*/
+ uleb128_t instance_fields_size; /* Qté de champs instanciables */
+ uleb128_t direct_methods_size; /* Qté de méthodes propres */
+ uleb128_t virtual_methods_size; /* Qté de méthodes virtuelles */
+
+ encoded_field *static_fields; /* Champs statiques */
+ encoded_field *instance_fields; /* Champs instanciables */
+ encoded_method *direct_methods; /* Méthodes propres */
+ encoded_method *virtual_methods; /* Méthodes virtuelles */
+
+} class_data_item;
+
+
+
+/* --------------------------- PORTION DE CODE EXECUTABLE --------------------------- */
+
+
+/* Exception gérée */
+typedef struct _encoded_type_addr_pair
+{
+ uleb128_t type_idx; /* Type d'exception couverte */
+ uleb128_t addr; /* Adresse du début du code */
+
+} encoded_type_addr_pair;
+
+/* Ensemble d'exceptions prises en compte */
+typedef struct _encoded_catch_handler
+{
+ leb128_t size; /* Quantité d'exceptions */
+ encoded_type_addr_pair *handlers; /* Gestionnaires explicites */
+ uleb128_t catch_all_addr; /* Adresse par défaut */
+
+ /**
+ * Note : les spécifications indiquent que le champ handler_off de
+ * try_item renvoie vers le gestionnaire à partir de la base de la structure
+ * encoded_catch_handler_list. Comme la représentation interne de cette
+ * structure efface la représentation physique, on conserve en mémoire
+ * le décalage rencontré à la lecture dans un champ artificiel.
+ */
+ phys_t offset; /* Position dans le binaire */
+
+} encoded_catch_handler;
+
+/* Liste des différents gestionnaires d'exceptions */
+typedef struct _encoded_catch_handler_list
+{
+ uleb128_t size; /* Taille de la liste */
+ encoded_catch_handler *list; /* Gestionnaires en place */
+
+} encoded_catch_handler_list;
+
+/* Zone couverte en cas de pépin */
+typedef struct _try_item
+{
+ uint32_t start_addr; /* Adresse du début couvert */
+ uint16_t insn_count; /* Nbre de doubles-octets gérés*/
+ uint16_t handler_off; /* Indice du gestionnaire */
+
+} try_item;
+
+/* Description de la zone */
+typedef struct _code_item
+{
+ uint16_t registers_size; /* Qté de registres utilisés */
+ uint16_t ins_size; /* Nbre d'arguments en entrée */
+ uint16_t outs_size; /* Nbre d'arguments en sortie */
+ uint16_t tries_size; /* Qté de try/catch */
+ uint32_t debug_info_off; /* Information de débogage */
+ uint32_t insns_size; /* Nbre de blocs de 2 octets */
+
+ uint16_t *insns; /* Code exécutable */
+ try_item *tries; /* Zone d'exceptions */
+ encoded_catch_handler_list *handlers; /* Gestionnaires associés */
+
+} code_item;
+
+
+
+/* ------------------------------- AIGUILLAGES DIVERS ------------------------------- */
+
+
+/* Aiguillage compressé */
+typedef struct _packed_switch
+{
+ uint16_t ident; /* Pseudo-code d'identification*/
+ uint16_t size; /* Nombre d'entrées */
+ uint32_t first_key; /* Première et plus petite clef*/
+ uint32_t *targets; /* Cibles relatives */
+
+} packed_switch;
+
+/* Aiguillage dispersé */
+typedef struct _sparse_switch
+{
+ uint16_t ident; /* Pseudo-code d'identification*/
+ uint16_t size; /* Nombre d'entrées */
+ uint32_t *keys; /* Clefs valeureuses */
+ uint32_t *targets; /* Cibles relatives */
+
+} sparse_switch;
+
+/* Manipulation interne */
+typedef union _dex_switch
+{
+ packed_switch packed; /* Modèle compact */
+ sparse_switch sparse; /* Modèle dispersé */
+
+} dex_switch;
+
+
+
+#endif /* _PLUGINS_DEX_DEX_DEF_H */
diff --git a/plugins/dex/format.c b/plugins/dex/format.c
new file mode 100755
index 0000000..72d0dd5
--- /dev/null
+++ b/plugins/dex/format.c
@@ -0,0 +1,611 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * format.c - support du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "format.h"
+
+
+#include <string.h>
+
+
+#include <i18n.h>
+#include <core/global.h>
+#include <plugins/pglist.h>
+
+
+#include "dex-int.h"
+#include "pool.h"
+
+
+
+/* Initialise la classe des formats d'exécutables DEX. */
+static void g_dex_format_class_init(GDexFormatClass *);
+
+/* Initialise une instance de format d'exécutable DEX. */
+static void g_dex_format_init(GDexFormat *);
+
+/* Supprime toutes les références externes. */
+static void g_dex_format_dispose(GDexFormat *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dex_format_finalize(GDexFormat *);
+
+/* Informe quant au boutisme utilisé. */
+static SourceEndian g_dex_format_get_endianness(const GDexFormat *);
+
+/* Indique le type d'architecture visée par le format. */
+static const char *g_dex_format_get_target_machine(const GDexFormat *);
+
+/* Etend la définition des portions au sein d'un binaire. */
+static void g_dex_format_refine_portions(GDexFormat *);
+
+/* Fournit l'emplacement d'une section donnée. */
+static bool g_dex_format_get_section_range_by_name(const GDexFormat *, const char *, mrange_t *);
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* Détermine tous les fichiers source indiqués. */
+//static void g_dex_format_find_all_sources(GDexFormat *);
+
+/* Procède à la décompilation complète du format. */
+static void g_dex_format_decompile(const GDexFormat *, void/*GCodeBuffer*/ *, const char *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à parcourir. *
+* parent = éventuel format exécutable déjà chargé. *
+* unused = adresse non utilisée ici. *
+* key = identifiant de format trouvé ou NULL. [OUT] *
+* *
+* Description : Indique si le format peut être pris en charge ici. *
+* *
+* Retour : Conclusion de haut niveau sur la reconnaissance effectuée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+FormatMatchStatus dex_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key)
+{
+ FormatMatchStatus result; /* Bilan à renvoyer */
+ vmpa2t addr; /* Tête de lecture initiale */
+ bool status; /* Bilan des accès mémoire */
+ char magic[DEX_FILE_MAGIC_LEN]; /* Idenfiant standard */
+
+
+ /* REMME */
+ if (parent != NULL) return FMS_UNKNOWN;
+
+
+ init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
+
+ status = g_binary_content_read_raw(content, &addr, DEX_FILE_MAGIC_LEN, (bin_t *)magic);
+
+ status &= (memcmp(magic, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0);
+
+ if (status)
+ {
+ result = FMS_MATCHED;
+ *key = strdup(parent == NULL ? "dex" : "dexdbg");
+ }
+ else
+ result = FMS_UNKNOWN;
+
+ return result;
+
+}
+
+
+/* Indique le type défini pour un format d'exécutable DEX. */
+G_DEFINE_TYPE(GDexFormat, g_dex_format, G_TYPE_EXE_FORMAT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des formats d'exécutables DEX. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_format_class_init(GDexFormatClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GBinFormatClass *fmt; /* Version en format basique */
+ GExeFormatClass *exe; /* Version en exécutable */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_format_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_dex_format_finalize;
+
+ fmt = G_BIN_FORMAT_CLASS(klass);
+
+ fmt->get_endian = (format_get_endian_fc)g_dex_format_get_endianness;
+
+ exe = G_EXE_FORMAT_CLASS(klass);
+
+ exe->get_machine = (get_target_machine_fc)g_dex_format_get_target_machine;
+ exe->refine_portions = (refine_portions_fc)g_dex_format_refine_portions;
+
+ exe->translate_phys = (translate_phys_fc)g_exe_format_without_virt_translate_offset_into_vmpa;
+ exe->translate_virt = (translate_virt_fc)g_exe_format_without_virt_translate_address_into_vmpa;
+
+ exe->get_range_by_name = (get_range_by_name_fc)g_dex_format_get_section_range_by_name;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = instance à initialiser. *
+* *
+* Description : Initialise une instance de format d'exécutable DEX. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_format_init(GDexFormat *format)
+{
+ GBinFormat *bin_format; /* Format parent à compléter #1*/
+
+ bin_format = G_BIN_FORMAT(format);
+
+ bin_format->decompile = (format_decompile_fc)g_dex_format_decompile;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_format_dispose(GDexFormat *format)
+{
+ G_OBJECT_CLASS(g_dex_format_parent_class)->dispose(G_OBJECT(format));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_format_finalize(GDexFormat *format)
+{
+ G_OBJECT_CLASS(g_dex_format_parent_class)->finalize(G_OBJECT(format));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire à parcourir. *
+* parent = éventuel format exécutable déjà chargé. *
+ status = barre de statut à tenir informée. *
+* *
+* Description : Prend en charge un nouveau format Dex. *
+* *
+* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status)
+{
+ GDexFormat *result; /* Structure à retourner */
+ GBinFormat *base; /* Version basique du format */
+ GExeFormat *exe_format; /* Autre version 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);
+
+ base = G_BIN_FORMAT(result);
+ exe_format = G_EXE_FORMAT(result);
+
+ g_binary_format_set_content(base, content);
+
+ init_vmpa(&pos, 0, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_header(result, &pos, &result->header))
+ goto gdfn_error;
+
+
+
+ /* TODO : vérifier que les *_id ne se chevauchent pas */
+
+
+ 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, gid, status))
+ goto gdfn_error;
+
+ if (!load_all_dex_classes(result, gid, status))
+ goto gdfn_error;
+
+ preload_binary_format(PGA_FORMAT_PRELOAD, base, base->info, status);
+
+ if (!g_executable_format_complete_loading(exe_format, status))
+ goto gdfn_error;
+
+ return base;
+
+ gdfn_error:
+
+ g_object_unref(G_OBJECT(result));
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* *
+* Description : Informe quant au boutisme utilisé. *
+* *
+* Retour : Indicateur de boutisme. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static SourceEndian g_dex_format_get_endianness(const GDexFormat *format)
+{
+ return SRE_LITTLE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* *
+* Description : Indique le type d'architecture visée par le format. *
+* *
+* Retour : Identifiant de l'architecture ciblée par le format. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static const char *g_dex_format_get_target_machine(const GDexFormat *format)
+{
+ return "dalvik";
+
+}
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* main = couche de portions principale à raffiner. *
+* *
+* Description : Etend la définition des portions au sein d'un binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_format_refine_portions(GDexFormat *format)
+{
+ GExeFormat *exe_format; /* Autre version du format */
+ size_t max; /* Nombre d'itérations prévues */
+ size_t i; /* Boucle de parcours */
+
+ exe_format = G_EXE_FORMAT(format);
+
+ max = g_dex_format_count_classes(format);
+
+ for (i = 0; i < max; i++)
+ g_dex_class_include_as_portion(format->classes[i], exe_format);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à consulter. *
+* name = nom de la section recherchée. *
+* range = emplacement en mémoire à renseigner. [OUT] *
+* *
+* Description : Fournit l'emplacement d'une section donnée. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_dex_format_get_section_range_by_name(const GDexFormat *format, const char *name, mrange_t *range)
+{
+ bool result; /* Bilan à retourner */
+
+ result = false;
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* addr = adresse de la routine à retrouver. *
+* *
+* Description : Retrouve si possible la méthode associée à une adresse. *
+* *
+* Retour : Méthde retrouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexMethod *g_dex_format_find_method_by_address(const GDexFormat *format, vmpa_t addr)
+{
+
+ return NULL;
+
+
+#if 0
+ GDexMethod *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ for (i = 0; i < format->classes_count && result == NULL; i++)
+ result = g_dex_class_find_method_by_address(format->classes[i], addr);
+
+ return result;
+#endif
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à mettre à jour. *
+* *
+* Description : Détermine tous les fichiers source indiqués. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#if 0
+static void g_dex_format_find_all_sources(GDexFormat *format)
+{
+
+#if 0
+
+ GBinFormat *bf; /* Instance parente */
+ size_t i; /* Boucle de parcours #1 */
+ const char *source; /* Fichier source trouvé */
+ bool found; /* Présence dans la liste */
+ size_t k; /* Boucle de parcours #2 */
+
+ bf = G_BIN_FORMAT(format);
+
+ for (i = 0; i < format->classes_count; i++)
+ {
+ source = g_dex_class_get_source_file(format->classes[i], format);
+ if (source == NULL) continue;
+
+ found = false;
+
+ for (k = 0; k < bf->src_count && !found; k++)
+ found = (strcmp(source, bf->src_files[k]) == 0);
+
+ if (!found)
+ {
+ bf->src_files = (const char **)realloc(bf->src_files,
+ ++bf->src_count * sizeof(const char **));
+ bf->src_files[bf->src_count - 1] = source;
+ }
+
+ }
+
+#endif
+
+}
+#endif
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* buffer = tampon mis à disposition pour la sortie. *
+* filename = nom du fichier source à cibler. *
+* *
+* Description : Procède à la décompilation complète du format. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_format_decompile(const GDexFormat *format, void/*GCodeBuffer*/ *buffer, const char *filename)
+{
+
+#if 0
+
+ GLangOutput *lang; /* Langage de sortie */
+ size_t i; /* Boucle de parcours */
+ const char *source; /* Fichier source trouvé */
+
+ lang = g_java_output_new();
+
+ for (i = 0; i < format->classes_count; i++)
+ {
+ source = g_dex_class_get_source_file(format->classes[i], format);
+ if (source == NULL || strcmp(source, filename) != 0) continue;
+
+ g_dex_class_decompile(format->classes[i], lang, buffer, format);
+
+
+
+#if 0
+ GDataType *get_type_from_dex_pool(const GDexFormat *format, uint16_t index)
+
+
+ Décrit le type fourni sous forme de caractères. *
+* *
+* Retour : Chaîne à libérer de la mémoire après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *_g_data_type_to_string(const GDataType *type, bool simple)
+
+#endif
+
+ }
+
+
+#endif
+
+}
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* *
+* Description : Présente l'en-tête DEX du format chargé. *
+* *
+* Retour : Pointeur vers la description principale. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const dex_header *g_dex_format_get_header(const GDexFormat *format)
+{
+ return &format->header;
+
+}
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à consulter. *
+* *
+* Description : Dénombre le nombre de classes trouvées. *
+* *
+* Retour : Quantité de classes présentes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_dex_format_count_classes(const GDexFormat *format)
+{
+ return format->header.class_defs_size;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à consulter. *
+* index = indice de la classe visée. *
+* *
+* Description : Fournit une classe du format chargée en mémoire. *
+* *
+* Retour : Instance représentant une classe chargée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexClass *g_dex_format_get_class(const GDexFormat *format, size_t index)
+{
+ /* TODO : ref() */
+
+ return format->classes[index];
+
+}
+
+
+
+
+
diff --git a/plugins/dex/format.h b/plugins/dex/format.h
new file mode 100755
index 0000000..0398b9c
--- /dev/null
+++ b/plugins/dex/format.h
@@ -0,0 +1,77 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * format.h - prototypes pour le support du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DEX_FORMAT_H
+#define _PLUGINS_DEX_FORMAT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+
+#include <core/formats.h>
+
+
+#include "dex_def.h"
+
+
+
+#define G_TYPE_DEX_FORMAT g_dex_format_get_type()
+#define G_DEX_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dex_format_get_type(), GDexFormat))
+#define G_IS_DEX_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dex_format_get_type()))
+#define G_DEX_FORMAT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dex_format_get_type(), GDexFormatIface))
+#define G_DEX_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_FORMAT, GDexFormatClass))
+
+
+/* Format d'exécutable DEX (instance) */
+typedef struct _GDexFormat GDexFormat;
+
+/* Format d'exécutable DEX (classe) */
+typedef struct _GDexFormatClass GDexFormatClass;
+
+
+/* Indique si le format peut être pris en charge ici. */
+FormatMatchStatus dex_is_matching(GBinContent *, GExeFormat *, void *, char **);
+
+/* Indique le type défini pour un format d'exécutable DEX. */
+GType g_dex_format_get_type(void);
+
+/* Prend en charge un nouveau format DEX. */
+GBinFormat *g_dex_format_new(GBinContent *, GExeFormat *, GtkStatusStack *);
+
+/* Présente l'en-tête DEX du format chargé. */
+const dex_header *g_dex_format_get_header(const GDexFormat *);
+
+/* Redéfinition : classe issue du code source (instance) */
+typedef struct _GDexClass GDexClass;
+
+/* Dénombre le nombre de classes trouvées. */
+size_t g_dex_format_count_classes(const GDexFormat *);
+
+/* Fournit une classe du format chargée en mémoire. */
+GDexClass *g_dex_format_get_class(const GDexFormat *, size_t);
+
+
+
+#endif /* _PLUGINS_DEX_FORMAT_H */
diff --git a/plugins/dex/loading.c b/plugins/dex/loading.c
new file mode 100644
index 0000000..c00d0c5
--- /dev/null
+++ b/plugins/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-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "loading.h"
+
+
+#include <i18n.h>
+#include <glibext/delayed-int.h>
+#include <gui/panels/log.h>
+
+
+#include "pool.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/plugins/dex/loading.h b/plugins/dex/loading.h
new file mode 100644
index 0000000..612f962
--- /dev/null
+++ b/plugins/dex/loading.h
@@ -0,0 +1,63 @@
+
+/* 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-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DEX_LOADING_H
+#define _PLUGINS_DEX_LOADING_H
+
+
+#include <gtkext/gtkstatusstack.h>
+
+
+#include "format.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 /* _PLUGINS_DEX_LOADING_H */
diff --git a/plugins/dex/method.c b/plugins/dex/method.c
new file mode 100644
index 0000000..0f49154
--- /dev/null
+++ b/plugins/dex/method.c
@@ -0,0 +1,489 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * method.c - manipulation des methodes du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "method.h"
+
+
+#include <stddef.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "dex-int.h"
+#include "pool.h"
+
+
+
+
+/* Methode issue du code source (instance) */
+struct _GDexMethod
+{
+ GObject parent; /* A laisser en premier */
+
+ GBinRoutine *routine; /* Représentation interne */
+
+ /* FIXME : méthode interne seulement */
+ encoded_method info; /* Propriétés de la méthode */
+ bool has_body; /* Indication de présence */
+ code_item body; /* Corps de la méthode */
+ off_t offset; /* Position du code */
+
+};
+
+/* Methode issue du code source (classe) */
+struct _GDexMethodClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Procède à l'initialisation d'une methode issue du code. */
+static void g_dex_method_class_init(GDexMethodClass *);
+
+/* Procède à l'initialisation d'une methode issue du code. */
+static void g_dex_method_init(GDexMethod *);
+
+/* Supprime toutes les références externes. */
+static void g_dex_method_dispose(GDexMethod *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dex_method_finalize(GDexMethod *);
+
+
+
+/* Détermine le type d'une methode issue du code source. */
+G_DEFINE_TYPE(GDexMethod, g_dex_method, G_TYPE_OBJECT);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe de composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'une methode issue du code. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_method_class_init(GDexMethodClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_method_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_dex_method_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = composant GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation d'une methode issue du code. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_method_init(GDexMethod *method)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_method_dispose(GDexMethod *method)
+{
+ if (method->routine != NULL)
+ g_object_unref(G_OBJECT(method->routine));
+
+ G_OBJECT_CLASS(g_dex_method_parent_class)->dispose(G_OBJECT(method));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_dex_method_finalize(GDexMethod *method)
+{
+ if (method->has_body)
+ reset_dex_code_item(&method->body);
+
+ G_OBJECT_CLASS(g_dex_method_parent_class)->finalize(G_OBJECT(method));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter. *
+* seed = graine des informations à extraire. *
+* last = dernier indice utilisé (à mettre à jour). [OUT] *
+* *
+* Description : Crée une nouvelle représentation de methode issue de code. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexMethod *g_dex_method_new_defined(GDexFormat *format, const encoded_method *seed, uleb128_t *last)
+{
+ GDexMethod *result; /* Composant à retourner */
+ vmpa2t addr; /* Tête de lecture générique */
+ code_item item; /* Corps de la méthode */
+ phys_t ins_offset; /* Position physique du code */
+ mrange_t range; /* Emplacement du code associé */
+
+ *last += seed->method_idx_diff;
+
+ result = get_method_from_dex_pool(format, *last);
+
+ if (result == NULL)
+ return NULL;
+
+ result->info = *seed;
+
+ result->has_body = (seed->code_off > 0);
+
+ if (result->has_body)
+ {
+ init_vmpa(&addr, seed->code_off, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_code_item(format, &addr, &item))
+ goto gdmnd_bad_code_item;
+
+ ins_offset = seed->code_off + offsetof(code_item, insns);
+
+ if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), ins_offset, &addr))
+ goto gdmnd_bad_translation;
+
+ result->body = item;
+
+ result->offset = ins_offset;
+
+ init_mrange(&range, &addr, item.insns_size * sizeof(uint16_t));
+ g_binary_symbol_set_range(G_BIN_SYMBOL(result->routine), &range);
+
+ }
+
+ return result;
+
+ gdmnd_bad_translation:
+
+ reset_dex_code_item(&item);
+
+ gdmnd_bad_code_item:
+
+ g_object_unref(G_OBJECT(result));
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter.*
+* method_id = informations de base quant à la méthode. *
+* *
+* Description : Crée une nouvelle représentation de methode vide. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexMethod *g_dex_method_new_callable(GDexFormat *format, const method_id_item *method_id)
+{
+ GDexMethod *result; /* Composant à retourner */
+ const char *name; /* Nom de la routine finale */
+ GBinRoutine *routine; /* Routine représentée */
+
+ result = NULL;
+
+ name = get_string_from_dex_pool(format, method_id->name_idx, NULL);
+ if (name == NULL) goto gdmne_exit;
+
+ routine = get_prototype_from_dex_pool(format, method_id->proto_idx);
+ if (routine == NULL) goto gdmne_exit;
+
+ g_binary_routine_set_name(routine, strdup(name));
+
+ result = g_object_new(G_TYPE_DEX_METHOD, NULL);
+
+ result->routine = routine;
+
+ gdmne_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = représentation interne de la méthode à consulter. *
+* *
+* Description : Fournit les indications Dex concernant la méthode. *
+* *
+* Retour : Données brutes du binaire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const encoded_method *g_dex_method_get_dex_info(const GDexMethod *method)
+{
+ return &method->info;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = représentation interne de la méthode à consulter. *
+* *
+* Description : Indique si du code est rattaché à une méthode Dex. *
+* *
+* Retour : true si la méthode n'est pas abstraite ni native. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_dex_method_has_dex_body(const GDexMethod *method)
+{
+ return method->has_body;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = représentation interne de la méthode à consulter. *
+* *
+* Description : Fournit les indications Dex relatives au corps de la méthode.*
+* *
+* Retour : Données brutes du binaire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const code_item *g_dex_method_get_dex_body(const GDexMethod *method)
+{
+ return (method->has_body ? &method->body : NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = représentation interne du format DEX à consulter. *
+* *
+* Description : Fournit la routine Chrysalide correspondant à la méthode. *
+* *
+* Retour : Instance de routine mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinRoutine *g_dex_method_get_routine(const GDexMethod *method)
+{
+ GBinRoutine *result; /* Instance à retourner */
+
+ result = method->routine;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = représentation interne du format DEX à consulter. *
+* format = format permettant d'obtenir une adresse complète. *
+* *
+* Description : Intègre la méthode en tant que portion de code. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_dex_method_include_as_portion(const GDexMethod *method, GExeFormat *format)
+{
+ vmpa2t addr; /* Emplacement dans le binaire */
+ GBinPortion *new; /* Nouvelle portion définie */
+
+ /* Si la taille est nulle, on ne fait rien */
+ if (method->info.access_flags & ACC_NATIVE)
+ return;
+
+ if (!method->has_body)
+ return;
+
+ if (!g_exe_format_translate_offset_into_vmpa(format, method->offset, &addr))
+ return;
+
+ new = g_binary_portion_new(BPC_CODE, &addr, method->body.insns_size * sizeof(uint16_t));
+
+ g_binary_portion_set_desc(new, _("Dalvik code"));
+
+ g_binary_portion_set_rights(new, PAC_READ | PAC_EXEC);
+
+ g_exe_format_include_portion(format, new, &method->info.origin);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = représentation interne du format DEX à consulter. *
+* offset = position physique à renseigner. [OUT] *
+* *
+* Description : Indique la position de la méthode au sein du binaire. *
+* *
+* Retour : Validiter de la position dans le contenu binaire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_dex_method_get_offset(const GDexMethod *method, phys_t *offset)
+{
+ bool result; /* Indication à retourner */
+
+ result = method->has_body;
+
+ if (result)
+ *offset = method->offset;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = représentation interne du format DEX à consulter. *
+* index = indice de base comme seul indice. *
+* *
+* Description : Fournit des indications sur la nature d'une variable donnée. *
+* *
+* Retour : Indentifiant complet d'une variable utilisée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+DexVariableIndex g_dex_method_get_variable(const GDexMethod *method, uint32_t index)
+{
+ const encoded_method *info; /* Propriétés de la méthode */
+ const code_item *body; /* Corps de la méthode */
+ uint32_t pivot; /* Bascule pour les arguments */
+
+ info = &method->info;
+ body = &method->body;
+
+ /* S'agit-il d'un argument ? */
+
+ pivot = body->registers_size - body->ins_size;
+
+ if (!(info->access_flags & ACC_STATIC))
+ pivot++;
+
+ if (index >= pivot)
+ return (index - pivot) | DVI_ARGUMENT;
+
+ /* S'agit-il de "this" ? */
+
+ if (!(info->access_flags & ACC_STATIC)
+ && index == (body->registers_size - body->ins_size))
+ return DVI_THIS;
+
+ /* Alors il s'agit d'une variable locale... */
+
+ return index | DVI_LOCAL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : method = informations chargées à consulter. *
+* lang = langage à utiliser pour la sortie humaine. *
+* buffer = tampon mis à disposition pour la sortie. *
+* *
+* Description : Procède à la décompilation complète d'une routine donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#if 0
+void g_dex_method_decompile(const GDexMethod *method, GLangOutput *lang, GCodeBuffer *buffer)
+{
+ g_binary_routine_print_code(method->routine, lang, buffer, true);
+
+}
+#endif
diff --git a/plugins/dex/method.h b/plugins/dex/method.h
new file mode 100644
index 0000000..6716713
--- /dev/null
+++ b/plugins/dex/method.h
@@ -0,0 +1,104 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * method.h - prototypes pour la manipulation des methodes du format DEX
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DEX_METHOD_H
+#define _PLUGINS_DEX_METHOD_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/routine.h>
+
+
+#include "dex_def.h"
+#include "format.h"
+
+
+
+#define G_TYPE_DEX_METHOD (g_dex_method_get_type())
+#define G_DEX_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_METHOD, GDexMethod))
+#define G_DEX_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_METHOD, GDexMethodClass))
+#define G_IS_DEX_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_METHOD))
+#define G_IS_DEX_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_METHOD))
+#define G_DEX_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_METHOD, GDexMethodClass))
+
+
+
+/* Methode issue du code source (instance) */
+typedef struct _GDexMethod GDexMethod;
+
+/* Methode issue du code source (classe) */
+typedef struct _GDexMethodClass GDexMethodClass;
+
+
+/* Détermination des variables */
+typedef enum _DexVariableIndex
+{
+ /* Indices... */
+
+ DVI_LOCAL = (1 << 29),
+ DVI_THIS = (1 << 30),
+ DVI_ARGUMENT = (1 << 31)
+
+} DexVariableIndex;
+
+#define DVI_INDEX(v) (v & ~(7 << 29))
+
+
+/* Détermine le type d'une methode issue du code source. */
+GType g_dex_method_get_type(void);
+
+/* Crée une nouvelle représentation de methode issue de code. */
+GDexMethod *g_dex_method_new_defined(GDexFormat *, const encoded_method *, uleb128_t *);
+
+/* Crée une nouvelle représentation de methode vide. */
+GDexMethod *g_dex_method_new_callable(GDexFormat *, const method_id_item *);
+
+/* Fournit les indications Dex concernant la méthode. */
+const encoded_method *g_dex_method_get_dex_info(const GDexMethod *);
+
+/* Indique si du code est rattaché à une méthode Dex. */
+bool g_dex_method_has_dex_body(const GDexMethod *);
+
+/* Fournit les indications Dex relatives au corps de la méthode. */
+const code_item *g_dex_method_get_dex_body(const GDexMethod *);
+
+/* Fournit la routine Chrysalide correspondant à la méthode. */
+GBinRoutine *g_dex_method_get_routine(const GDexMethod *);
+
+/* Intègre la méthode en tant que portion de code. */
+void g_dex_method_include_as_portion(const GDexMethod *, GExeFormat *);
+
+/* Indique la position de la méthode au sein du binaire. */
+bool g_dex_method_get_offset(const GDexMethod *method, phys_t *);
+
+/* Fournit des indications sur la nature d'une variable donnée. */
+DexVariableIndex g_dex_method_get_variable(const GDexMethod *, uint32_t);
+
+/* Procède à la décompilation complète d'une routine donnée. */
+//void g_dex_method_decompile(const GDexMethod *, GLangOutput *, GCodeBuffer *);
+
+
+
+#endif /* _PLUGINS_DEX_METHOD_H */
diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c
new file mode 100644
index 0000000..3c97da3
--- /dev/null
+++ b/plugins/dex/pool.c
@@ -0,0 +1,686 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pool.c - extraction des informations issues des tables globales
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "pool.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include <i18n.h>
+#include <core/global.h>
+#include <format/mangling/demangler.h>
+#include <format/mangling/dex/context.h>
+
+
+#include "dex-int.h"
+#include "loading.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à analyser. *
+* *
+* Description : Charge en mémoire toutes les chaînes trouvées. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool find_all_dex_strings(GDexFormat *format)
+{
+ GBinFormat *base; /* Autre version du format */
+ uint32_t i; /* Boucle de parcours */
+ mrange_t range; /* Couverture associée */
+ const char *text; /* Texte issu du binaire */
+ GBinSymbol *symbol; /* Nouveau symbole construit */
+ char *label; /* Désignation de la chaîne */
+
+ base = G_BIN_FORMAT(format);
+
+ for (i = 0; i < format->header.string_ids_size; i++)
+ {
+ text = get_string_from_dex_pool(format, i, &range);
+ if (text == NULL) continue;
+
+ symbol = g_binary_symbol_new(&range, STP_STRING);
+
+ label = create_string_label(base, get_mrange_addr(&range), get_mrange_length(&range));
+
+ g_binary_symbol_set_alt_label(symbol, label);
+
+ free(label);
+
+ g_binary_format_add_symbol(base, symbol);
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter. *
+* index = index du type recherchée. *
+* range = éventuelle couverture à renseigner ou NULL. [OUT] *
+* *
+* Description : Extrait une chaîne de caractères d'une table DEX. *
+* *
+* Retour : Chaîne de caractères trouvées ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index, mrange_t *range)
+{
+ off_t pos; /* Tête de lecture */
+ vmpa2t addr; /* Tête de lecture générique */
+ string_id_item str_id; /* Identifiant de chaîne */
+ string_data_item str_data; /* Description de chaîne */
+ vmpa2t start; /* Début de la chaîne */
+ phys_t diff; /* Avancée de tête de lecture */
+
+ if (index >= format->header.string_ids_size)
+ return NULL;
+
+ pos = format->header.string_ids_off + index * sizeof(string_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_string_id_item(format, &addr, &str_id))
+ return NULL;
+
+ pos = str_id.string_data_off;
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_string_data_item(format, &addr, &str_data))
+ return NULL;
+
+ if (range != NULL)
+ {
+ init_vmpa(&start, pos, VMPA_NO_VIRTUAL);
+ diff = compute_vmpa_diff(&start, &addr);
+
+ init_mrange(range, &start, diff);
+
+ }
+
+ return (const char *)str_data.data;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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 */
+ 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 < runs_count; i++)
+ {
+ begin = i * run_size;
+
+ if ((i + 1) == runs_count)
+ end = format->header.type_ids_size;
+ else
+ end = begin + run_size;
+
+ loading = g_dex_loading_new(format, begin, end, msg,
+ (dex_loading_cb)get_type_from_dex_pool, &result);
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter. *
+* index = index du type recherchée. *
+* *
+* Description : Extrait une représentation de type d'une table DEX. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index)
+{
+ GDataType *result; /* Instance à retourner */
+ phys_t pos; /* Tête de lecture */
+ vmpa2t addr; /* Tête de lecture générique */
+ type_id_item type_id; /* Définition de la classe */
+ string_id_item str_id; /* Identifiant de chaîne */
+ string_data_item str_data; /* Description de chaîne */
+
+ result = NULL;
+
+ if (index >= format->header.type_ids_size)
+ goto gtfdp_error;
+
+ if (format->types[index] == NULL)
+ {
+ pos = format->header.type_ids_off + index * sizeof(type_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_type_id_item(format, &addr, &type_id))
+ goto gtfdp_error;
+
+ pos = format->header.string_ids_off + type_id.descriptor_idx * sizeof(string_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_string_id_item(format, &addr, &str_id))
+ goto gtfdp_error;
+
+ pos = str_id.string_data_off;
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_string_data_item(format, &addr, &str_data))
+ goto gtfdp_error;
+
+ format->types[index] = demangle_type(G_TYPE_DEX_DEMANGLER, (char *)str_data.data);
+
+ }
+
+ result = format->types[index];
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ gtfdp_error:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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 */
+ 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 < runs_count; i++)
+ {
+ begin = i * run_size;
+
+ if ((i + 1) == runs_count)
+ end = format->header.field_ids_size;
+ else
+ end = begin + run_size;
+
+ loading = g_dex_loading_new(format, begin, end, msg,
+ (dex_loading_cb)get_field_from_dex_pool, &result);
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter. *
+* index = index du champ recherché. *
+* *
+* Description : Extrait une représentation de champ d'une table DEX. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinVariable *get_field_from_dex_pool(GDexFormat *format, uint32_t index)
+{
+ GBinVariable *result; /* Instance à retourner */
+ phys_t pos; /* Tête de lecture */
+ vmpa2t addr; /* Tête de lecture générique */
+ field_id_item field_id; /* Description du champ */
+ GDataType *type; /* Type du champ */
+ const char *name; /* Désignation humaine */
+ GBinVariable *field; /* Instance nouvelle à définir */
+ GDataType *owner; /* Propriétaire du champ */
+
+ result = NULL;
+
+ if (index >= format->header.field_ids_size)
+ goto gffdp_error;
+
+ if (format->fields[index] == NULL)
+ {
+ pos = format->header.field_ids_off + index * sizeof(field_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_field_id_item(format, &addr, &field_id))
+ goto gffdp_error;
+
+ type = get_type_from_dex_pool(format, field_id.type_idx);
+ if (type == NULL) goto gffdp_error;
+
+ name = get_string_from_dex_pool(format, field_id.name_idx, NULL);
+ if (name == NULL) goto gffdp_bad_name;
+
+ field = g_binary_variable_new(type);
+ g_binary_variable_set_name(field, name);
+
+ if (field_id.class_idx != NO_INDEX)
+ {
+ owner = get_type_from_dex_pool(format, field_id.class_idx);
+ if (owner == NULL) goto gffdp_bad_owner;
+
+ g_binary_variable_set_owner(field, owner);
+
+ }
+
+ format->fields[index] = field;
+
+ }
+
+ result = format->fields[index];
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ gffdp_error:
+
+ return result;
+
+ gffdp_bad_owner:
+
+ g_object_ref(G_OBJECT(type));
+ g_object_unref(G_OBJECT(result));
+
+ gffdp_bad_name:
+
+ g_object_unref(G_OBJECT(type));
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter. *
+* index = index de la routine recherchée. *
+* *
+* Description : Extrait une représentation de routine d'une table DEX. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index)
+{
+ GBinRoutine *result; /* Instance à retourner */
+ phys_t pos; /* Tête de lecture */
+ vmpa2t addr; /* Tête de lecture générique */
+ proto_id_item proto_id; /* Prototype de routine */
+ GDataType *type; /* Type de retour */
+ const char *name; /* Description compressée */
+ type_list args; /* Liste des arguments */
+ uint32_t i; /* Boucle de parcours */
+ GBinVariable *arg; /* Argument reconstitué */
+
+ result = NULL;
+
+ /**
+ * Les prototypes sont personnalisés après chargement.
+ * Donc on ne peut pas conserver de version globale comme pour
+ * les autres éléments de la table des constantes.
+ */
+
+ if (index >= format->header.proto_ids_size)
+ goto grfdp_error;
+
+ pos = format->header.proto_ids_off + index * sizeof(proto_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_proto_id_item(format, &addr, &proto_id))
+ goto grfdp_error;
+
+ /* Type de retour */
+
+ type = get_type_from_dex_pool(format, proto_id.return_type_idx);
+
+ /* Nom de la méthode */
+
+ name = get_string_from_dex_pool(format, proto_id.shorty_idx, NULL);
+
+ /* Liste des arguments */
+
+ pos = proto_id.parameters_off;
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ result = g_binary_routine_new();///////////////////////
+
+ if (read_dex_type_list(format, &addr, &args))
+ for (i = 0; i < args.size; i++)
+ {
+ type = get_type_from_dex_pool(format, args.list[i].type_idx);
+ if (type == NULL) continue;
+
+ arg = g_binary_variable_new(type);
+ g_binary_routine_add_arg(result, arg);///////////////////////
+
+ }
+
+ /* Mise en place finale */
+
+ ///////result = demangle_routine(G_TYPE_DEX_DEMANGLER, name);
+
+ g_binary_routine_set_name(result, strdup("..."));
+
+#if 1
+ if (result != NULL)///////////////////////
+ g_binary_routine_set_return_type(result, type);
+#endif
+
+ /*
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+ */
+
+ grfdp_error:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter. *
+* index = index de la classe recherchée. *
+* *
+* Description : Extrait une représentation de méthode d'une table DEX. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index)
+{
+ GDexMethod *result; /* Instance à retourner */
+ phys_t pos; /* Tête de lecture */
+ vmpa2t addr; /* Tête de lecture générique */
+ method_id_item method_id; /* Définition de la méthode */
+
+ result = NULL;
+
+ if (index >= format->header.method_ids_size)
+ goto gmfdp_error;
+
+ /**
+ * On charge ici une méthode à partir de la définition de 'method_id_item'.
+ *
+ * C'est l'élément 'encoded_method' qui référence cette cette définition et qui
+ * applique ensuite les attributs finaux de la méthode. La classe parente est
+ * précisée en outre bien en amont.
+ *
+ * Comme une même définition peut donc servir à plusieurs instances,
+ * on ne peut pas conserver un tableau d'allocations communes.
+ */
+
+ pos = format->header.method_ids_off + index * sizeof(method_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_method_id_item(format, &addr, &method_id))
+ goto gmfdp_error;
+
+ result = g_dex_method_new_callable(format, &method_id);
+
+ gmfdp_error:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à compléter. *
+* gid = groupe de travail impliqué. *
+ status = barre de statut à tenir informée. *
+* *
+* Description : Charge toutes les classes listées dans le contenu binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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 */
+ 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 < runs_count; i++)
+ {
+ begin = i * run_size;
+
+ if ((i + 1) == runs_count)
+ end = format->header.class_defs_size;
+ else
+ end = begin + run_size;
+
+ loading = g_dex_loading_new(format, begin, end, msg,
+ (dex_loading_cb)get_class_from_dex_pool, &result);
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à consulter. *
+* index = index de la classe recherchée. *
+* *
+* Description : Extrait une représentation de classe d'une table DEX. *
+* *
+* Retour : Composant GLib créé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexClass *get_class_from_dex_pool(GDexFormat *format, uint32_t index)
+{
+ GDexClass *result; /* Instance à retourner */
+ phys_t pos; /* Tête de lecture */
+ vmpa2t addr; /* Tête de lecture générique */
+ class_def_item class_def; /* Définition de la classe */
+
+ result = NULL;
+
+ if (index >= format->header.class_defs_size)
+ goto gcfdp_error;
+
+ if (format->classes[index] == NULL)
+ {
+ pos = format->header.class_defs_off + index * sizeof(class_def_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ if (!read_dex_class_def_item(format, &addr, &class_def))
+ goto gcfdp_error;
+
+ format->classes[index] = g_dex_class_new(format, &class_def);
+
+ }
+
+ result = format->classes[index];
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ gcfdp_error:
+
+ return result;
+
+}
diff --git a/plugins/dex/pool.h b/plugins/dex/pool.h
new file mode 100644
index 0000000..56bcd64
--- /dev/null
+++ b/plugins/dex/pool.h
@@ -0,0 +1,74 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pool.h - prototypes pour l'extraction des informations issues des tables globales
+ *
+ * Copyright (C) 2010-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DEX_POOL_H
+#define _PLUGINS_DEX_POOL_H
+
+
+#include <analysis/routine.h>
+#include <glibext/delayed.h>
+
+
+#include "class.h"
+#include "format.h"
+#include "method.h"
+
+
+
+/* Charge en mémoire toutes les chaînes trouvées. */
+bool find_all_dex_strings(GDexFormat *);
+
+/* Extrait une chaîne de caractères d'une table DEX. */
+const char *get_string_from_dex_pool(const GDexFormat *, uint32_t, mrange_t *);
+
+
+
+
+
+/* Charge en mémoire l'ensemble des types du format DEX. */
+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 *, wgroup_id_t, GtkStatusStack *);
+
+/* Extrait une représentation de champ d'une table DEX. */
+GBinVariable *get_field_from_dex_pool(GDexFormat *, uint32_t);
+
+/* Extrait une représentation de routine d'une table DEX. */
+GBinRoutine *get_prototype_from_dex_pool(GDexFormat *, uint32_t);
+
+/* Extrait une représentation de méthode d'une table DEX. */
+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 *, wgroup_id_t, GtkStatusStack *);
+
+/* Extrait une représentation de classe d'une table DEX. */
+GDexClass *get_class_from_dex_pool(GDexFormat *, uint32_t);
+
+
+
+#endif /* _PLUGINS_DEX_POOL_H */
diff --git a/plugins/dex/python/Makefile.am b/plugins/dex/python/Makefile.am
new file mode 100644
index 0000000..fc6f85e
--- /dev/null
+++ b/plugins/dex/python/Makefile.am
@@ -0,0 +1,16 @@
+
+noinst_LTLIBRARIES = libdexpython.la
+
+libdexpython_la_SOURCES = \
+ class.h class.c \
+ format.h format.c \
+ module.h module.c
+
+
+libdexpython_la_LDFLAGS =
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/dex/python/class.c b/plugins/dex/python/class.c
new file mode 100644
index 0000000..ec1c3f7
--- /dev/null
+++ b/plugins/dex/python/class.c
@@ -0,0 +1,107 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * class.c - équivalent Python du fichier "plugins/dex/class.c"
+ *
+ * Copyright (C) 2012-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "class.h"
+
+
+#include <pygobject.h>
+
+
+#include <plugins/pychrysa/helpers.h>
+
+
+#include "../class.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_dex_class_type(void)
+{
+ static PyMethodDef py_dex_class_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_dex_class_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_dex_class_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.format.dex.DexClass",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = "PyChrysalide Dex class.",
+
+ .tp_methods = py_dex_class_methods,
+ .tp_getset = py_dex_class_getseters
+
+ };
+
+ return &py_dex_class_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.format.dex.DexClass'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_dex_class(PyObject *module)
+{
+ PyTypeObject *py_dex_class_type; /* Type Python 'DexClass' */
+ PyObject *dict; /* Dictionnaire du module */
+
+ py_dex_class_type = get_python_dex_class_type();
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_CLASS, py_dex_class_type, &PyGObject_Type))
+ return false;
+
+ return true;
+
+}
diff --git a/plugins/dex/python/class.h b/plugins/dex/python/class.h
new file mode 100644
index 0000000..02ec882
--- /dev/null
+++ b/plugins/dex/python/class.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * class.h - prototypes pour l'équivalent Python du fichier "plugins/dex/class.h"
+ *
+ * Copyright (C) 2012-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_DEX_PYTHON_CLASS_H
+#define _PLUGINS_DEX_PYTHON_CLASS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_dex_class_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.dex.DexClass'. */
+bool register_python_dex_class(PyObject *module);
+
+
+
+#endif /* _PLUGINS_DEX_PYTHON_CLASS_H */
diff --git a/plugins/dex/python/format.c b/plugins/dex/python/format.c
new file mode 100644
index 0000000..74f6eae
--- /dev/null
+++ b/plugins/dex/python/format.c
@@ -0,0 +1,287 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * format.c - équivalent Python du fichier "plugins/dex/format.c"
+ *
+ * Copyright (C) 2012-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "format.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysa/helpers.h>
+#include <plugins/pychrysa/analysis/binary.h>
+#include <plugins/pychrysa/analysis/content.h>
+#include <plugins/pychrysa/format/executable.h>
+
+
+#include "../class.h"
+#include "../format.h"
+
+
+
+/* Crée un nouvel objet Python de type 'DexFormat'. */
+static PyObject *py_dex_format_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Dénombre le nombre de classes trouvées. */
+static PyObject *py_dex_format_count_classes(PyObject *, PyObject *);
+
+/* Fournit une classe du format chargée en mémoire. */
+static PyObject *py_dex_format_get_class(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de l'objet à instancier. *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Crée un nouvel objet Python de type 'DexFormat'. *
+* *
+* Retour : Instance Python mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_dex_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Instance à retourner */
+ PyObject *content_obj; /* Objet pour le contenu */
+ PyObject *parent_obj; /* Objet pour le parent */
+ PyObject *status_obj; /* Objet pour la progression */
+ int ret; /* Bilan de lecture des args. */
+ GBinContent *content; /* Instance GLib du contenu */
+ GExeFormat *parent; /* Instance GLib du parent */
+ GtkStatusStack *status; /* Instance GTK de suivi */
+ GBinFormat *format; /* Création GLib à transmettre */
+
+ ret = PyArg_ParseTuple(args, "OOO", &content_obj, &parent_obj, &status_obj);
+ if (!ret) return NULL;
+
+ ret = PyObject_IsInstance(content_obj, (PyObject *)get_python_binary_content_type());
+ if (!ret)
+ {
+ PyErr_SetString(PyExc_TypeError, _("The first argument must be an instance of BinContent."));
+ return NULL;
+ }
+
+ content = G_BIN_CONTENT(pygobject_get(content_obj));
+
+ if (parent_obj == Py_None)
+ parent = NULL;
+
+ else
+ {
+ ret = PyObject_IsInstance(parent_obj, (PyObject *)get_python_executable_format_type());
+ if (!ret)
+ {
+ PyErr_SetString(PyExc_TypeError, _("The second argument must be a container format or None."));
+ return NULL;
+ }
+
+ parent = G_EXE_FORMAT(pygobject_get(parent_obj));
+
+ }
+
+ if (status_obj == Py_None)
+ status = NULL;
+
+ else
+ {
+ ret = PyObject_IsInstance(status_obj, (PyObject *)get_python_binary_content_type());
+ if (!ret)
+ {
+ PyErr_SetString(PyExc_TypeError, _("The third argument must be a status bar object or None."));
+ return NULL;
+ }
+
+ status = GTK_STATUS_STACK(pygobject_get(status_obj));
+
+ }
+
+ format = g_dex_format_new(content, parent, status);
+ if (format == NULL)
+ {
+ PyErr_SetString(PyExc_RuntimeError, _("Unable to load the DEX format."));
+ return NULL;
+ }
+
+ result = pygobject_new(G_OBJECT(format));
+
+ g_object_unref(format);
+
+ return (PyObject *)result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un binaire. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Dénombre le nombre de classes trouvées. *
+* *
+* Retour : Quantité de classes présentes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_dex_format_count_classes(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ GDexFormat *format; /* Version native */
+ size_t count; /* Quantité à retourner */
+
+ format = G_DEX_FORMAT(pygobject_get(self));
+
+ count = g_dex_format_count_classes(format);
+
+ result = PyLong_FromLong(count);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un binaire. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Fournit une classe du format chargée en mémoire. *
+* *
+* Retour : Instance représentant une classe chargée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_dex_format_get_class(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ int ret; /* Bilan de lecture des args. */
+ int index; /* Indice de la classe */
+ GDexFormat *format; /* Version native */
+ GDexClass *class; /* Classe à communiquer */
+
+ ret = PyArg_ParseTuple(args, "i", &index);
+ if (!ret) Py_RETURN_NONE;
+
+ format = G_DEX_FORMAT(pygobject_get(self));
+
+ class = g_dex_format_get_class(format, index);
+ if (class == NULL) Py_RETURN_NONE;
+
+ result = pygobject_new(G_OBJECT(class));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_dex_format_type(void)
+{
+ static PyMethodDef py_dex_format_methods[] = {
+ {
+ "count_classes", (PyCFunction)py_dex_format_count_classes,
+ METH_NOARGS,
+ "count_classes($self, /)\n--\n\nCount the quantity of loaded Dex classes."
+ },
+ {
+ "get_class", (PyCFunction)py_dex_format_get_class,
+ METH_VARARGS,
+ "get_class($self, index, /)\n--\n\nProvide a given loaded Dex class."
+ },
+ { NULL }
+ };
+
+ static PyGetSetDef py_dex_format_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_dex_format_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.format.dex.DexFormat",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = "PyChrysalide Dex format",
+
+ .tp_methods = py_dex_format_methods,
+ .tp_getset = py_dex_format_getseters,
+ .tp_new = (newfunc)py_dex_format_new
+
+ };
+
+ return &py_dex_format_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.format.dex.DexFormat'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_dex_format(PyObject *module)
+{
+ PyTypeObject *py_dex_format_type; /* Type Python 'DexFormat' */
+ PyObject *dict; /* Dictionnaire du module */
+
+ py_dex_format_type = get_python_dex_format_type();
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_DEX_FORMAT,
+ py_dex_format_type, get_python_executable_format_type()))
+ return false;
+
+ return true;
+
+}
diff --git a/plugins/dex/python/format.h b/plugins/dex/python/format.h
new file mode 100644
index 0000000..4a365c9
--- /dev/null
+++ b/plugins/dex/python/format.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * format.h - prototypes pour l'équivalent Python du fichier "plugins/dex/format.h"
+ *
+ * Copyright (C) 2012-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_DEX_PYTHON_FORMAT_H
+#define _PLUGINS_DEX_PYTHON_FORMAT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_dex_format_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.dex.DexFormat'. */
+bool register_python_dex_format(PyObject *);
+
+
+
+#endif /* _PLUGINS_DEX_PYTHON_FORMAT_H */
diff --git a/plugins/dex/python/module.c b/plugins/dex/python/module.c
new file mode 100644
index 0000000..8d5092d
--- /dev/null
+++ b/plugins/dex/python/module.c
@@ -0,0 +1,95 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire dex en tant que module
+ *
+ * Copyright (C) 2012-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysa/access.h>
+
+
+#include "class.h"
+#include "format.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'format.dex' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_format_dex_module_to_python_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+ int ret; /* Bilan d'un appel */
+
+ static PyModuleDef py_chrysalide_dex_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.format.dex",
+ .m_doc = "Python module for Chrysalide.format.dex",
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.format");
+
+ module = PyModule_Create(&py_chrysalide_dex_module);
+ if (module == NULL) return false;
+
+ ret = PyState_AddModule(super, &py_chrysalide_dex_module);
+ if (ret != 0) goto loading_failed;
+
+ ret = _PyImport_FixupBuiltin(module, "pychrysalide.format.dex");
+ if (ret != 0) goto loading_failed;
+
+ Py_INCREF(module);
+ ret = PyModule_AddObject(super, "dex", module);
+ if (ret != 0) goto loading_failed;
+
+ result = register_python_dex_class(module);
+
+ if (result)
+ result = register_python_dex_format(module);
+
+ loading_failed:
+
+ return result;
+
+}
diff --git a/plugins/dex/python/module.h b/plugins/dex/python/module.h
new file mode 100644
index 0000000..d1540d7
--- /dev/null
+++ b/plugins/dex/python/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire dex en tant que module
+ *
+ * Copyright (C) 2012-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_DEX_PYTHON_MODULE_H
+#define _PLUGINS_DEX_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'format.dex' au module Python. */
+bool add_format_dex_module_to_python_module(void);
+
+
+
+#endif /* _PLUGINS_DEX_PYTHON_MODULE_H */