Beispiel #1
0
static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
{
  FAR uint8_t *dest;
  int ret;
  int i;

  /* Allocate (and zero) memory for the ELF file. */
  
  loadinfo->elfalloc = (uintptr_t)kzalloc(loadinfo->elfsize);
  if (!loadinfo->elfalloc)
    {
      return -ENOMEM;
    }

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

  bvdbg("Loaded sections:\n");
  dest = (FAR uint8_t*)loadinfo->elfalloc;

  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;
        }

      /* 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 dest */

          ret = elf_read(loadinfo, dest, shdr->sh_size, shdr->sh_offset);
          if (ret < 0)
            {
              bdbg("Failed to read section %d: %d\n", i, ret);
              return ret;
            }
        }

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

      bvdbg("%d. %08x->%08x\n", i, (long)shdr->sh_addr, (long)dest);
      shdr->sh_addr = (uintptr_t)dest;

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

      dest += ELF_ALIGNUP(shdr->sh_size);
    }

  return OK;
}
int unload_module(FAR struct binary_s *binp)
{
  int ret;
  int i;

  if (binp)
    {
      /* Perform any format-specific unload operations */

      if (binp->unload)
        {
          ret = binp->unload(binp);
          if (ret < 0)
            {
              bdbg("binp->unload() failed: %d\n", ret);
              set_errno(-ret);
              return ERROR;
            }
        }

#ifdef CONFIG_BINFMT_CONSTRUCTORS
      /* Execute C++ destructors */

      ret = exec_dtors(binp);
      if (ret < 0)
        {
          bdbg("exec_ctors() failed: %d\n", ret);
          set_errno(-ret);
          return ERROR;
        }
#endif

      /* Unmap mapped address spaces */

      if (binp->mapped)
        {
          bvdbg("Unmapping address space: %p\n", binp->mapped);

          munmap(binp->mapped, binp->mapsize);
        }

      /* Free allocated address spaces */

      for (i = 0; i < BINFMT_NALLOC; i++)
        {
          if (binp->alloc[i])
            {
              bvdbg("Freeing alloc[%d]: %p\n", i, binp->alloc[i]);
              kumm_free((FAR void *)binp->alloc[i]);
            }
        }

      /* Notice that the address environment is not destroyed.  This should
       * happen automatically when the task exits.
       */
    }

  return OK;
}
int up_addrenv_destroy(FAR group_addrenv_t *addrenv)
{
  bvdbg("addrenv=%p\n", addrenv);
  DEBUGASSERT(addrenv);

  /* Destroy the .text region */

  arm_addrenv_destroy_region(addrenv->text, ARCH_TEXT_NSECTS,
                             CONFIG_ARCH_TEXT_VBASE);

  /* Destroy the .bss/.data region */

  arm_addrenv_destroy_region(addrenv->data, ARCH_DATA_NSECTS,
                             CONFIG_ARCH_DATA_VBASE);

#ifdef CONFIG_BUILD_KERNEL
  /* Destroy the heap region */

  arm_addrenv_destroy_region(addrenv->heap, ARCH_HEAP_NSECTS,
                             CONFIG_ARCH_HEAP_VBASE);
#endif

  memset(addrenv, 0, sizeof(group_addrenv_t));
  return OK;
}
int up_addrenv_ustackalloc(FAR struct tcb_s *tcb, size_t stacksize)
{
  int ret;

  bvdbg("tcb=%p stacksize=%lu\n", tcb, (unsigned long)stacksize);

  DEBUGASSERT(tcb);

  /* Initialize the address environment list to all zeroes */

  memset(tcb->xcp.ustack, 0, ARCH_STACK_NSECTS * sizeof(uintptr_t *));

  /* Back the allocation up with physical pages and set up the level 2 mapping
   * (which of course does nothing until the L2 page table is hooked into
   * the L1 page table).
   */

  /* Allocate .text space pages */

  ret = arm_addrenv_create_region(tcb->xcp.ustack, ARCH_STACK_NSECTS,
                                  CONFIG_ARCH_STACK_VBASE, stacksize,
                                  MMU_L2_UDATAFLAGS);
  if (ret < 0)
    {
      bdbg("ERROR: Failed to create stack region: %d\n", ret);
      up_addrenv_ustackfree(tcb);
      return ret;
    }

  return OK;
}
int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb)
{
  bvdbg("group=%p tcb=%p\n", group, tcb);

  /* Nothing needs to be done in this implementation */

  return OK;
}
Beispiel #6
0
int nxflat_read(struct nxflat_loadinfo_s *loadinfo, char *buffer, int readsize, int offset)
{
  ssize_t nbytes;      /* Number of bytes read */
  off_t   rpos;        /* Position returned by lseek */
  char   *bufptr;      /* Next buffer location to read into */
  int     bytesleft;   /* Number of bytes of .data left to read */
  int     bytesread;   /* Total number of bytes read */

  bvdbg("Read %d bytes from offset %d\n", readsize, offset);

  /* Seek to the position in the object file where the initialized
   * data is saved.
   */

  bytesread = 0;
  bufptr    = buffer;
  bytesleft = readsize;
  do
    {
      rpos = lseek(loadinfo->filfd, offset, SEEK_SET);
      if (rpos != offset)
        {
          int errval = errno;
          bdbg("Failed to seek to position %d: %d\n", offset, errval);
          return -errval;
        }

      /* Read the file data at offset into the user buffer */

       nbytes = read(loadinfo->filfd, bufptr, bytesleft);
       if (nbytes < 0)
         {
           int errval = errno;
           if (errval != EINTR)
             {
               bdbg("Read from offset %d failed: %d\n", offset, errval);
               return -errval;
             }
         }
       else if (nbytes == 0)
         {
           bdbg("Unexpected end of file\n");
           return -ENODATA;
         }
       else
         {
           bytesread += nbytes;
           bytesleft -= nbytes;
           bufptr    += nbytes;
           offset    += nbytes;
         }
    }
  while (bytesread < readsize);

  nxflat_dumpreaddata(buffer, readsize);
  return OK;
}
Beispiel #7
0
static int nxflat_loadbinary(struct binary_s *binp)
{
  struct nxflat_loadinfo_s loadinfo;  /* Contains globals for libnxflat */
  int                      ret;

  bvdbg("Loading file: %s\n", binp->filename);

  /* Initialize the xflat library to load the program binary. */

  ret = nxflat_init(binp->filename, &loadinfo);
  nxflat_dumploadinfo(&loadinfo);
  if (ret != 0)
    {
      bdbg("Failed to initialize for load of NXFLT program: %d\n", ret);
      goto errout;
    }

  /* Load the program binary */

  ret = nxflat_load(&loadinfo);
  nxflat_dumploadinfo(&loadinfo);
  if (ret != 0)
    {
      bdbg("Failed to load NXFLT program binary: %d\n", ret);
      goto errout_with_init;
    }

  /* Bind the program to the exported symbol table */

  ret = nxflat_bind(&loadinfo, binp->exports, binp->nexports);
  if (ret != 0)
    {
      bdbg("Failed to bind symbols program binary: %d\n", ret);
      goto errout_with_load;
    }

  /* Return the load information */

  binp->entrypt   = (main_t)(loadinfo.ispace + loadinfo.entryoffs);
  binp->ispace    = (void*)loadinfo.ispace;
  binp->dspace    = (void*)loadinfo.dspace;
  binp->isize     = loadinfo.isize;
  binp->stacksize = loadinfo.stacksize;

  nxflat_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt,
                    MIN(binp->isize - loadinfo.entryoffs,512));

  nxflat_uninit(&loadinfo);
  return OK;

