diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index cf17c3d5b155..4c0aa1bb86a4 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -471,7 +471,7 @@ public: /// Gets the symbol file spec list for this object file. /// /// If the object file format contains a debug symbol file link, - /// the values will be return in the FileSpecList. + /// the values will be returned in the FileSpecList. /// /// @return /// Returns filespeclist. @@ -482,6 +482,21 @@ public: return FileSpecList(); } + //------------------------------------------------------------------ + /// Gets the file spec list of libraries re-exported by this object file. + /// + /// If the object file format has the notion of one library re-exporting the symbols from another, + /// the re-exported libraries will be returned in the FileSpecList. + /// + /// @return + /// Returns filespeclist. + //------------------------------------------------------------------ + virtual lldb_private::FileSpecList + GetReExportedLibraries () + { + return FileSpecList(); + } + //------------------------------------------------------------------ /// Sets the load address for an entire module, assuming a rigid /// slide of sections, if possible in the implementation. diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h index db32ba373e42..cd10bf34e45a 100644 --- a/lldb/include/lldb/Symbol/Symbol.h +++ b/lldb/include/lldb/Symbol/Symbol.h @@ -303,7 +303,15 @@ public: Stream &strm); protected: - + // This is the internal guts of ResolveReExportedSymbol, it assumes reexport_name is not null, and that module_spec + // is valid. We track the modules we've already seen to make sure we don't get caught in a cycle. + + Symbol * + ResolveReExportedSymbolInModuleSpec (Target &target, + ConstString &reexport_name, + lldb_private::ModuleSpec &module_spec, + lldb_private::ModuleList &seen_modules); + uint32_t m_uid; // User ID (usually the original symbol table index) uint16_t m_type_data; // data specific to m_type uint16_t m_type_data_resolved:1, // True if the data in m_type_data has already been calculated diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 4f491ce67b0b..6866a068ef75 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1838,6 +1838,11 @@ ObjectFileMachO::ParseSymtab () // 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 c565ac63e4ef..dff0b21be803 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 @@ public: virtual uint32_t GetDependentModules (lldb_private::FileSpecList& files); + virtual lldb_private::FileSpecList + GetReExportedLibraries () + { + return m_reexported_dylibs; + } //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -208,6 +214,7 @@ protected: 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 9bda7b20ecbc..98b5a320580c 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -536,6 +536,71 @@ Symbol::GetByteSize () const 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; iIsExternal()) + 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 @@ Symbol::ResolveReExportedSymbol (Target &target) 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; iIsExternal()) - return sc.symbol; - } - } - } + return ResolveReExportedSymbolInModuleSpec(target, reexport_name, module_spec, seen_modules); } } return nullptr;