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:
parent
5df3625b62
commit
a9cb28cd23
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -33,6 +33,16 @@ SECTIONS
|
|||
_etext = . ;
|
||||
}
|
||||
|
||||
.init_array :
|
||||
{
|
||||
*(.init_array)
|
||||
}
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
*(.fini_array)
|
||||
}
|
||||
|
||||
.rodata :
|
||||
{
|
||||
_srodata = . ;
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue