aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitriy Ivanov <dimitry@google.com>2015-06-05 22:16:23 -0700
committerDavid Srbecky <dsrbecky@google.com>2015-06-18 23:58:34 +0100
commit34e8e47d321b129920c5142a81c2db88128c1595 (patch)
tree618970aa7d64ff3f2d24dd0d6f73c265c7786f68
parent848276051a24266e1eacf2e508692c62d5a6176d (diff)
downloadandroid_bionic-34e8e47d321b129920c5142a81c2db88128c1595.tar.gz
android_bionic-34e8e47d321b129920c5142a81c2db88128c1595.tar.bz2
android_bionic-34e8e47d321b129920c5142a81c2db88128c1595.zip
Add flag that makes linker honor min(p_vaddr)
(cherry picked from commit 8a1162835597be38705b381ac34c07da17932568) Bug: 21924613 Bug: http://b/21523078 Change-Id: I3f944a08dd2ed1df4d8a807da4fee423fdd35eb7
-rw-r--r--libc/include/android/dlext.h10
-rw-r--r--linker/linker_phdr.cpp8
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;