From 1b7c29ed7dd9561a387be694f09c089e6126716c Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 5 Aug 2021 10:28:08 +0200
Subject: Sort Dex smybols when needed at format loading.

---
 plugins/dex/pool.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

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]);
 
-- 
cgit v0.11.2-87-g4458