summaryrefslogtreecommitdiff
path: root/src/format/dex/pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/format/dex/pool.c')
-rw-r--r--src/format/dex/pool.c472
1 files changed, 356 insertions, 116 deletions
diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c
index a869873..904ab76 100644
--- a/src/format/dex/pool.c
+++ b/src/format/dex/pool.c
@@ -24,11 +24,13 @@
#include "pool.h"
+#include <malloc.h>
#include <string.h>
#include "dex-int.h"
#include "../mangling/demangler.h"
+#include "../mangling/dex/context.h"
@@ -83,6 +85,7 @@ bool find_all_dex_strings(GDexFormat *format)
const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index)
{
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 */
@@ -90,13 +93,15 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index)
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, &pos, &str_id))
+ 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, &pos, &str_data))
+ if (!read_dex_string_data_item(format, &addr, &str_data))
return NULL;
return (const char *)str_data.data;
@@ -109,6 +114,49 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index)
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* *
+* 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)
+{
+ bool result; /* Bilan à retourner */
+ uint32_t i; /* Boucle de parcours */
+ GDataType *type; /* Type récupéré */
+
+ result = true;
+
+ format->types = (GDataType **)calloc(format->header.type_ids_size, sizeof(GDataType *));
+
+ for (i = 0; i < format->header.type_ids_size && result; i++)
+ {
+ type = get_type_from_dex_pool(format, i);
+
+ if (type != NULL)
+ g_object_unref(G_OBJECT(type));
+ else
+ result = false;
+
+ }
+
+ return result;
+
+}
+
+
/******************************************************************************
* *
* Paramètres : format = représentation interne du format DEX à consulter. *
@@ -122,89 +170,94 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index)
* *
******************************************************************************/
-GDataType *get_type_from_dex_pool(const GDexFormat *format, uint16_t index)
+GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index)
{
- off_t pos; /* Tête de lecture */
+ 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 */
-
- //printf("Tp Index :: %hd / %d\n", index, format->header.type_ids_size);
-
+ result = NULL;
if (index >= format->header.type_ids_size)
- return NULL;
-
- pos = format->header.type_ids_off + index * sizeof(type_id_item);
+ goto gtfdp_error;
- if (!read_dex_type_id_item(format, &pos, &type_id))
- return NULL;
+ 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 = format->header.string_ids_off + type_id.descriptor_idx * sizeof(string_id_item);
+ pos = str_id.string_data_off;
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
- if (!read_dex_string_id_item(format, &pos, &str_id))
- return NULL;
+ if (!read_dex_string_data_item(format, &addr, &str_data))
+ goto gtfdp_error;
- pos = str_id.string_data_off;
+ format->types[index] = demangle_type(G_TYPE_DEX_DEMANGLER, (char *)str_data.data);
- if (!read_dex_string_data_item(format, &pos, &str_data))
- return NULL;
+ }
+ result = format->types[index];
- //printf(">> String :: '%s'\n", str_data.data);
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+ gtfdp_error:
- return demangle_type(DGT_JAVA, (char *)str_data.data);
+ return result;
}
-
-
-
/******************************************************************************
* *
-* Paramètres : format = représentation interne du format DEX à consulter. *
-* index = index de la classe recherchée. *
+* Paramètres : format = description de l'exécutable à compléter. *
* *
-* Description : Extrait une représentation de classe d'une table DEX. *
+* Description : Charge en mémoire l'ensemble des champs du format DEX. *
* *
-* Retour : Composant GLib créé. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GDataType *get_class_from_dex_pool(const GDexFormat *format, uint32_t index)
+bool load_all_dex_fields(GDexFormat *format)
{
- GDataType *result; /* Instance à retourner */
- off_t pos; /* Tête de lecture */
- class_def_item class_def; /* Définition de la classe */
-
- if (index >= format->header.class_defs_size)
- return NULL;
+ bool result; /* Bilan à retourner */
+ uint32_t i; /* Boucle de parcours */
+ GBinVariable *field; /* Champ récupéré */
- pos = format->header.class_defs_off + index * sizeof(class_def_item);
-
- if (!read_dex_class_def_item(format, &pos, &class_def))
- return NULL;
+ result = true;
+ format->fields = (GBinVariable **)calloc(format->header.field_ids_size, sizeof(GBinVariable *));
+ for (i = 0; i < format->header.field_ids_size && result; i++)
+ {
+ field = get_field_from_dex_pool(format, i);
- result = NULL;
+ if (field != NULL)
+ g_object_unref(G_OBJECT(field));
+ else
+ result = false;
+ }
return result;
}
-
-
/******************************************************************************
* *
* Paramètres : format = représentation interne du format DEX à consulter. *
@@ -218,48 +271,67 @@ GDataType *get_class_from_dex_pool(const GDexFormat *format, uint32_t index)
* *
******************************************************************************/
-GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index)
+GBinVariable *get_field_from_dex_pool(GDexFormat *format, uint32_t index)
{
GBinVariable *result; /* Instance à retourner */
- off_t pos; /* Tête de lecture */
+ 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)
- return NULL;
+ goto gffdp_error;
- pos = format->header.field_ids_off + index * sizeof(field_id_item);
+ 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, &pos, &field_id))
- return NULL;
+ if (!read_dex_field_id_item(format, &addr, &field_id))
+ goto gffdp_error;
- type = get_type_from_dex_pool(format, field_id.type_idx);
+ 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);
- if (name == NULL) goto bad_name;
+ name = get_string_from_dex_pool(format, field_id.name_idx);
+ if (name == NULL) goto gffdp_bad_name;
- result = g_binary_variable_new(type);
- g_binary_variable_set_name(result, 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 bad_owner;
+ 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);
+
+ }
- g_binary_variable_set_owner(result, owner);
+ format->fields[index] = field;
}
+ result = format->fields[index];
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ gffdp_error:
+
return result;
- bad_owner:
+ gffdp_bad_owner:
g_object_ref(G_OBJECT(type));
g_object_unref(G_OBJECT(result));
- bad_name:
+ gffdp_bad_name:
g_object_unref(G_OBJECT(type));
@@ -270,6 +342,44 @@ GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index)
/******************************************************************************
* *
+* Paramètres : format = représentation interne du format DEX à compléter. *
+* *
+* Description : Charge tous les prototypes listés dans le contenu binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_all_dex_prototypes(GDexFormat *format)
+{
+ bool result; /* Bilan à retourner */
+ uint32_t i; /* Boucle de parcours */
+ GBinRoutine *proto; /* Prototype récupéré */
+
+ result = true;
+
+ format->prototypes = (GBinRoutine **)calloc(format->header.proto_ids_size, sizeof(GBinRoutine *));
+
+ for (i = 0; i < format->header.proto_ids_size && result; i++)
+ {
+ proto = get_prototype_from_dex_pool(format, i);
+
+ if (proto != NULL)
+ g_object_unref(G_OBJECT(proto));
+ else
+ result = false;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : format = représentation interne du format DEX à consulter. *
* index = index de la routine recherchée. *
* *
@@ -281,114 +391,244 @@ GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index)
* *
******************************************************************************/
-GBinRoutine *get_routine_from_dex_pool(const GDexFormat *format, uint32_t index)
+GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index)
{
GBinRoutine *result; /* Instance à retourner */
- off_t pos; /* Tête de lecture */
- method_id_item meth_id; /* Description de la méthode */
+ 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é */
+ if (index >= format->header.method_ids_size)
+ goto grfdp_error;
- GDataType *type;
+ if (format->prototypes[index] == NULL)
+ {
+ pos = format->header.proto_ids_off + index * sizeof(proto_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
- string_id_item str_id; /* Identifiant de chaîne */
- string_data_item str_data; /* Description de chaîne */
+ if (!read_dex_proto_id_item(format, &addr, &proto_id))
+ goto grfdp_error;
+ /* Type de retour */
- proto_id_item proto_id; /* Information de prototypage */
- type_list args; /* Liste des arguments */
+ 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);
+
+ /* Liste des arguments */
+
+ pos = proto_id.parameters_off;
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
+
+ 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 */
+
+ format->prototypes[index] = demangle_routine(G_TYPE_DEX_DEMANGLER, name);
+
+#if 0
+ if (format->prototypes[index] != NULL)
+ g_binary_routine_set_return_type(format->prototypes[index], type);
+#endif
+
+ }
+
+ result = format->prototypes[index];
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ grfdp_error:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à compléter. *
+* *
+* Description : Charge toutes les méthodes listées dans le contenu binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_all_dex_methods(GDexFormat *format)
+{
+ bool result; /* Bilan à retourner */
uint32_t i; /* Boucle de parcours */
- GBinVariable *arg; /* Argument reconstitué */
+ GDexMethod *method; /* Méthode récupérée */
- if (index >= format->header.method_ids_size)
- return NULL;
+ result = true;
- pos = format->header.method_ids_off + index * sizeof(method_id_item);
+ format->methods = (GDexMethod **)calloc(format->header.method_ids_size, sizeof(GDexMethod *));
- if (!read_dex_method_id_item(format, &pos, &meth_id))
- return NULL;
+ for (i = 0; i < format->header.method_ids_size && result; i++)
+ {
+ method = get_method_from_dex_pool(format, i);
+ if (method != NULL)
+ g_object_unref(G_OBJECT(method));
+ else
+ result = false;
+ }
+ return result;
+}
- type = get_type_from_dex_pool(format, meth_id.class_idx);
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
- /*
- if (type == NULL)
- printf("class is nil\n");
+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 */
- else
- printf("class = '%s'\n", g_data_type_to_string(type));
- */
+ result = NULL;
- /* Nom de la méthode */
+ if (index >= format->header.method_ids_size)
+ goto gmfdp_error;
- pos = format->header.string_ids_off + meth_id.name_idx * sizeof(string_id_item);
+ if (format->methods[index] == NULL)
+ {
+ pos = format->header.method_ids_off + index * sizeof(method_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
- if (!read_dex_string_id_item(format, &pos, &str_id))
- return NULL;
+ if (!read_dex_method_id_item(format, &addr, &method_id))
+ goto gmfdp_error;
- pos = str_id.string_data_off;
+ format->methods[index] = g_dex_method_new_empty(format, &method_id);
- if (!read_dex_string_data_item(format, &pos, &str_data))
- return NULL;
+ }
+ result = format->methods[index];
- //printf("String :: '%s'\n", str_data.data);
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+ gmfdp_error:
- result = g_binary_routine_new();
+ return result;
- g_binary_routine_set_name(result, (char *)str_data.data);
+}
- if (type != NULL)
- g_binary_routine_set_namespace(result, type);
+/******************************************************************************
+* *
+* Paramètres : format = représentation interne du format DEX à compléter. *
+* *
+* 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)
+{
+ bool result; /* Bilan à retourner */
+ uint32_t i; /* Boucle de parcours */
+ GDexClass *class; /* Classe récupérée */
- /*
- printf(" ####\n");
- printf(" #### ROUTINE '%s'\n", g_binary_routine_to_string(result));
- printf(" ####\n");
- printf(" ####\n");
- */
+ result = true;
- //printf("==>>> routine :: '%s'\n", g_binary_routine_to_string(result));
+ format->classes = (GDexClass **)calloc(format->header.class_defs_size, sizeof(GDexClass *));
+ for (i = 0; i < format->header.class_defs_size && result; i++)
+ {
+ class = get_class_from_dex_pool(format, i);
+ if (class != NULL)
+ g_object_unref(G_OBJECT(class));
+ else
+ result = false;
+ }
+ return result;
+}
- /* Retour de la routine */
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
- pos = format->header.proto_ids_off + meth_id.proto_idx * sizeof(proto_id_item);
+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 */
- if (!read_dex_proto_id_item(format, &pos, &proto_id))
- goto no_more_info;
+ result = NULL;
- type = get_type_from_dex_pool(format, proto_id.return_type_idx);
+ if (index >= format->header.class_defs_size)
+ goto gcfdp_error;
- g_binary_routine_set_return_type(result, type);
+ if (format->classes[index] == NULL)
+ {
+ pos = format->header.class_defs_off + index * sizeof(class_def_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
- /* Arguments de la routine */
+ if (!read_dex_class_def_item(format, &addr, &class_def))
+ goto gcfdp_error;
- pos = proto_id.parameters_off;
+ format->classes[index] = g_dex_class_new(format, &class_def);
- if (read_dex_type_list(format, &pos, &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);
+ result = format->classes[index];
- }
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
- no_more_info:
+ gcfdp_error:
return result;