errout_with_load:
  nxflat_unload(&loadinfo);
errout_with_init:
  nxflat_uninit(&loadinfo);
errout:
  return ret;
}
int prun(FAR char *exepath, size_t varsize, size_t strsize)
{
  FAR struct pexec_s *st;
  int errcode;
  int ret = OK;

  /* Load the POFF file into memory */

  st = pload(exepath, varsize, varsize);
  if (!st)
    {
      bdbg("ERROR: Could not load %s\n", exepath);
      return -ENOEXEC;
    }

  bvdbg("Loaded %s\n", exepath);

  /* Execute the P-Code program until a stopping condition occurs */

  for (;;)
    {
      /* Execute the instruction; Check for exceptional conditions */

      errcode = pexec(st);
      if (errcode != eNOERROR)
        {
          break;
        }
    }

  if (errcode != eEXIT)
    {
      /* REVISIT: Select a more appropriated return errocode */

      bdbg("ERROR: Runtime error 0x%02x -- Execution Stopped\n", errcode);
      ret = -ENOEXEC;
    }

  /* Clean up resources used by the interpreter */

  bvdbg("Execution terminated\n");
  pexec_release(st);
  return ret;
}
int up_addrenv_vustack(FAR const struct tcb_s *tcb, FAR void **vstack)
{
  bvdbg("Return=%p\n", (FAR void *)CONFIG_ARCH_STACK_VBASE);

  /* Not much to do in this case */

  DEBUGASSERT(tcb);
  *vstack = (FAR void *)CONFIG_ARCH_STACK_VBASE;
  return OK;
}
int up_addrenv_vtext(FAR group_addrenv_t *addrenv, FAR void **vtext)
{
  bvdbg("return=%p\n", (FAR void *)CONFIG_ARCH_TEXT_VBASE);

  /* Not much to do in this case */

  DEBUGASSERT(addrenv && vtext);
  *vtext = (FAR void *)CONFIG_ARCH_TEXT_VBASE;
  return OK;
}
static int builtin_loadbinary(struct binary_s *binp)
{
  FAR const char *filename;
  FAR const struct builtin_s *b;
  int fd;
  int index;
  int ret;

  bvdbg("Loading file: %s\n", binp->filename);

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

  fd = open(binp->filename, O_RDONLY);
  if (fd < 0)
    {
      int errval = get_errno();
      bdbg("ERROR: Failed to open binary %s: %d\n", binp->filename, errval);
      return -errval;
    }

  /* If this file is a BINFS file system, then we can recover the name of
   * the file using the FIOC_FILENAME ioctl() call.
   */

  ret = ioctl(fd, FIOC_FILENAME, (unsigned long)((uintptr_t)&filename));
  if (ret < 0)
    {
      int errval = get_errno();
      bdbg("ERROR: FIOC_FILENAME ioctl failed: %d\n", errval);
      return -errval;
    }

  /* Other file systems may also support FIOC_FILENAME, so the real proof
   * is that we can look up the index to this name in g_builtins[].
   */

  index = builtin_isavail(filename);
  if (index < 0)
    {
      int errval = get_errno();
      bdbg("ERROR: %s is not a builtin application\n", filename);
      return -errval;

    }

  /* Return the load information.  NOTE: that there is no way to configure
   * the priority.  That is a bug and needs to be fixed.
   */

  b = builtin_for_index(index);
  binp->entrypt   = b->main;
  binp->stacksize = b->stacksize;
  binp->priority  = b->priority;
  return OK;
}
Beispiel #12
0
int elf_load(FAR struct elf_loadinfo_s *loadinfo)
{
  int ret;

  bvdbg("loadinfo: %p\n", loadinfo);
  DEBUGASSERT(loadinfo && loadinfo->filfd >= 0);

  /* Load section headers into memory */

  ret = elf_loadshdrs(loadinfo);
  if (ret < 0)
    {
      bdbg("elf_loadshdrs failed: %d\n", ret);
      goto errout_with_buffers;
    }

  /* Determine total size to allocate */

  elf_elfsize(loadinfo);

  /* Allocate memory and load sections into memory */

  ret = elf_loadfile(loadinfo);
  if (ret < 0)
    {
      bdbg("elf_loadfile failed: %d\n", ret);
      goto errout_with_buffers;
    }

  /* Load static constructors and destructors. */

#ifdef CONFIG_BINFMT_CONSTRUCTORS
  ret = elf_loadctors(loadinfo);
  if (ret < 0)
    {
      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;

  /* Error exits */

errout_with_buffers:
  elf_unload(loadinfo);
  return ret;
}
int up_addrenv_clone(FAR const group_addrenv_t *src,
                     FAR group_addrenv_t *dest)
{
  bvdbg("src=%p dest=%p\n", src, dest);
  DEBUGASSERT(src && dest);

  /* Just copy the address environment from the source to the destination */

  memcpy(dest, src, sizeof(group_addrenv_t));
  return OK;
}
Beispiel #14
0
int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer,
             size_t readsize, off_t offset)
{
  ssize_t nbytes;      /* Number of bytes read */
  off_t   rpos;        /* Position returned by lseek */

  bvdbg("Read %ld bytes from offset %ld\n", (long)readsize, (long)offset);

  /* Loop until all of the requested data has been read. */

  while (readsize > 0)
    {
      /* Seek to the next read position */

      rpos = lseek(loadinfo->filfd, offset, SEEK_SET);
      if (rpos != offset)
        {
          int errval = errno;
          bdbg("Failed to seek to position %ld: %d\n", (long)offset, errval);
          return -errval;
        }

      /* Read the file data at offset into the user buffer */

       nbytes = read(loadinfo->filfd, buffer, readsize);
       if (nbytes < 0)
         {
           int errval = errno;

           /* EINTR just means that we received a signal */

           if (errval != EINTR)
             {
               bdbg("Read of .data failed: %d\n", errval);
               return -errval;
             }
         }
       else if (nbytes == 0)
         {
           bdbg("Unexpected end of file\n");
           return -ENODATA;
         }
       else
         {
           readsize -= nbytes;
           buffer   += nbytes;
           offset   += nbytes;
         }
    }

  elf_dumpreaddata(buffer, readsize);
  return OK;
}
int up_addrenv_vdata(FAR group_addrenv_t *addrenv, uintptr_t textsize,
                     FAR void **vdata)
{
  bvdbg("return=%p\n",
        (FAR void *)(CONFIG_ARCH_DATA_VBASE + ARCH_DATA_RESERVE_SIZE));

  /* Not much to do in this case */

  DEBUGASSERT(addrenv && vdata);
  *vdata = (FAR void *)(CONFIG_ARCH_DATA_VBASE + ARCH_DATA_RESERVE_SIZE);
  return OK;
}
int up_addrenv_ustackfree(FAR struct tcb_s *tcb)
{
  bvdbg("tcb=%p\n", tcb);
  DEBUGASSERT(tcb);

  /* Destroy the stack region */

  arm_addrenv_destroy_region(tcb->xcp.ustack, ARCH_STACK_NSECTS,
                             CONFIG_ARCH_STACK_VBASE);

  memset(tcb->xcp.ustack, 0, ARCH_STACK_NSECTS * sizeof(uintptr_t *));
  return OK;
}
Beispiel #17
0
int nxflat_initialize(void)
{
  int ret;

  /* Register ourselves as a binfmt loader */

  bvdbg("Registering NXFLAT\n");
  ret = register_binfmt(&g_nxflatbinfmt);
  if (ret != 0)
    {
      bdbg("Failed to register binfmt: %d\n", ret);
    }
  return ret;
}
int load_module(FAR struct binary_s *bin)
{
  FAR struct binfmt_s *binfmt;
  int ret = -ENOENT;

#ifdef CONFIG_DEBUG
  if (bin && bin->filename)
#endif
    {
      bdbg("Loading %s\n", bin->filename);

      /* Disabling pre-emption should be sufficient protection while
       * accessing the list of registered binary format handlers.
       */

      sched_lock();

      /* Traverse the list of registered binary format handlers.  Stop
       * when either (1) a handler recognized and loads the format, or
       * (2) no handler recognizes the format.
       */

      for (binfmt = g_binfmts; binfmt; binfmt = binfmt->next)
        {
          /* Use this handler to try to load the format */

          ret = binfmt->load(bin);
          if (ret == OK)
            {
              /* Successfully loaded -- break out with ret == 0 */

              bvdbg("Successfully loaded module %s\n", bin->filename);
              dump_module(bin);
              break;
            }
        }

      sched_unlock();
    }

  /* This is an end-user function.  Return failures via errno */

  if (ret < 0)
    {
      bdbg("Returning errno %d\n", -ret);
      errno = -ret;
      return ERROR;
    }
  return OK;
}
Beispiel #19
0
static inline void exec_ctors(FAR const struct binary_s *binp)
{
  binfmt_ctor_t *ctor = binp->ctors;
  int i;

  /* Execute each constructor */

  for (i = 0; i < binp->nctors; i++)
    {
      bvdbg("Calling ctor %d at %p\n", i, (FAR void *)ctor);

      (*ctor)();
      ctor++;
    }
}
Beispiel #20
0
int elf_initialize(void)
{
  int ret;

  /* Register ourselves as a binfmt loader */

  bvdbg("Registering ELF\n");

  ret = register_binfmt(&g_elfbinfmt);
  if (ret != 0)
    {
      bdbg("Failed to register binfmt: %d\n", ret);
    }

  return ret;
}
int builtin_initialize(void)
{
  int ret;

  /* Register ourselves as a binfmt loader */

  bvdbg("Registering Builtin Loader\n");

  ret = register_binfmt(&g_builtin_binfmt);
  if (ret != 0)
    {
      bdbg("Failed to register binfmt: %d\n", ret);
    }

  return ret;
}
int up_addrenv_restore(FAR const save_addrenv_t *oldenv)
{
  uintptr_t vaddr;
  int i;

  bvdbg("oldenv=%p\n", oldenv);
  DEBUGASSERT(oldenv);

  for (vaddr = CONFIG_ARCH_TEXT_VBASE, i = 0;
       i < ARCH_TEXT_NSECTS;
       vaddr += SECTION_SIZE, i++)
    {
      /* Restore the L1 page table entry */

      mmu_l1_restore(vaddr, oldenv->text[i]);
    }

  for (vaddr = CONFIG_ARCH_DATA_VBASE, i = 0;
       i < ARCH_DATA_NSECTS;
       vaddr += SECTION_SIZE, i++)
    {
      /* Restore the L1 page table entry */

      mmu_l1_restore(vaddr, oldenv->data[i]);
    }

#ifdef CONFIG_BUILD_KERNEL
  for (vaddr = CONFIG_ARCH_HEAP_VBASE, i = 0;
       i < ARCH_HEAP_NSECTS;
       vaddr += SECTION_SIZE, i++)
    {
      /* Restore the L1 page table entry */

      mmu_l1_restore(vaddr, oldenv->heap[i]);
    }
#endif

  return OK;
}
Beispiel #23
0
static inline int exec_ctors(FAR const struct binary_s *binp)
{
  binfmt_ctor_t *ctor = binp->ctors;
#ifdef CONFIG_ADDRENV
  hw_addrenv_t oldenv;
  int ret;
#endif
  int i;

  /* Instantiate the address enviroment containing the constructors */

#ifdef CONFIG_ADDRENV
  ret = up_addrenv_select(binp->addrenv, &oldenv);
  if (ret < 0)
    {
      bdbg("up_addrenv_select() failed: %d\n", ret);
      return ret;
    }
#endif

  /* Execute each constructor */

  for (i = 0; i < binp->nctors; i++)
    {
      bvdbg("Calling ctor %d at %p\n", i, (FAR void *)ctor);

      (*ctor)();
      ctor++;
    }

  /* Restore the address enviroment */

#ifdef CONFIG_ADDRENV
  return up_addrenv_restore(oldenv);
#else
  return OK;
#endif
}
static inline int exec_dtors(FAR struct binary_s *binp)
{
  binfmt_dtor_t *dtor = binp->dtors;
#ifdef CONFIG_ARCH_ADDRENV
  save_addrenv_t oldenv;
  int ret;
#endif
  int i;

  /* Instantiate the address environment containing the destructors */

#ifdef CONFIG_ARCH_ADDRENV
  ret = up_addrenv_select(&binp->addrenv, &oldenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_select() failed: %d\n", ret);
      return ret;
    }
#endif

  /* Execute each destructor */

  for (i = 0; i < binp->ndtors; i++)
    {
      bvdbg("Calling dtor %d at %p\n", i, (FAR void *)dtor);

      (*dtor)();
      dtor++;
    }

  /* Restore the address environment */

#ifdef CONFIG_ARCH_ADDRENV
  return up_addrenv_restore(&oldenv);
#else
  return OK;
#endif
}
Beispiel #25
0
static int load_absmodule(FAR struct binary_s *bin)
{
  FAR struct binfmt_s *binfmt;
  int ret = -ENOENT;

  bdbg("Loading %s\n", bin->filename);

  /* Disabling pre-emption should be sufficient protection while accessing
   * the list of registered binary format handlers.
   */

  sched_lock();

  /* Traverse the list of registered binary format handlers.  Stop
   * when either (1) a handler recognized and loads the format, or
   * (2) no handler recognizes the format.
   */

  for (binfmt = g_binfmts; binfmt; binfmt = binfmt->next)
    {
      /* Use this handler to try to load the format */

      ret = binfmt->load(bin);
      if (ret == OK)
        {
          /* Successfully loaded -- break out with ret == 0 */

          bvdbg("Successfully loaded module %s\n", bin->filename);
          dump_module(bin);
          break;
        }
    }

  sched_unlock();
  return ret;
}
Beispiel #26
0
static int elf_loadbinary(struct binary_s *binp)
{
  struct elf_loadinfo_s loadinfo;  /* Contains globals for libelf */
  int                   ret;

  bvdbg("Loading file: %s\n", binp->filename);

  /* Initialize the xflat library to load the program binary. */

  ret = elf_init(binp->filename, &loadinfo);
  elf_dumploadinfo(&loadinfo);
  if (ret != 0)
    {
      bdbg("Failed to initialize for load of ELF program: %d\n", ret);
      goto errout;
    }

  /* Load the program binary */

  ret = elf_load(&loadinfo);
  elf_dumploadinfo(&loadinfo);
  if (ret != 0)
    {
      bdbg("Failed to load ELF program binary: %d\n", ret);
      goto errout_with_init;
    }

  /* Bind the program to the exported symbol table */

  ret = elf_bind(&loadinfo, binp->exports, binp->nexports);
  if (ret != 0)
    {
      bdbg("Failed to bind symbols program binary: %d\n", ret);
      goto errout_with_load;
    }

  /* Return the load information */

  binp->entrypt   = (main_t)(loadinfo.elfalloc + loadinfo.ehdr.e_entry);
  binp->alloc[0]  = (FAR void *)loadinfo.elfalloc;
  binp->stacksize = CONFIG_ELF_STACKSIZE;

#ifdef CONFIG_BINFMT_CONSTRUCTORS
  /* Save information about constructors.  NOTE:  desctructors are not
   * yet supported.
   */

  binp->alloc[1]  = loadinfo.ctoralloc;
  binp->ctors     = loadinfo.ctors;
  binp->nctors    = loadinfo.nctors;

  binp->alloc[2]  = loadinfo.dtoralloc;
  binp->dtors     = loadinfo.dtors;
  binp->ndtors    = loadinfo.ndtors;
#endif

  elf_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt,
                 MIN(loadinfo.allocsize - loadinfo.ehdr.e_entry, 512));

  elf_uninit(&loadinfo);
  return OK;

