diff --git a/include/elf.h b/include/elf.h index ef6258c2b3ab8..649095f74f1ec 100644 --- a/include/elf.h +++ b/include/elf.h @@ -191,6 +191,7 @@ #define SHF_WRITE 1 #define SHF_ALLOC 2 #define SHF_EXECINSTR 4 +#define SHF_INFO_LINK 0x40 #define SHF_MASKPROC 0xf0000000 /* Figure 4-16: Symbol Binding, ELF_ST_BIND */ @@ -211,6 +212,13 @@ #define STT_LOPROC 13 #define STT_HIPROC 15 +/* Table 7-21 ELF Symbol Visibility */ + +#define STV_DEFAULT 0 +#define STV_INTERNAL 1 +#define STV_HIDDEN 2 +#define STV_PROTECTED 3 + /* Figure 5-2: Segment Types, p_type */ #define PT_NULL 0 diff --git a/include/elf32.h b/include/elf32.h index 5b5f27a3cd2b8..1e62a7cf913ee 100644 --- a/include/elf32.h +++ b/include/elf32.h @@ -36,25 +36,27 @@ * Pre-processor Definitions ****************************************************************************/ -#define ELF_CLASS ELFCLASS32 +#define ELF_CLASS ELFCLASS32 -#define ELF32_ST_BIND(i) ((i) >> 4) -#define ELF32_ST_TYPE(i) ((i) & 0xf) -#define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf)) +#define ELF32_ST_BIND(i) ((i) >> 4) +#define ELF32_ST_TYPE(i) ((i) & 0xf) +#define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf)) +#define ELF32_ST_VISIBILITY(o) ((o) & 0x3) /* Generic macro to abstract ELF32/ELF64 type/bind */ -#define ELF_ST_TYPE(a) ELF32_ST_TYPE(a) -#define ELF_ST_BIND(a) ELF32_ST_BIND(a) +#define ELF_ST_TYPE(a) ELF32_ST_TYPE(a) +#define ELF_ST_BIND(a) ELF32_ST_BIND(a) +#define ELF_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o) /* Definitions for Elf32_Rel*::r_info */ -#define ELF32_R_SYM(i) ((i) >> 8) -#define ELF32_R_TYPE(i) ((i) & 0xff) -#define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff)) +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((i) & 0xff) +#define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff)) -#define ELF_R_SYM(i) ELF32_R_SYM(i) -#define ELF_R_TYPE(i) ELF32_R_TYPE(i) +#define ELF_R_SYM(i) ELF32_R_SYM(i) +#define ELF_R_TYPE(i) ELF32_R_TYPE(i) /**************************************************************************** * Public Type Definitions diff --git a/include/elf64.h b/include/elf64.h index 865cc95a1804d..27ac06246dbff 100644 --- a/include/elf64.h +++ b/include/elf64.h @@ -36,27 +36,29 @@ * Pre-processor Definitions ****************************************************************************/ -#define ELF_CLASS ELFCLASS64 +#define ELF_CLASS ELFCLASS64 /* See ELF-64 Object File Format: Version 1.5 Draft 2 */ -#define ELF64_ST_BIND(i) ((i) >> 4) -#define ELF64_ST_TYPE(i) ((i) & 0xf) -#define ELF64_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf)) +#define ELF64_ST_BIND(i) ((i) >> 4) +#define ELF64_ST_TYPE(i) ((i) & 0xf) +#define ELF64_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf)) +#define ELF64_ST_VISIBILITY(o) ((o) & 0x3) /* Generic macro to abstract ELF32/ELF64 type/bind */ -#define ELF_ST_TYPE(a) ELF64_ST_TYPE(a) -#define ELF_ST_BIND(a) ELF64_ST_BIND(a) +#define ELF_ST_TYPE(a) ELF64_ST_TYPE(a) +#define ELF_ST_BIND(a) ELF64_ST_BIND(a) +#define ELF_ST_VISIBILITY(o) ELF64_ST_VISIBILITY(o) /* Definitions for Elf64_Rel*::r_info */ -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i) & 0xffffffffL) -#define ELF64_R_INFO(s,t) (((s)<< 32) + ((t) & 0xffffffffL)) +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffffL) +#define ELF64_R_INFO(s,t) (((s)<< 32) + ((t) & 0xffffffffL)) -#define ELF_R_SYM(i) ELF64_R_SYM(i) -#define ELF_R_TYPE(i) ELF64_R_TYPE(i) +#define ELF_R_SYM(i) ELF64_R_SYM(i) +#define ELF_R_TYPE(i) ELF64_R_TYPE(i) /**************************************************************************** * Public Type Definitions diff --git a/include/nuttx/lib/modlib.h b/include/nuttx/lib/modlib.h index 9533d8d5ec94d..4889c6c0c870c 100644 --- a/include/nuttx/lib/modlib.h +++ b/include/nuttx/lib/modlib.h @@ -154,9 +154,6 @@ struct module_s FAR struct module_s *flink; /* Supports a singly linked list */ #ifdef HAVE_MODLIB_NAMES char modname[MODLIB_NAMEMAX]; /* Module name */ -#endif -#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) - mod_initializer_t initializer; /* Module initializer function */ #endif struct mod_info_s modinfo; /* Module information */ FAR void *textalloc; /* Allocated kernel text memory */ diff --git a/libs/libc/modlib/gnu-elf.ld b/libs/libc/modlib/gnu-elf.ld index 0d6648ab1adeb..f78a75a14a37c 100644 --- a/libs/libc/modlib/gnu-elf.ld +++ b/libs/libc/modlib/gnu-elf.ld @@ -33,6 +33,16 @@ SECTIONS _etext = . ; } + .init_array : + { + *(.init_array) + } + + .fini_array : + { + *(.fini_array) + } + .rodata : { _srodata = . ; diff --git a/libs/libc/modlib/modlib_bind.c b/libs/libc/modlib/modlib_bind.c index 51703c6c6080b..2e9ef7ac5e2b0 100644 --- a/libs/libc/modlib/modlib_bind.c +++ b/libs/libc/modlib/modlib_bind.c @@ -814,32 +814,6 @@ static int modlib_relocatedyn(FAR struct module_s *modp, } } - /* Iterate through the dynamic symbol table looking for global symbols - * to put in our own symbol table for use with dlgetsym() - */ - - /* Relocate the entries in the table */ - - for (i = 0; i < symhdr->sh_size / sizeof(Elf_Sym); i++) - { - FAR Elf_Shdr *s = &loadinfo->shdr[sym[i].st_shndx]; - - if (sym[i].st_shndx != SHN_UNDEF) - { - if (s->sh_addr < loadinfo->datasec) - { - sym[i].st_value = sym[i].st_value + loadinfo->textalloc; - } - else - { - sym[i].st_value = sym[i].st_value - - loadinfo->datasec + loadinfo->datastart; - } - } - } - - ret = modlib_insertsymtab(modp, loadinfo, symhdr, sym); - lib_free(sym); lib_free(rels); lib_free(dyn); @@ -872,6 +846,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 Elf_Shdr *symhdr; + FAR Elf_Sym *sym; int ret; int i; @@ -937,7 +913,8 @@ int modlib_bind(FAR struct module_s *modp, * relocate sections that were not loaded into memory. */ - if ((loadinfo->shdr[infosec].sh_flags & SHF_ALLOC) == 0) + if ((loadinfo->shdr[i].sh_flags & SHF_ALLOC) == 0 && + (loadinfo->shdr[i].sh_flags & SHF_INFO_LINK) == 0) { continue; } @@ -952,6 +929,16 @@ int modlib_bind(FAR struct module_s *modp, case SHT_RELA: ret = modlib_relocateadd(modp, loadinfo, i); break; + case SHT_INIT_ARRAY: + loadinfo->initarr = loadinfo->shdr[i].sh_addr; + loadinfo->ninit = loadinfo->shdr[i].sh_size / + sizeof(uintptr_t); + break; + case SHT_FINI_ARRAY: + loadinfo->finiarr = loadinfo->shdr[i].sh_addr; + loadinfo->nfini = loadinfo->shdr[i].sh_size / + sizeof(uintptr_t); + break; } } @@ -961,6 +948,37 @@ int modlib_bind(FAR struct module_s *modp, } } + symhdr = &loadinfo->shdr[loadinfo->symtabidx]; + sym = lib_malloc(symhdr->sh_size); + + ret = modlib_read(loadinfo, (FAR uint8_t *)sym, symhdr->sh_size, + symhdr->sh_offset); + + if (ret < 0) + { + berr("Failed to read symbol table\n"); + lib_free(sym); + return ret; + } + + for (i = 0; i < symhdr->sh_size / sizeof(Elf_Sym); i++) + { + FAR Elf_Shdr *s = &loadinfo->shdr[sym[i].st_shndx]; + + if (sym[i].st_shndx != SHN_UNDEF) + { + sym[i].st_value = sym[i].st_value + s->sh_addr; + } + } + + ret = modlib_insertsymtab(modp, loadinfo, symhdr, sym); + lib_free(sym); + if (ret != 0) + { + binfo("Failed to export symbols program binary: %d\n", ret); + return ret; + } + /* Ensure that the I and D caches are coherent before starting the newly * loaded module by cleaning the D cache (i.e., flushing the D cache * contents to memory and invalidating the I cache). diff --git a/libs/libc/modlib/modlib_insert.c b/libs/libc/modlib/modlib_insert.c index ec3098db440c2..7056f47fccf92 100644 --- a/libs/libc/modlib/modlib_insert.c +++ b/libs/libc/modlib/modlib_insert.c @@ -105,21 +105,6 @@ static void modlib_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo) # define modlib_dumploadinfo(i) #endif -/**************************************************************************** - * Name: modlib_dumpinitializer - ****************************************************************************/ - -#ifdef CONFIG_MODLIB_DUMPBUFFER -static void modlib_dumpinitializer(mod_initializer_t initializer, - FAR struct mod_loadinfo_s *loadinfo) -{ - modlib_dumpbuffer("Initializer code", (FAR const uint8_t *)initializer, - MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512)); -} -#else -# define modlib_dumpinitializer(b,l) -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -154,7 +139,6 @@ FAR void *modlib_insert(FAR const char *filename, FAR const char *modname) { struct mod_loadinfo_s loadinfo; FAR struct module_s *modp; - mod_initializer_t initializer; FAR void (**array)(void); int ret; int i; @@ -231,27 +215,11 @@ FAR void *modlib_insert(FAR const char *filename, FAR const char *modname) modp->datasize = loadinfo.datasize; #endif - /* Get the module initializer entry point */ - - initializer = (mod_initializer_t)(loadinfo.textalloc + - loadinfo.ehdr.e_entry); -#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) - modp->initializer = initializer; -#endif - modlib_dumpinitializer(initializer, &loadinfo); - /* Call the module initializer */ switch (loadinfo.ehdr.e_type) { case ET_REL : - ret = initializer(&modp->modinfo); - if (ret < 0) - { - binfo("Failed to initialize the module: %d\n", ret); - goto errout_with_load; - } - break; case ET_DYN : /* Process any preinit_array entries */ @@ -296,4 +264,3 @@ FAR void *modlib_insert(FAR const char *filename, FAR const char *modname) set_errno(-ret); return NULL; } - diff --git a/libs/libc/modlib/modlib_remove.c b/libs/libc/modlib/modlib_remove.c index a645c689866de..765b85ee31b8f 100644 --- a/libs/libc/modlib/modlib_remove.c +++ b/libs/libc/modlib/modlib_remove.c @@ -53,7 +53,9 @@ int modlib_remove(FAR void *handle) { FAR struct module_s *modp = (FAR struct module_s *)handle; + FAR void (**array)(void); int ret; + int i; DEBUGASSERT(modp != NULL); @@ -83,6 +85,12 @@ int modlib_remove(FAR void *handle) /* Is there an uninitializer? */ + array = (FAR void (**)(void))modp->finiarr; + for (i = 0; i < modp->nfini; i++) + { + array[i](); + } + if (modp->modinfo.uninitializer != NULL) { /* Try to uninitialize the module */ @@ -97,11 +105,12 @@ int modlib_remove(FAR void *handle) goto errout_with_lock; } + modlib_freesymtab(modp); + /* Nullify so that the uninitializer cannot be called again */ modp->modinfo.uninitializer = NULL; #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) - modp->initializer = NULL; modp->modinfo.arg = NULL; modp->modinfo.exports = NULL; modp->modinfo.nexports = 0; diff --git a/libs/libc/modlib/modlib_symbols.c b/libs/libc/modlib/modlib_symbols.c index 7cf0b4fa6961a..5412daf3c041a 100644 --- a/libs/libc/modlib/modlib_symbols.c +++ b/libs/libc/modlib/modlib_symbols.c @@ -495,8 +495,13 @@ int modlib_insertsymtab(FAR struct module_s *modp, nsym = shdr->sh_size / sizeof(Elf_Sym); for (i = 0, symcount = 0; i < nsym; i++) { - if (sym[i].st_name != 0) + if (sym[i].st_name != 0 && + ELF_ST_BIND(sym[i].st_info) == STB_GLOBAL && + ELF_ST_TYPE(sym[i].st_info) != STT_NOTYPE && + ELF_ST_VISIBILITY(sym[i].st_other) == STV_DEFAULT) + { symcount++; + } } if (symcount > 0) @@ -511,7 +516,10 @@ int modlib_insertsymtab(FAR struct module_s *modp, modp->modinfo.nexports = symcount; for (i = 0, j = 0; i < nsym; i++) { - if (sym[i].st_name != 0) + if (sym[i].st_name != 0 && + ELF_ST_BIND(sym[i].st_info) == STB_GLOBAL && + ELF_ST_TYPE(sym[i].st_info) != STT_NOTYPE && + ELF_ST_VISIBILITY(sym[i].st_other) == STV_DEFAULT) { ret = modlib_symname(loadinfo, &sym[i], strtab->sh_offset); if (ret < 0) @@ -528,6 +536,10 @@ int modlib_insertsymtab(FAR struct module_s *modp, j++; } } + +#ifdef CONFIG_SYMTAB_ORDEREDBYNAME + symtab_sortbyname(symbol, symcount); +#endif } else { diff --git a/sched/module/mod_procfs.c b/sched/module/mod_procfs.c index 85938d877a55d..0644ad3cb89cc 100644 --- a/sched/module/mod_procfs.c +++ b/sched/module/mod_procfs.c @@ -137,8 +137,8 @@ static int modprocfs_callback(FAR struct module_s *modp, FAR void *arg) priv = (FAR struct modprocfs_file_s *)arg; linesize = snprintf(priv->line, MOD_LINELEN, - "%s,%p,%p,%p,%u,%p,%lu,%p,%lu\n", - modp->modname, modp->initializer, + "%s,%p,%p,%u,%p,%lu,%p,%lu\n", + modp->modname, modp->modinfo.uninitializer, modp->modinfo.arg, modp->modinfo.nexports, modp->textalloc,