modlib:Standardized module loading method

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 <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao 2024-04-28 18:16:07 +08:00 committed by Xiang Xiao
parent 5df3625b62
commit a9cb28cd23
10 changed files with 115 additions and 90 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -33,6 +33,16 @@ SECTIONS
_etext = . ;
}
.init_array :
{
*(.init_array)
}
.fini_array :
{
*(.fini_array)
}
.rodata :
{
_srodata = . ;

View File

@ -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).

View File

@ -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 @@ errout_with_loadinfo:
set_errno(-ret);
return NULL;
}

View File

@ -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;

View File

@ -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
{

View File

@ -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,