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