summaryrefslogtreecommitdiff
path: root/src/format
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-01-27 18:48:58 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-01-27 18:48:58 (GMT)
commitc1ca03be00a4e975f89d30edfb72b57fb5612282 (patch)
tree4884513252458a261eb1290c93748b2bbbd98ff8 /src/format
parent1b3887c5609831bc2aee2f00f6a4d31d7406a225 (diff)
Created a huge optimization for the Dex format loading.
Diffstat (limited to 'src/format')
-rw-r--r--src/format/format.c107
-rw-r--r--src/format/format.h3
2 files changed, 110 insertions, 0 deletions
diff --git a/src/format/format.c b/src/format/format.c
index ab4864f..f6a4bd0 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -871,6 +871,113 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
/******************************************************************************
* *
+* Paramètres : format = informations chargées à compléter. *
+* symbols = ensemble de symboles à ajouter à la liste. *
+* count = taille de cet ensemble. *
+* *
+* Description : Ajoute plusieurs symboles à la collection du format binaire. *
+* *
+* Retour : true si les symboles dûment localisés ont été insérés. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_binary_format_add_symbols(GBinFormat *format, GBinSymbol **symbols, size_t count)
+{
+ bool result; /* Statut d'ajout à retourner */
+#ifndef NDEBUG
+ phys_t last; /* Dernière position rencontrée*/
+#endif
+ size_t i; /* Boucle de parcours */
+#ifndef NDEBUG
+ const mrange_t *range; /* Couverture du symbole */
+ const vmpa2t *addr; /* Emplacement du symbole */
+#endif
+ size_t index; /* Indice du point d'insertion */
+
+ /**
+ * Pour que les fonctions de recherche basées sur _g_binary_format_find_symbol()
+ * fassent bien leur office, il faut que les symboles soient triés.
+ *
+ * Cependant, les localisations à satisfaire lors d'une recherche recontrent
+ * un problème si les positions physiques ne sont pas renseignées. En effet
+ * les adresses virtuelles en sont potentiellement décorrélées (c'est le cas
+ * avec le format ELF par exemple, où les zones en mémoire ne suivent pas le
+ * même ordre que les segments du binaire).
+ *
+ * Comme les comparaisons entre localisations se réalisent sur les éléments
+ * renseignés communs, à commencer par la position physique si c'est possible,
+ * une localisation s'appuyant uniquement sur une adresse virtuelle va être
+ * analysée suivant une liste non triée d'adresses virtuelles.
+ *
+ * On corrige donc le tir si besoin est en forçant la comparaison via les
+ * positions physiques.
+ */
+
+#ifndef NDEBUG
+ last = VMPA_NO_PHYSICAL;
+
+ for (i = 0; i < count; i++)
+ {
+ range = g_binary_symbol_get_range(symbols[i]);
+ addr = get_mrange_addr(range);
+
+ assert(has_phys_addr(addr)
+ || g_binary_symbol_get_status(symbols[i]) == SSS_IMPORTED
+ || g_binary_symbol_get_status(symbols[i]) == SSS_DYNAMIC);
+
+
+ if (has_phys_addr(addr))
+ {
+ assert(last == VMPA_NO_PHYSICAL || last <= get_phy_addr(addr));
+ last = get_phy_addr(addr);
+ }
+
+ }
+#endif
+
+ g_binary_format_lock_unlock_symbols_wr(format, true);
+
+ /**
+ * Avec tous les traitements parallèles, il est possible que plusieurs chemins d'exécution
+ * amènent à la création d'un même symbole.
+ *
+ * Plutôt que de verrouiller la liste des symboles en amont (et donc assez longtemps)
+ * pour faire une vérification avant construction puis ajout, on préfère limiter
+ * l'état figé à cette seule fonction, quitte à annuler le travail fourni pour la
+ * construction du symbole dans les cas peu fréquents où le symbole était déjà en place.
+ */
+
+ result = bsearch_index(symbols[0], format->symbols, format->sym_count,
+ sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp, &index);
+
+ if (!result)
+ {
+ for (i = 0; i < count; i++)
+ g_object_ref(G_OBJECT(symbols[i]));
+
+ format->symbols = _qinsert_batch(format->symbols, &format->sym_count,
+ sizeof(GBinSymbol *), symbols, count, index);
+
+ format->sym_stamp++;
+ result = true;
+
+ }
+
+ g_binary_format_lock_unlock_symbols_wr(format, false);
+
+ if (result)
+ for (i = 0; i < count; i++)
+ g_signal_emit_by_name(format, "symbol-added", symbols[i]);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : format = informations chargées à compléter. *
* index = indice du symbole à retirer de la liste. *
* *
diff --git a/src/format/format.h b/src/format/format.h
index 748fd54..b001a15 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -129,6 +129,9 @@ GBinSymbol *g_binary_format_get_symbol(const GBinFormat *, size_t);
/* Ajoute un symbole à la collection du format binaire. */
bool g_binary_format_add_symbol(GBinFormat *, GBinSymbol *);
+/* Ajoute plusieurs symboles à la collection du format binaire. */
+bool g_binary_format_add_symbols(GBinFormat *, GBinSymbol **, size_t);
+
/* Retire un symbole de la collection du format binaire. */
void g_binary_format_remove_symbol(GBinFormat *, GBinSymbol *);