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