summaryrefslogtreecommitdiff
path: root/src/format/format.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-01-06 04:12:24 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-01-06 04:12:24 (GMT)
commit6db53b26e6c3d973295df51bb1934d5b42fb6ebe (patch)
tree401358c8b10a879daa23336d06d7f14f273ee764 /src/format/format.c
parent73308548c2be7f6480f3c898ceb6d01ae4e3f64c (diff)
Checked if a symbol exists right before adding it to the symbol list.
Diffstat (limited to 'src/format/format.c')
-rw-r--r--src/format/format.c51
1 files changed, 37 insertions, 14 deletions
diff --git a/src/format/format.c b/src/format/format.c
index 6f2c03e..be522cb 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -286,12 +286,14 @@ void g_binary_format_setup_disassembling_context(GBinFormat *format, GProcContex
* *
******************************************************************************/
-void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
+bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
{
+ bool result; /* Statut d'ajout à retourner */
#ifndef NDEBUG
const mrange_t *range; /* Couverture du symbole */
const vmpa2t *addr; /* Emplacement du symbole */
#endif
+ size_t index; /* Indice du point d'insertion */
GBinRoutine *routine; /* Nouvelle routine à insérer */
/**
@@ -309,33 +311,54 @@ void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
range = g_binary_symbol_get_range(symbol);
addr = get_mrange_addr(range);
- assert(get_phy_addr(addr) != VMPA_NO_PHYSICAL && get_virt_addr(addr) != VMPA_NO_VIRTUAL);
+ assert(!is_invalid_vmpa(addr));
#endif
g_rw_lock_writer_lock(&format->syms_lock);
- format->symbols = qinsert(format->symbols, &format->symbols_count,
- sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp, &symbol);
+ /**
+ * 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.
+ */
- switch (g_binary_symbol_get_target_type(symbol))
+ result = bsearch_index(&symbol, format->symbols, format->symbols_count,
+ sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp, &index);
+
+ if (!result)
{
- case STP_ROUTINE:
- case STP_ENTRY_POINT:
+ format->symbols = _qinsert(format->symbols, &format->symbols_count,
+ sizeof(GBinSymbol *), &symbol, index);
- routine = g_binary_symbol_get_routine(symbol);
+ switch (g_binary_symbol_get_target_type(symbol))
+ {
+ case STP_ROUTINE:
+ case STP_ENTRY_POINT:
- format->routines = qinsert(format->routines, &format->routines_count,
- sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare,
- &routine);
- break;
+ routine = g_binary_symbol_get_routine(symbol);
- default:
- break;
+ format->routines = qinsert(format->routines, &format->routines_count,
+ sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare,
+ &routine);
+ break;
+
+ default:
+ break;
+
+ }
}
+ else
+ g_object_unref(G_OBJECT(symbol));
g_rw_lock_writer_unlock(&format->syms_lock);
+ return result;
+
}