https://github.com/da-viper created 
https://github.com/llvm/llvm-project/pull/141773

Rough implementation of a source locator plugin for LLDB.

>From c8ca502eeed9fe026c39c0f34acdbcca7b3f7f30 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimy...@gmail.com>
Date: Wed, 28 May 2025 09:04:08 +0100
Subject: [PATCH] [lldb] Inital implementation of fetching source files used in
 modules.

Rough implementation of a source locator plugin for LLDB.
---
 lldb/cmake/modules/LLDBConfig.cmake           |  2 +-
 lldb/include/lldb/Core/PluginManager.h        | 15 ++++-
 lldb/include/lldb/Core/SourceLocator.h        | 18 +++++
 lldb/include/lldb/lldb-private-interfaces.h   |  4 ++
 lldb/source/Core/CMakeLists.txt               |  1 +
 lldb/source/Core/PluginManager.cpp            | 55 ++++++++++++++++
 lldb/source/Core/SourceLocator.cpp            |  9 +++
 lldb/source/Core/SourceManager.cpp            | 26 ++++++++
 lldb/source/Plugins/CMakeLists.txt            |  1 +
 lldb/source/Plugins/SourceFile/CMakeLists.txt |  1 +
 .../SourceFile/Debuginfod/CMakeLists.txt      |  8 +++
 .../Debuginfod/SourceLocatorDebuginfod.cpp    | 66 +++++++++++++++++++
 .../Debuginfod/SourceLocatorDebuginfod.h      | 36 ++++++++++
 13 files changed, 240 insertions(+), 2 deletions(-)
 create mode 100644 lldb/include/lldb/Core/SourceLocator.h
 create mode 100644 lldb/source/Core/SourceLocator.cpp
 create mode 100644 lldb/source/Plugins/SourceFile/CMakeLists.txt
 create mode 100644 lldb/source/Plugins/SourceFile/Debuginfod/CMakeLists.txt
 create mode 100644 
lldb/source/Plugins/SourceFile/Debuginfod/SourceLocatorDebuginfod.cpp
 create mode 100644 
lldb/source/Plugins/SourceFile/Debuginfod/SourceLocatorDebuginfod.h

