Skip to content

Commit

Permalink
symtabs: improve handling of symbol lookups
Browse files Browse the repository at this point in the history
When CONFIG_SYMTAB_ORDEREDBYNAME is selected most code will use
the ordered search function. When it is not selected no code will
use the ordered search function. This change merges the two
functions and varies its behaviour based on the config setting,
such that all callers can simply call the one search function
and get the best behaviour.

An additional configuration option allows leading underscores to
be stripped from symbols being relocated in loaded objects. This
allows toolchains which prefix C symbol with underscores to make
loadable ELF objects.
  • Loading branch information
codebje authored and xiaoxiang781216 committed Mar 16, 2021
1 parent c80cdf0 commit c9db653
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 178 deletions.
25 changes: 11 additions & 14 deletions Documentation/components/binfmt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,11 @@ symbol by its name and to provide the address associated with the symbol
as needed to perform the dynamic linking of the binary object to the
base FLASH code.
Some toolchains will prefix symbols with an underscore. To support these
toolchains the ``CONFIG_SYMTAB_DECORATED`` setting may be defined. This
will cause a leading underscore to be ignored on *undefined* symbols
during dynamic linking.
Symbol Table Header Files
-------------------------
Expand Down Expand Up @@ -323,33 +328,24 @@ Symbol Table Function Interfaces
.. c:function:: FAR const struct symtab_s *symtab_findbyname(FAR const struct symtab_s *symtab, FAR const char *name, int nsyms);
Find the symbol in the symbol table with the matching name.
This version assumes that table is not ordered with respect to
symbol name and, hence, access time will be linear with respect
to ``nsyms``.
:return:
A reference to the symbol table entry if an entry with the matching name is found; NULL is returned if the entry is not found.
.. c:function:: FAR const struct symtab_s *symtab_findorderedbyname(FAR const struct symtab_s *symtab, FAR const char *name, int nsyms);
Find the symbol in the symbol table with the matching name.
This version assumes that table ordered with respect to symbol name.
The implementation will be linear with respect to ``nsyms`` if
``CONFIG_SYMTAB_ORDEREDBYNAME`` is not selected, and logarithmic
if it is.
:return:
A reference to the symbol table entry if an entry with
the matching name is found; NULL is returned if the entry is not found.
.. c:function:: FAR const struct symtab_s *symtab_findbyvalue(FAR const struct symtab_s *symtab, FAR void *value, int nsyms);
Find the symbol in the symbol table whose value closest
(but not greater than), the provided value. This version assumes
that table is not ordered with respect to symbol name and, hence,
that table is not ordered with respect to symbol value and, hence,
access time will be linear with respect to ``nsyms``.
:return:
A reference to the symbol table entry if an entry with the matching
name is found; ``NULL`` is returned if the entry is not found.
value is found; ``NULL`` is returned if the entry is not found.
Configuration Variables
=======================
Expand All @@ -358,6 +354,7 @@ Configuration Variables
This logic may be suppressed be defining this setting.
- ``CONFIG_BINFMT_CONSTRUCTORS``: Build in support for C++ constructors in loaded modules.
- ``CONFIG_SYMTAB_ORDEREDBYNAME``: Symbol tables are order by name (rather than value).
- ``CONFIG_SYMTAB_DECORATED``: Symbols will have a leading underscore in object files.
Additional configuration options may be required for the each enabled
binary format.
9 changes: 0 additions & 9 deletions binfmt/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,3 @@ config BINFMT_CONSTRUCTORS
---help---
Built-in support for C++ constructors in loaded modules. Currently
only support for ELF binary formats.

config SYMTAB_ORDEREDBYNAME
bool "Symbol Tables Ordered by Name"
default n
---help---
Select if the symbol table is ordered by symbol name. In this case,
the logic can perform faster lookups using a binary search.
Otherwise, the symbol table is assumed to be un-ordered and only
slow, linear searches are supported.
6 changes: 0 additions & 6 deletions binfmt/libelf/libelf_symbols.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,8 @@ int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf_Sym *sym,

/* Check if the base code exports a symbol of this name */

