diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-05-07 14:24:16 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-05-07 14:24:16 (GMT) |
commit | c136e2c4c1ad02ea2e363fbe71ce54c6255793e2 (patch) | |
tree | ba19cc948ac23a3930d9943e94f8e37ec86991c1 /plugins/dex/class.c | |
parent | b38035259b6e09c77d87950fe409fb72d09887d3 (diff) |
Extended the Python bindings for the Dex format.
Diffstat (limited to 'plugins/dex/class.c')
-rw-r--r-- | plugins/dex/class.c | 254 |
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; |