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;
   }