ReExported symbols can point to a library that doesn't actually
contain the symbol, but just reexports wholesale from another
library.  Handle this case.

<rdar://problem/16977589>

llvm-svn: 209270
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 4f491ce..6866a06 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -1838,6 +1838,11 @@
                     // Strip the path if there is @rpath, @executanble, etc so we just use the basename
                     if (path[0] == '@')
                         file_spec.GetDirectory().Clear();
+                    
+                    if (lc.cmd == LC_REEXPORT_DYLIB)
+                    {
+                        m_reexported_dylibs.AppendIfUnique(file_spec);
+                    }
 
                     dylib_files.Append(file_spec);
                 }
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index c565ac6..dff0b21 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -13,6 +13,7 @@
 #include "lldb/Utility/SafeMachO.h"
 
 #include "lldb/Core/Address.h"
+#include "lldb/Core/FileSpecList.h"
 #include "lldb/Core/RangeMap.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Host/Mutex.h"
@@ -127,6 +128,11 @@
     virtual uint32_t
     GetDependentModules (lldb_private::FileSpecList& files);
 
+    virtual lldb_private::FileSpecList
+    GetReExportedLibraries ()
+    {
+        return m_reexported_dylibs;
+    }
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
@@ -208,6 +214,7 @@
     lldb_private::Address  m_entry_point_address;
     FileRangeArray m_thread_context_offsets;
     bool m_thread_context_offsets_valid;
+    lldb_private::FileSpecList m_reexported_dylibs;
 
     size_t
     ParseSymtab ();
diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index 9bda7b2..98b5a32 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -536,6 +536,71 @@
     return m_addr_range.GetByteSize();
 }
 
+
+Symbol *
+Symbol::ResolveReExportedSymbolInModuleSpec (Target &target,
+                                             ConstString &reexport_name,
+                                             ModuleSpec &module_spec,
+                                             ModuleList &seen_modules)
+{
+    ModuleSP module_sp;
+    if (module_spec.GetFileSpec())
+    {
+        // Try searching for the module file spec first using the full path
+        module_sp = target.GetImages().FindFirstModule(module_spec);
+        if (!module_sp)
+        {
+            // Next try and find the module by basename in case environment
+            // variables or other runtime trickery causes shared libraries
+            // to be loaded from alternate paths
+            module_spec.GetFileSpec().GetDirectory().Clear();
+            module_sp = target.GetImages().FindFirstModule(module_spec);
+        }
+    }
+
+    if (module_sp)
+    {
+        // There should not be cycles in the reexport list, but we don't want to crash if there are so make sure
+        // we haven't seen this before:
+        if (!seen_modules.AppendIfNeeded(module_sp))
+            return nullptr;
+        
+        lldb_private::SymbolContextList sc_list;
+        module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny, sc_list);
+        const size_t num_scs = sc_list.GetSize();
+        if (num_scs > 0)
+        {
+            for (size_t i=0; i<num_scs; ++i)
+            {
+                lldb_private::SymbolContext sc;
+                if (sc_list.GetContextAtIndex(i, sc))
+                {
+                    if (sc.symbol->IsExternal())
+                        return sc.symbol;
+                }
+            }
+        }
+        // If we didn't find the symbol in this module, it may be because this module re-exports some
+        // whole other library.  We have to search those as well:
+        seen_modules.Append(module_sp);
+        
+        FileSpecList reexported_libraries = module_sp->GetObjectFile()->GetReExportedLibraries();
+        size_t num_reexported_libraries = reexported_libraries.GetSize();
+        for (size_t idx = 0; idx < num_reexported_libraries; idx++)
+        {
+            ModuleSpec reexported_module_spec;
+            reexported_module_spec.GetFileSpec() = reexported_libraries.GetFileSpecAtIndex(idx);
+            Symbol *result_symbol = ResolveReExportedSymbolInModuleSpec(target,
+                                                                        reexport_name,
+                                                                        reexported_module_spec,
+                                                                        seen_modules);
+            if (result_symbol)
+                return result_symbol;
+        }
+    }
+    return nullptr;
+}
+
 Symbol *
 Symbol::ResolveReExportedSymbol (Target &target)
 {
@@ -543,39 +608,11 @@
     if (reexport_name)
     {
         ModuleSpec module_spec;
-        ModuleSP module_sp;
+        ModuleList seen_modules;
         module_spec.GetFileSpec() = GetReExportedSymbolSharedLibrary();
         if (module_spec.GetFileSpec())
         {
-            // Try searching for the module file spec first using the full path
-            module_sp = target.GetImages().FindFirstModule(module_spec);
-            if (!module_sp)
-            {
-                // Next try and find the module by basename in case environment
-                // variables or other runtime trickery causes shared libraries
-                // to be loaded from alternate paths
-                module_spec.GetFileSpec().GetDirectory().Clear();
-                module_sp = target.GetImages().FindFirstModule(module_spec);
-            }
-        }
-        
-        if (module_sp)
-        {
-            lldb_private::SymbolContextList sc_list;
-            module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny, sc_list);
-            const size_t num_scs = sc_list.GetSize();
-            if (num_scs > 0)
-            {
-                for (size_t i=0; i<num_scs; ++i)
-                {
-                    lldb_private::SymbolContext sc;
-                    if (sc_list.GetContextAtIndex(i, sc))
-                    {
-                        if (sc.symbol->IsExternal())
-                            return sc.symbol;
-                    }
-                }
-            }
+            return ResolveReExportedSymbolInModuleSpec(target, reexport_name, module_spec, seen_modules);
         }
     }
     return nullptr;