diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/dex/pool.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c index 6007019..af591d3 100644 --- a/plugins/dex/pool.c +++ b/plugins/dex/pool.c @@ -26,6 +26,7 @@ #include <assert.h> #include <malloc.h> +#include <stdlib.h> #include <string.h> @@ -1181,6 +1182,10 @@ bool g_dex_pool_load_all_classes(GDexPool *pool, wgroup_id_t gid, GtkStatusStack size_t scount; /* Quantité de ces symboles */ uint32_t j; /* Boucle de parcours #2 */ size_t k; /* Boucle de parcours #3 */ + bool need_sort; /* Tri des symboles nécessaire */ + phys_t last; /* Dernière position rencontrée*/ + const mrange_t *range; /* Couverture du symbole */ + const vmpa2t *addr; /* Emplacement du symbole */ result = true; @@ -1229,8 +1234,38 @@ bool g_dex_pool_load_all_classes(GDexPool *pool, wgroup_id_t gid, GtkStatusStack result = g_dex_class_get_collect_symbols(pool->classes[j], &symbols, &scount); if (result) + { + /** + * Si le format DEX impose un ordre croissant dans les identifiants + * des méthodes d'une classe (champ method_idx de la structure + * encoded_method), cela ne conduit pas forcément à : + * - à disposer de champs code_off eux-même ordonnés ; + * - à retrouver des ordonnancements d'une classe à une autre. + * + * Un tri est donc forcé ici s'il s'avère nécessaire. + */ + + need_sort = false; + last = VMPA_NO_PHYSICAL; + + for (k = 0; k < scount && !need_sort; k++) + { + range = g_binary_symbol_get_range(symbols[k]); + addr = get_mrange_addr(range); + + need_sort = (last != VMPA_NO_PHYSICAL && last > get_phy_addr(addr)); + + last = get_phy_addr(addr); + + } + + if (need_sort) + qsort(symbols, count, sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp); + result = g_binary_format_add_symbols(G_BIN_FORMAT(pool->format), symbols, count); + } + for (k = 0; k < scount; k++) g_object_unref(symbols[k]); |