summaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2018-10-17 15:59:38 -0400
committerTorne (Richard Coles) <torne@google.com>2019-02-20 17:29:36 -0500
commitefbe9a5eefce28db6d1dbba18c212eb45915cf78 (patch)
tree0e35795b7b52bc65af89143af0662b5b0f4ce3e1 /linker/linker.cpp
parent73ee7a6320024c8f390d954a01b7a067c919bfc4 (diff)
linker: allow using reserved space for multiple libraries.
Introduce a new flag ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE which instructs the linker to use the reserved address space to load all of the newly-loaded libraries required by a dlopen() call instead of only the main library. They will be loaded consecutively into that region if they fit. The RELRO sections of all the loaded libraries will also be considered for reading/writing shared RELRO data. This will allow the WebView implementation to potentially consist of more than one .so file while still benefiting from the RELRO sharing optimisation, which would otherwise only apply to the "root" .so file. Test: bionic-unit-tests (existing and newly added) Bug: 110790153 Change-Id: I61da775c29fd5017d9a1e2b6b3757c3d20a355b3
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp38
1 files changed, 31 insertions, 7 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 428dd25de..415b36373 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -658,9 +658,9 @@ class LoadTask {
return elf_reader.Read(realpath, fd_, file_offset_, file_size);
}
- bool load() {
+ bool load(address_space_params* address_space) {
ElfReader& elf_reader = get_elf_reader();
- if (!elf_reader.Load(extinfo_)) {
+ if (!elf_reader.Load(address_space)) {
return false;
}
@@ -1651,10 +1651,34 @@ bool find_libraries(android_namespace_t* ns,
load_list.push_back(task);
}
}
- shuffle(&load_list);
+ bool reserved_address_recursive = false;
+ if (extinfo) {
+ reserved_address_recursive = extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE;
+ }
+ if (!reserved_address_recursive) {
+ // Shuffle the load order in the normal case, but not if we are loading all
+ // the libraries to a reserved address range.
+ shuffle(&load_list);
+ }
+
+ // Set up address space parameters.
+ address_space_params extinfo_params, default_params;
+ size_t relro_fd_offset = 0;
+ if (extinfo) {
+ if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
+ extinfo_params.start_addr = extinfo->reserved_addr;
+ extinfo_params.reserved_size = extinfo->reserved_size;
+ extinfo_params.must_use_address = true;
+ } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
+ extinfo_params.start_addr = extinfo->reserved_addr;
+ extinfo_params.reserved_size = extinfo->reserved_size;
+ }
+ }
for (auto&& task : load_list) {
- if (!task->load()) {
+ address_space_params* address_space =
+ (reserved_address_recursive || !task->is_dt_needed()) ? &extinfo_params : &default_params;
+ if (!task->load(address_space)) {
return false;
}
}
@@ -1764,7 +1788,7 @@ bool find_libraries(android_namespace_t* ns,
// we should avoid linking them (because if they are not linked -> they
// are in the local_group_roots and will be linked later).
if (!si->is_linked() && si->get_primary_namespace() == local_group_ns) {
- if (!si->link_image(global_group, local_group, extinfo) ||
+ if (!si->link_image(global_group, local_group, extinfo, &relro_fd_offset) ||
!get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
return false;
}
@@ -3712,7 +3736,7 @@ bool soinfo::prelink_image() {
}
bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
- const android_dlextinfo* extinfo) {
+ const android_dlextinfo* extinfo, size_t* relro_fd_offset) {
if (is_image_linked()) {
// already linked.
return true;
@@ -3859,7 +3883,7 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
}
} else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {
if (phdr_table_map_gnu_relro(phdr, phnum, load_bias,
- extinfo->relro_fd) < 0) {
+ extinfo->relro_fd, relro_fd_offset) < 0) {
DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",
get_realpath(), strerror(errno));
return false;