summaryrefslogtreecommitdiffstats
path: root/linker
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2013-06-10 15:41:19 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2013-06-10 15:41:19 -0700
commitd978d21d195976fa3f257b8d17ec2fe18fb436a7 (patch)
treeb44d2c943473f96b5cf53cee791560ff67d35d12 /linker
parent6bcf71c9ac8395038ca243160d4367759be8dd80 (diff)
parent8252b8e4b730b13623f31dc66396e000586d1c58 (diff)
downloadbionic-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.cpp47
-rw-r--r--linker/linker_phdr.h6
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,