Merge "Hide __libc_init_vdso()."
diff --git a/libc/private/bionic_systrace.h b/libc/private/bionic_systrace.h
index ad9ff7f..0b4560f 100644
--- a/libc/private/bionic_systrace.h
+++ b/libc/private/bionic_systrace.h
@@ -23,7 +23,7 @@
 //   ScopedTrace("Trace message");
 // The trace will end when the contructor goes out of scope.
 
-class ScopedTrace {
+class __LIBC_HIDDEN__ ScopedTrace {
  public:
   explicit ScopedTrace(const char* message);
   ~ScopedTrace();
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 7f8c901..8096e62 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -100,6 +100,15 @@
     }
   }
 
+  bool contains(const T* el) {
+    for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
+      if (e->element != nullptr && e->element == el) {
+        return true;
+      }
+    }
+    return false;
+  }
+
  private:
   LinkedListEntry<T>* head_;
   LinkedListEntry<T>* tail_;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f8b35d7..77fb70c 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -607,17 +607,24 @@
 // specified soinfo object and its dependencies in breadth first order.
 ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller) {
   LinkedList<soinfo, SoinfoListAllocatorRW> visit_list;
+  LinkedList<soinfo, SoinfoListAllocatorRW> visited;
   visit_list.push_back(si);
   soinfo* current_soinfo;
   while ((current_soinfo = visit_list.pop_front()) != nullptr) {
+    if (visited.contains(current_soinfo)) {
+      continue;
+    }
+
     ElfW(Sym)* result = soinfo_elf_lookup(current_soinfo, elfhash(name), name,
         caller == current_soinfo ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
 
     if (result != nullptr) {
       *found = current_soinfo;
       visit_list.clear();
+      visited.clear();
       return result;
     }
+    visited.push_back(current_soinfo);
 
     current_soinfo->get_children().for_each([&](soinfo* child) {
       visit_list.push_back(child);
@@ -625,6 +632,7 @@
   }
 
   visit_list.clear();
+  visited.clear();
   return nullptr;
 }