Don't create anonymous namespace
Anonymous namespace is not created separately. When a regular namespace
is created with ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS, that
namespace is used as the anonymous namespace.
Bug: 130388701
Test: CtsBionicTestCases
Change-Id: Ie449a59f303487a7a9ff6fff98e6148e9f968fd2
diff --git a/linker/linker.cpp b/linker/linker.cpp
index df7dd40..6826396 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 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 @@
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 @@
"(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 @@
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 @@
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;
}