LLDB mainline
ModuleSpec.h
Go to the documentation of this file.
1//===-- ModuleSpec.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_CORE_MODULESPEC_H
10#define LLDB_CORE_MODULESPEC_H
11
19#include "lldb/Utility/Stream.h"
20#include "lldb/Utility/UUID.h"
21#include "lldb/lldb-forward.h"
22
23#include "llvm/Support/Chrono.h"
24
25#include <memory>
26#include <mutex>
27#include <vector>
28
29namespace lldb_private {
30
32public:
33 ModuleSpec() = default;
34
35 /// If the \c extractor_sp argument is passed, its contents will be used
36 /// as the module contents instead of trying to read them from
37 /// \c file_spec .
38 ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID(),
40 : m_file(file_spec), m_uuid(uuid), m_object_offset(0),
41 m_extractor_sp(extractor_sp) {
42 if (extractor_sp)
43 m_object_size = extractor_sp->GetByteSize();
44 else if (m_file)
45 m_object_size = FileSystem::Instance().GetByteSize(file_spec);
46 }
47
48 ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
49 : m_file(file_spec), m_arch(arch), m_object_offset(0),
50 m_object_size(FileSystem::Instance().GetByteSize(file_spec)) {}
51
52 FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); }
53
54 const FileSpec *GetFileSpecPtr() const {
55 return (m_file ? &m_file : nullptr);
56 }
57
59
60 const FileSpec &GetFileSpec() const { return m_file; }
61
65
67 return (m_platform_file ? &m_platform_file : nullptr);
68 }
69
71
72 const FileSpec &GetPlatformFileSpec() const { return m_platform_file; }
73
75 return (m_symbol_file ? &m_symbol_file : nullptr);
76 }
77
79 return (m_symbol_file ? &m_symbol_file : nullptr);
80 }
81
83
84 const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; }
85
87 return (m_arch.IsValid() ? &m_arch : nullptr);
88 }
89
91 return (m_arch.IsValid() ? &m_arch : nullptr);
92 }
93
95
96 const ArchSpec &GetArchitecture() const { return m_arch; }
97
98 UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : nullptr); }
99
100 const UUID *GetUUIDPtr() const {
101 return (m_uuid.IsValid() ? &m_uuid : nullptr);
102 }
103
104 UUID &GetUUID() { return m_uuid; }
105
106 const UUID &GetUUID() const { return m_uuid; }
107
109
111
112 uint64_t GetObjectOffset() const { return m_object_offset; }
113
114 void SetObjectOffset(uint64_t object_offset) {
115 m_object_offset = object_offset;
116 }
117
118 uint64_t GetObjectSize() const { return m_object_size; }
119
120 void SetObjectSize(uint64_t object_size) { m_object_size = object_size; }
121
122 /// Get the load address of a module in process memory. If the optional
123 /// has no value, there is no load address for this module spec.
124 std::optional<lldb::addr_t> GetLoadAddress() const { return m_load_addr; }
125
126 /// Set the load address of a module in process memory.
128
129 void ClearLoadAddress() { m_load_addr.reset(); }
130
131 llvm::sys::TimePoint<> &GetObjectModificationTime() {
132 return m_object_mod_time;
133 }
134
135 const llvm::sys::TimePoint<> &GetObjectModificationTime() const {
136 return m_object_mod_time;
137 }
138
140
142
143 lldb::TargetSP GetTargetSP() const { return m_target_wp.lock(); }
144
145 /// Set the target to be used when resolving a module.
146 ///
147 /// A target can help locate a module specified by a ModuleSpec. The target
148 /// settings, like the executable and debug info search paths, can be
149 /// essential. The target's platform can also be used to locate or download
150 /// the specified module.
151 void SetTarget(lldb::TargetSP target) { m_target_wp = target; }
152
154
155 /// Set the platform to be used when resolving a module.
156 ///
157 /// This is useful when a Target is not yet available (e.g., during target
158 /// creation) but a Platform is. The platform can be used to invoke locate
159 /// module callbacks and other platform-specific module resolution logic.
160 void SetPlatform(lldb::PlatformSP platform) { m_platform_wp = platform; }
161
162 void Clear() {
163 m_file.Clear();
164 m_platform_file.Clear();
165 m_symbol_file.Clear();
166 m_arch.Clear();
167 m_uuid.Clear();
168 m_object_name.Clear();
169 m_object_offset = 0;
170 m_object_size = 0;
171 m_source_mappings.Clear(false);
172 m_extractor_sp.reset();
173 m_object_mod_time = llvm::sys::TimePoint<>();
174 m_target_wp.reset();
175 m_platform_wp.reset();
176 m_load_addr.reset();
177 }
178
179 explicit operator bool() const {
180 if (m_file)
181 return true;
182 if (m_platform_file)
183 return true;
184 if (m_symbol_file)
185 return true;
186 if (m_arch.IsValid())
187 return true;
188 if (m_uuid.IsValid())
189 return true;
190 if (m_object_name)
191 return true;
192 if (m_object_size)
193 return true;
194 if (m_object_mod_time != llvm::sys::TimePoint<>())
195 return true;
196 if (m_load_addr.has_value())
197 return true;
198 return false;
199 }
200
201 void Dump(Stream &strm) const {
202 bool dumped_something = false;
203 if (m_file) {
204 strm.PutCString("file = '");
205 strm << m_file;
206 strm.PutCString("'");
207 dumped_something = true;
208 }
209 if (m_platform_file) {
210 if (dumped_something)
211 strm.PutCString(", ");
212 strm.PutCString("platform_file = '");
213 strm << m_platform_file;
214 strm.PutCString("'");
215 dumped_something = true;
216 }
217 if (m_symbol_file) {
218 if (dumped_something)
219 strm.PutCString(", ");
220 strm.PutCString("symbol_file = '");
221 strm << m_symbol_file;
222 strm.PutCString("'");
223 dumped_something = true;
224 }
225 if (m_arch.IsValid()) {
226 if (dumped_something)
227 strm.PutCString(", ");
228 strm.PutCString("arch = ");
229 m_arch.DumpTriple(strm.AsRawOstream());
230 dumped_something = true;
231 }
232 if (m_uuid.IsValid()) {
233 if (dumped_something)
234 strm.PutCString(", ");
235 strm.PutCString("uuid = ");
236 m_uuid.Dump(strm);
237 dumped_something = true;
238 }
239 if (m_object_name) {
240 if (dumped_something)
241 strm.PutCString(", ");
242 strm.Printf("object_name = %s", m_object_name.GetCString());
243 dumped_something = true;
244 }
245 if (m_object_offset > 0) {
246 if (dumped_something)
247 strm.PutCString(", ");
248 strm.Printf("object_offset = %" PRIu64, m_object_offset);
249 dumped_something = true;
250 }
251 if (m_object_size > 0) {
252 if (dumped_something)
253 strm.PutCString(", ");
254 strm.Printf("object size = %" PRIu64, m_object_size);
255 dumped_something = true;
256 }
257 if (m_object_mod_time != llvm::sys::TimePoint<>()) {
258 if (dumped_something)
259 strm.PutCString(", ");
260 strm.Format("object_mod_time = {0:x+}",
261 uint64_t(llvm::sys::toTimeT(m_object_mod_time)));
262 dumped_something = true;
263 }
264 if (m_load_addr.has_value()) {
265 if (dumped_something)
266 strm.PutCString(", ");
267 strm.Printf("load_addr = 0x%" PRIx64, m_load_addr.value());
268 dumped_something = true;
269 }
270 }
271
272 bool Matches(const ModuleSpec &match_module_spec,
273 bool exact_arch_match) const {
274 if (match_module_spec.GetUUIDPtr() &&
275 match_module_spec.GetUUID() != GetUUID())
276 return false;
277 if (match_module_spec.GetObjectName() &&
278 match_module_spec.GetObjectName() != GetObjectName())
279 return false;
280 if (!FileSpec::Match(match_module_spec.GetFileSpec(), GetFileSpec()))
281 return false;
282 if (GetPlatformFileSpec() &&
283 !FileSpec::Match(match_module_spec.GetPlatformFileSpec(),
285 return false;
286 }
287 // Only match the symbol file spec if there is one in this ModuleSpec
288 if (GetSymbolFileSpec() &&
289 !FileSpec::Match(match_module_spec.GetSymbolFileSpec(),
291 return false;
292 }
293 if (match_module_spec.GetArchitecturePtr()) {
294 if (exact_arch_match) {
295 if (!GetArchitecture().IsExactMatch(
296 match_module_spec.GetArchitecture()))
297 return false;
298 } else {
299 if (!GetArchitecture().IsCompatibleMatch(
300 match_module_spec.GetArchitecture()))
301 return false;
302 }
303 }
304 // Only match on load address if they both have a valid value.
305 if (m_load_addr.has_value() && match_module_spec.m_load_addr.has_value() &&
306 match_module_spec.GetLoadAddress() != GetLoadAddress())
307 return false;
308 return true;
309 }
310
311protected:
318 /// The target used when resolving a module. A target can help locate a module
319 /// specified by a ModuleSpec. The target settings, like the executable and
320 /// debug info search paths, can be essential. The target's platform can also
321 /// be used to locate or download the specified module.
322 std::weak_ptr<Target> m_target_wp;
323 /// The platform used when resolving a module. This is useful when a Target
324 /// is not yet available (e.g., during target creation) but a Platform is.
325 std::weak_ptr<Platform> m_platform_wp;
326 uint64_t m_object_offset = 0;
327 uint64_t m_object_size = 0;
328 llvm::sys::TimePoint<> m_object_mod_time;
331 /// The load address of the module in a process. This allows for modules
332 /// to be uniquely identified and created by reading an object file from
333 /// memory when we can't locate the correct file on disk. Useful for post
334 /// mortem debugging when we might not be able to locate symbols for the
335 /// core file, but we can read the object file from memory.
336 std::optional<lldb::addr_t> m_load_addr = std::nullopt;
337};
338
340public:
341 ModuleSpecList() = default;
342
344 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
345 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
346 m_specs = rhs.m_specs;
347 }
348
349 ~ModuleSpecList() = default;
350
352 if (this != &rhs) {
353 std::lock(m_mutex, rhs.m_mutex);
354 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock);
355 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex,
356 std::adopt_lock);
357 m_specs = rhs.m_specs;
358 }
359 return *this;
360 }
361
362 size_t GetSize() const {
363 std::lock_guard<std::recursive_mutex> guard(m_mutex);
364 return m_specs.size();
365 }
366
367 void Clear() {
368 std::lock_guard<std::recursive_mutex> guard(m_mutex);
369 m_specs.clear();
370 }
371
372 void Append(const ModuleSpec &spec) {
373 std::lock_guard<std::recursive_mutex> guard(m_mutex);
374 m_specs.push_back(spec);
375 }
376
377 void Append(const ModuleSpecList &rhs) {
378 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
379 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
380 m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
381 }
382
383 // The index "i" must be valid and this can't be used in multi-threaded code
384 // as no mutex lock is taken.
386
387 bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const {
388 std::lock_guard<std::recursive_mutex> guard(m_mutex);
389 if (i < m_specs.size()) {
390 module_spec = m_specs[i];
391 return true;
392 }
393 module_spec.Clear();
394 return false;
395 }
396
397 bool FindMatchingModuleSpec(const ModuleSpec &module_spec,
398 ModuleSpec &match_module_spec) const {
399 std::lock_guard<std::recursive_mutex> guard(m_mutex);
400 bool exact_arch_match = true;
401 for (auto spec : m_specs) {
402 if (spec.Matches(module_spec, exact_arch_match)) {
403 match_module_spec = spec;
404 return true;
405 }
406 }
407
408 // If there was an architecture, retry with a compatible arch
409 if (module_spec.GetArchitecturePtr()) {
410 exact_arch_match = false;
411 for (auto spec : m_specs) {
412 if (spec.Matches(module_spec, exact_arch_match)) {
413 match_module_spec = spec;
414 return true;
415 }
416 }
417 }
418 match_module_spec.Clear();
419 return false;
420 }
421
422 void FindMatchingModuleSpecs(const ModuleSpec &module_spec,
423 ModuleSpecList &matching_list) const {
424 std::lock_guard<std::recursive_mutex> guard(m_mutex);
425 bool exact_arch_match = true;
426 const size_t initial_match_count = matching_list.GetSize();
427 for (auto spec : m_specs) {
428 if (spec.Matches(module_spec, exact_arch_match))
429 matching_list.Append(spec);
430 }
431
432 // If there was an architecture, retry with a compatible arch if no matches
433 // were found
434 if (module_spec.GetArchitecturePtr() &&
435 (initial_match_count == matching_list.GetSize())) {
436 exact_arch_match = false;
437 for (auto spec : m_specs) {
438 if (spec.Matches(module_spec, exact_arch_match))
439 matching_list.Append(spec);
440 }
441 }
442 }
443
444 void Dump(Stream &strm) {
445 std::lock_guard<std::recursive_mutex> guard(m_mutex);
446 uint32_t idx = 0;
447 for (auto spec : m_specs) {
448 strm.Printf("[%u] ", idx);
449 spec.Dump(strm);
450 strm.EOL();
451 ++idx;
452 }
453 }
454
455 typedef std::vector<ModuleSpec> collection;
458
462
463protected:
464 collection m_specs; ///< The collection of modules.
465 mutable std::recursive_mutex m_mutex;
466};
467
468} // namespace lldb_private
469
470#endif // LLDB_CORE_MODULESPEC_H
An architecture specification class.
Definition ArchSpec.h:32
A uniqued constant string class.
Definition ConstString.h:40
A file utility class.
Definition FileSpec.h:56
static bool Match(const FileSpec &pattern, const FileSpec &file)
Match FileSpec pattern against FileSpec file.
Definition FileSpec.cpp:317
static FileSystem & Instance()
std::recursive_mutex m_mutex
Definition ModuleSpec.h:465
ModuleSpecList & operator=(const ModuleSpecList &rhs)
Definition ModuleSpec.h:351
collection m_specs
The collection of modules.
Definition ModuleSpec.h:464
void Dump(Stream &strm)
Definition ModuleSpec.h:444
std::vector< ModuleSpec > collection
Definition ModuleSpec.h:455
ModuleSpecIterable ModuleSpecs()
Definition ModuleSpec.h:459
bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const
Definition ModuleSpec.h:387
void Append(const ModuleSpec &spec)
Definition ModuleSpec.h:372
bool FindMatchingModuleSpec(const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const
Definition ModuleSpec.h:397
LockingAdaptedIterable< std::recursive_mutex, collection > ModuleSpecIterable
Definition ModuleSpec.h:457
ModuleSpecList(const ModuleSpecList &rhs)
Definition ModuleSpec.h:343
ModuleSpec & GetModuleSpecRefAtIndex(size_t i)
Definition ModuleSpec.h:385
void Append(const ModuleSpecList &rhs)
Definition ModuleSpec.h:377
void FindMatchingModuleSpecs(const ModuleSpec &module_spec, ModuleSpecList &matching_list) const
Definition ModuleSpec.h:422
PathMappingList & GetSourceMappingList() const
Definition ModuleSpec.h:139
void SetPlatform(lldb::PlatformSP platform)
Set the platform to be used when resolving a module.
Definition ModuleSpec.h:160
const UUID & GetUUID() const
Definition ModuleSpec.h:106
void SetObjectSize(uint64_t object_size)
Definition ModuleSpec.h:120
uint64_t GetObjectOffset() const
Definition ModuleSpec.h:112
void SetLoadAddress(lldb::addr_t addr)
Set the load address of a module in process memory.
Definition ModuleSpec.h:127
lldb::DataExtractorSP m_extractor_sp
Definition ModuleSpec.h:330
void Dump(Stream &strm) const
Definition ModuleSpec.h:201
const ArchSpec * GetArchitecturePtr() const
Definition ModuleSpec.h:90
bool Matches(const ModuleSpec &match_module_spec, bool exact_arch_match) const
Definition ModuleSpec.h:272
ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
Definition ModuleSpec.h:48
ConstString & GetObjectName()
Definition ModuleSpec.h:108
std::weak_ptr< Target > m_target_wp
The target used when resolving a module.
Definition ModuleSpec.h:322
FileSpec & GetPlatformFileSpec()
Definition ModuleSpec.h:70
PathMappingList m_source_mappings
Definition ModuleSpec.h:329
const FileSpec * GetSymbolFileSpecPtr() const
Definition ModuleSpec.h:78
FileSpec * GetSymbolFileSpecPtr()
Definition ModuleSpec.h:74
const FileSpec * GetFileSpecPtr() const
Definition ModuleSpec.h:54
const FileSpec & GetPlatformFileSpec() const
Definition ModuleSpec.h:72
FileSpec & GetFileSpec()
Definition ModuleSpec.h:58
const FileSpec * GetPlatformFileSpecPtr() const
Definition ModuleSpec.h:66
FileSpec * GetPlatformFileSpecPtr()
Definition ModuleSpec.h:62
lldb::PlatformSP GetPlatformSP() const
Definition ModuleSpec.h:153
ArchSpec & GetArchitecture()
Definition ModuleSpec.h:94
void SetObjectOffset(uint64_t object_offset)
Definition ModuleSpec.h:114
FileSpec * GetFileSpecPtr()
Definition ModuleSpec.h:52
FileSpec & GetSymbolFileSpec()
Definition ModuleSpec.h:82
const FileSpec & GetFileSpec() const
Definition ModuleSpec.h:60
const ArchSpec & GetArchitecture() const
Definition ModuleSpec.h:96
const UUID * GetUUIDPtr() const
Definition ModuleSpec.h:100
std::weak_ptr< Platform > m_platform_wp
The platform used when resolving a module.
Definition ModuleSpec.h:325
llvm::sys::TimePoint & GetObjectModificationTime()
Definition ModuleSpec.h:131
lldb::DataExtractorSP GetExtractor() const
Definition ModuleSpec.h:141
ArchSpec * GetArchitecturePtr()
Definition ModuleSpec.h:86
void SetTarget(lldb::TargetSP target)
Set the target to be used when resolving a module.
Definition ModuleSpec.h:151
const FileSpec & GetSymbolFileSpec() const
Definition ModuleSpec.h:84
std::optional< lldb::addr_t > m_load_addr
The load address of the module in a process.
Definition ModuleSpec.h:336
ConstString GetObjectName() const
Definition ModuleSpec.h:110
llvm::sys::TimePoint m_object_mod_time
Definition ModuleSpec.h:328
const llvm::sys::TimePoint & GetObjectModificationTime() const
Definition ModuleSpec.h:135
uint64_t GetObjectSize() const
Definition ModuleSpec.h:118
lldb::TargetSP GetTargetSP() const
Definition ModuleSpec.h:143
ModuleSpec(const FileSpec &file_spec, const UUID &uuid=UUID(), lldb::DataExtractorSP extractor_sp=lldb::DataExtractorSP())
If the extractor_sp argument is passed, its contents will be used as the module contents instead of t...
Definition ModuleSpec.h:38
std::optional< lldb::addr_t > GetLoadAddress() const
Get the load address of a module in process memory.
Definition ModuleSpec.h:124
A stream class that can stream formatted output to a file.
Definition Stream.h:28
void Format(const char *format, Args &&... args)
Forwards the arguments to llvm::formatv and writes to the stream.
Definition Stream.h:370
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition Stream.h:405
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:63
size_t EOL()
Output and End of Line character to the stream.
Definition Stream.cpp:155
Represents UUID's of various sizes.
Definition UUID.h:27
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::Platform > PlatformSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::DataExtractor > DataExtractorSP