diff options
Diffstat (limited to 'src/format/format.c')
-rw-r--r-- | src/format/format.c | 51 |
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; + } |