Skip to content

Commit c43c86c

Browse files
kevinfreiKevin Freibulbazord
authored
DEBUGINFOD based DWP acquisition for LLDB (#70996)
I've plumbed the LLVM DebugInfoD client into LLDB, and added automatic downloading of DWP files to the SymbolFileDWARF.cpp plugin. If you have DEBUGINFOD_URLS set to a space delimited set of web servers, LLDB will try to use them as a last resort when searching for DWP files. If you do *not* have that environment variable set, nothing should be changed. There's also a setting, per @clayborg 's suggestion, that will override the environment variable, or can be used instead of the environment variable. The setting is why I also needed to add an API to the llvm-debuginfod library ### Test Plan: Suggestions are welcome here. I should probably have some positive and negative tests, but I wanted to get the diff up for people who have a clue what they're doing to rip it to pieces before spending too much time validating the initial implementation. --------- Co-authored-by: Kevin Frei <[email protected]> Co-authored-by: Alex Langford <[email protected]>
1 parent 6886a52 commit c43c86c

File tree

12 files changed

+298
-13
lines changed

12 files changed

+298
-13
lines changed

lldb/include/lldb/Core/PluginManager.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,8 @@ class PluginManager {
355355
nullptr,
356356
SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file =
357357
nullptr,
358-
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle = nullptr);
358+
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle = nullptr,
359+
DebuggerInitializeCallback debugger_init_callback = nullptr);
359360

360361
static bool UnregisterPlugin(SymbolLocatorCreateInstance create_callback);
361362

@@ -528,6 +529,14 @@ class PluginManager {
528529
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
529530
llvm::StringRef description, bool is_global_property);
530531

532+
static lldb::OptionValuePropertiesSP
533+
GetSettingForSymbolLocatorPlugin(Debugger &debugger,
534+
llvm::StringRef setting_name);
535+
536+
static bool CreateSettingForSymbolLocatorPlugin(
537+
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
538+
llvm::StringRef description, bool is_global_property);
539+
531540
static bool CreateSettingForTracePlugin(
532541
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
533542
llvm::StringRef description, bool is_global_property);

lldb/source/Core/CoreProperties.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ let Definition = "modulelist" in {
44
def EnableExternalLookup: Property<"enable-external-lookup", "Boolean">,
55
Global,
66
DefaultTrue,
7-
Desc<"Control the use of external tools and repositories to locate symbol files. Directories listed in target.debug-file-search-paths and directory of the executable are always checked first for separate debug info files. Then depending on this setting: On macOS, Spotlight would be also used to locate a matching .dSYM bundle based on the UUID of the executable. On NetBSD, directory /usr/libdata/debug would be also searched. On platforms other than NetBSD directory /usr/lib/debug would be also searched.">;
7+
Desc<"Control the use of external tools and repositories to locate symbol files. Directories listed in target.debug-file-search-paths and directory of the executable are always checked first for separate debug info files. Then depending on this setting: On macOS, Spotlight would be also used to locate a matching .dSYM bundle based on the UUID of the executable. On NetBSD, directory /usr/libdata/debug would be also searched. On platforms other than NetBSD directory /usr/lib/debug would be also searched. If all other methods fail there may be symbol-locator plugins that, if configured properly, will also attempt to acquire symbols. The debuginfod plugin defaults to the DEGUFINFOD_URLS environment variable which is configurable through the 'plugin.symbol-locator.debuginfod.server_urls' setting.">;
88
def EnableBackgroundLookup: Property<"enable-background-lookup", "Boolean">,
99
Global,
1010
DefaultFalse,

lldb/source/Core/PluginManager.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,9 +1091,10 @@ struct SymbolLocatorInstance
10911091
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file,
10921092
SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
10931093
SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file,
1094-
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle)
1095-
: PluginInstance<SymbolLocatorCreateInstance>(name, description,
1096-
create_callback),
1094+
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle,
1095+
DebuggerInitializeCallback debugger_init_callback)
1096+
: PluginInstance<SymbolLocatorCreateInstance>(
1097+
name, description, create_callback, debugger_init_callback),
10971098
locate_executable_object_file(locate_executable_object_file),
10981099
locate_executable_symbol_file(locate_executable_symbol_file),
10991100
download_object_symbol_file(download_object_symbol_file),
@@ -1117,11 +1118,12 @@ bool PluginManager::RegisterPlugin(
11171118
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file,
11181119
SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
11191120
SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file,
1120-
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle) {
1121+
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle,
1122+
DebuggerInitializeCallback debugger_init_callback) {
11211123
return GetSymbolLocatorInstances().RegisterPlugin(
11221124
name, description, create_callback, locate_executable_object_file,
11231125
locate_executable_symbol_file, download_object_symbol_file,
1124-
find_symbol_file_in_bundle);
1126+
find_symbol_file_in_bundle, debugger_init_callback);
11251127
}
11261128

