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