am d978d21d: am 8252b8e4: Merge "Honor p_vaddr if set"

* commit 'd978d21d195976fa3f257b8d17ec2fe18fb436a7':
  Honor p_vaddr if set
This commit is contained in:
Brian Carlstrom 2013-06-10 15:44:13 -07:00 committed by Android Git Automerger
commit b181747aa1
2 changed files with 32 additions and 21 deletions

View File

@ -226,24 +226,32 @@ bool ElfReader::ReadProgramHeader() {
return true;
}
/* Compute the extent of all loadable segments in an ELF program header
* table. This corresponds to the page-aligned size in bytes that needs to be
* reserved in the process' address space
/* Returns the size of the extent of all the possibly non-contiguous
* loadable segments in an ELF program header table. This corresponds
* to the page-aligned size in bytes that needs to be reserved in the
* process' address space. If there are no loadable segments, 0 is
* returned.
*
* This returns 0 if there are no loadable segments.
* If out_min_vaddr or out_max_vaddr are non-NULL, they will be
* set to the minimum and maximum addresses of pages to be reserved,
* or 0 if there is nothing to load.
*/
Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
size_t phdr_count)
size_t phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
size_t phdr_count,
Elf32_Addr* out_min_vaddr,
Elf32_Addr* out_max_vaddr)
{
Elf32_Addr min_vaddr = 0xFFFFFFFFU;
Elf32_Addr max_vaddr = 0x00000000U;
bool found_pt_load = false;
for (size_t i = 0; i < phdr_count; ++i) {
const Elf32_Phdr* phdr = &phdr_table[i];
if (phdr->p_type != PT_LOAD) {
continue;
}
found_pt_load = true;
if (phdr->p_vaddr < min_vaddr) {
min_vaddr = phdr->p_vaddr;
@ -253,14 +261,19 @@ Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
max_vaddr = phdr->p_vaddr + phdr->p_memsz;
}
}
if (min_vaddr > max_vaddr) {
return 0;
if (!found_pt_load) {
min_vaddr = 0x00000000U;
}
min_vaddr = PAGE_START(min_vaddr);
max_vaddr = PAGE_END(max_vaddr);
if (out_min_vaddr != NULL) {
*out_min_vaddr = min_vaddr;
}
if (out_max_vaddr != NULL) {
*out_max_vaddr = max_vaddr;
}
return max_vaddr - min_vaddr;
}
@ -268,29 +281,23 @@ Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
// 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_);
Elf32_Addr min_vaddr;
load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
if (load_size_ == 0) {
DL_ERR("\"%s\" has no loadable segments", name_);
return false;
}
uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
void* start = mmap(NULL, load_size_, PROT_NONE, mmap_flags, -1, 0);
void* start = mmap(addr, 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;
}
}
load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
return true;
}

View File

@ -80,7 +80,11 @@ class ElfReader {
const Elf32_Phdr* loaded_phdr_;
};
Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr, size_t phnum);
size_t
phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
size_t phdr_count,
Elf32_Addr* min_vaddr = NULL,
Elf32_Addr* max_vaddr = NULL);
int
phdr_table_protect_segments(const Elf32_Phdr* phdr_table,