summaryrefslogtreecommitdiff
path: root/src/format
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-04-23 20:23:33 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-04-23 20:23:33 (GMT)
commit3284ce333cc4b09d9150b59c60005af8e4ddc417 (patch)
treeff9c6a51e20f3a15654005f1c9e2ee22d91e7b6c /src/format
parentdf4bc1a413561f9de095e1c30c678bd7272c3478 (diff)
Loaded all Dex methods in a proper way.
Diffstat (limited to 'src/format')
-rw-r--r--src/format/dex/class.c24
-rwxr-xr-xsrc/format/dex/dex-int.h1
-rwxr-xr-xsrc/format/dex/dex.c14
-rw-r--r--src/format/dex/method.c26
-rw-r--r--src/format/dex/method.h4
-rw-r--r--src/format/dex/pool.c66
6 files changed, 61 insertions, 74 deletions
diff --git a/src/format/dex/class.c b/src/format/dex/class.c
index a5181d2..02ac19d 100644
--- a/src/format/dex/class.c
+++ b/src/format/dex/class.c
@@ -196,6 +196,8 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
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 */
+ GBinSymbol *symbol; /* Nouveau symbole construit */
init_vmpa(&addr, def->class_data_off, VMPA_NO_VIRTUAL);
@@ -219,11 +221,20 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
for (i = 0; i < data.direct_methods_size; i++)
{
- method = g_dex_method_new(format, &data.direct_methods[i], &index);
+ 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 */
+
+ routine = g_dex_method_get_routine(method);
+
+ symbol = g_binary_symbol_new(STP_ROUTINE);
+ g_binary_symbol_attach_routine(symbol, routine);
+
+ _g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol, false);
+
}
index = 0;
@@ -233,11 +244,20 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def)
for (i = 0; i < data.virtual_methods_size; i++)
{
- method = g_dex_method_new(format, &data.virtual_methods[i], &index);
+ 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 */
+
+ routine = g_dex_method_get_routine(method);
+
+ symbol = g_binary_symbol_new(STP_ROUTINE);
+ g_binary_symbol_attach_routine(symbol, routine);
+
+ _g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol, false);
+
}
gdcn_done:
diff --git a/src/format/dex/dex-int.h b/src/format/dex/dex-int.h
index a5f39a6..ee43bc8 100755
--- a/src/format/dex/dex-int.h
+++ b/src/format/dex/dex-int.h
@@ -43,7 +43,6 @@ struct _GDexFormat
GDataType **types; /* Types partagés pour Dalvik */
GBinVariable **fields; /* Champs de données partagés */
- GDexMethod **methods; /* Méthodes retrouvées */
GDexClass **classes; /* Classes retrouvées */
};
diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c
index a918c31..51938f9 100755
--- a/src/format/dex/dex.c
+++ b/src/format/dex/dex.c
@@ -245,11 +245,14 @@ static void g_dex_format_finalize(GDexFormat *format)
GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent)
{
GDexFormat *result; /* Structure à retourner */
+ GBinFormat *base; /* Version basique du format */
vmpa2t pos; /* Position de tête de lecture */
result = g_object_new(G_TYPE_DEX_FORMAT, NULL);
- g_binary_format_set_content(G_BIN_FORMAT(result), content);
+ base = G_BIN_FORMAT(result);
+
+ g_binary_format_set_content(base, content);
init_vmpa(&pos, 0, VMPA_NO_VIRTUAL);
@@ -267,16 +270,15 @@ GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent)
if (!load_all_dex_fields(result))
goto gdfn_error;
- if (!load_all_dex_methods(result))
- goto gdfn_error;
-
if (!load_all_dex_classes(result))
goto gdfn_error;
- if (!g_binary_format_complete_loading(G_BIN_FORMAT(result)))
+ g_binary_format_sort_symbols(base);
+
+ if (!g_binary_format_complete_loading(base))
goto gdfn_error;
- return G_BIN_FORMAT(result);
+ return base;
gdfn_error:
diff --git a/src/format/dex/method.c b/src/format/dex/method.c
index bc4a063..f91af0d 100644
--- a/src/format/dex/method.c
+++ b/src/format/dex/method.c
@@ -24,6 +24,7 @@
#include "method.h"
+#include <stddef.h>
#include <string.h>
@@ -174,12 +175,12 @@ static void g_dex_method_finalize(GDexMethod *method)
* *
******************************************************************************/
-GDexMethod *g_dex_method_new(GDexFormat *format, const encoded_method *seed, uleb128_t *last)
+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 */
- GBinRoutine *routine; /* Routine représentée */
+ phys_t ins_offset; /* Position physique du code */
mrange_t range; /* Emplacement du code associé */
init_vmpa(&addr, seed->code_off, VMPA_NO_VIRTUAL);
@@ -188,23 +189,24 @@ GDexMethod *g_dex_method_new(GDexFormat *format, const encoded_method *seed, ule
return NULL;
*last += seed->method_idx_diff;
- routine = get_prototype_from_dex_pool(format, *last);
- if (routine == NULL) return NULL;
+ ins_offset = seed->code_off + offsetof(code_item, insns);
- result = g_object_new(G_TYPE_DEX_METHOD, NULL);
+ if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), ins_offset, &addr))
+ return NULL;
+
+ result = get_method_from_dex_pool(format, *last);
+
+ if (result == NULL)
+ return NULL;
result->info = *seed;
result->body = item;
- result->offset = seed->code_off + 4 * sizeof(uint16_t) + 2 * sizeof(uint32_t);/* TODO : faire plus propre ! */
+ result->offset = ins_offset;
- init_vmpa(&addr, result->offset, VMPA_NO_VIRTUAL);
init_mrange(&range, &addr, item.insns_size * sizeof(uint16_t));
-
- g_binary_routine_set_range(routine, &range);
-
- result->routine = routine;
+ g_binary_routine_set_range(result->routine, &range);
return result;
@@ -224,7 +226,7 @@ GDexMethod *g_dex_method_new(GDexFormat *format, const encoded_method *seed, ule
* *
******************************************************************************/
-GDexMethod *g_dex_method_new_empty(GDexFormat *format, const method_id_item *method_id)
+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 */
diff --git a/src/format/dex/method.h b/src/format/dex/method.h
index cb85bc6..c7e945d 100644
--- a/src/format/dex/method.h
+++ b/src/format/dex/method.h
@@ -67,10 +67,10 @@ typedef enum _DexVariableIndex
GType g_dex_method_get_type(void);
/* Crée une nouvelle représentation de methode issue de code. */
-GDexMethod *g_dex_method_new(GDexFormat *, const encoded_method *, uleb128_t *);
+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_empty(GDexFormat *, const method_id_item *);
+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 *);
diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c
index 056443e..3842aa9 100644
--- a/src/format/dex/pool.c
+++ b/src/format/dex/pool.c
@@ -443,44 +443,6 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index)
/******************************************************************************
* *
-* 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 */
- GDexMethod *method; /* Méthode récupérée */
-
- result = true;
-
- format->methods = (GDexMethod **)calloc(format->header.method_ids_size, sizeof(GDexMethod *));
-
- 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;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : format = représentation interne du format DEX à consulter. *
* index = index de la classe recherchée. *
* *
@@ -504,22 +466,24 @@ GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index)
if (index >= format->header.method_ids_size)
goto gmfdp_error;
- 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_method_id_item(format, &addr, &method_id))
- goto gmfdp_error;
-
- format->methods[index] = g_dex_method_new_empty(format, &method_id);
+ /**
+ * 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);
- result = format->methods[index];
+ if (!read_dex_method_id_item(format, &addr, &method_id))
+ goto gmfdp_error;
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
+ result = g_dex_method_new_callable(format, &method_id);
gmfdp_error: