summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/sort.c35
-rw-r--r--src/common/sort.h3
-rw-r--r--src/format/format.c107
-rw-r--r--src/format/format.h3
4 files changed, 148 insertions, 0 deletions
diff --git a/src/common/sort.c b/src/common/sort.c
index e34d995..a905440 100644
--- a/src/common/sort.c
+++ b/src/common/sort.c
@@ -267,6 +267,41 @@ void *_qinsert(void *base, size_t *nmemb, size_t size, void *new, size_t index)
/******************************************************************************
* *
+* Paramètres : base = adresse du tableau à parcourir. *
+* nmemb = nombre d'éléments présents au total. [OUT] *
+* size = taille de chaque élément du tableau. *
+* new = nouveaux éléments à insérer. *
+* count = quantité de ces nouveaux éléments. *
+* index = indice du point d'insertion. *
+* *
+* Description : Ajoute à l'endroit indiqué des éléments dans un tableau. *
+* *
+* Retour : Nouvel emplacement du tableau agrandi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void *_qinsert_batch(void *base, size_t *nmemb, size_t size, void *new, size_t count, size_t index)
+{
+ void *result; /* Tableau trié à retourner */
+
+ result = realloc(base, (*nmemb + count) * size);
+
+ if (index < *nmemb)
+ memmove((char *)result + (index + count) * size, (char *)result + index * size, (*nmemb - index) * size);
+
+ (*nmemb) += count;
+
+ memcpy((char *)result + index * size, new, count * size);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : base = adresse du tableau à parcourir. *
* nmemb = nombre d'éléments présents au total. [OUT] *
* size = taille de chaque élément du tableau. *
diff --git a/src/common/sort.h b/src/common/sort.h
index eb86ccb..7362f64 100644
--- a/src/common/sort.h
+++ b/src/common/sort.h
@@ -49,6 +49,9 @@ bool bsearch_index(const void *, const void *, size_t, size_t, __compar_fn_t, si
/* Ajoute à l'endroit indiqué un élément dans un tableau. */
void *_qinsert(void *, size_t *, size_t, void *, size_t);
+/* Ajoute à l'endroit indiqué des éléments dans un tableau. */
+void *_qinsert_batch(void *, size_t *, size_t, void *, size_t, size_t);
+
/* Ajoute au bon endroit un élément dans un tableau trié. */
void *qinsert(void *, size_t *, size_t, __compar_fn_t, void *);
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 *);