errout_with_load:
  elf_unload(&loadinfo);
errout_with_init:
  elf_uninit(&loadinfo);
errout:
  return ret;
}
Beispiel #27
0
int nxflat_init(const char *filename, struct nxflat_loadinfo_s *loadinfo)
{
  uint32_t datastart;
  uint32_t dataend;
  uint32_t bssstart;
  uint32_t bssend;
  int      ret;

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

  /* Clear the load info structure */

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

  /* Open the binary file */

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

  /* Read the NXFLAT header from offset 0 */

  ret = nxflat_read(loadinfo, (char*)&loadinfo->header,
                    sizeof(struct nxflat_hdr_s), 0);
  if (ret < 0)
    {
      bdbg("Failed to read NXFLAT header: %d\n", ret);
      return ret;
    }
  nxflat_dumpbuffer("NXFLAT header", (FAR const uint8_t*)&loadinfo->header,
                    sizeof(struct nxflat_hdr_s));

  /* Verify the NXFLAT header */

  if (nxflat_verifyheader(&loadinfo->header) != 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 NXFLAT file.  Besides, if there is something worth
       * complaining about, nnxflat_verifyheader() has already
       * done so.
       */

      bdbg("Bad NXFLAT header\n");
      return -ENOEXEC;
    }

  /* 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;
}
int elf_load(FAR struct elf_loadinfo_s *loadinfo)
{
  int ret;

  bvdbg("loadinfo: %p\n", loadinfo);
  DEBUGASSERT(loadinfo && loadinfo->filfd >= 0);

  /* Load section headers into memory */

  ret = elf_loadshdrs(loadinfo);
  if (ret < 0)
    {
      bdbg("ERROR: elf_loadshdrs failed: %d\n", ret);
      goto errout_with_buffers;
    }

  /* Determine total size to allocate */

  elf_elfsize(loadinfo);

  /* Allocate (and zero) memory for the ELF file. */

  ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize);
  if (ret < 0)
    {
      bdbg("ERROR: elf_addrenv_alloc() failed: %d\n", ret);
      goto errout_with_buffers;
    }

