diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h
index 24d8e28cf686e..feaa351b71fa2 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -345,6 +345,19 @@ class PluginManager {
   static SymbolVendorCreateInstance
   GetSymbolVendorCreateCallbackAtIndex(uint32_t idx);
 
+  // SymbolLocator
+  static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
+                             SymbolLocatorCreateInstance create_callback,
+                             SymbolLocatorLocateExecutableObjectFile
+                                 locate_executable_object_file = nullptr);
+
+  static bool UnregisterPlugin(SymbolLocatorCreateInstance create_callback);
+
+  static SymbolLocatorCreateInstance
+  GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx);
+
+  static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec);
+
   // Trace
   static bool RegisterPlugin(
       llvm::StringRef name, llvm::StringRef description,
diff --git a/lldb/include/lldb/Symbol/LocateSymbolFile.h b/lldb/include/lldb/Symbol/LocateSymbolFile.h
index 0bf6555909676..8cd62cd3f73e7 100644
--- a/lldb/include/lldb/Symbol/LocateSymbolFile.h
+++ b/lldb/include/lldb/Symbol/LocateSymbolFile.h
@@ -24,12 +24,6 @@ class UUID;
 
 class Symbols {
 public:
-  // Locate the executable file given a module specification.
-  //
-  // Locating the file should happen only on the local computer or using the
-  // current computers global settings.
-  static 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
diff --git a/lldb/include/lldb/Symbol/SymbolLocator.h b/lldb/include/lldb/Symbol/SymbolLocator.h
new file mode 100644
index 0000000000000..e8376ff756880
--- /dev/null
+++ b/lldb/include/lldb/Symbol/SymbolLocator.h
@@ -0,0 +1,23 @@
+//===-- SymbolLocator.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SYMBOL_SYMBOLLOCATOR_H
+#define LLDB_SYMBOL_SYMBOLLOCATOR_H
+
+#include "lldb/Core/PluginInterface.h"
+
+namespace lldb_private {
+
+class SymbolLocator : public PluginInterface {
+public:
+  SymbolLocator() = default;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SYMBOL_SYMBOLFILELOCATOR_H
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index aa099d4abc3b0..f66b2ad4362f9 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -217,6 +217,7 @@ class SymbolContextScope;
 class SymbolContextSpecifier;
 class SymbolFile;
 class SymbolFileType;
+class SymbolLocator;
 class SymbolVendor;
 class Symtab;
 class SyntheticChildren;
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index 2313723b16782..a22a3e9792b31 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -89,6 +89,9 @@ typedef SymbolVendor *(*SymbolVendorCreateInstance)(
     const lldb::ModuleSP &module_sp,
     lldb_private::Stream
         *feedback_strm); // Module can be NULL for default system symbol vendor
+typedef SymbolLocator *(*SymbolLocatorCreateInstance)();
+typedef std::optional<ModuleSpec> (*SymbolLocatorLocateExecutableObjectFile)(
+    const ModuleSpec &module_spec);
 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 ce6a84e4e0226..7751fd70dedd7 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -221,7 +221,7 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
       module_spec.GetSymbolFileSpec() =
           Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
       ModuleSpec objfile_module_spec =
-          Symbols::LocateExecutableObjectFile(module_spec);
+          PluginManager::LocateExecutableObjectFile(module_spec);
       module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
       if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
           FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) {
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 3650df762231d..519145bba4955 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -9,6 +9,7 @@
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Interpreter/OptionValueFileSpec.h"
 #include "lldb/Interpreter/OptionValueFileSpecList.h"
@@ -906,7 +907,7 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
   // Fixup the incoming path in case the path points to a valid file, yet the
   // arch or UUID (if one was passed in) don't match.
   ModuleSpec located_binary_modulespec =
-      Symbols::LocateExecutableObjectFile(module_spec);
+      PluginManager::LocateExecutableObjectFile(module_spec);
 
   // Don't look for the file if it appears to be the same one we already
   // checked for above...
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index ac274112e53df..85e3f1cdcf124 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -1081,6 +1081,59 @@ PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) {
   return GetSymbolVendorInstances().GetCallbackAtIndex(idx);
 }
 
+#pragma mark SymbolLocator
+
+struct SymbolLocatorInstance
+    : public PluginInstance<SymbolLocatorCreateInstance> {
+  SymbolLocatorInstance(
+      llvm::StringRef name, llvm::StringRef description,
+      CallbackType create_callback,
+      SymbolLocatorLocateExecutableObjectFile locate_executable_object_file)
+      : PluginInstance<SymbolLocatorCreateInstance>(name, description,
+                                                    create_callback),
+        locate_executable_object_file(locate_executable_object_file) {}
+
+  SymbolLocatorLocateExecutableObjectFile locate_executable_object_file;
+};
+typedef PluginInstances<SymbolLocatorInstance> SymbolLocatorInstances;
+
+static SymbolLocatorInstances &GetSymbolLocatorInstances() {
+  static SymbolLocatorInstances g_instances;
+  return g_instances;
+}
+
+bool PluginManager::RegisterPlugin(
+    llvm::StringRef name, llvm::StringRef description,
+    SymbolLocatorCreateInstance create_callback,
+    SymbolLocatorLocateExecutableObjectFile locate_executable_object_file) {
+  return GetSymbolLocatorInstances().RegisterPlugin(
+      name, description, create_callback, locate_executable_object_file);
+}
+
+bool PluginManager::UnregisterPlugin(
+    SymbolLocatorCreateInstance create_callback) {
+  return GetSymbolLocatorInstances().UnregisterPlugin(create_callback);
+}
+
+SymbolLocatorCreateInstance
+PluginManager::GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx) {
+  return GetSymbolLocatorInstances().GetCallbackAtIndex(idx);
+}
+
+ModuleSpec
+PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
+  auto &instances = GetSymbolLocatorInstances().GetInstances();
+  for (auto &instance : instances) {
+    if (instance.locate_executable_object_file) {
+      std::optional<ModuleSpec> result =
+          instance.locate_executable_object_file(module_spec);
+      if (result)
+        return *result;
+    }
+  }
+  return {};
+}
+
 #pragma mark Trace
 
 struct TraceInstance
diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt
index 63f2c5b685a89..854f589f45ae0 100644
--- a/lldb/source/Plugins/CMakeLists.txt
+++ b/lldb/source/Plugins/CMakeLists.txt
@@ -20,6 +20,7 @@ add_subdirectory(ScriptInterpreter)
 add_subdirectory(StructuredData)
 add_subdirectory(SymbolFile)
 add_subdirectory(SystemRuntime)
+add_subdirectory(SymbolLocator)
 add_subdirectory(SymbolVendor)
 add_subdirectory(Trace)
 add_subdirectory(TraceExporter)
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 0d1caf4d7318b..93d8e9bf75f52 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -282,7 +282,7 @@ Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) {
                                                       search_paths);
               if (module_spec.GetSymbolFileSpec()) {
                 ModuleSpec executable_module_spec =
-                    Symbols::LocateExecutableObjectFile(module_spec);
+                    PluginManager::LocateExecutableObjectFile(module_spec);
                 if (FileSystem::Instance().Exists(
                         executable_module_spec.GetFileSpec())) {
                   module_spec.GetFileSpec() =
diff --git a/lldb/source/Plugins/SymbolLocator/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt
new file mode 100644
index 0000000000000..74abecd796949
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_subdirectory(Default)
+if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+  add_subdirectory(DebugSymbols)
+endif()
diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/DebugSymbols/CMakeLists.txt
new file mode 100644
index 0000000000000..40f9cc1d44e2d
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_lldb_library(lldbPluginSymbolLocatorDebugSymbols PLUGIN
+  SymbolLocatorDebugSymbols.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbHost
+    lldbSymbol
+  )
diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
new file mode 100644
index 0000000000000..ef19507e87e5d
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
@@ -0,0 +1,327 @@
+//===-- SymbolLocatorDebugSymbols.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolLocatorDebugSymbols.h"
+
+#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Progress.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/Timer.h"
+#include "lldb/Utility/UUID.h"
+
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ThreadPool.h"
+
+#include "Host/macosx/cfcpp/CFCBundle.h"
+#include "Host/macosx/cfcpp/CFCData.h"
+#include "Host/macosx/cfcpp/CFCReleaser.h"
+#include "Host/macosx/cfcpp/CFCString.h"
+
+#include "mach/machine.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <cstring>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <optional>
+#include <pwd.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+static CFURLRef (*g_dlsym_DBGCopyFullDSYMURLForUUID)(
+    CFUUIDRef uuid, CFURLRef exec_url) = nullptr;
+static CFDictionaryRef (*g_dlsym_DBGCopyDSYMPropertyLists)(CFURLRef dsym_url) =
+    nullptr;
+
+LLDB_PLUGIN_DEFINE(SymbolLocatorDebugSymbols)
+
+SymbolLocatorDebugSymbols::SymbolLocatorDebugSymbols() : SymbolLocator() {}
+
+void SymbolLocatorDebugSymbols::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                GetPluginDescriptionStatic(), CreateInstance,
+                                LocateExecutableObjectFile);
+}
+
+void SymbolLocatorDebugSymbols::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+llvm::StringRef SymbolLocatorDebugSymbols::GetPluginDescriptionStatic() {
+  return "DebugSymbols symbol locator.";
+}
+
+SymbolLocator *SymbolLocatorDebugSymbols::CreateInstance() {
+  return new SymbolLocatorDebugSymbols();
+}
+
+std::optional<ModuleSpec> SymbolLocatorDebugSymbols::LocateExecutableObjectFile(
+    const ModuleSpec &module_spec) {
+  Log *log = GetLog(LLDBLog::Host);
+  if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
+    LLDB_LOGF(log, "Spotlight lookup for .dSYM bundles is disabled.");
+    return {};
+  }
+  ModuleSpec return_module_spec;
+  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 {};
+  }
+
+  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 =
+                  Symbols::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;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (items_found)
+    return return_module_spec;
+
+  return {};
+}
diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
new file mode 100644
index 0000000000000..a7641b28c0dc8
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
@@ -0,0 +1,44 @@
+//===-- SymbolLocatorDebugSymbols.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H
+#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H
+
+#include "lldb/Symbol/SymbolLocator.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+class SymbolLocatorDebugSymbols : public SymbolLocator {
+public:
+  SymbolLocatorDebugSymbols();
+
+  static void Initialize();
+  static void Terminate();
+
+  static llvm::StringRef GetPluginNameStatic() { return "DebugSymbols"; }
+  static llvm::StringRef GetPluginDescriptionStatic();
+
+  static lldb_private::SymbolLocator *CreateInstance();
+
+  /// PluginInterface protocol.
+  /// \{
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+  /// \}
+
+  // Locate the executable 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<ModuleSpec>
+  LocateExecutableObjectFile(const ModuleSpec &module_spec);
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H
diff --git a/lldb/source/Plugins/SymbolLocator/Default/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/Default/CMakeLists.txt
new file mode 100644
index 0000000000000..6d1d300d0ca9d
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/Default/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_lldb_library(lldbPluginSymbolLocatorDefault PLUGIN
+  SymbolLocatorDefault.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbHost
+    lldbSymbol
+  )
diff --git a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
new file mode 100644
index 0000000000000..4ccca5ca0f6a1
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
@@ -0,0 +1,90 @@
+//===-- SymbolLocatorDefault.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolLocatorDefault.h"
+
+#include <cstring>
+#include <optional>
+
+#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Progress.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/Timer.h"
+#include "lldb/Utility/UUID.h"
+
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ThreadPool.h"
+
+// From MacOSX system header "mach/machine.h"
+typedef int cpu_type_t;
+typedef int cpu_subtype_t;
+
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(SymbolLocatorDefault)
+
+SymbolLocatorDefault::SymbolLocatorDefault() : SymbolLocator() {}
+
+void SymbolLocatorDefault::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                GetPluginDescriptionStatic(), CreateInstance,
+                                LocateExecutableObjectFile);
+}
+
+void SymbolLocatorDefault::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+llvm::StringRef SymbolLocatorDefault::GetPluginDescriptionStatic() {
+  return "Default symbol locator.";
+}
+
+SymbolLocator *SymbolLocatorDefault::CreateInstance() {
+  return new SymbolLocatorDefault();
+}
+
+std::optional<ModuleSpec> SymbolLocatorDefault::LocateExecutableObjectFile(
+    const ModuleSpec &module_spec) {
+  const FileSpec &exec_fspec = module_spec.GetFileSpec();
+  const ArchSpec *arch = module_spec.GetArchitecturePtr();
+  const UUID *uuid = module_spec.GetUUIDPtr();
+  LLDB_SCOPED_TIMERF(
+      "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
+      exec_fspec ? exec_fspec.GetFilename().AsCString("<NULL>") : "<NULL>",
+      arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
+
+  ModuleSpecList module_specs;
+  ModuleSpec matched_module_spec;
+  if (exec_fspec &&
+      ObjectFile::GetModuleSpecifications(exec_fspec, 0, 0, module_specs) &&
+      module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) {
+    ModuleSpec result;
+    result.GetFileSpec() = exec_fspec;
+    return result;
+  }
+
+  return {};
+}
diff --git a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
new file mode 100644
index 0000000000000..b1bb58ec29804
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h
@@ -0,0 +1,44 @@
+//===-- SymbolLocatorDefault.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H
+#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H
+
+#include "lldb/Symbol/SymbolLocator.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+class SymbolLocatorDefault : public SymbolLocator {
+public:
+  SymbolLocatorDefault();
+
+  static void Initialize();
+  static void Terminate();
+
+  static llvm::StringRef GetPluginNameStatic() { return "Default"; }
+  static llvm::StringRef GetPluginDescriptionStatic();
+
+  static lldb_private::SymbolLocator *CreateInstance();
+
+  /// PluginInterface protocol.
+  /// \{
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+  /// \}
+
+  // Locate the executable 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<ModuleSpec>
+  LocateExecutableObjectFile(const ModuleSpec &module_spec);
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H
diff --git a/lldb/source/Symbol/LocateSymbolFile.cpp b/lldb/source/Symbol/LocateSymbolFile.cpp
index 66ee7589ac604..b23b53230a4ff 100644
--- a/lldb/source/Symbol/LocateSymbolFile.cpp
+++ b/lldb/source/Symbol/LocateSymbolFile.cpp
@@ -234,29 +234,6 @@ static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) {
   return dsym_module_spec.GetSymbolFileSpec();
 }
 
-ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
-  ModuleSpec result;
-  const FileSpec &exec_fspec = module_spec.GetFileSpec();
-  const ArchSpec *arch = module_spec.GetArchitecturePtr();
-  const UUID *uuid = module_spec.GetUUIDPtr();
-  LLDB_SCOPED_TIMERF(
-      "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
-      exec_fspec ? exec_fspec.GetFilename().AsCString("<NULL>") : "<NULL>",
-      arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
-
-  ModuleSpecList module_specs;
-  ModuleSpec matched_module_spec;
-  if (exec_fspec &&
-      ObjectFile::GetModuleSpecifications(exec_fspec, 0, 0, module_specs) &&
-      module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) {
-    result.GetFileSpec() = exec_fspec;
-  } else {
-    LocateMacOSXFilesUsingDebugSymbols(module_spec, result);
-  }
-
-  return result;
-}
-
 // Keep "symbols.enable-external-lookup" description in sync with this function.
 
 FileSpec