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