diff options
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r-- | linker/linker.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index 4ebb476aa..f07285d77 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -691,6 +691,68 @@ enum walk_action_result_t : uint32_t { kWalkSkip = 2 }; +static soinfo* find_library(android_namespace_t* ns, + const char* name, int rtld_flags, + const android_dlextinfo* extinfo, + soinfo* needed_by); + +// g_ld_all_shim_libs maintains the references to memory as it used +// in the soinfo structures and in the g_active_shim_libs list. + +typedef std::pair<std::string, std::string> ShimDescriptor; +static std::vector<ShimDescriptor> g_ld_all_shim_libs; + +// g_active_shim_libs are all shim libs that are still eligible +// to be loaded. We must remove a shim lib from the list before +// we load the library to avoid recursive loops (load shim libA +// for libB where libA also links against libB). + +static linked_list_t<const ShimDescriptor> g_active_shim_libs; + +static void reset_g_active_shim_libs(void) { + g_active_shim_libs.clear(); + for (const auto& pair : g_ld_all_shim_libs) { + g_active_shim_libs.push_back(&pair); + } +} + +void parse_LD_SHIM_LIBS(const char* path) { + g_ld_all_shim_libs.clear(); + if (path != nullptr) { + // We have historically supported ':' as well as ' ' in LD_SHIM_LIBS. + for (const auto& pair : android::base::Split(path, " :")) { + size_t pos = pair.find('|'); + if (pos > 0 && pos < pair.length() - 1) { + auto desc = std::pair<std::string, std::string>(pair.substr(0, pos), pair.substr(pos + 1)); + g_ld_all_shim_libs.push_back(desc); + } + } + } + reset_g_active_shim_libs(); +} + +template<typename F> +static void for_each_matching_shim(const char *const path, F action) { + if (path == nullptr) return; + INFO("Finding shim libs for \"%s\"\n", path); + std::vector<const ShimDescriptor *> matched; + + g_active_shim_libs.for_each([&](const ShimDescriptor *a_pair) { + if (a_pair->first == path) { + matched.push_back(a_pair); + } + }); + + g_active_shim_libs.remove_if([&](const ShimDescriptor *a_pair) { + return a_pair->first == path; + }); + + for (const auto& one_pair : matched) { + INFO("Injecting shim lib \"%s\" as needed for %s", one_pair->second.c_str(), path); + action(one_pair->second.c_str()); + } +} + // This function walks down the tree of soinfo dependencies // in breadth-first order and // * calls action(soinfo* si) for each node, and @@ -1108,6 +1170,7 @@ const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) { template<typename F> static void for_each_dt_needed(const ElfReader& elf_reader, F action) { + for_each_matching_shim(elf_reader.name(), action); for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) { if (d->d_tag == DT_NEEDED) { action(fix_dt_needed(elf_reader.get_string(d->d_un.d_val), elf_reader.name())); @@ -1967,6 +2030,7 @@ void* do_dlopen(const char* name, int flags, } ProtectedDataGuard guard; + reset_g_active_shim_libs(); soinfo* si = find_library(ns, translated_name, flags, extinfo, caller); loading_trace.End(); |