Fix and improve dynamic loader
This patch fixes some issues found by Mark Stevens and improve the dynamic loader.
This commit is contained in:
parent
4d285cb14d
commit
878384fef0
@ -175,6 +175,9 @@
|
|||||||
#define SHT_REL 9
|
#define SHT_REL 9
|
||||||
#define SHT_SHLIB 10
|
#define SHT_SHLIB 10
|
||||||
#define SHT_DYNSYM 11
|
#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_LOPROC 0x70000000
|
||||||
#define SHT_HIPROC 0x7fffffff
|
#define SHT_HIPROC 0x7fffffff
|
||||||
#define SHT_LOUSER 0x80000000
|
#define SHT_LOUSER 0x80000000
|
||||||
|
@ -40,6 +40,11 @@
|
|||||||
#define ELF32_ST_TYPE(i) ((i) & 0xf)
|
#define ELF32_ST_TYPE(i) ((i) & 0xf)
|
||||||
#define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 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 */
|
/* Definitions for Elf32_Rel*::r_info */
|
||||||
|
|
||||||
#define ELF32_R_SYM(i) ((i) >> 8)
|
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||||
|
@ -38,6 +38,15 @@
|
|||||||
|
|
||||||
/* See ELF-64 Object File Format: Version 1.5 Draft 2 */
|
/* 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 */
|
/* Definitions for Elf64_Rel*::r_info */
|
||||||
|
|
||||||
#define ELF64_R_SYM(i) ((i) >> 32)
|
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||||
|
@ -173,6 +173,8 @@ struct module_s
|
|||||||
|
|
||||||
FAR struct module_s *dependencies[CONFIG_MODLIB_MAXDEPEND];
|
FAR struct module_s *dependencies[CONFIG_MODLIB_MAXDEPEND];
|
||||||
#endif
|
#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
|
/* 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 */
|
uint8_t *iobuffer; /* File I/O buffer */
|
||||||
uintptr_t datasec; /* ET_DYN - data area start from Phdr */
|
uintptr_t datasec; /* ET_DYN - data area start from Phdr */
|
||||||
uintptr_t segpad; /* Padding between text and data */
|
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 symtabidx; /* Symbol table section index */
|
||||||
uint16_t strtabidx; /* String table section index */
|
uint16_t strtabidx; /* String table section index */
|
||||||
uint16_t dsymtabidx; /* Dynamic symbol table section index */
|
uint16_t dsymtabidx; /* Dynamic symbol table section index */
|
||||||
|
@ -57,7 +57,9 @@
|
|||||||
static inline int dlremove(FAR void *handle)
|
static inline int dlremove(FAR void *handle)
|
||||||
{
|
{
|
||||||
FAR struct module_s *modp = (FAR struct module_s *)handle;
|
FAR struct module_s *modp = (FAR struct module_s *)handle;
|
||||||
|
void (**array)(void);
|
||||||
int ret;
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
DEBUGASSERT(modp != NULL);
|
DEBUGASSERT(modp != NULL);
|
||||||
|
|
||||||
@ -104,6 +106,15 @@ static inline int dlremove(FAR void *handle)
|
|||||||
/* Nullify so that the uninitializer cannot be called again */
|
/* Nullify so that the uninitializer cannot be called again */
|
||||||
|
|
||||||
modp->modinfo.uninitializer = NULL;
|
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)
|
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||||
modp->initializer = NULL;
|
modp->initializer = NULL;
|
||||||
modp->modinfo.arg = NULL;
|
modp->modinfo.arg = NULL;
|
||||||
|
@ -181,7 +181,9 @@ static inline FAR void *dlinsert(FAR const char *filename)
|
|||||||
struct mod_loadinfo_s loadinfo;
|
struct mod_loadinfo_s loadinfo;
|
||||||
FAR struct module_s *modp;
|
FAR struct module_s *modp;
|
||||||
mod_initializer_t initializer;
|
mod_initializer_t initializer;
|
||||||
|
void (**array)(void);
|
||||||
int ret;
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
binfo("Loading file: %s\n", filename);
|
binfo("Loading file: %s\n", filename);
|
||||||
|
|
||||||
@ -249,14 +251,37 @@ static inline FAR void *dlinsert(FAR const char *filename)
|
|||||||
|
|
||||||
/* Call the module initializer */
|
/* Call the module initializer */
|
||||||
|
|
||||||
if (loadinfo.ehdr.e_type == ET_REL)
|
switch (loadinfo.ehdr.e_type)
|
||||||
{
|
{
|
||||||
|
case ET_REL :
|
||||||
ret = initializer(&modp->modinfo);
|
ret = initializer(&modp->modinfo);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
binfo("Failed to initialize the module: %d\n", ret);
|
binfo("Failed to initialize the module: %d\n", ret);
|
||||||
goto errout_with_load;
|
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 */
|
/* Add the new module entry to the registry */
|
||||||
|
@ -658,10 +658,19 @@ static int modlib_relocatedyn(FAR struct module_s *modp,
|
|||||||
|
|
||||||
if (!(i % CONFIG_MODLIB_RELOCATION_BUFFERCOUNT))
|
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,
|
ret = modlib_read(loadinfo, (FAR uint8_t *) rels,
|
||||||
sizeof(Elf_Rel) * CONFIG_MODLIB_RELOCATION_BUFFERCOUNT,
|
relSize,
|
||||||
relData.relOff[idx_rel] +
|
relData.relOff[idx_rel] +
|
||||||
i * sizeof(Elf_Rel));
|
i * sizeof(Elf_Rel));
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
berr("ERROR: Section %d reloc %d:"
|
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,
|
ep = modlib_findglobal(modp, loadinfo, symhdr,
|
||||||
&sym[idx_sym]);
|
&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",
|
berr("ERROR: Unable to resolve addr of ext ref %s\n",
|
||||||
loadinfo->iobuffer);
|
loadinfo->iobuffer);
|
||||||
@ -834,6 +844,27 @@ int modlib_bind(FAR struct module_s *modp,
|
|||||||
case SHT_DYNSYM :
|
case SHT_DYNSYM :
|
||||||
loadinfo->dsymtabidx = i;
|
loadinfo->dsymtabidx = i;
|
||||||
break;
|
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
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user