diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-06-12 23:46:47 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-06-12 23:46:47 (GMT) |
commit | 04d108111fe7ddd01713b4ca22f8d96961ec2486 (patch) | |
tree | 72ca086e0db2568bc93acb865b84e29c7d206897 /src/format | |
parent | 64aee7b4301e720a7420ab8942ef88f72d7a2c99 (diff) |
Improved loading speed with binary search of sorted arrays.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@538 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format')
-rw-r--r-- | src/format/elf/symbols.c | 6 | ||||
-rw-r--r-- | src/format/format-int.h | 3 | ||||
-rw-r--r-- | src/format/format.c | 121 | ||||
-rw-r--r-- | src/format/format.h | 7 | ||||
-rw-r--r-- | src/format/symbol.c | 4 |
5 files changed, 100 insertions, 41 deletions
diff --git a/src/format/elf/symbols.c b/src/format/elf/symbols.c index 04ba3de..655eda1 100644 --- a/src/format/elf/symbols.c +++ b/src/format/elf/symbols.c @@ -137,6 +137,8 @@ bool load_elf_symbols(GElfFormat *format) result &= load_all_elf_basic_entry_points(format); + g_binary_format_sort_symbols(G_BIN_FORMAT(format)); + return result; } @@ -201,7 +203,7 @@ static void register_elf_entry_point(GElfFormat *format, virt_t vaddr, phys_t le symbol = g_binary_symbol_new(STP_ENTRY_POINT, "XXX", ~0); g_binary_symbol_attach_routine(symbol, routine); - g_binary_format_add_symbol(base, symbol); + _g_binary_format_add_symbol(base, symbol, false); } @@ -632,7 +634,7 @@ static bool load_elf_internal_symbols(GElfFormat *format) } if (symbol != NULL) - g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); + _g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol, false); } diff --git a/src/format/format-int.h b/src/format/format-int.h index 96ff081..340264a 100644 --- a/src/format/format-int.h +++ b/src/format/format-int.h @@ -50,9 +50,12 @@ struct _GBinFormat GBinSymbol **symbols; /* Liste des symboles trouvés */ size_t symbols_count; /* Quantité de ces symboles */ + GRWLock syms_lock; /* Accès à la liste de symboles*/ + gint unsorted_symbols; /* Etat du tri des symboles */ GBinRoutine **routines; /* Liste des routines trouvées */ size_t routines_count; /* Nombre de ces routines */ + bool unsorted_routines; /* Etat du tri des routines */ const char **src_files; /* Nom des fichiers source */ size_t src_count; /* Taille de la liste */ diff --git a/src/format/format.c b/src/format/format.c index c1877d2..3373af3 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -90,10 +90,19 @@ static void g_binary_format_class_init(GBinFormatClass *klass) static void g_binary_format_init(GBinFormat *format) { + g_rw_lock_init(&format->syms_lock); + g_atomic_int_set(&format->unsorted_symbols, false); + + format->unsorted_routines = false; } + +/* FIXME : g_rw_lock_clear(&format->syms_lock);*/ + + + /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * @@ -181,6 +190,7 @@ void g_binary_format_setup_disassembling_context(const GBinFormat *format, GProc * * * Paramètres : format = informations chargées à compléter. * * symbol = symbole à ajouter à la liste. * +* sort = fait état d'un obligation de tri final. * * * * Description : Ajoute un symbole à la collection du format binaire. * * * @@ -190,15 +200,17 @@ void g_binary_format_setup_disassembling_context(const GBinFormat *format, GProc * * ******************************************************************************/ -void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol) +void _g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol, bool sort) { + + g_rw_lock_writer_lock(&format->syms_lock); + format->symbols = (GBinSymbol **)realloc(format->symbols, ++format->symbols_count * sizeof(GBinSymbol *)); format->symbols[format->symbols_count - 1] = symbol; - qsort(format->symbols, format->symbols_count, - sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp); + g_atomic_int_set(&format->unsorted_symbols, true); switch (g_binary_symbol_get_target_type(symbol)) { @@ -209,9 +221,8 @@ void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol) ++format->routines_count * sizeof(GBinRoutine *)); format->routines[format->routines_count - 1] = g_binary_symbol_get_routine(symbol); - - qsort(format->routines, format->routines_count, - sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare); + + format->unsorted_routines = true; break; @@ -220,6 +231,11 @@ void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol) } + g_rw_lock_writer_unlock(&format->syms_lock); + + if (sort) + g_binary_format_sort_symbols(format); + } @@ -315,6 +331,43 @@ void g_binary_format_remove_symbol(GBinFormat *format, GBinSymbol *symbol) /****************************************************************************** * * +* Paramètres : format = informations chargées à arranger. * +* * +* Description : Réorganise si besoin est les symboles collectés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_format_sort_symbols(GBinFormat *format) +{ + if (g_atomic_int_compare_and_exchange(&format->unsorted_symbols, true, false)) + { + g_rw_lock_writer_lock(&format->syms_lock); + + qsort(format->symbols, format->symbols_count, + sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp); + + if (format->unsorted_routines) + { + qsort(format->routines, format->routines_count, + sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare); + + format->unsorted_routines = false; + + } + + g_rw_lock_writer_unlock(&format->syms_lock); + + } + +} + + +/****************************************************************************** +* * * Paramètres : format = informations chargées à consulter. * * count = taille du tableau créé. [OUT] * * * @@ -477,25 +530,32 @@ bool g_binary_format_find_symbol_by_label(const GBinFormat *format, const char * bool g_binary_format_find_symbol_at(const GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol) { bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - const mrange_t *range; /* Espace mémoire parcouru */ + void *found; /* Résultat de recherches */ result = false; *symbol = NULL; /* TODO : vérifier les doublons côtés appelants */ - for (i = 0; i < format->symbols_count && !result; i++) + int find_symbol(const vmpa2t *addr, const GBinSymbol **sym) { - range = g_binary_symbol_get_range(format->symbols[i]); + const mrange_t *range; /* Espace mémoire parcouru */ - if (cmp_vmpa(get_mrange_addr(range), addr) == 0) - { - *symbol = format->symbols[i]; - g_object_ref(G_OBJECT(*symbol)); + range = g_binary_symbol_get_range(*sym); - result = true; + return cmp_vmpa_by_virt(addr, get_mrange_addr(range)); - } + } + + found = bsearch(addr, format->symbols, + format->symbols_count, sizeof(GBinSymbol *), + (__compar_fn_t)find_symbol); + + if (found != NULL) + { + *symbol = *(GBinSymbol **)found; + + g_object_ref(G_OBJECT(*symbol)); + result = true; } @@ -565,29 +625,16 @@ bool g_binary_format_find_next_symbol_at(const GBinFormat *format, const vmpa2t bool g_binary_format_resolve_symbol(const GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol, phys_t *diff) { - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - const mrange_t *range; /* Espace mémoire parcouru */ + bool result; /* Bilan à retourner */ + const mrange_t *range; /* Espace mémoire parcouru */ - result = false; - - //for (i = 0; i < format->symbols_count && !result; i++) - for (i = format->symbols_count; i > 0 && !result; i--) - { - range = g_binary_symbol_get_range(format->symbols[i - 1]); + result = g_binary_format_find_symbol_at(format, addr, symbol); - if (mrange_contains_addr(range, addr)) - { - *symbol = format->symbols[i - 1]; - g_object_ref(G_OBJECT(*symbol)); - - *diff = compute_vmpa_diff(get_mrange_addr(range), addr); - - result = true; - - } - - } + if (result) + { + range = g_binary_symbol_get_range(*symbol); + *diff = compute_vmpa_diff(get_mrange_addr(range), addr); + } return result; diff --git a/src/format/format.h b/src/format/format.h index 807e328..51c542f 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -65,11 +65,16 @@ GBinContent *g_binary_format_get_conten_(const GBinFormat *); void g_binary_format_setup_disassembling_context(const GBinFormat *, GProcContext *); /* Ajoute un symbole à la collection du format binaire. */ -void g_binary_format_add_symbol(GBinFormat *, GBinSymbol *); +void _g_binary_format_add_symbol(GBinFormat *, GBinSymbol *, bool); + +#define g_binary_format_add_symbol(fmt, sym) _g_binary_format_add_symbol(fmt, sym, true) /* Retire un symbole de la collection du format binaire. */ void g_binary_format_remove_symbol(GBinFormat *, GBinSymbol *); +/* Réorganise si besoin est les symboles collectés. */ +void g_binary_format_sort_symbols(GBinFormat *); + /* Fournit la liste de tous les symboles détectés. */ GBinSymbol **g_binary_format_get_symbols(const GBinFormat *, size_t *); diff --git a/src/format/symbol.c b/src/format/symbol.c index c867b68..f676e9e 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -177,7 +177,9 @@ int g_binary_symbol_cmp(const GBinSymbol **a, const GBinSymbol **b) aa = get_mrange_addr(ra); ab = get_mrange_addr(rb); - result = aa->virtual < ab->virtual ? -1 : (aa->virtual > ab->virtual ? 1 : 0); + result = cmp_vmpa_by_virt(aa, ab); + + //result = aa->virtual < ab->virtual ? -1 : (aa->virtual > ab->virtual ? 1 : 0); ///result = cmp_mrange(ra, rb); //printf(" ?? 0x%08lx vs 0x%08lx -> %d\n", aa->virtual, ab->virtual, result); |