From 8a1162835597be38705b381ac34c07da17932568 Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Fri, 5 Jun 2015 22:16:23 -0700 Subject: [PATCH] Add flag that makes linker honor min(p_vaddr) Bug: http://b/21523078 Change-Id: Ice72766fb6ad3bd333c32b496e7870121e17a763 --- libc/include/android/dlext.h | 10 +++++++++- linker/linker_phdr.cpp | 8 +++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h index f10a8a2a8..40f610f29 100644 --- a/libc/include/android/dlext.h +++ b/libc/include/android/dlext.h @@ -73,6 +73,13 @@ enum { */ ANDROID_DLEXT_FORCE_LOAD = 0x40, + /* When set, if the minimum p_vaddr of the ELF file's PT_LOAD segments is non-zero, + * the dynamic linker will load it at that address. + * + * This flag is for ART internal use only. + */ + ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80, + /* Mask of valid bits */ ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_HINT | @@ -80,7 +87,8 @@ enum { ANDROID_DLEXT_USE_RELRO | ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET | - ANDROID_DLEXT_FORCE_LOAD, + ANDROID_DLEXT_FORCE_LOAD | + ANDROID_DLEXT_FORCE_FIXED_VADDR, }; typedef struct { diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index 638c9d6ba..f586b08b5 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -316,6 +316,8 @@ bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) { void* start; size_t reserved_size = 0; bool reserved_hint = true; + // Assume position independent executable by default. + uint8_t* mmap_hint = nullptr; if (extinfo != nullptr) { if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) { @@ -324,6 +326,10 @@ bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) { } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) { reserved_size = extinfo->reserved_size; } + + if ((extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) { + mmap_hint = addr; + } } if (load_size_ > reserved_size) { @@ -333,7 +339,7 @@ bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) { return false; } int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS; - start = mmap(nullptr, load_size_, PROT_NONE, mmap_flags, -1, 0); + start = mmap(mmap_hint, load_size_, PROT_NONE, mmap_flags, -1, 0); if (start == MAP_FAILED) { DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_); return false;