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