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 #include "lldb/Core/ArchSpec.h"
14 #include "lldb/Core/Stream.h"
15 #include "lldb/Core/UUID.h"
16 #include "lldb/Host/FileSpec.h"
17 #include "lldb/Target/PathMappingList.h"
18 
19 namespace lldb_private {
20 
21 class ModuleSpec
22 {
23 public:
ModuleSpec()24     ModuleSpec () :
25         m_file (),
26         m_platform_file (),
27         m_symbol_file (),
28         m_arch (),
29         m_uuid (),
30         m_object_name (),
31         m_object_offset (0),
32         m_object_mod_time (),
33         m_source_mappings ()
34     {
35     }
36 
ModuleSpec(const FileSpec & file_spec)37     ModuleSpec (const FileSpec &file_spec) :
38         m_file (file_spec),
39         m_platform_file (),
40         m_symbol_file (),
41         m_arch (),
42         m_uuid (),
43         m_object_name (),
44         m_object_offset (0),
45         m_object_mod_time (),
46         m_source_mappings ()
47     {
48     }
49 
ModuleSpec(const FileSpec & file_spec,const ArchSpec & arch)50     ModuleSpec (const FileSpec &file_spec, const ArchSpec &arch) :
51         m_file (file_spec),
52         m_platform_file (),
53         m_symbol_file (),
54         m_arch (arch),
55         m_uuid (),
56         m_object_name (),
57         m_object_offset (0),
58         m_object_mod_time (),
59         m_source_mappings ()
60     {
61     }
62 
ModuleSpec(const ModuleSpec & rhs)63     ModuleSpec (const ModuleSpec &rhs) :
64         m_file (rhs.m_file),
65         m_platform_file (rhs.m_platform_file),
66         m_symbol_file (rhs.m_symbol_file),
67         m_arch (rhs.m_arch),
68         m_uuid (rhs.m_uuid),
69         m_object_name (rhs.m_object_name),
70         m_object_offset (rhs.m_object_offset),
71         m_object_mod_time (rhs.m_object_mod_time),
72         m_source_mappings (rhs.m_source_mappings)
73     {
74     }
75 
76     ModuleSpec &
77     operator = (const ModuleSpec &rhs)
78     {
79         if (this != &rhs)
80         {
81             m_file = rhs.m_file;
82             m_platform_file = rhs.m_platform_file;
83             m_symbol_file = rhs.m_symbol_file;
84             m_arch = rhs.m_arch;
85             m_uuid = rhs.m_uuid;
86             m_object_name = rhs.m_object_name;
87             m_object_offset = rhs.m_object_offset;
88             m_object_mod_time = rhs.m_object_mod_time;
89             m_source_mappings = rhs.m_source_mappings;
90         }
91         return *this;
92     }
93 
94     FileSpec *
GetFileSpecPtr()95     GetFileSpecPtr ()
96     {
97         if (m_file)
98             return &m_file;
99         return NULL;
100     }
101 
102     const FileSpec *
GetFileSpecPtr()103     GetFileSpecPtr () const
104     {
105         if (m_file)
106             return &m_file;
107         return NULL;
108     }
109 
110     FileSpec &
GetFileSpec()111     GetFileSpec ()
112     {
113         return m_file;
114     }
115     const FileSpec &
GetFileSpec()116     GetFileSpec () const
117     {
118         return m_file;
119     }
120 
121     FileSpec *
GetPlatformFileSpecPtr()122     GetPlatformFileSpecPtr ()
123     {
124         if (m_platform_file)
125             return &m_platform_file;
126         return NULL;
127     }
128 
129     const FileSpec *
GetPlatformFileSpecPtr()130     GetPlatformFileSpecPtr () const
131     {
132         if (m_platform_file)
133             return &m_platform_file;
134         return NULL;
135     }
136 
137     FileSpec &
GetPlatformFileSpec()138     GetPlatformFileSpec ()
139     {
140         return m_platform_file;
141     }
142 
143     const FileSpec &
GetPlatformFileSpec()144     GetPlatformFileSpec () const
145     {
146         return m_platform_file;
147     }
148 
149     FileSpec *
GetSymbolFileSpecPtr()150     GetSymbolFileSpecPtr ()
151     {
152         if (m_symbol_file)
153             return &m_symbol_file;
154         return NULL;
155     }
156 
157     const FileSpec *
GetSymbolFileSpecPtr()158     GetSymbolFileSpecPtr () const
159     {
160         if (m_symbol_file)
161             return &m_symbol_file;
162         return NULL;
163     }
164 
165     FileSpec &
GetSymbolFileSpec()166     GetSymbolFileSpec ()
167     {
168         return m_symbol_file;
169     }
170 
171     const FileSpec &
GetSymbolFileSpec()172     GetSymbolFileSpec () const
173     {
174         return m_symbol_file;
175     }
176 
177 
178     ArchSpec *
GetArchitecturePtr()179     GetArchitecturePtr ()
180     {
181         if (m_arch.IsValid())
182             return &m_arch;
183         return NULL;
184     }
185 
186     const ArchSpec *
GetArchitecturePtr()187     GetArchitecturePtr () const
188     {
189         if (m_arch.IsValid())
190             return &m_arch;
191         return NULL;
192     }
193 
194     ArchSpec &
GetArchitecture()195     GetArchitecture ()
196     {
197         return m_arch;
198     }
199 
200     const ArchSpec &
GetArchitecture()201     GetArchitecture () const
202     {
203         return m_arch;
204     }
205 
206     UUID *
GetUUIDPtr()207     GetUUIDPtr ()
208     {
209         if (m_uuid.IsValid())
210             return &m_uuid;
211         return NULL;
212     }
213 
214     const UUID *
GetUUIDPtr()215     GetUUIDPtr () const
216     {
217         if (m_uuid.IsValid())
218             return &m_uuid;
219         return NULL;
220     }
221 
222     UUID &
GetUUID()223     GetUUID ()
224     {
225         return m_uuid;
226     }
227 
228     const UUID &
GetUUID()229     GetUUID () const
230     {
231         return m_uuid;
232     }
233 
234     ConstString &
GetObjectName()235     GetObjectName ()
236     {
237         return m_object_name;
238     }
239 
240     const ConstString &
GetObjectName()241     GetObjectName () const
242     {
243         return m_object_name;
244     }
245 
246     uint64_t
GetObjectOffset()247     GetObjectOffset () const
248     {
249         return m_object_offset;
250     }
251 
252     void
SetObjectOffset(uint64_t object_offset)253     SetObjectOffset (uint64_t object_offset)
254     {
255         m_object_offset = object_offset;
256     }
257 
258     TimeValue &
GetObjectModificationTime()259     GetObjectModificationTime ()
260     {
261         return m_object_mod_time;
262     }
263 
264     const TimeValue &
GetObjectModificationTime()265     GetObjectModificationTime () const
266     {
267         return m_object_mod_time;
268     }
269 
270     PathMappingList &
GetSourceMappingList()271     GetSourceMappingList () const
272     {
273         return m_source_mappings;
274     }
275 
276     void
Clear()277     Clear ()
278     {
279         m_file.Clear();
280         m_platform_file.Clear();
281         m_symbol_file.Clear();
282         m_arch.Clear();
283         m_uuid.Clear();
284         m_object_name.Clear();
285         m_object_offset = 0;
286         m_source_mappings.Clear(false);
287         m_object_mod_time.Clear();
288     }
289 
290 
291     operator bool () const
292     {
293         if (m_file)
294             return true;
295         if (m_platform_file)
296             return true;
297         if (m_symbol_file)
298             return true;
299         if (m_arch.IsValid())
300             return true;
301         if (m_uuid.IsValid())
302             return true;
303         if (m_object_name)
304             return true;
305         if (m_object_mod_time.IsValid())
306             return true;
307         return false;
308     }
309 
310     void
Dump(Stream & strm)311     Dump (Stream &strm)
312     {
313         bool dumped_something = false;
314         if (m_file)
315         {
316             strm.PutCString("file = '");
317             strm << m_file;
318             strm.PutCString("'");
319             dumped_something = true;
320         }
321         if (m_platform_file)
322         {
323             if (dumped_something)
324                 strm.PutCString(", ");
325             strm.PutCString("platform_file = '");
326             strm << m_platform_file;
327             strm.PutCString("'");
328             dumped_something = true;
329         }
330         if (m_symbol_file)
331         {
332             if (dumped_something)
333                 strm.PutCString(", ");
334             strm.PutCString("symbol_file = '");
335             strm << m_symbol_file;
336             strm.PutCString("'");
337             dumped_something = true;
338         }
339         if (m_arch.IsValid())
340         {
341             if (dumped_something)
342                 strm.PutCString(", ");
343             strm.Printf("arch = %s", m_arch.GetTriple().str().c_str());
344             dumped_something = true;
345         }
346         if (m_uuid.IsValid())
347         {
348             if (dumped_something)
349                 strm.PutCString(", ");
350             strm.PutCString("uuid = ");
351             m_uuid.Dump(&strm);
352             dumped_something = true;
353         }
354         if (m_object_name)
355         {
356             if (dumped_something)
357                 strm.PutCString(", ");
358             strm.Printf("object_name = %s", m_object_name.GetCString());
359             dumped_something = true;
360         }
361         if (m_object_offset > 0)
362         {
363             if (dumped_something)
364                 strm.PutCString(", ");
365             strm.Printf("object_offset = 0x%" PRIx64, m_object_offset);
366             dumped_something = true;
367         }
368         if (m_object_mod_time.IsValid())
369         {
370             if (dumped_something)
371                 strm.PutCString(", ");
372             strm.Printf("object_mod_time = 0x%" PRIx64, m_object_mod_time.GetAsSecondsSinceJan1_1970());
373             dumped_something = true;
374         }
375     }
376 
377     bool
Matches(const ModuleSpec & match_module_spec,bool exact_arch_match)378     Matches (const ModuleSpec &match_module_spec, bool exact_arch_match) const
379     {
380         if (match_module_spec.GetUUIDPtr() && match_module_spec.GetUUID() != GetUUID())
381             return false;
382         if (match_module_spec.GetObjectName() && match_module_spec.GetObjectName() != GetObjectName())
383             return false;
384         if (match_module_spec.GetFileSpecPtr())
385         {
386             const FileSpec &fspec = match_module_spec.GetFileSpec();
387             if (!FileSpec::Equal(fspec, GetFileSpec(), fspec.GetDirectory().IsEmpty() == false))
388                 return false;
389         }
390         if (match_module_spec.GetPlatformFileSpecPtr())
391         {
392             const FileSpec &fspec = match_module_spec.GetPlatformFileSpec();
393             if (!FileSpec::Equal(fspec, GetPlatformFileSpec(), fspec.GetDirectory().IsEmpty() == false))
394                 return false;
395 
396         }
397         if (match_module_spec.GetSymbolFileSpecPtr())
398         {
399             const FileSpec &fspec = match_module_spec.GetSymbolFileSpec();
400             if (!FileSpec::Equal(fspec, GetSymbolFileSpec(), fspec.GetDirectory().IsEmpty() == false))
401                 return false;
402 
403         }
404         if (match_module_spec.GetArchitecturePtr())
405         {
406             if (exact_arch_match)
407             {
408                 if (!GetArchitecture().IsExactMatch(match_module_spec.GetArchitecture()))
409                     return false;
410             }
411             else
412             {
413                 if (!GetArchitecture().IsCompatibleMatch(match_module_spec.GetArchitecture()))
414                     return false;
415             }
416         }
417         return true;
418     }
419 
420 protected:
421     FileSpec m_file;
422     FileSpec m_platform_file;
423     FileSpec m_symbol_file;
424     ArchSpec m_arch;
425     UUID m_uuid;
426     ConstString m_object_name;
427     uint64_t m_object_offset;
428     TimeValue m_object_mod_time;
429     mutable PathMappingList m_source_mappings;
430 };
431 
432 class ModuleSpecList
433 {
434 public:
ModuleSpecList()435     ModuleSpecList () :
436         m_specs(),
437         m_mutex(Mutex::eMutexTypeRecursive)
438     {
439     }
440 
ModuleSpecList(const ModuleSpecList & rhs)441     ModuleSpecList (const ModuleSpecList &rhs) :
442         m_specs(),
443         m_mutex(Mutex::eMutexTypeRecursive)
444     {
445         Mutex::Locker lhs_locker(m_mutex);
446         Mutex::Locker rhs_locker(rhs.m_mutex);
447         m_specs = rhs.m_specs;
448     }
449 
~ModuleSpecList()450     ~ModuleSpecList ()
451     {
452     }
453 
454     ModuleSpecList &
455     operator = (const ModuleSpecList &rhs)
456     {
457         if (this != &rhs)
458         {
459             Mutex::Locker lhs_locker(m_mutex);
460             Mutex::Locker rhs_locker(rhs.m_mutex);
461             m_specs = rhs.m_specs;
462         }
463         return *this;
464     }
465 
466     size_t
GetSize()467     GetSize() const
468     {
469         Mutex::Locker locker(m_mutex);
470         return m_specs.size();
471     }
472 
473     void
Clear()474     Clear ()
475     {
476         Mutex::Locker locker(m_mutex);
477         m_specs.clear();
478     }
479 
480     void
Append(const ModuleSpec & spec)481     Append (const ModuleSpec &spec)
482     {
483         Mutex::Locker locker(m_mutex);
484         m_specs.push_back (spec);
485     }
486 
487     void
Append(const ModuleSpecList & rhs)488     Append (const ModuleSpecList &rhs)
489     {
490         Mutex::Locker lhs_locker(m_mutex);
491         Mutex::Locker rhs_locker(rhs.m_mutex);
492         m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
493     }
494 
495     // The index "i" must be valid and this can't be used in
496     // multi-threaded code as no mutex lock is taken.
497     ModuleSpec &
GetModuleSpecRefAtIndex(size_t i)498     GetModuleSpecRefAtIndex (size_t i)
499     {
500         return m_specs[i];
501     }
502     bool
GetModuleSpecAtIndex(size_t i,ModuleSpec & module_spec)503     GetModuleSpecAtIndex (size_t i, ModuleSpec &module_spec) const
504     {
505         Mutex::Locker locker(m_mutex);
506         if (i < m_specs.size())
507         {
508             module_spec = m_specs[i];
509             return true;
510         }
511         module_spec.Clear();
512         return false;
513     }
514 
515 
516     bool
FindMatchingModuleSpec(const ModuleSpec & module_spec,ModuleSpec & match_module_spec)517     FindMatchingModuleSpec (const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const
518     {
519         Mutex::Locker locker(m_mutex);
520         bool exact_arch_match = true;
521         for (auto spec: m_specs)
522         {
523             if (spec.Matches(module_spec, exact_arch_match))
524             {
525                 match_module_spec = spec;
526                 return true;
527             }
528         }
529 
530         // If there was an architecture, retry with a compatible arch
531         if (module_spec.GetArchitecturePtr())
532         {
533             exact_arch_match = false;
534             for (auto spec: m_specs)
535             {
536                 if (spec.Matches(module_spec, exact_arch_match))
537                 {
538                     match_module_spec = spec;
539                     return true;
540                 }
541             }
542         }
543         match_module_spec.Clear();
544         return false;
545     }
546 
547     size_t
FindMatchingModuleSpecs(const ModuleSpec & module_spec,ModuleSpecList & matching_list)548     FindMatchingModuleSpecs (const ModuleSpec &module_spec, ModuleSpecList &matching_list) const
549     {
550         Mutex::Locker locker(m_mutex);
551         bool exact_arch_match = true;
552         const size_t initial_match_count = matching_list.GetSize();
553         for (auto spec: m_specs)
554         {
555             if (spec.Matches(module_spec, exact_arch_match))
556                 matching_list.Append (spec);
557         }
558 
559         // If there was an architecture, retry with a compatible arch if no matches were found
560         if (module_spec.GetArchitecturePtr() && (initial_match_count == matching_list.GetSize()))
561         {
562             exact_arch_match = false;
563             for (auto spec: m_specs)
564             {
565                 if (spec.Matches(module_spec, exact_arch_match))
566                     matching_list.Append (spec);
567             }
568         }
569         return matching_list.GetSize() - initial_match_count;
570     }
571 
572     void
Dump(Stream & strm)573     Dump (Stream &strm)
574     {
575         Mutex::Locker locker(m_mutex);
576         uint32_t idx = 0;
577         for (auto spec: m_specs)
578         {
579             strm.Printf("[%u] ", idx);
580             spec.Dump (strm);
581             strm.EOL();
582             ++idx;
583         }
584     }
585 
586 protected:
587     typedef std::vector<ModuleSpec> collection; ///< The module collection type.
588     collection m_specs; ///< The collection of modules.
589     mutable Mutex m_mutex;
590 };
591 
592 } // namespace lldb_private
593 
594 #endif  // liblldb_ModuleSpec_h_
595