1 //===-- SearchFilter.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Core/SearchFilter.h"
12 #include "lldb/Breakpoint/Breakpoint.h" // for Breakpoint
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/ModuleList.h" // for ModuleList
15 #include "lldb/Symbol/CompileUnit.h"
16 #include "lldb/Symbol/SymbolContext.h" // for SymbolContext
17 #include "lldb/Target/Target.h"
18 #include "lldb/Utility/ConstString.h" // for ConstString
19 #include "lldb/Utility/Status.h" // for Status
20 #include "lldb/Utility/Stream.h" // for Stream
21 #include "lldb/lldb-enumerations.h" // for SymbolContextItem::eSymbolCo...
23 #include "llvm/ADT/StringRef.h" // for StringRef
24 #include "llvm/Support/ErrorHandling.h" // for llvm_unreachable
26 #include <memory> // for shared_ptr
27 #include <mutex> // for recursive_mutex, lock_guard
28 #include <string> // for string
30 #include <inttypes.h> // for PRIu64
31 #include <string.h> // for size_t, strcmp
33 namespace lldb_private {
36 namespace lldb_private {
41 using namespace lldb_private;
43 const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception",
45 "ModulesAndCU", "Unknown"};
48 *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = {
49 "ModuleList", "CUList"};
51 const char *SearchFilter::FilterTyToName(enum FilterTy type) {
52 if (type > LastKnownFilterType)
53 return g_ty_to_name[UnknownFilter];
55 return g_ty_to_name[type];
58 SearchFilter::FilterTy SearchFilter::NameToFilterTy(llvm::StringRef name) {
59 for (size_t i = 0; i <= LastKnownFilterType; i++) {
60 if (name == g_ty_to_name[i])
66 Searcher::Searcher() = default;
68 Searcher::~Searcher() = default;
70 void Searcher::GetDescription(Stream *s) {}
72 SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType)
73 : m_target_sp(target_sp), SubclassID(filterType) {}
75 SearchFilter::SearchFilter(const SearchFilter &rhs) = default;
77 SearchFilter &SearchFilter::operator=(const SearchFilter &rhs) = default;
79 SearchFilter::~SearchFilter() = default;
81 SearchFilterSP SearchFilter::CreateFromStructuredData(
82 Target &target, const StructuredData::Dictionary &filter_dict,
84 SearchFilterSP result_sp;
85 if (!filter_dict.IsValid()) {
86 error.SetErrorString("Can't deserialize from an invalid data object.");
90 llvm::StringRef subclass_name;
92 bool success = filter_dict.GetValueForKeyAsString(
93 GetSerializationSubclassKey(), subclass_name);
95 error.SetErrorStringWithFormat("Filter data missing subclass key");
99 FilterTy filter_type = NameToFilterTy(subclass_name);
100 if (filter_type == UnknownFilter) {
101 error.SetErrorStringWithFormatv("Unknown filter type: {0}.", subclass_name);
105 StructuredData::Dictionary *subclass_options = nullptr;
106 success = filter_dict.GetValueForKeyAsDictionary(
107 GetSerializationSubclassOptionsKey(), subclass_options);
108 if (!success || !subclass_options || !subclass_options->IsValid()) {
109 error.SetErrorString("Filter data missing subclass options key.");
113 switch (filter_type) {
115 result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
116 target, *subclass_options, error);
119 result_sp = SearchFilterByModule::CreateFromStructuredData(
120 target, *subclass_options, error);
123 result_sp = SearchFilterByModuleList::CreateFromStructuredData(
124 target, *subclass_options, error);
127 result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData(
128 target, *subclass_options, error);
131 error.SetErrorString("Can't serialize exception breakpoints yet.");
134 llvm_unreachable("Should never get an uresolvable filter type.");
140 bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; }
142 bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; }
144 bool SearchFilter::AddressPasses(Address &address) { return true; }
146 bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; }
148 bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; }
150 uint32_t SearchFilter::GetFilterRequiredItems() {
151 return (lldb::SymbolContextItem)0;
154 void SearchFilter::GetDescription(Stream *s) {}
156 void SearchFilter::Dump(Stream *s) const {}
158 lldb::SearchFilterSP SearchFilter::CopyForBreakpoint(Breakpoint &breakpoint) {
159 SearchFilterSP ret_sp = DoCopyForBreakpoint(breakpoint);
160 TargetSP target_sp = breakpoint.GetTargetSP();
161 ret_sp->SetTarget(target_sp);
165 //----------------------------------------------------------------------
166 // Helper functions for serialization.
167 //----------------------------------------------------------------------
169 StructuredData::DictionarySP
170 SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) {
171 if (!options_dict_sp || !options_dict_sp->IsValid())
172 return StructuredData::DictionarySP();
174 auto type_dict_sp = std::make_shared<StructuredData::Dictionary>();
175 type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetFilterName());
176 type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp);
181 void SearchFilter::SerializeFileSpecList(
182 StructuredData::DictionarySP &options_dict_sp, OptionNames name,
183 FileSpecList &file_list) {
184 size_t num_modules = file_list.GetSize();
186 // Don't serialize empty lists.
187 if (num_modules == 0)
190 auto module_array_sp = std::make_shared<StructuredData::Array>();
191 for (size_t i = 0; i < num_modules; i++) {
192 module_array_sp->AddItem(std::make_shared<StructuredData::String>(
193 file_list.GetFileSpecAtIndex(i).GetPath()));
195 options_dict_sp->AddItem(GetKey(name), module_array_sp);
198 //----------------------------------------------------------------------
199 // UTILITY Functions to help iterate down through the elements of the
201 //----------------------------------------------------------------------
203 void SearchFilter::Search(Searcher &searcher) {
204 SymbolContext empty_sc;
208 empty_sc.target_sp = m_target_sp;
210 if (searcher.GetDepth() == Searcher::eDepthTarget)
211 searcher.SearchCallback(*this, empty_sc, nullptr, false);
213 DoModuleIteration(empty_sc, searcher);
216 void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
217 SymbolContext empty_sc;
221 empty_sc.target_sp = m_target_sp;
223 if (searcher.GetDepth() == Searcher::eDepthTarget)
224 searcher.SearchCallback(*this, empty_sc, nullptr, false);
226 std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
227 const size_t numModules = modules.GetSize();
229 for (size_t i = 0; i < numModules; i++) {
230 ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i));
231 if (ModulePasses(module_sp)) {
232 if (DoModuleIteration(module_sp, searcher) ==
233 Searcher::eCallbackReturnStop)
240 Searcher::CallbackReturn
241 SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp,
242 Searcher &searcher) {
243 SymbolContext matchingContext(m_target_sp, module_sp);
244 return DoModuleIteration(matchingContext, searcher);
247 Searcher::CallbackReturn
248 SearchFilter::DoModuleIteration(const SymbolContext &context,
249 Searcher &searcher) {
250 if (searcher.GetDepth() >= Searcher::eDepthModule) {
251 if (context.module_sp) {
252 if (searcher.GetDepth() == Searcher::eDepthModule) {
253 SymbolContext matchingContext(context.module_sp.get());
254 searcher.SearchCallback(*this, matchingContext, nullptr, false);
256 return DoCUIteration(context.module_sp, context, searcher);
259 const ModuleList &target_images = m_target_sp->GetImages();
260 std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
262 size_t n_modules = target_images.GetSize();
263 for (size_t i = 0; i < n_modules; i++) {
264 // If this is the last level supplied, then call the callback directly,
265 // otherwise descend.
266 ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i));
267 if (!ModulePasses(module_sp))
270 if (searcher.GetDepth() == Searcher::eDepthModule) {
271 SymbolContext matchingContext(m_target_sp, module_sp);
273 Searcher::CallbackReturn shouldContinue =
274 searcher.SearchCallback(*this, matchingContext, nullptr, false);
275 if (shouldContinue == Searcher::eCallbackReturnStop ||
276 shouldContinue == Searcher::eCallbackReturnPop)
277 return shouldContinue;
279 Searcher::CallbackReturn shouldContinue =
280 DoCUIteration(module_sp, context, searcher);
281 if (shouldContinue == Searcher::eCallbackReturnStop)
282 return shouldContinue;
283 else if (shouldContinue == Searcher::eCallbackReturnPop)
289 return Searcher::eCallbackReturnContinue;
292 Searcher::CallbackReturn
293 SearchFilter::DoCUIteration(const ModuleSP &module_sp,
294 const SymbolContext &context, Searcher &searcher) {
295 Searcher::CallbackReturn shouldContinue;
296 if (context.comp_unit == nullptr) {
297 const size_t num_comp_units = module_sp->GetNumCompileUnits();
298 for (size_t i = 0; i < num_comp_units; i++) {
299 CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i));
301 if (!CompUnitPasses(*(cu_sp.get())))
304 if (searcher.GetDepth() == Searcher::eDepthCompUnit) {
305 SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
308 searcher.SearchCallback(*this, matchingContext, nullptr, false);
310 if (shouldContinue == Searcher::eCallbackReturnPop)
311 return Searcher::eCallbackReturnContinue;
312 else if (shouldContinue == Searcher::eCallbackReturnStop)
313 return shouldContinue;
315 // FIXME Descend to block.
320 if (CompUnitPasses(*context.comp_unit)) {
321 SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit);
322 return searcher.SearchCallback(*this, matchingContext, nullptr, false);
325 return Searcher::eCallbackReturnContinue;
328 Searcher::CallbackReturn SearchFilter::DoFunctionIteration(
329 Function *function, const SymbolContext &context, Searcher &searcher) {
330 // FIXME: Implement...
331 return Searcher::eCallbackReturnContinue;
334 //----------------------------------------------------------------------
335 // SearchFilterForUnconstrainedSearches:
336 // Selects a shared library matching a given file spec, consulting the targets
338 //----------------------------------------------------------------------
339 SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
340 Target &target, const StructuredData::Dictionary &data_dict,
342 // No options for an unconstrained search.
343 return std::make_shared<SearchFilterForUnconstrainedSearches>(
344 target.shared_from_this());
347 StructuredData::ObjectSP
348 SearchFilterForUnconstrainedSearches::SerializeToStructuredData() {
349 // The options dictionary is an empty dictionary:
350 auto result_sp = std::make_shared<StructuredData::Dictionary>();
351 return WrapOptionsDict(result_sp);
354 bool SearchFilterForUnconstrainedSearches::ModulePasses(
355 const FileSpec &module_spec) {
356 if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec))
362 bool SearchFilterForUnconstrainedSearches::ModulePasses(
363 const lldb::ModuleSP &module_sp) {
366 else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp))
372 lldb::SearchFilterSP SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint(
373 Breakpoint &breakpoint) {
374 return std::make_shared<SearchFilterForUnconstrainedSearches>(*this);
377 //----------------------------------------------------------------------
378 // SearchFilterByModule:
379 // Selects a shared library matching a given file spec
380 //----------------------------------------------------------------------
382 SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp,
383 const FileSpec &module)
384 : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {}
386 SearchFilterByModule::SearchFilterByModule(const SearchFilterByModule &rhs) =
389 SearchFilterByModule &SearchFilterByModule::
390 operator=(const SearchFilterByModule &rhs) {
391 m_target_sp = rhs.m_target_sp;
392 m_module_spec = rhs.m_module_spec;
396 SearchFilterByModule::~SearchFilterByModule() = default;
398 bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) {
400 FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false));
403 bool SearchFilterByModule::ModulePasses(const FileSpec &spec) {
404 // Do a full match only if "spec" has a directory
405 const bool full_match = (bool)spec.GetDirectory();
406 return FileSpec::Equal(spec, m_module_spec, full_match);
409 bool SearchFilterByModule::AddressPasses(Address &address) {
410 // FIXME: Not yet implemented
414 bool SearchFilterByModule::CompUnitPasses(FileSpec &fileSpec) { return true; }
416 bool SearchFilterByModule::CompUnitPasses(CompileUnit &compUnit) {
420 void SearchFilterByModule::Search(Searcher &searcher) {
424 if (searcher.GetDepth() == Searcher::eDepthTarget) {
425 SymbolContext empty_sc;
426 empty_sc.target_sp = m_target_sp;
427 searcher.SearchCallback(*this, empty_sc, nullptr, false);
430 // If the module file spec is a full path, then we can just find the one
431 // filespec that passes. Otherwise, we need to go through all modules and
432 // find the ones that match the file name.
434 const ModuleList &target_modules = m_target_sp->GetImages();
435 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
437 const size_t num_modules = target_modules.GetSize();
438 for (size_t i = 0; i < num_modules; i++) {
439 Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
440 const bool full_match = (bool)m_module_spec.GetDirectory();
441 if (FileSpec::Equal(m_module_spec, module->GetFileSpec(), full_match)) {
442 SymbolContext matchingContext(m_target_sp, module->shared_from_this());
443 Searcher::CallbackReturn shouldContinue;
445 shouldContinue = DoModuleIteration(matchingContext, searcher);
446 if (shouldContinue == Searcher::eCallbackReturnStop)
452 void SearchFilterByModule::GetDescription(Stream *s) {
453 s->PutCString(", module = ");
454 s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>"));
457 uint32_t SearchFilterByModule::GetFilterRequiredItems() {
458 return eSymbolContextModule;
461 void SearchFilterByModule::Dump(Stream *s) const {}
464 SearchFilterByModule::DoCopyForBreakpoint(Breakpoint &breakpoint) {
465 return std::make_shared<SearchFilterByModule>(*this);
468 SearchFilterSP SearchFilterByModule::CreateFromStructuredData(
469 Target &target, const StructuredData::Dictionary &data_dict,
471 StructuredData::Array *modules_array;
472 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
475 error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
479 size_t num_modules = modules_array->GetSize();
480 if (num_modules > 1) {
481 error.SetErrorString(
482 "SFBM::CFSD: Only one modules allowed for SearchFilterByModule.");
486 llvm::StringRef module;
487 success = modules_array->GetItemAtIndexAsString(0, module);
489 error.SetErrorString("SFBM::CFSD: filter module item not a string.");
492 FileSpec module_spec(module, false);
494 return std::make_shared<SearchFilterByModule>(target.shared_from_this(),
498 StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() {
499 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
500 auto module_array_sp = std::make_shared<StructuredData::Array>();
501 module_array_sp->AddItem(
502 std::make_shared<StructuredData::String>(m_module_spec.GetPath()));
503 options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp);
504 return WrapOptionsDict(options_dict_sp);
507 //----------------------------------------------------------------------
508 // SearchFilterByModuleList:
509 // Selects a shared library matching a given file spec
510 //----------------------------------------------------------------------
512 SearchFilterByModuleList::SearchFilterByModuleList(
513 const lldb::TargetSP &target_sp, const FileSpecList &module_list)
514 : SearchFilter(target_sp, FilterTy::ByModules),
515 m_module_spec_list(module_list) {}
517 SearchFilterByModuleList::SearchFilterByModuleList(
518 const lldb::TargetSP &target_sp, const FileSpecList &module_list,
519 enum FilterTy filter_ty)
520 : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {}
522 SearchFilterByModuleList::SearchFilterByModuleList(
523 const SearchFilterByModuleList &rhs) = default;
525 SearchFilterByModuleList &SearchFilterByModuleList::
526 operator=(const SearchFilterByModuleList &rhs) {
527 m_target_sp = rhs.m_target_sp;
528 m_module_spec_list = rhs.m_module_spec_list;
532 SearchFilterByModuleList::~SearchFilterByModuleList() = default;
534 bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) {
535 if (m_module_spec_list.GetSize() == 0)
539 m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) !=
546 bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) {
547 if (m_module_spec_list.GetSize() == 0)
550 if (m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX)
556 bool SearchFilterByModuleList::AddressPasses(Address &address) {
557 // FIXME: Not yet implemented
561 bool SearchFilterByModuleList::CompUnitPasses(FileSpec &fileSpec) {
565 bool SearchFilterByModuleList::CompUnitPasses(CompileUnit &compUnit) {
569 void SearchFilterByModuleList::Search(Searcher &searcher) {
573 if (searcher.GetDepth() == Searcher::eDepthTarget) {
574 SymbolContext empty_sc;
575 empty_sc.target_sp = m_target_sp;
576 searcher.SearchCallback(*this, empty_sc, nullptr, false);
579 // If the module file spec is a full path, then we can just find the one
580 // filespec that passes. Otherwise, we need to go through all modules and
581 // find the ones that match the file name.
583 const ModuleList &target_modules = m_target_sp->GetImages();
584 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
586 const size_t num_modules = target_modules.GetSize();
587 for (size_t i = 0; i < num_modules; i++) {
588 Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
589 if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) !=
591 SymbolContext matchingContext(m_target_sp, module->shared_from_this());
592 Searcher::CallbackReturn shouldContinue;
594 shouldContinue = DoModuleIteration(matchingContext, searcher);
595 if (shouldContinue == Searcher::eCallbackReturnStop)
601 void SearchFilterByModuleList::GetDescription(Stream *s) {
602 size_t num_modules = m_module_spec_list.GetSize();
603 if (num_modules == 1) {
604 s->Printf(", module = ");
606 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
609 s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules);
610 for (size_t i = 0; i < num_modules; i++) {
612 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
614 if (i != num_modules - 1)
620 uint32_t SearchFilterByModuleList::GetFilterRequiredItems() {
621 return eSymbolContextModule;
624 void SearchFilterByModuleList::Dump(Stream *s) const {}
627 SearchFilterByModuleList::DoCopyForBreakpoint(Breakpoint &breakpoint) {
628 return std::make_shared<SearchFilterByModuleList>(*this);
631 SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
632 Target &target, const StructuredData::Dictionary &data_dict,
634 StructuredData::Array *modules_array;
635 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
637 FileSpecList modules;
639 size_t num_modules = modules_array->GetSize();
640 for (size_t i = 0; i < num_modules; i++) {
641 llvm::StringRef module;
642 success = modules_array->GetItemAtIndexAsString(i, module);
644 error.SetErrorStringWithFormat(
645 "SFBM::CFSD: filter module item %zu not a string.", i);
648 modules.Append(FileSpec(module, false));
652 return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(),
656 void SearchFilterByModuleList::SerializeUnwrapped(
657 StructuredData::DictionarySP &options_dict_sp) {
658 SerializeFileSpecList(options_dict_sp, OptionNames::ModList,
662 StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() {
663 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
664 SerializeUnwrapped(options_dict_sp);
665 return WrapOptionsDict(options_dict_sp);
668 //----------------------------------------------------------------------
669 // SearchFilterByModuleListAndCU:
670 // Selects a shared library matching a given file spec
671 //----------------------------------------------------------------------
673 SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
674 const lldb::TargetSP &target_sp, const FileSpecList &module_list,
675 const FileSpecList &cu_list)
676 : SearchFilterByModuleList(target_sp, module_list,
677 FilterTy::ByModulesAndCU),
678 m_cu_spec_list(cu_list) {}
680 SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
681 const SearchFilterByModuleListAndCU &rhs) = default;
683 SearchFilterByModuleListAndCU &SearchFilterByModuleListAndCU::
684 operator=(const SearchFilterByModuleListAndCU &rhs) {
686 m_target_sp = rhs.m_target_sp;
687 m_module_spec_list = rhs.m_module_spec_list;
688 m_cu_spec_list = rhs.m_cu_spec_list;
693 SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default;
695 lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
696 Target &target, const StructuredData::Dictionary &data_dict,
698 StructuredData::Array *modules_array = nullptr;
699 SearchFilterSP result_sp;
700 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
702 FileSpecList modules;
704 size_t num_modules = modules_array->GetSize();
705 for (size_t i = 0; i < num_modules; i++) {
706 llvm::StringRef module;
707 success = modules_array->GetItemAtIndexAsString(i, module);
709 error.SetErrorStringWithFormat(
710 "SFBM::CFSD: filter module item %zu not a string.", i);
713 modules.Append(FileSpec(module, false));
717 StructuredData::Array *cus_array = nullptr;
719 data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array);
721 error.SetErrorString("SFBM::CFSD: Could not find the CU list key.");
725 size_t num_cus = cus_array->GetSize();
727 for (size_t i = 0; i < num_cus; i++) {
729 success = cus_array->GetItemAtIndexAsString(i, cu);
731 error.SetErrorStringWithFormat(
732 "SFBM::CFSD: filter cu item %zu not a string.", i);
735 cus.Append(FileSpec(cu, false));
738 return std::make_shared<SearchFilterByModuleListAndCU>(
739 target.shared_from_this(), modules, cus);
742 StructuredData::ObjectSP
743 SearchFilterByModuleListAndCU::SerializeToStructuredData() {
744 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
745 SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp);
746 SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list);
747 return WrapOptionsDict(options_dict_sp);
750 bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
754 bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
755 return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX;
758 bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) {
760 m_cu_spec_list.FindFileIndex(0, compUnit, false) != UINT32_MAX;
762 ModuleSP module_sp(compUnit.GetModule());
764 bool module_passes = SearchFilterByModuleList::ModulePasses(module_sp);
765 return module_passes;
772 void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
776 if (searcher.GetDepth() == Searcher::eDepthTarget) {
777 SymbolContext empty_sc;
778 empty_sc.target_sp = m_target_sp;
779 searcher.SearchCallback(*this, empty_sc, nullptr, false);
782 // If the module file spec is a full path, then we can just find the one
783 // filespec that passes. Otherwise, we need to go through all modules and
784 // find the ones that match the file name.
786 ModuleList matching_modules;
787 const ModuleList &target_images = m_target_sp->GetImages();
788 std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
790 const size_t num_modules = target_images.GetSize();
791 bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
792 for (size_t i = 0; i < num_modules; i++) {
793 lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i);
794 if (no_modules_in_filter ||
795 m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) !=
797 SymbolContext matchingContext(m_target_sp, module_sp);
798 Searcher::CallbackReturn shouldContinue;
800 if (searcher.GetDepth() == Searcher::eDepthModule) {
801 shouldContinue = DoModuleIteration(matchingContext, searcher);
802 if (shouldContinue == Searcher::eCallbackReturnStop)
805 const size_t num_cu = module_sp->GetNumCompileUnits();
806 for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) {
807 CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
808 matchingContext.comp_unit = cu_sp.get();
809 if (matchingContext.comp_unit) {
810 if (m_cu_spec_list.FindFileIndex(0, *matchingContext.comp_unit,
811 false) != UINT32_MAX) {
813 DoCUIteration(module_sp, matchingContext, searcher);
814 if (shouldContinue == Searcher::eCallbackReturnStop)
824 void SearchFilterByModuleListAndCU::GetDescription(Stream *s) {
825 size_t num_modules = m_module_spec_list.GetSize();
826 if (num_modules == 1) {
827 s->Printf(", module = ");
829 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
831 } else if (num_modules > 0) {
832 s->Printf(", modules(%" PRIu64 ") = ", static_cast<uint64_t>(num_modules));
833 for (size_t i = 0; i < num_modules; i++) {
835 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
837 if (i != num_modules - 1)
843 uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() {
844 return eSymbolContextModule | eSymbolContextCompUnit;
847 void SearchFilterByModuleListAndCU::Dump(Stream *s) const {}
850 SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) {
851 return std::make_shared<SearchFilterByModuleListAndCU>(*this);