diff options
Diffstat (limited to 'nuttx/binfmt/libelf/libelf_load.c')
-rw-r--r-- | nuttx/binfmt/libelf/libelf_load.c | 147 |
1 files changed, 145 insertions, 2 deletions
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 ****************************************************************************/ |