1195534Sscottl//===-- ModuleSpec.h --------------------------------------------*- C++ -*-===//
2238805Smav//
3195534Sscottl//                     The LLVM Compiler Infrastructure
4195534Sscottl//
5195534Sscottl// This file is distributed under the University of Illinois Open Source
6195534Sscottl// License. See LICENSE.TXT for details.
7195534Sscottl//
8195534Sscottl//===----------------------------------------------------------------------===//
9195534Sscottl
10195534Sscottl#ifndef liblldb_ModuleSpec_h_
11195534Sscottl#define liblldb_ModuleSpec_h_
12195534Sscottl
13195534Sscottl#include "lldb/Core/ArchSpec.h"
14195534Sscottl#include "lldb/Core/Stream.h"
15195534Sscottl#include "lldb/Core/UUID.h"
16195534Sscottl#include "lldb/Host/FileSpec.h"
17195534Sscottl#include "lldb/Target/PathMappingList.h"
18195534Sscottl
19195534Sscottlnamespace lldb_private {
20195534Sscottl
21195534Sscottlclass ModuleSpec
22195534Sscottl{
23195534Sscottlpublic:
24195534Sscottl    ModuleSpec () :
25195534Sscottl        m_file (),
26195534Sscottl        m_platform_file (),
27195534Sscottl        m_symbol_file (),
28195534Sscottl        m_arch (),
29195534Sscottl        m_uuid (),
30195534Sscottl        m_object_name (),
31195534Sscottl        m_object_offset (0),
32195534Sscottl        m_object_mod_time (),
33195534Sscottl        m_source_mappings ()
34195534Sscottl    {
35220576Smav    }
36195534Sscottl
37195534Sscottl    ModuleSpec (const FileSpec &file_spec) :
38195534Sscottl        m_file (file_spec),
39195534Sscottl        m_platform_file (),
40195534Sscottl        m_symbol_file (),
41195534Sscottl        m_arch (),
42195534Sscottl        m_uuid (),
43195534Sscottl        m_object_name (),
44195534Sscottl        m_object_offset (0),
45195534Sscottl        m_object_mod_time (),
46195534Sscottl        m_source_mappings ()
47195534Sscottl    {
48271146Simp    }
49271146Simp
50195534Sscottl    ModuleSpec (const FileSpec &file_spec, const ArchSpec &arch) :
51276344Smarius        m_file (file_spec),
52199176Smav        m_platform_file (),
53203030Smav        m_symbol_file (),
54199176Smav        m_arch (arch),
55199322Smav        m_uuid (),
56199176Smav        m_object_name (),
57271146Simp        m_object_offset (0),
58278034Ssmh        m_object_mod_time (),
59278034Ssmh        m_source_mappings ()
60278034Ssmh    {
61278034Ssmh    }
62278034Ssmh
63278034Ssmh    ModuleSpec (const ModuleSpec &rhs) :
64278034Ssmh        m_file (rhs.m_file),
65278034Ssmh        m_platform_file (rhs.m_platform_file),
66278034Ssmh        m_symbol_file (rhs.m_symbol_file),
67278034Ssmh        m_arch (rhs.m_arch),
68278034Ssmh        m_uuid (rhs.m_uuid),
69271146Simp        m_object_name (rhs.m_object_name),
70271146Simp        m_object_offset (rhs.m_object_offset),
71334453Smarius        m_object_mod_time (rhs.m_object_mod_time),
72327568Smav        m_source_mappings (rhs.m_source_mappings)
73244146Smav    {
74244146Smav    }
75244146Smav
76244146Smav    ModuleSpec &
77244146Smav    operator = (const ModuleSpec &rhs)
78326120Smav    {
79326120Smav        if (this != &rhs)
80326120Smav        {
81326120Smav            m_file = rhs.m_file;
82326120Smav            m_platform_file = rhs.m_platform_file;
83317673Smav            m_symbol_file = rhs.m_symbol_file;
84317673Smav            m_arch = rhs.m_arch;
85317673Smav            m_uuid = rhs.m_uuid;
86317673Smav            m_object_name = rhs.m_object_name;
87317673Smav            m_object_offset = rhs.m_object_offset;
88317673Smav            m_object_mod_time = rhs.m_object_mod_time;
89317673Smav            m_source_mappings = rhs.m_source_mappings;
90317673Smav        }
91317673Smav        return *this;
92203030Smav    }
93203030Smav
94203030Smav    FileSpec *
95203030Smav    GetFileSpecPtr ()
96203030Smav    {
97203030Smav        if (m_file)
98203030Smav            return &m_file;
99203030Smav        return NULL;
100203030Smav    }
101203030Smav
102322572Smav    const FileSpec *
103203030Smav    GetFileSpecPtr () const
104203030Smav    {
105322572Smav        if (m_file)
106203030Smav            return &m_file;
107203030Smav        return NULL;
108203030Smav    }
109203030Smav
110203030Smav    FileSpec &
111203030Smav    GetFileSpec ()
112203030Smav    {
113203030Smav        return m_file;
114203030Smav    }
115203030Smav    const FileSpec &
116203030Smav    GetFileSpec () const
117203030Smav    {
118322572Smav        return m_file;
119203030Smav    }
120322572Smav
121322573Smav    FileSpec *
122322573Smav    GetPlatformFileSpecPtr ()
123322573Smav    {
124322573Smav        if (m_platform_file)
125322573Smav            return &m_platform_file;
126322573Smav        return NULL;
127331195Seadler    }
128331195Seadler
129331195Seadler    const FileSpec *
130331195Seadler    GetPlatformFileSpecPtr () const
131331195Seadler    {
132331195Seadler        if (m_platform_file)
133331195Seadler            return &m_platform_file;
134331195Seadler        return NULL;
135331195Seadler    }
136331195Seadler
137331195Seadler    FileSpec &
138331195Seadler    GetPlatformFileSpec ()
139331195Seadler    {
140331195Seadler        return m_platform_file;
141331195Seadler    }
142331195Seadler
143331195Seadler    const FileSpec &
144331195Seadler    GetPlatformFileSpec () const
145331195Seadler    {
146331195Seadler        return m_platform_file;
147211922Smav    }
148211922Smav
149322572Smav    FileSpec *
150322572Smav    GetSymbolFileSpecPtr ()
151322572Smav    {
152218605Smav        if (m_symbol_file)
153218605Smav            return &m_symbol_file;
154218605Smav        return NULL;
155322572Smav    }
156221789Sjfv
157221789Sjfv    const FileSpec *
158258162Smav    GetSymbolFileSpecPtr () const
159258162Smav    {
160258162Smav        if (m_symbol_file)
161258162Smav            return &m_symbol_file;
162258162Smav        return NULL;
163258162Smav    }
164258162Smav
165258162Smav    FileSpec &
166258162Smav    GetSymbolFileSpec ()
167258162Smav    {
168258162Smav        return m_symbol_file;
169258162Smav    }
170258162Smav
171258162Smav    const FileSpec &
172258162Smav    GetSymbolFileSpec () const
173258162Smav    {
174258162Smav        return m_symbol_file;
175258162Smav    }
176258162Smav
177258162Smav
178258162Smav    ArchSpec *
179258162Smav    GetArchitecturePtr ()
180278034Ssmh    {
181244983Sjfv        if (m_arch.IsValid())
182244983Sjfv            return &m_arch;
183258162Smav        return NULL;
184258162Smav    }
185258162Smav
186258162Smav    const ArchSpec *
187258162Smav    GetArchitecturePtr () const
188258162Smav    {
189275101Smav        if (m_arch.IsValid())
190275101Smav            return &m_arch;
191275101Smav        return NULL;
192275101Smav    }
193275101Smav
194275101Smav    ArchSpec &
195275101Smav    GetArchitecture ()
196275101Smav    {
197258162Smav        return m_arch;
198258162Smav    }
199258162Smav
200258162Smav    const ArchSpec &
201258162Smav    GetArchitecture () const
202258162Smav    {
203258162Smav        return m_arch;
204322572Smav    }
205322572Smav
206258162Smav    UUID *
207258162Smav    GetUUIDPtr ()
208258162Smav    {
209258162Smav        if (m_uuid.IsValid())
210258162Smav            return &m_uuid;
211258162Smav        return NULL;
212258162Smav    }
213258162Smav
214298983Smav    const UUID *
215298983Smav    GetUUIDPtr () const
216298983Smav    {
217298983Smav        if (m_uuid.IsValid())
218298983Smav            return &m_uuid;
219298983Smav        return NULL;
220298983Smav    }
221298983Smav
222298983Smav    UUID &
223322572Smav    GetUUID ()
224322572Smav    {
225322572Smav        return m_uuid;
226322572Smav    }
227322572Smav
228322572Smav    const UUID &
229322572Smav    GetUUID () const
230322572Smav    {
231322572Smav        return m_uuid;
232322572Smav    }
233322572Smav
234221789Sjfv    ConstString &
235239907Smav    GetObjectName ()
236304658Savg    {
237239907Smav        return m_object_name;
238203030Smav    }
239203030Smav
240203030Smav    const ConstString &
241203030Smav    GetObjectName () const
242285020Smav    {
243285020Smav        return m_object_name;
244285020Smav    }
245285020Smav
246285020Smav    uint64_t
247285020Smav    GetObjectOffset () const
248285020Smav    {
249285020Smav        return m_object_offset;
250271163Smav    }
251271163Smav
252271163Smav    void
253271163Smav    SetObjectOffset (uint64_t object_offset)
254271163Smav    {
255271163Smav        m_object_offset = object_offset;
256271163Smav    }
257271163Smav
258271163Smav    TimeValue &
259271163Smav    GetObjectModificationTime ()
260271163Smav    {
261271163Smav        return m_object_mod_time;
262271163Smav    }
263271163Smav
264271163Smav    const TimeValue &
265271163Smav    GetObjectModificationTime () const
266271163Smav    {
267271163Smav        return m_object_mod_time;
268271163Smav    }
269271163Smav
270271163Smav    PathMappingList &
271271163Smav    GetSourceMappingList () const
272271163Smav    {
273271163Smav        return m_source_mappings;
274271163Smav    }
275207499Smav
276207499Smav    void
277207499Smav    Clear ()
278207499Smav    {
279207499Smav        m_file.Clear();
280207499Smav        m_platform_file.Clear();
281207499Smav        m_symbol_file.Clear();
282207499Smav        m_arch.Clear();
283207499Smav        m_uuid.Clear();
284207499Smav        m_object_name.Clear();
285207499Smav        m_object_offset = 0;
286207499Smav        m_source_mappings.Clear(false);
287207499Smav        m_object_mod_time.Clear();
288207499Smav    }
289207499Smav
290207499Smav
291207499Smav    explicit operator bool () const
292207499Smav    {
293207499Smav        if (m_file)
294207499Smav            return true;
295207499Smav        if (m_platform_file)
296207499Smav            return true;
297207499Smav        if (m_symbol_file)
298207499Smav            return true;
299207499Smav        if (m_arch.IsValid())
300207499Smav            return true;
301207499Smav        if (m_uuid.IsValid())
302207499Smav            return true;
303207499Smav        if (m_object_name)
304207499Smav            return true;
305207499Smav        if (m_object_mod_time.IsValid())
306207499Smav            return true;
307207499Smav        return false;
308207499Smav    }
309207499Smav
310207499Smav    void
311207499Smav    Dump (Stream &strm)
312207499Smav    {
313207499Smav        bool dumped_something = false;
314207499Smav        if (m_file)
315207499Smav        {
316207499Smav            strm.PutCString("file = '");
317207499Smav            strm << m_file;
318207499Smav            strm.PutCString("'");
319207499Smav            dumped_something = true;
320207499Smav        }
321207499Smav        if (m_platform_file)
322207499Smav        {
323207499Smav            if (dumped_something)
324207499Smav                strm.PutCString(", ");
325207499Smav            strm.PutCString("platform_file = '");
326207499Smav            strm << m_platform_file;
327207499Smav            strm.PutCString("'");
328207499Smav            dumped_something = true;
329207499Smav        }
330207499Smav        if (m_symbol_file)
331207499Smav        {
332207499Smav            if (dumped_something)
333224603Smav                strm.PutCString(", ");
334207499Smav            strm.PutCString("symbol_file = '");
335207499Smav            strm << m_symbol_file;
336207499Smav            strm.PutCString("'");
337207499Smav            dumped_something = true;
338207499Smav        }
339207499Smav        if (m_arch.IsValid())
340207499Smav        {
341207499Smav            if (dumped_something)
342207499Smav                strm.PutCString(", ");
343207499Smav            strm.Printf("arch = %s", m_arch.GetTriple().str().c_str());
344271403Smav            dumped_something = true;
345208907Smav        }
346208907Smav        if (m_uuid.IsValid())
347203030Smav        {
348203030Smav            if (dumped_something)
349203030Smav                strm.PutCString(", ");
350279573Semaste            strm.PutCString("uuid = ");
351297447Szbb            m_uuid.Dump(&strm);
352203030Smav            dumped_something = true;
353199176Smav        }
354199176Smav        if (m_object_name)
355271146Simp        {
356271146Simp            if (dumped_something)
357271146Simp                strm.PutCString(", ");
358220565Smav            strm.Printf("object_name = %s", m_object_name.GetCString());
359271146Simp            dumped_something = true;
360271146Simp        }
361271146Simp        if (m_object_offset > 0)
362271146Simp        {
363271146Simp            if (dumped_something)
364228200Smav                strm.PutCString(", ");
365195534Sscottl            strm.Printf("object_offset = 0x%" PRIx64, m_object_offset);
366195534Sscottl            dumped_something = true;
367195534Sscottl        }
368199176Smav        if (m_object_mod_time.IsValid())
369199322Smav        {
370199322Smav            if (dumped_something)
371203030Smav                strm.PutCString(", ");
372199322Smav            strm.Printf("object_mod_time = 0x%" PRIx64, m_object_mod_time.GetAsSecondsSinceJan1_1970());
373260163Szbb            dumped_something = true;
374260163Szbb        }
375260163Szbb    }
376260163Szbb
377260163Szbb    bool
378260163Szbb    Matches (const ModuleSpec &match_module_spec, bool exact_arch_match) const
379260163Szbb    {
380199322Smav        if (match_module_spec.GetUUIDPtr() && match_module_spec.GetUUID() != GetUUID())
381199322Smav            return false;
382199322Smav        if (match_module_spec.GetObjectName() && match_module_spec.GetObjectName() != GetObjectName())
383199322Smav            return false;
384199322Smav        if (match_module_spec.GetFileSpecPtr())
385288111Smav        {
386288111Smav            const FileSpec &fspec = match_module_spec.GetFileSpec();
387288111Smav            if (!FileSpec::Equal(fspec, GetFileSpec(), fspec.GetDirectory().IsEmpty() == false))
388199322Smav                return false;
389199322Smav        }
390199322Smav        if (match_module_spec.GetPlatformFileSpecPtr())
391203030Smav        {
392228200Smav            const FileSpec &fspec = match_module_spec.GetPlatformFileSpec();
393228200Smav            if (!FileSpec::Equal(fspec, GetPlatformFileSpec(), fspec.GetDirectory().IsEmpty() == false))
394199717Smav                return false;
395199717Smav
396199717Smav        }
397199717Smav        if (match_module_spec.GetSymbolFileSpecPtr())
398199322Smav        {
399199322Smav            const FileSpec &fspec = match_module_spec.GetSymbolFileSpec();
400199322Smav            if (!FileSpec::Equal(fspec, GetSymbolFileSpec(), fspec.GetDirectory().IsEmpty() == false))
401280393Smav                return false;
402199322Smav
403199322Smav        }
404288111Smav        if (match_module_spec.GetArchitecturePtr())
405199322Smav        {
406199322Smav            if (exact_arch_match)
407280393Smav            {
408199322Smav                if (!GetArchitecture().IsExactMatch(match_module_spec.GetArchitecture()))
409199322Smav                    return false;
410199322Smav            }
411199322Smav            else
412199322Smav            {
413199322Smav                if (!GetArchitecture().IsCompatibleMatch(match_module_spec.GetArchitecture()))
414199176Smav                    return false;
415199176Smav            }
416203030Smav        }
417195534Sscottl        return true;
418199322Smav    }
419199322Smav
420199176Smavprotected:
421199176Smav    FileSpec m_file;
422203030Smav    FileSpec m_platform_file;
423203030Smav    FileSpec m_symbol_file;
424199176Smav    ArchSpec m_arch;
425199176Smav    UUID m_uuid;
426199176Smav    ConstString m_object_name;
427280393Smav    uint64_t m_object_offset;
428199176Smav    TimeValue m_object_mod_time;
429199176Smav    mutable PathMappingList m_source_mappings;
430199176Smav};
431280393Smav
432195534Sscottlclass ModuleSpecList
433195534Sscottl{
434195534Sscottlpublic:
435285789Szbb    ModuleSpecList () :
436285789Szbb        m_specs(),
437285789Szbb        m_mutex(Mutex::eMutexTypeRecursive)
438285789Szbb    {
439285789Szbb    }
440285789Szbb
441285789Szbb    ModuleSpecList (const ModuleSpecList &rhs) :
442285789Szbb        m_specs(),
443285789Szbb        m_mutex(Mutex::eMutexTypeRecursive)
444285789Szbb    {
445285789Szbb        Mutex::Locker lhs_locker(m_mutex);
446285789Szbb        Mutex::Locker rhs_locker(rhs.m_mutex);
447285789Szbb        m_specs = rhs.m_specs;
448285789Szbb    }
449285789Szbb
450285789Szbb    ~ModuleSpecList ()
451285789Szbb    {
452285789Szbb    }
453285789Szbb
454285789Szbb    ModuleSpecList &
455285789Szbb    operator = (const ModuleSpecList &rhs)
456285789Szbb    {
457271146Simp        if (this != &rhs)
458195534Sscottl        {
459195534Sscottl            Mutex::Locker lhs_locker(m_mutex);
460271146Simp            Mutex::Locker rhs_locker(rhs.m_mutex);
461199322Smav            m_specs = rhs.m_specs;
462203030Smav        }
463285789Szbb        return *this;
464285789Szbb    }
465195534Sscottl
466285789Szbb    size_t
467285789Szbb    GetSize() const
468285789Szbb    {
469199322Smav        Mutex::Locker locker(m_mutex);
470203030Smav        return m_specs.size();
471203030Smav    }
472203030Smav
473199322Smav    void
474199322Smav    Clear ()
475271146Simp    {
476271146Simp        Mutex::Locker locker(m_mutex);
477271146Simp        m_specs.clear();
478271146Simp    }
479271146Simp
480271146Simp    void
481297921Smav    Append (const ModuleSpec &spec)
482297921Smav    {
483271146Simp        Mutex::Locker locker(m_mutex);
484271146Simp        m_specs.push_back (spec);
485271146Simp    }
486271146Simp
487277100Skib    void
488277100Skib    Append (const ModuleSpecList &rhs)
489277100Skib    {
490277100Skib        Mutex::Locker lhs_locker(m_mutex);
491277100Skib        Mutex::Locker rhs_locker(rhs.m_mutex);
492277100Skib        m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
493195534Sscottl    }
494195534Sscottl
495195534Sscottl    // The index "i" must be valid and this can't be used in
496285789Szbb    // multi-threaded code as no mutex lock is taken.
497297447Szbb    ModuleSpec &
498297447Szbb    GetModuleSpecRefAtIndex (size_t i)
499297447Szbb    {
500285789Szbb        return m_specs[i];
501285789Szbb    }
502285789Szbb    bool
503285789Szbb    GetModuleSpecAtIndex (size_t i, ModuleSpec &module_spec) const
504285789Szbb    {
505285789Szbb        Mutex::Locker locker(m_mutex);
506285789Szbb        if (i < m_specs.size())
507285789Szbb        {
508285789Szbb            module_spec = m_specs[i];
509285789Szbb            return true;
510285789Szbb        }
511285789Szbb        module_spec.Clear();
512285789Szbb        return false;
513285789Szbb    }
514285789Szbb
515285789Szbb
516285789Szbb    bool
517285789Szbb    FindMatchingModuleSpec (const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const
518285789Szbb    {
519285789Szbb        Mutex::Locker locker(m_mutex);
520285789Szbb        bool exact_arch_match = true;
521285789Szbb        for (auto spec: m_specs)
522285789Szbb        {
523285789Szbb            if (spec.Matches(module_spec, exact_arch_match))
524285789Szbb            {
525285789Szbb                match_module_spec = spec;
526285789Szbb                return true;
527285789Szbb            }
528285789Szbb        }
529285789Szbb
530285789Szbb        // If there was an architecture, retry with a compatible arch
531285789Szbb        if (module_spec.GetArchitecturePtr())
532285789Szbb        {
533285789Szbb            exact_arch_match = false;
534285789Szbb            for (auto spec: m_specs)
535285789Szbb            {
536285789Szbb                if (spec.Matches(module_spec, exact_arch_match))
537285789Szbb                {
538285789Szbb                    match_module_spec = spec;
539285789Szbb                    return true;
540285789Szbb                }
541285789Szbb            }
542285789Szbb        }
543285789Szbb        match_module_spec.Clear();
544285789Szbb        return false;
545285789Szbb    }
546207511Smav
547195534Sscottl    size_t
548271146Simp    FindMatchingModuleSpecs (const ModuleSpec &module_spec, ModuleSpecList &matching_list) const
549285789Szbb    {
550195534Sscottl        Mutex::Locker locker(m_mutex);
551297793Spfg        bool exact_arch_match = true;
552222304Smav        const size_t initial_match_count = matching_list.GetSize();
553195534Sscottl        for (auto spec: m_specs)
554195534Sscottl        {
555271146Simp            if (spec.Matches(module_spec, exact_arch_match))
556195534Sscottl                matching_list.Append (spec);
557245875Smav        }
558256843Smav
559278034Ssmh        // If there was an architecture, retry with a compatible arch if no matches were found
560278034Ssmh        if (module_spec.GetArchitecturePtr() && (initial_match_count == matching_list.GetSize()))
561278034Ssmh        {
562278034Ssmh            exact_arch_match = false;
563195534Sscottl            for (auto spec: m_specs)
564256843Smav            {
565256843Smav                if (spec.Matches(module_spec, exact_arch_match))
566285789Szbb                    matching_list.Append (spec);
567285789Szbb            }
568256843Smav        }
569256843Smav        return matching_list.GetSize() - initial_match_count;
570285789Szbb    }
571285789Szbb
572285789Szbb    void
573285789Szbb    Dump (Stream &strm)
574256843Smav    {
575285789Szbb        Mutex::Locker locker(m_mutex);
576285789Szbb        uint32_t idx = 0;
577285789Szbb        for (auto spec: m_specs)
578285789Szbb        {
579285789Szbb            strm.Printf("[%u] ", idx);
580285789Szbb            spec.Dump (strm);
581285789Szbb            strm.EOL();
582285789Szbb            ++idx;
583285789Szbb        }
584285789Szbb    }
585285789Szbb
586285789Szbbprotected:
587285789Szbb    typedef std::vector<ModuleSpec> collection; ///< The module collection type.
588285789Szbb    collection m_specs; ///< The collection of modules.
589285789Szbb    mutable Mutex m_mutex;
590285789Szbb};
591285789Szbb
592285789Szbb} // namespace lldb_private
593285789Szbb
594285789Szbb#endif  // liblldb_ModuleSpec_h_
595285789Szbb