Author: Jonas Devlieghere
Date: 2023-11-03T19:48:36-07:00
New Revision: 19df9aa3f4ca4c1ab1976c980ffa7981329ea78c

URL: 
https://github.com/llvm/llvm-project/commit/19df9aa3f4ca4c1ab1976c980ffa7981329ea78c
DIFF: 
https://github.com/llvm/llvm-project/commit/19df9aa3f4ca4c1ab1976c980ffa7981329ea78c.diff

LOG: [lldb] Move LocateExecutableSymbolFile to SymbolLocator plugin (#71266)

This builds on top of the work started in c3a302d to convert
LocateSymbolFile to a SymbolLocator plugin. This commit moves
LocateExecutableSymbolFile.

Added: 
    

Modified: 
    lldb/include/lldb/Core/PluginManager.h
    lldb/include/lldb/Symbol/LocateSymbolFile.h
    lldb/include/lldb/lldb-private-interfaces.h
    lldb/source/Core/DynamicLoader.cpp
    lldb/source/Core/PluginManager.cpp
    lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
    lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
    lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
    lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
    lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
    lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
    lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
    lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
    lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
    lldb/source/Symbol/LocateSymbolFile.cpp
    lldb/test/Shell/ObjectFile/PECOFF/dwarf-gnu-debuglink-i686.yaml
    lldb/unittests/Symbol/LocateSymbolFileTest.cpp

Removed: 
    


################################################################################
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;
+              return_module_spec.GetFileSpec() = module_spec.GetFileSpec();
+              LLDB_LOGF(log, "using original binary filepath %s for UUID %s",
+                        module_spec.GetFileSpec().GetPath().c_str(),
+                        uuid->GetAsString().c_str());
+              ++items_found;
+            }
+          }
+
+          // Check if the requested image is in our shared cache.
+          if (!success) {
+            SharedCacheImageInfo image_info = 
HostInfo::GetSharedCacheImageInfo(
+                module_spec.GetFileSpec().GetPath());
+
+            // If we found it and it has the correct UUID, let's proceed with
+            // creating a module from the memory contents.
+            if (image_info.uuid && (!module_spec.GetUUID() ||
+                                    module_spec.GetUUID() == image_info.uuid)) 
{
+              success = true;
+              return_module_spec.GetFileSpec() = module_spec.GetFileSpec();
+              LLDB_LOGF(log,
+                        "using binary from shared cache for filepath %s for "
+                        "UUID %s",
+                        module_spec.GetFileSpec().GetPath().c_str(),
+                        uuid->GetAsString().c_str());
+              ++items_found;
+            }
+          }
+
+          // Use the DBGSymbolRichExecutable filepath if present
+          if (!success && uuid_dict) {
+            CFStringRef exec_cf_path =
+                static_cast<CFStringRef>(::CFDictionaryGetValue(
+                    uuid_dict, CFSTR("DBGSymbolRichExecutable")));
+            if (exec_cf_path && ::CFStringGetFileSystemRepresentation(
+                                    exec_cf_path, path, sizeof(path))) {
+              LLDB_LOGF(log, "plist bundle has exec path of %s for UUID %s",
+                        path, uuid->GetAsString().c_str());
+              ++items_found;
+              FileSpec exec_filespec(path);
+              if (path[0] == '~')
+                FileSystem::Instance().Resolve(exec_filespec);
+              if (FileSystem::Instance().Exists(exec_filespec)) {
+                success = true;
+                return_module_spec.GetFileSpec() = exec_filespec;
+              }
+            }
+          }
+
+          // Look next to the dSYM for the binary file.
+          if (!success) {
+            if (::CFURLGetFileSystemRepresentation(
+                    dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) {
+              char *dsym_extension_pos = ::strstr(path, ".dSYM");
+              if (dsym_extension_pos) {
+                *dsym_extension_pos = '\0';
+                LLDB_LOGF(log,
+                          "Looking for executable binary next to dSYM "
+                          "bundle with name with name %s",
+                          path);
+                FileSpec file_spec(path);
+                FileSystem::Instance().Resolve(file_spec);
+                ModuleSpecList module_specs;
+                ModuleSpec matched_module_spec;
+                using namespace llvm::sys::fs;
+                switch (get_file_type(file_spec.GetPath())) {
+
+                case file_type::directory_file: // Bundle directory?
+                {
+                  CFCBundle bundle(path);
+                  CFCReleaser<CFURLRef> bundle_exe_url(
+                      bundle.CopyExecutableURL());
+                  if (bundle_exe_url.get()) {
+                    if 
(::CFURLGetFileSystemRepresentation(bundle_exe_url.get(),
+                                                           true, (UInt8 *)path,
+                                                           sizeof(path) - 1)) {
+                      FileSpec bundle_exe_file_spec(path);
+                      FileSystem::Instance().Resolve(bundle_exe_file_spec);
+                      if (ObjectFile::GetModuleSpecifications(
+                              bundle_exe_file_spec, 0, 0, module_specs) &&
+                          module_specs.FindMatchingModuleSpec(
+                              module_spec, matched_module_spec))
+
+                      {
+                        ++items_found;
+                        return_module_spec.GetFileSpec() = 
bundle_exe_file_spec;
+                        LLDB_LOGF(log,
+                                  "Executable binary %s next to dSYM is "
+                                  "compatible; using",
+                                  path);
+                      }
+                    }
+                  }
+                } break;
+
+                case file_type::fifo_file:      // Forget pipes
+                case file_type::socket_file:    // We can't process socket 
files
+                case file_type::file_not_found: // File doesn't exist...
+                case file_type::status_error:
+                  break;
+
+                case file_type::type_unknown:
+                case file_type::regular_file:
+                case file_type::symlink_file:
+                case file_type::block_file:
+                case file_type::character_file:
+                  if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0,
+                                                          module_specs) &&
+                      module_specs.FindMatchingModuleSpec(module_spec,
+                                                          matched_module_spec))
+
+                  {
+                    ++items_found;
+                    return_module_spec.GetFileSpec() = file_spec;
+                    LLDB_LOGF(log,
+                              "Executable binary %s next to dSYM is "
+                              "compatible; using",
+                              path);
+                  }
+                  break;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return items_found;
+}
+
+std::optional<FileSpec> SymbolLocatorDebugSymbols::LocateExecutableSymbolFile(
+    const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
+  const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+  const ArchSpec *arch = module_spec.GetArchitecturePtr();
+  const UUID *uuid = module_spec.GetUUIDPtr();
+
+  LLDB_SCOPED_TIMERF(
+      "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)",
+      exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
+      arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
+
+  FileSpec symbol_fspec;
+  ModuleSpec dsym_module_spec;
+  // First try and find the dSYM in the same directory as the executable or in
+  // an appropriate parent directory
+  if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) {
+    // We failed to easily find the dSYM above, so use DebugSymbols
+    LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec);
+  } else {
+    dsym_module_spec.GetSymbolFileSpec() = symbol_fspec;
+  }
+
+  return dsym_module_spec.GetSymbolFileSpec();
+}

diff  --git 
a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h 
b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
index 256ac9372edd28f..72bd6de433dd706 100644
--- a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
@@ -38,6 +38,14 @@ class SymbolLocatorDebugSymbols : public SymbolLocator {
   static std::optional<ModuleSpec>
   LocateExecutableObjectFile(const ModuleSpec &module_spec);
 
+  // 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 std::optional<FileSpec>
+  LocateExecutableSymbolFile(const ModuleSpec &module_spec,
+                             const FileSpecList &default_search_paths);
+
   static std::optional<FileSpec>
   FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, const UUID *uuid,
                          const ArchSpec *arch);

diff  --git 
a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp 
b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
index 4ccca5ca0f6a1e8..831b2b1ae0c4961 100644
--- a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
+++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
@@ -49,9 +49,9 @@ LLDB_PLUGIN_DEFINE(SymbolLocatorDefault)
 SymbolLocatorDefault::SymbolLocatorDefault() : SymbolLocator() {}
 
 void SymbolLocatorDefault::Initialize() {
-  PluginManager::RegisterPlugin(GetPluginNameStatic(),
-                                GetPluginDescriptionStatic(), CreateInstance,
-                                LocateExecutableObjectFile);
+  PluginManager::RegisterPlugin(
+      GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
+      LocateExecutableObjectFile, LocateExecutableSymbolFile);
 }
 
 void SymbolLocatorDefault::Terminate() {
@@ -88,3 +88,145 @@ std::optional<ModuleSpec> 
SymbolLocatorDefault::LocateExecutableObjectFile(
 
   return {};
 }
+
+// Keep "symbols.enable-external-lookup" description in sync with this 
function.
+std::optional<FileSpec> SymbolLocatorDefault::LocateExecutableSymbolFile(
+    const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
+
+  FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec();
+  if (symbol_file_spec.IsAbsolute() &&
+      FileSystem::Instance().Exists(symbol_file_spec))
+    return symbol_file_spec;
+
+  Progress progress(llvm::formatv(
+      "Locating external symbol file for {0}",
+      module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>")));
+
+  FileSpecList debug_file_search_paths = default_search_paths;
+
+  // Add module directory.
+  FileSpec module_file_spec = module_spec.GetFileSpec();
+  // We keep the unresolved pathname if it fails.
+  FileSystem::Instance().ResolveSymbolicLink(module_file_spec,
+                                             module_file_spec);
+
+  ConstString file_dir = module_file_spec.GetDirectory();
+  {
+    FileSpec file_spec(file_dir.AsCString("."));
+    FileSystem::Instance().Resolve(file_spec);
+    debug_file_search_paths.AppendIfUnique(file_spec);
+  }
+
+  if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
+
+    // Add current working directory.
+    {
+      FileSpec file_spec(".");
+      FileSystem::Instance().Resolve(file_spec);
+      debug_file_search_paths.AppendIfUnique(file_spec);
+    }
+
+#ifndef _WIN32
+#if defined(__NetBSD__)
+    // Add /usr/libdata/debug directory.
+    {
+      FileSpec file_spec("/usr/libdata/debug");
+      FileSystem::Instance().Resolve(file_spec);
+      debug_file_search_paths.AppendIfUnique(file_spec);
+    }
+#else
+    // Add /usr/lib/debug directory.
+    {
+      FileSpec file_spec("/usr/lib/debug");
+      FileSystem::Instance().Resolve(file_spec);
+      debug_file_search_paths.AppendIfUnique(file_spec);
+    }
+#endif
+#endif // _WIN32
+  }
+
+  std::string uuid_str;
+  const UUID &module_uuid = module_spec.GetUUID();
+  if (module_uuid.IsValid()) {
+    // Some debug files are stored in the .build-id directory like this:
+    //   
/usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
+    uuid_str = module_uuid.GetAsString("");
+    std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(),
+                   ::tolower);
+    uuid_str.insert(2, 1, '/');
+    uuid_str = uuid_str + ".debug";
+  }
+
+  size_t num_directories = debug_file_search_paths.GetSize();
+  for (size_t idx = 0; idx < num_directories; ++idx) {
+    FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
+    FileSystem::Instance().Resolve(dirspec);
+    if (!FileSystem::Instance().IsDirectory(dirspec))
+      continue;
+
+    std::vector<std::string> files;
+    std::string dirname = dirspec.GetPath();
+
+    if (!uuid_str.empty())
+      files.push_back(dirname + "/.build-id/" + uuid_str);
+    if (symbol_file_spec.GetFilename()) {
+      files.push_back(dirname + "/" +
+                      symbol_file_spec.GetFilename().GetCString());
+      files.push_back(dirname + "/.debug/" +
+                      symbol_file_spec.GetFilename().GetCString());
+
+      // Some debug files may stored in the module directory like this:
+      //   /usr/lib/debug/usr/lib/library.so.debug
+      if (!file_dir.IsEmpty())
+        files.push_back(dirname + file_dir.AsCString() + "/" +
+                        symbol_file_spec.GetFilename().GetCString());
+    }
+
+    const uint32_t num_files = files.size();
+    for (size_t idx_file = 0; idx_file < num_files; ++idx_file) {
+      const std::string &filename = files[idx_file];
+      FileSpec file_spec(filename);
+      FileSystem::Instance().Resolve(file_spec);
+
+      if (llvm::sys::fs::equivalent(file_spec.GetPath(),
+                                    module_file_spec.GetPath()))
+        continue;
+
+      if (FileSystem::Instance().Exists(file_spec)) {
+        lldb_private::ModuleSpecList specs;
+        const size_t num_specs =
+            ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs);
+        ModuleSpec mspec;
+        bool valid_mspec = false;
+        if (num_specs == 2) {
+          // Special case to handle both i386 and i686 from ObjectFilePECOFF
+          ModuleSpec mspec2;
+          if (specs.GetModuleSpecAtIndex(0, mspec) &&
+              specs.GetModuleSpecAtIndex(1, mspec2) &&
+              mspec.GetArchitecture().GetTriple().isCompatibleWith(
+                  mspec2.GetArchitecture().GetTriple())) {
+            valid_mspec = true;
+          }
+        }
+        if (!valid_mspec) {
+          assert(num_specs <= 1 &&
+                 "Symbol Vendor supports only a single architecture");
+          if (num_specs == 1) {
+            if (specs.GetModuleSpecAtIndex(0, mspec)) {
+              valid_mspec = true;
+            }
+          }
+        }
+        if (valid_mspec) {
+          // Skip the uuids check if module_uuid is invalid. For example,
+          // this happens for *.dwp files since at the moment llvm-dwp
+          // doesn't output build ids, nor does binutils dwp.
+          if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID())
+            return file_spec;
+        }
+      }
+    }
+  }
+
+  return {};
+}