#ifdef CONFIG_ARCH_ADDRENV
  /* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address
   * space that may not be in place now.  elf_addrenv_select() will
   * temporarily instantiate that address space.
   */

  ret = elf_addrenv_select(loadinfo);
  if (ret < 0)
    {
      bdbg("ERROR: elf_addrenv_select() failed: %d\n", ret);
      goto errout_with_buffers;
    }
#endif

  /* Load ELF section data into memory */

  ret = elf_loadfile(loadinfo);
  if (ret < 0)
    {
      bdbg("ERROR: elf_loadfile failed: %d\n", ret);
      goto errout_with_addrenv;
    }

  /* Load static constructors and destructors. */

#ifdef CONFIG_BINFMT_CONSTRUCTORS
  ret = elf_loadctors(loadinfo);
  if (ret < 0)
    {
      bdbg("ERROR: elf_loadctors failed: %d\n", ret);
      goto errout_with_addrenv;
    }

  ret = elf_loaddtors(loadinfo);
  if (ret < 0)
    {
      bdbg("ERROR: elf_loaddtors failed: %d\n", ret);
      goto errout_with_addrenv;
    }
#endif

#ifdef CONFIG_ARCH_ADDRENV
  /* Restore the original address environment */

  ret = elf_addrenv_restore(loadinfo);
  if (ret < 0)
    {
      bdbg("ERROR: elf_addrenv_restore() failed: %d\n", ret);
      goto errout_with_buffers;
    }
