summaryrefslogtreecommitdiff
path: root/plugins/dex/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/dex/class.c')
-rw-r--r--plugins/dex/class.c254
1 files changed, 241 insertions, 13 deletions
diff --git a/plugins/dex/class.c b/plugins/dex/class.c
index 5cd159b..ef3ed85 100644
--- a/plugins/dex/class.c
+++ b/plugins/dex/class.c
@@ -28,7 +28,6 @@
#include "dex-int.h"
-#include "method.h"
#include "pool.h"
@@ -38,10 +37,17 @@ struct _GDexClass
{
GObject parent; /* A laisser en premier */
+ GDexFormat *format; /* Lien vers la table globale */
+
class_def_item definition; /* Définition de la classe */
bool has_data; /* Indicateur de présence */
class_data_item data; /* Contenu de la classe */
+ GDexField **static_fields; /* Champs statiques */
+ size_t sfields_count; /* Quantité de ces champs */
+ GDexField **instance_fields; /* Champs propres à la classe */
+ size_t ifields_count; /* Quantité de ces champs */
+
GDexMethod **direct_methods; /* Méthodes propres */
size_t dmethods_count; /* Quantité de ces méthodes */
GDexMethod **virtual_methods; /* Méthodes virtuelles */
@@ -69,9 +75,6 @@ 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. */
@@ -136,6 +139,16 @@ static void g_dex_class_dispose(GDexClass *class)
{
size_t i; /* Boucle de parcours */
+ if (class->static_fields != NULL)
+ for (i = 0; i < class->sfields_count; i++)
+ if (class->static_fields[i] != NULL)
+ g_object_unref(G_OBJECT(class->static_fields[i]));
+
+ if (class->instance_fields != NULL)
+ for (i = 0; i < class->ifields_count; i++)
+ if (class->instance_fields[i] != NULL)
+ g_object_unref(G_OBJECT(class->instance_fields[i]));
+
if (class->direct_methods != NULL)
for (i = 0; i < class->dmethods_count; i++)
if (class->direct_methods[i] != NULL)
@@ -146,6 +159,8 @@ static void g_dex_class_dispose(GDexClass *class)
if (class->virtual_methods[i] != NULL)
g_object_unref(G_OBJECT(class->virtual_methods[i]));
+ g_object_unref(G_OBJECT(class->format));
+
G_OBJECT_CLASS(g_dex_class_parent_class)->dispose(G_OBJECT(class));
}
@@ -165,6 +180,15 @@ static void g_dex_class_dispose(GDexClass *class)
static void g_dex_class_finalize(GDexClass *class)
{
+ if (class->has_data)
+ reset_dex_class_data_item(&class->data);
+
+ if (class->static_fields != NULL)
+ free(class->static_fields);
+
+ if (class->instance_fields != NULL)
+ free(class->instance_fields);
+
if (class->direct_methods != NULL)
free(class->direct_methods);
@@ -194,15 +218,19 @@ 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 */
+ GDexField *field; /* Champ chargé */
+ GDataType *ctype; /* Type créé par la classe */
+ GBinFormat *base; /* Autre version du format */
GDexMethod *method; /* Méthode chargée */
GBinRoutine *routine; /* Version interne de méthode */
result = g_object_new(G_TYPE_DEX_CLASS, NULL);
+ result->format = format;
+ g_object_ref(G_OBJECT(format));
+
result->definition = *def;
result->has_data = (def->class_data_off != 0);
@@ -227,6 +255,42 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
result->data = data;
/**
+ * Chargement des champs de classe.
+ */
+
+ index = 0;
+
+ result->sfields_count = data.static_fields_size;
+ result->static_fields = (GDexField **)calloc(result->sfields_count, sizeof(GDexField *));
+
+ for (i = 0; i < result->sfields_count; i++)
+ {
+ field = g_dex_field_new(format, &data.static_fields[i], &index);
+ if (field == NULL) goto gdcn_bad_field;
+
+ result->static_fields[i] = field;
+
+ }
+
+ index = 0;
+
+ result->ifields_count = data.instance_fields_size;
+ result->instance_fields = (GDexField **)calloc(result->ifields_count, sizeof(GDexField *));
+
+ for (i = 0; i < result->ifields_count; i++)
+ {
+ field = g_dex_field_new(format, &data.instance_fields[i], &index);
+ if (field == NULL) goto gdcn_bad_field;
+
+ result->instance_fields[i] = field;
+
+ }
+
+ /**
+ * Chargement des méthodes de classe.
+ */
+
+ /**
* On évite ici les méthodes (virtuelles) non définies.
*/
if (def->access_flags & ACC_ANNOTATION) goto gdcn_done;
@@ -241,7 +305,7 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
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++)
+ for (i = 0; i < result->dmethods_count; i++)
{
method = g_dex_method_new_defined(format, &data.direct_methods[i], &index);
if (method == NULL) goto gdcn_bad_method;
@@ -267,7 +331,7 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
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++)
+ for (i = 0; i < result->vmethods_count; i++)
{
method = g_dex_method_new_defined(format, &data.virtual_methods[i], &index);
if (method == NULL) goto gdcn_bad_method;
@@ -300,6 +364,8 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
gdcn_unknown_type:
+ gdcn_bad_field:
+
gdcn_bad_item:
g_object_unref(G_OBJECT(result));
@@ -349,6 +415,166 @@ const class_data_item *g_dex_class_get_data(const GDexClass *class)
/******************************************************************************
* *
+* Paramètres : class = informations chargées à consulter. *
+* *
+* Description : Indique le type Android d'une classe. *
+* *
+* Retour : Type de classe ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDataType *g_dex_class_get_class_type(const GDexClass *class)
+{
+ GDataType *result; /* Type à renvoyer */
+
+ result = get_type_from_dex_pool(class->format, class->definition.class_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* *
+* Description : Indique le type Android parent d'une classe. *
+* *
+* Retour : Type de classe ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDataType *g_dex_class_get_superclass_type(const GDexClass *class)
+{
+ GDataType *result; /* Type à renvoyer */
+
+ result = get_type_from_dex_pool(class->format, class->definition.superclass_idx);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* count = taille de la liste constituée. [OUT] *
+* *
+* Description : Indique le type Android des interfaces d'une classe. *
+* *
+* Retour : Types d'interfaces ou NULL si aucune. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDataType **g_dex_class_get_interface_types(const GDexClass *class, size_t *count)
+{
+ GDataType **result; /* Types à renvoyer */
+ vmpa2t addr; /* Tête de lecture générique */
+ type_list interfaces; /* Liste des interfaces */
+ bool status; /* Bilan d'une lecture */
+ size_t i; /* Boucle de parcours */
+
+ if (class->definition.interfaces_off == 0)
+ {
+ *count = 0;
+ result = NULL;
+ }
+
+ else
+ {
+ init_vmpa(&addr, class->definition.interfaces_off, VMPA_NO_VIRTUAL);
+
+ status = read_dex_type_list(class->format, &addr, &interfaces);
+
+ if (status)
+ {
+ *count = interfaces.size;
+ result = (GDataType **)malloc(*count * sizeof(GDataType *));
+
+ for (i = 0; i < *count; i++)
+ result[i] = get_type_from_dex_pool(class->format, interfaces.list[i].type_idx);
+
+ }
+
+ else
+ {
+ *count = 0;
+ result = NULL;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* instance = précise la nature des champs ciblés. *
+* *
+* Description : Dénombre les champs de classe chargés d'une classe donnée. *
+* *
+* Retour : Quantité de champs trouvés. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_dex_class_count_fields(const GDexClass *class, bool instance)
+{
+ size_t result; /* Compte à retourner */
+
+ if (instance)
+ result = class->ifields_count;
+ else
+ result = class->sfields_count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = informations chargées à consulter. *
+* instance = précise la nature des champs ciblés. *
+* index = indique l'indice du champ désiré. *
+* *
+* Description : Fournit un champ chargé correspondant à une classe donnée. *
+* *
+* Retour : Champ intégré ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDexField *g_dex_class_get_field(const GDexClass *class, bool instance, size_t index)
+{
+ GDexField *result; /* Instance à renvoyer */
+
+ if (instance)
+ result = class->instance_fields[index];
+ else
+ result = class->static_fields[index];
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : class = informations chargées à consulter. *
* virtual = précise la nature des méthodes ciblées. *
* *
@@ -382,7 +608,7 @@ size_t g_dex_class_count_methods(const GDexClass *class, bool virtual)
* *
* Description : Fournit une méthode chargée correspondant à un type donné. *
* *
-* Retour : Quantité de méthodes trouvées. *
+* Retour : Méthode intégrée ou NULL. *
* *
* Remarques : - *
* *
@@ -397,6 +623,9 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t
else
result = class->direct_methods[index];
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
return result;
}
@@ -475,8 +704,7 @@ bool g_dex_method_get_offset(const GDexMethod *method, phys_t *offset)
/******************************************************************************
* *
-* Paramètres : class = informations chargées à consulter. *
-* format = représentation interne du format DEX à compléter. *
+* Paramètres : class = informations chargées à consulter. *
* *
* Description : Retrouve si possible le nom du fichier source d'une classe. *
* *
@@ -486,11 +714,11 @@ bool g_dex_method_get_offset(const GDexMethod *method, phys_t *offset)
* *
******************************************************************************/
-const char *g_dex_class_get_source_file(const GDexClass *class, const GDexFormat *format)
+const char *g_dex_class_get_source_file(const GDexClass *class)
{
const char *result; /* Trouvaille à renvoyer */
- result = get_string_from_dex_pool(format, class->definition.source_file_idx, NULL);
+ result = get_string_from_dex_pool(class->format, class->definition.source_file_idx, NULL);
return result;