diff  --git a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h 
b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
index b1bb58ec298047a..99e0f0b1a78dc8c 100644
--- a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
+++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
@@ -37,6 +37,14 @@ class SymbolLocatorDefault : public SymbolLocator {
   // current computers global settings.
   static std::optional<ModuleSpec>
   LocateExecutableObjectFile(const ModuleSpec &module_spec);
+
+  // 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 std::optional<FileSpec>
+  LocateExecutableSymbolFile(const ModuleSpec &module_spec,
+                             const FileSpecList &default_search_paths);
 };
 
 } // namespace lldb_private

diff  --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp 
b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index 55a663bb1b9630d..cb61063151f1fdc 100644
--- a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -87,7 +87,7 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP 
&module_sp,
   module_spec.GetUUID() = uuid;
   FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
   FileSpec dsym_fspec =
-      Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+      PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
   if (!dsym_fspec)
     return nullptr;
 

diff  --git a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp 
b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
index 6008c582454a7ba..6fc9e40ba4a1285 100644
--- a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -130,7 +130,7 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP 
&module_sp,
       module_spec.GetUUID() = module_sp->GetUUID();
       FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
       dsym_fspec =
-          Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+          PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
       if (module_spec.GetSourceMappingList().GetSize())
         module_sp->GetSourceMappingList().Append(
             module_spec.GetSourceMappingList(), true);