11271129
bool PluginManager::UnregisterPlugin(
@@ -1533,6 +1535,7 @@ void PluginManager::DebuggerInitialize(Debugger &debugger) {
15331535
GetPlatformInstances().PerformDebuggerCallback(debugger);
15341536
GetProcessInstances().PerformDebuggerCallback(debugger);
15351537
GetSymbolFileInstances().PerformDebuggerCallback(debugger);
1538+
GetSymbolLocatorInstances().PerformDebuggerCallback(debugger);
15361539
GetOperatingSystemInstances().PerformDebuggerCallback(debugger);
15371540
GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger);
15381541
GetTracePluginInstances().PerformDebuggerCallback(debugger);
@@ -1660,6 +1663,7 @@ static constexpr llvm::StringLiteral kProcessPluginName("process");
16601663
static constexpr llvm::StringLiteral kTracePluginName("trace");
16611664
static constexpr llvm::StringLiteral kObjectFilePluginName("object-file");
16621665
static constexpr llvm::StringLiteral kSymbolFilePluginName("symbol-file");
1666+
static constexpr llvm::StringLiteral kSymbolLocatorPluginName("symbol-locator");
16631667
static constexpr llvm::StringLiteral kJITLoaderPluginName("jit-loader");
16641668
static constexpr llvm::StringLiteral
16651669
kStructuredDataPluginName("structured-data");
@@ -1708,6 +1712,20 @@ bool PluginManager::CreateSettingForProcessPlugin(
17081712
description, is_global_property);
17091713
}
17101714

1715+
lldb::OptionValuePropertiesSP
1716+
PluginManager::GetSettingForSymbolLocatorPlugin(Debugger &debugger,
1717+
llvm::StringRef setting_name) {
1718+
return GetSettingForPlugin(debugger, setting_name, kSymbolLocatorPluginName);
1719+
}
1720+
1721+
bool PluginManager::CreateSettingForSymbolLocatorPlugin(
1722+
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1723+
llvm::StringRef description, bool is_global_property) {
1724+
return CreateSettingForPlugin(debugger, kSymbolLocatorPluginName,
1725+
"Settings for symbol locator plug-ins",
1726+
properties_sp, description, is_global_property);
1727+
}
1728+
17111729
bool PluginManager::CreateSettingForTracePlugin(
17121730
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
17131731
llvm::StringRef description, bool is_global_property) {

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4339,6 +4339,7 @@ const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
43394339
module_spec.GetSymbolFileSpec() =
43404340
FileSpec(m_objfile_sp->GetModule()->GetFileSpec().GetPath() + ".dwp");
43414341

4342+
module_spec.GetUUID() = m_objfile_sp->GetUUID();
43424343
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
43434344
FileSpec dwp_filespec =
43444345
PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);

