aboutsummaryrefslogtreecommitdiffstats
path: root/linker/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp64
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();