Index: include/lldb/Core/Module.h =================================================================== --- include/lldb/Core/Module.h +++ include/lldb/Core/Module.h @@ -985,13 +985,12 @@ llvm::Optional m_unwind_table; ///< Table of FuncUnwinders /// objects created for this /// Module's functions - lldb::SymbolVendorUP - m_symfile_up; ///< A pointer to the symbol vendor for this module. - std::vector - m_old_symfiles; ///< If anyone calls Module::SetSymbolFileFileSpec() and - ///changes the symbol file, - ///< we need to keep all old symbol files around in case anyone has type - ///references to them + + /// Symbol files for this module. The last entry in the vector is the active + /// file, but we also need keep all old symbol files around in case anyone has + /// type references to them + std::vector> m_symfiles; + TypeSystemMap m_type_system_map; ///< A map of any type systems associated ///with this module PathMappingList m_source_mappings; ///< Module specific source remappings for Index: include/lldb/Core/PluginManager.h =================================================================== --- include/lldb/Core/PluginManager.h +++ include/lldb/Core/PluginManager.h @@ -329,17 +329,13 @@ GetSymbolFileCreateCallbackForPluginName(ConstString name); // SymbolVendor - static bool RegisterPlugin(ConstString name, const char *description, - SymbolVendorCreateInstance create_callback); + static bool RegisterPlugin(SymbolVendorCreateInstance create_callback); static bool UnregisterPlugin(SymbolVendorCreateInstance create_callback); static SymbolVendorCreateInstance GetSymbolVendorCreateCallbackAtIndex(uint32_t idx); - static SymbolVendorCreateInstance - GetSymbolVendorCreateCallbackForPluginName(ConstString name); - // UnwindAssembly static bool RegisterPlugin(ConstString name, const char *description, UnwindAssemblyCreateInstance create_callback); Index: include/lldb/Symbol/SymbolVendor.h =================================================================== --- include/lldb/Symbol/SymbolVendor.h +++ include/lldb/Symbol/SymbolVendor.h @@ -9,50 +9,27 @@ #ifndef liblldb_SymbolVendor_h_ #define liblldb_SymbolVendor_h_ -#include - -#include "lldb/Core/ModuleChild.h" -#include "lldb/Core/PluginInterface.h" -#include "lldb/Symbol/SourceModule.h" -#include "lldb/Symbol/TypeMap.h" -#include "lldb/lldb-private.h" -#include "llvm/ADT/DenseSet.h" +#include "lldb/lldb-forward.h" +#include namespace lldb_private { -// The symbol vendor class is designed to abstract the process of searching for -// debug information for a given module. Platforms can subclass this class and -// provide extra ways to find debug information. Examples would be a subclass -// that would allow for locating a stand alone debug file, parsing debug maps, -// or runtime data in the object files. A symbol vendor can use multiple -// sources (SymbolFile objects) to provide the information and only parse as -// deep as needed in order to provide the information that is requested. -class SymbolVendor : public ModuleChild, public PluginInterface { +/// Symbol vendors perform the task of searching for debug information which is +/// located in a standalone debug file. New symbol vendors can be registered via +/// the plugin manager. Symbol vendors return symbol file (instances of +/// SymbolFile class), which perform the actual parsing of the located debug +/// info. +class SymbolVendor { public: - static SymbolVendor *FindPlugin(const lldb::ModuleSP &module_sp, - Stream *feedback_strm); - - // Constructors and Destructors - SymbolVendor(const lldb::ModuleSP &module_sp); - - ~SymbolVendor() override; - - void AddSymbolFileRepresentation(const lldb::ObjectFileSP &objfile_sp); - - SymbolFile *GetSymbolFile() { return m_sym_file_up.get(); } - - // PluginInterface protocol - ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -protected: - std::unique_ptr m_sym_file_up; // A single symbol file. Subclasses - // can add more of these if needed. - -private: - // For SymbolVendor only - DISALLOW_COPY_AND_ASSIGN(SymbolVendor); + /// Consult the registered symbol vendor plugins and return the symbol file + /// they created. If no symbol vendor returns a valid symbol file. The default + /// behavior is to create a symbol file instance based on the Module's symbol + /// file spec (if one exists), or simply return a symbol file which reads the + /// debug information from the Module's main object file. + static std::unique_ptr FindPlugin(const lldb::ModuleSP &module_sp, + Stream *feedback_strm); + + SymbolVendor() = delete; }; } // namespace lldb_private Index: include/lldb/lldb-private-interfaces.h =================================================================== --- include/lldb/lldb-private-interfaces.h +++ include/lldb/lldb-private-interfaces.h @@ -71,7 +71,7 @@ typedef lldb::ScriptInterpreterSP (*ScriptInterpreterCreateInstance)( Debugger &debugger); typedef SymbolFile *(*SymbolFileCreateInstance)(lldb::ObjectFileSP objfile_sp); -typedef SymbolVendor *(*SymbolVendorCreateInstance)( +typedef std::unique_ptr (*SymbolVendorCreateInstance)( const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); // Module can be NULL for default system symbol vendor Index: source/Core/Module.cpp =================================================================== --- source/Core/Module.cpp +++ source/Core/Module.cpp @@ -279,7 +279,7 @@ // here because symbol files can require the module object file. So we tear // down the symbol file first, then the object file. m_sections_up.reset(); - m_symfile_up.reset(); + m_symfiles.clear(); m_objfile_sp.reset(); } @@ -1038,20 +1038,25 @@ } SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) { - if (!m_did_load_symfile.load()) { - std::lock_guard guard(m_mutex); - if (!m_did_load_symfile.load() && can_create) { - ObjectFile *obj_file = GetObjectFile(); - if (obj_file != nullptr) { - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); - m_symfile_up.reset( - SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); - m_did_load_symfile = true; - } - } - } - return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr; + if (m_did_load_symfile.load()) + return m_symfiles.back().get(); + + std::lock_guard guard(m_mutex); + if (m_did_load_symfile.load()) + return m_symfiles.back().get(); + + if (!can_create) + return nullptr; + + if (!GetObjectFile()) + return nullptr; + + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); + Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); + m_symfiles.push_back( + SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); + m_did_load_symfile = true; + return m_symfiles.back().get(); } Symtab *Module::GetSymtab() { @@ -1400,7 +1405,8 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) { if (!FileSystem::Instance().Exists(file)) return; - if (m_symfile_up) { + std::lock_guard guard(m_mutex); + if (m_did_load_symfile.load()) { // Remove any sections in the unified section list that come from the // current symbol vendor. SectionList *section_list = GetSectionList(); @@ -1454,12 +1460,8 @@ } } } - // Keep all old symbol files around in case there are any lingering type - // references in any SBValue objects that might have been handed out. - m_old_symfiles.push_back(std::move(m_symfile_up)); } m_symfile_spec = file; - m_symfile_up.reset(); m_did_load_symfile = false; } Index: source/Core/PluginManager.cpp =================================================================== --- source/Core/PluginManager.cpp +++ source/Core/PluginManager.cpp @@ -1742,15 +1742,7 @@ #pragma mark SymbolVendor -struct SymbolVendorInstance { - SymbolVendorInstance() : name(), description(), create_callback(nullptr) {} - - ConstString name; - std::string description; - SymbolVendorCreateInstance create_callback; -}; - -typedef std::vector SymbolVendorInstances; +typedef std::vector SymbolVendorInstances; static std::recursive_mutex &GetSymbolVendorMutex() { static std::recursive_mutex g_instances_mutex; @@ -1762,18 +1754,10 @@ return g_instances; } -bool PluginManager::RegisterPlugin(ConstString name, - const char *description, - SymbolVendorCreateInstance create_callback) { +bool PluginManager::RegisterPlugin(SymbolVendorCreateInstance create_callback) { if (create_callback) { - SymbolVendorInstance instance; - assert((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; std::lock_guard guard(GetSymbolVendorMutex()); - GetSymbolVendorInstances().push_back(instance); + GetSymbolVendorInstances().push_back(create_callback); } return false; } @@ -1786,7 +1770,7 @@ SymbolVendorInstances::iterator pos, end = instances.end(); for (pos = instances.begin(); pos != end; ++pos) { - if (pos->create_callback == create_callback) { + if (*pos == create_callback) { instances.erase(pos); return true; } @@ -1800,23 +1784,7 @@ std::lock_guard guard(GetSymbolVendorMutex()); SymbolVendorInstances &instances = GetSymbolVendorInstances(); if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; -} - -SymbolVendorCreateInstance -PluginManager::GetSymbolVendorCreateCallbackForPluginName( - ConstString name) { - if (name) { - std::lock_guard guard(GetSymbolVendorMutex()); - SymbolVendorInstances &instances = GetSymbolVendorInstances(); - - SymbolVendorInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++pos) { - if (name == pos->name) - return pos->create_callback; - } - } + return instances[idx]; return nullptr; } Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -176,10 +176,13 @@ SymbolFile * GetSymbolFile(bool can_create = true, lldb_private::Stream *feedback_strm = nullptr) override { - // Scope for locker - if (m_symfile_up.get() || !can_create) - return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr; + // If the symbol file has been created already, or we're not allowed to + // create it, we are done. + SymbolFile *symfile = Module::GetSymbolFile(/*can_create*/ false); + if (symfile || !can_create) + return symfile; + // Otherwise, create the file and link it up to the debug map. ModuleSP exe_module_sp(m_exe_module_wp.lock()); if (exe_module_sp) { // Now get the object file outside of a locking scope Index: source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp =================================================================== --- source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -28,6 +28,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Utility/Log.h" Index: source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h =================================================================== --- source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h +++ source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h @@ -14,31 +14,14 @@ class SymbolVendorELF : public lldb_private::SymbolVendor { public: - // Constructors and Destructors - SymbolVendorELF(const lldb::ModuleSP &module_sp); - - ~SymbolVendorELF() override; - // Static Functions static void Initialize(); static void Terminate(); - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::SymbolVendor * + static std::unique_ptr CreateInstance(const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); - - // PluginInterface protocol - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -private: - DISALLOW_COPY_AND_ASSIGN(SymbolVendorELF); }; #endif // liblldb_SymbolVendorELF_h_ Index: source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp =================================================================== --- source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -18,6 +18,7 @@ #include "lldb/Host/Host.h" #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/Target.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" @@ -25,38 +26,20 @@ using namespace lldb; using namespace lldb_private; -// SymbolVendorELF constructor -SymbolVendorELF::SymbolVendorELF(const lldb::ModuleSP &module_sp) - : SymbolVendor(module_sp) {} - -// Destructor -SymbolVendorELF::~SymbolVendorELF() {} - void SymbolVendorELF::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); + PluginManager::RegisterPlugin(CreateInstance); } void SymbolVendorELF::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } -lldb_private::ConstString SymbolVendorELF::GetPluginNameStatic() { - static ConstString g_name("ELF"); - return g_name; -} - -const char *SymbolVendorELF::GetPluginDescriptionStatic() { - return "Symbol vendor for ELF that looks for dSYM files that match " - "executables."; -} - // CreateInstance // // Platforms can register a callback to use when creating symbol vendors to // allow for complex debug information file setups, and to also allow for // finding separate debug information files. -SymbolVendor * +std::unique_ptr SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm) { if (!module_sp) @@ -111,8 +94,6 @@ // have stripped the code sections, etc. dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo); - SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp); - // Get the module unified section list and add our debug sections to // that. SectionList *module_section_list = module_sp->GetSectionList(); @@ -140,11 +121,6 @@ } } - symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); - return symbol_vendor; + return std::unique_ptr( + SymbolFile::FindPlugin(std::move(dsym_objfile_sp))); } - -// PluginInterface protocol -ConstString SymbolVendorELF::GetPluginName() { return GetPluginNameStatic(); } - -uint32_t SymbolVendorELF::GetPluginVersion() { return 1; } Index: source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h =================================================================== --- source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h +++ source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h @@ -19,26 +19,9 @@ static void Terminate(); - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::SymbolVendor * + static std::unique_ptr CreateInstance(const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); - - // Constructors and Destructors - SymbolVendorMacOSX(const lldb::ModuleSP &module_sp); - - virtual ~SymbolVendorMacOSX(); - - // PluginInterface protocol - virtual lldb_private::ConstString GetPluginName(); - - virtual uint32_t GetPluginVersion(); - -private: - DISALLOW_COPY_AND_ASSIGN(SymbolVendorMacOSX); }; #endif // liblldb_SymbolVendorMacOSX_h_ Index: source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp =================================================================== --- source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp +++ source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp @@ -14,25 +14,16 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Host/Host.h" #include "lldb/Host/XML.h" #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/Target.h" -#include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" using namespace lldb; using namespace lldb_private; -// SymbolVendorMacOSX constructor -SymbolVendorMacOSX::SymbolVendorMacOSX(const lldb::ModuleSP &module_sp) - : SymbolVendor(module_sp) {} - -// Destructor -SymbolVendorMacOSX::~SymbolVendorMacOSX() {} - static bool UUIDsMatch(Module *module, ObjectFile *ofile, lldb_private::Stream *feedback_strm) { if (module && ofile) { @@ -69,30 +60,15 @@ } void SymbolVendorMacOSX::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); + PluginManager::RegisterPlugin(CreateInstance); } void SymbolVendorMacOSX::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } -lldb_private::ConstString SymbolVendorMacOSX::GetPluginNameStatic() { - static ConstString g_name("macosx"); - return g_name; -} - -const char *SymbolVendorMacOSX::GetPluginDescriptionStatic() { - return "Symbol vendor for MacOSX that looks for dSYM files that match " - "executables."; -} - // CreateInstance -// -// Platforms can register a callback to use when creating symbol vendors to -// allow for complex debug information file setups, and to also allow for -// finding separate debug information files. -SymbolVendor * +std::unique_ptr SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm) { if (!module_sp) @@ -107,205 +83,188 @@ Timer scoped_timer(func_cat, "SymbolVendorMacOSX::CreateInstance (module = %s)", module_sp->GetFileSpec().GetPath().c_str()); - SymbolVendorMacOSX *symbol_vendor = new SymbolVendorMacOSX(module_sp); - if (symbol_vendor) { - char path[PATH_MAX]; - path[0] = '\0'; - - // Try and locate the dSYM file on Mac OS X - static Timer::Category func_cat2( - "SymbolVendorMacOSX::CreateInstance() locate dSYM"); - Timer scoped_timer2( - func_cat2, - "SymbolVendorMacOSX::CreateInstance (module = %s) locate dSYM", - module_sp->GetFileSpec().GetPath().c_str()); - - // First check to see if the module has a symbol file in mind already. If - // it does, then we MUST use that. - FileSpec dsym_fspec(module_sp->GetSymbolFileFileSpec()); - - ObjectFileSP dsym_objfile_sp; - if (!dsym_fspec) { - // No symbol file was specified in the module, lets try and find one - // ourselves. - FileSpec file_spec = obj_file->GetFileSpec(); - if (!file_spec) - file_spec = module_sp->GetFileSpec(); - - ModuleSpec module_spec(file_spec, module_sp->GetArchitecture()); - module_spec.GetUUID() = module_sp->GetUUID(); - FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); - dsym_fspec = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); - if (module_spec.GetSourceMappingList().GetSize()) - module_sp->GetSourceMappingList().Append( - module_spec.GetSourceMappingList(), true); - } - - if (dsym_fspec) { - DataBufferSP dsym_file_data_sp; - lldb::offset_t dsym_file_data_offset = 0; - dsym_objfile_sp = - ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, - FileSystem::Instance().GetByteSize(dsym_fspec), - dsym_file_data_sp, dsym_file_data_offset); - if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm)) { - // We need a XML parser if we hope to parse a plist... - if (XMLDocument::XMLEnabled()) { - char dsym_path[PATH_MAX]; - if (module_sp->GetSourceMappingList().IsEmpty() && - dsym_fspec.GetPath(dsym_path, sizeof(dsym_path))) { - lldb_private::UUID dsym_uuid = dsym_objfile_sp->GetUUID(); - if (dsym_uuid) { - std::string uuid_str = dsym_uuid.GetAsString(); - if (!uuid_str.empty()) { - char *resources = strstr(dsym_path, "/Contents/Resources/"); - if (resources) { - char dsym_uuid_plist_path[PATH_MAX]; - resources[strlen("/Contents/Resources/")] = '\0'; - snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), - "%s%s.plist", dsym_path, uuid_str.c_str()); - FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path); - if (FileSystem::Instance().Exists(dsym_uuid_plist_spec)) { - ApplePropertyList plist(dsym_uuid_plist_path); - if (plist) { - std::string DBGBuildSourcePath; - std::string DBGSourcePath; + char path[PATH_MAX]; + path[0] = '\0'; + + // Try and locate the dSYM file on Mac OS X + static Timer::Category func_cat2( + "SymbolVendorMacOSX::CreateInstance() locate dSYM"); + Timer scoped_timer2( + func_cat2, "SymbolVendorMacOSX::CreateInstance (module = %s) locate dSYM", + module_sp->GetFileSpec().GetPath().c_str()); + + // First check to see if the module has a symbol file in mind already. If + // it does, then we MUST use that. + FileSpec dsym_fspec(module_sp->GetSymbolFileFileSpec()); + + ObjectFileSP dsym_objfile_sp; + if (!dsym_fspec) { + // No symbol file was specified in the module, lets try and find one + // ourselves. + FileSpec file_spec = obj_file->GetFileSpec(); + if (!file_spec) + file_spec = module_sp->GetFileSpec(); + + ModuleSpec module_spec(file_spec, module_sp->GetArchitecture()); + module_spec.GetUUID() = module_sp->GetUUID(); + FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); + dsym_fspec = Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + if (module_spec.GetSourceMappingList().GetSize()) + module_sp->GetSourceMappingList().Append( + module_spec.GetSourceMappingList(), true); + } - // DBGSourcePathRemapping is a dictionary in the plist - // with keys which are DBGBuildSourcePath file paths and - // values which are DBGSourcePath file paths + if (!dsym_fspec) + return nullptr; - StructuredData::ObjectSP plist_sp = - plist.GetStructuredData(); - if (plist_sp.get() && plist_sp->GetAsDictionary() && - plist_sp->GetAsDictionary()->HasKey( - "DBGSourcePathRemapping") && - plist_sp->GetAsDictionary() - ->GetValueForKey("DBGSourcePathRemapping") - ->GetAsDictionary()) { + DataBufferSP dsym_file_data_sp; + lldb::offset_t dsym_file_data_offset = 0; + dsym_objfile_sp = ObjectFile::FindPlugin( + module_sp, &dsym_fspec, 0, FileSystem::Instance().GetByteSize(dsym_fspec), + dsym_file_data_sp, dsym_file_data_offset); + if (!UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm)) { + // Just create our symbol file using the current objfile as this is + // either an executable with no dSYM (that we could locate), an executable + // with a dSYM that has a UUID that doesn't match. + return std::unique_ptr( + SymbolFile::FindPlugin(obj_file->shared_from_this())); + } - // If DBGVersion 1 or DBGVersion missing, ignore DBGSourcePathRemapping. - // If DBGVersion 2, strip last two components of path remappings from - // entries to fix an issue with a specific set of - // DBGSourcePathRemapping entries that lldb worked - // with. - // If DBGVersion 3, trust & use the source path remappings as-is. - // + // We need a XML parser if we hope to parse a plist... + if (XMLDocument::XMLEnabled()) { + char dsym_path[PATH_MAX]; + if (module_sp->GetSourceMappingList().IsEmpty() && + dsym_fspec.GetPath(dsym_path, sizeof(dsym_path))) { + lldb_private::UUID dsym_uuid = dsym_objfile_sp->GetUUID(); + if (dsym_uuid) { + std::string uuid_str = dsym_uuid.GetAsString(); + if (!uuid_str.empty()) { + char *resources = strstr(dsym_path, "/Contents/Resources/"); + if (resources) { + char dsym_uuid_plist_path[PATH_MAX]; + resources[strlen("/Contents/Resources/")] = '\0'; + snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), + "%s%s.plist", dsym_path, uuid_str.c_str()); + FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path); + if (FileSystem::Instance().Exists(dsym_uuid_plist_spec)) { + ApplePropertyList plist(dsym_uuid_plist_path); + if (plist) { + std::string DBGBuildSourcePath; + std::string DBGSourcePath; + + // DBGSourcePathRemapping is a dictionary in the plist + // with keys which are DBGBuildSourcePath file paths and + // values which are DBGSourcePath file paths + + StructuredData::ObjectSP plist_sp = plist.GetStructuredData(); + if (plist_sp.get() && plist_sp->GetAsDictionary() && + plist_sp->GetAsDictionary()->HasKey( + "DBGSourcePathRemapping") && + plist_sp->GetAsDictionary() + ->GetValueForKey("DBGSourcePathRemapping") + ->GetAsDictionary()) { + + // If DBGVersion 1 or DBGVersion missing, ignore + // DBGSourcePathRemapping. If DBGVersion 2, strip last two + // components of path remappings from entries to fix an issue + // with a specific set of DBGSourcePathRemapping entries that + // lldb worked with. If DBGVersion 3, trust & use the source + // path remappings as-is. + + bool new_style_source_remapping_dictionary = false; + bool do_truncate_remapping_names = false; + std::string original_DBGSourcePath_value = DBGSourcePath; + if (plist_sp->GetAsDictionary()->HasKey("DBGVersion")) { + std::string version_string = + plist_sp->GetAsDictionary() + ->GetValueForKey("DBGVersion") + ->GetStringValue(""); + if (!version_string.empty() && isdigit(version_string[0])) { + int version_number = atoi(version_string.c_str()); + if (version_number > 1) { + new_style_source_remapping_dictionary = true; + } + if (version_number == 2) { + do_truncate_remapping_names = true; + } + } + } - bool new_style_source_remapping_dictionary = false; - bool do_truncate_remapping_names = false; - std::string original_DBGSourcePath_value = - DBGSourcePath; - if (plist_sp->GetAsDictionary()->HasKey("DBGVersion")) { - std::string version_string = - plist_sp->GetAsDictionary() - ->GetValueForKey("DBGVersion") - ->GetStringValue(""); - if (!version_string.empty() && - isdigit(version_string[0])) { - int version_number = atoi(version_string.c_str()); - if (version_number > 1) { - new_style_source_remapping_dictionary = true; - } - if (version_number == 2) { - do_truncate_remapping_names = true; - } + StructuredData::Dictionary *remappings_dict = + plist_sp->GetAsDictionary() + ->GetValueForKey("DBGSourcePathRemapping") + ->GetAsDictionary(); + remappings_dict->ForEach( + [&module_sp, new_style_source_remapping_dictionary, + original_DBGSourcePath_value, + do_truncate_remapping_names]( + ConstString key, + StructuredData::Object *object) -> bool { + if (object && object->GetAsString()) { + + // key is DBGBuildSourcePath + // object is DBGSourcePath + std::string DBGSourcePath = object->GetStringValue(); + if (!new_style_source_remapping_dictionary && + !original_DBGSourcePath_value.empty()) { + DBGSourcePath = original_DBGSourcePath_value; + } + if (DBGSourcePath[0] == '~') { + FileSpec resolved_source_path( + DBGSourcePath.c_str()); + FileSystem::Instance().Resolve( + resolved_source_path); + DBGSourcePath = resolved_source_path.GetPath(); + } + module_sp->GetSourceMappingList().Append( + key, ConstString(DBGSourcePath), true); + // With version 2 of DBGSourcePathRemapping, we + // can chop off the last two filename parts + // from the source remapping and get a more + // general source remapping that still works. + // Add this as another option in addition to + // the full source path remap. + if (do_truncate_remapping_names) { + FileSpec build_path(key.AsCString()); + FileSpec source_path(DBGSourcePath.c_str()); + build_path.RemoveLastPathComponent(); + build_path.RemoveLastPathComponent(); + source_path.RemoveLastPathComponent(); + source_path.RemoveLastPathComponent(); + module_sp->GetSourceMappingList().Append( + ConstString(build_path.GetPath().c_str()), + ConstString(source_path.GetPath().c_str()), + true); } } + return true; + }); + } - StructuredData::Dictionary *remappings_dict = - plist_sp->GetAsDictionary() - ->GetValueForKey("DBGSourcePathRemapping") - ->GetAsDictionary(); - remappings_dict->ForEach( - [&module_sp, new_style_source_remapping_dictionary, - original_DBGSourcePath_value, do_truncate_remapping_names]( - ConstString key, - StructuredData::Object *object) -> bool { - if (object && object->GetAsString()) { - - // key is DBGBuildSourcePath - // object is DBGSourcePath - std::string DBGSourcePath = - object->GetStringValue(); - if (!new_style_source_remapping_dictionary && - !original_DBGSourcePath_value.empty()) { - DBGSourcePath = original_DBGSourcePath_value; - } - if (DBGSourcePath[0] == '~') { - FileSpec resolved_source_path( - DBGSourcePath.c_str()); - FileSystem::Instance().Resolve( - resolved_source_path); - DBGSourcePath = - resolved_source_path.GetPath(); - } - module_sp->GetSourceMappingList().Append( - key, ConstString(DBGSourcePath), true); - // With version 2 of DBGSourcePathRemapping, we - // can chop off the last two filename parts - // from the source remapping and get a more - // general source remapping that still works. - // Add this as another option in addition to - // the full source path remap. - if (do_truncate_remapping_names) { - FileSpec build_path(key.AsCString()); - FileSpec source_path(DBGSourcePath.c_str()); - build_path.RemoveLastPathComponent(); - build_path.RemoveLastPathComponent(); - source_path.RemoveLastPathComponent(); - source_path.RemoveLastPathComponent(); - module_sp->GetSourceMappingList().Append( - ConstString(build_path.GetPath().c_str()), - ConstString(source_path.GetPath().c_str()), true); - } - } - return true; - }); - } - - // If we have a DBGBuildSourcePath + DBGSourcePath pair, - // append those to the source path remappings. - - plist.GetValueAsString("DBGBuildSourcePath", - DBGBuildSourcePath); - plist.GetValueAsString("DBGSourcePath", DBGSourcePath); - if (!DBGBuildSourcePath.empty() && - !DBGSourcePath.empty()) { - if (DBGSourcePath[0] == '~') { - FileSpec resolved_source_path(DBGSourcePath.c_str()); - FileSystem::Instance().Resolve(resolved_source_path); - DBGSourcePath = resolved_source_path.GetPath(); - } - module_sp->GetSourceMappingList().Append( - ConstString(DBGBuildSourcePath), - ConstString(DBGSourcePath), true); - } - } + // If we have a DBGBuildSourcePath + DBGSourcePath pair, + // append those to the source path remappings. + + plist.GetValueAsString("DBGBuildSourcePath", + DBGBuildSourcePath); + plist.GetValueAsString("DBGSourcePath", DBGSourcePath); + if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { + if (DBGSourcePath[0] == '~') { + FileSpec resolved_source_path(DBGSourcePath.c_str()); + FileSystem::Instance().Resolve(resolved_source_path); + DBGSourcePath = resolved_source_path.GetPath(); } + module_sp->GetSourceMappingList().Append( + ConstString(DBGBuildSourcePath), + ConstString(DBGSourcePath), true); } } } } } - - symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); - return symbol_vendor; } } - - // Just create our symbol vendor using the current objfile as this is - // either an executable with no dSYM (that we could locate), an executable - // with a dSYM that has a UUID that doesn't match. - symbol_vendor->AddSymbolFileRepresentation(obj_file->shared_from_this()); } - return symbol_vendor; -} -// PluginInterface protocol -ConstString SymbolVendorMacOSX::GetPluginName() { - return GetPluginNameStatic(); + return std::unique_ptr( + SymbolFile::FindPlugin(std::move(dsym_objfile_sp))); } - -uint32_t SymbolVendorMacOSX::GetPluginVersion() { return 1; } Index: source/Symbol/SymbolContext.cpp =================================================================== --- source/Symbol/SymbolContext.cpp +++ source/Symbol/SymbolContext.cpp @@ -18,6 +18,7 @@ #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/Variable.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" Index: source/Symbol/SymbolVendor.cpp =================================================================== --- source/Symbol/SymbolVendor.cpp +++ source/Symbol/SymbolVendor.cpp @@ -7,13 +7,10 @@ //===----------------------------------------------------------------------===// #include "lldb/Symbol/SymbolVendor.h" - #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Utility/Stream.h" using namespace lldb; using namespace lldb_private; @@ -23,20 +20,20 @@ // Platforms can register a callback to use when creating symbol vendors to // allow for complex debug information file setups, and to also allow for // finding separate debug information files. -SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp, - lldb_private::Stream *feedback_strm) { - std::unique_ptr instance_up; +std::unique_ptr +SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp, + lldb_private::Stream *feedback_strm) { + std::unique_ptr instance_up; SymbolVendorCreateInstance create_callback; for (size_t idx = 0; (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex( idx)) != nullptr; ++idx) { - instance_up.reset(create_callback(module_sp, feedback_strm)); + instance_up = create_callback(module_sp, feedback_strm); - if (instance_up) { - return instance_up.release(); - } + if (instance_up) + return instance_up; } // The default implementation just tries to create debug information using // the file representation for the module. @@ -51,32 +48,6 @@ } if (!sym_objfile_sp) sym_objfile_sp = module_sp->GetObjectFile()->shared_from_this(); - instance_up.reset(new SymbolVendor(module_sp)); - instance_up->AddSymbolFileRepresentation(sym_objfile_sp); - return instance_up.release(); + return std::unique_ptr( + SymbolFile::FindPlugin(std::move(sym_objfile_sp))); } - -// SymbolVendor constructor -SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp) - : ModuleChild(module_sp), m_sym_file_up() {} - -// Destructor -SymbolVendor::~SymbolVendor() {} - -// Add a representation given an object file. -void SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard guard(module_sp->GetMutex()); - if (objfile_sp) - m_sym_file_up.reset(SymbolFile::FindPlugin(objfile_sp)); - } -} - -// PluginInterface protocol -lldb_private::ConstString SymbolVendor::GetPluginName() { - static ConstString g_name("vendor-default"); - return g_name; -} - -uint32_t SymbolVendor::GetPluginVersion() { return 1; }