1 //===-- SymbolLocatorDebuginfod.cpp ---------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "SymbolLocatorDebuginfod.h" 10 11 #include "lldb/Core/PluginManager.h" 12 #include "lldb/Utility/Args.h" 13 14 #include "llvm/Debuginfod/Debuginfod.h" 15 #include "llvm/Debuginfod/HTTPClient.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 LLDB_PLUGIN_DEFINE(SymbolLocatorDebuginfod) 21 22 namespace { 23 24 #define LLDB_PROPERTIES_symbollocatordebuginfod 25 #include "SymbolLocatorDebuginfodProperties.inc" 26 27 enum { 28 #define LLDB_PROPERTIES_symbollocatordebuginfod 29 #include "SymbolLocatorDebuginfodPropertiesEnum.inc" 30 }; 31 32 class PluginProperties : public Properties { 33 public: 34 static llvm::StringRef GetSettingName() { 35 return SymbolLocatorDebuginfod::GetPluginNameStatic(); 36 } 37 38 PluginProperties() { 39 m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); 40 m_collection_sp->Initialize(g_symbollocatordebuginfod_properties); 41 42 // We need to read the default value first to read the environment variable. 43 llvm::SmallVector<llvm::StringRef> urls = llvm::getDefaultDebuginfodUrls(); 44 Args arg_urls{urls}; 45 m_collection_sp->SetPropertyAtIndexFromArgs(ePropertyServerURLs, arg_urls); 46 47 m_collection_sp->SetValueChangedCallback( 48 ePropertyServerURLs, [this] { ServerURLsChangedCallback(); }); 49 } 50 51 Args GetDebugInfoDURLs() const { 52 Args urls; 53 m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyServerURLs, urls); 54 return urls; 55 } 56 57 private: 58 void ServerURLsChangedCallback() { 59 m_server_urls = GetDebugInfoDURLs(); 60 llvm::SmallVector<llvm::StringRef> dbginfod_urls; 61 llvm::for_each(m_server_urls, [&](const auto &obj) { 62 dbginfod_urls.push_back(obj.ref()); 63 }); 64 llvm::setDefaultDebuginfodUrls(dbginfod_urls); 65 } 66 // Storage for the StringRef's used within the Debuginfod library. 67 Args m_server_urls; 68 }; 69 70 } // namespace 71 72 static PluginProperties &GetGlobalPluginProperties() { 73 static PluginProperties g_settings; 74 return g_settings; 75 } 76 77 SymbolLocatorDebuginfod::SymbolLocatorDebuginfod() : SymbolLocator() {} 78 79 void SymbolLocatorDebuginfod::Initialize() { 80 static llvm::once_flag g_once_flag; 81 82 llvm::call_once(g_once_flag, []() { 83 PluginManager::RegisterPlugin( 84 GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, 85 LocateExecutableObjectFile, LocateExecutableSymbolFile, nullptr, 86 nullptr, SymbolLocatorDebuginfod::DebuggerInitialize); 87 llvm::HTTPClient::initialize(); 88 }); 89 } 90 91 void SymbolLocatorDebuginfod::DebuggerInitialize(Debugger &debugger) { 92 if (!PluginManager::GetSettingForSymbolLocatorPlugin( 93 debugger, PluginProperties::GetSettingName())) { 94 const bool is_global_setting = true; 95 PluginManager::CreateSettingForSymbolLocatorPlugin( 96 debugger, GetGlobalPluginProperties().GetValueProperties(), 97 "Properties for the Debuginfod Symbol Locator plug-in.", 98 is_global_setting); 99 } 100 } 101 102 void SymbolLocatorDebuginfod::Terminate() { 103 PluginManager::UnregisterPlugin(CreateInstance); 104 llvm::HTTPClient::cleanup(); 105 } 106 107 llvm::StringRef SymbolLocatorDebuginfod::GetPluginDescriptionStatic() { 108 return "Debuginfod symbol locator."; 109 } 110 111 SymbolLocator *SymbolLocatorDebuginfod::CreateInstance() { 112 return new SymbolLocatorDebuginfod(); 113 } 114 115 static std::optional<FileSpec> GetFileForModule( 116 const ModuleSpec &module_spec, 117 std::function<llvm::Expected<std::string>(llvm::object::BuildIDRef)> 118 PullFromServer) { 119 if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) 120 return {}; 121 const UUID &module_uuid = module_spec.GetUUID(); 122 if (module_uuid.IsValid() && llvm::canUseDebuginfod()) { 123 llvm::object::BuildID build_id(module_uuid.GetBytes()); 124 llvm::Expected<std::string> result = PullFromServer(build_id); 125 if (result) 126 return FileSpec(*result); 127 // An error here should be logged as a failure in the Debuginfod library, 128 // so just consume it here 129 consumeError(result.takeError()); 130 } 131 return {}; 132 } 133 134 std::optional<ModuleSpec> SymbolLocatorDebuginfod::LocateExecutableObjectFile( 135 const ModuleSpec &module_spec) { 136 return GetFileForModule(module_spec, llvm::getCachedOrDownloadExecutable); 137 } 138 139 std::optional<FileSpec> SymbolLocatorDebuginfod::LocateExecutableSymbolFile( 140 const ModuleSpec &module_spec, const FileSpecList &default_search_paths) { 141 return GetFileForModule(module_spec, llvm::getCachedOrDownloadDebuginfo); 142 } 143