Fix dlclose for libraries with thread_local dtors

Introduce new flag to mark soinfo as TLS_NODELETE when
there are thread_local dtors associated with dso_handle
belonging to it.

Test: bionic-unit-tests --gtest_filter=dl*
Test: bionic-unit-tests-glibc --gtest_filter=dl*
Bug: https://github.com/android-ndk/ndk/issues/360
Change-Id: I724ef89fc899788f95c47e6372c38b3313f18fed
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 869e0c1..7f40f90 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -82,6 +82,8 @@
                       const char* symbol,
                       const char* version,
                       const void* caller_addr) __LINKER_PUBLIC__;
+void __loader_add_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
+void __loader_remove_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
 #if defined(__arm__)
 _Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) __LINKER_PUBLIC__;
 #endif
@@ -272,6 +274,16 @@
   CFIShadowWriter::CfiFail(CallSiteTypeId, Ptr, DiagData, CallerPc);
 }
 
+void __loader_add_thread_local_dtor(void* dso_handle) {
+  ScopedPthreadMutexLocker locker(&g_dl_mutex);
+  increment_dso_handle_reference_counter(dso_handle);
+}
+
+void __loader_remove_thread_local_dtor(void* dso_handle) {
+  ScopedPthreadMutexLocker locker(&g_dl_mutex);
+  decrement_dso_handle_reference_counter(dso_handle);
+}
+
 static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
 static soinfo* __libdl_info = nullptr;