From 327e45dac2edae51caabc7777e2381ad653502ff Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Tue, 14 May 2019 10:34:32 +1000 Subject: libdl: Sort object file symbols and use a binary search to find - Replace the linear object file symbol search with a binary search. - Sort the object file symbols after loading. Closes #3748 --- cpukit/libdl/rtl-obj.c | 6 +++++- cpukit/libdl/rtl-sym.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 9 deletions(-) (limited to 'cpukit/libdl') diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index 9acb6f3943..1683ec1c6d 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -914,7 +914,11 @@ rtems_rtl_obj_load_symbols (rtems_rtl_obj* obj, void* data) { uint32_t mask = RTEMS_RTL_OBJ_SECT_SYM; - return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data); + bool ok; + ok = rtems_rtl_obj_section_handler (mask, obj, fd, handler, data); + if (ok) + rtems_rtl_symbol_obj_sort (obj); + return ok; } static int diff --git a/cpukit/libdl/rtl-sym.c b/cpukit/libdl/rtl-sym.c index c27f2ee676..9dd891525b 100644 --- a/cpukit/libdl/rtl-sym.c +++ b/cpukit/libdl/rtl-sym.c @@ -200,26 +200,59 @@ rtems_rtl_symbol_global_find (const char* name) return NULL; } +static int +rtems_rtl_symbol_obj_compare (const void* a, const void* b) +{ + const rtems_rtl_obj_sym* sa; + const rtems_rtl_obj_sym* sb; + sa = (const rtems_rtl_obj_sym*) a; + sb = (const rtems_rtl_obj_sym*) b; + return strcmp (sa->name, sb->name); +} + +void +rtems_rtl_symbol_obj_sort (rtems_rtl_obj* obj) +{ + qsort (obj->local_table, + obj->local_syms, + sizeof (rtems_rtl_obj_sym), + rtems_rtl_symbol_obj_compare); + qsort (obj->global_table, + obj->global_syms, + sizeof (rtems_rtl_obj_sym), + rtems_rtl_symbol_obj_compare); +} + rtems_rtl_obj_sym* rtems_rtl_symbol_obj_find (rtems_rtl_obj* obj, const char* name) { - rtems_rtl_obj_sym* sym; - size_t s; /* * Check the object file's symbols first. If not found search the * global symbol table. */ if (obj->local_syms) { - for (s = 0, sym = obj->local_table; s < obj->local_syms; ++s, ++sym) - if (strcmp (name, sym->name) == 0) - return sym; + rtems_rtl_obj_sym* match; + rtems_rtl_obj_sym key = { 0 }; + key.name = name; + match = bsearch (&key, obj->local_table, + obj->local_syms, + sizeof (rtems_rtl_obj_sym), + rtems_rtl_symbol_obj_compare); + if (match != NULL) + return match; } if (obj->global_syms) { - for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym) - if (strcmp (name, sym->name) == 0) - return sym; + rtems_rtl_obj_sym* match; + rtems_rtl_obj_sym key = { 0 }; + key.name = name; + match = bsearch (&key, obj->global_table, + obj->global_syms, + sizeof (rtems_rtl_obj_sym), + rtems_rtl_symbol_obj_compare); + if (match != NULL) + return match; } return rtems_rtl_symbol_global_find (name); } -- cgit v1.2.3