@@ -149,7 +149,7 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP 
&module_sp,
                                  
FileSystem::Instance().GetByteSize(dsym_fspec),
                                  dsym_file_data_sp, dsym_file_data_offset);
       // Important to save the dSYM FileSpec so we don't call
-      // Symbols::LocateExecutableSymbolFile a second time while trying to
+      // PluginManager::LocateExecutableSymbolFile a second time while trying 
to
       // add the symbol ObjectFile to this Module.
       if (dsym_objfile_sp && !module_sp->GetSymbolFileFileSpec()) {
         module_sp->SetSymbolFileFileSpec(dsym_fspec);

diff  --git a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp 
b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
index 0f8d3108998da54..e4f4308d86c85a0 100644
--- a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
@@ -87,7 +87,7 @@ SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP 
&module_sp,
   module_spec.GetUUID() = uuid;
   FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
   FileSpec dsym_fspec =
-      Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+      PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
   if (!dsym_fspec)
     return nullptr;
 

diff  --git a/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp 
b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
index 91b10ea64535d45..22ab7b001d3a84d 100644
--- a/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
+++ b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
@@ -87,7 +87,7 @@ SymbolVendorWasm::CreateInstance(const lldb::ModuleSP 
&module_sp,
 
   FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
   FileSpec sym_fspec =
-      Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+      PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
   if (!sym_fspec)
     return nullptr;
 

diff  --git a/lldb/source/Symbol/LocateSymbolFile.cpp 
b/lldb/source/Symbol/LocateSymbolFile.cpp
index d9414ef93aa7135..17f5a090c71882d 100644
--- a/lldb/source/Symbol/LocateSymbolFile.cpp
+++ b/lldb/source/Symbol/LocateSymbolFile.cpp
@@ -35,348 +35,6 @@ typedef int cpu_subtype_t;
 using namespace lldb;
 using namespace lldb_private;
 
-#if defined(__APPLE__)
-
-// Forward declaration of method defined in source/Host/macosx/Symbols.cpp
-int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
-                                       ModuleSpec &return_module_spec);
-
-#else
-
-int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
-                                       ModuleSpec &return_module_spec) {
-  // Cannot find MacOSX files using debug symbols on non MacOSX.
-  return 0;
-}
-
-#endif
-
-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 FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) {
-  const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
-  const ArchSpec *arch = module_spec.GetArchitecturePtr();
-  const UUID *uuid = module_spec.GetUUIDPtr();
-
-  LLDB_SCOPED_TIMERF(
-      "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)",
-      exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
-      arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
-
-  FileSpec symbol_fspec;
-  ModuleSpec dsym_module_spec;
-  // First try and find the dSYM in the same directory as the executable or in
-  // an appropriate parent directory
-  if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) {
-    // We failed to easily find the dSYM above, so use DebugSymbols
-    LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec);
-  } else {
-    dsym_module_spec.GetSymbolFileSpec() = symbol_fspec;
-  }
-
-  return dsym_module_spec.GetSymbolFileSpec();
-}
-
-// Keep "symbols.enable-external-lookup" description in sync with this 
function.
-
-FileSpec
-Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec,
-                                    const FileSpecList &default_search_paths) {
-  FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec();
-  if (symbol_file_spec.IsAbsolute() &&
-      FileSystem::Instance().Exists(symbol_file_spec))
-    return symbol_file_spec;
-
-  Progress progress(llvm::formatv(
-      "Locating external symbol file for {0}",
-      module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>")));
-
-  FileSpecList debug_file_search_paths = default_search_paths;
-
-  // Add module directory.
-  FileSpec module_file_spec = module_spec.GetFileSpec();
-  // We keep the unresolved pathname if it fails.
-  FileSystem::Instance().ResolveSymbolicLink(module_file_spec,
-                                             module_file_spec);
-
-  ConstString file_dir = module_file_spec.GetDirectory();
-  {
-    FileSpec file_spec(file_dir.AsCString("."));
-    FileSystem::Instance().Resolve(file_spec);
-    debug_file_search_paths.AppendIfUnique(file_spec);
-  }
-
-  if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
-
-    // Add current working directory.
-    {
-      FileSpec file_spec(".");
-      FileSystem::Instance().Resolve(file_spec);
-      debug_file_search_paths.AppendIfUnique(file_spec);
-    }
-
-#ifndef _WIN32
-#if defined(__NetBSD__)
-    // Add /usr/libdata/debug directory.
-    {
-      FileSpec file_spec("/usr/libdata/debug");
-      FileSystem::Instance().Resolve(file_spec);
-      debug_file_search_paths.AppendIfUnique(file_spec);
-    }
-#else
-    // Add /usr/lib/debug directory.
-    {
-      FileSpec file_spec("/usr/lib/debug");
-      FileSystem::Instance().Resolve(file_spec);
-      debug_file_search_paths.AppendIfUnique(file_spec);
-    }
-#endif
-#endif // _WIN32
-  }
-
-  std::string uuid_str;
-  const UUID &module_uuid = module_spec.GetUUID();
-  if (module_uuid.IsValid()) {
-    // Some debug files are stored in the .build-id directory like this:
-    //   
/usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
-    uuid_str = module_uuid.GetAsString("");
-    std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(),
-                   ::tolower);
-    uuid_str.insert(2, 1, '/');
-    uuid_str = uuid_str + ".debug";
-  }
-
-  size_t num_directories = debug_file_search_paths.GetSize();
-  for (size_t idx = 0; idx < num_directories; ++idx) {
-    FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
-    FileSystem::Instance().Resolve(dirspec);
-    if (!FileSystem::Instance().IsDirectory(dirspec))
-      continue;
-
-    std::vector<std::string> files;
-    std::string dirname = dirspec.GetPath();
-
-    if (!uuid_str.empty())
-      files.push_back(dirname + "/.build-id/" + uuid_str);
-    if (symbol_file_spec.GetFilename()) {
-      files.push_back(dirname + "/" +
-                      symbol_file_spec.GetFilename().GetCString());
-      files.push_back(dirname + "/.debug/" +
-                      symbol_file_spec.GetFilename().GetCString());
-
-      // Some debug files may stored in the module directory like this:
-      //   /usr/lib/debug/usr/lib/library.so.debug
-      if (!file_dir.IsEmpty())
-        files.push_back(dirname + file_dir.AsCString() + "/" +
-                        symbol_file_spec.GetFilename().GetCString());
-    }
-
-    const uint32_t num_files = files.size();
-    for (size_t idx_file = 0; idx_file < num_files; ++idx_file) {
-      const std::string &filename = files[idx_file];
-      FileSpec file_spec(filename);
-      FileSystem::Instance().Resolve(file_spec);
-
-      if (llvm::sys::fs::equivalent(file_spec.GetPath(),
-                                    module_file_spec.GetPath()))
-        continue;
-
-      if (FileSystem::Instance().Exists(file_spec)) {
-        lldb_private::ModuleSpecList specs;
-        const size_t num_specs =
-            ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs);
-        ModuleSpec mspec;
-        bool valid_mspec = false;
-        if (num_specs == 2) {
-          // Special case to handle both i386 and i686 from ObjectFilePECOFF
-          ModuleSpec mspec2;
-          if (specs.GetModuleSpecAtIndex(0, mspec) &&
-              specs.GetModuleSpecAtIndex(1, mspec2) &&
-              mspec.GetArchitecture().GetTriple().isCompatibleWith(
-                  mspec2.GetArchitecture().GetTriple())) {
-            valid_mspec = true;
-          }
-        }
-        if (!valid_mspec) {
-          assert(num_specs <= 1 &&
-                 "Symbol Vendor supports only a single architecture");
-          if (num_specs == 1) {
-            if (specs.GetModuleSpecAtIndex(0, mspec)) {
-              valid_mspec = true;
-            }
-          }
-        }
-        if (valid_mspec) {
-          // Skip the uuids check if module_uuid is invalid. For example,
-          // this happens for *.dwp files since at the moment llvm-dwp
-          // doesn't output build ids, nor does binutils dwp.
-          if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID())
-            return file_spec;
-        }
-      }
-    }
-  }
-
-  return LocateExecutableSymbolFileDsym(module_spec);
-}
-
 void Symbols::DownloadSymbolFileAsync(const UUID &uuid) {
   if (!ModuleList::GetGlobalModuleListProperties().GetEnableBackgroundLookup())
     return;

diff  --git a/lldb/test/Shell/ObjectFile/PECOFF/dwarf-gnu-debuglink-i686.yaml 
b/lldb/test/Shell/ObjectFile/PECOFF/dwarf-gnu-debuglink-i686.yaml
index a28a4f396d68d77..aa07830dad4d7f6 100644
--- a/lldb/test/Shell/ObjectFile/PECOFF/dwarf-gnu-debuglink-i686.yaml
+++ b/lldb/test/Shell/ObjectFile/PECOFF/dwarf-gnu-debuglink-i686.yaml
@@ -2,10 +2,9 @@
 # gnu-debuglink section to it linking to the unstripped version of the object
 # file. The debug info shall be loaded from the gnu-debuglink reference.
 #
-# This test is added to check that Symbols::LocateExecutableSymbolFile (in
-# LocateSymbolFile.cpp) can handle ObjectFilePECOFF::GetModuleSpecifications
-# returning two 
diff erent module specs for MachineX86 -- "i386-pc-windows" and
-# "i686-pc-windows".
+# This test is added to check that LocateExecutableSymbolFile can handle
+# ObjectFilePECOFF::GetModuleSpecifications returning two 
diff erent module
+# specs for MachineX86 -- "i386-pc-windows" and "i686-pc-windows".
 
 # RUN: yaml2obj %s -o %t
 # RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t %t %t.stripped

diff  --git a/lldb/unittests/Symbol/LocateSymbolFileTest.cpp 
b/lldb/unittests/Symbol/LocateSymbolFileTest.cpp
index 268faeaf1dbbda3..d243a9df6e8a320 100644
--- a/lldb/unittests/Symbol/LocateSymbolFileTest.cpp
+++ b/lldb/unittests/Symbol/LocateSymbolFileTest.cpp
@@ -10,6 +10,7 @@
 
 #include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Symbol/LocateSymbolFile.h"
@@ -30,7 +31,7 @@ TEST_F(
   ModuleSpec module_spec;
   FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
   FileSpec symbol_file_spec =
-      Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+      PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
   EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty());
 }
 
@@ -42,6 +43,6 @@ TEST_F(SymbolsTest,
       "4A524676-B24B-4F4E-968A-551D465EBAF1.so", FileSpec::Style::native);
   FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
   FileSpec symbol_file_spec =
-      Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+      PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
   EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty());
 }


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to