diff options
author | Brian Carlstrom <bdc@google.com> | 2013-06-10 15:41:19 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2013-06-10 15:41:19 -0700 |
commit | d978d21d195976fa3f257b8d17ec2fe18fb436a7 (patch) | |
tree | b44d2c943473f96b5cf53cee791560ff67d35d12 /linker | |
parent | 6bcf71c9ac8395038ca243160d4367759be8dd80 (diff) | |
parent | 8252b8e4b730b13623f31dc66396e000586d1c58 (diff) | |
download | bionic-d978d21d195976fa3f257b8d17ec2fe18fb436a7.zip bionic-d978d21d195976fa3f257b8d17ec2fe18fb436a7.tar.gz bionic-d978d21d195976fa3f257b8d17ec2fe18fb436a7.tar.bz2 |
am 8252b8e4: Merge "Honor p_vaddr if set"
* commit '8252b8e4b730b13623f31dc66396e000586d1c58':
Honor p_vaddr if set
Diffstat (limited to 'linker')
-rw-r--r-- | linker/linker_phdr.cpp | 47 | ||||
-rw-r--r-- | linker/linker_phdr.h | 6 |
2 files changed, 32 insertions, 21 deletions
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index d1387f6..83f163c 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -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; } diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h index a31d1d9..992d95e 100644 --- a/linker/linker_phdr.h +++ b/linker/linker_phdr.h @@ -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, |