Пример #1
0
int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
{
  FAR Elf32_Shdr *shdr;
  size_t ctorsize;
  int ctoridx;
  int ret;
  int i;

  DEBUGASSERT(loadinfo->ctors == NULL);

  /* Allocate an I/O buffer if necessary.  This buffer is used by
   * elf_sectname() to accumulate the variable length symbol name.
   */

  ret = elf_allocbuffer(loadinfo);
  if (ret < 0)
    {
      bdbg("elf_allocbuffer failed: %d\n", ret);
      return -ENOMEM;
    }

  /* Find the index to the section named ".ctors."  NOTE:  On old ABI system,
   * .ctors is the name of the section containing the list of constructors;
   * On newer systems, the similar section is called .init_array.  It is 
   * expected that the linker script will force the section name to be ".ctors"
   * in either case.
   */

  ctoridx = elf_findsection(loadinfo, ".ctors");
  if (ctoridx < 0)
    {
      /* This may not be a failure.  -ENOENT indicates that the file has no
       * static constructor section.
       */

      bvdbg("elf_findsection .ctors section failed: %d\n", ctoridx);
      return ret == -ENOENT ? OK : ret;
    }

  /* Now we can get a pointer to the .ctor section in the section header
   * table.
   */

  shdr = &loadinfo->shdr[ctoridx];

  /* Get the size of the .ctor section and the number of constructors that
   * will need to be called.
   */

  ctorsize         = shdr->sh_size;
  loadinfo->nctors = ctorsize / sizeof(binfmt_ctor_t);

  bvdbg("ctoridx=%d ctorsize=%d sizeof(binfmt_ctor_t)=%d nctors=%d\n",
        ctoridx, ctorsize,  sizeof(binfmt_ctor_t), loadinfo->nctors);

  /* Check if there are any constructors.  It is not an error if there
   * are none.
   */

  if (loadinfo->nctors > 0)
    {
      /* Check an assumption that we made above */

      DEBUGASSERT(shdr->sh_size == loadinfo->nctors * sizeof(binfmt_ctor_t));

      /* In the old ABI, the .ctors section is not allocated.  In that case,
       * we need to allocate memory to hold the .ctors and then copy the
       * from the file into the allocated memory.
       *
       * SHF_ALLOC indicates that the section requires memory during
       * execution.
       */

      if ((shdr->sh_flags & SHF_ALLOC) == 0)
        {
          /* Allocate memory to hold a copy of the .ctor section */

          loadinfo->ctoralloc = (binfmt_ctor_t*)kmalloc(ctorsize);
          if (!loadinfo->ctoralloc)
            {
              bdbg("Failed to allocate memory for .ctors\n");
              return -ENOMEM;
            }

          loadinfo->ctors = (binfmt_ctor_t *)loadinfo->ctoralloc;

          /* Read the section header table into memory */

          ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->ctors, ctorsize,
                         shdr->sh_offset);
          if (ret < 0)
            {
              bdbg("Failed to allocate .ctors: %d\n", ret);
              return ret;
            }

          /* Fix up all of the .ctor addresses.  Since the addresses
           * do not lie in allocated memory, there will be no relocation
           * section for them.
           */

          for (i = 0; i < loadinfo->nctors; i++)
            {
              FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]);

              bvdbg("ctor %d: %08lx + %08lx = %08lx\n",
                    i, *ptr, loadinfo->elfalloc, *ptr + loadinfo->elfalloc);

              *ptr += loadinfo->elfalloc;
            }
        }
      else
        {

          /* Save the address of the .ctors (actually, .init_array) where it was
           * loaded into memory.  Since the .ctors lie in allocated memory, they
           * will be relocated via the normal mechanism.
           */
 
          loadinfo->ctors = (binfmt_ctor_t*)shdr->sh_addr;
        }
    }

  return OK;
}
Пример #2
0
int elf_load(FAR struct elf_loadinfo_s *loadinfo)
{
  size_t heapsize;
#ifdef CONFIG_UCLIBCXX_EXCEPTION
  int exidx;
#endif
  int ret;

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

  /* Load section headers into memory */

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

  /* Determine total size to allocate */

  elf_elfsize(loadinfo);

  /* Determine the heapsize to allocate.  heapsize is ignored if there is
   * no address environment because the heap is a shared resource in that
   * case.  If there is no dynamic stack then heapsize must at least as big
   * as the fixed stack size since the stack will be allocated from the heap
   * in that case.
   */

#if !defined(CONFIG_ARCH_ADDRENV)
  heapsize = 0;
#elif defined(CONFIG_ARCH_STACK_DYNAMIC)
  heapsize = ARCH_HEAP_SIZE;
#else
  heapsize = MIN(ARCH_HEAP_SIZE, CONFIG_ELF_STACKSIZE);
#endif

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

  ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize, heapsize);
  if (ret < 0)
    {
      berr("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)
    {
      berr("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)
    {
      berr("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)
    {
      berr("ERROR: elf_loadctors failed: %d\n", ret);
      goto errout_with_addrenv;
    }

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

#ifdef CONFIG_UCLIBCXX_EXCEPTION
  exidx = elf_findsection(loadinfo, CONFIG_ELF_EXIDX_SECTNAME);
  if (exidx < 0)
    {
      binfo("elf_findsection: Exception Index section not found: %d\n", exidx);
    }
  else
    {
      up_init_exidx(loadinfo->shdr[exidx].sh_addr, loadinfo->shdr[exidx].sh_size);
    }
#endif

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

  ret = elf_addrenv_restore(loadinfo);
  if (ret < 0)
    {
      berr("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;
}