This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new fcce684bcbf libs/libc/elf: Read the symbol and string tables at once 
to find a symbol.
fcce684bcbf is described below

commit fcce684bcbfe0e491af4b4cdf89347be5c544e02
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Oct 11 15:04:33 2026 +0200

    libs/libc/elf: Read the symbol and string tables at once to find a symbol.
    
    libelf_findsymbol() read every symbol and then its name with separate
    file reads.  binfmt calls it for nx_stacksize and nx_priority (and with
    SCHED_USER_IDENTITY for nx_uid, nx_gid and nx_mode) on every exec, and
    most programs define none of them, so each call read the whole table.
    For a program with 5700 symbols that is about 23000 reads per exec; on
    a virtio 9P file system under a hypervisor it took 1.2 s.
    
    Read the symbol table and the string table into memory once and compare
    the names there.  If there is no memory for them, read one symbol at a
    time as before.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 libs/libc/elf/elf_symbols.c | 76 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/libs/libc/elf/elf_symbols.c b/libs/libc/elf/elf_symbols.c
index 43c74c3a6bf..d81f954ff12 100644
--- a/libs/libc/elf/elf_symbols.c
+++ b/libs/libc/elf/elf_symbols.c
@@ -124,6 +124,68 @@ static int libelf_symcallback(FAR struct module_s *modp, 
FAR void *arg)
   return SYM_NOT_FOUND;
 }
 
+/****************************************************************************
+ * Name: libelf_findsymbol_bulk
+ *
+ * Description:
+ *   Locate a symbol by its name with the symbol table and the string table
+ *   read into memory at once.
+ *
+ * Returned Value:
+ *   0 (OK) if the symbol was found, -ENOENT if it was not, -ENOMEM if there
+ *   is no memory for the tables, or another negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int libelf_findsymbol_bulk(FAR struct mod_loadinfo_s *loadinfo,
+                                  FAR const char *name, FAR Elf_Sym *sym,
+                                  size_t num)
+{
+  FAR const Elf_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx];
+  FAR const Elf_Shdr *strtab = &loadinfo->shdr[loadinfo->strtabidx];
+  FAR Elf_Sym *syms;
+  FAR char *strs;
+  size_t symsize = num * sizeof(Elf_Sym);
+  size_t i;
+  int ret;
+
+  syms = lib_malloc(symsize + strtab->sh_size + 1);
+  if (syms == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  strs = (FAR char *)syms + symsize;
+
+  ret = libelf_read(loadinfo, (FAR uint8_t *)syms, symsize,
+                    symtab->sh_offset);
+  if (ret >= 0)
+    {
+      ret = libelf_read(loadinfo, (FAR uint8_t *)strs, strtab->sh_size,
+                        strtab->sh_offset);
+    }
+
+  if (ret >= 0)
+    {
+      strs[strtab->sh_size] = '\0';
+      ret = -ENOENT;
+
+      for (i = 0; i < num; i++)
+        {
+          if (syms[i].st_name < strtab->sh_size &&
+              strcmp(&strs[syms[i].st_name], name) == 0)
+            {
+              *sym = syms[i];
+              ret = OK;
+              break;
+            }
+        }
+    }
+
+  lib_free(syms);
+  return ret;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -726,9 +788,21 @@ int libelf_findsymbol(FAR struct mod_loadinfo_s *loadinfo,
         }
     }
 
+  num = loadinfo->shdr[loadinfo->symtabidx].sh_size / sizeof(Elf_Sym);
+
+  /* Reading each symbol and then its name costs two file reads per
+   * symbol, which is slow for a large program on a slow file system.  If
+   * there is memory for it, read both tables at once.
+   */
+
+  ret = libelf_findsymbol_bulk(loadinfo, name, sym, num);
+  if (ret != -ENOMEM)
+    {
+      return ret;
+    }
+
   /* Loop through all symbols in the symbol table */
 
-  num = loadinfo->shdr[loadinfo->symtabidx].sh_size / sizeof(Elf_Sym);
   for (i = 0; i < num; i++)
     {
       /* Read the symbol entry */

Reply via email to