diff --git a/Documentation/components/binfmt.rst b/Documentation/components/binfmt.rst index d109a705fb6..e86c0ee1348 100644 --- a/Documentation/components/binfmt.rst +++ b/Documentation/components/binfmt.rst @@ -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 ------------------------- @@ -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 ======================= @@ -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. diff --git a/binfmt/Kconfig b/binfmt/Kconfig index fff34e52753..22c3df5eb5b 100644 --- a/binfmt/Kconfig +++ b/binfmt/Kconfig @@ -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. diff --git a/binfmt/libelf/libelf_symbols.c b/binfmt/libelf/libelf_symbols.c index deea6c58db2..1781f689d0c 100644 --- a/binfmt/libelf/libelf_symbols.c +++ b/binfmt/libelf/libelf_symbols.c @@ -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", diff --git a/binfmt/libnxflat/libnxflat_bind.c b/binfmt/libnxflat/libnxflat_bind.c index ec038bc0fd2..15361a2946a 100644 --- a/binfmt/libnxflat/libnxflat_bind.c +++ b/binfmt/libnxflat/libnxflat_bind.c @@ -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); diff --git a/include/nuttx/symtab.h b/include/nuttx/symtab.h index 2d61672c127..e6bde2c4d1e 100644 --- a/include/nuttx/symtab.h +++ b/include/nuttx/symtab.h @@ -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 @@ -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: diff --git a/libs/libc/modlib/modlib_symbols.c b/libs/libc/modlib/modlib_symbols.c index 3d3fd437e6d..4956dd943dc 100644 --- a/libs/libc/modlib/modlib_symbols.c +++ b/libs/libc/modlib/modlib_symbols.c @@ -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) { @@ -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? */ diff --git a/libs/libc/symtab/Make.defs b/libs/libc/symtab/Make.defs index 6bdc111d258..cb00ccaba75 100644 --- a/libs/libc/symtab/Make.defs +++ b/libs/libc/symtab/Make.defs @@ -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 diff --git a/libs/libc/symtab/symtab_findbyname.c b/libs/libc/symtab/symtab_findbyname.c index ce80cc0f5ad..d3bd0d01938 100644 --- a/libs/libc/symtab/symtab_findbyname.c +++ b/libs/libc/symtab/symtab_findbyname.c @@ -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) @@ -63,4 +121,5 @@ symtab_findbyname(FAR const struct symtab_s *symtab, } return NULL; +#endif } diff --git a/libs/libc/symtab/symtab_findbyvalue.c b/libs/libc/symtab/symtab_findbyvalue.c index 1c68405d05b..c65567a897c 100644 --- a/libs/libc/symtab/symtab_findbyvalue.c +++ b/libs/libc/symtab/symtab_findbyvalue.c @@ -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. * ****************************************************************************/ diff --git a/libs/libc/symtab/symtab_findorderedbyname.c b/libs/libc/symtab/symtab_findorderedbyname.c deleted file mode 100644 index fa690033e52..00000000000 --- a/libs/libc/symtab/symtab_findorderedbyname.c +++ /dev/null @@ -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 - -#include -#include -#include -#include - -#include - -/**************************************************************************** - * 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; -} diff --git a/libs/libc/unistd/Kconfig b/libs/libc/unistd/Kconfig index f481ea543b7..e82b5ea6aa6 100644 --- a/libs/libc/unistd/Kconfig +++ b/libs/libc/unistd/Kconfig @@ -94,6 +94,23 @@ config EXECFUNCS_SYSTEM_SYMTAB endif # EXECFUNCS_HAVE_SYMTAB 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 int "Spawn Stack Size" default 1024