forked from Imagelibrary/rtems
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
This commit is contained in:
@@ -96,6 +96,15 @@ bool rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
|
||||
*/
|
||||
rtems_rtl_obj_sym* rtems_rtl_symbol_global_find (const char* name);
|
||||
|
||||
/**
|
||||
* Sort an object file's local and global symbol table. This needs to
|
||||
* be done before calling @ref rtems_rtl_symbol_obj_find as it
|
||||
* performs a binary search on the tables.
|
||||
*
|
||||
* @param obj The object file to sort.
|
||||
*/
|
||||
void rtems_rtl_symbol_obj_sort (rtems_rtl_obj* obj);
|
||||
|
||||
/**
|
||||
* Find a symbol given the symbol label in the local object file.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user