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

View File

@ -175,6 +175,9 @@
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_INIT_ARRAY 14
#define SHT_FINI_ARRAY 15
#define SHT_PREINIT_ARRAY 16
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000

View File

@ -40,6 +40,11 @@
#define ELF32_ST_TYPE(i) ((i) & 0xf)
#define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf))
/* 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)
/* Definitions for Elf32_Rel*::r_info */
#define ELF32_R_SYM(i) ((i) >> 8)

View File

@ -38,6 +38,15 @@
/* 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))
/* 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)
/* Definitions for Elf64_Rel*::r_info */
#define ELF64_R_SYM(i) ((i) >> 32)

View File

@ -173,6 +173,8 @@ struct module_s
FAR struct module_s *dependencies[CONFIG_MODLIB_MAXDEPEND];
#endif
uintptr_t finiarr; /* .fini_array */
uint16_t nfini; /* Number of entries in .fini_array */
};
/* This struct provides a description of the currently loaded instantiation
@ -202,6 +204,12 @@ struct mod_loadinfo_s
uint8_t *iobuffer; /* File I/O buffer */
uintptr_t datasec; /* ET_DYN - data area start from Phdr */
uintptr_t segpad; /* Padding between text and data */
uintptr_t initarr; /* .init_array */
uintptr_t finiarr; /* .fini_array */
uintptr_t preiarr; /* .preinit_array */
uint16_t ninit; /* Number of .init_array entries */
uint16_t nfini; /* Number of .fini_array entries */
uint16_t nprei; /* Number of .preinit_array entries */
uint16_t symtabidx; /* Symbol table section index */
uint16_t strtabidx; /* String table section index */
uint16_t dsymtabidx; /* Dynamic symbol table section index */

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;

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)
{
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 */

View File

@ -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:"
@ -695,7 +704,8 @@ static int modlib_relocatedyn(FAR struct module_s *modp,
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);
@ -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