aboutsummaryrefslogtreecommitdiff
path: root/linker
diff options
context:
space:
mode:
Diffstat (limited to 'linker')
-rw-r--r--linker/dlfcn.cpp2
-rw-r--r--linker/linker.cpp35
-rw-r--r--linker/linker_main.cpp7
-rw-r--r--linker/linker_soinfo.cpp7
4 files changed, 28 insertions, 23 deletions
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 772e7b81c..af050274d 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -328,7 +328,7 @@ soinfo* get_libdl_info(const soinfo& linker_si) {
__libdl_info->ref_count_ = 1;
__libdl_info->strtab_size_ = linker_si.strtab_size_;
__libdl_info->local_group_root_ = __libdl_info;
- __libdl_info->soname_ = linker_si.soname_.c_str();
+ __libdl_info->soname_ = linker_si.soname_;
__libdl_info->target_sdk_version_ = __ANDROID_API__;
__libdl_info->generate_handle();
#if defined(__work_around_b_24465209__)
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 77824f615..c240c5639 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3193,26 +3193,27 @@ 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_.empty() && 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",
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 59e803665..0b501a7b1 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -725,6 +725,13 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so)
// Initialize the linker's own global variables
tmp_linker_so.call_constructors();
+ // Setting the linker soinfo's soname can allocate heap memory, so delay it until here.
+ for (const ElfW(Dyn)* d = tmp_linker_so.dynamic; d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_SONAME) {
+ tmp_linker_so.set_soname(tmp_linker_so.get_string(d->d_un.d_val));
+ }
+ }
+
// When the linker is run directly rather than acting as PT_INTERP, parse
// arguments and determine the executable to load. When it's instead acting
// as PT_INTERP, AT_ENTRY will refer to the loaded executable rather than the
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index f44cb1c4b..287e757a9 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -485,11 +485,8 @@ static void call_function(const char* function_name __unused,
}
template <typename F>
-static void call_array(const char* array_name __unused,
- F* functions,
- size_t count,
- bool reverse,
- const char* realpath) {
+static inline void call_array(const char* array_name __unused, F* functions, size_t count,
+ bool reverse, const char* realpath) {
if (functions == nullptr) {
return;
}