diff options
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r-- | linker/linker.cpp | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index df7dd4020..6826396ba 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -76,6 +76,7 @@ static std::unordered_map<void*, size_t> g_dso_handle_counters; +static bool g_anonymous_namespace_set = false; static android_namespace_t* g_anonymous_namespace = &g_default_namespace; static std::unordered_map<std::string, android_namespace_t*> g_exported_namespaces; @@ -270,8 +271,6 @@ static bool translateSystemPathToApexPath(const char* name, std::string* out_nam static std::vector<std::string> g_ld_preload_names; -static bool g_anonymous_namespace_initialized; - #if STATS struct linker_stats_t { int count[kRelocMax]; @@ -2471,14 +2470,29 @@ int do_dlclose(void* handle) { return 0; } -bool init_anonymous_namespace(const char* shared_lib_sonames, const char* library_search_path) { - if (g_anonymous_namespace_initialized) { - DL_ERR("anonymous namespace has already been initialized."); - return false; +// Make ns as the anonymous namespace that is a namespace used when +// we fail to determine the caller address (e.g., call from mono-jited code) +// Since there can be multiple anonymous namespace in a process, subsequent +// call to this function causes an error. +static bool set_anonymous_namespace(android_namespace_t* ns) { + if (!g_anonymous_namespace_set && ns != nullptr) { + CHECK(ns->is_also_used_as_anonymous()); + g_anonymous_namespace = ns; + g_anonymous_namespace_set = true; + return true; } + return false; +} +// TODO(b/130388701) remove this. Currently, this is used only for testing +// where we don't have classloader namespace. +bool init_anonymous_namespace(const char* shared_lib_sonames, const char* library_search_path) { ProtectedDataGuard guard; + // Test-only feature: we need to change the anonymous namespace multiple times + // while the test is running. + g_anonymous_namespace_set = false; + // create anonymous namespace // When the caller is nullptr - create_namespace will take global group // from the anonymous namespace, which is fine because anonymous namespace @@ -2488,21 +2502,18 @@ bool init_anonymous_namespace(const char* shared_lib_sonames, const char* librar "(anonymous)", nullptr, library_search_path, - ANDROID_NAMESPACE_TYPE_ISOLATED, + ANDROID_NAMESPACE_TYPE_ISOLATED | + ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS, nullptr, &g_default_namespace); - if (anon_ns == nullptr) { - return false; - } + CHECK(anon_ns != nullptr); if (!link_namespaces(anon_ns, &g_default_namespace, shared_lib_sonames)) { + // TODO: delete anon_ns return false; } - g_anonymous_namespace = anon_ns; - g_anonymous_namespace_initialized = true; - return true; } @@ -2542,6 +2553,7 @@ android_namespace_t* create_namespace(const void* caller_addr, 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_also_used_as_anonymous((type & ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS) != 0); if ((type & ANDROID_NAMESPACE_TYPE_SHARED) != 0) { // append parent namespace paths. @@ -2573,6 +2585,16 @@ android_namespace_t* create_namespace(const void* caller_addr, ns->set_default_library_paths(std::move(default_library_paths)); ns->set_permitted_paths(std::move(permitted_paths)); + if (ns->is_also_used_as_anonymous() && !set_anonymous_namespace(ns)) { + DL_ERR("failed to set namespace: [name=\"%s\", ld_library_path=\"%s\", default_library_paths=\"%s\"" + " permitted_paths=\"%s\"] as the anonymous namespace", + ns->get_name(), + android::base::Join(ns->get_ld_library_paths(), ':').c_str(), + android::base::Join(ns->get_default_library_paths(), ':').c_str(), + android::base::Join(ns->get_permitted_paths(), ':').c_str()); + return nullptr; + } + return ns; } |