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