LLDB mainline
SymbolLocatorDebuginfod.cpp
Go to the documentation of this file.
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
10
13#include "lldb/Utility/Args.h"
15#include "lldb/Utility/Log.h"
16
17#include "llvm/Debuginfod/Debuginfod.h"
18#include "llvm/HTTP/HTTPClient.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
24
25namespace {
26
27#define LLDB_PROPERTIES_symbollocatordebuginfod
28#include "SymbolLocatorDebuginfodProperties.inc"
29
30enum {
31#define LLDB_PROPERTIES_symbollocatordebuginfod
32#include "SymbolLocatorDebuginfodPropertiesEnum.inc"
33};
34
35class PluginProperties : public Properties {
36public:
37 static llvm::StringRef GetSettingName() {
39 }
40
41 PluginProperties() {
42 m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
43 m_collection_sp->Initialize(g_symbollocatordebuginfod_properties_def);
44
45 // We need to read the default value first to read the environment variable.
46 llvm::SmallVector<llvm::StringRef> urls = llvm::getDefaultDebuginfodUrls();
47 Args arg_urls{urls};
48 m_collection_sp->SetPropertyAtIndexFromArgs(ePropertyServerURLs, arg_urls);
49
50 m_collection_sp->SetValueChangedCallback(
51 ePropertyServerURLs, [this] { ServerURLsChangedCallback(); });
52 }
53
54 Args GetDebugInfoDURLs() const {
55 Args urls;
56 m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyServerURLs, urls);
57 return urls;
58 }
59
60 llvm::Expected<std::string> GetCachePath() {
61 OptionValueString *s =
62 m_collection_sp->GetPropertyAtIndexAsOptionValueString(
63 ePropertySymbolCachePath);
64 // If we don't have a valid cache location, use the default one.
65 if (!s || !s->GetCurrentValueAsRef().size()) {
66 llvm::Expected<std::string> maybeCachePath =
67 llvm::getDefaultDebuginfodCacheDirectory();
68 if (!maybeCachePath)
69 return maybeCachePath;
70 return *maybeCachePath;
71 }
72 return s->GetCurrentValue();
73 }
74
75 std::chrono::milliseconds GetTimeout() const {
76 std::optional<uint64_t> seconds =
77 m_collection_sp->GetPropertyAtIndexAs<uint64_t>(ePropertyTimeout);
78 if (seconds && *seconds != 0) {
79 return std::chrono::duration_cast<std::chrono::milliseconds>(
80 std::chrono::seconds(*seconds));
81 } else {
82 return llvm::getDefaultDebuginfodTimeout();
83 }
84 }
85
86private:
87 void ServerURLsChangedCallback() {
88 m_server_urls = GetDebugInfoDURLs();
89 llvm::SmallVector<llvm::StringRef> dbginfod_urls;
90 for (const auto &obj : m_server_urls)
91 dbginfod_urls.push_back(obj.ref());
92 llvm::setDefaultDebuginfodUrls(dbginfod_urls);
93 }
94 // Storage for the StringRef's used within the Debuginfod library.
95 Args m_server_urls;
96};
97
98} // namespace
99
100static PluginProperties &GetGlobalPluginProperties() {
101 static PluginProperties g_settings;
102 return g_settings;
103}
104
106
108 static llvm::once_flag g_once_flag;
109
110 llvm::call_once(g_once_flag, []() {
115 llvm::HTTPClient::initialize();
116 });
117}
118
121 debugger, PluginProperties::GetSettingName())) {
122 const bool is_global_setting = true;
124 debugger, GetGlobalPluginProperties().GetValueProperties(),
125 "Properties for the Debuginfod Symbol Locator plug-in.",
126 is_global_setting);
127 }
128}
129
132 llvm::HTTPClient::cleanup();
133}
134
136 return "Debuginfod symbol locator.";
137}
138
142
143static llvm::StringRef getFileName(const ModuleSpec &module_spec,
144 std::string url_path) {
145 // Check if the URL path requests an executable file or a symbol file
146 bool is_executable = url_path.find("debuginfo") == std::string::npos;
147 if (is_executable)
148 return module_spec.GetFileSpec().GetFilename();
149 llvm::StringRef symbol_file = module_spec.GetSymbolFileSpec().GetFilename();
150 // Remove llvmcache- prefix and hash, keep origin file name
151 if (symbol_file.starts_with("llvmcache-")) {
152 size_t pos = symbol_file.rfind('-');
153 if (pos != llvm::StringRef::npos) {
154 symbol_file = symbol_file.substr(pos + 1);
155 }
156 }
157 return symbol_file;
158}
159
160static std::optional<FileSpec>
161GetFileForModule(const ModuleSpec &module_spec,
162 std::function<std::string(llvm::object::BuildID)> UrlBuilder) {
163 const UUID &module_uuid = module_spec.GetUUID();
164 // Don't bother if we don't have a valid UUID, Debuginfod isn't available,
165 // or if the 'symbols.enable-external-lookup' setting is false.
166 if (!module_uuid.IsValid() || !llvm::canUseDebuginfod() ||
167 !ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup())
168 return {};
169
170 // Grab LLDB's Debuginfod overrides from the
171 // plugin.symbol-locator.debuginfod.* settings.
172 PluginProperties &plugin_props = GetGlobalPluginProperties();
173 llvm::Expected<std::string> cache_path_or_err = plugin_props.GetCachePath();
174 // A cache location is *required*.
175 if (!cache_path_or_err) {
176 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), cache_path_or_err.takeError(),
177 "debuginfod cache path unavailable: {0}");
178 return {};
179 }
180 std::string cache_path = *cache_path_or_err;
181 llvm::SmallVector<llvm::StringRef> debuginfod_urls =
182 llvm::getDefaultDebuginfodUrls();
183 std::chrono::milliseconds timeout = plugin_props.GetTimeout();
184
185 // We're ready to ask the Debuginfod library to find our file.
186 llvm::object::BuildID build_id(module_uuid.GetBytes());
187 std::string url_path = UrlBuilder(build_id);
188 llvm::StringRef file_name = getFileName(module_spec, url_path);
189 std::string cache_file_name = llvm::toHex(build_id, true);
190 if (!file_name.empty())
191 cache_file_name += "-" + file_name.str();
192 llvm::Expected<std::string> result = llvm::getCachedOrDownloadArtifact(
193 cache_file_name, url_path, cache_path, debuginfod_urls, timeout);
194 if (result)
195 return FileSpec(*result);
196
198 auto err_message = llvm::toString(result.takeError());
200 log, "Debuginfod failed to download symbol artifact {0} with error {1}",
201 url_path, err_message);
202 return {};
203}
204
206 const ModuleSpec &module_spec) {
207 return GetFileForModule(module_spec, llvm::getDebuginfodExecutableUrlPath);
208}
209
211 const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
212 return GetFileForModule(module_spec, llvm::getDebuginfodDebuginfoUrlPath);
213}
static PluginProperties & GetGlobalPluginProperties()
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:406
#define LLDB_LOG_VERBOSE(log,...)
Definition Log.h:383
#define LLDB_PLUGIN_DEFINE(PluginName)
static PluginProperties & GetGlobalPluginProperties()
static std::optional< FileSpec > GetFileForModule(const ModuleSpec &module_spec, std::function< std::string(llvm::object::BuildID)> UrlBuilder)
static llvm::StringRef getFileName(const ModuleSpec &module_spec, std::string url_path)
A class to manage flag bits.
Definition Debugger.h:100
A file collection class.
A file utility class.
Definition FileSpec.h:57
llvm::StringRef GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:249
static ModuleListProperties & GetGlobalModuleListProperties()
FileSpec & GetFileSpec()
Definition ModuleSpec.h:57
FileSpec & GetSymbolFileSpec()
Definition ModuleSpec.h:81
llvm::StringRef GetCurrentValueAsRef() const
const char * GetCurrentValue() const
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static lldb::OptionValuePropertiesSP GetSettingForSymbolLocatorPlugin(Debugger &debugger, llvm::StringRef setting_name)
static bool UnregisterPlugin(ABICreateInstance create_callback)
static bool CreateSettingForSymbolLocatorPlugin(Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, llvm::StringRef description, bool is_global_property)
static std::optional< FileSpec > LocateExecutableSymbolFile(const ModuleSpec &module_spec, const FileSpecList &default_search_paths)
static lldb_private::SymbolLocator * CreateInstance()
static void DebuggerInitialize(Debugger &debugger)
static std::optional< ModuleSpec > LocateExecutableObjectFile(const ModuleSpec &module_spec)
Represents UUID's of various sizes.
Definition UUID.h:27
llvm::ArrayRef< uint8_t > GetBytes() const
Definition UUID.h:66
bool IsValid() const
Definition UUID.h:69
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:339