Change when address environment is instantiated; there are/were locations where access is made to the allocation address environment when it is not yet in place

This commit is contained in:
Gregory Nutt 2014-08-26 07:57:30 -06:00
parent dbeba82e85
commit d52599fe8e
2 changed files with 80 additions and 73 deletions

View file

@ -195,42 +195,14 @@ static int elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
addr = dstsec->sh_addr + rel.r_offset;
/* If CONFIG_ARCH_ADDRENV=y, then 'addr' lies in a virtual address space that
* may not be in place now. elf_addrenv_select() will temporarily
* instantiate that address space.
*/
#ifdef CONFIG_ARCH_ADDRENV
ret = elf_addrenv_select(loadinfo);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_select() failed: %d\n", ret);
return ret;
}
#endif
/* Now perform the architecture-specific relocation */
ret = up_relocate(&rel, &sym, addr);
if (ret < 0)
{
#ifdef CONFIG_ARCH_ADDRENV
(void)elf_addrenv_restore(loadinfo);
#endif
bdbg("ERROR: Section %d reloc %d: Relocation failed: %d\n", ret);
return ret;
}
/* Restore the original address environment */
#ifdef CONFIG_ARCH_ADDRENV
ret = elf_addrenv_restore(loadinfo);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_restore() failed: %d\n", ret);
return ret;
}
#endif
}
return OK;
@ -263,6 +235,9 @@ static int elf_relocateadd(FAR struct elf_loadinfo_s *loadinfo, int relidx,
int elf_bind(FAR struct elf_loadinfo_s *loadinfo,
FAR const struct symtab_s *exports, int nexports)
{
#ifdef CONFIG_ARCH_ADDRENV
int status;
#endif
int ret;
int i;
@ -285,6 +260,20 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo,
return -ENOMEM;
}
#ifdef CONFIG_ARCH_ADDRENV
/* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address
* space that may not be in place now. elf_addrenv_select() will
* temporarily instantiate that address space.
*/
ret = elf_addrenv_select(loadinfo);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_select() failed: %d\n", ret);
return ret;
}
#endif
/* Process relocations in every allocated section */
for (i = 1; i < loadinfo->ehdr.e_shnum; i++)
@ -332,5 +321,19 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo,
up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
#endif
#ifdef CONFIG_ARCH_ADDRENV
/* Restore the original address environment */
status = elf_addrenv_restore(loadinfo);
if (status < 0)
{
bdbg("ERROR: elf_addrenv_restore() failed: %d\n", status);
if (ret == OK)
{
ret = status;
}
}
#endif
return ret;
}

View file

@ -132,9 +132,8 @@ static void elf_elfsize(struct elf_loadinfo_s *loadinfo)
* Name: elf_loadfile
*
* Description:
* Allocate memory for the file and read the section data into the
* allocated memory. Section addresses in the shdr[] are updated to point
* to the corresponding position in the allocated memory.
* Read the section data into memory. Section addresses in the shdr[] are
* updated to point to the corresponding position in the memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
@ -150,15 +149,6 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
int ret;
int i;
/* Allocate (and zero) memory for the ELF file. */
ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_alloc() failed: %d\n", ret);
return ret;
}
/* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */
bvdbg("Loaded sections:\n");
@ -196,39 +186,14 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
if (shdr->sh_type != SHT_NOBITS)
{
/* If CONFIG_ARCH_ADDRENV=y, then 'text' lies in a virtual address
* space that may not be in place now. elf_addrenv_select() will
* temporarily instantiate that address space.
*/
#ifdef CONFIG_ARCH_ADDRENV
ret = elf_addrenv_select(loadinfo);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_select() failed: %d\n", ret);
return ret;
}
#endif
/* Read the section data from sh_offset to the memory region */
ret = elf_read(loadinfo, *pptr, shdr->sh_size, shdr->sh_offset);
if (ret < 0)
{
bdbg("Failed to read section %d: %d\n", i, ret);
bdbg("ERROR: Failed to read section %d: %d\n", i, ret);
return ret;
}
/* Restore the original address environment */
#ifdef CONFIG_ARCH_ADDRENV
ret = elf_addrenv_restore(loadinfo);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_restore() failed: %d\n", ret);
return ret;
}
#endif
}
/* Update sh_addr to point to copy in memory */
@ -275,7 +240,7 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo)
ret = elf_loadshdrs(loadinfo);
if (ret < 0)
{
bdbg("elf_loadshdrs failed: %d\n", ret);
bdbg("ERROR: elf_loadshdrs failed: %d\n", ret);
goto errout_with_buffers;
}
@ -283,13 +248,36 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo)
elf_elfsize(loadinfo);
/* Allocate memory and load sections into memory */
/* Allocate (and zero) memory for the ELF file. */
ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_alloc() failed: %d\n", ret);
goto errout_with_buffers;
}
#ifdef CONFIG_ARCH_ADDRENV
/* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address
* space that may not be in place now. elf_addrenv_select() will
* temporarily instantiate that address space.
*/
ret = elf_addrenv_select(loadinfo);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_select() failed: %d\n", ret);
goto errout_with_buffers;
}
#endif
/* Load ELF section data into memory */
ret = elf_loadfile(loadinfo);
if (ret < 0)
{
bdbg("elf_loadfile failed: %d\n", ret);
goto errout_with_buffers;
bdbg("ERROR: elf_loadfile failed: %d\n", ret);
goto errout_with_addrenv;
}
/* Load static constructors and destructors. */
@ -298,14 +286,25 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo)
ret = elf_loadctors(loadinfo);
if (ret < 0)
{
bdbg("elf_loadctors failed: %d\n", ret);
goto errout_with_buffers;
bdbg("ERROR: elf_loadctors failed: %d\n", ret);
goto errout_with_addrenv;
}
ret = elf_loaddtors(loadinfo);
if (ret < 0)
{
bdbg("elf_loaddtors failed: %d\n", ret);
bdbg("ERROR: elf_loaddtors failed: %d\n", ret);
goto errout_with_addrenv;
}
#endif
#ifdef CONFIG_ARCH_ADDRENV
/* Restore the original address environment */
ret = elf_addrenv_restore(loadinfo);
if (ret < 0)
{
bdbg("ERROR: elf_addrenv_restore() failed: %d\n", ret);
goto errout_with_buffers;
}
#endif
@ -314,6 +313,11 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo)
/* Error exits */
errout_with_addrenv:
#ifdef CONFIG_ARCH_ADDRENV
(void)elf_addrenv_restore(loadinfo);
#endif
errout_with_buffers:
elf_unload(loadinfo);
return ret;