#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
symbol = symtab_findorderedbyname(exports,
(FAR char *)loadinfo->iobuffer,
nexports);
#else
symbol = symtab_findbyname(exports, (FAR char *)loadinfo->iobuffer,
nexports);
#endif
if (!symbol)
{
berr("SHN_UNDEF: Exported symbol \"%s\" not found\n",
Expand Down
4 changes: 0 additions & 4 deletions binfmt/libnxflat/libnxflat_bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,7 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,

/* Find the exported symbol value for this symbol name. */

#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
symbol = symtab_findorderedbyname(exports, symname, nexports);
#else
symbol = symtab_findbyname(exports, symname, nexports);
#endif
if (!symbol)
{
berr("Exported symbol \"%s\" not found\n", symname);
Expand Down
24 changes: 4 additions & 20 deletions include/nuttx/symtab.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ extern "C"
*
* Description:
* Find the symbol in the symbol table with the matching name.
* This version assumes that table is not ordered with respect to symbol
* name and, hence, access time will be linear with respect to nsyms.
* The implementation will be linear with respect to nsyms if
* CONFIG_SYMTAB_ORDEREDBYNAME is not selected, and logarithmic
* if it is.
*
* Returned Value:
* A reference to the symbol table entry if an entry with the matching
Expand All @@ -86,30 +87,13 @@ FAR const struct symtab_s *
symtab_findbyname(FAR const struct symtab_s *symtab,
FAR const char *name, int nsyms);

/****************************************************************************
* Name: symtab_findorderedbyname
*
* Description:
* Find the symbol in the symbol table with the matching name.
* This version assumes that table ordered with respect to symbol name.
*
* Returned Value:
* A reference to the symbol table entry if an entry with the matching
* name is found; NULL is returned if the entry is not found.
*
****************************************************************************/

FAR const struct symtab_s *
symtab_findorderedbyname(FAR const struct symtab_s *symtab,
FAR const char *name, int nsyms);

/****************************************************************************
* Name: symtab_findbyvalue
*
* Description:
* Find the symbol in the symbol table whose value closest (but not greater
* than), the provided value. This version assumes that table is not
* ordered with respect to symbol name and, hence, access time will be
* ordered with respect to symbol value and, hence, access time will be
* linear with respect to nsyms.
*
* Returned Value:
Expand Down
11 changes: 0 additions & 11 deletions libs/libc/modlib/modlib_symbols.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,9 @@ static int modlib_symcallback(FAR struct module_s *modp, FAR void *arg)

/* Check if this module exports a symbol of that name */

#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
exportinfo->symbol = symtab_findorderedbyname(modp->modinfo.exports,
exportinfo->name,
modp->modinfo.nexports);
#else
exportinfo->symbol = symtab_findbyname(modp->modinfo.exports,
exportinfo->name,
modp->modinfo.nexports);
#endif

if (exportinfo->symbol != NULL)
{
Expand Down Expand Up @@ -381,13 +375,8 @@ int modlib_symvalue(FAR struct module_s *modp,
if (symbol == NULL)
{
modlib_getsymtab(&symbol, &nsymbols);
#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
symbol = symtab_findorderedbyname(symbol, exportinfo.name,
nsymbols);
#else
symbol = symtab_findbyname(symbol, exportinfo.name,
nsymbols);
#endif
}

/* Was the symbol found from any exporter? */
Expand Down
3 changes: 1 addition & 2 deletions libs/libc/symtab/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@

# Symbol table source files

CSRCS += symtab_findbyname.c symtab_findbyvalue.c
CSRCS += symtab_findorderedbyname.c symtab_sortbyname.c
CSRCS += symtab_findbyname.c symtab_findbyvalue.c symtab_sortbyname.c

# Add the symtab directory to the build

Expand Down
59 changes: 59 additions & 0 deletions libs/libc/symtab/symtab_findbyname.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,65 @@ FAR const struct symtab_s *
symtab_findbyname(FAR const struct symtab_s *symtab,
FAR const char *name, int nsyms)
{
#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
int low = 0;
int high = nsyms - 1;
int mid;
int cmp;
#endif

#ifdef CONFIG_SYMTAB_DECORATED
if (name[0] == '_')
{
name++;
}
#endif

DEBUGASSERT(symtab != NULL && name != NULL);

#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
while (low < high)
{
/* Compare the name to the one in the middle. (or just below
* the middle in the case where one is even and one is odd).
*/

mid = (low + high) >> 1;
cmp = strcmp(name, symtab[mid].sym_name);
if (cmp < 0)
{
/* name < symtab[mid].sym_name
*
* NOTE: Because of truncation in the calculation of 'mid'.
* 'mid' could be equal to 'low'
*/

high = mid > low ? mid - 1 : low;
}
else if (cmp > 0)
{
/* name > symtab[mid].sym_name */

low = mid + 1;
}
else
{
/* symtab[mid].sym_name == name */

return &symtab[mid];
}
}

/* low == high... One final check. We might not have actually tested
* the final symtab[] name.
*
* Example: Only the last pass through loop, suppose low = 1, high = 2,
* mid = 1, and symtab[high].sym_name == name. Then we would get here
* with low = 2, high = 2, but symtab[2].sym_name was never tested.
*/

return strcmp(name, symtab[low].sym_name) == 0 ? &symtab[low] : NULL;
#else
for (; nsyms > 0; symtab++, nsyms--)
{
if (strcmp(name, symtab->sym_name) == 0)
Expand All @@ -63,4 +121,5 @@ symtab_findbyname(FAR const struct symtab_s *symtab,
}

return NULL;
#endif
}
4 changes: 2 additions & 2 deletions libs/libc/symtab/symtab_findbyvalue.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@
* Description:
* Find the symbol in the symbol table whose value closest (but not greater
* than), the provided value. This version assumes that table is not
* ordered with respect to symbol name and, hence, access time will be
* ordered with respect to symbol value and, hence, access time will be
* linear with respect to nsyms.
*
* Returned Value:
* A reference to the symbol table entry if an entry with the matching
* name is found; NULL is returned if the entry is not found.
* value is found; NULL is returned if the entry is not found.
*
****************************************************************************/

Expand Down
110 changes: 0 additions & 110 deletions libs/libc/symtab/symtab_findorderedbyname.c

This file was deleted.

Loading

0 comments on commit c9db653

Please sign in to comment.