summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-10-24 23:40:31 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-10-24 23:40:31 +0000
commit571f43ec01f49a9630b10c4c3c8a224f0aeb01ee (patch)
tree714baa74493bc9615430f984d8caab4a5646dc76
parentded016c6fbd656792ca99872cc717df581fe7910 (diff)
downloadpx4-nuttx-571f43ec01f49a9630b10c4c3c8a224f0aeb01ee.tar.gz
px4-nuttx-571f43ec01f49a9630b10c4c3c8a224f0aeb01ee.tar.bz2
px4-nuttx-571f43ec01f49a9630b10c4c3c8a224f0aeb01ee.zip
A little more ELF loader logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5253 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/binfmt/libelf/libelf.h13
-rw-r--r--nuttx/binfmt/libelf/libelf_bind.c1
-rw-r--r--nuttx/binfmt/libelf/libelf_init.c72
-rw-r--r--nuttx/binfmt/libelf/libelf_load.c147
-rw-r--r--nuttx/binfmt/libelf/libelf_read.c1
-rw-r--r--nuttx/binfmt/libelf/libelf_unload.c17
-rw-r--r--nuttx/binfmt/libelf/libelf_verify.c42
-rw-r--r--nuttx/include/elf.h9
-rw-r--r--nuttx/include/nuttx/binfmt/elf.h38
9 files changed, 228 insertions, 112 deletions
diff --git a/nuttx/binfmt/libelf/libelf.h b/nuttx/binfmt/libelf/libelf.h
index 80d971bca..ed352865c 100644
--- a/nuttx/binfmt/libelf/libelf.h
+++ b/nuttx/binfmt/libelf/libelf.h
@@ -42,6 +42,8 @@
#include <nuttx/config.h>
+#include <elf.h>
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -50,4 +52,15 @@
* Public Types
****************************************************************************/
+/****************************************************************************
+ * Name: arch_checkarch
+ *
+ * Description:
+ * Given the ELF header in hdr, verify that the ELF file is appropriate
+ * for the current, configured architecture.
+ *
+ ****************************************************************************/
+
+bool arch_checkarch(const struct Elf32_Ehdr *hdr);
+
#endif /* __BINFMT_LIBELF_LIBELF_H */
diff --git a/nuttx/binfmt/libelf/libelf_bind.c b/nuttx/binfmt/libelf/libelf_bind.c
index 87afe79c9..74b713b9e 100644
--- a/nuttx/binfmt/libelf/libelf_bind.c
+++ b/nuttx/binfmt/libelf/libelf_bind.c
@@ -46,7 +46,6 @@
#include <assert.h>
#include <debug.h>
-#include <arpa/inet.h>
#include <nuttx/binfmt/elf.h>
#include <nuttx/binfmt/symtab.h>
diff --git a/nuttx/binfmt/libelf/libelf_init.c b/nuttx/binfmt/libelf/libelf_init.c
index 71b6b9227..b024f2d19 100644
--- a/nuttx/binfmt/libelf/libelf_init.c
+++ b/nuttx/binfmt/libelf/libelf_init.c
@@ -47,7 +47,6 @@
#include <debug.h>
#include <errno.h>
-#include <arpa/inet.h>
#include <nuttx/binfmt/elf.h>
/****************************************************************************
@@ -95,11 +94,7 @@
int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo)
{
- uint32_t datastart;
- uint32_t dataend;
- uint32_t bssstart;
- uint32_t bssend;
- int ret;
+ int ret;
bvdbg("filename: %s loadinfo: %p\n", filename, loadinfo);
@@ -116,72 +111,33 @@ int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo)
return -errno;
}
- /* Read the ELF header from offset 0 */
+ /* Read the ELF ehdr from offset 0 */
- ret = elf_read(loadinfo, (char*)&loadinfo->header, sizeof(Elf32_Ehdr), 0);
+ ret = elf_read(loadinfo, (char*)&loadinfo->ehdr, sizeof(Elf32_Ehdr), 0);
if (ret < 0)
{
bdbg("Failed to read ELF header: %d\n", ret);
return ret;
}
- elf_dumpbuffer("ELF header", (FAR const uint8_t*)&loadinfo->header, sizeof(Elf32_Ehdr));
+ elf_dumpbuffer("ELF header", (FAR const uint8_t*)&loadinfo->ehdr, sizeof(Elf32_Ehdr));
/* Verify the ELF header */
- if (elf_verifyheader(&loadinfo->header) != 0)
+ ret = elf_verifyheader(&loadinfo->ehdr);
+ if (ret <0)
{
- /* This is not an error because we will be called to attempt loading
- * EVERY binary. Returning -ENOEXEC simply informs the system that
- * the file is not an ELF file. Besides, if there is something worth
- * complaining about, nelf_verifyheader() has already
- * done so.
+ /* This may not be an error because we will be called to attempt loading
+ * EVERY binary. If elf_verifyheader() does not recognize the ELF header,
+ * it will -ENOEXEC whcih simply informs the system that the file is not an
+ * ELF file. elf_verifyheader() will return other errors if the ELF header
+ * is not correctly formed.
*/
- bdbg("Bad ELF header\n");
- return -ENOEXEC;
+ bdbg("Bad ELF header: %d\n", ret);
+ return ret;
}
- /* Save all of the input values in the loadinfo structure
- * and extract some additional information from the xflat
- * header. Note that the information in the xflat header is in
- * network order.
- */
-
- datastart = ntohl(loadinfo->header.h_datastart);
- dataend = ntohl(loadinfo->header.h_dataend);
- bssstart = dataend;
- bssend = ntohl(loadinfo->header.h_bssend);
-
- /* And put this information into the loadinfo structure as well.
- *
- * Note that:
- *
- * isize = the address range from 0 up to datastart.
- * datasize = the address range from datastart up to dataend
- * bsssize = the address range from dataend up to bssend.
- */
-
- loadinfo->entryoffs = ntohl(loadinfo->header.h_entry);
- loadinfo->isize = datastart;
-
- loadinfo->datasize = dataend - datastart;
- loadinfo->bsssize = bssend - dataend;
- loadinfo->stacksize = ntohl(loadinfo->header.h_stacksize);
-
- /* This is the initial dspace size. We'll re-calculate this later
- * after the memory has been allocated.
- */
-
- loadinfo->dsize = bssend - datastart;
-
- /* Get the offset to the start of the relocations (we'll relocate
- * this later).
- */
-
- loadinfo->relocstart = ntohl(loadinfo->header.h_relocstart);
- loadinfo->reloccount = ntohs(loadinfo->header.h_reloccount);
-
- return 0;
+ return OK;
}
diff --git a/nuttx/binfmt/libelf/libelf_load.c b/nuttx/binfmt/libelf/libelf_load.c
index 26785f6b1..41bafe04e 100644
--- a/nuttx/binfmt/libelf/libelf_load.c
+++ b/nuttx/binfmt/libelf/libelf_load.c
@@ -40,14 +40,15 @@
#include <nuttx/config.h>
#include <sys/types.h>
-#include <sys/mman.h>
+#include <sys/stat.h>
+
#include <stdint.h>
#include <stdlib.h>
+#include <unistd.h>
#include <elf.h>
#include <debug.h>
#include <errno.h>
-#include <arpa/inet.h>
#include <nuttx/binfmt/elf.h>
/****************************************************************************
@@ -67,6 +68,148 @@
****************************************************************************/
/****************************************************************************
+ * Name: elf_filelen
+ *
+ * Description:
+ * Get the size of the ELF file
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static inline int elf_filelen(FAR struct elf_loadinfo_s *loadinfo)
+{
+ struct stat buf;
+ int ret;
+
+ /* Get the file stats */
+
+ ret = fstat(loadinfo->filfd, &buf);
+ if (ret < 0)
+ {
+ int errval = errno;
+ bdbg("Failed to fstat file: %d\n", errval);
+ return -errval;
+ }
+
+ /* Verify that it is a regular file */
+
+ if (!S_ISREG(buf.st_mode))
+ {
+ bdbg("Not a regular file. mode: %d\n", buf.st_mode);
+ return -errval;
+ }
+
+ /* TODO: Verify that the file is readable */
+
+ /* Return the size of the file in the loadinfo structure */
+
+ loadinfo->filelen = buf.st_size;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: elf_loadshdrs
+ *
+ * Description:
+ * Loads section headers into memory.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+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);
+
+ /* Verify that there are sections */
+
+ if (loadinfo->e_shum < 1)
+ {
+ bdbg("No section(?)\n");
+ return -EINVAL;
+ }
+
+ /* Get the total size of the section header table */
+
+ shdrsize = (size_t)loadinfo->ehdr.e_shentsize * (size_t)loadinfo->e_shum;
+ if(loadinfo->e_shoff + shdrsize > loadinfo->filelen)
+ {
+ bdbg("Insufficent space in file for section header table\n");
+ return -ESPIPE;
+ }
+
+ /* Allocate memory to hold a working copy of the sector header table */
+
+ loadinfo->shdrs = (FAR Elf32_Shdr*)kmalloc(shdrsize);
+ if (!loadinfo->shdrs)
+ {
+ bdbg("Failed to allocate the section header table. Size: %ld\n", (long)shdrsize);
+ return -ENOMEM;
+ }
+
+ /* Seek to the start of the section header table */
+
+ offset = lseek(loadinfo->filfd, loadinfo->e_shoff, SEEK_SET);
+ if (offset == (off_t)-1)
+ {
+ int errval = errno;
+ bdbg("See to %ld failed: %d\n", (long)loadinfo->e_shoff, errval);
+ ret = -errval;
+ goto errout_with_alloc;
+ }
+
+ /* Now load the section header table into the allocated memory */
+
+ buffer = 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);
+ ret = -errval;
+ goto errout_with_alloc;
+ }
+ }
+ else if (bytes == 0)
+ {
+ bdbg("Unexpectged end of file\n");
+ ret = -ENODATA;
+ goto errout_with_alloc;
+ }
+ else
+ {
+ buffer += bytesread;
+ shdrsize -= bytesread;
+ }
+ }
+
+ return OK;
+
+errout_with_alloc:
+ kfree(loadinfo->shdrs);
+ loadinfo->shdrs = 0;
+ return ret;
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
diff --git a/nuttx/binfmt/libelf/libelf_read.c b/nuttx/binfmt/libelf/libelf_read.c
index 377030174..35b9090f9 100644
--- a/nuttx/binfmt/libelf/libelf_read.c
+++ b/nuttx/binfmt/libelf/libelf_read.c
@@ -47,7 +47,6 @@
#include <debug.h>
#include <errno.h>
-#include <arpa/inet.h>
#include <nuttx/binfmt/elf.h>
/****************************************************************************
diff --git a/nuttx/binfmt/libelf/libelf_unload.c b/nuttx/binfmt/libelf/libelf_unload.c
index 9a198fc78..217a1981e 100644
--- a/nuttx/binfmt/libelf/libelf_unload.c
+++ b/nuttx/binfmt/libelf/libelf_unload.c
@@ -76,20 +76,19 @@
int elf_unload(struct elf_loadinfo_s *loadinfo)
{
- /* Reset the contents of the info structure. */
+ /* Release the all allocated memory */
- /* Release the memory segments */
-
- if (loadinfo->ispace)
+ if (loadinfo->alloc)
{
- kfree((void*)loadinfo->ispace, loadinfo->isize);
- loadinfo->ispace = 0;
+ kfree((void*)loadinfo->alloc);
+ loadinfo->alloc = NULL;
+ loadinfo->allocsize = 0;
}
- if (loadinfo->dspace)
+ if (loadinfo->shdrs)
{
- kfree((void*)loadinfo->dspace);
- loadinfo->dspace = 0;
+ kfree((void*)loadinfo->shdrs);
+ loadinfo->shdrs = 0;
}
return OK;
diff --git a/nuttx/binfmt/libelf/libelf_verify.c b/nuttx/binfmt/libelf/libelf_verify.c
index 9139700b3..0e0dd8e1a 100644
--- a/nuttx/binfmt/libelf/libelf_verify.c
+++ b/nuttx/binfmt/libelf/libelf_verify.c
@@ -42,7 +42,7 @@
#include <string.h>
#include <debug.h>
#include <errno.h>
-#include <arpa/inet.h>
+
#include <nuttx/binfmt/elf.h>
/****************************************************************************
@@ -53,6 +53,8 @@
* Private Constant Data
****************************************************************************/
+static const char g_elfmagic[EI_MAGIC_SIZE] = { 0x7f, 'E', 'L', 'F' }
+
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -72,17 +74,47 @@
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
+ * -ENOEXEC : Not an ELF file
+ * -EINVALID : Not a relocatable ELF file or not supported by the current,
+ * configured architecture.
+ *
****************************************************************************/
-int elf_verifyheader(const Elf32_Ehdr *header)
+int elf_verifyheader(const Elf32_Ehdr *ehdr)
{
- if (!header)
+ if (!ehdr)
{
bdbg("NULL ELF header!");
return -ENOEXEC;
}
-#warning "Missing Logic"
- return -ENOSYS;
+ /* Verify that the magic number indicates an ELF file */
+
+ if (memcmp(ehdr->e_ident, g_elfmagic, EI_MAGIC_SIZE) != 0)
+ {
+ bvdbg("Not ELF magic {%02x, %02x, %02x, %02x}\n",
+ ehdr->e_ident[0], ehdr->e_ident[1], ehdr->e_ident[2], ehdr->e_ident[3]);
+ return -ENOEXEC;
+ }
+
+ /* Verify that this is a relocatable file */
+
+ if (ehdr->e_type != ET_REL)
+ {
+ bdbg("Not a relocatable file: e_type=%d\n", ehdr->e_type);
+ return -EINVALID;
+ }
+
+ /* Verify that this file works with the currently configured architecture */
+
+ if (arch_checkarch(ehdr))
+ {
+ bdbg("Not a supported architecture\n");
+ return -ENOEXEC;
+ }
+
+ /* Looks good so far... we still might find some problems later. */
+
+ return OK;
}
diff --git a/nuttx/include/elf.h b/nuttx/include/elf.h
index 31818249f..dbc615dcd 100644
--- a/nuttx/include/elf.h
+++ b/nuttx/include/elf.h
@@ -86,16 +86,17 @@
/* Ehe ELF identifier */
#define EI_MAG0 0 /* File identification */
-#define EI_MAG1 1 /* File identification */
-#define EI_MAG2 2 /* File identification */
-#define EI_MAG3 3 /* File identification */
+#define EI_MAG1 1 /* " " " " */
+#define EI_MAG2 2 /* " " " " */
+#define EI_MAG3 3 /* " " " " */
#define EI_CLASS 4 /* File class */
#define EI_DATA 5 /* Data encoding */
#define EI_VERSION 6 /* File version */
#define EI_PAD 7 /* Start of padding bytes */
#define EI_NIDENT 16 /* Size of eident[] */
-#define EI_MAGIC { 0x7f, 'E', 'L', 'F' }
+#define EI_MAGIC_SIZE 4
+#define EI_MAGIC {0x7f, 'E', 'L', 'F'}
/* Values for EI_CLASS */
diff --git a/nuttx/include/nuttx/binfmt/elf.h b/nuttx/include/nuttx/binfmt/elf.h
index 8937790b1..95db7d16f 100644
--- a/nuttx/include/nuttx/binfmt/elf.h
+++ b/nuttx/include/nuttx/binfmt/elf.h
@@ -60,38 +60,12 @@
struct elf_loadinfo_s
{
- /* Instruction Space (ISpace): This region contains the ELF file header
- * plus everything from the text section. Ideally, will have only one mmap'ed
- * text section instance in the system for each module.
- */
-
- uint32_t ispace; /* Address where hdr/text is loaded */
- uint32_t entryoffs; /* Offset from ispace to entry point */
- uint32_t isize; /* Size of ispace. */
-
- /* Data Space (DSpace): This region contains all information that in referenced
- * as data (other than the stack which is separately allocated). There will be
- * a unique instance of DSpace (and stack) for each instance of a process.
- */
-
- FAR struct dspace_s *dspace; /* Allocated D-Space (data/bss/etc) */
- uint32_t datasize; /* Size of data segment in dspace */
- uint32_t bsssize; /* Size of bss segment in dspace */
- uint32_t stacksize; /* Size of stack (not allocated) */
- uint32_t dsize; /* Size of dspace (may be large than parts) */
-
- /* This is temporary memory where relocation records will be loaded. */
-
- uint32_t relocstart; /* Start of array of struct flat_reloc */
- uint16_t reloccount; /* Number of elements in reloc array */
-
- /* File descriptors */
-
- int filfd; /* Descriptor for the file being loaded */
-
- /* This is a copy of the ELF header */
-
- Elf32_Ehdr header;
+ uintptr_t alloc; /* Allocated memory with the ELF file is loaded */
+ size_t allocsize; /* Size of the memory allocation */
+ off_t filelen; /* Length of the entire ELF file */
+ int filfd; /* Descriptor for the file being loaded */
+ Elf32_Ehdr ehdr; /* Buffered ELF file header */
+ FAR Elf32_Shdr *shdr; /* Buffered ELF section headers */
};
/****************************************************************************