diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-10-29 20:43:35 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-10-29 20:43:35 +0000 |
commit | b48508c844dbd558e728c5695136696b5dfea1fc (patch) | |
tree | b7c28580644d845360274723b39b8367ed109bba /nuttx/binfmt/libelf | |
parent | 5681b615ec10265a27677bc2ca98fa385460afec (diff) | |
download | px4-firmware-b48508c844dbd558e728c5695136696b5dfea1fc.tar.gz px4-firmware-b48508c844dbd558e728c5695136696b5dfea1fc.tar.bz2 px4-firmware-b48508c844dbd558e728c5695136696b5dfea1fc.zip |
C++ static destructors work with ELF load too now
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5274 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/binfmt/libelf')
-rw-r--r-- | nuttx/binfmt/libelf/Make.defs | 2 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf.h | 19 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_bind.c | 2 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_ctors.c | 35 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_dtors.c | 215 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_load.c | 31 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_unload.c | 39 |
7 files changed, 291 insertions, 52 deletions
diff --git a/nuttx/binfmt/libelf/Make.defs b/nuttx/binfmt/libelf/Make.defs index 26198ade2..c8857c3f7 100644 --- a/nuttx/binfmt/libelf/Make.defs +++ b/nuttx/binfmt/libelf/Make.defs @@ -46,7 +46,7 @@ BINFMT_CSRCS += libelf_bind.c libelf_init.c libelf_iobuffer.c libelf_load.c \ libelf_unload.c libelf_verify.c ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y) -BINFMT_CSRCS += libelf_ctors.c +BINFMT_CSRCS += libelf_ctors.c libelf_dtors.c endif # Hook the libelf subdirectory into the build diff --git a/nuttx/binfmt/libelf/libelf.h b/nuttx/binfmt/libelf/libelf.h index bea92496a..5b0be9ab0 100644 --- a/nuttx/binfmt/libelf/libelf.h +++ b/nuttx/binfmt/libelf/libelf.h @@ -236,4 +236,23 @@ int elf_reallocbuffer(FAR struct elf_loadinfo_s *loadinfo, size_t increment); int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo); #endif +/**************************************************************************** + * Name: elf_loaddtors + * + * Description: + * Load pointers to static destructors into an in-memory array. + * + * Input Parameters: + * loadinfo - Load state information + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_BINFMT_CONSTRUCTORS +int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo); +#endif + #endif /* __BINFMT_LIBELF_LIBELF_H */ diff --git a/nuttx/binfmt/libelf/libelf_bind.c b/nuttx/binfmt/libelf/libelf_bind.c index ef1b4fc8f..e35087b1d 100644 --- a/nuttx/binfmt/libelf/libelf_bind.c +++ b/nuttx/binfmt/libelf/libelf_bind.c @@ -298,7 +298,7 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo, /* Flush the instruction cache before starting the newly loaded module */ #ifdef CONFIG_ELF_ICACHE - arch_flushicache((FAR void*)loadinfo->alloc, loadinfo->allocsize); + arch_flushicache((FAR void*)loadinfo->elfalloc, loadinfo->elfsize); #endif return ret; diff --git a/nuttx/binfmt/libelf/libelf_ctors.c b/nuttx/binfmt/libelf/libelf_ctors.c index a57fc37d9..20f1256e2 100644 --- a/nuttx/binfmt/libelf/libelf_ctors.c +++ b/nuttx/binfmt/libelf/libelf_ctors.c @@ -75,7 +75,7 @@ * Name: elf_loadctors * * Description: - * Load points to static constructors into an in-memory array. + * Load pointers to static constructors into an in-memory array. * * Input Parameters: * loadinfo - Load state information @@ -96,8 +96,8 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) DEBUGASSERT(loadinfo->ctors == NULL); - /* Allocate an I/O buffer. This buffer is used by elf_sectname() to - * accumulate the variable length symbol name. + /* Allocate an I/O buffer if necessary. This buffer is used by + * elf_sectname() to accumulate the variable length symbol name. */ ret = elf_allocbuffer(loadinfo); @@ -110,7 +110,7 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) /* Find the index to the section named ".ctors." NOTE: On old ABI system, * .ctors is the name of the section containing the list of constructors; * On newer systems, the similar section is called .init_array. It is - * expected that the linker script will force the sectino name to be ".ctors" + * expected that the linker script will force the section name to be ".ctors" * in either case. */ @@ -136,10 +136,10 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) */ ctorsize = shdr->sh_size; - loadinfo->nctors = ctorsize / sizeof(elf_ctor_t); + loadinfo->nctors = ctorsize / sizeof(binfmt_ctor_t); - bvdbg("ctoridx=%d ctorsize=%d sizeof(elf_ctor_t)=%d nctors=%d\n", - ctoridx, ctorsize, sizeof(elf_ctor_t), loadinfo->nctors); + bvdbg("ctoridx=%d ctorsize=%d sizeof(binfmt_ctor_t)=%d nctors=%d\n", + ctoridx, ctorsize, sizeof(binfmt_ctor_t), loadinfo->nctors); /* Check if there are any constructors. It is not an error if there * are none. @@ -149,7 +149,7 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) { /* Check an assumption that we made above */ - DEBUGASSERT(shdr->sh_size == loadinfo->nctors * sizeof(elf_ctor_t)); + DEBUGASSERT(shdr->sh_size == loadinfo->nctors * sizeof(binfmt_ctor_t)); /* In the old ABI, the .ctors section is not allocated. In that case, * we need to allocate memory to hold the .ctors and then copy the @@ -161,19 +161,17 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) if ((shdr->sh_flags & SHF_ALLOC) == 0) { - /* Not loaded -> Old ABI. */ - - loadinfo->newabi = false; - /* Allocate memory to hold a copy of the .ctor section */ - loadinfo->ctors = (elf_ctor_t*)kmalloc(ctorsize); - if (!loadinfo->ctors) + loadinfo->ctoralloc = (binfmt_ctor_t*)kmalloc(ctorsize); + if (!loadinfo->ctoralloc) { bdbg("Failed to allocate memory for .ctors\n"); return -ENOMEM; } + loadinfo->ctors = (binfmt_ctor_t *)loadinfo->ctoralloc; + /* Read the section header table into memory */ ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->ctors, ctorsize, @@ -194,23 +192,20 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]); bvdbg("ctor %d: %08lx + %08lx = %08lx\n", - i, *ptr, loadinfo->alloc, *ptr + loadinfo->alloc); + i, *ptr, loadinfo->elfalloc, *ptr + loadinfo->elfalloc); - *ptr += loadinfo->alloc; + *ptr += loadinfo->elfalloc; } } else { - /* Loaded -> New ABI. */ - - loadinfo->newabi = true; /* Save the address of the .ctors (actually, .init_array) where it was * loaded into memory. Since the .ctors lie in allocated memory, they * will be relocated via the normal mechanism. */ - loadinfo->ctors = (elf_ctor_t*)shdr->sh_addr; + loadinfo->ctors = (binfmt_ctor_t*)shdr->sh_addr; } } diff --git a/nuttx/binfmt/libelf/libelf_dtors.c b/nuttx/binfmt/libelf/libelf_dtors.c new file mode 100644 index 000000000..c0c73a337 --- /dev/null +++ b/nuttx/binfmt/libelf/libelf_dtors.c @@ -0,0 +1,215 @@ +/**************************************************************************** + * binfmt/libelf/libelf_dtors.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/kmalloc.h> +#include <nuttx/binfmt/elf.h> + +#include "libelf.h" + +#ifdef CONFIG_BINFMT_CONSTRUCTORS + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: elf_loaddtors + * + * Description: + * Load pointers to static destructors into an in-memory array. + * + * Input Parameters: + * loadinfo - Load state information + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo) +{ + FAR Elf32_Shdr *shdr; + size_t dtorsize; + int dtoridx; + int ret; + int i; + + DEBUGASSERT(loadinfo->dtors == NULL); + + /* Allocate an I/O buffer if necessary. This buffer is used by + * elf_sectname() to accumulate the variable length symbol name. + */ + + ret = elf_allocbuffer(loadinfo); + if (ret < 0) + { + bdbg("elf_allocbuffer failed: %d\n", ret); + return -ENOMEM; + } + + /* Find the index to the section named ".dtors." NOTE: On old ABI system, + * .dtors is the name of the section containing the list of destructors; + * On newer systems, the similar section is called .fini_array. It is + * expected that the linker script will force the section name to be ".dtors" + * in either case. + */ + + dtoridx = elf_findsection(loadinfo, ".dtors"); + if (dtoridx < 0) + { + /* This may not be a failure. -ENOENT indicates that the file has no + * static destructor section. + */ + + bvdbg("elf_findsection .dtors section failed: %d\n", dtoridx); + return ret == -ENOENT ? OK : ret; + } + + /* Now we can get a pointer to the .dtor section in the section header + * table. + */ + + shdr = &loadinfo->shdr[dtoridx]; + + /* Get the size of the .dtor section and the number of destructors that + * will need to be called. + */ + + dtorsize = shdr->sh_size; + loadinfo->ndtors = dtorsize / sizeof(binfmt_dtor_t); + + bvdbg("dtoridx=%d dtorsize=%d sizeof(binfmt_dtor_t)=%d ndtors=%d\n", + dtoridx, dtorsize, sizeof(binfmt_dtor_t), loadinfo->ndtors); + + /* Check if there are any destructors. It is not an error if there + * are none. + */ + + if (loadinfo->ndtors > 0) + { + /* Check an assumption that we made above */ + + DEBUGASSERT(shdr->sh_size == loadinfo->ndtors * sizeof(binfmt_dtor_t)); + + /* In the old ABI, the .dtors section is not allocated. In that case, + * we need to allocate memory to hold the .dtors and then copy the + * from the file into the allocated memory. + * + * SHF_ALLOC indicates that the section requires memory during + * execution. + */ + + if ((shdr->sh_flags & SHF_ALLOC) == 0) + { + /* Allocate memory to hold a copy of the .dtor section */ + + loadinfo->ctoralloc = (binfmt_dtor_t*)kmalloc(dtorsize); + if (!loadinfo->ctoralloc) + { + bdbg("Failed to allocate memory for .dtors\n"); + return -ENOMEM; + } + + loadinfo->dtors = (binfmt_dtor_t *)loadinfo->ctoralloc; + + /* Read the section header table into memory */ + + ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->dtors, dtorsize, + shdr->sh_offset); + if (ret < 0) + { + bdbg("Failed to allocate .dtors: %d\n", ret); + return ret; + } + + /* Fix up all of the .dtor addresses. Since the addresses + * do not lie in allocated memory, there will be no relocation + * section for them. + */ + + for (i = 0; i < loadinfo->ndtors; i++) + { + FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->dtors)[i]); + + bvdbg("dtor %d: %08lx + %08lx = %08lx\n", + i, *ptr, loadinfo->elfalloc, *ptr + loadinfo->elfalloc); + + *ptr += loadinfo->elfalloc; + } + } + else + { + + /* Save the address of the .dtors (actually, .init_array) where it was + * loaded into memory. Since the .dtors lie in allocated memory, they + * will be relocated via the normal mechanism. + */ + + loadinfo->dtors = (binfmt_dtor_t*)shdr->sh_addr; + } + } + + return OK; +} + +#endif /* CONFIG_BINFMT_CONSTRUCTORS */ diff --git a/nuttx/binfmt/libelf/libelf_load.c b/nuttx/binfmt/libelf/libelf_load.c index 221ae8d43..b1ac44e21 100644 --- a/nuttx/binfmt/libelf/libelf_load.c +++ b/nuttx/binfmt/libelf/libelf_load.c @@ -76,7 +76,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: elf_allocsize + * Name: elf_elfsize * * Description: * Calculate total memory allocation for the ELF file. @@ -87,14 +87,14 @@ * ****************************************************************************/ -static void elf_allocsize(struct elf_loadinfo_s *loadinfo) +static void elf_elfsize(struct elf_loadinfo_s *loadinfo) { - size_t allocsize; + size_t elfsize; int i; /* Accumulate the size each section into memory that is marked SHF_ALLOC */ - allocsize = 0; + elfsize = 0; for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; @@ -105,13 +105,13 @@ static void elf_allocsize(struct elf_loadinfo_s *loadinfo) if ((shdr->sh_flags & SHF_ALLOC) != 0) { - allocsize += ELF_ALIGNUP(shdr->sh_size); + elfsize += ELF_ALIGNUP(shdr->sh_size); } } /* Save the allocation size */ - loadinfo->allocsize = allocsize; + loadinfo->elfsize = elfsize; } /**************************************************************************** @@ -136,8 +136,8 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo) /* Allocate (and zero) memory for the ELF file. */ - loadinfo->alloc = (uintptr_t)kzalloc(loadinfo->allocsize); - if (!loadinfo->alloc) + loadinfo->elfalloc = (uintptr_t)kzalloc(loadinfo->elfsize); + if (!loadinfo->elfalloc) { return -ENOMEM; } @@ -145,7 +145,7 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo) /* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */ bvdbg("Loaded sections:\n"); - dest = (FAR uint8_t*)loadinfo->alloc; + dest = (FAR uint8_t*)loadinfo->elfalloc; for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { @@ -223,7 +223,7 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo) /* Determine total size to allocate */ - elf_allocsize(loadinfo); + elf_elfsize(loadinfo); /* Allocate memory and load sections into memory */ @@ -234,7 +234,7 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo) goto errout_with_buffers; } - /* Find static constructors. */ + /* Load static constructors and destructors. */ #ifdef CONFIG_BINFMT_CONSTRUCTORS ret = elf_loadctors(loadinfo); @@ -243,6 +243,13 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo) bdbg("elf_loadctors failed: %d\n", ret); goto errout_with_buffers; } + + ret = elf_loaddtors(loadinfo); + if (ret < 0) + { + bdbg("elf_loaddtors failed: %d\n", ret); + goto errout_with_buffers; + } #endif return OK; @@ -250,7 +257,7 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo) /* Error exits */ errout_with_buffers: - elf_freebuffers(loadinfo); + elf_unload(loadinfo); return ret; } diff --git a/nuttx/binfmt/libelf/libelf_unload.c b/nuttx/binfmt/libelf/libelf_unload.c index 8102f7bf2..532fc606f 100644 --- a/nuttx/binfmt/libelf/libelf_unload.c +++ b/nuttx/binfmt/libelf/libelf_unload.c @@ -84,31 +84,34 @@ int elf_unload(struct elf_loadinfo_s *loadinfo) /* Release memory holding the relocated ELF image */ - if (loadinfo->alloc) + if (loadinfo->elfalloc != 0) { - kfree((FAR void *)loadinfo->alloc); - loadinfo->alloc = 0; - loadinfo->allocsize = 0; + kfree((FAR void *)loadinfo->elfalloc); + loadinfo->elfalloc = 0; } - /* Release any allocated constructor memory */ + loadinfo->elfsize = 0; + + /* Release memory used to hold static constructors and destructors */ #ifdef CONFIG_BINFMT_CONSTRUCTORS - if (loadinfo->ctors) + if (loadinfo->ctoralloc != 0) { - /* In the old ABI, the .ctors section is not make for allocation. In - * that case, we need to free the working buffer that was used to hold - * the constructors. - */ - - if (!loadinfo->newabi) - { - kfree((FAR void *)loadinfo->ctors); - } - - loadinfo->ctors = NULL; - loadinfo->nctors = 0; + kfree(loadinfo->ctoralloc); + loadinfo->ctoralloc = NULL; } + + loadinfo->ctors = NULL; + loadinfo->nctors = 0; + + if (loadinfo->dtoralloc != 0) + { + kfree(loadinfo->dtoralloc); + loadinfo->dtoralloc = NULL; + } + + loadinfo->dtors = NULL; + loadinfo->ndtors = 0; #endif return OK; |