190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber//===-- ModuleList.cpp ------------------------------------------*- C++ -*-===//
2f71323e297a928af368937089d3ed71239786f86Andreas Huber//
390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber//                     The LLVM Compiler Infrastructure
4f71323e297a928af368937089d3ed71239786f86Andreas Huber//
5f71323e297a928af368937089d3ed71239786f86Andreas Huber// This file is distributed under the University of Illinois Open Source
6f71323e297a928af368937089d3ed71239786f86Andreas Huber// License. See LICENSE.TXT for details.
7f71323e297a928af368937089d3ed71239786f86Andreas Huber//
8f71323e297a928af368937089d3ed71239786f86Andreas Huber//===----------------------------------------------------------------------===//
990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
1090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "lldb/Core/ModuleList.h"
111b362b15af34006e6a11974088a46d42b903418eJohann
12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// C Includes
131b362b15af34006e6a11974088a46d42b903418eJohann// C++ Includes
14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// Other libraries and framework includes
1590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// Project includes
16ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "lldb/Core/Log.h"
1790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "lldb/Core/Module.h"
1890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "lldb/Core/ModuleSpec.h"
19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "lldb/Host/Host.h"
2079f15823c34ae1e423108295e416213200bb280fAndreas Huber#include "lldb/Host/Symbols.h"
211b362b15af34006e6a11974088a46d42b903418eJohann#include "lldb/Symbol/ClangNamespaceDecl.h"
2290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "lldb/Symbol/ObjectFile.h"
2390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "lldb/Symbol/VariableList.h"
2490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
2590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberusing namespace lldb;
2690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberusing namespace lldb_private;
2790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
2890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber//----------------------------------------------------------------------
2990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber// ModuleList constructor
3090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber//----------------------------------------------------------------------
3190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberModuleList::ModuleList() :
3290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    m_modules(),
33    m_modules_mutex (Mutex::eMutexTypeRecursive),
34    m_notifier(NULL)
35{
36}
37
38//----------------------------------------------------------------------
39// Copy constructor
40//----------------------------------------------------------------------
41ModuleList::ModuleList(const ModuleList& rhs) :
42    m_modules(),
43    m_modules_mutex (Mutex::eMutexTypeRecursive)
44{
45    Mutex::Locker lhs_locker(m_modules_mutex);
46    Mutex::Locker rhs_locker(rhs.m_modules_mutex);
47    m_modules = rhs.m_modules;
48}
49
50ModuleList::ModuleList (ModuleList::Notifier* notifier) :
51    m_modules(),
52    m_modules_mutex (Mutex::eMutexTypeRecursive),
53    m_notifier(notifier)
54{
55}
56
57//----------------------------------------------------------------------
58// Assignment operator
59//----------------------------------------------------------------------
60const ModuleList&
61ModuleList::operator= (const ModuleList& rhs)
62{
63    if (this != &rhs)
64    {
65        Mutex::Locker lhs_locker(m_modules_mutex);
66        Mutex::Locker rhs_locker(rhs.m_modules_mutex);
67        m_modules = rhs.m_modules;
68    }
69    return *this;
70}
71
72//----------------------------------------------------------------------
73// Destructor
74//----------------------------------------------------------------------
75ModuleList::~ModuleList()
76{
77}
78
79void
80ModuleList::AppendImpl (const ModuleSP &module_sp, bool use_notifier)
81{
82    if (module_sp)
83    {
84        Mutex::Locker locker(m_modules_mutex);
85        m_modules.push_back(module_sp);
86        if (use_notifier && m_notifier)
87            m_notifier->ModuleAdded(*this, module_sp);
88    }
89}
90
91void
92ModuleList::Append (const ModuleSP &module_sp)
93{
94    AppendImpl (module_sp);
95}
96
97void
98ModuleList::ReplaceEquivalent (const ModuleSP &module_sp)
99{
100    if (module_sp)
101    {
102        Mutex::Locker locker(m_modules_mutex);
103
104        // First remove any equivalent modules. Equivalent modules are modules
105        // whose path, platform path and architecture match.
106        ModuleSpec equivalent_module_spec (module_sp->GetFileSpec(), module_sp->GetArchitecture());
107        equivalent_module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
108
109        size_t idx = 0;
110        while (idx < m_modules.size())
111        {
112            ModuleSP module_sp (m_modules[idx]);
113            if (module_sp->MatchesModuleSpec (equivalent_module_spec))
114                RemoveImpl(m_modules.begin() + idx);
115            else
116                ++idx;
117        }
118        // Now add the new module to the list
119        Append(module_sp);
120    }
121}
122
123bool
124ModuleList::AppendIfNeeded (const ModuleSP &module_sp)
125{
126    if (module_sp)
127    {
128        Mutex::Locker locker(m_modules_mutex);
129        collection::iterator pos, end = m_modules.end();
130        for (pos = m_modules.begin(); pos != end; ++pos)
131        {
132            if (pos->get() == module_sp.get())
133                return false; // Already in the list
134        }
135        // Only push module_sp on the list if it wasn't already in there.
136        Append(module_sp);
137        return true;
138    }
139    return false;
140}
141
142void
143ModuleList::Append (const ModuleList& module_list)
144{
145    for (auto pos : module_list.m_modules)
146        Append(pos);
147}
148
149bool
150ModuleList::AppendIfNeeded (const ModuleList& module_list)
151{
152    bool any_in = false;
153    for (auto pos : module_list.m_modules)
154        any_in = AppendIfNeeded(pos) | any_in;
155    return any_in;
156}
157
158bool
159ModuleList::RemoveImpl (const ModuleSP &module_sp, bool use_notifier)
160{
161    if (module_sp)
162    {
163        Mutex::Locker locker(m_modules_mutex);
164        collection::iterator pos, end = m_modules.end();
165        for (pos = m_modules.begin(); pos != end; ++pos)
166        {
167            if (pos->get() == module_sp.get())
168            {
169                m_modules.erase (pos);
170                if (use_notifier && m_notifier)
171                    m_notifier->ModuleRemoved(*this, module_sp);
172                return true;
173            }
174        }
175    }
176    return false;
177}
178
179ModuleList::collection::iterator
180ModuleList::RemoveImpl (ModuleList::collection::iterator pos, bool use_notifier)
181{
182    ModuleSP module_sp(*pos);
183    collection::iterator retval = m_modules.erase(pos);
184    if (use_notifier && m_notifier)
185        m_notifier->ModuleRemoved(*this, module_sp);
186    return retval;
187}
188
189bool
190ModuleList::Remove (const ModuleSP &module_sp)
191{
192    return RemoveImpl (module_sp);
193}
194
195bool
196ModuleList::ReplaceModule (const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp)
197{
198    if (!RemoveImpl(old_module_sp, false))
199        return false;
200    AppendImpl (new_module_sp, false);
201    if (m_notifier)
202        m_notifier->ModuleUpdated(*this, old_module_sp,new_module_sp);
203    return true;
204}
205
206bool
207ModuleList::RemoveIfOrphaned (const Module *module_ptr)
208{
209    if (module_ptr)
210    {
211        Mutex::Locker locker(m_modules_mutex);
212        collection::iterator pos, end = m_modules.end();
213        for (pos = m_modules.begin(); pos != end; ++pos)
214        {
215            if (pos->get() == module_ptr)
216            {
217                if (pos->unique())
218                {
219                    pos = RemoveImpl(pos);
220                    return true;
221                }
222                else
223                    return false;
224            }
225        }
226    }
227    return false;
228}
229
230size_t
231ModuleList::RemoveOrphans (bool mandatory)
232{
233    Mutex::Locker locker;
234
235    if (mandatory)
236    {
237        locker.Lock (m_modules_mutex);
238    }
239    else
240    {
241        // Not mandatory, remove orphans if we can get the mutex
242        if (!locker.TryLock(m_modules_mutex))
243            return 0;
244    }
245    collection::iterator pos = m_modules.begin();
246    size_t remove_count = 0;
247    while (pos != m_modules.end())
248    {
249        if (pos->unique())
250        {
251            pos = RemoveImpl(pos);
252            ++remove_count;
253        }
254        else
255        {
256            ++pos;
257        }
258    }
259    return remove_count;
260}
261
262size_t
263ModuleList::Remove (ModuleList &module_list)
264{
265    Mutex::Locker locker(m_modules_mutex);
266    size_t num_removed = 0;
267    collection::iterator pos, end = module_list.m_modules.end();
268    for (pos = module_list.m_modules.begin(); pos != end; ++pos)
269    {
270        if (Remove (*pos))
271            ++num_removed;
272    }
273    return num_removed;
274}
275
276
277void
278ModuleList::Clear()
279{
280    ClearImpl();
281}
282
283void
284ModuleList::Destroy()
285{
286    ClearImpl();
287}
288
289void
290ModuleList::ClearImpl (bool use_notifier)
291{
292    Mutex::Locker locker(m_modules_mutex);
293    if (use_notifier && m_notifier)
294        m_notifier->WillClearList(*this);
295    m_modules.clear();
296}
297
298Module*
299ModuleList::GetModulePointerAtIndex (size_t idx) const
300{
301    Mutex::Locker locker(m_modules_mutex);
302    return GetModulePointerAtIndexUnlocked(idx);
303}
304
305Module*
306ModuleList::GetModulePointerAtIndexUnlocked (size_t idx) const
307{
308    if (idx < m_modules.size())
309        return m_modules[idx].get();
310    return NULL;
311}
312
313ModuleSP
314ModuleList::GetModuleAtIndex(size_t idx) const
315{
316    Mutex::Locker locker(m_modules_mutex);
317    return GetModuleAtIndexUnlocked(idx);
318}
319
320ModuleSP
321ModuleList::GetModuleAtIndexUnlocked(size_t idx) const
322{
323    ModuleSP module_sp;
324    if (idx < m_modules.size())
325        module_sp = m_modules[idx];
326    return module_sp;
327}
328
329size_t
330ModuleList::FindFunctions (const ConstString &name,
331                           uint32_t name_type_mask,
332                           bool include_symbols,
333                           bool include_inlines,
334                           bool append,
335                           SymbolContextList &sc_list) const
336{
337    if (!append)
338        sc_list.Clear();
339
340    const size_t old_size = sc_list.GetSize();
341
342    if (name_type_mask & eFunctionNameTypeAuto)
343    {
344        ConstString lookup_name;
345        uint32_t lookup_name_type_mask = 0;
346        bool match_name_after_lookup = false;
347        Module::PrepareForFunctionNameLookup (name, name_type_mask,
348                                              lookup_name,
349                                              lookup_name_type_mask,
350                                              match_name_after_lookup);
351
352        Mutex::Locker locker(m_modules_mutex);
353        collection::const_iterator pos, end = m_modules.end();
354        for (pos = m_modules.begin(); pos != end; ++pos)
355        {
356            (*pos)->FindFunctions (lookup_name,
357                                   NULL,
358                                   lookup_name_type_mask,
359                                   include_symbols,
360                                   include_inlines,
361                                   true,
362                                   sc_list);
363        }
364
365        if (match_name_after_lookup)
366        {
367            SymbolContext sc;
368            size_t i = old_size;
369            while (i<sc_list.GetSize())
370            {
371                if (sc_list.GetContextAtIndex(i, sc))
372                {
373                    const char *func_name = sc.GetFunctionName().GetCString();
374                    if (func_name && strstr (func_name, name.GetCString()) == NULL)
375                    {
376                        // Remove the current context
377                        sc_list.RemoveContextAtIndex(i);
378                        // Don't increment i and continue in the loop
379                        continue;
380                    }
381                }
382                ++i;
383            }
384        }
385
386    }
387    else
388    {
389        Mutex::Locker locker(m_modules_mutex);
390        collection::const_iterator pos, end = m_modules.end();
391        for (pos = m_modules.begin(); pos != end; ++pos)
392        {
393            (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
394        }
395    }
396    return sc_list.GetSize() - old_size;
397}
398
399size_t
400ModuleList::FindFunctionSymbols (const ConstString &name,
401                                 uint32_t name_type_mask,
402                                 SymbolContextList& sc_list)
403{
404    const size_t old_size = sc_list.GetSize();
405
406    if (name_type_mask & eFunctionNameTypeAuto)
407    {
408        ConstString lookup_name;
409        uint32_t lookup_name_type_mask = 0;
410        bool match_name_after_lookup = false;
411        Module::PrepareForFunctionNameLookup (name, name_type_mask,
412                                              lookup_name,
413                                              lookup_name_type_mask,
414                                              match_name_after_lookup);
415
416        Mutex::Locker locker(m_modules_mutex);
417        collection::const_iterator pos, end = m_modules.end();
418        for (pos = m_modules.begin(); pos != end; ++pos)
419        {
420            (*pos)->FindFunctionSymbols (lookup_name,
421                                   lookup_name_type_mask,
422                                   sc_list);
423        }
424
425        if (match_name_after_lookup)
426        {
427            SymbolContext sc;
428            size_t i = old_size;
429            while (i<sc_list.GetSize())
430            {
431                if (sc_list.GetContextAtIndex(i, sc))
432                {
433                    const char *func_name = sc.GetFunctionName().GetCString();
434                    if (func_name && strstr (func_name, name.GetCString()) == NULL)
435                    {
436                        // Remove the current context
437                        sc_list.RemoveContextAtIndex(i);
438                        // Don't increment i and continue in the loop
439                        continue;
440                    }
441                }
442                ++i;
443            }
444        }
445
446    }
447    else
448    {
449        Mutex::Locker locker(m_modules_mutex);
450        collection::const_iterator pos, end = m_modules.end();
451        for (pos = m_modules.begin(); pos != end; ++pos)
452        {
453            (*pos)->FindFunctionSymbols (name, name_type_mask, sc_list);
454        }
455    }
456
457    return sc_list.GetSize() - old_size;
458}
459
460size_t
461ModuleList::FindCompileUnits (const FileSpec &path,
462                              bool append,
463                              SymbolContextList &sc_list) const
464{
465    if (!append)
466        sc_list.Clear();
467
468    Mutex::Locker locker(m_modules_mutex);
469    collection::const_iterator pos, end = m_modules.end();
470    for (pos = m_modules.begin(); pos != end; ++pos)
471    {
472        (*pos)->FindCompileUnits (path, true, sc_list);
473    }
474
475    return sc_list.GetSize();
476}
477
478size_t
479ModuleList::FindGlobalVariables (const ConstString &name,
480                                 bool append,
481                                 size_t max_matches,
482                                 VariableList& variable_list) const
483{
484    size_t initial_size = variable_list.GetSize();
485    Mutex::Locker locker(m_modules_mutex);
486    collection::const_iterator pos, end = m_modules.end();
487    for (pos = m_modules.begin(); pos != end; ++pos)
488    {
489        (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list);
490    }
491    return variable_list.GetSize() - initial_size;
492}
493
494
495size_t
496ModuleList::FindGlobalVariables (const RegularExpression& regex,
497                                 bool append,
498                                 size_t max_matches,
499                                 VariableList& variable_list) const
500{
501    size_t initial_size = variable_list.GetSize();
502    Mutex::Locker locker(m_modules_mutex);
503    collection::const_iterator pos, end = m_modules.end();
504    for (pos = m_modules.begin(); pos != end; ++pos)
505    {
506        (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list);
507    }
508    return variable_list.GetSize() - initial_size;
509}
510
511
512size_t
513ModuleList::FindSymbolsWithNameAndType (const ConstString &name,
514                                        SymbolType symbol_type,
515                                        SymbolContextList &sc_list,
516                                        bool append) const
517{
518    Mutex::Locker locker(m_modules_mutex);
519    if (!append)
520        sc_list.Clear();
521    size_t initial_size = sc_list.GetSize();
522
523    collection::const_iterator pos, end = m_modules.end();
524    for (pos = m_modules.begin(); pos != end; ++pos)
525        (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
526    return sc_list.GetSize() - initial_size;
527}
528
529size_t
530ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression &regex,
531                                             lldb::SymbolType symbol_type,
532                                             SymbolContextList &sc_list,
533                                             bool append) const
534{
535    Mutex::Locker locker(m_modules_mutex);
536    if (!append)
537        sc_list.Clear();
538    size_t initial_size = sc_list.GetSize();
539
540    collection::const_iterator pos, end = m_modules.end();
541    for (pos = m_modules.begin(); pos != end; ++pos)
542        (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
543    return sc_list.GetSize() - initial_size;
544}
545
546size_t
547ModuleList::FindModules (const ModuleSpec &module_spec, ModuleList& matching_module_list) const
548{
549    size_t existing_matches = matching_module_list.GetSize();
550
551    Mutex::Locker locker(m_modules_mutex);
552    collection::const_iterator pos, end = m_modules.end();
553    for (pos = m_modules.begin(); pos != end; ++pos)
554    {
555        ModuleSP module_sp(*pos);
556        if (module_sp->MatchesModuleSpec (module_spec))
557            matching_module_list.Append(module_sp);
558    }
559    return matching_module_list.GetSize() - existing_matches;
560}
561
562ModuleSP
563ModuleList::FindModule (const Module *module_ptr) const
564{
565    ModuleSP module_sp;
566
567    // Scope for "locker"
568    {
569        Mutex::Locker locker(m_modules_mutex);
570        collection::const_iterator pos, end = m_modules.end();
571
572        for (pos = m_modules.begin(); pos != end; ++pos)
573        {
574            if ((*pos).get() == module_ptr)
575            {
576                module_sp = (*pos);
577                break;
578            }
579        }
580    }
581    return module_sp;
582
583}
584
585ModuleSP
586ModuleList::FindModule (const UUID &uuid) const
587{
588    ModuleSP module_sp;
589
590    if (uuid.IsValid())
591    {
592        Mutex::Locker locker(m_modules_mutex);
593        collection::const_iterator pos, end = m_modules.end();
594
595        for (pos = m_modules.begin(); pos != end; ++pos)
596        {
597            if ((*pos)->GetUUID() == uuid)
598            {
599                module_sp = (*pos);
600                break;
601            }
602        }
603    }
604    return module_sp;
605}
606
607
608size_t
609ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, size_t max_matches, TypeList& types) const
610{
611    Mutex::Locker locker(m_modules_mutex);
612
613    size_t total_matches = 0;
614    collection::const_iterator pos, end = m_modules.end();
615    if (sc.module_sp)
616    {
617        // The symbol context "sc" contains a module so we want to search that
618        // one first if it is in our list...
619        for (pos = m_modules.begin(); pos != end; ++pos)
620        {
621            if (sc.module_sp.get() == (*pos).get())
622            {
623                total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types);
624
625                if (total_matches >= max_matches)
626                    break;
627            }
628        }
629    }
630
631    if (total_matches < max_matches)
632    {
633        SymbolContext world_sc;
634        for (pos = m_modules.begin(); pos != end; ++pos)
635        {
636            // Search the module if the module is not equal to the one in the symbol
637            // context "sc". If "sc" contains a empty module shared pointer, then
638            // the comparisong will always be true (valid_module_ptr != NULL).
639            if (sc.module_sp.get() != (*pos).get())
640                total_matches += (*pos)->FindTypes (world_sc, name, name_is_fully_qualified, max_matches, types);
641
642            if (total_matches >= max_matches)
643                break;
644        }
645    }
646
647    return total_matches;
648}
649
650bool
651ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const
652{
653    Mutex::Locker locker(m_modules_mutex);
654    collection::const_iterator pos, end = m_modules.end();
655    for (pos = m_modules.begin(); pos != end; ++pos)
656    {
657        if ((*pos)->FindSourceFile (orig_spec, new_spec))
658            return true;
659    }
660    return false;
661}
662
663
664
665ModuleSP
666ModuleList::FindFirstModule (const ModuleSpec &module_spec) const
667{
668    ModuleSP module_sp;
669    Mutex::Locker locker(m_modules_mutex);
670    collection::const_iterator pos, end = m_modules.end();
671    for (pos = m_modules.begin(); pos != end; ++pos)
672    {
673        ModuleSP module_sp(*pos);
674        if (module_sp->MatchesModuleSpec (module_spec))
675            return module_sp;
676    }
677    return module_sp;
678
679}
680
681size_t
682ModuleList::GetSize() const
683{
684    size_t size = 0;
685    {
686        Mutex::Locker locker(m_modules_mutex);
687        size = m_modules.size();
688    }
689    return size;
690}
691
692
693void
694ModuleList::Dump(Stream *s) const
695{
696//  s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
697//  s.Indent();
698//  s << "ModuleList\n";
699
700    Mutex::Locker locker(m_modules_mutex);
701    collection::const_iterator pos, end = m_modules.end();
702    for (pos = m_modules.begin(); pos != end; ++pos)
703    {
704        (*pos)->Dump(s);
705    }
706}
707
708void
709ModuleList::LogUUIDAndPaths (Log *log, const char *prefix_cstr)
710{
711    if (log)
712    {
713        Mutex::Locker locker(m_modules_mutex);
714        collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end();
715        for (pos = begin; pos != end; ++pos)
716        {
717            Module *module = pos->get();
718            const FileSpec &module_file_spec = module->GetFileSpec();
719            log->Printf ("%s[%u] %s (%s) \"%s\"",
720                         prefix_cstr ? prefix_cstr : "",
721                         (uint32_t)std::distance (begin, pos),
722                         module->GetUUID().GetAsString().c_str(),
723                         module->GetArchitecture().GetArchitectureName(),
724                         module_file_spec.GetPath().c_str());
725        }
726    }
727}
728
729bool
730ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) const
731{
732    Mutex::Locker locker(m_modules_mutex);
733    collection::const_iterator pos, end = m_modules.end();
734    for (pos = m_modules.begin(); pos != end; ++pos)
735    {
736        if ((*pos)->ResolveFileAddress (vm_addr, so_addr))
737            return true;
738    }
739
740    return false;
741}
742
743uint32_t
744ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) const
745{
746    // The address is already section offset so it has a module
747    uint32_t resolved_flags = 0;
748    ModuleSP module_sp (so_addr.GetModule());
749    if (module_sp)
750    {
751        resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr,
752                                                                    resolve_scope,
753                                                                    sc);
754    }
755    else
756    {
757        Mutex::Locker locker(m_modules_mutex);
758        collection::const_iterator pos, end = m_modules.end();
759        for (pos = m_modules.begin(); pos != end; ++pos)
760        {
761            resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr,
762                                                                     resolve_scope,
763                                                                     sc);
764            if (resolved_flags != 0)
765                break;
766        }
767    }
768
769    return resolved_flags;
770}
771
772uint32_t
773ModuleList::ResolveSymbolContextForFilePath
774(
775    const char *file_path,
776    uint32_t line,
777    bool check_inlines,
778    uint32_t resolve_scope,
779    SymbolContextList& sc_list
780)  const
781{
782    FileSpec file_spec(file_path, false);
783    return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
784}
785
786uint32_t
787ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) const
788{
789    Mutex::Locker locker(m_modules_mutex);
790    collection::const_iterator pos, end = m_modules.end();
791    for (pos = m_modules.begin(); pos != end; ++pos)
792    {
793        (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
794    }
795
796    return sc_list.GetSize();
797}
798
799size_t
800ModuleList::GetIndexForModule (const Module *module) const
801{
802    if (module)
803    {
804        Mutex::Locker locker(m_modules_mutex);
805        collection::const_iterator pos;
806        collection::const_iterator begin = m_modules.begin();
807        collection::const_iterator end = m_modules.end();
808        for (pos = begin; pos != end; ++pos)
809        {
810            if ((*pos).get() == module)
811                return std::distance (begin, pos);
812        }
813    }
814    return LLDB_INVALID_INDEX32;
815}
816
817static ModuleList &
818GetSharedModuleList ()
819{
820    // NOTE: Intentionally leak the module list so a program doesn't have to
821    // cleanup all modules and object files as it exits. This just wastes time
822    // doing a bunch of cleanup that isn't required.
823    static ModuleList *g_shared_module_list = NULL;
824    if (g_shared_module_list == NULL)
825        g_shared_module_list = new ModuleList(); // <--- Intentional leak!!!
826
827    return *g_shared_module_list;
828}
829
830bool
831ModuleList::ModuleIsInCache (const Module *module_ptr)
832{
833    if (module_ptr)
834    {
835        ModuleList &shared_module_list = GetSharedModuleList ();
836        return shared_module_list.FindModule (module_ptr).get() != NULL;
837    }
838    return false;
839}
840
841size_t
842ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list)
843{
844    return GetSharedModuleList ().FindModules (module_spec, matching_module_list);
845}
846
847size_t
848ModuleList::RemoveOrphanSharedModules (bool mandatory)
849{
850    return GetSharedModuleList ().RemoveOrphans(mandatory);
851}
852
853Error
854ModuleList::GetSharedModule
855(
856    const ModuleSpec &module_spec,
857    ModuleSP &module_sp,
858    const FileSpecList *module_search_paths_ptr,
859    ModuleSP *old_module_sp_ptr,
860    bool *did_create_ptr,
861    bool always_create
862)
863{
864    ModuleList &shared_module_list = GetSharedModuleList ();
865    Mutex::Locker locker(shared_module_list.m_modules_mutex);
866    char path[PATH_MAX];
867
868    Error error;
869
870    module_sp.reset();
871
872    if (did_create_ptr)
873        *did_create_ptr = false;
874    if (old_module_sp_ptr)
875        old_module_sp_ptr->reset();
876
877    const UUID *uuid_ptr = module_spec.GetUUIDPtr();
878    const FileSpec &module_file_spec = module_spec.GetFileSpec();
879    const ArchSpec &arch = module_spec.GetArchitecture();
880
881    // Make sure no one else can try and get or create a module while this
882    // function is actively working on it by doing an extra lock on the
883    // global mutex list.
884    if (always_create == false)
885    {
886        ModuleList matching_module_list;
887        const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list);
888        if (num_matching_modules > 0)
889        {
890            for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
891            {
892                module_sp = matching_module_list.GetModuleAtIndex(module_idx);
893
894                // Make sure the file for the module hasn't been modified
895                if (module_sp->FileHasChanged())
896                {
897                    if (old_module_sp_ptr && !old_module_sp_ptr->get())
898                        *old_module_sp_ptr = module_sp;
899
900                    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES));
901                    if (log)
902                        log->Printf("module changed: %p, removing from global module list", module_sp.get());
903
904                    shared_module_list.Remove (module_sp);
905                    module_sp.reset();
906                }
907                else
908                {
909                    // The module matches and the module was not modified from
910                    // when it was last loaded.
911                    return error;
912                }
913            }
914        }
915    }
916
917    if (module_sp)
918        return error;
919    else
920    {
921        module_sp.reset (new Module (module_spec));
922        // Make sure there are a module and an object file since we can specify
923        // a valid file path with an architecture that might not be in that file.
924        // By getting the object file we can guarantee that the architecture matches
925        if (module_sp)
926        {
927            if (module_sp->GetObjectFile())
928            {
929                // If we get in here we got the correct arch, now we just need
930                // to verify the UUID if one was given
931                if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
932                    module_sp.reset();
933                else
934                {
935                    if (did_create_ptr)
936                        *did_create_ptr = true;
937
938                    shared_module_list.ReplaceEquivalent(module_sp);
939                    return error;
940                }
941            }
942            else
943                module_sp.reset();
944        }
945    }
946
947    // Either the file didn't exist where at the path, or no path was given, so
948    // we now have to use more extreme measures to try and find the appropriate
949    // module.
950
951    // Fixup the incoming path in case the path points to a valid file, yet
952    // the arch or UUID (if one was passed in) don't match.
953    FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec);
954
955    // Don't look for the file if it appears to be the same one we already
956    // checked for above...
957    if (file_spec != module_file_spec)
958    {
959        if (!file_spec.Exists())
960        {
961            file_spec.GetPath(path, sizeof(path));
962            if (path[0] == '\0')
963                module_file_spec.GetPath(path, sizeof(path));
964            if (file_spec.Exists())
965            {
966                std::string uuid_str;
967                if (uuid_ptr && uuid_ptr->IsValid())
968                    uuid_str = uuid_ptr->GetAsString();
969
970                if (arch.IsValid())
971                {
972                    if (!uuid_str.empty())
973                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_str.c_str());
974                    else
975                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
976                }
977            }
978            else
979            {
980                error.SetErrorStringWithFormat("'%s' does not exist", path);
981            }
982            if (error.Fail())
983                module_sp.reset();
984            return error;
985        }
986
987
988        // Make sure no one else can try and get or create a module while this
989        // function is actively working on it by doing an extra lock on the
990        // global mutex list.
991        ModuleSpec platform_module_spec(module_spec);
992        platform_module_spec.GetFileSpec() = file_spec;
993        platform_module_spec.GetPlatformFileSpec() = file_spec;
994        ModuleList matching_module_list;
995        if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0)
996        {
997            module_sp = matching_module_list.GetModuleAtIndex(0);
998
999            // If we didn't have a UUID in mind when looking for the object file,
1000            // then we should make sure the modification time hasn't changed!
1001            if (platform_module_spec.GetUUIDPtr() == NULL)
1002            {
1003                TimeValue file_spec_mod_time(file_spec.GetModificationTime());
1004                if (file_spec_mod_time.IsValid())
1005                {
1006                    if (file_spec_mod_time != module_sp->GetModificationTime())
1007                    {
1008                        if (old_module_sp_ptr)
1009                            *old_module_sp_ptr = module_sp;
1010                        shared_module_list.Remove (module_sp);
1011                        module_sp.reset();
1012                    }
1013                }
1014            }
1015        }
1016
1017        if (module_sp.get() == NULL)
1018        {
1019            module_sp.reset (new Module (platform_module_spec));
1020            // Make sure there are a module and an object file since we can specify
1021            // a valid file path with an architecture that might not be in that file.
1022            // By getting the object file we can guarantee that the architecture matches
1023            if (module_sp && module_sp->GetObjectFile())
1024            {
1025                if (did_create_ptr)
1026                    *did_create_ptr = true;
1027
1028                shared_module_list.ReplaceEquivalent(module_sp);
1029            }
1030            else
1031            {
1032                file_spec.GetPath(path, sizeof(path));
1033
1034                if (file_spec)
1035                {
1036                    if (arch.IsValid())
1037                        error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
1038                    else
1039                        error.SetErrorStringWithFormat("unable to open '%s'", path);
1040                }
1041                else
1042                {
1043                    std::string uuid_str;
1044                    if (uuid_ptr && uuid_ptr->IsValid())
1045                        uuid_str = uuid_ptr->GetAsString();
1046
1047                    if (!uuid_str.empty())
1048                        error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_str.c_str());
1049                    else
1050                        error.SetErrorStringWithFormat("cannot locate a module");
1051                }
1052            }
1053        }
1054    }
1055
1056    return error;
1057}
1058
1059bool
1060ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp)
1061{
1062    return GetSharedModuleList ().Remove (module_sp);
1063}
1064
1065bool
1066ModuleList::RemoveSharedModuleIfOrphaned (const Module *module_ptr)
1067{
1068    return GetSharedModuleList ().RemoveIfOrphaned (module_ptr);
1069}
1070
1071bool
1072ModuleList::LoadScriptingResourcesInTarget (Target *target,
1073                                            std::list<Error>& errors,
1074                                            Stream *feedback_stream,
1075                                            bool continue_on_error)
1076{
1077    if (!target)
1078        return false;
1079    Mutex::Locker locker(m_modules_mutex);
1080    for (auto module : m_modules)
1081    {
1082        Error error;
1083        if (module)
1084        {
1085            if (!module->LoadScriptingResourceInTarget(target, error, feedback_stream))
1086            {
1087                if (error.Fail() && error.AsCString())
1088                {
1089                    error.SetErrorStringWithFormat("unable to load scripting data for module %s - error reported was %s",
1090                                                   module->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
1091                                                   error.AsCString());
1092                    errors.push_back(error);
1093                }
1094                if (!continue_on_error)
1095                    return false;
1096            }
1097        }
1098    }
1099    return errors.size() == 0;
1100}
1101