Introduce anonymous namespace
The anonymous namespace is introduced to
handle cases when linker can not find the
caller. This usually happens when caller
code was not loaded by dynamic linker;
for example mono-generated code.
Bug: http://b/25844435
Bug: http://b/22548808
Change-Id: I9e5b1d23c1c75bc78548d68e79216a6a943a33cf
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 1ecf65b..9780231 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -111,6 +111,7 @@
};
android_namespace_t g_default_namespace;
+android_namespace_t* g_anonymous_namespace = &g_default_namespace;
static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf);
@@ -2201,7 +2202,7 @@
return nullptr;
}
- android_namespace_t* ns = caller->get_namespace();
+ android_namespace_t* ns = caller != nullptr ? caller->get_namespace() : g_anonymous_namespace;
if (extinfo != nullptr) {
if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
@@ -2246,14 +2247,14 @@
soinfo_unload(si);
}
-bool init_public_namespace(const char* libs) {
- CHECK(libs != nullptr);
+bool init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_path) {
+ CHECK(public_ns_sonames != nullptr);
if (g_public_namespace_initialized) {
- DL_ERR("Public namespace has already been initialized.");
+ DL_ERR("public namespace has already been initialized.");
return false;
}
- std::vector<std::string> sonames = android::base::Split(libs, ":");
+ std::vector<std::string> sonames = android::base::Split(public_ns_sonames, ":");
ProtectedDataGuard guard;
@@ -2267,7 +2268,7 @@
find_loaded_library_by_soname(&g_default_namespace, soname.c_str(), &candidate);
if (candidate == nullptr) {
- DL_ERR("Error initializing public namespace: \"%s\" was not found"
+ DL_ERR("error initializing public namespace: \"%s\" was not found"
" in the default namespace", soname.c_str());
return false;
}
@@ -2276,8 +2277,18 @@
g_public_namespace.push_back(candidate);
}
- failure_guard.disable();
g_public_namespace_initialized = true;
+
+ // create anonymous namespace
+ android_namespace_t* anon_ns =
+ create_namespace("(anonymous)", nullptr, anon_ns_library_path, false);
+
+ if (anon_ns == nullptr) {
+ g_public_namespace_initialized = false;
+ return false;
+ }
+ g_anonymous_namespace = anon_ns;
+ failure_guard.disable();
return true;
}
@@ -2286,7 +2297,7 @@
const char* default_library_path,
bool is_isolated) {
if (!g_public_namespace_initialized) {
- DL_ERR("Cannot create namespace: public namespace is not initialized.");
+ DL_ERR("cannot create namespace: public namespace is not initialized.");
return nullptr;
}