lldb/source/Plugins/SymbolLocator/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ add_subdirectory(Default)
22
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
33
add_subdirectory(DebugSymbols)
44
endif()
5+
add_subdirectory(Debuginfod)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
lldb_tablegen(SymbolLocatorDebuginfodProperties.inc -gen-lldb-property-defs
2+
SOURCE SymbolLocatorDebuginfodProperties.td
3+
TARGET LLDBPluginSymbolLocatorDebuginfodPropertiesGen)
4+
5+
lldb_tablegen(SymbolLocatorDebuginfodPropertiesEnum.inc -gen-lldb-property-enum-defs
6+
SOURCE SymbolLocatorDebuginfodProperties.td
7+
TARGET LLDBPluginSymbolLocatorDebuginfodPropertiesEnumGen)
8+
9+
add_lldb_library(lldbPluginSymbolLocatorDebuginfod PLUGIN
10+
SymbolLocatorDebuginfod.cpp
11+
12+
LINK_LIBS
13+
lldbCore
14+
lldbHost
15+
lldbSymbol
16+
LLVMDebuginfod
17+
)
18+
19+
add_dependencies(lldbPluginSymbolLocatorDebuginfod
20+
LLDBPluginSymbolLocatorDebuginfodPropertiesGen
21+
LLDBPluginSymbolLocatorDebuginfodPropertiesEnumGen)
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===-- SymbolLocatorDebuginfod.h -------------------------------*- C++ -*-===//
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+
#ifndef LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGINFOD_SYMBOLLOCATORDEBUGINFOD_H
10+
#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGINFOD_SYMBOLLOCATORDEBUGINFOD_H
11+
12+
#include "lldb/Core/Debugger.h"
13+
#include "lldb/Symbol/SymbolLocator.h"
14+
#include "lldb/lldb-private.h"
15+
16+
namespace lldb_private {
17+
18+
class SymbolLocatorDebuginfod : public SymbolLocator {
19+
public:
20+
SymbolLocatorDebuginfod();
21+
22+
static void Initialize();
23+
static void Terminate();
24+
static void DebuggerInitialize(Debugger &debugger);
25+
26+
static llvm::StringRef GetPluginNameStatic() { return "debuginfod"; }
27+
static llvm::StringRef GetPluginDescriptionStatic();
28+
29+
static lldb_private::SymbolLocator *CreateInstance();
30+
31+
/// PluginInterface protocol.
32+
/// \{
33+
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
34+
/// \}
35+
36+
// Locate the executable file given a module specification.
37+
//
38+
// Locating the file should happen only on the local computer or using the
39+
// current computers global settings.
40+
static std::optional<ModuleSpec>
41+
LocateExecutableObjectFile(const ModuleSpec &module_spec);
42+
43+
// Locate the symbol file given a module specification.
44+
//
45+
// Locating the file should happen only on the local computer or using the
46+
// current computers global settings.
47+
static std::optional<FileSpec>
48+
LocateExecutableSymbolFile(const ModuleSpec &module_spec,
49+
const FileSpecList &default_search_paths);
50+
};
51+
52+
} // namespace lldb_private
53+
54+
#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGINFOD_SYMBOLLOCATORDEBUGINFOD_H
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
include "../../../../include/lldb/Core/PropertiesBase.td"
2+
3+
let Definition = "symbollocatordebuginfod" in {
4+
def ServerURLs : Property<"server_urls", "Array">,
5+
ElementType<"String">,
6+
Desc<"An ordered list of Debuginfod server URLs to query for symbols. This defaults to the contents of the DEBUGINFOD_URLS environment variable.">;
7+
}

llvm/docs/ReleaseNotes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,13 @@ Changes to LLDB
262262
(SME) and Scalable Matrix Extension 2 (SME2) for both live processes and core
263263
files. For details refer to the
264264
`AArch64 Linux documentation <https://lldb.llvm.org/use/aarch64-linux.html>`_.
265+
* LLDB now supports symbol and binary acquisition automatically using the
266+
DEBUFINFOD protocol. The standard mechanism of specifying DEBUFINOD servers in
267+
the ``DEBUGINFOD_URLS`` environment variable is used by default. In addition,
268+
users can specify servers to request symbols from using the LLDB setting
269+
``plugin.symbol-locator.debuginfod.server_urls``, override or adding to the
270+
environment variable.
271+
265272

266273
* When running on AArch64 Linux, ``lldb-server`` now provides register
267274
field information for the following registers: ``cpsr``, ``fpcr``,

llvm/include/llvm/Debuginfod/Debuginfod.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ bool canUseDebuginfod();
4646
/// environment variable.
4747
SmallVector<StringRef> getDefaultDebuginfodUrls();
4848

49+
/// Sets the list of debuginfod server URLs to query. This overrides the
50+
/// environment variable DEBUGINFOD_URLS.
51+
void setDefaultDebuginfodUrls(const SmallVector<StringRef> &URLs);
52+
4953
/// Finds a default local file caching directory for the debuginfod client,
5054
/// first checking DEBUGINFOD_CACHE_PATH.
5155
Expected<std::string> getDefaultDebuginfodCacheDirectory();

0 commit comments

Comments
 (0)