Fix and improve dynamic loader

This patch fixes some issues found by Mark Stevens and
improve the dynamic loader.
This commit is contained in:
Neale Ferguson
2023-07-12 14:37:56 -03:00
committed by Xiang Xiao
parent 4d285cb14d
commit 878384fef0
7 changed files with 122 additions and 30 deletions
+11
View File
@@ -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;
+32 -7
View File
@@ -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 */
+49 -18
View File
@@ -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);