From 3284ce333cc4b09d9150b59c60005af8e4ddc417 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 23 Apr 2016 22:23:33 +0200
Subject: Loaded all Dex methods in a proper way.

---
 ChangeLog                | 14 ++++++++++
 src/format/dex/class.c   | 24 ++++++++++++++++--
 src/format/dex/dex-int.h |  1 -
 src/format/dex/dex.c     | 14 +++++-----
 src/format/dex/method.c  | 26 ++++++++++---------
 src/format/dex/method.h  |  4 +--
 src/format/dex/pool.c    | 66 +++++++++++-------------------------------------
 7 files changed, 75 insertions(+), 74 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index cd855bc..cfc9c84 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+16-04-23  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/format/dex/class.c:
+	Register all loaded class methods as symbols.
+
+	* src/format/dex/dex-int.h:
+	* src/format/dex/dex.c:
+	Update code.
+
+	* src/format/dex/method.c:
+	* src/format/dex/method.h:
+	* src/format/dex/pool.c:
+	Load all Dex methods in a proper way.
+
 16-04-22  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/output.c:
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:
 
-- 
cgit v0.11.2-87-g4458