aboutsummaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp363
1 files changed, 186 insertions, 177 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f24167722..3488f5cc7 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -186,10 +186,10 @@ static bool maybe_accessible_via_namespace_links(android_namespace_t* ns, const
return false;
}
-// TODO(dimitry): The grey-list is a workaround for http://b/26394120 ---
+// TODO(dimitry): The exempt-list is a workaround for http://b/26394120 ---
// gradually remove libraries from this list until it is gone.
-static bool is_greylisted(android_namespace_t* ns, const char* name, const soinfo* needed_by) {
- static const char* const kLibraryGreyList[] = {
+static bool is_exempt_lib(android_namespace_t* ns, const char* name, const soinfo* needed_by) {
+ static const char* const kLibraryExemptList[] = {
"libandroid_runtime.so",
"libbinder.so",
"libcrypto.so",
@@ -206,13 +206,13 @@ static bool is_greylisted(android_namespace_t* ns, const char* name, const soinf
nullptr
};
- // If you're targeting N, you don't get the greylist.
- if (g_greylist_disabled || get_application_target_sdk_version() >= 24) {
+ // If you're targeting N, you don't get the exempt-list.
+ if (get_application_target_sdk_version() >= 24) {
return false;
}
// if the library needed by a system library - implicitly assume it
- // is greylisted unless it is in the list of shared libraries for one or
+ // is exempt unless it is in the list of shared libraries for one or
// more linked namespaces
if (needed_by != nullptr && is_system_library(needed_by->get_realpath())) {
return !maybe_accessible_via_namespace_links(ns, name);
@@ -224,8 +224,8 @@ static bool is_greylisted(android_namespace_t* ns, const char* name, const soinf
name = basename(name);
}
- for (size_t i = 0; kLibraryGreyList[i] != nullptr; ++i) {
- if (strcmp(name, kLibraryGreyList[i]) == 0) {
+ for (size_t i = 0; kLibraryExemptList[i] != nullptr; ++i) {
+ if (strcmp(name, kLibraryExemptList[i]) == 0) {
return true;
}
}
@@ -311,6 +311,10 @@ static void soinfo_free(soinfo* si) {
}
}
+ if (si->has_min_version(6) && si->get_gap_size()) {
+ munmap(reinterpret_cast<void*>(si->get_gap_start()), si->get_gap_size());
+ }
+
TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
if (!solist_remove_soinfo(si)) {
@@ -498,10 +502,10 @@ class LoadTask {
static deleter_t deleter;
- static LoadTask* create(const char* name,
- soinfo* needed_by,
- android_namespace_t* start_from,
- std::unordered_map<const soinfo*, ElfReader>* readers_map) {
+ // needed_by is NULL iff dlopen is called from memory that isn't part of any known soinfo.
+ static LoadTask* create(const char* _Nonnull name, soinfo* _Nullable needed_by,
+ android_namespace_t* _Nonnull start_from,
+ std::unordered_map<const soinfo*, ElfReader>* _Nonnull readers_map) {
LoadTask* ptr = TypeBasedAllocator<LoadTask>::alloc();
return new (ptr) LoadTask(name, needed_by, start_from, readers_map);
}
@@ -563,6 +567,11 @@ class LoadTask {
return start_from_;
}
+ void remove_cached_elf_reader() {
+ CHECK(si_ != nullptr);
+ (*elf_readers_map_).erase(si_);
+ }
+
const ElfReader& get_elf_reader() const {
CHECK(si_ != nullptr);
return (*elf_readers_map_)[si_];
@@ -594,6 +603,8 @@ class LoadTask {
si_->load_bias = elf_reader.load_bias();
si_->phnum = elf_reader.phdr_count();
si_->phdr = elf_reader.loaded_phdr();
+ si_->set_gap_start(elf_reader.gap_start());
+ si_->set_gap_size(elf_reader.gap_size());
return true;
}
@@ -621,7 +632,7 @@ class LoadTask {
bool close_fd_;
off64_t file_offset_;
std::unordered_map<const soinfo*, ElfReader>* elf_readers_map_;
- // TODO(dimitry): needed by workaround for http://b/26394120 (the grey-list)
+ // TODO(dimitry): needed by workaround for http://b/26394120 (the exempt-list)
bool is_dt_needed_;
// END OF WORKAROUND
const android_namespace_t* const start_from_;
@@ -1001,47 +1012,24 @@ static int open_library(android_namespace_t* ns,
// If the name contains a slash, we should attempt to open it directly and not search the paths.
if (strchr(name, '/') != nullptr) {
- int fd = -1;
-
- if (strstr(name, kZipFileSeparator) != nullptr) {
- fd = open_library_in_zipfile(zip_archive_cache, name, file_offset, realpath);
- }
-
- if (fd == -1) {
- fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CLOEXEC));
- if (fd != -1) {
- *file_offset = 0;
- if (!realpath_fd(fd, realpath)) {
- if (!is_first_stage_init()) {
- PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
- name);
- }
- *realpath = name;
- }
- }
- }
-
- return fd;
+ return open_library_at_path(zip_archive_cache, name, file_offset, realpath);
}
- // Otherwise we try LD_LIBRARY_PATH first, and fall back to the default library path
+ // LD_LIBRARY_PATH has the highest priority. We don't have to check accessibility when searching
+ // the namespace's path lists, because anything found on a namespace path list should always be
+ // accessible.
int fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_ld_library_paths(), realpath);
+
+ // Try the DT_RUNPATH, and verify that the library is accessible.
if (fd == -1 && needed_by != nullptr) {
fd = open_library_on_paths(zip_archive_cache, name, file_offset, needed_by->get_dt_runpath(), realpath);
- // Check if the library is accessible
if (fd != -1 && !ns->is_accessible(*realpath)) {
close(fd);
fd = -1;
}
}
-#if !defined(__ANDROID_APEX__)
- if (fd == -1) {
- std::vector<std::string> bootstrap_paths = { std::string(kSystemLibDir) + "/bootstrap" };
- fd = open_library_on_paths(zip_archive_cache, name, file_offset, bootstrap_paths, realpath);
- }
-#endif
-
+ // Finally search the namespace's main search path list.
if (fd == -1) {
fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_default_library_paths(), realpath);
}
@@ -1199,12 +1187,12 @@ static bool load_library(android_namespace_t* ns,
// do not check accessibility using realpath if fd is located on tmpfs
// this enables use of memfd_create() for apps
if ((fs_stat.f_type != TMPFS_MAGIC) && (!ns->is_accessible(realpath))) {
- // TODO(dimitry): workaround for http://b/26394120 - the grey-list
+ // TODO(dimitry): workaround for http://b/26394120 - the exempt-list
// TODO(dimitry) before O release: add a namespace attribute to have this enabled
// only for classloader-namespaces
const soinfo* needed_by = task->is_dt_needed() ? task->get_needed_by() : nullptr;
- if (is_greylisted(ns, name, needed_by)) {
+ if (is_exempt_lib(ns, name, needed_by)) {
// print warning only if needed by non-system library
if (needed_by == nullptr || !is_system_library(needed_by->get_realpath())) {
const soinfo* needed_or_dlopened_by = task->get_needed_by();
@@ -1243,20 +1231,18 @@ static bool load_library(android_namespace_t* ns,
}
soinfo* si = soinfo_alloc(ns, realpath.c_str(), &file_stat, file_offset, rtld_flags);
- if (si == nullptr) {
- return false;
- }
task->set_soinfo(si);
// Read the ELF header and some of the segments.
if (!task->read(realpath.c_str(), file_stat.st_size)) {
- soinfo_free(si);
+ task->remove_cached_elf_reader();
task->set_soinfo(nullptr);
+ soinfo_free(si);
return false;
}
- // find and set DT_RUNPATH and dt_soname
+ // Find and set DT_RUNPATH, DT_SONAME, and DT_FLAGS_1.
// Note that these field values are temporary and are
// going to be overwritten on soinfo::prelink_image
// with values from PT_LOAD segments.
@@ -1268,6 +1254,10 @@ static bool load_library(android_namespace_t* ns,
if (d->d_tag == DT_SONAME) {
si->set_soname(elf_reader.get_string(d->d_un.d_val));
}
+ // We need to identify a DF_1_GLOBAL library early so we can link it to namespaces.
+ if (d->d_tag == DT_FLAGS_1) {
+ si->set_dt_flags_1(d->d_un.d_val);
+ }
}
#if !defined(__ANDROID__)
@@ -1298,14 +1288,13 @@ static bool load_library(android_namespace_t* ns,
soinfo* needed_by = task->get_needed_by();
const android_dlextinfo* extinfo = task->get_extinfo();
- off64_t file_offset;
- std::string realpath;
if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
- file_offset = 0;
+ off64_t file_offset = 0;
if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
file_offset = extinfo->library_fd_offset;
}
+ std::string realpath;
if (!realpath_fd(extinfo->library_fd, &realpath)) {
if (!is_first_stage_init()) {
PRINT(
@@ -1323,10 +1312,12 @@ static bool load_library(android_namespace_t* ns,
LD_LOG(kLogDlopen,
"load_library(ns=%s, task=%s, flags=0x%x, search_linked_namespaces=%d): calling "
- "open_library with realpath=%s",
- ns->get_name(), name, rtld_flags, search_linked_namespaces, realpath.c_str());
+ "open_library",
+ ns->get_name(), name, rtld_flags, search_linked_namespaces);
// Open the file.
+ off64_t file_offset;
+ std::string realpath;
int fd = open_library(ns, zip_archive_cache, name, needed_by, &file_offset, &realpath);
if (fd == -1) {
if (task->is_dt_needed()) {
@@ -1352,8 +1343,7 @@ static bool find_loaded_library_by_soname(android_namespace_t* ns,
const char* name,
soinfo** candidate) {
return !ns->soinfo_list().visit([&](soinfo* si) {
- const char* soname = si->get_soname();
- if (soname != nullptr && (strcmp(name, soname) == 0)) {
+ if (strcmp(name, si->get_soname()) == 0) {
*candidate = si;
return false;
}
@@ -1437,11 +1427,11 @@ static bool find_library_internal(android_namespace_t* ns,
LoadTask* task,
ZipArchiveCache* zip_archive_cache,
LoadTaskList* load_tasks,
- int rtld_flags,
- bool search_linked_namespaces) {
+ int rtld_flags) {
soinfo* candidate;
- if (find_loaded_library_by_soname(ns, task->get_name(), search_linked_namespaces, &candidate)) {
+ if (find_loaded_library_by_soname(ns, task->get_name(), true /* search_linked_namespaces */,
+ &candidate)) {
LD_LOG(kLogDlopen,
"find_library_internal(ns=%s, task=%s): Already loaded (by soname): %s",
ns->get_name(), task->get_name(), candidate->get_realpath());
@@ -1454,54 +1444,49 @@ static bool find_library_internal(android_namespace_t* ns,
TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder... ]",
task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
- if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags, search_linked_namespaces)) {
+ if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags,
+ true /* search_linked_namespaces */)) {
return true;
}
- // TODO(dimitry): workaround for http://b/26394120 (the grey-list)
- if (ns->is_greylist_enabled() && is_greylisted(ns, task->get_name(), task->get_needed_by())) {
- // For the libs in the greylist, switch to the default namespace and then
+ // TODO(dimitry): workaround for http://b/26394120 (the exempt-list)
+ if (ns->is_exempt_list_enabled() && is_exempt_lib(ns, task->get_name(), task->get_needed_by())) {
+ // For the libs in the exempt-list, switch to the default namespace and then
// try the load again from there. The library could be loaded from the
// default namespace or from another namespace (e.g. runtime) that is linked
// from the default namespace.
LD_LOG(kLogDlopen,
- "find_library_internal(ns=%s, task=%s): Greylisted library - trying namespace %s",
+ "find_library_internal(ns=%s, task=%s): Exempt system library - trying namespace %s",
ns->get_name(), task->get_name(), g_default_namespace.get_name());
ns = &g_default_namespace;
if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags,
- search_linked_namespaces)) {
+ true /* search_linked_namespaces */)) {
return true;
}
}
// END OF WORKAROUND
- if (search_linked_namespaces) {
- // if a library was not found - look into linked namespaces
- // preserve current dlerror in the case it fails.
- DlErrorRestorer dlerror_restorer;
- LD_LOG(kLogDlopen, "find_library_internal(ns=%s, task=%s): Trying %zu linked namespaces",
- ns->get_name(), task->get_name(), ns->linked_namespaces().size());
- for (auto& linked_namespace : ns->linked_namespaces()) {
- if (find_library_in_linked_namespace(linked_namespace, task)) {
- if (task->get_soinfo() == nullptr) {
- // try to load the library - once namespace boundary is crossed
- // we need to load a library within separate load_group
- // to avoid using symbols from foreign namespace while.
- //
- // However, actual linking is deferred until when the global group
- // is fully identified and is applied to all namespaces.
- // Otherwise, the libs in the linked namespace won't get symbols from
- // the global group.
- if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks, rtld_flags, false)) {
- LD_LOG(
- kLogDlopen, "find_library_internal(ns=%s, task=%s): Found in linked namespace %s",
- ns->get_name(), task->get_name(), linked_namespace.linked_namespace()->get_name());
- return true;
- }
- } else {
- // lib is already loaded
- return true;
- }
+ // if a library was not found - look into linked namespaces
+ // preserve current dlerror in the case it fails.
+ DlErrorRestorer dlerror_restorer;
+ LD_LOG(kLogDlopen, "find_library_internal(ns=%s, task=%s): Trying %zu linked namespaces",
+ ns->get_name(), task->get_name(), ns->linked_namespaces().size());
+ for (auto& linked_namespace : ns->linked_namespaces()) {
+ if (find_library_in_linked_namespace(linked_namespace, task)) {
+ // Library is already loaded.
+ if (task->get_soinfo() != nullptr) {
+ // n.b. This code path runs when find_library_in_linked_namespace found an already-loaded
+ // library by soname. That should only be possible with a exempt-list lookup, where we
+ // switch the namespace, because otherwise, find_library_in_linked_namespace is duplicating
+ // the soname scan done in this function's first call to find_loaded_library_by_soname.
+ return true;
+ }
+
+ if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks,
+ rtld_flags, false /* search_linked_namespaces */)) {
+ LD_LOG(kLogDlopen, "find_library_internal(ns=%s, task=%s): Found in linked namespace %s",
+ ns->get_name(), task->get_name(), linked_namespace.linked_namespace()->get_name());
+ return true;
}
}
}
@@ -1538,7 +1523,6 @@ bool find_libraries(android_namespace_t* ns,
int rtld_flags,
const android_dlextinfo* extinfo,
bool add_as_children,
- bool search_linked_namespaces,
std::vector<android_namespace_t*>* namespaces) {
// Step 0: prepare.
std::unordered_map<const soinfo*, ElfReader> readers_map;
@@ -1572,6 +1556,7 @@ bool find_libraries(android_namespace_t* ns,
});
ZipArchiveCache zip_archive_cache;
+ soinfo_list_t new_global_group_members;
// Step 1: expand the list of load_tasks to include
// all DT_NEEDED libraries (do not load them just yet)
@@ -1594,8 +1579,7 @@ bool find_libraries(android_namespace_t* ns,
task,
&zip_archive_cache,
&load_tasks,
- rtld_flags,
- search_linked_namespaces || is_dt_needed)) {
+ rtld_flags)) {
return false;
}
@@ -1607,13 +1591,31 @@ bool find_libraries(android_namespace_t* ns,
// When ld_preloads is not null, the first
// ld_preloads_count libs are in fact ld_preloads.
+ bool is_ld_preload = false;
if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) {
ld_preloads->push_back(si);
+ is_ld_preload = true;
}
if (soinfos_count < library_names_count) {
soinfos[soinfos_count++] = si;
}
+
+ // Add the new global group members to all initial namespaces. Do this secondary namespace setup
+ // at the same time that libraries are added to their primary namespace so that the order of
+ // global group members is the same in the every namespace. Only add a library to a namespace
+ // once, even if it appears multiple times in the dependency graph.
+ if (is_ld_preload || (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
+ if (!si->is_linked() && namespaces != nullptr && !new_global_group_members.contains(si)) {
+ new_global_group_members.push_back(si);
+ for (auto linked_ns : *namespaces) {
+ if (si->get_primary_namespace() != linked_ns) {
+ linked_ns->add_soinfo(si);
+ si->add_secondary_namespace(linked_ns);
+ }
+ }
+ }
+ }
}
// Step 2: Load libraries in random order (see b/24047022)
@@ -1670,39 +1672,15 @@ bool find_libraries(android_namespace_t* ns,
register_soinfo_tls(si);
}
- // Step 4: Construct the global group. Note: DF_1_GLOBAL bit of a library is
- // determined at step 3.
-
- // Step 4-1: DF_1_GLOBAL bit is force set for LD_PRELOADed libs because they
- // must be added to the global group
+ // Step 4: Construct the global group. DF_1_GLOBAL bit is force set for LD_PRELOADed libs because
+ // they must be added to the global group. Note: The DF_1_GLOBAL bit for a library is normally set
+ // in step 3.
if (ld_preloads != nullptr) {
for (auto&& si : *ld_preloads) {
si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
}
}
- // Step 4-2: Gather all DF_1_GLOBAL libs which were newly loaded during this
- // run. These will be the new member of the global group
- soinfo_list_t new_global_group_members;
- for (auto&& task : load_tasks) {
- soinfo* si = task->get_soinfo();
- if (!si->is_linked() && (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
- new_global_group_members.push_back(si);
- }
- }
-
- // Step 4-3: Add the new global group members to all the linked namespaces
- if (namespaces != nullptr) {
- for (auto linked_ns : *namespaces) {
- for (auto si : new_global_group_members) {
- if (si->get_primary_namespace() != linked_ns) {
- linked_ns->add_soinfo(si);
- si->add_secondary_namespace(linked_ns);
- }
- }
- }
- }
-
// Step 5: Collect roots of local_groups.
// Whenever needed_by->si link crosses a namespace boundary it forms its own local_group.
// Here we collect new roots to link them separately later on. Note that we need to avoid
@@ -1837,8 +1815,7 @@ static soinfo* find_library(android_namespace_t* ns,
0,
rtld_flags,
extinfo,
- false /* add_as_children */,
- true /* search_linked_namespaces */)) {
+ false /* add_as_children */)) {
if (si != nullptr) {
soinfo_unload(si);
}
@@ -2404,6 +2381,21 @@ static void add_soinfos_to_namespace(const soinfo_list_t& soinfos, android_names
}
}
+std::vector<std::string> fix_lib_paths(std::vector<std::string> paths) {
+ // For the bootstrap linker, insert /system/${LIB}/bootstrap in front of /system/${LIB} in any
+ // namespace search path. The bootstrap linker should prefer to use the bootstrap bionic libraries
+ // (e.g. libc.so).
+#if !defined(__ANDROID_APEX__)
+ for (size_t i = 0; i < paths.size(); ++i) {
+ if (paths[i] == kSystemLibDir) {
+ paths.insert(paths.begin() + i, std::string(kSystemLibDir) + "/bootstrap");
+ ++i;
+ }
+ }
+#endif
+ return paths;
+}
+
android_namespace_t* create_namespace(const void* caller_addr,
const char* name,
const char* ld_library_path,
@@ -2432,7 +2424,7 @@ android_namespace_t* create_namespace(const void* caller_addr,
android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
ns->set_name(name);
ns->set_isolated((type & ANDROID_NAMESPACE_TYPE_ISOLATED) != 0);
- ns->set_greylist_enabled((type & ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED) != 0);
+ ns->set_exempt_list_enabled((type & ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED) != 0);
ns->set_also_used_as_anonymous((type & ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS) != 0);
if ((type & ANDROID_NAMESPACE_TYPE_SHARED) != 0) {
@@ -2577,9 +2569,8 @@ bool VersionTracker::init_verneed(const soinfo* si_from) {
const char* target_soname = si_from->get_string(verneed->vn_file);
// find it in dependencies
- soinfo* target_si = si_from->get_children().find_if([&](const soinfo* si) {
- return si->get_soname() != nullptr && strcmp(si->get_soname(), target_soname) == 0;
- });
+ soinfo* target_si = si_from->get_children().find_if(
+ [&](const soinfo* si) { return strcmp(si->get_soname(), target_soname) == 0; });
if (target_si == nullptr) {
DL_ERR("cannot find \"%s\" from verneed[%zd] in DT_NEEDED list for \"%s\"",
@@ -3147,6 +3138,14 @@ bool soinfo::prelink_image() {
// resolves everything eagerly, so these can be ignored.
break;
+#if defined(__aarch64__)
+ case DT_AARCH64_BTI_PLT:
+ case DT_AARCH64_PAC_PLT:
+ case DT_AARCH64_VARIANT_PCS:
+ // Ignored: AArch64 processor-specific dynamic array tags.
+ break;
+#endif
+
default:
if (!relocating_linker) {
const char* tag_name;
@@ -3174,7 +3173,7 @@ bool soinfo::prelink_image() {
DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
reinterpret_cast<void*>(base), strtab_, symtab_);
- // Sanity checks.
+ // Validity checks.
if (relocating_linker && needed_count != 0) {
DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");
return false;
@@ -3193,34 +3192,32 @@ bool soinfo::prelink_image() {
return false;
}
- // second pass - parse entries relying on strtab
- for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
- switch (d->d_tag) {
- case DT_SONAME:
- set_soname(get_string(d->d_un.d_val));
- break;
- case DT_RUNPATH:
- set_dt_runpath(get_string(d->d_un.d_val));
- break;
+ // Second pass - parse entries relying on strtab. Skip this while relocating the linker so as to
+ // avoid doing heap allocations until later in the linker's initialization.
+ if (!relocating_linker) {
+ for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
+ switch (d->d_tag) {
+ case DT_SONAME:
+ set_soname(get_string(d->d_un.d_val));
+ break;
+ case DT_RUNPATH:
+ set_dt_runpath(get_string(d->d_un.d_val));
+ break;
+ }
}
}
- // Before M release linker was using basename in place of soname.
- // In the case when dt_soname is absent some apps stop working
- // because they can't find dt_needed library by soname.
- // This workaround should keep them working. (Applies only
- // for apps targeting sdk version < M.) Make an exception for
- // the main executable and linker; they do not need to have dt_soname.
- // TODO: >= O the linker doesn't need this workaround.
- if (soname_ == nullptr &&
- this != solist_get_somain() &&
- (flags_ & FLAG_LINKER) == 0 &&
+ // Before M release, linker was using basename in place of soname. In the case when DT_SONAME is
+ // absent some apps stop working because they can't find DT_NEEDED library by soname. This
+ // workaround should keep them working. (Applies only for apps targeting sdk version < M.) Make
+ // an exception for the main executable, which does not need to have DT_SONAME. The linker has an
+ // DT_SONAME but the soname_ field is initialized later on.
+ if (soname_.empty() && this != solist_get_somain() && !relocating_linker &&
get_application_target_sdk_version() < 23) {
soname_ = basename(realpath_.c_str());
- DL_WARN_documented_change(23,
- "missing-soname-enforced-for-api-level-23",
- "\"%s\" has no DT_SONAME (will use %s instead)",
- get_realpath(), soname_);
+ DL_WARN_documented_change(23, "missing-soname-enforced-for-api-level-23",
+ "\"%s\" has no DT_SONAME (will use %s instead)", get_realpath(),
+ soname_.c_str());
// Don't call add_dlwarning because a missing DT_SONAME isn't important enough to show in the UI
}
@@ -3259,9 +3256,8 @@ bool soinfo::link_image(const SymbolLookupList& lookup_list, soinfo* local_group
// Fail if app is targeting M or above.
int app_target_api_level = get_application_target_sdk_version();
if (app_target_api_level >= 23) {
- DL_ERR_AND_LOG("\"%s\" has text relocations (https://android.googlesource.com/platform/"
- "bionic/+/master/android-changes-for-ndk-developers.md#Text-Relocations-"
- "Enforced-for-API-level-23)", get_realpath());
+ DL_ERR_AND_LOG("\"%s\" has text relocations (%s#Text-Relocations-Enforced-for-API-level-23)",
+ get_realpath(), kBionicChangesUrl);
return false;
}
// Make segments writable to allow text relocations to work properly. We will later call
@@ -3385,6 +3381,22 @@ static std::string get_ld_config_file_vndk_path() {
return ld_config_file_vndk;
}
+bool is_linker_config_expected(const char* executable_path) {
+ // Do not raise message from a host environment which is expected to miss generated linker
+ // configuration.
+#if !defined(__ANDROID__)
+ return false;
+#endif
+
+ if (strcmp(executable_path, "/system/bin/init") == 0) {
+ // Generated linker configuration can be missed from processes executed
+ // with init binary
+ return false;
+ }
+
+ return true;
+}
+
static std::string get_ld_config_file_path(const char* executable_path) {
#ifdef USE_LD_CONFIG_FILE
// This is a debugging/testing only feature. Must not be available on
@@ -3411,10 +3423,11 @@ static std::string get_ld_config_file_path(const char* executable_path) {
if (file_exists(kLdGeneratedConfigFilePath)) {
return kLdGeneratedConfigFilePath;
- } else {
- // TODO(b/146386369) : Adjust log level and add more condition to log only when necessary
- INFO("Warning: failed to find generated linker configuration from \"%s\"",
- kLdGeneratedConfigFilePath);
+ }
+
+ if (is_linker_config_expected(executable_path)) {
+ DL_WARN("Warning: failed to find generated linker configuration from \"%s\"",
+ kLdGeneratedConfigFilePath);
}
path = get_ld_config_file_vndk_path();
@@ -3440,23 +3453,19 @@ std::vector<android_namespace_t*> init_default_namespaces(const char* executable
const Config* config = nullptr;
- std::string error_msg;
-
- std::string ld_config_file_path = get_ld_config_file_path(executable_path);
-
- INFO("[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
- if (!Config::read_binary_config(ld_config_file_path.c_str(),
- executable_path,
- g_is_asan,
- &config,
- &error_msg)) {
- if (!error_msg.empty()) {
- DL_WARN("Warning: couldn't read \"%s\" for \"%s\" (using default configuration instead): %s",
- ld_config_file_path.c_str(),
- executable_path,
- error_msg.c_str());
+ {
+ std::string ld_config_file_path = get_ld_config_file_path(executable_path);
+ INFO("[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
+ ScopedTrace trace(("linker config " + ld_config_file_path).c_str());
+ std::string error_msg;
+ if (!Config::read_binary_config(ld_config_file_path.c_str(), executable_path, g_is_asan,
+ &config, &error_msg)) {
+ if (!error_msg.empty()) {
+ DL_WARN("Warning: couldn't read '%s' for '%s' (using default configuration instead): %s",
+ ld_config_file_path.c_str(), executable_path, error_msg.c_str());
+ }
+ config = nullptr;
}
- config = nullptr;
}
if (config == nullptr) {
@@ -3490,7 +3499,7 @@ std::vector<android_namespace_t*> init_default_namespaces(const char* executable
ns->set_isolated(ns_config->isolated());
ns->set_default_library_paths(ns_config->search_paths());
ns->set_permitted_paths(ns_config->permitted_paths());
- ns->set_whitelisted_libs(ns_config->whitelisted_libs());
+ ns->set_allowed_libs(ns_config->allowed_libs());
namespaces[ns_config->name()] = ns;
if (ns_config->visible()) {