llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) <details> <summary>Changes</summary> This builds on top of the work started in c3a302d to convert LocateSymbolFile to a SymbolLocator plugin. This commit moves LocateExecutableSymbolFile. --- Patch is 54.31 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/71266.diff 18 Files Affected: - (modified) lldb/include/lldb/Core/PluginManager.h (+6) - (modified) lldb/include/lldb/Symbol/LocateSymbolFile.h (-8) - (modified) lldb/include/lldb/lldb-private-interfaces.h (+2) - (modified) lldb/source/Core/DynamicLoader.cpp (+1-1) - (modified) lldb/source/Core/PluginManager.cpp (+19-1) - (modified) lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (+2-2) - (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+1-1) - (modified) lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp (+427-1) - (modified) lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h (+8) - (modified) lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp (+145-3) - (modified) lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h (+8) - (modified) lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp (+1-1) - (modified) lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp (+2-2) - (modified) lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp (+1-1) - (modified) lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp (+1-1) - (modified) lldb/source/Symbol/LocateSymbolFile.cpp (-342) - (modified) lldb/test/Shell/ObjectFile/PECOFF/dwarf-gnu-debuglink-i686.yaml (+3-4) - (modified) lldb/unittests/Symbol/LocateSymbolFileTest.cpp (+3-2) ``````````diff diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h index b69aff9e00651bb..50f0662f4bb2b95 100644 --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -351,6 +351,8 @@ class PluginManager { SymbolLocatorCreateInstance create_callback, SymbolLocatorLocateExecutableObjectFile locate_executable_object_file = nullptr, + SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file = + nullptr, SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle = nullptr); static bool UnregisterPlugin(SymbolLocatorCreateInstance create_callback); @@ -360,6 +362,10 @@ class PluginManager { static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec); + static FileSpec + LocateExecutableSymbolFile(const ModuleSpec &module_spec, + const FileSpecList &default_search_paths); + static FileSpec FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, const UUID *uuid, const ArchSpec *arch); diff --git a/lldb/include/lldb/Symbol/LocateSymbolFile.h b/lldb/include/lldb/Symbol/LocateSymbolFile.h index 03d3d9a2d440edf..3c0f069c27f8dd6 100644 --- a/lldb/include/lldb/Symbol/LocateSymbolFile.h +++ b/lldb/include/lldb/Symbol/LocateSymbolFile.h @@ -24,14 +24,6 @@ class UUID; class Symbols { public: - // Locate the symbol file given a module specification. - // - // Locating the file should happen only on the local computer or using the - // current computers global settings. - static FileSpec - LocateExecutableSymbolFile(const ModuleSpec &module_spec, - const FileSpecList &default_search_paths); - // Locate the object and symbol file given a module specification. // // Locating the file can try to download the file from a corporate build diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h index faf85833fe9f9e3..4c324a721029075 100644 --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -94,6 +94,8 @@ typedef std::optional<ModuleSpec> (*SymbolLocatorLocateExecutableObjectFile)( const ModuleSpec &module_spec); typedef std::optional<FileSpec> (*SymbolLocatorFindSymbolFileInBundle)( const FileSpec &dsym_bundle_fspec, const UUID *uuid, const ArchSpec *arch); +typedef std::optional<FileSpec> (*SymbolLocatorLocateExecutableSymbolFile)( + const ModuleSpec &module_spec, const FileSpecList &default_search_paths); typedef bool (*BreakpointHitCallback)(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp index 7751fd70dedd730..efed29da0835ebf 100644 --- a/lldb/source/Core/DynamicLoader.cpp +++ b/lldb/source/Core/DynamicLoader.cpp @@ -219,7 +219,7 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( if (!module_sp) { FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); module_spec.GetSymbolFileSpec() = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); ModuleSpec objfile_module_spec = PluginManager::LocateExecutableObjectFile(module_spec); module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec(); diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index 85c6b1d948a2d85..810e487f723de06 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -1089,13 +1089,16 @@ struct SymbolLocatorInstance llvm::StringRef name, llvm::StringRef description, CallbackType create_callback, SymbolLocatorLocateExecutableObjectFile locate_executable_object_file, + SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file, SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle) : PluginInstance<SymbolLocatorCreateInstance>(name, description, create_callback), locate_executable_object_file(locate_executable_object_file), + locate_executable_symbol_file(locate_executable_symbol_file), find_symbol_file_in_bundle(find_symbol_file_in_bundle) {} SymbolLocatorLocateExecutableObjectFile locate_executable_object_file; + SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file; SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle; }; typedef PluginInstances<SymbolLocatorInstance> SymbolLocatorInstances; @@ -1109,10 +1112,11 @@ bool PluginManager::RegisterPlugin( llvm::StringRef name, llvm::StringRef description, SymbolLocatorCreateInstance create_callback, SymbolLocatorLocateExecutableObjectFile locate_executable_object_file, + SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file, SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle) { return GetSymbolLocatorInstances().RegisterPlugin( name, description, create_callback, locate_executable_object_file, - find_symbol_file_in_bundle); + locate_executable_symbol_file, find_symbol_file_in_bundle); } bool PluginManager::UnregisterPlugin( @@ -1139,6 +1143,20 @@ PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec) { return {}; } +FileSpec PluginManager::LocateExecutableSymbolFile( + const ModuleSpec &module_spec, const FileSpecList &default_search_paths) { + auto &instances = GetSymbolLocatorInstances().GetInstances(); + for (auto &instance : instances) { + if (instance.locate_executable_symbol_file) { + std::optional<FileSpec> result = instance.locate_executable_symbol_file( + module_spec, default_search_paths); + if (result) + return *result; + } + } + return {}; +} + FileSpec PluginManager::FindSymbolFileInBundle(const FileSpec &symfile_bundle, const UUID *uuid, const ArchSpec *arch) { diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 93d8e9bf75f52ea..9af544b31d89649 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -278,8 +278,8 @@ Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) { FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); module_spec.GetSymbolFileSpec() = - Symbols::LocateExecutableSymbolFile(module_spec, - search_paths); + PluginManager::LocateExecutableSymbolFile(module_spec, + search_paths); if (module_spec.GetSymbolFileSpec()) { ModuleSpec executable_module_spec = PluginManager::LocateExecutableObjectFile(module_spec); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 63b2c3a0c883097..122ab57e06ad9d7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4329,7 +4329,7 @@ const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() { FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dwp_filespec = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); if (FileSystem::Instance().Exists(dwp_filespec)) { DataBufferSP dwp_file_data_sp; lldb::offset_t dwp_file_data_offset = 0; diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp index 217080bfd3ef3b1..2c57ef8b6a54ea0 100644 --- a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp +++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp @@ -65,7 +65,8 @@ SymbolLocatorDebugSymbols::SymbolLocatorDebugSymbols() : SymbolLocator() {} void SymbolLocatorDebugSymbols::Initialize() { PluginManager::RegisterPlugin( GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, - LocateExecutableObjectFile, FindSymbolFileInBundle); + LocateExecutableObjectFile, LocateExecutableSymbolFile, + FindSymbolFileInBundle); } void SymbolLocatorDebugSymbols::Terminate() { @@ -363,3 +364,428 @@ std::optional<FileSpec> SymbolLocatorDebugSymbols::FindSymbolFileInBundle( return {}; } + +static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec, + const ArchSpec *arch, + const lldb_private::UUID *uuid) { + ModuleSpecList module_specs; + if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) { + ModuleSpec spec; + for (size_t i = 0; i < module_specs.GetSize(); ++i) { + bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); + UNUSED_IF_ASSERT_DISABLED(got_spec); + assert(got_spec); + if ((uuid == nullptr || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && + (arch == nullptr || + (spec.GetArchitecturePtr() && + spec.GetArchitecture().IsCompatibleMatch(*arch)))) { + return true; + } + } + } + return false; +} + +// Given a binary exec_fspec, and a ModuleSpec with an architecture/uuid, +// return true if there is a matching dSYM bundle next to the exec_fspec, +// and return that value in dsym_fspec. +// If there is a .dSYM.yaa compressed archive next to the exec_fspec, +// call through Symbols::DownloadObjectAndSymbolFile to download the +// expanded/uncompressed dSYM and return that filepath in dsym_fspec. +static bool LookForDsymNextToExecutablePath(const ModuleSpec &mod_spec, + const FileSpec &exec_fspec, + FileSpec &dsym_fspec) { + ConstString filename = exec_fspec.GetFilename(); + FileSpec dsym_directory = exec_fspec; + dsym_directory.RemoveLastPathComponent(); + + std::string dsym_filename = filename.AsCString(); + dsym_filename += ".dSYM"; + dsym_directory.AppendPathComponent(dsym_filename); + dsym_directory.AppendPathComponent("Contents"); + dsym_directory.AppendPathComponent("Resources"); + dsym_directory.AppendPathComponent("DWARF"); + + if (FileSystem::Instance().Exists(dsym_directory)) { + + // See if the binary name exists in the dSYM DWARF + // subdir. + dsym_fspec = dsym_directory; + dsym_fspec.AppendPathComponent(filename.AsCString()); + if (FileSystem::Instance().Exists(dsym_fspec) && + FileAtPathContainsArchAndUUID(dsym_fspec, mod_spec.GetArchitecturePtr(), + mod_spec.GetUUIDPtr())) { + return true; + } + + // See if we have "../CF.framework" - so we'll look for + // CF.framework.dSYM/Contents/Resources/DWARF/CF + // We need to drop the last suffix after '.' to match + // 'CF' in the DWARF subdir. + std::string binary_name(filename.AsCString()); + auto last_dot = binary_name.find_last_of('.'); + if (last_dot != std::string::npos) { + binary_name.erase(last_dot); + dsym_fspec = dsym_directory; + dsym_fspec.AppendPathComponent(binary_name); + if (FileSystem::Instance().Exists(dsym_fspec) && + FileAtPathContainsArchAndUUID(dsym_fspec, + mod_spec.GetArchitecturePtr(), + mod_spec.GetUUIDPtr())) { + return true; + } + } + } + + // See if we have a .dSYM.yaa next to this executable path. + FileSpec dsym_yaa_fspec = exec_fspec; + dsym_yaa_fspec.RemoveLastPathComponent(); + std::string dsym_yaa_filename = filename.AsCString(); + dsym_yaa_filename += ".dSYM.yaa"; + dsym_yaa_fspec.AppendPathComponent(dsym_yaa_filename); + + if (FileSystem::Instance().Exists(dsym_yaa_fspec)) { + ModuleSpec mutable_mod_spec = mod_spec; + Status error; + if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, error, true) && + FileSystem::Instance().Exists(mutable_mod_spec.GetSymbolFileSpec())) { + dsym_fspec = mutable_mod_spec.GetSymbolFileSpec(); + return true; + } + } + + return false; +} + +// Given a ModuleSpec with a FileSpec and optionally uuid/architecture +// filled in, look for a .dSYM bundle next to that binary. Returns true +// if a .dSYM bundle is found, and that path is returned in the dsym_fspec +// FileSpec. +// +// This routine looks a few directory layers above the given exec_path - +// exec_path might be /System/Library/Frameworks/CF.framework/CF and the +// dSYM might be /System/Library/Frameworks/CF.framework.dSYM. +// +// If there is a .dSYM.yaa compressed archive found next to the binary, +// we'll call DownloadObjectAndSymbolFile to expand it into a plain .dSYM +static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, + FileSpec &dsym_fspec) { + Log *log = GetLog(LLDBLog::Host); + const FileSpec &exec_fspec = module_spec.GetFileSpec(); + if (exec_fspec) { + if (::LookForDsymNextToExecutablePath(module_spec, exec_fspec, + dsym_fspec)) { + if (log) { + LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); + } + return true; + } else { + FileSpec parent_dirs = exec_fspec; + + // Remove the binary name from the FileSpec + parent_dirs.RemoveLastPathComponent(); + + // Add a ".dSYM" name to each directory component of the path, + // stripping off components. e.g. we may have a binary like + // /S/L/F/Foundation.framework/Versions/A/Foundation and + // /S/L/F/Foundation.framework.dSYM + // + // so we'll need to start with + // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the + // "A", and if that doesn't exist, strip off the "A" and try it again + // with "Versions", etc., until we find a dSYM bundle or we've + // stripped off enough path components that there's no need to + // continue. + + for (int i = 0; i < 4; i++) { + // Does this part of the path have a "." character - could it be a + // bundle's top level directory? + const char *fn = parent_dirs.GetFilename().AsCString(); + if (fn == nullptr) + break; + if (::strchr(fn, '.') != nullptr) { + if (::LookForDsymNextToExecutablePath(module_spec, parent_dirs, + dsym_fspec)) { + if (log) { + LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); + } + return true; + } + } + parent_dirs.RemoveLastPathComponent(); + } + } + } + dsym_fspec.Clear(); + return false; +} + +static int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, + ModuleSpec &return_module_spec) { + Log *log = GetLog(LLDBLog::Host); + if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { + LLDB_LOGF(log, "Spotlight lookup for .dSYM bundles is disabled."); + return 0; + } + + return_module_spec = module_spec; + return_module_spec.GetFileSpec().Clear(); + return_module_spec.GetSymbolFileSpec().Clear(); + + const UUID *uuid = module_spec.GetUUIDPtr(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + + int items_found = 0; + + if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr || + g_dlsym_DBGCopyDSYMPropertyLists == nullptr) { + void *handle = dlopen( + "/System/Library/PrivateFrameworks/DebugSymbols.framework/DebugSymbols", + RTLD_LAZY | RTLD_LOCAL); + if (handle) { + g_dlsym_DBGCopyFullDSYMURLForUUID = + (CFURLRef(*)(CFUUIDRef, CFURLRef))dlsym(handle, + "DBGCopyFullDSYMURLForUUID"); + g_dlsym_DBGCopyDSYMPropertyLists = (CFDictionaryRef(*)(CFURLRef))dlsym( + handle, "DBGCopyDSYMPropertyLists"); + } + } + + if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr || + g_dlsym_DBGCopyDSYMPropertyLists == nullptr) { + return items_found; + } + + if (uuid && uuid->IsValid()) { + // Try and locate the dSYM file using DebugSymbols first + llvm::ArrayRef<uint8_t> module_uuid = uuid->GetBytes(); + if (module_uuid.size() == 16) { + CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes( + NULL, module_uuid[0], module_uuid[1], module_uuid[2], module_uuid[3], + module_uuid[4], module_uuid[5], module_uuid[6], module_uuid[7], + module_uuid[8], module_uuid[9], module_uuid[10], module_uuid[11], + module_uuid[12], module_uuid[13], module_uuid[14], module_uuid[15])); + + if (module_uuid_ref.get()) { + CFCReleaser<CFURLRef> exec_url; + const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); + if (exec_fspec) { + char exec_cf_path[PATH_MAX]; + if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path))) + exec_url.reset(::CFURLCreateFromFileSystemRepresentation( + NULL, (const UInt8 *)exec_cf_path, strlen(exec_cf_path), + FALSE)); + } + + CFCReleaser<CFURLRef> dsym_url(g_dlsym_DBGCopyFullDSYMURLForUUID( + module_uuid_ref.get(), exec_url.get())); + char path[PATH_MAX]; + + if (dsym_url.get()) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + LLDB_LOGF(log, + "DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for the dSYM", + path, uuid->GetAsString().c_str()); + FileSpec dsym_filespec(path); + if (path[0] == '~') + FileSystem::Instance().Resolve(dsym_filespec); + + if (FileSystem::Instance().IsDirectory(dsym_filespec)) { + dsym_filespec = PluginManager::FindSymbolFileInBundle( + dsym_filespec, uuid, arch); + ++items_found; + } else { + ++items_found; + } + return_module_spec.GetSymbolFileSpec() = dsym_filespec; + } + + bool success = false; + if (log) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + LLDB_LOGF(log, + "DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for an exec file", + path, uuid->GetAsString().c_str()); + } + } + + CFCReleaser<CFDictionaryRef> dict( + g_dlsym_DBGCopyDSYMPropertyLists(dsym_url.get())); + CFDictionaryRef uuid_dict = NULL; + if (dict.get()) { + CFCString uuid_cfstr(uuid->GetAsString().c_str()); + uuid_dict = static_cast<CFDictionaryRef>( + ::CFDictionaryGetValue(dict.get(), uuid_cfstr.get())); + } + + // Check to see if we have the file on the local filesystem. + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + ModuleSpec exe_spec; + exe_spec.GetFileSpec() = module_spec.GetFileSpec(); + exe_spec.GetUUID() = module_spec.GetUUID(); + ModuleSP module_sp; + module_sp.reset(new Module(exe_spec)); + if (module_sp && module_sp->GetObjectFile() && + module_sp->MatchesModuleSpec(exe_spec)) { + success = true; + ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/71266 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits