Example #1
0
int mod_loadshdrs(FAR struct mod_loadinfo_s *loadinfo)
{
  size_t shdrsize;
  int ret;

  DEBUGASSERT(loadinfo->shdr == NULL);

  /* Verify that there are sections */

  if (loadinfo->ehdr.e_shnum < 1)
    {
      serr("ERROR: No sections(?)\n");
      return -EINVAL;
    }

  /* Get the total size of the section header table */

  shdrsize = (size_t)loadinfo->ehdr.e_shentsize * (size_t)loadinfo->ehdr.e_shnum;
  if (loadinfo->ehdr.e_shoff + shdrsize > loadinfo->filelen)
    {
      serr("ERROR: Insufficent space in file for section header table\n");
      return -ESPIPE;
    }

  /* Allocate memory to hold a working copy of the sector header table */

  loadinfo->shdr = (FAR FAR Elf32_Shdr *)kmm_malloc(shdrsize);
  if (!loadinfo->shdr)
    {
      serr("ERROR: Failed to allocate the section header table. Size: %ld\n",
           (long)shdrsize);
      return -ENOMEM;
    }

  /* Read the section header table into memory */

  ret = mod_read(loadinfo, (FAR uint8_t *)loadinfo->shdr, shdrsize,
                    loadinfo->ehdr.e_shoff);
  if (ret < 0)
    {
      serr("ERROR: Failed to read section header table: %d\n", ret);
    }

  return ret;
}
Example #2
0
static inline int mod_loadfile(FAR struct mod_loadinfo_s *loadinfo)
{
  FAR uint8_t *text;
  FAR uint8_t *data;
  FAR uint8_t **pptr;
  int ret;
  int i;

  /* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */

  svdbg("Loaded sections:\n");
  text = (FAR uint8_t *)loadinfo->textalloc;
  data = (FAR uint8_t *)loadinfo->datastart;

  for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
    {
      FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];

      /* SHF_ALLOC indicates that the section requires memory during
       * execution */

      if ((shdr->sh_flags & SHF_ALLOC) == 0)
        {
          continue;
        }

      /* SHF_WRITE indicates that the section address space is write-
       * able
       */

      if ((shdr->sh_flags & SHF_WRITE) != 0)
        {
          pptr = &data;
        }
      else
        {
          pptr = &text;
        }

      /* SHT_NOBITS indicates that there is no data in the file for the
       * section.
       */

      if (shdr->sh_type != SHT_NOBITS)
        {
          /* Read the section data from sh_offset to the memory region */

          ret = mod_read(loadinfo, *pptr, shdr->sh_size, shdr->sh_offset);
          if (ret < 0)
            {
              sdbg("ERROR: Failed to read section %d: %d\n", i, ret);
              return ret;
            }
        }

      /* If there is no data in an allocated section, then the allocated
       * section must be cleared.
       */

      else
        {
          memset(*pptr, 0, shdr->sh_size);
        }

      /* Update sh_addr to point to copy in memory */

      svdbg("%d. %08lx->%08lx\n", i,
            (unsigned long)shdr->sh_addr, (unsigned long)*pptr);

      shdr->sh_addr = (uintptr_t)*pptr;

      /* Setup the memory pointer for the next time through the loop */

      *pptr += ELF_ALIGNUP(shdr->sh_size);
    }

  return OK;
}
Example #3
0
static inline int mod_sectname(FAR struct mod_loadinfo_s *loadinfo,
                               FAR const Elf32_Shdr *shdr)
{
  FAR Elf32_Shdr *shstr;
  FAR uint8_t *buffer;
  off_t  offset;
  size_t readlen;
  size_t bytesread;
  int shstrndx;
  int ret;

  /* Get the section header table index of the entry associated with the
   * section name string table. If the file has no section name string table,
   * this member holds the value SH_UNDEF.
   */

  shstrndx = loadinfo->ehdr.e_shstrndx;
  if (shstrndx == SHN_UNDEF)
    {
      serr("ERROR: No section header string table\n");
      return -EINVAL;
    }

  /* Get the section name string table section header */

  shstr = &loadinfo->shdr[shstrndx];

  /* Get the file offset to the string that is the name of the section. This
   * is the sum of:
   *
   *   shstr->sh_offset: The file offset to the first byte of the section
   *     header string table data.
   *   shdr->sh_name: The offset to the name of the section in the section
   *     name table
   */

  offset = shstr->sh_offset + shdr->sh_name;

  /* Loop until we get the entire section name into memory */

  buffer    = loadinfo->iobuffer;
  bytesread = 0;

  for (; ; )
    {
      /* Get the number of bytes to read */

      readlen = loadinfo->buflen - bytesread;
      if (offset + readlen > loadinfo->filelen)
        {
          if (loadinfo->filelen <= offset)
            {
              serr("ERROR: At end of file\n");
              return -EINVAL;
            }

          readlen = loadinfo->filelen - offset;
        }

      /* Read that number of bytes into the array */

      buffer = &loadinfo->iobuffer[bytesread];
      ret = mod_read(loadinfo, buffer, readlen, offset);
      if (ret < 0)
        {
          serr("ERROR: Failed to read section name: %d\n", ret);
          return ret;
        }

      bytesread += readlen;

      /* Did we read the NUL terminator? */

      if (memchr(buffer, '\0', readlen) != NULL)
        {
          /* Yes, the buffer contains a NUL terminator. */

          return OK;
        }

      /* No.. then we have to read more */

      ret = mod_reallocbuffer(loadinfo, CONFIG_MODULE_BUFFERINCR);
      if (ret < 0)
        {
          serr("ERROR: mod_reallocbuffer failed: %d\n", ret);
          return ret;
        }
    }

  /* We will not get here */

  return OK;
}
Example #4
0
int mod_initialize(FAR const char *filename,
                   FAR struct mod_loadinfo_s *loadinfo)
{
  int ret;

  svdbg("filename: %s loadinfo: %p\n", filename, loadinfo);

  /* Clear the load info structure */

  memset(loadinfo, 0, sizeof(struct mod_loadinfo_s));

  /* Get the length of the file. */

  ret = mod_filelen(loadinfo, filename);
  if (ret < 0)
    {
      sdbg("mod_filelen failed: %d\n", ret);
      return ret;
    }

  /* Open the binary file for reading (only) */

  loadinfo->filfd = open(filename, O_RDONLY);
  if (loadinfo->filfd < 0)
    {
      int errval = errno;
      sdbg("Failed to open ELF binary %s: %d\n", filename, errval);
      return -errval;
    }

  /* Read the ELF ehdr from offset 0 */

  ret = mod_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr,
                    sizeof(Elf32_Ehdr), 0);
  if (ret < 0)
    {
      sdbg("Failed to read ELF header: %d\n", ret);
      return ret;
    }

  mod_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr,
                    sizeof(Elf32_Ehdr));

  /* Verify the ELF header */

  ret = mod_verifyheader(&loadinfo->ehdr);
  if (ret < 0)
    {
      /* This may not be an error because we will be called to attempt loading
       * EVERY binary.  If mod_verifyheader() does not recognize the ELF header,
       * it will -ENOEXEC whcih simply informs the system that the file is not an
       * ELF file.  mod_verifyheader() will return other errors if the ELF header
       * is not correctly formed.
       */

      sdbg("Bad ELF header: %d\n", ret);
      return ret;
    }

  return OK;
}