summaryrefslogtreecommitdiff
path: root/nuttx/binfmt
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-08-26 07:57:30 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-08-26 07:57:30 -0600
commitaa4358a48b3469d6f99b2bda43752ba8bd4007ad (patch)
tree82f020a674be9240eea421abc4c66d3dd0d567e4 /nuttx/binfmt
parent8591a6b1d525711a3cf3d226f0ce80eda4a6b663 (diff)
downloadnuttx-aa4358a48b3469d6f99b2bda43752ba8bd4007ad.tar.gz
nuttx-aa4358a48b3469d6f99b2bda43752ba8bd4007ad.tar.bz2
nuttx-aa4358a48b3469d6f99b2bda43752ba8bd4007ad.zip
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
Diffstat (limited to 'nuttx/binfmt')
-rw-r--r--nuttx/binfmt/libelf/libelf_bind.c59
-rw-r--r--nuttx/binfmt/libelf/libelf_load.c94
2 files changed, 80 insertions, 73 deletions
diff --git a/nuttx/binfmt/libelf/libelf_bind.c b/nuttx/binfmt/libelf/libelf_bind.c
index d046b7a7b..da2dcd4ce 100644
--- a/nuttx/binfmt/libelf/libelf_bind.c
+++ b/nuttx/binfmt/libelf/libelf_bind.c
@@ -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;
}
diff --git a/nuttx/binfmt/libelf/libelf_load.c b/nuttx/binfmt/libelf/libelf_load.c
index 81016a908..de3165606 100644
--- a/nuttx/binfmt/libelf/libelf_load.c
+++ b/nuttx/binfmt/libelf/libelf_load.c
@@ -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,29 +248,63 @@ 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_loadfile(loadinfo);
+ ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize);
if (ret < 0)
{
- bdbg("elf_loadfile failed: %d\n", ret);
+ 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("ERROR: elf_loadfile failed: %d\n", ret);
+ goto errout_with_addrenv;
+ }
+
/* Load static constructors and destructors. */
#ifdef CONFIG_BINFMT_CONSTRUCTORS
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;