diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-08-26 07:57:30 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-08-26 07:57:30 -0600 |
commit | aa4358a48b3469d6f99b2bda43752ba8bd4007ad (patch) | |
tree | 82f020a674be9240eea421abc4c66d3dd0d567e4 | |
parent | 8591a6b1d525711a3cf3d226f0ce80eda4a6b663 (diff) | |
download | px4-nuttx-aa4358a48b3469d6f99b2bda43752ba8bd4007ad.tar.gz px4-nuttx-aa4358a48b3469d6f99b2bda43752ba8bd4007ad.tar.bz2 px4-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
-rw-r--r-- | nuttx/binfmt/libelf/libelf_bind.c | 59 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_load.c | 94 |
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; |