loader: fix d-tor call order

In the case when there are multiple dependencies on
the same library in the local_group the unload may
in some situations (covered now by tests) result
calling d-tors for some libraries prematurely.

In order to have correct call order loader checks if this
is last dependency in local group before adding it to BFS
queue.

Bug: http://b/35201832
Test: bionic-unit-tests --gtest_filter=dl*:Dl*
Test: bionic-unit-tests-glibc --gtest_filter=dl*
Change-Id: I4c6955b9032acc7147a51d9f09b61d9e0818700c
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 3e9e85e..48fb6d1 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1142,8 +1142,9 @@
   g_fini_call_order_str += s;
 }
 
-TEST(dlfcn, init_fini_call_order) {
-  void* handle = dlopen("libtest_init_fini_order_root.so", RTLD_NOW);
+static void test_init_fini_call_order_for(const char* libname) {
+  g_fini_call_order_str.clear();
+  void* handle = dlopen(libname, RTLD_NOW);
   ASSERT_TRUE(handle != nullptr) << dlerror();
   typedef int (*get_init_order_number_t)();
   get_init_order_number_t get_init_order_number =
@@ -1158,6 +1159,11 @@
   ASSERT_EQ("(root)(child)(grandchild)", g_fini_call_order_str);
 }
 
+TEST(dlfcn, init_fini_call_order) {
+  test_init_fini_call_order_for("libtest_init_fini_order_root.so");
+  test_init_fini_call_order_for("libtest_init_fini_order_root2.so");
+}
+
 TEST(dlfcn, symbol_versioning_use_v1) {
   void* handle = dlopen("libtest_versioned_uselibv1.so", RTLD_NOW);
   ASSERT_TRUE(handle != nullptr) << dlerror();
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 31a0916..5eb16c5 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -448,13 +448,26 @@
 }
 
 // -----------------------------------------------------------------------------
-// Library used to check init/fini call order
+// Libraries used to check init/fini call order
 // -----------------------------------------------------------------------------
 cc_test_library {
     name: "libtest_init_fini_order_root",
     defaults: ["bionic_testlib_defaults"],
     srcs: ["dlopen_check_init_fini_root.cpp"],
-    shared_libs: ["libtest_init_fini_order_child"],
+    shared_libs: [
+        "libtest_init_fini_order_child",
+        "libtest_init_fini_order_grand_child",
+    ],
+}
+
+cc_test_library {
+    name: "libtest_init_fini_order_root2",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["dlopen_check_init_fini_root.cpp"],
+    shared_libs: [
+        "libtest_init_fini_order_grand_child",
+        "libtest_init_fini_order_child",
+    ],
 }
 
 cc_test_library {