Introducing linker namespaces

Bug: http://b/22548808
Change-Id: Ia3af3c0a167f1d16447a3d83bb045d143319b1e1
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 93189df..7957921 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -108,9 +108,16 @@
   const ElfW(Sym)* sym = nullptr;
   void* caller_addr = __builtin_return_address(0);
   soinfo* caller = find_containing_library(caller_addr);
+  if (caller == nullptr) {
+    char buf[256];
+    __libc_format_buffer(buf, sizeof(buf), "dlsym couldn't locate its caller address=%p; "
+                         "the caller was code not loaded by the dynamic linker", caller_addr);
+    __bionic_format_dlerror(buf, nullptr);
+    return nullptr;
+  }
 
   if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) {
-    sym = dlsym_linear_lookup(symbol, &found, caller, handle);
+    sym = dlsym_linear_lookup(caller->get_namespace(), symbol, &found, caller, handle);
   } else {
     sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol);
   }
@@ -177,6 +184,30 @@
   return get_application_target_sdk_version();
 }
 
+bool android_init_public_namespace(const char* path) {
+  ScopedPthreadMutexLocker locker(&g_dl_mutex);
+  bool success = init_public_namespace(path);
+  if (!success) {
+    __bionic_format_dlerror("android_init_public_namespace failed", linker_get_error_buffer());
+  }
+
+  return success;
+}
+
+android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
+                                              const char* default_library_path, bool is_isolated) {
+  ScopedPthreadMutexLocker locker(&g_dl_mutex);
+
+  android_namespace_t* result = create_namespace(name, ld_library_path,
+                                                 default_library_path, is_isolated);
+
+  if (result == nullptr) {
+    __bionic_format_dlerror("android_create_namespace failed", linker_get_error_buffer());
+  }
+
+  return result;
+}
+
 // name_offset: starting index of the name in libdl_info.strtab
 #define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \
     { name_offset, \
@@ -203,11 +234,11 @@
   // 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999
   // 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789
     "erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar"
-  // 0000000000111111
-  // 0123456789012345
-    "get_sdk_version\0"
+  // 0000000000111111 111122222222223333333333444444 4444555555555566666666667
+  // 0123456789012345 678901234567890123456789012345 6789012345678901234567890
+    "get_sdk_version\0android_init_public_namespace\0android_create_namespace\0"
 #if defined(__arm__)
-  // 216
+  // 271
     "dl_unwind_find_exidx\0"
 #endif
     ;
@@ -229,8 +260,10 @@
   ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1),
   ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1),
   ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1),
+  ELFW(SYM_INITIALIZER)(216, &android_init_public_namespace, 1),
+  ELFW(SYM_INITIALIZER)(246, &android_create_namespace, 1),
 #if defined(__arm__)
-  ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1),
+  ELFW(SYM_INITIALIZER)(271, &dl_unwind_find_exidx, 1),
 #endif
 };
 
@@ -247,18 +280,20 @@
 // Note that adding any new symbols here requires stubbing them out in libdl.
 static unsigned g_libdl_buckets[1] = { 1 };
 #if defined(__arm__)
-static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 };
+static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 };
 #else
-static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 };
+static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 };
 #endif
 
 static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
 static soinfo* __libdl_info = nullptr;
 
+extern android_namespace_t g_default_namespace;
+
 // This is used by the dynamic linker. Every process gets these symbols for free.
 soinfo* get_libdl_info() {
   if (__libdl_info == nullptr) {
-    __libdl_info = new (__libdl_info_buf) soinfo("libdl.so", nullptr, 0, RTLD_GLOBAL);
+    __libdl_info = new (__libdl_info_buf) soinfo(&g_default_namespace, "libdl.so", nullptr, 0, RTLD_GLOBAL);
     __libdl_info->flags_ |= FLAG_LINKED;
     __libdl_info->strtab_ = ANDROID_LIBDL_STRTAB;
     __libdl_info->symtab_ = g_libdl_symtab;