[Lldb-commits] [lldb] [lldb] Convert LocateSymbolFile into a plugin (PR #71151)

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Thu Nov 2 23:38:33 PDT 2023


https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/71151

This commit contains the initial scaffolding to convert the functionality currently implemented in LocateSymbolFile to a plugin architecture. The plugin approach allows us to easily add new ways to find plugins.

The current implementation abuses the host OS to use the DebugSymbols framework on macOS. With the plugin approach, we retain all the benefits (including the ability to compile it out) with a much cleaner level of abstraction.

To limit the scope of this patch, I've only converted LocateExecutableObjectFile. The goal is to do the same for the remaining LocateSymbolFile functions and eventually remove the file. To make reviewing easier, that will done as follow-up patches.

>From 234258ff47b075a7094b5d57bfc0a420c49c7edb Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 2 Nov 2023 23:29:20 -0700
Subject: [PATCH] [lldb] Convert LocateSymbolFile into a plugin

This commit contains the initial scaffolding to convert the
functionality currently implemented in LocateSymbolFile to a plugin
architecture. The plugin approach allows us to easily add new ways to
find plugins.

The current implementation abuses the host OS to use the DebugSymbols
framework on macOS. With the plugin approach, we retain all the benefits
(including the ability to compile it out) with a much cleaner level of
abstraction.

To limit the scope of this patch, I've only converted
LocateExecutableObjectFile. The goal is to do the same for the remaining
LocateSymbolFile functions and eventually remove the file. To make
reviewing easier, that will done as follow-up patches.
---
 lldb/include/lldb/Core/PluginManager.h        |  13 +
 lldb/include/lldb/Symbol/LocateSymbolFile.h   |   6 -
 lldb/include/lldb/Symbol/SymbolLocator.h      |  23 ++
 lldb/include/lldb/lldb-forward.h              |   1 +
 lldb/include/lldb/lldb-private-interfaces.h   |   3 +
 lldb/source/Core/DynamicLoader.cpp            |   2 +-
 lldb/source/Core/ModuleList.cpp               |   3 +-
 lldb/source/Core/PluginManager.cpp            |  53 +++
 lldb/source/Plugins/CMakeLists.txt            |   1 +
 .../Process/MacOSX-Kernel/ProcessKDP.cpp      |   2 +-
 .../Plugins/SymbolLocator/CMakeLists.txt      |   4 +
 .../SymbolLocator/DebugSymbols/CMakeLists.txt |   8 +
 .../SymbolLocatorDebugSymbols.cpp             | 328 ++++++++++++++++++
 .../DebugSymbols/SymbolLocatorDebugSymbols.h  |  45 +++
 .../SymbolLocator/Default/CMakeLists.txt      |   8 +
 .../Default/SymbolLocatorDefault.cpp          |  91 +++++
 .../Default/SymbolLocatorDefault.h            |  44 +++
 lldb/source/Symbol/LocateSymbolFile.cpp       |  23 --
 18 files changed, 626 insertions(+), 32 deletions(-)
 create mode 100644 lldb/include/lldb/Symbol/SymbolLocator.h
 create mode 100644 lldb/source/Plugins/SymbolLocator/CMakeLists.txt
 create mode 100644 lldb/source/Plugins/SymbolLocator/DebugSymbols/CMakeLists.txt
 create mode 100644 lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
 create mode 100644 lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
 create mode 100644 lldb/source/Plugins/SymbolLocator/Default/CMakeLists.txt
 create mode 100644 lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
 create mode 100644 lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h

diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h
index 24d8e28cf686ebd..feaa351b71fa2df 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 0bf65559096766a..8cd62cd3f73e706 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 000000000000000..353d93246e47f24
--- /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_SYMBOLFILELOCATOR_H
+#define LLDB_SYMBOL_SYMBOLFILELOCATOR_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 aa099d4abc3b09f..f66b2ad4362f926 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 2313723b167829a..a22a3e9792b318d 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 ce6a84e4e02269b..7751fd70dedd730 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 3650df762231d54..519145bba49559c 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 ac274112e53dff9..85e3f1cdcf12438 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 63f2c5b685a89d7..854f589f45ae0b0 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 0d1caf4d7318b72..93d8e9bf75f52ea 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 000000000000000..74abecd79694902
--- /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 000000000000000..40f9cc1d44e2d39
--- /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 000000000000000..96ae876e8088b65
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
@@ -0,0 +1,328 @@
+//===-- 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 000000000000000..ed62709b4d138b6
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h
@@ -0,0 +1,45 @@
+//===-- 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 000000000000000..6d1d300d0ca9db9
--- /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 000000000000000..cb1409e1a550bc7
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp
@@ -0,0 +1,91 @@
+//===-- 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 000000000000000..b1bb58ec298047a
--- /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 66ee7589ac60499..b23b53230a4fff0 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



More information about the lldb-commits mailing list