diff --git a/include/nuttx/lib/modlib.h b/include/nuttx/lib/modlib.h index f29fd550f7f..a41730094f4 100644 --- a/include/nuttx/lib/modlib.h +++ b/include/nuttx/lib/modlib.h @@ -360,6 +360,12 @@ int modlib_load_with_addrenv(FAR struct mod_loadinfo_s *loadinfo); * 'loadinfo' using the exported symbol values provided by * modlib_setsymtab(). * + * Input Parameters: + * modp - Module state information + * loadinfo - Load state information + * exports - The table of exported symbols + * nexports - The number of symbols in the exports table + * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on * failure. @@ -367,7 +373,8 @@ int modlib_load_with_addrenv(FAR struct mod_loadinfo_s *loadinfo); ****************************************************************************/ int modlib_bind(FAR struct module_s *modp, - FAR struct mod_loadinfo_s *loadinfo); + FAR struct mod_loadinfo_s *loadinfo, + FAR const struct symtab_s *exports, int nexports); /**************************************************************************** * Name: modlib_unload diff --git a/libs/libc/modlib/modlib.h b/libs/libc/modlib/modlib.h index 4e004521d37..a3d2c0ed0ee 100644 --- a/libs/libc/modlib/modlib.h +++ b/libs/libc/modlib/modlib.h @@ -91,9 +91,12 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, * in the st_value field of the symbol table entry. * * Input Parameters: - * modp - Module state information - * loadinfo - Load state information - * sym - Symbol table entry (value might be undefined) + * modp - Module state information + * loadinfo - Load state information + * sym - Symbol table entry (value might be undefined) + * sh_offset - Offset of strtab + * exports - Pointer to the symbol table + * nexports - Number of symbols in the symbol table* * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on @@ -109,7 +112,8 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, int modlib_symvalue(FAR struct module_s *modp, FAR struct mod_loadinfo_s *loadinfo, FAR Elf_Sym *sym, - Elf_Off offset); + Elf_Off sh_offset, + FAR const struct symtab_s *exports, int nexports); /**************************************************************************** * Name: modlib_insertsymtab diff --git a/libs/libc/modlib/modlib_bind.c b/libs/libc/modlib/modlib_bind.c index d8679d28545..af1e09366a4 100644 --- a/libs/libc/modlib/modlib_bind.c +++ b/libs/libc/modlib/modlib_bind.c @@ -176,7 +176,8 @@ static inline int modlib_readrelas(FAR struct mod_loadinfo_s *loadinfo, ****************************************************************************/ static int modlib_relocate(FAR struct module_s *modp, - FAR struct mod_loadinfo_s *loadinfo, int relidx) + FAR struct mod_loadinfo_s *loadinfo, int relidx, + FAR const struct symtab_s *exports, int nexports) { FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx]; FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info]; @@ -291,7 +292,8 @@ static int modlib_relocate(FAR struct module_s *modp, /* Get the value of the symbol (in sym.st_value) */ ret = modlib_symvalue(modp, loadinfo, sym, - loadinfo->shdr[loadinfo->strtabidx].sh_offset); + loadinfo->shdr[loadinfo->strtabidx].sh_offset, + exports, nexports); if (ret < 0) { /* The special error -ESRCH is returned only in one condition: @@ -367,7 +369,9 @@ static int modlib_relocate(FAR struct module_s *modp, static int modlib_relocateadd(FAR struct module_s *modp, FAR struct mod_loadinfo_s *loadinfo, - int relidx) + int relidx, + FAR const struct symtab_s *exports, + int nexports) { FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx]; FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info]; @@ -483,7 +487,8 @@ static int modlib_relocateadd(FAR struct module_s *modp, /* Get the value of the symbol (in sym.st_value) */ ret = modlib_symvalue(modp, loadinfo, sym, - loadinfo->shdr[loadinfo->strtabidx].sh_offset); + loadinfo->shdr[loadinfo->strtabidx].sh_offset, + exports, nexports); if (ret < 0) { /* The special error -ESRCH is returned only in one condition: @@ -836,6 +841,8 @@ static int modlib_relocatedyn(FAR struct module_s *modp, * Input Parameters: * modp - Module state information * loadinfo - Load state information + * exports - The table of exported symbols + * nexports - The number of symbols in the exports table * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on @@ -844,7 +851,8 @@ static int modlib_relocatedyn(FAR struct module_s *modp, ****************************************************************************/ int modlib_bind(FAR struct module_s *modp, - FAR struct mod_loadinfo_s *loadinfo) + FAR struct mod_loadinfo_s *loadinfo, + FAR const struct symtab_s *exports, int nexports) { FAR Elf_Shdr *symhdr; FAR Elf_Sym *sym; @@ -921,6 +929,11 @@ int modlib_bind(FAR struct module_s *modp, sizeof(uintptr_t); break; } + + if (ret < 0) + { + return ret; + } } else { @@ -941,10 +954,21 @@ int modlib_bind(FAR struct module_s *modp, switch (loadinfo->shdr[i].sh_type) { case SHT_REL: - ret = modlib_relocate(modp, loadinfo, i); + if ((loadinfo->shdr[infosec].sh_flags & SHF_ALLOC) == 0) + { + continue; + } + + ret = modlib_relocate(modp, loadinfo, i, exports, nexports); break; case SHT_RELA: - ret = modlib_relocateadd(modp, loadinfo, i); + if ((loadinfo->shdr[infosec].sh_flags & SHF_ALLOC) == 0) + { + continue; + } + + ret = modlib_relocateadd(modp, loadinfo, i, exports, + nexports); break; case SHT_INIT_ARRAY: loadinfo->initarr = loadinfo->shdr[i].sh_addr; @@ -961,7 +985,7 @@ int modlib_bind(FAR struct module_s *modp, if (ret < 0) { - break; + return ret; } } diff --git a/libs/libc/modlib/modlib_insert.c b/libs/libc/modlib/modlib_insert.c index 3516e675e9d..92c58ce5d43 100644 --- a/libs/libc/modlib/modlib_insert.c +++ b/libs/libc/modlib/modlib_insert.c @@ -231,9 +231,11 @@ void modlib_dumpentrypt(FAR struct mod_loadinfo_s *loadinfo) FAR void *modlib_insert(FAR const char *filename, FAR const char *modname) { + FAR const struct symtab_s *exports; struct mod_loadinfo_s loadinfo; FAR struct module_s *modp; FAR void (**array)(void); + int nexports; int ret; int i; @@ -291,9 +293,13 @@ FAR void *modlib_insert(FAR const char *filename, FAR const char *modname) goto errout_with_registry_entry; } + /* Get the symbol table */ + + modlib_getsymtab(&exports, &nexports); + /* Bind the program to the kernel symbol table */ - ret = modlib_bind(modp, &loadinfo); + ret = modlib_bind(modp, &loadinfo, exports, nexports); if (ret != 0) { binfo("Failed to bind symbols program binary: %d\n", ret); diff --git a/libs/libc/modlib/modlib_symbols.c b/libs/libc/modlib/modlib_symbols.c index 5412daf3c04..f27a8dbb49c 100644 --- a/libs/libc/modlib/modlib_symbols.c +++ b/libs/libc/modlib/modlib_symbols.c @@ -322,6 +322,8 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, * loadinfo - Load state information * sym - Symbol table entry (value might be undefined) * sh_offset - Offset of strtab + * exports - Pointer to the symbol table + * nexports - Number of symbols in the symbol table* * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on @@ -337,12 +339,12 @@ int modlib_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, int modlib_symvalue(FAR struct module_s *modp, FAR struct mod_loadinfo_s *loadinfo, FAR Elf_Sym *sym, - Elf_Off sh_offset) + Elf_Off sh_offset, + FAR const struct symtab_s *exports, int nexports) { FAR const struct symtab_s *symbol; struct mod_exportinfo_s exportinfo; uintptr_t secbase; - int nsymbols; int ret; switch (sym->st_shndx) @@ -406,9 +408,8 @@ int modlib_symvalue(FAR struct module_s *modp, if (symbol == NULL) { - modlib_getsymtab(&symbol, &nsymbols); - symbol = symtab_findbyname(symbol, exportinfo.name, - nsymbols); + symbol = symtab_findbyname(exports, exportinfo.name, + nexports); } /* Was the symbol found from any exporter? */