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