Fix soinfo_unload

 1. Take into consideration that the local_group_root_
    is not set for all of not linked libraries.
 2. We need to check visited list earlier to avoid double
    soinfo_free.

Change-Id: Iabc0a06a97c63f7e6bd4641731f50bb1466fed4f
diff --git a/linker/linker.cpp b/linker/linker.cpp
index b2e7464..3409931 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -320,7 +320,7 @@
 
   if (trav == nullptr) {
     // si was not in solist
-    DL_ERR("name \"%s\" is not in solist!", si->name);
+    DL_ERR("name \"%s\"@%p is not in solist!", si->name, si);
     return;
   }
 
@@ -1150,20 +1150,29 @@
     soinfo* si = nullptr;
 
     while ((si = depth_first_list.pop_front()) != nullptr) {
+      if (local_unload_list.contains(si)) {
+        continue;
+      }
+
       local_unload_list.push_back(si);
+
       if (si->has_min_version(0)) {
         soinfo* child = nullptr;
         while ((child = si->get_children().pop_front()) != nullptr) {
-          TRACE("%s needs to unload %s", si->name, child->name);
+          TRACE("%s@%p needs to unload %s@%p", si->name, si, child->name, child);
           if (local_unload_list.contains(child)) {
             continue;
-          } else if (child->get_local_group_root() != root) {
+          } else if (child->is_linked() && child->get_local_group_root() != root) {
             external_unload_list.push_back(child);
           } else {
             depth_first_list.push_front(child);
           }
         }
       } else {
+#ifdef __LP64__
+        __libc_fatal("soinfo for \"%s\"@%p has no version", si->name, si);
+#else
+        PRINT("warning: soinfo for \"%s\"@%p has no version", si->name, si);
         for_each_dt_needed(si, [&] (const char* library_name) {
           TRACE("deprecated (old format of soinfo): %s needs to unload %s", si->name, library_name);
           soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr);
@@ -1175,7 +1184,7 @@
           } else if (local_unload_list.contains(needed)) {
             // already visited
             return;
-          } else if (needed->get_local_group_root() != root) {
+          } else if (needed->is_linked() && needed->get_local_group_root() != root) {
             // external group
             external_unload_list.push_back(needed);
           } else {
@@ -1183,6 +1192,7 @@
             depth_first_list.push_front(needed);
           }
         });
+#endif
       }
     }