LLDB mainline
ModuleList.cpp
Go to the documentation of this file.
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
10#include "lldb/Core/Debugger.h"
11#include "lldb/Core/Module.h"
24#include "lldb/Target/Target.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)
36#endif
37
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 {
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_modulelist
72#include "CoreProperties.inc"
73
74enum {
75#define LLDB_PROPERTIES_modulelist
76#include "CorePropertiesEnum.inc"
77};
78
79} // namespace
80
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)) {
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");
97 }
98}
99
101 const uint32_t idx = ePropertyEnableExternalLookup;
103 idx, g_modulelist_properties[idx].default_uint_value != 0);
104}
105
107 return SetPropertyAtIndex(ePropertyEnableExternalLookup, new_value);
108}
109
111 // Backward compatibility alias.
112 if (GetPropertyAtIndexAs<bool>(ePropertyEnableBackgroundLookup, false))
114
115 const uint32_t idx = ePropertyAutoDownload;
117 idx, static_cast<lldb::SymbolDownload>(
118 g_modulelist_properties[idx].default_uint_value));
119}
120
122 const uint32_t idx = ePropertyClangModulesCachePath;
123 return GetPropertyAtIndexAs<FileSpec>(idx, {});
124}
125
127 const uint32_t idx = ePropertyClangModulesCachePath;
128 return SetPropertyAtIndex(idx, path);
129}
130
132 const uint32_t idx = ePropertyLLDBIndexCachePath;
133 return GetPropertyAtIndexAs<FileSpec>(idx, {});
134}
135
137 const uint32_t idx = ePropertyLLDBIndexCachePath;
138 return SetPropertyAtIndex(idx, path);
139}
140
142 const uint32_t idx = ePropertyEnableLLDBIndexCache;
144 idx, g_modulelist_properties[idx].default_uint_value != 0);
145}
146
148 return SetPropertyAtIndex(ePropertyEnableLLDBIndexCache, new_value);
149}
150
152 const uint32_t idx = ePropertyLLDBIndexCacheMaxByteSize;
154 idx, g_modulelist_properties[idx].default_uint_value);
155}
156
158 const uint32_t idx = ePropertyLLDBIndexCacheMaxPercent;
160 idx, g_modulelist_properties[idx].default_uint_value);
161}
162
164 const uint32_t idx = ePropertyLLDBIndexCacheExpirationDays;
166 idx, g_modulelist_properties[idx].default_uint_value);
167}
168
170 FileSpecList list =
171 GetPropertyAtIndexAs<FileSpecList>(ePropertySymLinkPaths, {});
172 llvm::sys::ScopedWriter lock(m_symlink_paths_mutex);
173 const bool notify = false;
174 m_symlink_paths.Clear(notify);
175 for (auto symlink : list) {
176 FileSpec resolved;
177 Status status = FileSystem::Instance().Readlink(symlink, resolved);
178 if (status.Success())
179 m_symlink_paths.Append(symlink.GetPath(), resolved.GetPath(), notify);
180 }
181}
182
184 llvm::sys::ScopedReader lock(m_symlink_paths_mutex);
185 return m_symlink_paths;
186}
187
189 const uint32_t idx = ePropertyLoadSymbolOnDemand;
191 idx, g_modulelist_properties[idx].default_uint_value != 0);
192}
193
195
197 std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex);
198 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex);
199 m_modules = rhs.m_modules;
200}
201
204
206 if (this != &rhs) {
207 std::lock(m_modules_mutex, rhs.m_modules_mutex);
208 std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex,
209 std::adopt_lock);
210 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex,
211 std::adopt_lock);
212 m_modules = rhs.m_modules;
213 }
214 return *this;
215}
216
217ModuleList::~ModuleList() = default;
218
219void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) {
220 if (!module_sp)
221 return;
222 {
223 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
224 // We are required to keep the first element of the Module List as the
225 // executable module. So check here and if the first module is NOT an
226 // but the new one is, we insert this module at the beginning, rather than
227 // at the end.
228 // We don't need to do any of this if the list is empty:
229 if (m_modules.empty()) {
230 m_modules.push_back(module_sp);
231 } else {
232 // Since producing the ObjectFile may take some work, first check the
233 // 0th element, and only if that's NOT an executable look at the
234 // incoming ObjectFile. That way in the normal case we only look at the
235 // element 0 ObjectFile.
236 const bool elem_zero_is_executable =
237 m_modules[0]->GetObjectFile()->GetType() ==
239 lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
240 if (!elem_zero_is_executable && obj &&
242 m_modules.insert(m_modules.begin(), module_sp);
243 } else {
244 m_modules.push_back(module_sp);
245 }
246 }
247 }
248 // Release the mutex before calling the notifier to avoid deadlock
249 // NotifyModuleAdded should be thread-safe
250 if (use_notifier && m_notifier)
251 m_notifier->NotifyModuleAdded(*this, module_sp);
252}
253
254void ModuleList::Append(const ModuleSP &module_sp, bool notify) {
255 AppendImpl(module_sp, notify);
256}
257
259 const ModuleSP &module_sp,
261 if (module_sp) {
262 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
263
264 // First remove any equivalent modules. Equivalent modules are modules
265 // whose path, platform path and architecture match.
266 ModuleSpec equivalent_module_spec(module_sp->GetFileSpec(),
267 module_sp->GetArchitecture());
268 equivalent_module_spec.GetPlatformFileSpec() =
269 module_sp->GetPlatformFileSpec();
270
271 size_t idx = 0;
272 while (idx < m_modules.size()) {
273 ModuleSP test_module_sp(m_modules[idx]);
274 if (test_module_sp->MatchesModuleSpec(equivalent_module_spec)) {
275 if (old_modules)
276 old_modules->push_back(test_module_sp);
277 RemoveImpl(m_modules.begin() + idx);
278 } else {
279 ++idx;
280 }
281 }
282 // Now add the new module to the list
283 Append(module_sp);
284 }
285}
286
287bool ModuleList::AppendIfNeeded(const ModuleSP &new_module, bool notify) {
288 if (new_module) {
289 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
290 for (const ModuleSP &module_sp : m_modules) {
291 if (module_sp.get() == new_module.get())
292 return false; // Already in the list
293 }
294 // Only push module_sp on the list if it wasn't already in there.
295 Append(new_module, notify);
296 return true;
297 }
298 return false;
299}
300
301void ModuleList::Append(const ModuleList &module_list) {
302 for (auto pos : module_list.m_modules)
303 Append(pos);
304}
305
306bool ModuleList::AppendIfNeeded(const ModuleList &module_list) {
307 bool any_in = false;
308 for (auto pos : module_list.m_modules) {
309 if (AppendIfNeeded(pos))
310 any_in = true;
311 }
312 return any_in;
313}
314
315bool ModuleList::RemoveImpl(const ModuleSP &module_sp, bool use_notifier) {
316 if (module_sp) {
317 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
318 collection::iterator pos, end = m_modules.end();
319 for (pos = m_modules.begin(); pos != end; ++pos) {
320 if (pos->get() == module_sp.get()) {
321 m_modules.erase(pos);
322 if (use_notifier && m_notifier)
323 m_notifier->NotifyModuleRemoved(*this, module_sp);
324 return true;
325 }
326 }
327 }
328 return false;
329}
330
331ModuleList::collection::iterator
332ModuleList::RemoveImpl(ModuleList::collection::iterator pos,
333 bool use_notifier) {
334 ModuleSP module_sp(*pos);
335 collection::iterator retval = m_modules.erase(pos);
336 if (use_notifier && m_notifier)
337 m_notifier->NotifyModuleRemoved(*this, module_sp);
338 return retval;
339}
340
341bool ModuleList::Remove(const ModuleSP &module_sp, bool notify) {
342 return RemoveImpl(module_sp, notify);
343}
344
346 const lldb::ModuleSP &new_module_sp) {
347 if (!RemoveImpl(old_module_sp, false))
348 return false;
349 AppendImpl(new_module_sp, false);
350 if (m_notifier)
351 m_notifier->NotifyModuleUpdated(*this, old_module_sp, new_module_sp);
352 return true;
353}
354
356 if (auto module_sp = module_wp.lock()) {
357 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
358 collection::iterator pos, end = m_modules.end();
359 for (pos = m_modules.begin(); pos != end; ++pos) {
360 if (pos->get() == module_sp.get()) {
361 // Since module_sp increases the refcount by 1, the use count should be
362 // the regular use count + 1.
363 constexpr long kUseCountOrphaned = kUseCountModuleListOrphaned + 1;
364 if (pos->use_count() == kUseCountOrphaned) {
365 pos = RemoveImpl(pos);
366 return true;
367 }
368 return false;
369 }
370 }
371 }
372 return false;
373}
374
375size_t ModuleList::RemoveOrphans(bool mandatory) {
376 std::unique_lock<std::recursive_mutex> lock(m_modules_mutex, std::defer_lock);
377
378 if (mandatory) {
379 lock.lock();
380 } else {
381 // Not mandatory, remove orphans if we can get the mutex
382 if (!lock.try_lock())
383 return 0;
384 }
385 size_t remove_count = 0;
386 // Modules might hold shared pointers to other modules, so removing one
387 // module might make other modules orphans. Keep removing modules until
388 // there are no further modules that can be removed.
389 bool made_progress = true;
390 while (made_progress) {
391 // Keep track if we make progress this iteration.
392 made_progress = false;
393 collection::iterator pos = m_modules.begin();
394 while (pos != m_modules.end()) {
395 if (pos->use_count() == kUseCountModuleListOrphaned) {
396 pos = RemoveImpl(pos);
397 ++remove_count;
398 // We did make progress.
399 made_progress = true;
400 } else {
401 ++pos;
402 }
403 }
404 }
405 return remove_count;
406}
407
408size_t ModuleList::Remove(ModuleList &module_list) {
409 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
410 size_t num_removed = 0;
411 collection::iterator pos, end = module_list.m_modules.end();
412 for (pos = module_list.m_modules.begin(); pos != end; ++pos) {
413 if (Remove(*pos, false /* notify */))
414 ++num_removed;
415 }
416 if (m_notifier)
417 m_notifier->NotifyModulesRemoved(module_list);
418 return num_removed;
419}
420
422
424
425void ModuleList::ClearImpl(bool use_notifier) {
426 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
427 if (use_notifier && m_notifier)
428 m_notifier->NotifyWillClearList(*this);
429 m_modules.clear();
430}
431
433 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
434 if (idx < m_modules.size())
435 return m_modules[idx].get();
436 return nullptr;
437}
438
440 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
441 return GetModuleAtIndexUnlocked(idx);
442}
443
445 ModuleSP module_sp;
446 if (idx < m_modules.size())
447 module_sp = m_modules[idx];
448 return module_sp;
449}
450
452 FunctionNameType name_type_mask,
453 const ModuleFunctionSearchOptions &options,
454 SymbolContextList &sc_list) const {
455 if (name_type_mask & eFunctionNameTypeAuto) {
456 std::vector<Module::LookupInfo> lookup_infos =
457 Module::LookupInfo::MakeLookupInfos(name, name_type_mask,
459 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
460 for (const auto &lookup_info : lookup_infos) {
461 const size_t old_size = sc_list.GetSize();
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 if (old_size < new_size)
469 lookup_info.Prune(sc_list, old_size);
470 }
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
481 lldb::FunctionNameType name_type_mask,
482 SymbolContextList &sc_list) {
483 if (name_type_mask & eFunctionNameTypeAuto) {
484 std::vector<Module::LookupInfo> lookup_infos =
485 Module::LookupInfo::MakeLookupInfos(name, name_type_mask,
487
488 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
489 for (const auto &lookup_info : lookup_infos) {
490 const size_t old_size = sc_list.GetSize();
491 for (const ModuleSP &module_sp : m_modules) {
492 module_sp->FindFunctionSymbols(lookup_info.GetLookupName(),
493 lookup_info.GetNameTypeMask(), sc_list);
494 }
495
496 const size_t new_size = sc_list.GetSize();
497
498 if (old_size < new_size)
499 lookup_info.Prune(sc_list, old_size);
500 }
501 } else {
502 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
503 for (const ModuleSP &module_sp : m_modules) {
504 module_sp->FindFunctionSymbols(name, name_type_mask, sc_list);
505 }
506 }
507}
508
510 const ModuleFunctionSearchOptions &options,
511 SymbolContextList &sc_list) {
512 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
513 for (const ModuleSP &module_sp : m_modules)
514 module_sp->FindFunctions(name, options, sc_list);
515}
516
518 SymbolContextList &sc_list) const {
519 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
520 for (const ModuleSP &module_sp : m_modules)
521 module_sp->FindCompileUnits(path, sc_list);
522}
523
524void ModuleList::FindGlobalVariables(ConstString name, size_t max_matches,
525 VariableList &variable_list) const {
526 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
527 for (const ModuleSP &module_sp : m_modules) {
528 module_sp->FindGlobalVariables(name, CompilerDeclContext(), max_matches,
529 variable_list);
530 }
531}
532
534 size_t max_matches,
535 VariableList &variable_list) const {
536 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
537 for (const ModuleSP &module_sp : m_modules)
538 module_sp->FindGlobalVariables(regex, max_matches, variable_list);
539}
540
542 SymbolType symbol_type,
543 SymbolContextList &sc_list) const {
544 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
545 for (const ModuleSP &module_sp : m_modules)
546 module_sp->FindSymbolsWithNameAndType(name, symbol_type, sc_list);
547}
548
550 const RegularExpression &regex, lldb::SymbolType symbol_type,
551 SymbolContextList &sc_list) const {
552 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
553 for (const ModuleSP &module_sp : m_modules)
554 module_sp->FindSymbolsMatchingRegExAndType(regex, symbol_type, sc_list);
555}
556
557void ModuleList::FindModules(const ModuleSpec &module_spec,
558 ModuleList &matching_module_list) const {
559 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
560 for (const ModuleSP &module_sp : m_modules) {
561 if (module_sp->MatchesModuleSpec(module_spec))
562 matching_module_list.Append(module_sp);
563 }
564}
565
566ModuleSP ModuleList::FindModule(const Module *module_ptr) const {
567 ModuleSP module_sp;
568
569 // Scope for "locker"
570 {
571 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
572 collection::const_iterator pos, end = m_modules.end();
573
574 for (pos = m_modules.begin(); pos != end; ++pos) {
575 if ((*pos).get() == module_ptr) {
576 module_sp = (*pos);
577 break;
578 }
579 }
580 }
581 return module_sp;
582}
583
585 ModuleSP module_sp;
586
587 if (uuid.IsValid()) {
588 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
589 collection::const_iterator pos, end = m_modules.end();
590
591 for (pos = m_modules.begin(); pos != end; ++pos) {
592 if ((*pos)->GetUUID() == uuid) {
593 module_sp = (*pos);
594 break;
595 }
596 }
597 }
598 return module_sp;
599}
600
602 ModuleSP module_sp;
603 ForEach([&](const ModuleSP &m) {
604 if (m->GetID() == uid) {
605 module_sp = m;
607 }
608
610 });
611
612 return module_sp;
613}
614
615void ModuleList::FindTypes(Module *search_first, const TypeQuery &query,
616 TypeResults &results) const {
617 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
618 if (search_first) {
619 search_first->FindTypes(query, results);
620 if (results.Done(query))
621 return;
622 }
623 for (const auto &module_sp : m_modules) {
624 if (search_first != module_sp.get()) {
625 module_sp->FindTypes(query, results);
626 if (results.Done(query))
627 return;
628 }
629 }
630}
631
633 FileSpec &new_spec) const {
634 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
635 for (const ModuleSP &module_sp : m_modules) {
636 if (module_sp->FindSourceFile(orig_spec, new_spec))
637 return true;
638 }
639 return false;
640}
641
643 const FileSpec &file, uint32_t line,
644 Function *function,
645 std::vector<Address> &output_local,
646 std::vector<Address> &output_extern) {
647 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
648 for (const ModuleSP &module_sp : m_modules) {
649 module_sp->FindAddressesForLine(target_sp, file, line, function,
650 output_local, output_extern);
651 }
652}
653
655 ModuleSP module_sp;
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 ModuleSP module_sp(*pos);
660 if (module_sp->MatchesModuleSpec(module_spec))
661 return module_sp;
662 }
663 return module_sp;
664}
665
666size_t ModuleList::GetSize() const {
667 size_t size = 0;
668 {
669 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
670 size = m_modules.size();
671 }
672 return size;
673}
674
675void ModuleList::Dump(Stream *s) const {
676 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
677 for (const ModuleSP &module_sp : m_modules)
678 module_sp->Dump(s);
679}
680
681void ModuleList::LogUUIDAndPaths(Log *log, const char *prefix_cstr) {
682 if (log != nullptr) {
683 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
684 collection::const_iterator pos, begin = m_modules.begin(),
685 end = m_modules.end();
686 for (pos = begin; pos != end; ++pos) {
687 Module *module = pos->get();
688 const FileSpec &module_file_spec = module->GetFileSpec();
689 LLDB_LOGF(log, "%s[%u] %s (%s) \"%s\"", prefix_cstr ? prefix_cstr : "",
690 (uint32_t)std::distance(begin, pos),
691 module->GetUUID().GetAsString().c_str(),
693 module_file_spec.GetPath().c_str());
694 }
695 }
696}
697
699 Address &so_addr) const {
700 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
701 for (const ModuleSP &module_sp : m_modules) {
702 if (module_sp->ResolveFileAddress(vm_addr, so_addr))
703 return true;
704 }
705
706 return false;
707}
708
709uint32_t
711 SymbolContextItem resolve_scope,
712 SymbolContext &sc) const {
713 // The address is already section offset so it has a module
714 uint32_t resolved_flags = 0;
715 ModuleSP module_sp(so_addr.GetModule());
716 if (module_sp) {
717 resolved_flags =
718 module_sp->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc);
719 } else {
720 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
721 collection::const_iterator pos, end = m_modules.end();
722 for (pos = m_modules.begin(); pos != end; ++pos) {
723 resolved_flags =
724 (*pos)->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc);
725 if (resolved_flags != 0)
726 break;
727 }
728 }
729
730 return resolved_flags;
731}
732
734 const char *file_path, uint32_t line, bool check_inlines,
735 SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {
736 FileSpec file_spec(file_path);
737 return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
738 resolve_scope, sc_list);
739}
740
742 const FileSpec &file_spec, uint32_t line, bool check_inlines,
743 SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {
744 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
745 for (const ModuleSP &module_sp : m_modules) {
746 module_sp->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
747 resolve_scope, sc_list);
748 }
749
750 return sc_list.GetSize();
751}
752
753size_t ModuleList::GetIndexForModule(const Module *module) const {
754 if (module) {
755 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
756 collection::const_iterator pos;
757 collection::const_iterator begin = m_modules.begin();
758 collection::const_iterator end = m_modules.end();
759 for (pos = begin; pos != end; ++pos) {
760 if ((*pos).get() == module)
761 return std::distance(begin, pos);
762 }
763 }
765}
766
767namespace {
768/// A wrapper around ModuleList for shared modules. Provides fast lookups for
769/// file-based ModuleSpec queries.
770class SharedModuleList {
771public:
772 /// Finds all the modules matching the module_spec, and adds them to \p
773 /// matching_module_list.
774 void FindModules(const ModuleSpec &module_spec,
775 ModuleList &matching_module_list) const {
776 std::lock_guard<std::recursive_mutex> guard(GetMutex());
777 // Try map first for performance - if found, skip expensive full list
778 // search.
779 FindModulesInMap(module_spec, matching_module_list);
780 if (!matching_module_list.IsEmpty())
781 return;
782 m_list.FindModules(module_spec, matching_module_list);
783 // Assert that modules were found in the list but not the map, it's
784 // because the module_spec has no filename or the found module has a
785 // different filename. For example, when searching by UUID and finding a
786 // module with an alias.
787 assert((matching_module_list.IsEmpty() ||
788 module_spec.GetFileSpec().GetFilename().IsEmpty() ||
789 module_spec.GetFileSpec().GetFilename() !=
790 matching_module_list.GetModuleAtIndex(0)
791 ->GetFileSpec()
792 .GetFilename()) &&
793 "Search by name not found in SharedModuleList's map");
794 }
795
796 ModuleSP FindModule(const Module &module) {
797
798 std::lock_guard<std::recursive_mutex> guard(GetMutex());
799 if (ModuleSP result = FindModuleInMap(module))
800 return result;
801 return m_list.FindModule(&module);
802 }
803
804 // UUID searches bypass map since UUIDs aren't indexed by filename.
805 ModuleSP FindModule(const UUID &uuid) const {
806 return m_list.FindModule(uuid);
807 }
808
809 void Append(const ModuleSP &module_sp, bool use_notifier) {
810 if (!module_sp)
811 return;
812 std::lock_guard<std::recursive_mutex> guard(GetMutex());
813 m_list.Append(module_sp, use_notifier);
814 AddToMap(module_sp);
815 }
816
817 size_t RemoveOrphans(bool mandatory) {
818 std::unique_lock<std::recursive_mutex> lock(GetMutex(), std::defer_lock);
819 if (mandatory) {
820 lock.lock();
821 } else {
822 if (!lock.try_lock())
823 return 0;
824 }
825 size_t total_count = 0;
826 size_t run_count;
827 do {
828 // Remove indexed orphans first, then remove non-indexed orphans. This
829 // order is important because the shared count will be different if a
830 // module is indexed or not.
831 run_count = RemoveOrphansFromMapAndList();
832 run_count += m_list.RemoveOrphans(mandatory);
833 total_count += run_count;
834 // Because removing orphans might make new orphans, remove from both
835 // containers until a fixed-point is reached.
836 } while (run_count != 0);
837
838 return total_count;
839 }
840
841 bool Remove(const ModuleSP &module_sp, bool use_notifier = true) {
842 if (!module_sp)
843 return false;
844 std::lock_guard<std::recursive_mutex> guard(GetMutex());
845 RemoveFromMap(module_sp);
846 return m_list.Remove(module_sp, use_notifier);
847 }
848
849 void ReplaceEquivalent(const ModuleSP &module_sp,
850 llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules) {
851 std::lock_guard<std::recursive_mutex> guard(GetMutex());
852 m_list.ReplaceEquivalent(module_sp, old_modules);
853 ReplaceEquivalentInMap(module_sp);
854 }
855
856 bool RemoveIfOrphaned(const ModuleWP module_wp) {
857 std::lock_guard<std::recursive_mutex> guard(GetMutex());
858 RemoveFromMap(module_wp, /*if_orphaned=*/true);
859 return m_list.RemoveIfOrphaned(module_wp);
860 }
861
862 std::recursive_mutex &GetMutex() const { return m_list.GetMutex(); }
863
864private:
865 ModuleSP FindModuleInMap(const Module &module) const {
866 if (!module.GetFileSpec().GetFilename())
867 return ModuleSP();
868 ConstString name = module.GetFileSpec().GetFilename();
869 auto it = m_name_to_modules.find(name);
870 if (it == m_name_to_modules.end())
871 return ModuleSP();
872 const llvm::SmallVectorImpl<ModuleSP> &vector = it->second;
873 for (const ModuleSP &module_sp : vector) {
874 if (module_sp.get() == &module)
875 return module_sp;
876 }
877 return ModuleSP();
878 }
879
880 void FindModulesInMap(const ModuleSpec &module_spec,
881 ModuleList &matching_module_list) const {
882 auto it = m_name_to_modules.find(module_spec.GetFileSpec().GetFilename());
883 if (it == m_name_to_modules.end())
884 return;
885 const llvm::SmallVectorImpl<ModuleSP> &vector = it->second;
886 for (const ModuleSP &module_sp : vector) {
887 if (module_sp->MatchesModuleSpec(module_spec))
888 matching_module_list.Append(module_sp);
889 }
890 }
891
892 void AddToMap(const ModuleSP &module_sp) {
893 ConstString name = module_sp->GetFileSpec().GetFilename();
894 if (name.IsEmpty())
895 return;
896 m_name_to_modules[name].push_back(module_sp);
897 }
898
899 void RemoveFromMap(const ModuleWP module_wp, bool if_orphaned = false) {
900 if (auto module_sp = module_wp.lock()) {
901 ConstString name = module_sp->GetFileSpec().GetFilename();
902 if (!m_name_to_modules.contains(name))
903 return;
904 llvm::SmallVectorImpl<ModuleSP> &vec = m_name_to_modules[name];
905 for (auto *it = vec.begin(); it != vec.end(); ++it) {
906 if (it->get() == module_sp.get()) {
907 // Since module_sp increases the refcount by 1, the use count should
908 // be the regular use count + 1.
909 constexpr long kUseCountOrphaned =
910 kUseCountSharedModuleListOrphaned + 1;
911 if (!if_orphaned || it->use_count() == kUseCountOrphaned) {
912 vec.erase(it);
913 break;
914 }
915 }
916 }
917 }
918 }
919
920 void ReplaceEquivalentInMap(const ModuleSP &module_sp) {
921 RemoveEquivalentModulesFromMap(module_sp);
922 AddToMap(module_sp);
923 }
924
925 void RemoveEquivalentModulesFromMap(const ModuleSP &module_sp) {
926 ConstString name = module_sp->GetFileSpec().GetFilename();
927 if (name.IsEmpty())
928 return;
929
930 auto it = m_name_to_modules.find(name);
931 if (it == m_name_to_modules.end())
932 return;
933
934 // First remove any equivalent modules. Equivalent modules are modules
935 // whose path, platform path and architecture match.
936 ModuleSpec equivalent_module_spec(module_sp->GetFileSpec(),
937 module_sp->GetArchitecture());
938 equivalent_module_spec.GetPlatformFileSpec() =
939 module_sp->GetPlatformFileSpec();
940
941 llvm::SmallVectorImpl<ModuleSP> &vec = it->second;
942 llvm::erase_if(vec, [&equivalent_module_spec](ModuleSP &element) {
943 return element->MatchesModuleSpec(equivalent_module_spec);
944 });
945 }
946
947 /// Remove orphans from the vector and return the removed modules.
948 ModuleList RemoveOrphansFromVector(llvm::SmallVectorImpl<ModuleSP> &vec) {
949 // remove_if moves the elements that match the condition to the end of the
950 // container, and returns an iterator to the first element that was moved.
951 auto *to_remove_start = llvm::remove_if(vec, [](const ModuleSP &module) {
952 return module.use_count() == kUseCountSharedModuleListOrphaned;
953 });
954
955 ModuleList to_remove;
956 for (ModuleSP *it = to_remove_start; it != vec.end(); ++it)
957 to_remove.Append(*it);
958
959 vec.erase(to_remove_start, vec.end());
960 return to_remove;
961 }
962
963 /// Remove orphans that exist in both the map and list. This does not remove
964 /// any orphans that exist exclusively on the list.
965 ///
966 /// The mutex must be locked by the caller.
967 int RemoveOrphansFromMapAndList() {
968 // Modules might hold shared pointers to other modules, so removing one
969 // module might orphan other modules. Keep removing modules until
970 // there are no further modules that can be removed.
971 int remove_count = 0;
972 int previous_remove_count;
973 do {
974 previous_remove_count = remove_count;
975 for (auto &[name, vec] : m_name_to_modules) {
976 if (vec.empty())
977 continue;
978 ModuleList to_remove = RemoveOrphansFromVector(vec);
979 remove_count += to_remove.GetSize();
980 m_list.Remove(to_remove);
981 }
982 // Break when fixed-point is reached.
983 } while (previous_remove_count != remove_count);
984
985 return remove_count;
986 }
987
988 ModuleList m_list;
989
990 /// A hash map from a module's filename to all the modules that share that
991 /// filename, for fast module lookups by name.
992 llvm::DenseMap<ConstString, llvm::SmallVector<ModuleSP, 1>> m_name_to_modules;
993
994 /// The use count of a module held only by m_list and m_name_to_modules.
995 static constexpr long kUseCountSharedModuleListOrphaned = 2;
996};
997
998struct SharedModuleListInfo {
999 SharedModuleList module_list;
1000 ModuleListProperties module_list_properties;
1001};
1002}
1003static SharedModuleListInfo &GetSharedModuleListInfo()
1004{
1005 static SharedModuleListInfo *g_shared_module_list_info = nullptr;
1006 static llvm::once_flag g_once_flag;
1007 llvm::call_once(g_once_flag, []() {
1008 // NOTE: Intentionally leak the module list so a program doesn't have to
1009 // cleanup all modules and object files as it exits. This just wastes time
1010 // doing a bunch of cleanup that isn't required.
1011 if (g_shared_module_list_info == nullptr)
1012 g_shared_module_list_info = new SharedModuleListInfo();
1013 });
1014 return *g_shared_module_list_info;
1015}
1016
1017static SharedModuleList &GetSharedModuleList() {
1018 return GetSharedModuleListInfo().module_list;
1019}
1020
1024
1025bool ModuleList::ModuleIsInCache(const Module *module_ptr) {
1026 if (module_ptr) {
1027 SharedModuleList &shared_module_list = GetSharedModuleList();
1028 return shared_module_list.FindModule(*module_ptr).get() != nullptr;
1029 }
1030 return false;
1031}
1032
1034 ModuleList &matching_module_list) {
1035 GetSharedModuleList().FindModules(module_spec, matching_module_list);
1036}
1037
1039 return GetSharedModuleList().FindModule(uuid);
1040}
1041
1043 return GetSharedModuleList().RemoveOrphans(mandatory);
1044}
1045
1046Status
1047ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
1049 bool *did_create_ptr, bool invoke_locate_callback) {
1050 SharedModuleList &shared_module_list = GetSharedModuleList();
1051 std::lock_guard<std::recursive_mutex> guard(shared_module_list.GetMutex());
1052 char path[PATH_MAX];
1053
1054 Status error;
1055
1056 module_sp.reset();
1057
1058 if (did_create_ptr)
1059 *did_create_ptr = false;
1060
1061 const UUID *uuid_ptr = module_spec.GetUUIDPtr();
1062 const FileSpec &module_file_spec = module_spec.GetFileSpec();
1063 const ArchSpec &arch = module_spec.GetArchitecture();
1064
1065 // Make sure no one else can try and get or create a module while this
1066 // function is actively working on it by doing an extra lock on the global
1067 // mutex list.
1068 {
1069 ModuleList matching_module_list;
1070 shared_module_list.FindModules(module_spec, matching_module_list);
1071 const size_t num_matching_modules = matching_module_list.GetSize();
1072
1073 if (num_matching_modules > 0) {
1074 for (size_t module_idx = 0; module_idx < num_matching_modules;
1075 ++module_idx) {
1076 module_sp = matching_module_list.GetModuleAtIndex(module_idx);
1077
1078 // Make sure the file for the module hasn't been modified
1079 if (module_sp->FileHasChanged()) {
1080 if (old_modules)
1081 old_modules->push_back(module_sp);
1082
1083 Log *log = GetLog(LLDBLog::Modules);
1084 if (log != nullptr)
1085 LLDB_LOGF(
1086 log, "%p '%s' module changed: removing from global module list",
1087 static_cast<void *>(module_sp.get()),
1088 module_sp->GetFileSpec().GetFilename().GetCString());
1089
1090 shared_module_list.Remove(module_sp);
1091 module_sp.reset();
1092 } else {
1093 // The module matches and the module was not modified from when it
1094 // was last loaded.
1095 return error;
1096 }
1097 }
1098 }
1099 }
1100
1101 if (module_sp)
1102 return error;
1103
1104 // Try platform's locate module callback before second attempt.
1105 // The platform can come from either the Target (if available) or directly
1106 // from the ModuleSpec (useful when Target is not yet created, e.g., during
1107 // target creation for launch mode).
1108 if (invoke_locate_callback) {
1109 PlatformSP platform_sp;
1110 if (TargetSP target_sp = module_spec.GetTargetSP()) {
1111 if (target_sp->IsValid())
1112 platform_sp = target_sp->GetPlatform();
1113 }
1114 if (!platform_sp)
1115 platform_sp = module_spec.GetPlatformSP();
1116
1117 if (platform_sp) {
1118 FileSpec symbol_file_spec;
1119 platform_sp->CallLocateModuleCallbackIfSet(
1120 module_spec, module_sp, symbol_file_spec, did_create_ptr);
1121 if (module_sp) {
1122 // The callback found a module.
1123 return error;
1124 }
1125 }
1126 }
1127
1128 module_sp = std::make_shared<Module>(module_spec);
1129 // Make sure there are a module and an object file since we can specify a
1130 // valid file path with an architecture that might not be in that file. By
1131 // getting the object file we can guarantee that the architecture matches
1132 if (module_sp->GetObjectFile()) {
1133 // If we get in here we got the correct arch, now we just need to verify
1134 // the UUID if one was given
1135 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {
1136 module_sp.reset();
1137 } else {
1138 if (module_sp->GetObjectFile() &&
1139 module_sp->GetObjectFile()->GetType() ==
1141 module_sp.reset();
1142 } else {
1143 if (did_create_ptr) {
1144 *did_create_ptr = true;
1145 }
1146
1147 shared_module_list.ReplaceEquivalent(module_sp, old_modules);
1148 return error;
1149 }
1150 }
1151 } else {
1152 module_sp.reset();
1153 }
1154
1155 // Get module search paths from the target if available.
1156 lldb::TargetSP target_sp = module_spec.GetTargetSP();
1157 FileSpecList module_search_paths;
1158 if (target_sp)
1159 module_search_paths = target_sp->GetExecutableSearchPaths();
1160
1161 if (!module_search_paths.IsEmpty()) {
1162 const auto num_directories = module_search_paths.GetSize();
1163 for (size_t idx = 0; idx < num_directories; ++idx) {
1164 auto search_path_spec = module_search_paths.GetFileSpecAtIndex(idx);
1165 FileSystem::Instance().Resolve(search_path_spec);
1166 namespace fs = llvm::sys::fs;
1167 if (!FileSystem::Instance().IsDirectory(search_path_spec))
1168 continue;
1169 search_path_spec.AppendPathComponent(
1170 module_spec.GetFileSpec().GetFilename().GetStringRef());
1171 if (!FileSystem::Instance().Exists(search_path_spec))
1172 continue;
1173
1174 auto resolved_module_spec(module_spec);
1175 resolved_module_spec.GetFileSpec() = search_path_spec;
1176 module_sp = std::make_shared<Module>(resolved_module_spec);
1177 if (module_sp->GetObjectFile()) {
1178 // If we get in here we got the correct arch, now we just need to
1179 // verify the UUID if one was given
1180 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {
1181 module_sp.reset();
1182 } else {
1183 if (module_sp->GetObjectFile()->GetType() ==
1185 module_sp.reset();
1186 } else {
1187 if (did_create_ptr)
1188 *did_create_ptr = true;
1189
1190 shared_module_list.ReplaceEquivalent(module_sp, old_modules);
1191 return Status();
1192 }
1193 }
1194 } else {
1195 module_sp.reset();
1196 }
1197 }
1198 }
1199
1200 // Either the file didn't exist where at the path, or no path was given, so
1201 // we now have to use more extreme measures to try and find the appropriate
1202 // module.
1203
1204 // Fixup the incoming path in case the path points to a valid file, yet the
1205 // arch or UUID (if one was passed in) don't match.
1206 ModuleSpec located_binary_modulespec;
1207 StatisticsMap symbol_locator_map;
1208 located_binary_modulespec = PluginManager::LocateExecutableObjectFile(
1209 module_spec, symbol_locator_map);
1210 // Don't look for the file if it appears to be the same one we already
1211 // checked for above...
1212 if (located_binary_modulespec.GetFileSpec() != module_file_spec) {
1213 if (!FileSystem::Instance().Exists(
1214 located_binary_modulespec.GetFileSpec())) {
1215 located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
1216 if (path[0] == '\0')
1217 module_file_spec.GetPath(path, sizeof(path));
1218 // How can this check ever be true? This branch it is false, and we
1219 // haven't modified file_spec.
1220 if (FileSystem::Instance().Exists(
1221 located_binary_modulespec.GetFileSpec())) {
1222 std::string uuid_str;
1223 if (uuid_ptr && uuid_ptr->IsValid())
1224 uuid_str = uuid_ptr->GetAsString();
1225
1226 if (arch.IsValid()) {
1227 if (!uuid_str.empty())
1229 "'%s' does not contain the %s architecture and UUID %s", path,
1230 arch.GetArchitectureName(), uuid_str.c_str());
1231 else
1233 "'%s' does not contain the %s architecture.", path,
1234 arch.GetArchitectureName());
1235 }
1236 } else {
1237 error = Status::FromErrorStringWithFormat("'%s' does not exist", path);
1238 }
1239 if (error.Fail())
1240 module_sp.reset();
1241 return error;
1242 }
1243
1244 // Make sure no one else can try and get or create a module while this
1245 // function is actively working on it by doing an extra lock on the global
1246 // mutex list.
1247 ModuleSpec platform_module_spec(module_spec);
1248 platform_module_spec.GetFileSpec() =
1249 located_binary_modulespec.GetFileSpec();
1250 platform_module_spec.GetPlatformFileSpec() =
1251 located_binary_modulespec.GetFileSpec();
1252 platform_module_spec.GetSymbolFileSpec() =
1253 located_binary_modulespec.GetSymbolFileSpec();
1254 ModuleList matching_module_list;
1255 shared_module_list.FindModules(platform_module_spec, matching_module_list);
1256 if (!matching_module_list.IsEmpty()) {
1257 module_sp = matching_module_list.GetModuleAtIndex(0);
1258
1259 // If we didn't have a UUID in mind when looking for the object file,
1260 // then we should make sure the modification time hasn't changed!
1261 if (platform_module_spec.GetUUIDPtr() == nullptr) {
1262 auto file_spec_mod_time = FileSystem::Instance().GetModificationTime(
1263 located_binary_modulespec.GetFileSpec());
1264 if (file_spec_mod_time != llvm::sys::TimePoint<>()) {
1265 if (file_spec_mod_time != module_sp->GetModificationTime()) {
1266 if (old_modules)
1267 old_modules->push_back(module_sp);
1268 shared_module_list.Remove(module_sp);
1269 module_sp.reset();
1270 }
1271 }
1272 }
1273 }
1274
1275 if (!module_sp) {
1276 module_sp = std::make_shared<Module>(platform_module_spec);
1277 // Make sure there are a module and an object file since we can specify a
1278 // valid file path with an architecture that might not be in that file.
1279 // By getting the object file we can guarantee that the architecture
1280 // matches
1281 if (module_sp && module_sp->GetObjectFile()) {
1282 module_sp->GetSymbolLocatorStatistics().merge(symbol_locator_map);
1283 if (module_sp->GetObjectFile()->GetType() ==
1285 module_sp.reset();
1286 } else {
1287 if (did_create_ptr)
1288 *did_create_ptr = true;
1289
1290 shared_module_list.ReplaceEquivalent(module_sp, old_modules);
1291 }
1292 } else {
1293 located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
1294
1295 if (located_binary_modulespec.GetFileSpec()) {
1296 if (arch.IsValid())
1298 "unable to open %s architecture in '%s'",
1299 arch.GetArchitectureName(), path);
1300 else
1301 error =
1302 Status::FromErrorStringWithFormat("unable to open '%s'", path);
1303 } else {
1304 std::string uuid_str;
1305 if (uuid_ptr && uuid_ptr->IsValid())
1306 uuid_str = uuid_ptr->GetAsString();
1307
1308 if (!uuid_str.empty())
1310 "cannot locate a module for UUID '%s'", uuid_str.c_str());
1311 else
1312 error = Status::FromErrorString("cannot locate a module");
1313 }
1314 }
1315 }
1316 }
1317
1318 return error;
1319}
1320
1322 return GetSharedModuleList().Remove(module_sp);
1323}
1324
1326 return GetSharedModuleList().RemoveIfOrphaned(module_wp);
1327}
1328
1330 std::list<Status> &errors,
1331 Stream &feedback_stream,
1332 bool continue_on_error) {
1333 if (!target)
1334 return false;
1335 m_modules_mutex.lock();
1336 // Don't hold the module list mutex while loading the scripting resources,
1337 // The initializer might do any amount of work, and having that happen while
1338 // the module list is held is asking for A/B locking problems.
1339 const ModuleList tmp_module_list(*this);
1340 m_modules_mutex.unlock();
1341
1342 for (auto module : tmp_module_list.ModulesNoLocking()) {
1343 if (module) {
1344 Status error;
1345 if (!module->LoadScriptingResourceInTarget(target, error,
1346 feedback_stream)) {
1347 if (error.Fail() && error.AsCString()) {
1349 "unable to load scripting data for "
1350 "module %s - error reported was %s",
1351 module->GetFileSpec()
1352 .GetFileNameStrippingExtension()
1353 .GetCString(),
1354 error.AsCString());
1355 errors.push_back(std::move(error));
1356 if (!continue_on_error)
1357 return false;
1358 }
1359 }
1360 }
1361 }
1362 return errors.empty();
1363}
1364
1366 std::function<IterationAction(const ModuleSP &module_sp)> const &callback)
1367 const {
1368 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1369 for (const auto &module_sp : m_modules) {
1370 assert(module_sp != nullptr);
1371 if (callback(module_sp) == IterationAction::Stop)
1372 break;
1373 }
1374}
1375
1377 std::function<bool(lldb_private::Module &module_sp)> const &callback)
1378 const {
1379 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1380 for (const auto &module_sp : m_modules) {
1381 assert(module_sp != nullptr);
1382 if (callback(*module_sp))
1383 return true;
1384 }
1385
1386 return false;
1387}
1388
1389
1391 // scoped_lock locks both mutexes at once.
1392 std::scoped_lock<std::recursive_mutex, std::recursive_mutex> lock(
1394 m_modules.swap(other.m_modules);
1395}
1396
1397void ModuleList::PreloadSymbols(bool parallelize) const {
1398 std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1399
1400 if (!parallelize) {
1401 for (const ModuleSP &module_sp : m_modules)
1402 module_sp->PreloadSymbols();
1403 return;
1404 }
1405
1406 llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
1407 for (const ModuleSP &module_sp : m_modules)
1408 task_group.async([module_sp] {
1409 if (module_sp)
1410 module_sp->PreloadSymbols();
1411 });
1412 task_group.wait();
1413}
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition LLDBAssert.h:16
#define LLDB_LOGF(log,...)
Definition Log.h:376
static SharedModuleListInfo & GetSharedModuleListInfo()
static SharedModuleList & GetSharedModuleList()
A section + offset based address class.
Definition Address.h:62
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition Address.cpp:273
An architecture specification class.
Definition ArchSpec.h:31
bool IsValid() const
Tests if this ArchSpec is valid.
Definition ArchSpec.h:366
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition ArchSpec.cpp:548
Represents a generic declaration context in a program.
A uniqued constant string class.
Definition ConstString.h:40
bool IsEmpty() const
Test for empty string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
static llvm::ThreadPoolInterface & GetThreadPool()
Shared thread pool. Use only with ThreadPoolTaskGroup.
A file collection class.
const FileSpec & GetFileSpecAtIndex(size_t idx) const
Get file at index.
size_t GetSize() const
Get the number of files in the file list.
A file utility class.
Definition FileSpec.h:57
const ConstString & GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:251
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:374
llvm::sys::TimePoint GetModificationTime(const FileSpec &file_spec) const
Returns the modification time of the given file.
Status Readlink(const FileSpec &src, FileSpec &dst)
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
A class that describes a function.
Definition Function.h:400
bool SetClangModulesCachePath(const FileSpec &path)
lldb::SymbolDownload GetSymbolAutoDownload() const
bool SetLLDBIndexCachePath(const FileSpec &path)
bool SetEnableExternalLookup(bool new_value)
PathMappingList GetSymlinkMappings() const
FileSpec GetClangModulesCachePath() const
llvm::sys::RWMutex m_symlink_paths_mutex
Definition ModuleList.h:72
bool SetEnableLLDBIndexCache(bool new_value)
virtual void NotifyModuleRemoved(const ModuleList &module_list, const lldb::ModuleSP &module_sp)=0
A collection class for Module objects.
Definition ModuleList.h:101
bool ReplaceModule(const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp)
collection m_modules
The collection of modules.
Definition ModuleList.h:531
void ClearImpl(bool use_notifier=true)
uint32_t ResolveSymbolContextsForFileSpec(const FileSpec &file_spec, uint32_t line, bool check_inlines, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const
Resolve items in the symbol context for a given file and line. (const FileSpec&,...
static bool RemoveSharedModule(lldb::ModuleSP &module_sp)
void FindFunctions(ConstString name, lldb::FunctionNameType name_type_mask, const ModuleFunctionSearchOptions &options, SymbolContextList &sc_list) const
bool FindSourceFile(const FileSpec &orig_spec, FileSpec &new_spec) const
bool AnyOf(std::function< bool(lldb_private::Module &module)> const &callback) const
Returns true if 'callback' returns true for one of the modules in this ModuleList.
ModuleIterableNoLocking ModulesNoLocking() const
Definition ModuleList.h:548
static constexpr long kUseCountModuleListOrphaned
An orphaned module that lives only in the ModuleList has a count of 1.
Definition ModuleList.h:537
static bool ModuleIsInCache(const Module *module_ptr)
void FindGlobalVariables(ConstString name, size_t max_matches, VariableList &variable_list) const
Find global and static variables by name.
void Swap(ModuleList &other)
Atomically swaps the contents of this module list with other.
static Status GetSharedModule(const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, llvm::SmallVectorImpl< lldb::ModuleSP > *old_modules, bool *did_create_ptr, bool invoke_locate_callback=true)
size_t GetIndexForModule(const Module *module) const
bool RemoveImpl(const lldb::ModuleSP &module_sp, bool use_notifier=true)
lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const
Finds the first module whose file specification matches module_spec.
void Clear()
Clear the object's state.
ModuleList()
Default constructor.
void Dump(Stream *s) const
Dump the description of each module contained in this list.
void FindTypes(Module *search_first, const TypeQuery &query, lldb_private::TypeResults &results) const
Find types using a type-matching object that contains all search parameters.
uint32_t ResolveSymbolContextForFilePath(const char *file_path, uint32_t line, bool check_inlines, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const
Resolve items in the symbol context for a given file and line. (const char*,uint32_t,...
lldb::ModuleSP GetModuleAtIndexUnlocked(size_t idx) const
Get the module shared pointer for the module at index idx without acquiring the ModuleList mutex.
static bool RemoveSharedModuleIfOrphaned(const lldb::ModuleWP module_ptr)
void FindCompileUnits(const FileSpec &path, SymbolContextList &sc_list) const
Find compile units by partial or full path.
void PreloadSymbols(bool parallelize) const
For each module in this ModuleList, preload its symbols.
const ModuleList & operator=(const ModuleList &rhs)
Assignment operator.
std::recursive_mutex m_modules_mutex
Definition ModuleList.h:532
bool AppendIfNeeded(const lldb::ModuleSP &new_module, bool notify=true)
Append a module to the module list, if it is not already there.
Module * GetModulePointerAtIndex(size_t idx) const
Get the module pointer for the module at index idx.
void FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
static lldb::ModuleSP FindSharedModule(const UUID &uuid)
lldb::ModuleSP FindModule(const Module *module_ptr) const
static ModuleListProperties & GetGlobalModuleListProperties()
void FindModules(const ModuleSpec &module_spec, ModuleList &matching_module_list) const
Finds modules whose file specification matches module_spec.
void FindAddressesForLine(const lldb::TargetSP target_sp, const FileSpec &file, uint32_t line, Function *function, std::vector< Address > &output_local, std::vector< Address > &output_extern)
Find addresses by file/line.
uint32_t ResolveSymbolContextForAddress(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) const
Resolve the symbol context for the given address. (const Address&,uint32_t,SymbolContext&)
bool Remove(const lldb::ModuleSP &module_sp, bool notify=true)
Remove a module from the module list.
size_t RemoveOrphans(bool mandatory)
lldb::ModuleSP GetModuleAtIndex(size_t idx) const
Get the module shared pointer for the module at index idx.
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
static size_t RemoveOrphanSharedModules(bool mandatory)
void Destroy()
Clear the object's state.
void AppendImpl(const lldb::ModuleSP &module_sp, bool use_notifier=true)
bool LoadScriptingResourcesInTarget(Target *target, std::list< Status > &errors, Stream &feedback_stream, bool continue_on_error=true)
void ReplaceEquivalent(const lldb::ModuleSP &module_sp, llvm::SmallVectorImpl< lldb::ModuleSP > *old_modules=nullptr)
Append a module to the module list and remove any equivalent modules.
void FindFunctionSymbols(ConstString name, lldb::FunctionNameType name_type_mask, SymbolContextList &sc_list)
static void FindSharedModules(const ModuleSpec &module_spec, ModuleList &matching_module_list)
void FindSymbolsMatchingRegExAndType(const RegularExpression &regex, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
bool ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) const
size_t GetSize() const
Gets the size of the module list.
bool RemoveIfOrphaned(const lldb::ModuleWP module_ptr)
void LogUUIDAndPaths(Log *log, const char *prefix_cstr)
void ForEach(std::function< IterationAction(const lldb::ModuleSP &module_sp)> const &callback) const
Applies 'callback' to each module in this ModuleList.
FileSpec & GetPlatformFileSpec()
Definition ModuleSpec.h:69
FileSpec & GetFileSpec()
Definition ModuleSpec.h:57
lldb::PlatformSP GetPlatformSP() const
Definition ModuleSpec.h:143
ArchSpec & GetArchitecture()
Definition ModuleSpec.h:93
FileSpec & GetSymbolFileSpec()
Definition ModuleSpec.h:81
lldb::TargetSP GetTargetSP() const
Definition ModuleSpec.h:133
static std::vector< LookupInfo > MakeLookupInfos(ConstString name, lldb::FunctionNameType name_type_mask, lldb::LanguageType lang_type, ConstString lookup_name_override={})
Creates a vector of lookup infos for function name resolution.
Definition Module.cpp:705
A class that describes an executable image and its associated object and symbol files.
Definition Module.h:90
const lldb_private::UUID & GetUUID()
Get a reference to the UUID value contained in this object.
Definition Module.cpp:348
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
Definition Module.cpp:1040
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition Module.h:446
void FindTypes(const TypeQuery &query, TypeResults &results)
Find types using a type-matching object that contains all search parameters.
Definition Module.cpp:976
A plug-in interface definition class for object file parsers.
Definition ObjectFile.h:46
@ eTypeExecutable
A normal executable.
Definition ObjectFile.h:55
@ eTypeStubLibrary
A library that can be linked against but not used for execution.
Definition ObjectFile.h:65
static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec, StatisticsMap &map)
lldb::OptionValuePropertiesSP m_collection_sp
T GetPropertyAtIndexAs(uint32_t idx, T default_value, const ExecutionContext *exe_ctx=nullptr) const
bool SetPropertyAtIndex(uint32_t idx, T t, const ExecutionContext *exe_ctx=nullptr) const
A class to count time for plugins.
Definition Statistics.h:94
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
bool Success() const
Test for success condition.
Definition Status.cpp:304
A stream class that can stream formatted output to a file.
Definition Stream.h:28
Defines a list of symbol context objects.
uint32_t GetSize() const
Get accessor for a symbol context list size.
Defines a symbol context baton that can be handed other debug core functions.
Provides public interface for all SymbolFiles.
Definition SymbolFile.h:51
A class that contains all state required for type lookups.
Definition Type.h:104
This class tracks the state and results of a TypeQuery.
Definition Type.h:344
bool Done(const TypeQuery &query) const
Check if the type matching has found all of the matches that it needs.
Definition Type.cpp:200
Represents UUID's of various sizes.
Definition UUID.h:27
std::string GetAsString(llvm::StringRef separator="-") const
Definition UUID.cpp:54
bool IsValid() const
Definition UUID.h:69
#define LLDB_INVALID_INDEX32
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
IterationAction
Useful for callbacks whose return type indicates whether to continue iteration or short-circuit.
std::weak_ptr< lldb_private::Module > ModuleWP
std::shared_ptr< lldb_private::Platform > PlatformSP
@ eLanguageTypeUnknown
Unknown or invalid language value.
SymbolType
Symbol types.
uint64_t user_id_t
Definition lldb-types.h:82
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
@ eSymbolDownloadBackground
std::shared_ptr< lldb_private::Module > ModuleSP
Options used by Module::FindFunctions.
Definition Module.h:66
#define PATH_MAX