mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 17:33:08 +08:00
Fix and improve dynamic loader
This patch fixes some issues found by Mark Stevens and improve the dynamic loader.
This commit is contained in:
committed by
Xiang Xiao
parent
4d285cb14d
commit
878384fef0
@@ -57,7 +57,9 @@
|
||||
static inline int dlremove(FAR void *handle)
|
||||
{
|
||||
FAR struct module_s *modp = (FAR struct module_s *)handle;
|
||||
void (**array)(void);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(modp != NULL);
|
||||
|
||||
@@ -104,6 +106,15 @@ static inline int dlremove(FAR void *handle)
|
||||
/* Nullify so that the uninitializer cannot be called again */
|
||||
|
||||
modp->modinfo.uninitializer = NULL;
|
||||
|
||||
/* Call any .fini_array entries in reverse order */
|
||||
|
||||
array = (void (**)(void)) modp->finiarr;
|
||||
for (i = (modp->nfini - 1); i >= 0; i--)
|
||||
{
|
||||
array[i]();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||
modp->initializer = NULL;
|
||||
modp->modinfo.arg = NULL;
|
||||
|
||||
@@ -181,7 +181,9 @@ static inline FAR void *dlinsert(FAR const char *filename)
|
||||
struct mod_loadinfo_s loadinfo;
|
||||
FAR struct module_s *modp;
|
||||
mod_initializer_t initializer;
|
||||
void (**array)(void);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
binfo("Loading file: %s\n", filename);
|
||||
|
||||
@@ -249,14 +251,37 @@ static inline FAR void *dlinsert(FAR const char *filename)
|
||||
|
||||
/* Call the module initializer */
|
||||
|
||||
if (loadinfo.ehdr.e_type == ET_REL)
|
||||
switch (loadinfo.ehdr.e_type)
|
||||
{
|
||||
ret = initializer(&modp->modinfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
binfo("Failed to initialize the module: %d\n", ret);
|
||||
goto errout_with_load;
|
||||
}
|
||||
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 */
|
||||
|
||||
array = (void (**)(void)) loadinfo.preiarr;
|
||||
for (i = 0; i < loadinfo.nprei; i++)
|
||||
{
|
||||
array[i]();
|
||||
}
|
||||
|
||||
/* Process any init_array entries */
|
||||
|
||||
array = (void (**)(void)) loadinfo.initarr;
|
||||
for (i = 0; i < loadinfo.ninit; i++)
|
||||
{
|
||||
array[i]();
|
||||
}
|
||||
|
||||
modp->finiarr = loadinfo.finiarr;
|
||||
modp->nfini = loadinfo.nfini;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add the new module entry to the registry */
|
||||
|
||||
@@ -591,7 +591,7 @@ static int modlib_relocatedyn(FAR struct module_s *modp,
|
||||
for (i = 0; dyn[i].d_tag != DT_NULL; i++)
|
||||
{
|
||||
switch (dyn[i].d_tag)
|
||||
{
|
||||
{
|
||||
case DT_REL :
|
||||
relData.relOff[I_REL] = dyn[i].d_un.d_val;
|
||||
break;
|
||||
@@ -601,18 +601,18 @@ static int modlib_relocatedyn(FAR struct module_s *modp,
|
||||
case DT_RELENT :
|
||||
relData.relEntSz = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_SYMTAB :
|
||||
relData.symOff = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_STRTAB :
|
||||
relData.strOff = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_JMPREL :
|
||||
relData.relOff[I_PLT] = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_PLTRELSZ :
|
||||
relData.relSz[I_PLT] = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_SYMTAB :
|
||||
relData.symOff = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_STRTAB :
|
||||
relData.strOff = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_JMPREL :
|
||||
relData.relOff[I_PLT] = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_PLTRELSZ :
|
||||
relData.relSz[I_PLT] = dyn[i].d_un.d_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,10 +658,19 @@ static int modlib_relocatedyn(FAR struct module_s *modp,
|
||||
|
||||
if (!(i % CONFIG_MODLIB_RELOCATION_BUFFERCOUNT))
|
||||
{
|
||||
size_t relSize = (sizeof(Elf_Rel) *
|
||||
CONFIG_MODLIB_RELOCATION_BUFFERCOUNT);
|
||||
|
||||
if (relData.relSz[idx_rel] < relSize)
|
||||
{
|
||||
relSize = relData.relSz[idx_rel];
|
||||
}
|
||||
|
||||
ret = modlib_read(loadinfo, (FAR uint8_t *) rels,
|
||||
sizeof(Elf_Rel) * CONFIG_MODLIB_RELOCATION_BUFFERCOUNT,
|
||||
relSize,
|
||||
relData.relOff[idx_rel] +
|
||||
i * sizeof(Elf_Rel));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
berr("ERROR: Section %d reloc %d:"
|
||||
@@ -689,13 +698,14 @@ static int modlib_relocatedyn(FAR struct module_s *modp,
|
||||
|
||||
if ((idx_sym = ELF_R_SYM(rel->r_info)) != 0)
|
||||
{
|
||||
if (sym[idx_sym].st_shndx == SHN_UNDEF) /* We have an external reference */
|
||||
if (sym[idx_sym].st_shndx == SHN_UNDEF) /* We have an external reference */
|
||||
{
|
||||
void *ep;
|
||||
|
||||
ep = modlib_findglobal(modp, loadinfo, symhdr,
|
||||
&sym[idx_sym]);
|
||||
if (ep == NULL)
|
||||
if ((ep == NULL) && (ELF_ST_BIND(sym[idx_sym].st_info)
|
||||
!= STB_WEAK))
|
||||
{
|
||||
berr("ERROR: Unable to resolve addr of ext ref %s\n",
|
||||
loadinfo->iobuffer);
|
||||
@@ -707,7 +717,7 @@ static int modlib_relocatedyn(FAR struct module_s *modp,
|
||||
}
|
||||
|
||||
addr = rel->r_offset + loadinfo->textalloc;
|
||||
*(uintptr_t *)addr = (uintptr_t)ep;
|
||||
*(uintptr_t *)addr = (uintptr_t)ep;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -834,6 +844,27 @@ int modlib_bind(FAR struct module_s *modp,
|
||||
case SHT_DYNSYM :
|
||||
loadinfo->dsymtabidx = i;
|
||||
break;
|
||||
case SHT_INIT_ARRAY :
|
||||
loadinfo->initarr = loadinfo->shdr[i].sh_addr -
|
||||
loadinfo->datasec +
|
||||
loadinfo->datastart;
|
||||
loadinfo->ninit = loadinfo->shdr[i].sh_size /
|
||||
sizeof(uintptr_t);
|
||||
break;
|
||||
case SHT_FINI_ARRAY :
|
||||
loadinfo->finiarr = loadinfo->shdr[i].sh_addr -
|
||||
loadinfo->datasec +
|
||||
loadinfo->datastart;
|
||||
loadinfo->nfini = loadinfo->shdr[i].sh_size /
|
||||
sizeof(uintptr_t);
|
||||
break;
|
||||
case SHT_PREINIT_ARRAY :
|
||||
loadinfo->preiarr = loadinfo->shdr[i].sh_addr -
|
||||
loadinfo->datasec +
|
||||
loadinfo->datastart;
|
||||
loadinfo->nprei = loadinfo->shdr[i].sh_size /
|
||||
sizeof(uintptr_t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -852,7 +883,7 @@ int modlib_bind(FAR struct module_s *modp,
|
||||
switch (loadinfo->shdr[i].sh_type)
|
||||
{
|
||||
case SHT_REL :
|
||||
ret = modlib_relocate(modp, loadinfo, i);
|
||||
ret = modlib_relocate(modp, loadinfo, i);
|
||||
break;
|
||||
case SHT_RELA :
|
||||
ret = modlib_relocateadd(modp, loadinfo, i);
|
||||
|
||||
Reference in New Issue
Block a user