LLDB mainline
SymbolLocatorDefault.cpp
Go to the documentation of this file.
1//===-- SymbolLocatorDefault.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
11#include <cstring>
12#include <optional>
13
15#include "lldb/Core/Debugger.h"
16#include "lldb/Core/Module.h"
20#include "lldb/Core/Progress.h"
21#include "lldb/Core/Section.h"
23#include "lldb/Host/Host.h"
25#include "lldb/Target/Target.h"
30#include "lldb/Utility/Log.h"
32#include "lldb/Utility/Timer.h"
33#include "lldb/Utility/UUID.h"
34
35#include "llvm/ADT/SmallSet.h"
36#include "llvm/Support/FileSystem.h"
37#include "llvm/Support/ThreadPool.h"
38
39#if defined(__FreeBSD__)
40#include <sys/sysctl.h>
41#endif
42
43// From MacOSX system header "mach/machine.h"
44typedef int cpu_type_t;
45typedef int cpu_subtype_t;
46
47using namespace lldb;
48using namespace lldb_private;
49
51
53
60
64
66 return "Default symbol locator.";
67}
68
72
74 const ModuleSpec &module_spec) {
75 const FileSpec &exec_fspec = module_spec.GetFileSpec();
76 const ArchSpec *arch = module_spec.GetArchitecturePtr();
77 const UUID *uuid = module_spec.GetUUIDPtr();
79 "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
80 exec_fspec ? exec_fspec.GetFilename().AsCString("<NULL>") : "<NULL>",
81 arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
82
83 ModuleSpec matched_module_spec;
84 if (!exec_fspec)
85 return {};
86 ModuleSpecList module_specs =
88 if (module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) {
89 ModuleSpec result;
90 result.GetFileSpec() = exec_fspec;
91 return result;
92 }
93
94 return {};
95}
96
97// Keep "symbols.enable-external-lookup" description in sync with this function.
99 const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
100
101 FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec();
102 if (symbol_file_spec.IsAbsolute() &&
103 FileSystem::Instance().Exists(symbol_file_spec))
104 return symbol_file_spec;
105
106 Progress progress(
107 "Locating external symbol file",
108 module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>"));
109
110 FileSpecList debug_file_search_paths = default_search_paths;
111
112 // Add module directory.
113 FileSpec module_file_spec = module_spec.GetFileSpec();
114 // We keep the unresolved pathname if it fails.
115 FileSystem::Instance().ResolveSymbolicLink(module_file_spec,
116 module_file_spec);
117
118 ConstString file_dir = module_file_spec.GetDirectory();
119 {
120 FileSpec file_spec(file_dir.AsCString("."));
121 FileSystem::Instance().Resolve(file_spec);
122 debug_file_search_paths.AppendIfUnique(file_spec);
123 }
124
125 if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
126
127 // Add current working directory.
128 {
129 FileSpec file_spec(".");
130 FileSystem::Instance().Resolve(file_spec);
131 debug_file_search_paths.AppendIfUnique(file_spec);
132 }
133
134#ifndef _WIN32
135#if defined(__NetBSD__)
136 // Add /usr/libdata/debug directory.
137 {
138 FileSpec file_spec("/usr/libdata/debug");
139 FileSystem::Instance().Resolve(file_spec);
140 debug_file_search_paths.AppendIfUnique(file_spec);
141 }
142#else
143 // Add /usr/lib/debug directory.
144 {
145 FileSpec file_spec("/usr/lib/debug");
146 FileSystem::Instance().Resolve(file_spec);
147 debug_file_search_paths.AppendIfUnique(file_spec);
148 }
149#if defined(__FreeBSD__)
150 // Add $LOCALBASE/lib/debug directory, where LOCALBASE is
151 // usually /usr/local, but may be adjusted by the end user.
152 {
153 int mib[2];
154 char buf[PATH_MAX];
155 size_t len = PATH_MAX;
156
157 mib[0] = CTL_USER;
158 mib[1] = USER_LOCALBASE;
159 if (::sysctl(mib, 2, buf, &len, NULL, 0) == 0) {
160 FileSpec file_spec("/lib/debug");
161 file_spec.PrependPathComponent(llvm::StringRef(buf));
162 FileSystem::Instance().Resolve(file_spec);
163 debug_file_search_paths.AppendIfUnique(file_spec);
164 }
165 }
166#endif // __FreeBSD__
167#endif
168#endif // _WIN32
169 }
170
171 std::string uuid_str;
172 const UUID &module_uuid = module_spec.GetUUID();
173 if (module_uuid.IsValid()) {
174 // Some debug files are stored in the .build-id directory like this:
175 // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
176 uuid_str = module_uuid.GetAsString("");
177 std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(),
178 ::tolower);
179 uuid_str.insert(2, 1, '/');
180 uuid_str = uuid_str + ".debug";
181 }
182
183 size_t num_directories = debug_file_search_paths.GetSize();
184 for (size_t idx = 0; idx < num_directories; ++idx) {
185 FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
186 FileSystem::Instance().Resolve(dirspec);
187 if (!FileSystem::Instance().IsDirectory(dirspec))
188 continue;
189
190 std::vector<std::string> files;
191 std::string dirname = dirspec.GetPath();
192
193 if (!uuid_str.empty())
194 files.push_back(dirname + "/.build-id/" + uuid_str);
195 if (symbol_file_spec.GetFilename()) {
196 files.push_back(dirname + "/" +
197 symbol_file_spec.GetFilename().GetCString());
198 files.push_back(dirname + "/.debug/" +
199 symbol_file_spec.GetFilename().GetCString());
200
201 // Some debug files may stored in the module directory like this:
202 // /usr/lib/debug/usr/lib/library.so.debug
203 if (!file_dir.IsEmpty())
204 files.push_back(dirname + file_dir.AsCString() + "/" +
205 symbol_file_spec.GetFilename().GetCString());
206 }
207
208 const uint32_t num_files = files.size();
209 for (size_t idx_file = 0; idx_file < num_files; ++idx_file) {
210 const std::string &filename = files[idx_file];
211 FileSpec file_spec(filename);
212 FileSystem::Instance().Resolve(file_spec);
213
214 if (llvm::sys::fs::equivalent(file_spec.GetPath(),
215 module_file_spec.GetPath()))
216 continue;
217
218 if (FileSystem::Instance().Exists(file_spec)) {
221 ModuleSpec mspec;
222 bool valid_mspec = false;
223 if (specs.GetSize() == 2) {
224 // Special case to handle both i386 and i686 from ObjectFilePECOFF
225 ModuleSpec mspec2;
226 if (specs.GetModuleSpecAtIndex(0, mspec) &&
227 specs.GetModuleSpecAtIndex(1, mspec2) &&
228 mspec.GetArchitecture().GetTriple().isCompatibleWith(
229 mspec2.GetArchitecture().GetTriple())) {
230 valid_mspec = true;
231 }
232 }
233 if (!valid_mspec) {
234 assert(specs.GetSize() <= 1 &&
235 "Symbol Vendor supports only a single architecture");
236 if (specs.GetSize() == 1) {
237 if (specs.GetModuleSpecAtIndex(0, mspec)) {
238 valid_mspec = true;
239 }
240 }
241 }
242 if (valid_mspec) {
243 // Skip the uuids check if module_uuid is invalid. For example,
244 // this happens for *.dwp files since at the moment llvm-dwp
245 // doesn't output build ids, nor does binutils dwp.
246 if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID())
247 return file_spec;
248 }
249 }
250 }
251 }
252
253 return {};
254}
255
257 Status &error,
258 bool force_lookup,
259 bool copy_executable) {
260 return false;
261}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_PLUGIN_DEFINE(PluginName)
int cpu_subtype_t
int cpu_type_t
#define LLDB_SCOPED_TIMERF(...)
Definition Timer.h:86
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:457
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition ArchSpec.cpp:548
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
bool IsEmpty() const
Test for empty string.
const char * GetCString() const
Get the string value as a C string.
A file collection class.
const FileSpec & GetFileSpecAtIndex(size_t idx) const
Get file at index.
size_t GetSize() const
Get the number of files in the file list.
bool AppendIfUnique(const FileSpec &file)
Append a FileSpec object if unique.
A file utility class.
Definition FileSpec.h:57
const ConstString & GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:250
const ConstString & GetDirectory() const
Directory string const get accessor.
Definition FileSpec.h:234
bool IsAbsolute() const
Returns true if the filespec represents an absolute path.
Definition FileSpec.cpp:518
void PrependPathComponent(llvm::StringRef component)
Definition FileSpec.cpp:440
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:374
Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst)
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
static ModuleListProperties & GetGlobalModuleListProperties()
bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const
Definition ModuleSpec.h:356
bool FindMatchingModuleSpec(const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const
Definition ModuleSpec.h:366
FileSpec & GetFileSpec()
Definition ModuleSpec.h:57
ArchSpec & GetArchitecture()
Definition ModuleSpec.h:93
FileSpec & GetSymbolFileSpec()
Definition ModuleSpec.h:81
ArchSpec * GetArchitecturePtr()
Definition ModuleSpec.h:85
static ModuleSpecList GetModuleSpecifications(const FileSpec &file, lldb::offset_t file_offset, lldb::offset_t file_size, lldb::DataExtractorSP=lldb::DataExtractorSP())
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
A Progress indicator helper class.
Definition Progress.h:60
An error handling class.
Definition Status.h:118
static llvm::StringRef GetPluginNameStatic()
static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, Status &error, bool force_lookup, bool copy_executable)
static llvm::StringRef GetPluginDescriptionStatic()
static std::optional< FileSpec > LocateExecutableSymbolFile(const ModuleSpec &module_spec, const FileSpecList &default_search_paths)
static std::optional< ModuleSpec > LocateExecutableObjectFile(const ModuleSpec &module_spec)
static lldb_private::SymbolLocator * CreateInstance()
Represents UUID's of various sizes.
Definition UUID.h:27
std::string GetAsString(llvm::StringRef separator="-") const
Definition UUID.cpp:54
bool IsValid() const
Definition UUID.h:69
A class that represents a running process on the host machine.
#define PATH_MAX