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