#endif

  return OK;

  /* Error exits */

errout_with_addrenv:
#ifdef CONFIG_ARCH_ADDRENV
  (void)elf_addrenv_restore(loadinfo);
#endif

errout_with_buffers:
  elf_unload(loadinfo);
  return ret;
}
int up_addrenv_create(size_t textsize, size_t datasize, size_t heapsize,
                      FAR group_addrenv_t *addrenv)
{
  int ret;

  bvdbg("addrenv=%p textsize=%lu datasize=%lu\n",
        addrenv, (unsigned long)textsize, (unsigned long)datasize);

  DEBUGASSERT(addrenv);

  /* Initialize the address environment structure to all zeroes */

  memset(addrenv, 0, sizeof(group_addrenv_t));

  /* Back the allocation up with physical pages and set up the level 2 mapping
   * (which of course does nothing until the L2 page table is hooked into
   * the L1 page table).
   */

  /* Allocate .text space pages */

  ret = arm_addrenv_create_region(addrenv->text, ARCH_TEXT_NSECTS,
                                  CONFIG_ARCH_TEXT_VBASE, textsize,
                                  MMU_L2_UTEXTFLAGS);
  if (ret < 0)
    {
      bdbg("ERROR: Failed to create .text region: %d\n", ret);
      goto errout;
    }

  /* Allocate .bss/.data space pages.  NOTE that a configurable offset is
   * added to the allocted size.  This is matched by the offset that is
   * used when reporting the virtual data address in up_addrenv_vdata().
   */

  ret = arm_addrenv_create_region(addrenv->data, ARCH_DATA_NSECTS,
                                  CONFIG_ARCH_DATA_VBASE,
                                  datasize + ARCH_DATA_RESERVE_SIZE,
                                  MMU_L2_UDATAFLAGS);
  if (ret < 0)
    {
      bdbg("ERROR: Failed to create .bss/.data region: %d\n", ret);
      goto errout;
    }

#ifdef CONFIG_BUILD_KERNEL
  /* Initialize the shared data are at the beginning of the .bss/.data
   * region.
   */

  ret = up_addrenv_initdata((uintptr_t)addrenv->data[0] & PMD_PTE_PADDR_MASK);
  if (ret < 0)
    {
      bdbg("ERROR: Failed to initialize .bss/.data region: %d\n", ret);
      goto errout;
    }
#endif

#ifdef CONFIG_BUILD_KERNEL
  /* Allocate heap space pages */

  ret = arm_addrenv_create_region(addrenv->heap, ARCH_HEAP_NSECTS,
                                  CONFIG_ARCH_HEAP_VBASE, heapsize,
                                  MMU_L2_UDATAFLAGS);
  if (ret < 0)
    {
      bdbg("ERROR: Failed to create heap region: %d\n", ret);
      goto errout;
    }

  /* Save the initial heap size allocated.  This will be needed when
   * the heap data structures are initialized.
   */

  addrenv->heapsize = (size_t)ret << MM_PGSHIFT;
#endif
  return OK;

errout:
  up_addrenv_destroy(addrenv);
  return ret;
}
Beispiel #30
0
static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
{
  FAR uint8_t *dest;
  int ret;
  int i;

  /* Allocate (and zero) memory for the ELF file. */

  ret = elf_addrenv_alloc(loadinfo, loadinfo->elfsize);
  if (ret < 0)
    {
      bdbg("ERROR: elf_addrenv_alloc() failed: %d\n", ret);
      return ret;
    }

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

  bvdbg("Loaded sections:\n");
  dest = (FAR uint8_t*)loadinfo->elfalloc;

  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;
        }

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

      if (shdr->sh_type != SHT_NOBITS)
        {
          /* If CONFIG_ADDRENV=y, then 'dest' lies in a virtual address space
           * that may not be in place now.  elf_addrenv_select() will
           * temporarily instantiate that address space.
           */

#ifdef CONFIG_ADDRENV
          ret = elf_addrenv_select(loadinfo);
          if (ret < 0)
            {
              bdbg("ERROR: elf_addrenv_select() failed: %d\n", ret);
              return ret;
            }
#endif

          /* Read the section data from sh_offset to dest */

          ret = elf_read(loadinfo, dest, shdr->sh_size, shdr->sh_offset);
          if (ret < 0)
            {
              bdbg("Failed to read section %d: %d\n", i, ret);
              return ret;
            }

          /* Restore the original address environment */

#ifdef CONFIG_ADDRENV
          ret = elf_addrenv_restore(loadinfo);
          if (ret < 0)
            {
              bdbg("ERROR: elf_addrenv_restore() failed: %d\n", ret);
             return ret;
            }
#endif
        }

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

      bvdbg("%d. %08x->%08x\n", i, (long)shdr->sh_addr, (long)dest);
      shdr->sh_addr = (uintptr_t)dest;

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

      dest += ELF_ALIGNUP(shdr->sh_size);
    }

  return OK;
}