linker: add android_get_exported_namespace

Depending on how ld.config.txt is configured, there can be multiple
built-in namespaces created by the linker from the beginning of a
process. android_get_exported_namespace is a platform only API for
getting a handle (android_namespace_t*) to one of the built-in namespaces
with given name. The returned namespace can then be given to
android_dlopen_ext in order to explicitly specify the target namespace
where the library is searched and loaded from.

Note that this function only returns 'exported' namespaces created via
ld.config.txt file. In order to export a namespace, the visible property
should be set to true:

namespace.<name>.visible = true

Namespaces are hidden by default. Hidden namespaces and namespaces
that are created programmatically, notably 'classloader-namespace',
aren't returned by this function.

Bug: 36851137
Test: confirmed that namespaces created with ld.config.txt is retrieved.
Test: linker-unit-tests passes
Change-Id: I0d05fa7e0e116009edf8ea362ab46774bc617cbf
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 2777d73..66bec58 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -71,6 +71,7 @@
 #define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
 
 static android_namespace_t* g_anonymous_namespace = &g_default_namespace;
+static std::unordered_map<std::string, android_namespace_t*> g_exported_namespaces;
 
 static LinkerTypeAllocator<soinfo> g_soinfo_allocator;
 static LinkerTypeAllocator<LinkedListEntry<soinfo>> g_soinfo_links_allocator;
@@ -3461,6 +3462,9 @@
     ns->set_permitted_paths(ns_config->permitted_paths());
 
     namespaces[ns_config->name()] = ns;
+    if (ns_config->visible()) {
+      g_exported_namespaces[ns_config->name()] = ns;
+    }
   }
 
   // 3. Establish links between namespaces
@@ -3485,3 +3489,16 @@
 
   set_application_target_sdk_version(config->target_sdk_version());
 }
+
+// This function finds a namespace exported in ld.config.txt by its name.
+// A namespace can be exported by setting .visible property to true.
+android_namespace_t* get_exported_namespace(const char* name) {
+  if (name == nullptr) {
+    return nullptr;
+  }
+  auto it = g_exported_namespaces.find(std::string(name));
+  if (it == g_exported_namespaces.end()) {
+    return nullptr;
+  }
+  return it->second;
+}