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
19namespace lldb_private {
20
21class ModuleSpec
22{
23public:
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
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
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
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 *
95    GetFileSpecPtr ()
96    {
97        if (m_file)
98            return &m_file;
99        return NULL;
100    }
101
102    const FileSpec *
103    GetFileSpecPtr () const
104    {
105        if (m_file)
106            return &m_file;
107        return NULL;
108    }
109
110    FileSpec &
111    GetFileSpec ()
112    {
113        return m_file;
114    }
115    const FileSpec &
116    GetFileSpec () const
117    {
118        return m_file;
119    }
120
121    FileSpec *
122    GetPlatformFileSpecPtr ()
123    {
124        if (m_platform_file)
125            return &m_platform_file;
126        return NULL;
127    }
128
129    const FileSpec *
130    GetPlatformFileSpecPtr () const
131    {
132        if (m_platform_file)
133            return &m_platform_file;
134        return NULL;
135    }
136
137    FileSpec &
138    GetPlatformFileSpec ()
139    {
140        return m_platform_file;
141    }
142
143    const FileSpec &
144    GetPlatformFileSpec () const
145    {
146        return m_platform_file;
147    }
148
149    FileSpec *
150    GetSymbolFileSpecPtr ()
151    {
152        if (m_symbol_file)
153            return &m_symbol_file;
154        return NULL;
155    }
156
157    const FileSpec *
158    GetSymbolFileSpecPtr () const
159    {
160        if (m_symbol_file)
161            return &m_symbol_file;
162        return NULL;
163    }
164
165    FileSpec &
166    GetSymbolFileSpec ()
167    {
168        return m_symbol_file;
169    }
170
171    const FileSpec &
172    GetSymbolFileSpec () const
173    {
174        return m_symbol_file;
175    }
176
177
178    ArchSpec *
179    GetArchitecturePtr ()
180    {
181        if (m_arch.IsValid())
182            return &m_arch;
183        return NULL;
184    }
185
186    const ArchSpec *
187    GetArchitecturePtr () const
188    {
189        if (m_arch.IsValid())
190            return &m_arch;
191        return NULL;
192    }
193
194    ArchSpec &
195    GetArchitecture ()
196    {
197        return m_arch;
198    }
199
200    const ArchSpec &
201    GetArchitecture () const
202    {
203        return m_arch;
204    }
205
206    UUID *
207    GetUUIDPtr ()
208    {
209        if (m_uuid.IsValid())
210            return &m_uuid;
211        return NULL;
212    }
213
214    const UUID *
215    GetUUIDPtr () const
216    {
217        if (m_uuid.IsValid())
218            return &m_uuid;
219        return NULL;
220    }
221
222    UUID &
223    GetUUID ()
224    {
225        return m_uuid;
226    }
227
228    const UUID &
229    GetUUID () const
230    {
231        return m_uuid;
232    }
233
234    ConstString &
235    GetObjectName ()
236    {
237        return m_object_name;
238    }
239
240    const ConstString &
241    GetObjectName () const
242    {
243        return m_object_name;
244    }
245
246    uint64_t
247    GetObjectOffset () const
248    {
249        return m_object_offset;
250    }
251
252    void
253    SetObjectOffset (uint64_t object_offset)
254    {
255        m_object_offset = object_offset;
256    }
257
258    TimeValue &
259    GetObjectModificationTime ()
260    {
261        return m_object_mod_time;
262    }
263
264    const TimeValue &
265    GetObjectModificationTime () const
266    {
267        return m_object_mod_time;
268    }
269
270    PathMappingList &
271    GetSourceMappingList () const
272    {
273        return m_source_mappings;
274    }
275
276    void
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
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
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
420protected:
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
432class ModuleSpecList
433{
434public:
435    ModuleSpecList () :
436        m_specs(),
437        m_mutex(Mutex::eMutexTypeRecursive)
438    {
439    }
440
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
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
467    GetSize() const
468    {
469        Mutex::Locker locker(m_mutex);
470        return m_specs.size();
471    }
472
473    void
474    Clear ()
475    {
476        Mutex::Locker locker(m_mutex);
477        m_specs.clear();
478    }
479
480    void
481    Append (const ModuleSpec &spec)
482    {
483        Mutex::Locker locker(m_mutex);
484        m_specs.push_back (spec);
485    }
486
487    void
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 &
498    GetModuleSpecRefAtIndex (size_t i)
499    {
500        return m_specs[i];
501    }
502    bool
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
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
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
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
586protected:
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