brintos

brintos / llvm-project-archived public Read only

0
0
Text · 47.8 KiB · 5444c04 Raw
1404 lines · cpp
1//===-- ModuleList.cpp ----------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/ModuleList.h"10#include "lldb/Core/Debugger.h"11#include "lldb/Core/Module.h"12#include "lldb/Core/ModuleSpec.h"13#include "lldb/Core/PluginManager.h"14#include "lldb/Host/FileSystem.h"15#include "lldb/Interpreter/OptionValueFileSpec.h"16#include "lldb/Interpreter/OptionValueFileSpecList.h"17#include "lldb/Interpreter/OptionValueProperties.h"18#include "lldb/Interpreter/Property.h"19#include "lldb/Symbol/ObjectFile.h"20#include "lldb/Symbol/SymbolContext.h"21#include "lldb/Symbol/TypeList.h"22#include "lldb/Symbol/VariableList.h"23#include "lldb/Target/Platform.h"24#include "lldb/Target/Target.h"25#include "lldb/Utility/ArchSpec.h"26#include "lldb/Utility/ConstString.h"27#include "lldb/Utility/FileSpecList.h"28#include "lldb/Utility/LLDBLog.h"29#include "lldb/Utility/Log.h"30#include "lldb/Utility/UUID.h"31#include "lldb/lldb-defines.h"32#include "llvm/Support/ThreadPool.h"33 34#if defined(_WIN32)35#include "lldb/Host/windows/PosixApi.h"36#endif37 38#include "clang/Driver/Driver.h"39#include "llvm/ADT/StringRef.h"40#include "llvm/Support/FileSystem.h"41#include "llvm/Support/Threading.h"42#include "llvm/Support/raw_ostream.h"43 44#include <chrono>45#include <memory>46#include <mutex>47#include <string>48#include <utility>49 50namespace lldb_private {51class Function;52}53namespace lldb_private {54class RegularExpression;55}56namespace lldb_private {57class Stream;58}59namespace lldb_private {60class SymbolFile;61}62namespace lldb_private {63class Target;64}65 66using namespace lldb;67using namespace lldb_private;68 69namespace {70 71#define LLDB_PROPERTIES_modulelist72#include "CoreProperties.inc"73 74enum {75#define LLDB_PROPERTIES_modulelist76#include "CorePropertiesEnum.inc"77};78 79} // namespace80 81ModuleListProperties::ModuleListProperties() {82  m_collection_sp = std::make_shared<OptionValueProperties>("symbols");83  m_collection_sp->Initialize(g_modulelist_properties);84  m_collection_sp->SetValueChangedCallback(ePropertySymLinkPaths,85                                           [this] { UpdateSymlinkMappings(); });86 87  llvm::SmallString<128> path;88  if (clang::driver::Driver::getDefaultModuleCachePath(path)) {89    lldbassert(SetClangModulesCachePath(FileSpec(path)));90  }91 92  path.clear();93  if (llvm::sys::path::cache_directory(path)) {94    llvm::sys::path::append(path, "lldb");95    llvm::sys::path::append(path, "IndexCache");96    lldbassert(SetLLDBIndexCachePath(FileSpec(path)));97  }98 99}100 101bool ModuleListProperties::GetEnableExternalLookup() const {102  const uint32_t idx = ePropertyEnableExternalLookup;103  return GetPropertyAtIndexAs<bool>(104      idx, g_modulelist_properties[idx].default_uint_value != 0);105}106 107bool ModuleListProperties::SetEnableExternalLookup(bool new_value) {108  return SetPropertyAtIndex(ePropertyEnableExternalLookup, new_value);109}110 111SymbolDownload ModuleListProperties::GetSymbolAutoDownload() const {112  // Backward compatibility alias.113  if (GetPropertyAtIndexAs<bool>(ePropertyEnableBackgroundLookup, false))114    return eSymbolDownloadBackground;115 116  const uint32_t idx = ePropertyAutoDownload;117  return GetPropertyAtIndexAs<lldb::SymbolDownload>(118      idx, static_cast<lldb::SymbolDownload>(119               g_modulelist_properties[idx].default_uint_value));120}121 122FileSpec ModuleListProperties::GetClangModulesCachePath() const {123  const uint32_t idx = ePropertyClangModulesCachePath;124  return GetPropertyAtIndexAs<FileSpec>(idx, {});125}126 127bool ModuleListProperties::SetClangModulesCachePath(const FileSpec &path) {128  const uint32_t idx = ePropertyClangModulesCachePath;129  return SetPropertyAtIndex(idx, path);130}131 132FileSpec ModuleListProperties::GetLLDBIndexCachePath() const {133  const uint32_t idx = ePropertyLLDBIndexCachePath;134  return GetPropertyAtIndexAs<FileSpec>(idx, {});135}136 137bool ModuleListProperties::SetLLDBIndexCachePath(const FileSpec &path) {138  const uint32_t idx = ePropertyLLDBIndexCachePath;139  return SetPropertyAtIndex(idx, path);140}141 142bool ModuleListProperties::GetEnableLLDBIndexCache() const {143  const uint32_t idx = ePropertyEnableLLDBIndexCache;144  return GetPropertyAtIndexAs<bool>(145      idx, g_modulelist_properties[idx].default_uint_value != 0);146}147 148bool ModuleListProperties::SetEnableLLDBIndexCache(bool new_value) {149  return SetPropertyAtIndex(ePropertyEnableLLDBIndexCache, new_value);150}151 152uint64_t ModuleListProperties::GetLLDBIndexCacheMaxByteSize() {153  const uint32_t idx = ePropertyLLDBIndexCacheMaxByteSize;154  return GetPropertyAtIndexAs<uint64_t>(155      idx, g_modulelist_properties[idx].default_uint_value);156}157 158uint64_t ModuleListProperties::GetLLDBIndexCacheMaxPercent() {159  const uint32_t idx = ePropertyLLDBIndexCacheMaxPercent;160  return GetPropertyAtIndexAs<uint64_t>(161      idx, g_modulelist_properties[idx].default_uint_value);162}163 164uint64_t ModuleListProperties::GetLLDBIndexCacheExpirationDays() {165  const uint32_t idx = ePropertyLLDBIndexCacheExpirationDays;166  return GetPropertyAtIndexAs<uint64_t>(167      idx, g_modulelist_properties[idx].default_uint_value);168}169 170void ModuleListProperties::UpdateSymlinkMappings() {171  FileSpecList list =172      GetPropertyAtIndexAs<FileSpecList>(ePropertySymLinkPaths, {});173  llvm::sys::ScopedWriter lock(m_symlink_paths_mutex);174  const bool notify = false;175  m_symlink_paths.Clear(notify);176  for (auto symlink : list) {177    FileSpec resolved;178    Status status = FileSystem::Instance().Readlink(symlink, resolved);179    if (status.Success())180      m_symlink_paths.Append(symlink.GetPath(), resolved.GetPath(), notify);181  }182}183 184PathMappingList ModuleListProperties::GetSymlinkMappings() const {185  llvm::sys::ScopedReader lock(m_symlink_paths_mutex);186  return m_symlink_paths;187}188 189bool ModuleListProperties::GetLoadSymbolOnDemand() {190  const uint32_t idx = ePropertyLoadSymbolOnDemand;191  return GetPropertyAtIndexAs<bool>(192      idx, g_modulelist_properties[idx].default_uint_value != 0);193}194 195ModuleList::ModuleList() : m_modules(), m_modules_mutex() {}196 197ModuleList::ModuleList(const ModuleList &rhs) : m_modules(), m_modules_mutex() {198  std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex);199  std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex);200  m_modules = rhs.m_modules;201}202 203ModuleList::ModuleList(ModuleList::Notifier *notifier)204    : m_modules(), m_modules_mutex(), m_notifier(notifier) {}205 206const ModuleList &ModuleList::operator=(const ModuleList &rhs) {207  if (this != &rhs) {208    std::lock(m_modules_mutex, rhs.m_modules_mutex);209    std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex,210                                                    std::adopt_lock);211    std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex,212                                                    std::adopt_lock);213    m_modules = rhs.m_modules;214  }215  return *this;216}217 218ModuleList::~ModuleList() = default;219 220void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) {221  if (!module_sp)222    return;223  {224    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);225    // We are required to keep the first element of the Module List as the226    // executable module.  So check here and if the first module is NOT an227    // but the new one is, we insert this module at the beginning, rather than228    // at the end.229    // We don't need to do any of this if the list is empty:230    if (m_modules.empty()) {231      m_modules.push_back(module_sp);232    } else {233      // Since producing the ObjectFile may take some work, first check the234      // 0th element, and only if that's NOT an executable look at the235      // incoming ObjectFile.  That way in the normal case we only look at the236      // element 0 ObjectFile.237      const bool elem_zero_is_executable =238          m_modules[0]->GetObjectFile()->GetType() ==239          ObjectFile::Type::eTypeExecutable;240      lldb_private::ObjectFile *obj = module_sp->GetObjectFile();241      if (!elem_zero_is_executable && obj &&242          obj->GetType() == ObjectFile::Type::eTypeExecutable) {243        m_modules.insert(m_modules.begin(), module_sp);244      } else {245        m_modules.push_back(module_sp);246      }247    }248  }249  // Release the mutex before calling the notifier to avoid deadlock250  // NotifyModuleAdded should be thread-safe251  if (use_notifier && m_notifier)252    m_notifier->NotifyModuleAdded(*this, module_sp);253}254 255void ModuleList::Append(const ModuleSP &module_sp, bool notify) {256  AppendImpl(module_sp, notify);257}258 259void ModuleList::ReplaceEquivalent(260    const ModuleSP &module_sp,261    llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules) {262  if (module_sp) {263    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);264 265    // First remove any equivalent modules. Equivalent modules are modules266    // whose path, platform path and architecture match.267    ModuleSpec equivalent_module_spec(module_sp->GetFileSpec(),268                                      module_sp->GetArchitecture());269    equivalent_module_spec.GetPlatformFileSpec() =270        module_sp->GetPlatformFileSpec();271 272    size_t idx = 0;273    while (idx < m_modules.size()) {274      ModuleSP test_module_sp(m_modules[idx]);275      if (test_module_sp->MatchesModuleSpec(equivalent_module_spec)) {276        if (old_modules)277          old_modules->push_back(test_module_sp);278        RemoveImpl(m_modules.begin() + idx);279      } else {280        ++idx;281      }282    }283    // Now add the new module to the list284    Append(module_sp);285  }286}287 288bool ModuleList::AppendIfNeeded(const ModuleSP &new_module, bool notify) {289  if (new_module) {290    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);291    for (const ModuleSP &module_sp : m_modules) {292      if (module_sp.get() == new_module.get())293        return false; // Already in the list294    }295    // Only push module_sp on the list if it wasn't already in there.296    Append(new_module, notify);297    return true;298  }299  return false;300}301 302void ModuleList::Append(const ModuleList &module_list) {303  for (auto pos : module_list.m_modules)304    Append(pos);305}306 307bool ModuleList::AppendIfNeeded(const ModuleList &module_list) {308  bool any_in = false;309  for (auto pos : module_list.m_modules) {310    if (AppendIfNeeded(pos))311      any_in = true;312  }313  return any_in;314}315 316bool ModuleList::RemoveImpl(const ModuleSP &module_sp, bool use_notifier) {317  if (module_sp) {318    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);319    collection::iterator pos, end = m_modules.end();320    for (pos = m_modules.begin(); pos != end; ++pos) {321      if (pos->get() == module_sp.get()) {322        m_modules.erase(pos);323        if (use_notifier && m_notifier)324          m_notifier->NotifyModuleRemoved(*this, module_sp);325        return true;326      }327    }328  }329  return false;330}331 332ModuleList::collection::iterator333ModuleList::RemoveImpl(ModuleList::collection::iterator pos,334                       bool use_notifier) {335  ModuleSP module_sp(*pos);336  collection::iterator retval = m_modules.erase(pos);337  if (use_notifier && m_notifier)338    m_notifier->NotifyModuleRemoved(*this, module_sp);339  return retval;340}341 342bool ModuleList::Remove(const ModuleSP &module_sp, bool notify) {343  return RemoveImpl(module_sp, notify);344}345 346bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp,347                               const lldb::ModuleSP &new_module_sp) {348  if (!RemoveImpl(old_module_sp, false))349    return false;350  AppendImpl(new_module_sp, false);351  if (m_notifier)352    m_notifier->NotifyModuleUpdated(*this, old_module_sp, new_module_sp);353  return true;354}355 356bool ModuleList::RemoveIfOrphaned(const ModuleWP module_wp) {357  if (auto module_sp = module_wp.lock()) {358    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);359    collection::iterator pos, end = m_modules.end();360    for (pos = m_modules.begin(); pos != end; ++pos) {361      if (pos->get() == module_sp.get()) {362        // Since module_sp increases the refcount by 1, the use count should be363        // the regular use count + 1.364        constexpr long kUseCountOrphaned = kUseCountModuleListOrphaned + 1;365        if (pos->use_count() == kUseCountOrphaned) {366          pos = RemoveImpl(pos);367          return true;368        }369        return false;370      }371    }372  }373  return false;374}375 376size_t ModuleList::RemoveOrphans(bool mandatory) {377  std::unique_lock<std::recursive_mutex> lock(m_modules_mutex, std::defer_lock);378 379  if (mandatory) {380    lock.lock();381  } else {382    // Not mandatory, remove orphans if we can get the mutex383    if (!lock.try_lock())384      return 0;385  }386  size_t remove_count = 0;387  // Modules might hold shared pointers to other modules, so removing one388  // module might make other modules orphans. Keep removing modules until389  // there are no further modules that can be removed.390  bool made_progress = true;391  while (made_progress) {392    // Keep track if we make progress this iteration.393    made_progress = false;394    collection::iterator pos = m_modules.begin();395    while (pos != m_modules.end()) {396      if (pos->use_count() == kUseCountModuleListOrphaned) {397        pos = RemoveImpl(pos);398        ++remove_count;399        // We did make progress.400        made_progress = true;401      } else {402        ++pos;403      }404    }405  }406  return remove_count;407}408 409size_t ModuleList::Remove(ModuleList &module_list) {410  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);411  size_t num_removed = 0;412  collection::iterator pos, end = module_list.m_modules.end();413  for (pos = module_list.m_modules.begin(); pos != end; ++pos) {414    if (Remove(*pos, false /* notify */))415      ++num_removed;416  }417  if (m_notifier)418    m_notifier->NotifyModulesRemoved(module_list);419  return num_removed;420}421 422void ModuleList::Clear() { ClearImpl(); }423 424void ModuleList::Destroy() { ClearImpl(); }425 426void ModuleList::ClearImpl(bool use_notifier) {427  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);428  if (use_notifier && m_notifier)429    m_notifier->NotifyWillClearList(*this);430  m_modules.clear();431}432 433Module *ModuleList::GetModulePointerAtIndex(size_t idx) const {434  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);435  if (idx < m_modules.size())436    return m_modules[idx].get();437  return nullptr;438}439 440ModuleSP ModuleList::GetModuleAtIndex(size_t idx) const {441  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);442  return GetModuleAtIndexUnlocked(idx);443}444 445ModuleSP ModuleList::GetModuleAtIndexUnlocked(size_t idx) const {446  ModuleSP module_sp;447  if (idx < m_modules.size())448    module_sp = m_modules[idx];449  return module_sp;450}451 452void ModuleList::FindFunctions(ConstString name,453                               FunctionNameType name_type_mask,454                               const ModuleFunctionSearchOptions &options,455                               SymbolContextList &sc_list) const {456  const size_t old_size = sc_list.GetSize();457 458  if (name_type_mask & eFunctionNameTypeAuto) {459    Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);460 461    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);462    for (const ModuleSP &module_sp : m_modules) {463      module_sp->FindFunctions(lookup_info, CompilerDeclContext(), options,464                               sc_list);465    }466 467    const size_t new_size = sc_list.GetSize();468 469    if (old_size < new_size)470      lookup_info.Prune(sc_list, old_size);471  } else {472    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);473    for (const ModuleSP &module_sp : m_modules) {474      module_sp->FindFunctions(name, CompilerDeclContext(), name_type_mask,475                               options, sc_list);476    }477  }478}479 480void ModuleList::FindFunctionSymbols(ConstString name,481                                     lldb::FunctionNameType name_type_mask,482                                     SymbolContextList &sc_list) {483  const size_t old_size = sc_list.GetSize();484 485  if (name_type_mask & eFunctionNameTypeAuto) {486    Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);487 488    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);489    for (const ModuleSP &module_sp : m_modules) {490      module_sp->FindFunctionSymbols(lookup_info.GetLookupName(),491                                     lookup_info.GetNameTypeMask(), sc_list);492    }493 494    const size_t new_size = sc_list.GetSize();495 496    if (old_size < new_size)497      lookup_info.Prune(sc_list, old_size);498  } else {499    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);500    for (const ModuleSP &module_sp : m_modules) {501      module_sp->FindFunctionSymbols(name, name_type_mask, sc_list);502    }503  }504}505 506void ModuleList::FindFunctions(const RegularExpression &name,507                               const ModuleFunctionSearchOptions &options,508                               SymbolContextList &sc_list) {509  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);510  for (const ModuleSP &module_sp : m_modules)511    module_sp->FindFunctions(name, options, sc_list);512}513 514void ModuleList::FindCompileUnits(const FileSpec &path,515                                  SymbolContextList &sc_list) const {516  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);517  for (const ModuleSP &module_sp : m_modules)518    module_sp->FindCompileUnits(path, sc_list);519}520 521void ModuleList::FindGlobalVariables(ConstString name, size_t max_matches,522                                     VariableList &variable_list) const {523  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);524  for (const ModuleSP &module_sp : m_modules) {525    module_sp->FindGlobalVariables(name, CompilerDeclContext(), max_matches,526                                   variable_list);527  }528}529 530void ModuleList::FindGlobalVariables(const RegularExpression &regex,531                                     size_t max_matches,532                                     VariableList &variable_list) const {533  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);534  for (const ModuleSP &module_sp : m_modules)535    module_sp->FindGlobalVariables(regex, max_matches, variable_list);536}537 538void ModuleList::FindSymbolsWithNameAndType(ConstString name,539                                            SymbolType symbol_type,540                                            SymbolContextList &sc_list) const {541  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);542  for (const ModuleSP &module_sp : m_modules)543    module_sp->FindSymbolsWithNameAndType(name, symbol_type, sc_list);544}545 546void ModuleList::FindSymbolsMatchingRegExAndType(547    const RegularExpression &regex, lldb::SymbolType symbol_type,548    SymbolContextList &sc_list) const {549  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);550  for (const ModuleSP &module_sp : m_modules)551    module_sp->FindSymbolsMatchingRegExAndType(regex, symbol_type, sc_list);552}553 554void ModuleList::FindModules(const ModuleSpec &module_spec,555                             ModuleList &matching_module_list) const {556  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);557  for (const ModuleSP &module_sp : m_modules) {558    if (module_sp->MatchesModuleSpec(module_spec))559      matching_module_list.Append(module_sp);560  }561}562 563ModuleSP ModuleList::FindModule(const Module *module_ptr) const {564  ModuleSP module_sp;565 566  // Scope for "locker"567  {568    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);569    collection::const_iterator pos, end = m_modules.end();570 571    for (pos = m_modules.begin(); pos != end; ++pos) {572      if ((*pos).get() == module_ptr) {573        module_sp = (*pos);574        break;575      }576    }577  }578  return module_sp;579}580 581ModuleSP ModuleList::FindModule(const UUID &uuid) const {582  ModuleSP module_sp;583 584  if (uuid.IsValid()) {585    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);586    collection::const_iterator pos, end = m_modules.end();587 588    for (pos = m_modules.begin(); pos != end; ++pos) {589      if ((*pos)->GetUUID() == uuid) {590        module_sp = (*pos);591        break;592      }593    }594  }595  return module_sp;596}597 598ModuleSP ModuleList::FindModule(lldb::user_id_t uid) const {599  ModuleSP module_sp;600  ForEach([&](const ModuleSP &m) {601    if (m->GetID() == uid) {602      module_sp = m;603      return IterationAction::Stop;604    }605 606    return IterationAction::Continue;607  });608 609  return module_sp;610}611 612void ModuleList::FindTypes(Module *search_first, const TypeQuery &query,613                           TypeResults &results) const {614  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);615  if (search_first) {616    search_first->FindTypes(query, results);617    if (results.Done(query))618      return;619  }620  for (const auto &module_sp : m_modules) {621    if (search_first != module_sp.get()) {622      module_sp->FindTypes(query, results);623      if (results.Done(query))624        return;625    }626  }627}628 629bool ModuleList::FindSourceFile(const FileSpec &orig_spec,630                                FileSpec &new_spec) const {631  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);632  for (const ModuleSP &module_sp : m_modules) {633    if (module_sp->FindSourceFile(orig_spec, new_spec))634      return true;635  }636  return false;637}638 639void ModuleList::FindAddressesForLine(const lldb::TargetSP target_sp,640                                      const FileSpec &file, uint32_t line,641                                      Function *function,642                                      std::vector<Address> &output_local,643                                      std::vector<Address> &output_extern) {644  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);645  for (const ModuleSP &module_sp : m_modules) {646    module_sp->FindAddressesForLine(target_sp, file, line, function,647                                    output_local, output_extern);648  }649}650 651ModuleSP ModuleList::FindFirstModule(const ModuleSpec &module_spec) const {652  ModuleSP module_sp;653  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);654  collection::const_iterator pos, end = m_modules.end();655  for (pos = m_modules.begin(); pos != end; ++pos) {656    ModuleSP module_sp(*pos);657    if (module_sp->MatchesModuleSpec(module_spec))658      return module_sp;659  }660  return module_sp;661}662 663size_t ModuleList::GetSize() const {664  size_t size = 0;665  {666    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);667    size = m_modules.size();668  }669  return size;670}671 672void ModuleList::Dump(Stream *s) const {673  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);674  for (const ModuleSP &module_sp : m_modules)675    module_sp->Dump(s);676}677 678void ModuleList::LogUUIDAndPaths(Log *log, const char *prefix_cstr) {679  if (log != nullptr) {680    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);681    collection::const_iterator pos, begin = m_modules.begin(),682                                    end = m_modules.end();683    for (pos = begin; pos != end; ++pos) {684      Module *module = pos->get();685      const FileSpec &module_file_spec = module->GetFileSpec();686      LLDB_LOGF(log, "%s[%u] %s (%s) \"%s\"", prefix_cstr ? prefix_cstr : "",687                (uint32_t)std::distance(begin, pos),688                module->GetUUID().GetAsString().c_str(),689                module->GetArchitecture().GetArchitectureName(),690                module_file_spec.GetPath().c_str());691    }692  }693}694 695bool ModuleList::ResolveFileAddress(lldb::addr_t vm_addr,696                                    Address &so_addr) const {697  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);698  for (const ModuleSP &module_sp : m_modules) {699    if (module_sp->ResolveFileAddress(vm_addr, so_addr))700      return true;701  }702 703  return false;704}705 706uint32_t707ModuleList::ResolveSymbolContextForAddress(const Address &so_addr,708                                           SymbolContextItem resolve_scope,709                                           SymbolContext &sc) const {710  // The address is already section offset so it has a module711  uint32_t resolved_flags = 0;712  ModuleSP module_sp(so_addr.GetModule());713  if (module_sp) {714    resolved_flags =715        module_sp->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc);716  } else {717    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);718    collection::const_iterator pos, end = m_modules.end();719    for (pos = m_modules.begin(); pos != end; ++pos) {720      resolved_flags =721          (*pos)->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc);722      if (resolved_flags != 0)723        break;724    }725  }726 727  return resolved_flags;728}729 730uint32_t ModuleList::ResolveSymbolContextForFilePath(731    const char *file_path, uint32_t line, bool check_inlines,732    SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {733  FileSpec file_spec(file_path);734  return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,735                                          resolve_scope, sc_list);736}737 738uint32_t ModuleList::ResolveSymbolContextsForFileSpec(739    const FileSpec &file_spec, uint32_t line, bool check_inlines,740    SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {741  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);742  for (const ModuleSP &module_sp : m_modules) {743    module_sp->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,744                                                resolve_scope, sc_list);745  }746 747  return sc_list.GetSize();748}749 750size_t ModuleList::GetIndexForModule(const Module *module) const {751  if (module) {752    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);753    collection::const_iterator pos;754    collection::const_iterator begin = m_modules.begin();755    collection::const_iterator end = m_modules.end();756    for (pos = begin; pos != end; ++pos) {757      if ((*pos).get() == module)758        return std::distance(begin, pos);759    }760  }761  return LLDB_INVALID_INDEX32;762}763 764namespace {765/// A wrapper around ModuleList for shared modules. Provides fast lookups for766/// file-based ModuleSpec queries.767class SharedModuleList {768public:769  /// Finds all the modules matching the module_spec, and adds them to \p770  /// matching_module_list.771  void FindModules(const ModuleSpec &module_spec,772                   ModuleList &matching_module_list) const {773    std::lock_guard<std::recursive_mutex> guard(GetMutex());774    // Try map first for performance - if found, skip expensive full list775    // search.776    FindModulesInMap(module_spec, matching_module_list);777    if (!matching_module_list.IsEmpty())778      return;779    m_list.FindModules(module_spec, matching_module_list);780    // Assert that modules were found in the list but not the map, it's781    // because the module_spec has no filename or the found module has a782    // different filename. For example, when searching by UUID and finding a783    // module with an alias.784    assert((matching_module_list.IsEmpty() ||785            module_spec.GetFileSpec().GetFilename().IsEmpty() ||786            module_spec.GetFileSpec().GetFilename() !=787                matching_module_list.GetModuleAtIndex(0)788                    ->GetFileSpec()789                    .GetFilename()) &&790           "Search by name not found in SharedModuleList's map");791  }792 793  ModuleSP FindModule(const Module &module) {794 795    std::lock_guard<std::recursive_mutex> guard(GetMutex());796    if (ModuleSP result = FindModuleInMap(module))797      return result;798    return m_list.FindModule(&module);799  }800 801  // UUID searches bypass map since UUIDs aren't indexed by filename.802  ModuleSP FindModule(const UUID &uuid) const {803    return m_list.FindModule(uuid);804  }805 806  void Append(const ModuleSP &module_sp, bool use_notifier) {807    if (!module_sp)808      return;809    std::lock_guard<std::recursive_mutex> guard(GetMutex());810    m_list.Append(module_sp, use_notifier);811    AddToMap(module_sp);812  }813 814  size_t RemoveOrphans(bool mandatory) {815    std::unique_lock<std::recursive_mutex> lock(GetMutex(), std::defer_lock);816    if (mandatory) {817      lock.lock();818    } else {819      if (!lock.try_lock())820        return 0;821    }822    size_t total_count = 0;823    size_t run_count;824    do {825      // Remove indexed orphans first, then remove non-indexed orphans. This826      // order is important because the shared count will be different if a827      // module is indexed or not.828      run_count = RemoveOrphansFromMapAndList();829      run_count += m_list.RemoveOrphans(mandatory);830      total_count += run_count;831      // Because removing orphans might make new orphans, remove from both832      // containers until a fixed-point is reached.833    } while (run_count != 0);834 835    return total_count;836  }837 838  bool Remove(const ModuleSP &module_sp, bool use_notifier = true) {839    if (!module_sp)840      return false;841    std::lock_guard<std::recursive_mutex> guard(GetMutex());842    RemoveFromMap(module_sp);843    return m_list.Remove(module_sp, use_notifier);844  }845 846  void ReplaceEquivalent(const ModuleSP &module_sp,847                         llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules) {848    std::lock_guard<std::recursive_mutex> guard(GetMutex());849    m_list.ReplaceEquivalent(module_sp, old_modules);850    ReplaceEquivalentInMap(module_sp);851  }852 853  bool RemoveIfOrphaned(const ModuleWP module_wp) {854    std::lock_guard<std::recursive_mutex> guard(GetMutex());855    RemoveFromMap(module_wp, /*if_orphaned=*/true);856    return m_list.RemoveIfOrphaned(module_wp);857  }858 859  std::recursive_mutex &GetMutex() const { return m_list.GetMutex(); }860 861private:862  ModuleSP FindModuleInMap(const Module &module) const {863    if (!module.GetFileSpec().GetFilename())864      return ModuleSP();865    ConstString name = module.GetFileSpec().GetFilename();866    auto it = m_name_to_modules.find(name);867    if (it == m_name_to_modules.end())868      return ModuleSP();869    const llvm::SmallVectorImpl<ModuleSP> &vector = it->second;870    for (const ModuleSP &module_sp : vector) {871      if (module_sp.get() == &module)872        return module_sp;873    }874    return ModuleSP();875  }876 877  void FindModulesInMap(const ModuleSpec &module_spec,878                        ModuleList &matching_module_list) const {879    auto it = m_name_to_modules.find(module_spec.GetFileSpec().GetFilename());880    if (it == m_name_to_modules.end())881      return;882    const llvm::SmallVectorImpl<ModuleSP> &vector = it->second;883    for (const ModuleSP &module_sp : vector) {884      if (module_sp->MatchesModuleSpec(module_spec))885        matching_module_list.Append(module_sp);886    }887  }888 889  void AddToMap(const ModuleSP &module_sp) {890    ConstString name = module_sp->GetFileSpec().GetFilename();891    if (name.IsEmpty())892      return;893    m_name_to_modules[name].push_back(module_sp);894  }895 896  void RemoveFromMap(const ModuleWP module_wp, bool if_orphaned = false) {897    if (auto module_sp = module_wp.lock()) {898      ConstString name = module_sp->GetFileSpec().GetFilename();899      if (!m_name_to_modules.contains(name))900        return;901      llvm::SmallVectorImpl<ModuleSP> &vec = m_name_to_modules[name];902      for (auto *it = vec.begin(); it != vec.end(); ++it) {903        if (it->get() == module_sp.get()) {904          // Since module_sp increases the refcount by 1, the use count should905          // be the regular use count + 1.906          constexpr long kUseCountOrphaned =907              kUseCountSharedModuleListOrphaned + 1;908          if (!if_orphaned || it->use_count() == kUseCountOrphaned) {909            vec.erase(it);910            break;911          }912        }913      }914    }915  }916 917  void ReplaceEquivalentInMap(const ModuleSP &module_sp) {918    RemoveEquivalentModulesFromMap(module_sp);919    AddToMap(module_sp);920  }921 922  void RemoveEquivalentModulesFromMap(const ModuleSP &module_sp) {923    ConstString name = module_sp->GetFileSpec().GetFilename();924    if (name.IsEmpty())925      return;926 927    auto it = m_name_to_modules.find(name);928    if (it == m_name_to_modules.end())929      return;930 931    // First remove any equivalent modules. Equivalent modules are modules932    // whose path, platform path and architecture match.933    ModuleSpec equivalent_module_spec(module_sp->GetFileSpec(),934                                      module_sp->GetArchitecture());935    equivalent_module_spec.GetPlatformFileSpec() =936        module_sp->GetPlatformFileSpec();937 938    llvm::SmallVectorImpl<ModuleSP> &vec = it->second;939    llvm::erase_if(vec, [&equivalent_module_spec](ModuleSP &element) {940      return element->MatchesModuleSpec(equivalent_module_spec);941    });942  }943 944  /// Remove orphans from the vector and return the removed modules.945  ModuleList RemoveOrphansFromVector(llvm::SmallVectorImpl<ModuleSP> &vec) {946    // remove_if moves the elements that match the condition to the end of the947    // container, and returns an iterator to the first element that was moved.948    auto *to_remove_start = llvm::remove_if(vec, [](const ModuleSP &module) {949      return module.use_count() == kUseCountSharedModuleListOrphaned;950    });951 952    ModuleList to_remove;953    for (ModuleSP *it = to_remove_start; it != vec.end(); ++it)954      to_remove.Append(*it);955 956    vec.erase(to_remove_start, vec.end());957    return to_remove;958  }959 960  /// Remove orphans that exist in both the map and list. This does not remove961  /// any orphans that exist exclusively on the list.962  ///963  /// The mutex must be locked by the caller.964  int RemoveOrphansFromMapAndList() {965    // Modules might hold shared pointers to other modules, so removing one966    // module might orphan other modules. Keep removing modules until967    // there are no further modules that can be removed.968    int remove_count = 0;969    int previous_remove_count;970    do {971      previous_remove_count = remove_count;972      for (auto &[name, vec] : m_name_to_modules) {973        if (vec.empty())974          continue;975        ModuleList to_remove = RemoveOrphansFromVector(vec);976        remove_count += to_remove.GetSize();977        m_list.Remove(to_remove);978      }979      // Break when fixed-point is reached.980    } while (previous_remove_count != remove_count);981 982    return remove_count;983  }984 985  ModuleList m_list;986 987  /// A hash map from a module's filename to all the modules that share that988  /// filename, for fast module lookups by name.989  llvm::DenseMap<ConstString, llvm::SmallVector<ModuleSP, 1>> m_name_to_modules;990 991  /// The use count of a module held only by m_list and m_name_to_modules.992  static constexpr long kUseCountSharedModuleListOrphaned = 2;993};994 995struct SharedModuleListInfo {996  SharedModuleList module_list;997  ModuleListProperties module_list_properties;998};999}1000static SharedModuleListInfo &GetSharedModuleListInfo()1001{1002  static SharedModuleListInfo *g_shared_module_list_info = nullptr;1003  static llvm::once_flag g_once_flag;1004  llvm::call_once(g_once_flag, []() {1005    // NOTE: Intentionally leak the module list so a program doesn't have to1006    // cleanup all modules and object files as it exits. This just wastes time1007    // doing a bunch of cleanup that isn't required.1008    if (g_shared_module_list_info == nullptr)1009      g_shared_module_list_info = new SharedModuleListInfo();1010  });1011  return *g_shared_module_list_info;1012}1013 1014static SharedModuleList &GetSharedModuleList() {1015  return GetSharedModuleListInfo().module_list;1016}1017 1018ModuleListProperties &ModuleList::GetGlobalModuleListProperties() {1019  return GetSharedModuleListInfo().module_list_properties;1020}1021 1022bool ModuleList::ModuleIsInCache(const Module *module_ptr) {1023  if (module_ptr) {1024    SharedModuleList &shared_module_list = GetSharedModuleList();1025    return shared_module_list.FindModule(*module_ptr).get() != nullptr;1026  }1027  return false;1028}1029 1030void ModuleList::FindSharedModules(const ModuleSpec &module_spec,1031                                   ModuleList &matching_module_list) {1032  GetSharedModuleList().FindModules(module_spec, matching_module_list);1033}1034 1035lldb::ModuleSP ModuleList::FindSharedModule(const UUID &uuid) {1036  return GetSharedModuleList().FindModule(uuid);1037}1038 1039size_t ModuleList::RemoveOrphanSharedModules(bool mandatory) {1040  return GetSharedModuleList().RemoveOrphans(mandatory);1041}1042 1043Status1044ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,1045                            llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,1046                            bool *did_create_ptr, bool always_create,1047                            bool invoke_locate_callback) {1048  SharedModuleList &shared_module_list = GetSharedModuleList();1049  std::lock_guard<std::recursive_mutex> guard(shared_module_list.GetMutex());1050  char path[PATH_MAX];1051 1052  Status error;1053 1054  module_sp.reset();1055 1056  if (did_create_ptr)1057    *did_create_ptr = false;1058 1059  const UUID *uuid_ptr = module_spec.GetUUIDPtr();1060  const FileSpec &module_file_spec = module_spec.GetFileSpec();1061  const ArchSpec &arch = module_spec.GetArchitecture();1062 1063  // Make sure no one else can try and get or create a module while this1064  // function is actively working on it by doing an extra lock on the global1065  // mutex list.1066  if (!always_create) {1067    ModuleList matching_module_list;1068    shared_module_list.FindModules(module_spec, matching_module_list);1069    const size_t num_matching_modules = matching_module_list.GetSize();1070 1071    if (num_matching_modules > 0) {1072      for (size_t module_idx = 0; module_idx < num_matching_modules;1073           ++module_idx) {1074        module_sp = matching_module_list.GetModuleAtIndex(module_idx);1075 1076        // Make sure the file for the module hasn't been modified1077        if (module_sp->FileHasChanged()) {1078          if (old_modules)1079            old_modules->push_back(module_sp);1080 1081          Log *log = GetLog(LLDBLog::Modules);1082          if (log != nullptr)1083            LLDB_LOGF(1084                log, "%p '%s' module changed: removing from global module list",1085                static_cast<void *>(module_sp.get()),1086                module_sp->GetFileSpec().GetFilename().GetCString());1087 1088          shared_module_list.Remove(module_sp);1089          module_sp.reset();1090        } else {1091          // The module matches and the module was not modified from when it1092          // was last loaded.1093          return error;1094        }1095      }1096    }1097  }1098 1099  if (module_sp)1100    return error;1101 1102  // Try target's platform locate module callback before second attempt.1103  if (invoke_locate_callback) {1104    TargetSP target_sp = module_spec.GetTargetSP();1105    if (target_sp && target_sp->IsValid()) {1106      if (PlatformSP platform_sp = target_sp->GetPlatform()) {1107        FileSpec symbol_file_spec;1108        platform_sp->CallLocateModuleCallbackIfSet(1109            module_spec, module_sp, symbol_file_spec, did_create_ptr);1110        if (module_sp) {1111          // The callback found a module.1112          return error;1113        }1114      }1115    }1116  }1117 1118  module_sp = std::make_shared<Module>(module_spec);1119  // Make sure there are a module and an object file since we can specify a1120  // valid file path with an architecture that might not be in that file. By1121  // getting the object file we can guarantee that the architecture matches1122  if (module_sp->GetObjectFile()) {1123    // If we get in here we got the correct arch, now we just need to verify1124    // the UUID if one was given1125    if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {1126      module_sp.reset();1127    } else {1128      if (module_sp->GetObjectFile() &&1129          module_sp->GetObjectFile()->GetType() ==1130              ObjectFile::eTypeStubLibrary) {1131        module_sp.reset();1132      } else {1133        if (did_create_ptr) {1134          *did_create_ptr = true;1135        }1136 1137        shared_module_list.ReplaceEquivalent(module_sp, old_modules);1138        return error;1139      }1140    }1141  } else {1142    module_sp.reset();1143  }1144 1145  // Get module search paths from the target if available.1146  lldb::TargetSP target_sp = module_spec.GetTargetSP();1147  FileSpecList module_search_paths;1148  if (target_sp)1149    module_search_paths = target_sp->GetExecutableSearchPaths();1150 1151  if (!module_search_paths.IsEmpty()) {1152    const auto num_directories = module_search_paths.GetSize();1153    for (size_t idx = 0; idx < num_directories; ++idx) {1154      auto search_path_spec = module_search_paths.GetFileSpecAtIndex(idx);1155      FileSystem::Instance().Resolve(search_path_spec);1156      namespace fs = llvm::sys::fs;1157      if (!FileSystem::Instance().IsDirectory(search_path_spec))1158        continue;1159      search_path_spec.AppendPathComponent(1160          module_spec.GetFileSpec().GetFilename().GetStringRef());1161      if (!FileSystem::Instance().Exists(search_path_spec))1162        continue;1163 1164      auto resolved_module_spec(module_spec);1165      resolved_module_spec.GetFileSpec() = search_path_spec;1166      module_sp = std::make_shared<Module>(resolved_module_spec);1167      if (module_sp->GetObjectFile()) {1168        // If we get in here we got the correct arch, now we just need to1169        // verify the UUID if one was given1170        if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {1171          module_sp.reset();1172        } else {1173          if (module_sp->GetObjectFile()->GetType() ==1174              ObjectFile::eTypeStubLibrary) {1175            module_sp.reset();1176          } else {1177            if (did_create_ptr)1178              *did_create_ptr = true;1179 1180            shared_module_list.ReplaceEquivalent(module_sp, old_modules);1181            return Status();1182          }1183        }1184      } else {1185        module_sp.reset();1186      }1187    }1188  }1189 1190  // Either the file didn't exist where at the path, or no path was given, so1191  // we now have to use more extreme measures to try and find the appropriate1192  // module.1193 1194  // Fixup the incoming path in case the path points to a valid file, yet the1195  // arch or UUID (if one was passed in) don't match.1196  ModuleSpec located_binary_modulespec;1197  StatisticsMap symbol_locator_map;1198  located_binary_modulespec = PluginManager::LocateExecutableObjectFile(1199      module_spec, symbol_locator_map);1200  // Don't look for the file if it appears to be the same one we already1201  // checked for above...1202  if (located_binary_modulespec.GetFileSpec() != module_file_spec) {1203    if (!FileSystem::Instance().Exists(1204            located_binary_modulespec.GetFileSpec())) {1205      located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));1206      if (path[0] == '\0')1207        module_file_spec.GetPath(path, sizeof(path));1208      // How can this check ever be true? This branch it is false, and we1209      // haven't modified file_spec.1210      if (FileSystem::Instance().Exists(1211              located_binary_modulespec.GetFileSpec())) {1212        std::string uuid_str;1213        if (uuid_ptr && uuid_ptr->IsValid())1214          uuid_str = uuid_ptr->GetAsString();1215 1216        if (arch.IsValid()) {1217          if (!uuid_str.empty())1218            error = Status::FromErrorStringWithFormat(1219                "'%s' does not contain the %s architecture and UUID %s", path,1220                arch.GetArchitectureName(), uuid_str.c_str());1221          else1222            error = Status::FromErrorStringWithFormat(1223                "'%s' does not contain the %s architecture.", path,1224                arch.GetArchitectureName());1225        }1226      } else {1227        error = Status::FromErrorStringWithFormat("'%s' does not exist", path);1228      }1229      if (error.Fail())1230        module_sp.reset();1231      return error;1232    }1233 1234    // Make sure no one else can try and get or create a module while this1235    // function is actively working on it by doing an extra lock on the global1236    // mutex list.1237    ModuleSpec platform_module_spec(module_spec);1238    platform_module_spec.GetFileSpec() =1239        located_binary_modulespec.GetFileSpec();1240    platform_module_spec.GetPlatformFileSpec() =1241        located_binary_modulespec.GetFileSpec();1242    platform_module_spec.GetSymbolFileSpec() =1243        located_binary_modulespec.GetSymbolFileSpec();1244    ModuleList matching_module_list;1245    shared_module_list.FindModules(platform_module_spec, matching_module_list);1246    if (!matching_module_list.IsEmpty()) {1247      module_sp = matching_module_list.GetModuleAtIndex(0);1248 1249      // If we didn't have a UUID in mind when looking for the object file,1250      // then we should make sure the modification time hasn't changed!1251      if (platform_module_spec.GetUUIDPtr() == nullptr) {1252        auto file_spec_mod_time = FileSystem::Instance().GetModificationTime(1253            located_binary_modulespec.GetFileSpec());1254        if (file_spec_mod_time != llvm::sys::TimePoint<>()) {1255          if (file_spec_mod_time != module_sp->GetModificationTime()) {1256            if (old_modules)1257              old_modules->push_back(module_sp);1258            shared_module_list.Remove(module_sp);1259            module_sp.reset();1260          }1261        }1262      }1263    }1264 1265    if (!module_sp) {1266      module_sp = std::make_shared<Module>(platform_module_spec);1267      // Make sure there are a module and an object file since we can specify a1268      // valid file path with an architecture that might not be in that file.1269      // By getting the object file we can guarantee that the architecture1270      // matches1271      if (module_sp && module_sp->GetObjectFile()) {1272        module_sp->GetSymbolLocatorStatistics().merge(symbol_locator_map);1273        if (module_sp->GetObjectFile()->GetType() ==1274            ObjectFile::eTypeStubLibrary) {1275          module_sp.reset();1276        } else {1277          if (did_create_ptr)1278            *did_create_ptr = true;1279 1280          shared_module_list.ReplaceEquivalent(module_sp, old_modules);1281        }1282      } else {1283        located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));1284 1285        if (located_binary_modulespec.GetFileSpec()) {1286          if (arch.IsValid())1287            error = Status::FromErrorStringWithFormat(1288                "unable to open %s architecture in '%s'",1289                arch.GetArchitectureName(), path);1290          else1291            error =1292                Status::FromErrorStringWithFormat("unable to open '%s'", path);1293        } else {1294          std::string uuid_str;1295          if (uuid_ptr && uuid_ptr->IsValid())1296            uuid_str = uuid_ptr->GetAsString();1297 1298          if (!uuid_str.empty())1299            error = Status::FromErrorStringWithFormat(1300                "cannot locate a module for UUID '%s'", uuid_str.c_str());1301          else1302            error = Status::FromErrorString("cannot locate a module");1303        }1304      }1305    }1306  }1307 1308  return error;1309}1310 1311bool ModuleList::RemoveSharedModule(lldb::ModuleSP &module_sp) {1312  return GetSharedModuleList().Remove(module_sp);1313}1314 1315bool ModuleList::RemoveSharedModuleIfOrphaned(const ModuleWP module_wp) {1316  return GetSharedModuleList().RemoveIfOrphaned(module_wp);1317}1318 1319bool ModuleList::LoadScriptingResourcesInTarget(Target *target,1320                                                std::list<Status> &errors,1321                                                Stream &feedback_stream,1322                                                bool continue_on_error) {1323  if (!target)1324    return false;1325  m_modules_mutex.lock();1326  // Don't hold the module list mutex while loading the scripting resources,1327  // The initializer might do any amount of work, and having that happen while1328  // the module list is held is asking for A/B locking problems.1329  const ModuleList tmp_module_list(*this);1330  m_modules_mutex.unlock();1331 1332  for (auto module : tmp_module_list.ModulesNoLocking()) {1333    if (module) {1334      Status error;1335      if (!module->LoadScriptingResourceInTarget(target, error,1336                                                 feedback_stream)) {1337        if (error.Fail() && error.AsCString()) {1338          error = Status::FromErrorStringWithFormat(1339              "unable to load scripting data for "1340              "module %s - error reported was %s",1341              module->GetFileSpec()1342                  .GetFileNameStrippingExtension()1343                  .GetCString(),1344              error.AsCString());1345          errors.push_back(std::move(error));1346          if (!continue_on_error)1347            return false;1348        }1349      }1350    }1351  }1352  return errors.empty();1353}1354 1355void ModuleList::ForEach(1356    std::function<IterationAction(const ModuleSP &module_sp)> const &callback)1357    const {1358  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);1359  for (const auto &module_sp : m_modules) {1360    assert(module_sp != nullptr);1361    if (callback(module_sp) == IterationAction::Stop)1362      break;1363  }1364}1365 1366bool ModuleList::AnyOf(1367    std::function<bool(lldb_private::Module &module_sp)> const &callback)1368    const {1369  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);1370  for (const auto &module_sp : m_modules) {1371    assert(module_sp != nullptr);1372    if (callback(*module_sp))1373      return true;1374  }1375 1376  return false;1377}1378 1379 1380void ModuleList::Swap(ModuleList &other) {1381  // scoped_lock locks both mutexes at once.1382  std::scoped_lock<std::recursive_mutex, std::recursive_mutex> lock(1383      m_modules_mutex, other.m_modules_mutex);1384  m_modules.swap(other.m_modules);1385}1386 1387void ModuleList::PreloadSymbols(bool parallelize) const {1388  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);1389 1390  if (!parallelize) {1391    for (const ModuleSP &module_sp : m_modules)1392      module_sp->PreloadSymbols();1393    return;1394  }1395 1396  llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());1397  for (const ModuleSP &module_sp : m_modules)1398    task_group.async([module_sp] {1399      if (module_sp)1400        module_sp->PreloadSymbols();1401    });1402  task_group.wait();1403}1404