diff --git a/lldb/cmake/modules/LLDBConfig.cmake 
b/lldb/cmake/modules/LLDBConfig.cmake
index cfd626c9358a1..54d1c67e1b671 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -57,7 +57,7 @@ add_optional_dependency(LLDB_ENABLE_CURSES "Enable curses 
support in LLDB" Curse
 add_optional_dependency(LLDB_ENABLE_LZMA "Enable LZMA compression support in 
LLDB" LibLZMA LIBLZMA_FOUND)
 add_optional_dependency(LLDB_ENABLE_LUA "Enable Lua scripting support in LLDB" 
LuaAndSwig LUAANDSWIG_FOUND)
 add_optional_dependency(LLDB_ENABLE_PYTHON "Enable Python scripting support in 
LLDB" PythonAndSwig PYTHONANDSWIG_FOUND)
-add_optional_dependency(LLDB_ENABLE_LIBXML2 "Enable Libxml 2 support in LLDB" 
LibXml2 LIBXML2_FOUND VERSION 2.8)
+add_optional_dependency(LLDB_ENABLE_LIBXML2 "Enable Libxml 2 support in LLDB" 
LibXml2 LIBXML2_FOUND)
 add_optional_dependency(LLDB_ENABLE_FBSDVMCORE "Enable libfbsdvmcore support 
in LLDB" FBSDVMCore FBSDVMCore_FOUND QUIET)
 
 option(LLDB_USE_ENTITLEMENTS "When codesigning, use entitlements if available" 
ON)
diff --git a/lldb/include/lldb/Core/PluginManager.h 
b/lldb/include/lldb/Core/PluginManager.h
index e2f709ecd2ff7..7008dfd26aa9e 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -362,6 +362,20 @@ class PluginManager {
   static SymbolVendorCreateInstance
   GetSymbolVendorCreateCallbackAtIndex(uint32_t idx);
 
+  // SourceLocator
+  static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
+                             SourceLocatorCreateInstance create_callback,
+                             SourceLocatorLocateSourceFile locate_source_file);
+
+  static bool UnregisterPlugin(SourceLocatorCreateInstance create_callback);
+
+  static std::optional<FileSpec> LocateSourceFile(const ModuleSpec 
&module_spec,
+                                                  const FileSpec &file_spec);
+
+  static bool CreateSettingForSourceLocatorPlugin(
+      Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+      llvm::StringRef description, bool is_global_property);
+
   // SymbolLocator
   static bool RegisterPlugin(
       llvm::StringRef name, llvm::StringRef description,
@@ -382,7 +396,6 @@ class PluginManager {
 
   static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec,
                                                StatisticsMap &map);
-
   static FileSpec
   LocateExecutableSymbolFile(const ModuleSpec &module_spec,
                              const FileSpecList &default_search_paths,
diff --git a/lldb/include/lldb/Core/SourceLocator.h 
b/lldb/include/lldb/Core/SourceLocator.h
new file mode 100644
index 0000000000000..e95dbb999dd12
--- /dev/null
+++ b/lldb/include/lldb/Core/SourceLocator.h
@@ -0,0 +1,18 @@
+//===-- SourceLocationSpec.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_UTILITY_SOURCELOCATIOR_H
+#define LLDB_UTILITY_SOURCELOCATIOR_H
+
+#include "lldb/Core/PluginInterface.h"
+
+namespace lldb_private {
+class SourceLocator : public PluginInterface {};
+} // namespace lldb_private
+
+#endif // LLDB_UTILITY_SOURCELOCATIOR_H
diff --git a/lldb/include/lldb/lldb-private-interfaces.h 
b/lldb/include/lldb/lldb-private-interfaces.h
index d366dbd1d7832..423e9989046f5 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -24,6 +24,7 @@ class Value;
 } // namespace llvm
 
 namespace lldb_private {
+class SourceLocator;
 class ScriptedInterfaceUsages;
 typedef lldb::ABISP (*ABICreateInstance)(lldb::ProcessSP process_sp,
                                          const ArchSpec &arch);
@@ -85,6 +86,9 @@ typedef lldb::RegisterTypeBuilderSP 
(*RegisterTypeBuilderCreateInstance)(
     Target &target);
 typedef lldb::ScriptInterpreterSP (*ScriptInterpreterCreateInstance)(
     Debugger &debugger);
+typedef SourceLocator *(*SourceLocatorCreateInstance)();
+typedef std::optional<FileSpec> (*SourceLocatorLocateSourceFile)(
+    const ModuleSpec &module_spec, const FileSpec &file_spec);
 typedef SymbolFile *(*SymbolFileCreateInstance)(lldb::ObjectFileSP objfile_sp);
 typedef SymbolVendor *(*SymbolVendorCreateInstance)(
     const lldb::ModuleSP &module_sp,
diff --git a/lldb/source/Core/CMakeLists.txt b/lldb/source/Core/CMakeLists.txt
index c4c442dcb2043..ce8e4f2ac0b9d 100644
--- a/lldb/source/Core/CMakeLists.txt
+++ b/lldb/source/Core/CMakeLists.txt
@@ -51,6 +51,7 @@ add_lldb_library(lldbCore NO_PLUGIN_DEPENDENCIES
   SearchFilter.cpp
   Section.cpp
   SourceLocationSpec.cpp
+        SourceLocator.cpp
   SourceManager.cpp
   StreamAsynchronousIO.cpp
   Telemetry.cpp
diff --git a/lldb/source/Core/PluginManager.cpp 
b/lldb/source/Core/PluginManager.cpp
index de815e6308838..f8f558315041b 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -1162,6 +1162,36 @@ 
PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) {
   return GetSymbolVendorInstances().GetCallbackAtIndex(idx);
 }
 
+#pragma mark SourceLocator
+
+struct SourceLocatorInstance
+    : public PluginInstance<SourceLocatorCreateInstance> {
+  SourceLocatorInstance(llvm::StringRef name, llvm::StringRef description,
+                        CallbackType create_callback,
+                        SourceLocatorLocateSourceFile locate_source_file)
+      : PluginInstance(name, description, create_callback),
+        locate_source_file(locate_source_file) {}
+  SourceLocatorLocateSourceFile locate_source_file;
+};
+typedef PluginInstances<SourceLocatorInstance> SourceLocatorInstances;
+
+static SourceLocatorInstances &GetSourceLocatorInstances() {
+  static SourceLocatorInstances g_instances;
+  return g_instances;
+}
+bool PluginManager::RegisterPlugin(
+    llvm::StringRef name, llvm::StringRef description,
+    SourceLocatorCreateInstance create_callback,
+    SourceLocatorLocateSourceFile locate_source_file) {
+  return GetSourceLocatorInstances().RegisterPlugin(
+      name, description, create_callback, locate_source_file);
+}
+
+bool PluginManager::UnregisterPlugin(
+    SourceLocatorCreateInstance create_callback) {
+  return GetSourceLocatorInstances().UnregisterPlugin(create_callback);
+}
+
 #pragma mark SymbolLocator
 
 struct SymbolLocatorInstance
@@ -1237,6 +1267,22 @@ PluginManager::LocateExecutableObjectFile(const 
ModuleSpec &module_spec,
   return {};
 }
 
+std::optional<FileSpec>
+PluginManager::LocateSourceFile(const ModuleSpec &module_spec,
+                                const FileSpec &file_spec) {
+  auto instances = GetSourceLocatorInstances().GetSnapshot();
+  for (auto &instance : instances) {
+    if (instance.locate_source_file) {
+      std::optional<FileSpec> result;
+      {
+        result = instance.locate_source_file(module_spec, file_spec);
+      }
+      if (result)
+        return *result;
+    }
+  }
+  return std::nullopt;
+}
 FileSpec PluginManager::LocateExecutableSymbolFile(
     const ModuleSpec &module_spec, const FileSpecList &default_search_paths,
     StatisticsMap &map) {
@@ -1820,6 +1866,7 @@ static constexpr llvm::StringLiteral 
kPlatformPluginName("platform");
 static constexpr llvm::StringLiteral kProcessPluginName("process");
 static constexpr llvm::StringLiteral kTracePluginName("trace");
 static constexpr llvm::StringLiteral kObjectFilePluginName("object-file");
+static constexpr llvm::StringLiteral kSourceFilePluginName("source-file");
 static constexpr llvm::StringLiteral kSymbolFilePluginName("symbol-file");
 static constexpr llvm::StringLiteral 
kSymbolLocatorPluginName("symbol-locator");
 static constexpr llvm::StringLiteral kJITLoaderPluginName("jit-loader");
@@ -1885,6 +1932,14 @@ bool PluginManager::CreateSettingForSymbolLocatorPlugin(
                                 properties_sp, description, 
is_global_property);
 }
 
+bool PluginManager::CreateSettingForSourceLocatorPlugin(
+    Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+    llvm::StringRef description, bool is_global_property) {
+  return CreateSettingForPlugin(debugger, kSymbolLocatorPluginName,
+                                "Settings for source locator plugins",
+                                properties_sp, description, 
is_global_property);
+}
+
 bool PluginManager::CreateSettingForTracePlugin(
     Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
     llvm::StringRef description, bool is_global_property) {
diff --git a/lldb/source/Core/SourceLocator.cpp 
b/lldb/source/Core/SourceLocator.cpp
new file mode 100644
index 0000000000000..47729ce111b93
--- /dev/null
+++ b/lldb/source/Core/SourceLocator.cpp
@@ -0,0 +1,9 @@
+//===-- SourceLocator.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 "lldb/Core/SourceLocator.h"
diff --git a/lldb/source/Core/SourceManager.cpp 
b/lldb/source/Core/SourceManager.cpp
index f786866a18137..48e2b30911323 100644
--- a/lldb/source/Core/SourceManager.cpp
+++ b/lldb/source/Core/SourceManager.cpp
@@ -15,6 +15,7 @@
 #include "lldb/Core/Highlighter.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
+#include "lldb/Core/PluginManager.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
@@ -542,6 +543,31 @@ void SourceManager::File::CommonInitializer(SupportFileSP 
support_file_sp,
                 *remapped, support_file_sp->GetChecksum()));
         }
       }
+      // Try Plugins
+      {
+        FileSpec file_spec = GetSupportFile()->GetSpecOnly();
+        if (!FileSystem::Instance().Exists(file_spec)) {
+
+          bool check_inlines = false;
+          SymbolContextList sc_list;
+          size_t num_matches =
+              target_sp->GetImages().ResolveSymbolContextForFilePath(
+                  file_spec.GetFilename().AsCString(), 0, check_inlines,
+                  eSymbolContextModule | eSymbolContextCompUnit, sc_list);
+          if (num_matches > 0) {
+            SymbolContext sc;
+            sc_list.GetContextAtIndex(0, sc);
+            ModuleSpec module_spec;
+            module_spec.GetUUID() = sc.module_sp->GetUUID();
+            const std::optional<FileSpec> result =
+                PluginManager::LocateSourceFile(module_spec, file_spec);
+            if (result.has_value()) {
+              SetSupportFile(std::make_shared<SupportFile>(
+                  *result, support_file_sp->GetChecksum()));
+            }
+          }
+        }
+      }
     }
   }
 
diff --git a/lldb/source/Plugins/CMakeLists.txt 
b/lldb/source/Plugins/CMakeLists.txt
index 854f589f45ae0..91a4cebdff62b 100644
--- a/lldb/source/Plugins/CMakeLists.txt
+++ b/lldb/source/Plugins/CMakeLists.txt
@@ -17,6 +17,7 @@ add_subdirectory(Process)
 add_subdirectory(REPL)
 add_subdirectory(RegisterTypeBuilder)
 add_subdirectory(ScriptInterpreter)
+add_subdirectory(SourceFile)
 add_subdirectory(StructuredData)
 add_subdirectory(SymbolFile)
 add_subdirectory(SystemRuntime)
diff --git a/lldb/source/Plugins/SourceFile/CMakeLists.txt 
b/lldb/source/Plugins/SourceFile/CMakeLists.txt
new file mode 100644
index 0000000000000..cd3bf188d43db
--- /dev/null
+++ b/lldb/source/Plugins/SourceFile/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Debuginfod)
\ No newline at end of file
diff --git a/lldb/source/Plugins/SourceFile/Debuginfod/CMakeLists.txt 
b/lldb/source/Plugins/SourceFile/Debuginfod/CMakeLists.txt
new file mode 100644
index 0000000000000..877dbdb0e330e
--- /dev/null
+++ b/lldb/source/Plugins/SourceFile/Debuginfod/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_lldb_library(lldbPluginSourceLocatorDebuginfod PLUGIN
+        SourceLocatorDebuginfod.cpp
+
+        LINK_LIBS
+        lldbCore
+        lldbHost
+        LLVMDebuginfod
+)
diff --git 
a/lldb/source/Plugins/SourceFile/Debuginfod/SourceLocatorDebuginfod.cpp 
b/lldb/source/Plugins/SourceFile/Debuginfod/SourceLocatorDebuginfod.cpp
new file mode 100644
index 0000000000000..607e2717e6c58
--- /dev/null
+++ b/lldb/source/Plugins/SourceFile/Debuginfod/SourceLocatorDebuginfod.cpp
@@ -0,0 +1,66 @@
+//
+// Created by da-viper on 26/05/25.
+//
+
+#include "SourceLocatorDebuginfod.h"
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Interpreter/OptionValueString.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include <lldb/Core/PluginManager.h>
+#include <llvm/Debuginfod/Debuginfod.h>
+#include <llvm/Debuginfod/HTTPClient.h>
+
+LLDB_PLUGIN_DEFINE(SourceLocatorDebuginfod)
+
+namespace lldb_private {
+void SourceLocatorDebuginfod::Initialize() {
+  static llvm::once_flag g_once_flag;
+
+  llvm::call_once(g_once_flag, [] {
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(), CreateInstance,
+                                  LocateSourceFile);
+    llvm::HTTPClient::initialize();
+  });
+}
+void SourceLocatorDebuginfod::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+  llvm::HTTPClient::cleanup();
+}
+
+SourceLocator *SourceLocatorDebuginfod::CreateInstance() {
+  return new SourceLocatorDebuginfod();
+}
+std::optional<FileSpec>
+SourceLocatorDebuginfod::LocateSourceFile(const ModuleSpec &module_spec,
+                                          const FileSpec &file_spec) {
+
+  const UUID &module_uuid = module_spec.GetUUID();
+  const std::string file_path = file_spec.GetPath();
+  // Don't bother if we don't have a path or valid UUID, Debuginfod isn't
+  // available, or if the 'symbols.enable-external-lookup' setting is false.
+  if (file_path.empty() || !module_uuid.IsValid() ||
+      !llvm::canUseDebuginfod() ||
+      !ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup())
+    return {};
+
+  llvm::SmallVector<llvm::StringRef> debuginfod_urls =
+      llvm::getDefaultDebuginfodUrls();
+
+  llvm::object::BuildID build_id(module_uuid.GetBytes());
+
+  llvm::Expected<std::string> result =
+      llvm::getCachedOrDownloadSource(build_id, file_path);
+  if (result)
+    return FileSpec(*result);
+
+  Log *log = GetLog(LLDBLog::Source);
+  auto err_message = llvm::toString(result.takeError());
+  LLDB_LOGV(log, "Debuginfod failed to download source file {0} with error 
{1}",
+            file_path, err_message);
+  return std::nullopt;
+}
+} // namespace lldb_private
\ No newline at end of file
diff --git 
a/lldb/source/Plugins/SourceFile/Debuginfod/SourceLocatorDebuginfod.h 
b/lldb/source/Plugins/SourceFile/Debuginfod/SourceLocatorDebuginfod.h
new file mode 100644
index 0000000000000..36e9b7c27e5f3
--- /dev/null
+++ b/lldb/source/Plugins/SourceFile/Debuginfod/SourceLocatorDebuginfod.h
@@ -0,0 +1,36 @@
+//===-- SourceLocatorDebuginfod.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_SOURCELOCATOR_DEBUGINFOD_SOURCELOCATORDEBUGINFOD_H
+#define LLDB_SOURCE_PLUGINS_SOURCELOCATOR_DEBUGINFOD_SOURCELOCATORDEBUGINFOD_H
+
+#include "lldb/Core/SourceLocator.h"
+#include <lldb/Core/Debugger.h>
+namespace lldb_private {
+
+class SourceLocatorDebuginfod : public SourceLocator {
+public:
+  explicit SourceLocatorDebuginfod() = default;
+  static void Initialize();
+  static void Terminate();
+
+  static llvm::StringRef GetPluginNameStatic() { return "debuginfod-source"; };
+  static llvm::StringRef GetPluginDescriptionStatic() {
+    return "Debuginfod source locator";
+  };
+
+  static SourceLocator *CreateInstance();
+  // static SourceLoc
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+  static std::optional<FileSpec> LocateSourceFile(const ModuleSpec 
&module_spec,
+                                                  const FileSpec &file_spec);
+};
+} // namespace lldb_private
+
+#endif // SOURCELOCATORDEBUGINFOD_H

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

Reply via email to