summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/dex/pool.c35
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]);