1 //===-- ModuleSpec.h --------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef liblldb_ModuleSpec_h_
11 #define liblldb_ModuleSpec_h_
13 #include "lldb/Host/FileSystem.h"
14 #include "lldb/Target/PathMappingList.h"
15 #include "lldb/Utility/ArchSpec.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/Utility/Stream.h"
18 #include "lldb/Utility/UUID.h"
20 #include "llvm/Support/Chrono.h"
25 namespace lldb_private {
30 : m_file(), m_platform_file(), m_symbol_file(), m_arch(), m_uuid(),
31 m_object_name(), m_object_offset(0), m_object_size(0),
32 m_source_mappings() {}
34 ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID())
35 : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(),
36 m_uuid(uuid), m_object_name(), m_object_offset(0),
37 m_object_size(FileSystem::Instance().GetByteSize(file_spec)),
38 m_source_mappings() {}
40 ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
41 : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(arch),
42 m_uuid(), m_object_name(), m_object_offset(0),
43 m_object_size(FileSystem::Instance().GetByteSize(file_spec)),
44 m_source_mappings() {}
46 ModuleSpec(const ModuleSpec &rhs)
47 : m_file(rhs.m_file), m_platform_file(rhs.m_platform_file),
48 m_symbol_file(rhs.m_symbol_file), m_arch(rhs.m_arch),
49 m_uuid(rhs.m_uuid), m_object_name(rhs.m_object_name),
50 m_object_offset(rhs.m_object_offset), m_object_size(rhs.m_object_size),
51 m_object_mod_time(rhs.m_object_mod_time),
52 m_source_mappings(rhs.m_source_mappings) {}
54 ModuleSpec &operator=(const ModuleSpec &rhs) {
57 m_platform_file = rhs.m_platform_file;
58 m_symbol_file = rhs.m_symbol_file;
61 m_object_name = rhs.m_object_name;
62 m_object_offset = rhs.m_object_offset;
63 m_object_size = rhs.m_object_size;
64 m_object_mod_time = rhs.m_object_mod_time;
65 m_source_mappings = rhs.m_source_mappings;
70 FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); }
72 const FileSpec *GetFileSpecPtr() const {
73 return (m_file ? &m_file : nullptr);
76 FileSpec &GetFileSpec() { return m_file; }
78 const FileSpec &GetFileSpec() const { return m_file; }
80 FileSpec *GetPlatformFileSpecPtr() {
81 return (m_platform_file ? &m_platform_file : nullptr);
84 const FileSpec *GetPlatformFileSpecPtr() const {
85 return (m_platform_file ? &m_platform_file : nullptr);
88 FileSpec &GetPlatformFileSpec() { return m_platform_file; }
90 const FileSpec &GetPlatformFileSpec() const { return m_platform_file; }
92 FileSpec *GetSymbolFileSpecPtr() {
93 return (m_symbol_file ? &m_symbol_file : nullptr);
96 const FileSpec *GetSymbolFileSpecPtr() const {
97 return (m_symbol_file ? &m_symbol_file : nullptr);
100 FileSpec &GetSymbolFileSpec() { return m_symbol_file; }
102 const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; }
104 ArchSpec *GetArchitecturePtr() {
105 return (m_arch.IsValid() ? &m_arch : nullptr);
108 const ArchSpec *GetArchitecturePtr() const {
109 return (m_arch.IsValid() ? &m_arch : nullptr);
112 ArchSpec &GetArchitecture() { return m_arch; }
114 const ArchSpec &GetArchitecture() const { return m_arch; }
116 UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : nullptr); }
118 const UUID *GetUUIDPtr() const {
119 return (m_uuid.IsValid() ? &m_uuid : nullptr);
122 UUID &GetUUID() { return m_uuid; }
124 const UUID &GetUUID() const { return m_uuid; }
126 ConstString &GetObjectName() { return m_object_name; }
128 const ConstString &GetObjectName() const { return m_object_name; }
130 uint64_t GetObjectOffset() const { return m_object_offset; }
132 void SetObjectOffset(uint64_t object_offset) {
133 m_object_offset = object_offset;
136 uint64_t GetObjectSize() const { return m_object_size; }
138 void SetObjectSize(uint64_t object_size) { m_object_size = object_size; }
140 llvm::sys::TimePoint<> &GetObjectModificationTime() {
141 return m_object_mod_time;
144 const llvm::sys::TimePoint<> &GetObjectModificationTime() const {
145 return m_object_mod_time;
148 PathMappingList &GetSourceMappingList() const { return m_source_mappings; }
152 m_platform_file.Clear();
153 m_symbol_file.Clear();
156 m_object_name.Clear();
159 m_source_mappings.Clear(false);
160 m_object_mod_time = llvm::sys::TimePoint<>();
163 explicit operator bool() const {
170 if (m_arch.IsValid())
172 if (m_uuid.IsValid())
178 if (m_object_mod_time != llvm::sys::TimePoint<>())
183 void Dump(Stream &strm) const {
184 bool dumped_something = false;
186 strm.PutCString("file = '");
188 strm.PutCString("'");
189 dumped_something = true;
191 if (m_platform_file) {
192 if (dumped_something)
193 strm.PutCString(", ");
194 strm.PutCString("platform_file = '");
195 strm << m_platform_file;
196 strm.PutCString("'");
197 dumped_something = true;
200 if (dumped_something)
201 strm.PutCString(", ");
202 strm.PutCString("symbol_file = '");
203 strm << m_symbol_file;
204 strm.PutCString("'");
205 dumped_something = true;
207 if (m_arch.IsValid()) {
208 if (dumped_something)
209 strm.PutCString(", ");
210 strm.Printf("arch = ");
211 m_arch.DumpTriple(strm);
212 dumped_something = true;
214 if (m_uuid.IsValid()) {
215 if (dumped_something)
216 strm.PutCString(", ");
217 strm.PutCString("uuid = ");
219 dumped_something = true;
222 if (dumped_something)
223 strm.PutCString(", ");
224 strm.Printf("object_name = %s", m_object_name.GetCString());
225 dumped_something = true;
227 if (m_object_offset > 0) {
228 if (dumped_something)
229 strm.PutCString(", ");
230 strm.Printf("object_offset = %" PRIu64, m_object_offset);
231 dumped_something = true;
233 if (m_object_size > 0) {
234 if (dumped_something)
235 strm.PutCString(", ");
236 strm.Printf("object size = %" PRIu64, m_object_size);
237 dumped_something = true;
239 if (m_object_mod_time != llvm::sys::TimePoint<>()) {
240 if (dumped_something)
241 strm.PutCString(", ");
242 strm.Format("object_mod_time = {0:x+}",
243 uint64_t(llvm::sys::toTimeT(m_object_mod_time)));
247 bool Matches(const ModuleSpec &match_module_spec,
248 bool exact_arch_match) const {
249 if (match_module_spec.GetUUIDPtr() &&
250 match_module_spec.GetUUID() != GetUUID())
252 if (match_module_spec.GetObjectName() &&
253 match_module_spec.GetObjectName() != GetObjectName())
255 if (match_module_spec.GetFileSpecPtr()) {
256 const FileSpec &fspec = match_module_spec.GetFileSpec();
257 if (!FileSpec::Equal(fspec, GetFileSpec(),
258 !fspec.GetDirectory().IsEmpty()))
261 if (GetPlatformFileSpec() && match_module_spec.GetPlatformFileSpecPtr()) {
262 const FileSpec &fspec = match_module_spec.GetPlatformFileSpec();
263 if (!FileSpec::Equal(fspec, GetPlatformFileSpec(),
264 !fspec.GetDirectory().IsEmpty()))
267 // Only match the symbol file spec if there is one in this ModuleSpec
268 if (GetSymbolFileSpec() && match_module_spec.GetSymbolFileSpecPtr()) {
269 const FileSpec &fspec = match_module_spec.GetSymbolFileSpec();
270 if (!FileSpec::Equal(fspec, GetSymbolFileSpec(),
271 !fspec.GetDirectory().IsEmpty()))
274 if (match_module_spec.GetArchitecturePtr()) {
275 if (exact_arch_match) {
276 if (!GetArchitecture().IsExactMatch(
277 match_module_spec.GetArchitecture()))
280 if (!GetArchitecture().IsCompatibleMatch(
281 match_module_spec.GetArchitecture()))
290 FileSpec m_platform_file;
291 FileSpec m_symbol_file;
294 ConstString m_object_name;
295 uint64_t m_object_offset;
296 uint64_t m_object_size;
297 llvm::sys::TimePoint<> m_object_mod_time;
298 mutable PathMappingList m_source_mappings;
301 class ModuleSpecList {
303 ModuleSpecList() : m_specs(), m_mutex() {}
305 ModuleSpecList(const ModuleSpecList &rhs) : m_specs(), m_mutex() {
306 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
307 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
308 m_specs = rhs.m_specs;
311 ~ModuleSpecList() = default;
313 ModuleSpecList &operator=(const ModuleSpecList &rhs) {
315 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
316 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
317 m_specs = rhs.m_specs;
322 size_t GetSize() const {
323 std::lock_guard<std::recursive_mutex> guard(m_mutex);
324 return m_specs.size();
328 std::lock_guard<std::recursive_mutex> guard(m_mutex);
332 void Append(const ModuleSpec &spec) {
333 std::lock_guard<std::recursive_mutex> guard(m_mutex);
334 m_specs.push_back(spec);
337 void Append(const ModuleSpecList &rhs) {
338 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
339 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
340 m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
343 // The index "i" must be valid and this can't be used in multi-threaded code
344 // as no mutex lock is taken.
345 ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; }
347 bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const {
348 std::lock_guard<std::recursive_mutex> guard(m_mutex);
349 if (i < m_specs.size()) {
350 module_spec = m_specs[i];
357 bool FindMatchingModuleSpec(const ModuleSpec &module_spec,
358 ModuleSpec &match_module_spec) const {
359 std::lock_guard<std::recursive_mutex> guard(m_mutex);
360 bool exact_arch_match = true;
361 for (auto spec : m_specs) {
362 if (spec.Matches(module_spec, exact_arch_match)) {
363 match_module_spec = spec;
368 // If there was an architecture, retry with a compatible arch
369 if (module_spec.GetArchitecturePtr()) {
370 exact_arch_match = false;
371 for (auto spec : m_specs) {
372 if (spec.Matches(module_spec, exact_arch_match)) {
373 match_module_spec = spec;
378 match_module_spec.Clear();
382 size_t FindMatchingModuleSpecs(const ModuleSpec &module_spec,
383 ModuleSpecList &matching_list) const {
384 std::lock_guard<std::recursive_mutex> guard(m_mutex);
385 bool exact_arch_match = true;
386 const size_t initial_match_count = matching_list.GetSize();
387 for (auto spec : m_specs) {
388 if (spec.Matches(module_spec, exact_arch_match))
389 matching_list.Append(spec);
392 // If there was an architecture, retry with a compatible arch if no matches
394 if (module_spec.GetArchitecturePtr() &&
395 (initial_match_count == matching_list.GetSize())) {
396 exact_arch_match = false;
397 for (auto spec : m_specs) {
398 if (spec.Matches(module_spec, exact_arch_match))
399 matching_list.Append(spec);
402 return matching_list.GetSize() - initial_match_count;
405 void Dump(Stream &strm) {
406 std::lock_guard<std::recursive_mutex> guard(m_mutex);
408 for (auto spec : m_specs) {
409 strm.Printf("[%u] ", idx);
417 typedef std::vector<ModuleSpec> collection; ///< The module collection type.
418 collection m_specs; ///< The collection of modules.
419 mutable std::recursive_mutex m_mutex;
422 } // namespace lldb_private
424 #endif // liblldb_ModuleSpec_h_