symtabs: improve handling of symbol lookups
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.
This commit is contained in:
parent
c80cdf06c2
commit
c9db653c8d
|
@ -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
|
as needed to perform the dynamic linking of the binary object to the
|
||||||
base FLASH code.
|
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
|
Symbol Table Header Files
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@ -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);
|
.. 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.
|
Find the symbol in the symbol table with the matching name.
|
||||||
This version assumes that table is not ordered with respect to
|
The implementation will be linear with respect to ``nsyms`` if
|
||||||
symbol name and, hence, access time will be linear with respect
|
``CONFIG_SYMTAB_ORDEREDBYNAME`` is not selected, and logarithmic
|
||||||
to ``nsyms``.
|
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_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.
|
|
||||||
|
|
||||||
:return:
|
:return:
|
||||||
A reference to the symbol table entry if an entry with
|
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.
|
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);
|
.. 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
|
Find the symbol in the symbol table whose value closest
|
||||||
(but not greater than), the provided value. This version assumes
|
(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``.
|
access time will be linear with respect to ``nsyms``.
|
||||||
|
|
||||||
:return:
|
:return:
|
||||||
A reference to the symbol table entry if an entry with the matching
|
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
|
Configuration Variables
|
||||||
=======================
|
=======================
|
||||||
|
@ -358,6 +354,7 @@ Configuration Variables
|
||||||
This logic may be suppressed be defining this setting.
|
This logic may be suppressed be defining this setting.
|
||||||
- ``CONFIG_BINFMT_CONSTRUCTORS``: Build in support for C++ constructors in loaded modules.
|
- ``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_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
|
Additional configuration options may be required for the each enabled
|
||||||
binary format.
|
binary format.
|
||||||
|
|
|
@ -66,12 +66,3 @@ config BINFMT_CONSTRUCTORS
|
||||||
---help---
|
---help---
|
||||||
Built-in support for C++ constructors in loaded modules. Currently
|
Built-in support for C++ constructors in loaded modules. Currently
|
||||||
only support for ELF binary formats.
|
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.
|
|
||||||
|
|
|
@ -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 */
|
/* 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,
|
symbol = symtab_findbyname(exports, (FAR char *)loadinfo->iobuffer,
|
||||||
nexports);
|
nexports);
|
||||||
#endif
|
|
||||||
if (!symbol)
|
if (!symbol)
|
||||||
{
|
{
|
||||||
berr("SHN_UNDEF: Exported symbol \"%s\" not found\n",
|
berr("SHN_UNDEF: Exported symbol \"%s\" not found\n",
|
||||||
|
|
|
@ -461,11 +461,7 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
|
||||||
|
|
||||||
/* Find the exported symbol value for this symbol name. */
|
/* 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);
|
symbol = symtab_findbyname(exports, symname, nexports);
|
||||||
#endif
|
|
||||||
if (!symbol)
|
if (!symbol)
|
||||||
{
|
{
|
||||||
berr("Exported symbol \"%s\" not found\n", symname);
|
berr("Exported symbol \"%s\" not found\n", symname);
|
||||||
|
|
|
@ -73,8 +73,9 @@ extern "C"
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Find the symbol in the symbol table with the matching name.
|
* Find the symbol in the symbol table with the matching name.
|
||||||
* This version assumes that table is not ordered with respect to symbol
|
* The implementation will be linear with respect to nsyms if
|
||||||
* name and, hence, access time will be linear with respect to nsyms.
|
* CONFIG_SYMTAB_ORDEREDBYNAME is not selected, and logarithmic
|
||||||
|
* if it is.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* A reference to the symbol table entry if an entry with the matching
|
* A reference to the symbol table entry if an entry with the matching
|
||||||
|
@ -86,30 +87,13 @@ FAR const struct symtab_s *
|
||||||
symtab_findbyname(FAR const struct symtab_s *symtab,
|
symtab_findbyname(FAR const struct symtab_s *symtab,
|
||||||
FAR const char *name, int nsyms);
|
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
|
* Name: symtab_findbyvalue
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Find the symbol in the symbol table whose value closest (but not greater
|
* Find the symbol in the symbol table whose value closest (but not greater
|
||||||
* than), the provided value. This version assumes that table is not
|
* 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.
|
* linear with respect to nsyms.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
|
|
|
@ -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 */
|
/* 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->symbol = symtab_findbyname(modp->modinfo.exports,
|
||||||
exportinfo->name,
|
exportinfo->name,
|
||||||
modp->modinfo.nexports);
|
modp->modinfo.nexports);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (exportinfo->symbol != NULL)
|
if (exportinfo->symbol != NULL)
|
||||||
{
|
{
|
||||||
|
@ -381,13 +375,8 @@ int modlib_symvalue(FAR struct module_s *modp,
|
||||||
if (symbol == NULL)
|
if (symbol == NULL)
|
||||||
{
|
{
|
||||||
modlib_getsymtab(&symbol, &nsymbols);
|
modlib_getsymtab(&symbol, &nsymbols);
|
||||||
#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
|
|
||||||
symbol = symtab_findorderedbyname(symbol, exportinfo.name,
|
|
||||||
nsymbols);
|
|
||||||
#else
|
|
||||||
symbol = symtab_findbyname(symbol, exportinfo.name,
|
symbol = symtab_findbyname(symbol, exportinfo.name,
|
||||||
nsymbols);
|
nsymbols);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Was the symbol found from any exporter? */
|
/* Was the symbol found from any exporter? */
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
|
|
||||||
# Symbol table source files
|
# Symbol table source files
|
||||||
|
|
||||||
CSRCS += symtab_findbyname.c symtab_findbyvalue.c
|
CSRCS += symtab_findbyname.c symtab_findbyvalue.c symtab_sortbyname.c
|
||||||
CSRCS += symtab_findorderedbyname.c symtab_sortbyname.c
|
|
||||||
|
|
||||||
# Add the symtab directory to the build
|
# Add the symtab directory to the build
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,65 @@ FAR const struct symtab_s *
|
||||||
symtab_findbyname(FAR const struct symtab_s *symtab,
|
symtab_findbyname(FAR const struct symtab_s *symtab,
|
||||||
FAR const char *name, int nsyms)
|
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);
|
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--)
|
for (; nsyms > 0; symtab++, nsyms--)
|
||||||
{
|
{
|
||||||
if (strcmp(name, symtab->sym_name) == 0)
|
if (strcmp(name, symtab->sym_name) == 0)
|
||||||
|
@ -63,4 +121,5 @@ symtab_findbyname(FAR const struct symtab_s *symtab,
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,12 @@
|
||||||
* Description:
|
* Description:
|
||||||
* Find the symbol in the symbol table whose value closest (but not greater
|
* Find the symbol in the symbol table whose value closest (but not greater
|
||||||
* than), the provided value. This version assumes that table is not
|
* 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.
|
* linear with respect to nsyms.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* A reference to the symbol table entry if an entry with the matching
|
* 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.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
* libs/libc/symtab/symtab_findorderedbyname.c
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership. The
|
|
||||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the
|
|
||||||
* License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Included Files
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <nuttx/symtab.h>
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Public Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* This function is a lot larger than symbtab_findbyname(). This function
|
|
||||||
* not be used, unless the symbol table is large and the performance
|
|
||||||
* benefit is worth the increased size.
|
|
||||||
*
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
int low = 0;
|
|
||||||
int high = nsyms - 1;
|
|
||||||
int mid;
|
|
||||||
int cmp;
|
|
||||||
|
|
||||||
/* Loop until the range has been isolated to a single symbol table
|
|
||||||
* entry that may or may not match the search name.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DEBUGASSERT(symtab != NULL && name != NULL);
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -94,6 +94,23 @@ config EXECFUNCS_SYSTEM_SYMTAB
|
||||||
endif # EXECFUNCS_HAVE_SYMTAB
|
endif # EXECFUNCS_HAVE_SYMTAB
|
||||||
endif # LIBC_EXECFUNCS
|
endif # LIBC_EXECFUNCS
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
config SYMTAB_DECORATED
|
||||||
|
bool "Symbols are decorated with leading underscores"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Select if symbols in relocatable objects are decorated with a leading
|
||||||
|
underscore. This option will remove the underscore from symbol names
|
||||||
|
when relocating a loadable object.
|
||||||
|
|
||||||
config POSIX_SPAWN_PROXY_STACKSIZE
|
config POSIX_SPAWN_PROXY_STACKSIZE
|
||||||
int "Spawn Stack Size"
|
int "Spawn Stack Size"
|
||||||
default 1024
|
default 1024
|
||||||
|
|
Loading…
Reference in New Issue