summaryrefslogtreecommitdiff
path: root/plugins/dex/pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/dex/pool.c')
-rw-r--r--plugins/dex/pool.c122
1 files changed, 102 insertions, 20 deletions
diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c
index 8a421b2..75841df 100644
--- a/plugins/dex/pool.c
+++ b/plugins/dex/pool.c
@@ -711,6 +711,93 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index)
/******************************************************************************
* *
+* Paramètres : format = représentation interne du format DEX à compléter. *
+* gid = groupe de travail impliqué. *
+ status = barre de statut à tenir informée. *
+* *
+* Description : Charge toutes les classes listées dans le contenu binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_all_dex_methods(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+ bool result; /* Bilan à retourner */
+ guint runs_count; /* Qté d'exécutions parallèles */
+ uint32_t run_size; /* Volume réparti par exécution*/
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ activity_id_t msg; /* Message de progression */
+ guint i; /* Boucle de parcours */
+ uint32_t begin; /* Début de bloc de traitement */
+ uint32_t end; /* Fin d'un bloc de traitement */
+ GDexLoading *loading; /* Tâche de chargement à lancer*/
+
+ /**
+ * Il existe deux voies pour récupérer une méthode :
+ *
+ * - depuis 'method_id_item', qui précise classe d'appartenance, prototype
+ * et nom.
+ *
+ * - depuis 'encoded_method', qui contient une définition 'method_id_item',
+ * ainsi que des attributs propres à la méthode visée.
+ *
+ * Techniquement, il peut donc y avoir plusieurs variations d'un même
+ * 'method_id_item' selon différents 'encoded_method'.
+ *
+ * Dans la pratique, c'est hautement improbable : une méthode ne peut pas
+ * être privée et publique par exemple, ou renvoyer vers différents code.
+ *
+ * Donc on se permet d'associer une unique méthode par 'method_id_item',
+ * et de précharger le tout.
+ */
+
+ result = true;
+
+ /* Préparation du réceptacle */
+
+ format->methods = (GDexMethod **)calloc(format->header.method_ids_size, sizeof(GDexMethod *));
+
+ /* Lancement des chargements */
+
+ runs_count = get_max_online_threads();
+
+ run_size = format->header.method_ids_size / runs_count;
+
+ queue = get_work_queue();
+
+ msg = gtk_status_stack_add_activity(status, _("Loading all methods from the Dex pool..."),
+ format->header.method_ids_size);
+
+ for (i = 0; i < runs_count; i++)
+ {
+ begin = i * run_size;
+
+ if ((i + 1) == runs_count)
+ end = format->header.method_ids_size;
+ else
+ end = begin + run_size;
+
+ loading = g_dex_loading_new(format, begin, end, msg,
+ (dex_loading_cb)get_method_from_dex_pool, &result);
+
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid);
+
+ }
+
+ g_work_queue_wait_for_completion(queue, gid);
+
+ gtk_status_stack_remove_activity(status, msg);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : format = représentation interne du format DEX à consulter. *
* *
* Description : Compte le nombre de méthodes dans une table DEX. *
@@ -735,7 +822,7 @@ uint32_t count_methods_in_dex_pool(const GDexFormat *format)
/******************************************************************************
* *
* Paramètres : format = représentation interne du format DEX à consulter. *
-* index = index de la classe recherchée. *
+* index = index de la méthode recherchée. *
* *
* Description : Extrait une représentation de méthode d'une table DEX. *
* *
@@ -748,36 +835,31 @@ uint32_t count_methods_in_dex_pool(const GDexFormat *format)
GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index)
{
GDexMethod *result; /* Instance à retourner */
- uint32_t count; /* Nombre d'éléments présents */
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 */
result = NULL;
- count = count_methods_in_dex_pool(format);
-
- if (index >= count)
+ if (index >= format->header.method_ids_size)
goto gmfdp_error;
- /**
- * 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.
- */
+ if (format->methods[index] == NULL)
+ {
+ pos = format->header.method_ids_off + index * sizeof(method_id_item);
+ init_vmpa(&addr, pos, VMPA_NO_VIRTUAL);
- 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;
- if (!read_dex_method_id_item(format, &addr, &method_id))
- goto gmfdp_error;
+ format->methods[index] = g_dex_method_new_callable(format, &method_id);
- result = g_dex_method_new_callable(format, &method_id);
+ }
+
+ result = format->methods[index];
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
gmfdp_error: