]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h
Merge upstream r4302 to support multiple concurrently valid anchors.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Core / ModuleSpec.h
1 //===-- ModuleSpec.h --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef liblldb_ModuleSpec_h_
11 #define liblldb_ModuleSpec_h_
12
13 // Project includes
14 #include "lldb/Core/ArchSpec.h"
15 #include "lldb/Target/PathMappingList.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/Utility/Stream.h"
18 #include "lldb/Utility/UUID.h"
19
20 // Other libraries and framework includes
21 #include "llvm/Support/Chrono.h"
22
23 // C Includes
24 // C++ Includes
25 #include <mutex>
26 #include <vector>
27
28 namespace lldb_private {
29
30 class ModuleSpec {
31 public:
32   ModuleSpec()
33       : m_file(), m_platform_file(), m_symbol_file(), m_arch(), m_uuid(),
34         m_object_name(), m_object_offset(0), m_object_size(0),
35         m_source_mappings() {}
36
37   ModuleSpec(const FileSpec &file_spec)
38       : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(),
39         m_uuid(), m_object_name(), m_object_offset(0),
40         m_object_size(file_spec.GetByteSize()), m_source_mappings() {}
41
42   ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
43       : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(arch),
44         m_uuid(), m_object_name(), m_object_offset(0),
45         m_object_size(file_spec.GetByteSize()), m_source_mappings() {}
46
47   ModuleSpec(const ModuleSpec &rhs)
48       : m_file(rhs.m_file), m_platform_file(rhs.m_platform_file),
49         m_symbol_file(rhs.m_symbol_file), m_arch(rhs.m_arch),
50         m_uuid(rhs.m_uuid), m_object_name(rhs.m_object_name),
51         m_object_offset(rhs.m_object_offset), m_object_size(rhs.m_object_size),
52         m_object_mod_time(rhs.m_object_mod_time),
53         m_source_mappings(rhs.m_source_mappings) {}
54
55   ModuleSpec &operator=(const ModuleSpec &rhs) {
56     if (this != &rhs) {
57       m_file = rhs.m_file;
58       m_platform_file = rhs.m_platform_file;
59       m_symbol_file = rhs.m_symbol_file;
60       m_arch = rhs.m_arch;
61       m_uuid = rhs.m_uuid;
62       m_object_name = rhs.m_object_name;
63       m_object_offset = rhs.m_object_offset;
64       m_object_size = rhs.m_object_size;
65       m_object_mod_time = rhs.m_object_mod_time;
66       m_source_mappings = rhs.m_source_mappings;
67     }
68     return *this;
69   }
70
71   FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); }
72
73   const FileSpec *GetFileSpecPtr() const {
74     return (m_file ? &m_file : nullptr);
75   }
76
77   FileSpec &GetFileSpec() { return m_file; }
78
79   const FileSpec &GetFileSpec() const { return m_file; }
80
81   FileSpec *GetPlatformFileSpecPtr() {
82     return (m_platform_file ? &m_platform_file : nullptr);
83   }
84
85   const FileSpec *GetPlatformFileSpecPtr() const {
86     return (m_platform_file ? &m_platform_file : nullptr);
87   }
88
89   FileSpec &GetPlatformFileSpec() { return m_platform_file; }
90
91   const FileSpec &GetPlatformFileSpec() const { return m_platform_file; }
92
93   FileSpec *GetSymbolFileSpecPtr() {
94     return (m_symbol_file ? &m_symbol_file : nullptr);
95   }
96
97   const FileSpec *GetSymbolFileSpecPtr() const {
98     return (m_symbol_file ? &m_symbol_file : nullptr);
99   }
100
101   FileSpec &GetSymbolFileSpec() { return m_symbol_file; }
102
103   const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; }
104
105   ArchSpec *GetArchitecturePtr() {
106     return (m_arch.IsValid() ? &m_arch : nullptr);
107   }
108
109   const ArchSpec *GetArchitecturePtr() const {
110     return (m_arch.IsValid() ? &m_arch : nullptr);
111   }
112
113   ArchSpec &GetArchitecture() { return m_arch; }
114
115   const ArchSpec &GetArchitecture() const { return m_arch; }
116
117   UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : nullptr); }
118
119   const UUID *GetUUIDPtr() const {
120     return (m_uuid.IsValid() ? &m_uuid : nullptr);
121   }
122
123   UUID &GetUUID() { return m_uuid; }
124
125   const UUID &GetUUID() const { return m_uuid; }
126
127   ConstString &GetObjectName() { return m_object_name; }
128
129   const ConstString &GetObjectName() const { return m_object_name; }
130
131   uint64_t GetObjectOffset() const { return m_object_offset; }
132
133   void SetObjectOffset(uint64_t object_offset) {
134     m_object_offset = object_offset;
135   }
136
137   uint64_t GetObjectSize() const { return m_object_size; }
138
139   void SetObjectSize(uint64_t object_size) { m_object_size = object_size; }
140
141   llvm::sys::TimePoint<> &GetObjectModificationTime() {
142     return m_object_mod_time;
143   }
144
145   const llvm::sys::TimePoint<> &GetObjectModificationTime() const {
146     return m_object_mod_time;
147   }
148
149   PathMappingList &GetSourceMappingList() const { return m_source_mappings; }
150
151   void Clear() {
152     m_file.Clear();
153     m_platform_file.Clear();
154     m_symbol_file.Clear();
155     m_arch.Clear();
156     m_uuid.Clear();
157     m_object_name.Clear();
158     m_object_offset = 0;
159     m_object_size = 0;
160     m_source_mappings.Clear(false);
161     m_object_mod_time = llvm::sys::TimePoint<>();
162   }
163
164   explicit operator bool() const {
165     if (m_file)
166       return true;
167     if (m_platform_file)
168       return true;
169     if (m_symbol_file)
170       return true;
171     if (m_arch.IsValid())
172       return true;
173     if (m_uuid.IsValid())
174       return true;
175     if (m_object_name)
176       return true;
177     if (m_object_size)
178       return true;
179     if (m_object_mod_time != llvm::sys::TimePoint<>())
180       return true;
181     return false;
182   }
183
184   void Dump(Stream &strm) const {
185     bool dumped_something = false;
186     if (m_file) {
187       strm.PutCString("file = '");
188       strm << m_file;
189       strm.PutCString("'");
190       dumped_something = true;
191     }
192     if (m_platform_file) {
193       if (dumped_something)
194         strm.PutCString(", ");
195       strm.PutCString("platform_file = '");
196       strm << m_platform_file;
197       strm.PutCString("'");
198       dumped_something = true;
199     }
200     if (m_symbol_file) {
201       if (dumped_something)
202         strm.PutCString(", ");
203       strm.PutCString("symbol_file = '");
204       strm << m_symbol_file;
205       strm.PutCString("'");
206       dumped_something = true;
207     }
208     if (m_arch.IsValid()) {
209       if (dumped_something)
210         strm.PutCString(", ");
211       strm.Printf("arch = ");
212       m_arch.DumpTriple(strm);
213       dumped_something = true;
214     }
215     if (m_uuid.IsValid()) {
216       if (dumped_something)
217         strm.PutCString(", ");
218       strm.PutCString("uuid = ");
219       m_uuid.Dump(&strm);
220       dumped_something = true;
221     }
222     if (m_object_name) {
223       if (dumped_something)
224         strm.PutCString(", ");
225       strm.Printf("object_name = %s", m_object_name.GetCString());
226       dumped_something = true;
227     }
228     if (m_object_offset > 0) {
229       if (dumped_something)
230         strm.PutCString(", ");
231       strm.Printf("object_offset = %" PRIu64, m_object_offset);
232       dumped_something = true;
233     }
234     if (m_object_size > 0) {
235       if (dumped_something)
236         strm.PutCString(", ");
237       strm.Printf("object size = %" PRIu64, m_object_size);
238       dumped_something = true;
239     }
240     if (m_object_mod_time != llvm::sys::TimePoint<>()) {
241       if (dumped_something)
242         strm.PutCString(", ");
243       strm.Format("object_mod_time = {0:x+}",
244                   uint64_t(llvm::sys::toTimeT(m_object_mod_time)));
245     }
246   }
247
248   bool Matches(const ModuleSpec &match_module_spec,
249                bool exact_arch_match) const {
250     if (match_module_spec.GetUUIDPtr() &&
251         match_module_spec.GetUUID() != GetUUID())
252       return false;
253     if (match_module_spec.GetObjectName() &&
254         match_module_spec.GetObjectName() != GetObjectName())
255       return false;
256     if (match_module_spec.GetFileSpecPtr()) {
257       const FileSpec &fspec = match_module_spec.GetFileSpec();
258       if (!FileSpec::Equal(fspec, GetFileSpec(),
259                            fspec.GetDirectory().IsEmpty() == false))
260         return false;
261     }
262     if (GetPlatformFileSpec() && match_module_spec.GetPlatformFileSpecPtr()) {
263       const FileSpec &fspec = match_module_spec.GetPlatformFileSpec();
264       if (!FileSpec::Equal(fspec, GetPlatformFileSpec(),
265                            fspec.GetDirectory().IsEmpty() == false))
266         return false;
267     }
268     // Only match the symbol file spec if there is one in this ModuleSpec
269     if (GetSymbolFileSpec() && match_module_spec.GetSymbolFileSpecPtr()) {
270       const FileSpec &fspec = match_module_spec.GetSymbolFileSpec();
271       if (!FileSpec::Equal(fspec, GetSymbolFileSpec(),
272                            fspec.GetDirectory().IsEmpty() == false))
273         return false;
274     }
275     if (match_module_spec.GetArchitecturePtr()) {
276       if (exact_arch_match) {
277         if (!GetArchitecture().IsExactMatch(
278                 match_module_spec.GetArchitecture()))
279           return false;
280       } else {
281         if (!GetArchitecture().IsCompatibleMatch(
282                 match_module_spec.GetArchitecture()))
283           return false;
284       }
285     }
286     return true;
287   }
288
289 protected:
290   FileSpec m_file;
291   FileSpec m_platform_file;
292   FileSpec m_symbol_file;
293   ArchSpec m_arch;
294   UUID m_uuid;
295   ConstString m_object_name;
296   uint64_t m_object_offset;
297   uint64_t m_object_size;
298   llvm::sys::TimePoint<> m_object_mod_time;
299   mutable PathMappingList m_source_mappings;
300 };
301
302 class ModuleSpecList {
303 public:
304   ModuleSpecList() : m_specs(), m_mutex() {}
305
306   ModuleSpecList(const ModuleSpecList &rhs) : m_specs(), m_mutex() {
307     std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
308     std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
309     m_specs = rhs.m_specs;
310   }
311
312   ~ModuleSpecList() = default;
313
314   ModuleSpecList &operator=(const ModuleSpecList &rhs) {
315     if (this != &rhs) {
316       std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
317       std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
318       m_specs = rhs.m_specs;
319     }
320     return *this;
321   }
322
323   size_t GetSize() const {
324     std::lock_guard<std::recursive_mutex> guard(m_mutex);
325     return m_specs.size();
326   }
327
328   void Clear() {
329     std::lock_guard<std::recursive_mutex> guard(m_mutex);
330     m_specs.clear();
331   }
332
333   void Append(const ModuleSpec &spec) {
334     std::lock_guard<std::recursive_mutex> guard(m_mutex);
335     m_specs.push_back(spec);
336   }
337
338   void Append(const ModuleSpecList &rhs) {
339     std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
340     std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
341     m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
342   }
343
344   // The index "i" must be valid and this can't be used in
345   // multi-threaded code as no mutex lock is taken.
346   ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; }
347
348   bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const {
349     std::lock_guard<std::recursive_mutex> guard(m_mutex);
350     if (i < m_specs.size()) {
351       module_spec = m_specs[i];
352       return true;
353     }
354     module_spec.Clear();
355     return false;
356   }
357
358   bool FindMatchingModuleSpec(const ModuleSpec &module_spec,
359                               ModuleSpec &match_module_spec) const {
360     std::lock_guard<std::recursive_mutex> guard(m_mutex);
361     bool exact_arch_match = true;
362     for (auto spec : m_specs) {
363       if (spec.Matches(module_spec, exact_arch_match)) {
364         match_module_spec = spec;
365         return true;
366       }
367     }
368
369     // If there was an architecture, retry with a compatible arch
370     if (module_spec.GetArchitecturePtr()) {
371       exact_arch_match = false;
372       for (auto spec : m_specs) {
373         if (spec.Matches(module_spec, exact_arch_match)) {
374           match_module_spec = spec;
375           return true;
376         }
377       }
378     }
379     match_module_spec.Clear();
380     return false;
381   }
382
383   size_t FindMatchingModuleSpecs(const ModuleSpec &module_spec,
384                                  ModuleSpecList &matching_list) const {
385     std::lock_guard<std::recursive_mutex> guard(m_mutex);
386     bool exact_arch_match = true;
387     const size_t initial_match_count = matching_list.GetSize();
388     for (auto spec : m_specs) {
389       if (spec.Matches(module_spec, exact_arch_match))
390         matching_list.Append(spec);
391     }
392
393     // If there was an architecture, retry with a compatible arch if no matches
394     // were found
395     if (module_spec.GetArchitecturePtr() &&
396         (initial_match_count == matching_list.GetSize())) {
397       exact_arch_match = false;
398       for (auto spec : m_specs) {
399         if (spec.Matches(module_spec, exact_arch_match))
400           matching_list.Append(spec);
401       }
402     }
403     return matching_list.GetSize() - initial_match_count;
404   }
405
406   void Dump(Stream &strm) {
407     std::lock_guard<std::recursive_mutex> guard(m_mutex);
408     uint32_t idx = 0;
409     for (auto spec : m_specs) {
410       strm.Printf("[%u] ", idx);
411       spec.Dump(strm);
412       strm.EOL();
413       ++idx;
414     }
415   }
416
417 protected:
418   typedef std::vector<ModuleSpec> collection; ///< The module collection type.
419   collection m_specs;                         ///< The collection of modules.
420   mutable std::recursive_mutex m_mutex;
421 };
422
423 } // namespace lldb_private
424
425 #endif // liblldb_ModuleSpec_h_