summaryrefslogtreecommitdiff
path: root/nuttx/binfmt
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-10-25 01:23:03 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-10-25 01:23:03 +0000
commit800a488f0a609d99227cb36a4bbf42e0ed2965c6 (patch)
treed7cf26065c05e175730f3ad5f13c818fa3d6dd9a /nuttx/binfmt
parent571f43ec01f49a9630b10c4c3c8a224f0aeb01ee (diff)
downloadpx4-nuttx-800a488f0a609d99227cb36a4bbf42e0ed2965c6.tar.gz
px4-nuttx-800a488f0a609d99227cb36a4bbf42e0ed2965c6.tar.bz2
px4-nuttx-800a488f0a609d99227cb36a4bbf42e0ed2965c6.zip
A little more ELF loader logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5254 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/binfmt')
-rw-r--r--nuttx/binfmt/libelf/Kconfig22
-rw-r--r--nuttx/binfmt/libelf/libelf_load.c211
2 files changed, 201 insertions, 32 deletions
diff --git a/nuttx/binfmt/libelf/Kconfig b/nuttx/binfmt/libelf/Kconfig
index c47bc9f9e..c6e00f604 100644
--- a/nuttx/binfmt/libelf/Kconfig
+++ b/nuttx/binfmt/libelf/Kconfig
@@ -3,7 +3,29 @@
# see misc/tools/kconfig-language.txt.
#
+config ELF_ALIGN_LOG2
+ int "Log2 Section Alignment"
+ default 2
+ ---help---
+ Align all sections to this Log2 value: 0->1, 1->2, 2->4, etc.
+
+config ELF_CONSTRUCTORS
+ bool "C++ Static Constructor Support"
+ default n
+ depends on HAVE_CXX
+ ---help---
+ Build in support for C++ constructors in ELF modules.
+
+config ELF_SYMBOLS
+ bool "Export symbols from ELF modules"
+ default n
+ ---help---
+ Allow symbols from one ELF module to be used by another. (NOT
+ fully implemented.
+
config ELF_DUMPBUFFER
bool "Dump ELF buffers"
default n
depends on DEBUG && DEBUG_VERBOSE
+ ---help---
+ Dump various ELF buffers for debug purposes
diff --git a/nuttx/binfmt/libelf/libelf_load.c b/nuttx/binfmt/libelf/libelf_load.c
index 41bafe04e..98e9abf38 100644
--- a/nuttx/binfmt/libelf/libelf_load.c
+++ b/nuttx/binfmt/libelf/libelf_load.c
@@ -55,6 +55,11 @@
* Pre-Processor Definitions
****************************************************************************/
+#define ELF_ALIGN_MASK ((1 << CONFIG_ELF_ALIGN_LOG2) - 1)
+#define ELF_ALIGNUP(a) (((unsigned long)(a) + ELF_ALIGN_MASK) & ~ELF_ALIGN_MASK)
+#define ELF_ALIGNDOWN(a) ((unsigned long)(a) & ~ELF_ALIGN_MASK)
+
+
#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
@@ -111,6 +116,69 @@ static inline int elf_filelen(FAR struct elf_loadinfo_s *loadinfo)
}
/****************************************************************************
+ * Name: elf_readfile
+ *
+ * Description:
+ * Allocate memory for the file and read the section data into the
+ * allocated memory.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static int elf_readfile(FAR struct elf_loadinfo_s *loadinfo, FAR void *buffer,
+ off_t offset, size_t nbytes)
+{
+ FAR uint8_t *buffer;
+ ssize_t bytesread;
+ off_t result;
+
+ /* Seek to the start of the section header table */
+
+ result = lseek(loadinfo->filfd, offset, SEEK_SET);
+ if (result == (off_t)-1)
+ {
+ int errval = errno;
+ bdbg("Seel to %ld failed: %d\n", (long)offset, errval);
+ return -errval;
+ }
+
+ /* Now load the file data into memory */
+
+ buffer = (FAR uint8_t *)loadinfo->shdrs;
+ while (shdrsize > 0)
+ {
+ bytesread = read(loadinfo->filfd, buffer, shdrsize);
+ if (bytes < 0)
+ {
+ int errval = errno;
+
+ /* EINTR just means that we received a signal */
+
+ if (errno != EINTR)
+ {
+ bdbg("read() failed: %d\n", errval);
+ return -errval;
+ }
+ }
+ else if (bytes == 0)
+ {
+ bdbg("Unexpected end of file\n");
+ return -ENODATA;
+ }
+ else
+ {
+ buffer += bytesread;
+ shdrsize -= bytesread;
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
* Name: elf_loadshdrs
*
* Description:
@@ -125,9 +193,6 @@ static inline int elf_filelen(FAR struct elf_loadinfo_s *loadinfo)
static inline int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
{
size_t shdrsize;
- ssize_t bytesread;
- uint8_t buffer;
- off_t offset;
int ret;
DEBUGASSERT(loadinfo->shdrs == NULL);
@@ -158,54 +223,136 @@ static inline int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
return -ENOMEM;
}
- /* Seek to the start of the section header table */
+ /* Read the section header table into memory */
- offset = lseek(loadinfo->filfd, loadinfo->e_shoff, SEEK_SET);
- if (offset == (off_t)-1)
+ ret = elf_readfile(loadinfo, loadinfo->shdrs, loadinfo->e_shoff, shdrsize);
+ if (ret < 0)
{
- int errval = errno;
- bdbg("See to %ld failed: %d\n", (long)loadinfo->e_shoff, errval);
- ret = -errval;
+ bdbg("Failed to read section header table: %d\n", ret);
goto errout_with_alloc;
}
- /* Now load the section header table into the allocated memory */
+ return OK;
- buffer = loadinfo->shdrs;
- while (shdrsize > 0)
+errout_with_alloc:
+ kfree(loadinfo->shdrs);
+ loadinfo->shdrs = 0;
+ return ret;
+}
+
+/****************************************************************************
+ * Name: elf_allocsize
+ *
+ * Description:
+ * Calculate total memory allocation for the ELF file.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static void elf_allocsize(struct load_info *loadinfo)
+{
+ size_t allocsize;
+ int i;
+
+ /* Accumulate the size each section into memory that is marked SHF_ALLOC */
+
+ allocsize = 0;
+ for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
- bytesread = read(loadinfo->filfd, buffer, shdrsize);
- if (bytes < 0)
- {
- int errval = errno;
+ FAR Elf32_Shdr *shdr = &loadinfo->shdrs[i];
- /* EINTR just means that we received a signal */
+ /* SHF_ALLOC indicates that the section requires memory during
+ * execution.
+ */
- if (errno != EINTR)
- {
- bdbg("read() failed: %d\n", errval);
- ret = -errval;
- goto errout_with_alloc;
- }
+ if ((shdr->sh_flags & SHF_ALLOC) != 0)
+ {
+ allocsize += ELF_ALIGNUP(shdr->sh_size);
}
- else if (bytes == 0)
+ }
+
+ /* Save the allocation size */
+
+ loadinfo->allocize = allocsize;
+}
+
+/****************************************************************************
+ * Name: elf_loadfile
+ *
+ * Description:
+ * Allocate memory for the file and read the section data into the
+ * allocated memory.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static inline int elf_loadfile(FAR struct load_info *loadinfo)
+{
+ FAR uint8_t *dest;
+ int i;
+
+ /* Allocate (and zero) memory for the ELF file. */
+
+ loadinfo->alloc = kzalloc(loadinfo->allocsize);
+ if (!loadinfo->alloc)
+ {
+ return -ENOMEM;
+ }
+
+ /* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */
+
+ bvdbg("Loaded sections:\n");
+ dest = (FAR uint8_t*)loadinfo->alloc;
+
+ for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
+ {
+ FAR Elf32_Shdr *shdr = &loadinfo->shdrs[i];
+
+ /* SHF_ALLOC indicates that the section requires memory during
+ * execution */
+
+ if ((shdr->sh_flags & SHF_ALLOC) == 0)
{
- bdbg("Unexpectged end of file\n");
- ret = -ENODATA;
- goto errout_with_alloc;
+ continue;
}
- else
+
+ /* SHT_NOBITS indicates that there is no data in the file for the
+ * section.
+ */
+
+ if (shdr->sh_type != SHT_NOBITS)
{
- buffer += bytesread;
- shdrsize -= bytesread;
+ /* Read the section data from sh_offset to dest */
+
+ ret = elf_readfile(loadinfo, dest, shdr->sh_offset, shdr->sh_size);
+ if (ret < 0)
+ {
+ bdbg("Failed to read section %d: %d\n", i, ret);
+ goto errout_with_alloc;
+ }
}
+
+ /* Update sh_addr to point to copy in image. */
+
+ shdr->sh_addr = (uintptr_t)dest;
+ bvdbg("%d. 0x%lx %s\n", (long)shdr->sh_addr, loadinfo->secstrings + shdr->sh_name);
+
+ /* Setup the memory pointer for the next time through the loop */
+
+ dest += ELF_ALIGNUP(shdr->sh_size);
}
return OK;
errout_with_alloc:
- kfree(loadinfo->shdrs);
- loadinfo->shdrs = 0;
+ kfree(loadinfo->alloc);
+ loadinfo->alloc = 0;
return ret;
}