Skip to content

Commit

Permalink
modlib:Standardized module loading method
Browse files Browse the repository at this point in the history
1. use '__attribute__((constructor))' mark initialize function
2. use '__attribute__((destructor))' mark uninitialize function
3. compile module with -fvisibility=hidden. use `__attribute__((visibility("default")))`
mark is need export symbol.so not need module_initialize to initialize export symbol.

Signed-off-by: anjiahao <[email protected]>
  • Loading branch information
anjiahao1 committed Oct 4, 2024
1 parent 0976258 commit 3641273
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 90 deletions.
8 changes: 8 additions & 0 deletions include/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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
Expand Down
24 changes: 13 additions & 11 deletions include/elf32.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 13 additions & 11 deletions include/elf64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions include/nuttx/lib/modlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
10 changes: 10 additions & 0 deletions libs/libc/modlib/gnu-elf.ld
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ SECTIONS
_etext = . ;
}

.init_array :
{
*(.init_array)
}

.fini_array :
{
*(.fini_array)
}

.rodata :
{
_srodata = . ;
Expand Down
72 changes: 45 additions & 27 deletions libs/libc/modlib/modlib_bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
}

Expand All @@ -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).
Expand Down
33 changes: 0 additions & 33 deletions libs/libc/modlib/modlib_insert.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
****************************************************************************/
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -296,4 +264,3 @@ FAR void *modlib_insert(FAR const char *filename, FAR const char *modname)
set_errno(-ret);
return NULL;
}

11 changes: 10 additions & 1 deletion libs/libc/modlib/modlib_remove.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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 */
Expand All @@ -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;
Expand Down
16 changes: 14 additions & 2 deletions libs/libc/modlib/modlib_symbols.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -528,6 +536,10 @@ int modlib_insertsymtab(FAR struct module_s *modp,
j++;
}
}

#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
symtab_sortbyname(symbol, symcount);
#endif
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions sched/module/mod_procfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 3641273

Please sign in to comment.