Ejemplo n.º 1
0
/* Reserve a virtual address range big enough to hold all loadable
 * segments of a program header table. This is done by creating a
 * private anonymous mmap() with PROT_NONE.
 *
 * Input:
 *   phdr_table    -> program header table
 *   phdr_count    -> number of entries in the tables
 * Output:
 *   load_start    -> first page of reserved address space range
 *   load_size     -> size in bytes of reserved address space range
 *   load_bias     -> load bias, as described in technical note above.
 *
 * Return:
 *   0 on success, -1 otherwise. Error code in errno.
 */
int
phdr_table_reserve_memory(const Elf32_Phdr* phdr_table,
                          size_t phdr_count,
                          void** load_start,
                          Elf32_Addr* load_size,
                          Elf32_Addr* load_bias)
{
    Elf32_Addr size = phdr_table_get_load_size(phdr_table, phdr_count);
    if (size == 0) {
        errno = EINVAL;
        return -1;
    }

    int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
    void* start = mmap(NULL, size, PROT_NONE, mmap_flags, -1, 0);
    if (start == MAP_FAILED) {
        return -1;
    }

    *load_start = start;
    *load_size  = size;
    *load_bias  = 0;

    for (size_t i = 0; i < phdr_count; ++i) {
        const Elf32_Phdr* phdr = &phdr_table[i];
        if (phdr->p_type == PT_LOAD) {
            *load_bias = (Elf32_Addr)start - PAGE_START(phdr->p_vaddr);
            break;
        }
    }
    return 0;
}
Ejemplo n.º 2
0
// Reserve a virtual address range big enough to hold all loadable
// segments of a program header table. This is done by creating a
// private anonymous mmap() with PROT_NONE.
bool ElfReader::ReserveAddressSpace() {
  load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_);
  if (load_size_ == 0) {
    DL_ERR("\"%s\" has no loadable segments", name_);
    return false;
  }

  int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
  void* start = mmap(NULL, load_size_, PROT_NONE, mmap_flags, -1, 0);
  if (start == MAP_FAILED) {
    DL_ERR("couldn't reserve %d bytes of address space for \"%s\"", load_size_, name_);
    return false;
  }

  load_start_ = start;
  load_bias_ = 0;

  for (size_t i = 0; i < phdr_num_; ++i) {
    const Elf32_Phdr* phdr = &phdr_table_[i];
    if (phdr->p_type == PT_LOAD) {
      load_bias_ = reinterpret_cast<Elf32_Addr>(start) - PAGE_START(phdr->p_vaddr);
      break;
    }
  }
  return true;
}
// Reserve a virtual address range big enough to hold all loadable
// segments of a program header table. This is done by creating a
// private anonymous mmap() with PROT_NONE.
//
// This will use the wanted_load_address_ value,
bool ElfLoader::ReserveAddressSpace(Error* error) {
  ELF::Addr min_vaddr;
  load_size_ =
      phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr, NULL);
  if (load_size_ == 0) {
    error->Set("No loadable segments");
    return false;
  }

  uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
  int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;

  // Support loading at a fixed address.
  if (wanted_load_address_) {
    addr = static_cast<uint8_t*>(wanted_load_address_);
    mmap_flags |= MAP_FIXED;
  }

  LOG("%s: address=%p size=%p\n", __FUNCTION__, addr, load_size_);
  void* start = mmap(addr, load_size_, PROT_NONE, mmap_flags, -1, 0);
  if (start == MAP_FAILED) {
    error->Format("Could not reserve %d bytes of address space", load_size_);
    return false;
  }

  load_start_ = start;
  load_bias_ = reinterpret_cast<ELF::Addr>(start) - min_vaddr;
  return true;
}
Ejemplo n.º 4
0
// Reserve a virtual address range big enough to hold all loadable
// segments of a program header table. This is done by creating a
// private anonymous mmap() with PROT_NONE.
bool ElfReader_ReserveAddressSpace(ElfReader* er) {
  Elf32_Addr min_vaddr;
  er->load_size_ = phdr_table_get_load_size(er->phdr_table_, er->phdr_num_, &min_vaddr, NULL);
  if (er->load_size_ == 0) {
    DL_ERR("\"%s\" has no loadable segments", er->name_);
    return false;
  }

  uint8_t* addr = (uint8_t*)(min_vaddr);
  int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
  void* start = mmap(NULL, er->load_size_, PROT_NONE, mmap_flags, -1, 0);
  if (start == MAP_FAILED) {
    DL_ERR("couldn't reserve %d bytes of address space for \"%s\"", er->load_size_, er->name_);
    return false;
  }

  er->load_start_ = start;
  er->load_bias_ = (uint8_t*)(start) - addr;
  return true;
}
Ejemplo n.º 5
0
bool ElfView::InitUnmapped(ELF::Addr load_address,
                           const ELF::Phdr* phdr,
                           size_t phdr_count,
                           Error* error) {
  // Compute load size and bias.
  ELF::Addr min_vaddr = 0;
  load_size_ = phdr_table_get_load_size(phdr, phdr_count, &min_vaddr, NULL);
  if (load_size_ == 0) {
    *error = "Invalid program header table";
    return false;
  }
  load_address_ = (load_address ? load_address : min_vaddr);
  load_bias_ = load_address - min_vaddr;

  // Extract the dynamic table information.
  phdr_table_get_dynamic_section(phdr,
                                 phdr_count,
                                 load_address,
                                 &dynamic_,
                                 &dynamic_count_,
                                 &dynamic_flags_);
  if (!dynamic_) {
    *error = "No PT_DYNAMIC section!";
    return false;
  }

  // Compute the program header table address relative to load_address.
  // This is different from |phdr|..|phdr + phdr_count| which can actually
  // be at a different location.
  const ELF::Phdr* phdr0 = NULL;

  // First, if there is a PT_PHDR, use it directly.
  for (size_t n = 0; n < phdr_count; ++n) {
    const ELF::Phdr* entry = &phdr[n];
    if (entry->p_type == PT_PHDR) {
      phdr0 = entry;
      break;
    }
  }

  // Otherwise, check the first loadable segment. If its file offset
  // is 0, it starts with the ELF header, and we can trivially find the
  // loaded program header from it.
  if (!phdr0) {
    for (size_t n = 0; n < phdr_count; ++n) {
      const ELF::Phdr* entry = &phdr[n];
      if (entry->p_type == PT_LOAD) {
        if (entry->p_offset == 0) {
          ELF::Addr elf_addr = load_bias_ + entry->p_vaddr;
          const ELF::Ehdr* ehdr = reinterpret_cast<const ELF::Ehdr*>(elf_addr);
          ELF::Addr offset = ehdr->e_phoff;
          phdr0 = reinterpret_cast<const ELF::Phdr*>(elf_addr + offset);
        }
        break;
      }
    }
  }

  // Check that the program header table is indeed in a loadable segment,
  // this helps catching malformed ELF binaries.
  if (phdr0) {
    ELF::Addr phdr0_addr = reinterpret_cast<ELF::Addr>(phdr0);
    ELF::Addr phdr0_limit = phdr0_addr + sizeof(ELF::Phdr) * phdr_count;
    bool found = false;
    for (size_t n = 0; n < phdr_count; ++n) {
      size_t seg_start = load_bias_ + phdr[n].p_vaddr;
      size_t seg_end = seg_start + phdr[n].p_filesz;

      if (seg_start <= phdr0_addr && phdr0_limit <= seg_end) {
        found = true;
        break;
      }
    }

    if (!found)
      phdr0 = NULL;
  }

  if (!phdr0) {
    *error = "Malformed ELF binary";
    return false;
  }

  phdr_ = phdr0;
  phdr_count_ = phdr_count;

  LOG("%s: New ELF view [load_address:%p, load_size:%p, load_bias:%p, phdr:%p, "
      "phdr_count:%d, dynamic:%p, dynamic_count:%d, dynamic_flags:%d\n",
      __FUNCTION__,
      load_address_,
      load_size_,
      load_bias_,
      phdr_,
      phdr_count_,
      dynamic_,
      dynamic_count_,
      dynamic_flags_);
  return true;
}