1 //===-- SearchFilter.cpp ----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Core/SearchFilter.h"
11 #include "lldb/Breakpoint/Breakpoint.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/ModuleList.h"
14 #include "lldb/Symbol/CompileUnit.h"
15 #include "lldb/Symbol/SymbolContext.h"
16 #include "lldb/Symbol/SymbolFile.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Utility/ConstString.h"
19 #include "lldb/Utility/Status.h"
20 #include "lldb/Utility/Stream.h"
21 #include "lldb/lldb-enumerations.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/Support/ErrorHandling.h"
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() = default;
77 SearchFilterSP SearchFilter::CreateFromStructuredData(
78 Target &target, const StructuredData::Dictionary &filter_dict,
80 SearchFilterSP result_sp;
81 if (!filter_dict.IsValid()) {
82 error.SetErrorString("Can't deserialize from an invalid data object.");
86 llvm::StringRef subclass_name;
88 bool success = filter_dict.GetValueForKeyAsString(
89 GetSerializationSubclassKey(), subclass_name);
91 error.SetErrorStringWithFormat("Filter data missing subclass key");
95 FilterTy filter_type = NameToFilterTy(subclass_name);
96 if (filter_type == UnknownFilter) {
97 error.SetErrorStringWithFormatv("Unknown filter type: {0}.", subclass_name);
101 StructuredData::Dictionary *subclass_options = nullptr;
102 success = filter_dict.GetValueForKeyAsDictionary(
103 GetSerializationSubclassOptionsKey(), subclass_options);
104 if (!success || !subclass_options || !subclass_options->IsValid()) {
105 error.SetErrorString("Filter data missing subclass options key.");
109 switch (filter_type) {
111 result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
112 target, *subclass_options, error);
115 result_sp = SearchFilterByModule::CreateFromStructuredData(
116 target, *subclass_options, error);
119 result_sp = SearchFilterByModuleList::CreateFromStructuredData(
120 target, *subclass_options, error);
123 result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData(
124 target, *subclass_options, error);
127 error.SetErrorString("Can't serialize exception breakpoints yet.");
130 llvm_unreachable("Should never get an uresolvable filter type.");
136 bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; }
138 bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; }
140 bool SearchFilter::AddressPasses(Address &address) { return true; }
142 bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; }
144 bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; }
146 bool SearchFilter::FunctionPasses(Function &function) {
147 // This is a slightly cheesy job, but since we don't have finer grained
148 // filters yet, just checking that the start address passes is probably
149 // good enough for the base class behavior.
150 Address addr = function.GetAddressRange().GetBaseAddress();
151 return AddressPasses(addr);
155 uint32_t SearchFilter::GetFilterRequiredItems() {
156 return (lldb::SymbolContextItem)0;
159 void SearchFilter::GetDescription(Stream *s) {}
161 void SearchFilter::Dump(Stream *s) const {}
163 lldb::SearchFilterSP SearchFilter::CopyForBreakpoint(Breakpoint &breakpoint) {
164 SearchFilterSP ret_sp = DoCopyForBreakpoint(breakpoint);
165 TargetSP target_sp = breakpoint.GetTargetSP();
166 ret_sp->SetTarget(target_sp);
170 // Helper functions for serialization.
172 StructuredData::DictionarySP
173 SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) {
174 if (!options_dict_sp || !options_dict_sp->IsValid())
175 return StructuredData::DictionarySP();
177 auto type_dict_sp = std::make_shared<StructuredData::Dictionary>();
178 type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetFilterName());
179 type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp);
184 void SearchFilter::SerializeFileSpecList(
185 StructuredData::DictionarySP &options_dict_sp, OptionNames name,
186 FileSpecList &file_list) {
187 size_t num_modules = file_list.GetSize();
189 // Don't serialize empty lists.
190 if (num_modules == 0)
193 auto module_array_sp = std::make_shared<StructuredData::Array>();
194 for (size_t i = 0; i < num_modules; i++) {
195 module_array_sp->AddItem(std::make_shared<StructuredData::String>(
196 file_list.GetFileSpecAtIndex(i).GetPath()));
198 options_dict_sp->AddItem(GetKey(name), module_array_sp);
201 // UTILITY Functions to help iterate down through the elements of the
204 void SearchFilter::Search(Searcher &searcher) {
205 SymbolContext empty_sc;
209 empty_sc.target_sp = m_target_sp;
211 if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
212 searcher.SearchCallback(*this, empty_sc, nullptr);
216 DoModuleIteration(empty_sc, searcher);
219 void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
220 SymbolContext empty_sc;
224 empty_sc.target_sp = m_target_sp;
226 if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
227 searcher.SearchCallback(*this, empty_sc, nullptr);
231 std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
232 const size_t numModules = modules.GetSize();
234 for (size_t i = 0; i < numModules; i++) {
235 ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i));
236 if (!ModulePasses(module_sp))
238 if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop)
243 Searcher::CallbackReturn
244 SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp,
245 Searcher &searcher) {
246 SymbolContext matchingContext(m_target_sp, module_sp);
247 return DoModuleIteration(matchingContext, searcher);
250 Searcher::CallbackReturn
251 SearchFilter::DoModuleIteration(const SymbolContext &context,
252 Searcher &searcher) {
253 if (searcher.GetDepth() < lldb::eSearchDepthModule)
254 return Searcher::eCallbackReturnContinue;
256 if (context.module_sp) {
257 if (searcher.GetDepth() != lldb::eSearchDepthModule)
258 return DoCUIteration(context.module_sp, context, searcher);
260 SymbolContext matchingContext(context.module_sp.get());
261 searcher.SearchCallback(*this, matchingContext, nullptr);
262 return Searcher::eCallbackReturnContinue;
265 const ModuleList &target_images = m_target_sp->GetImages();
266 std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
268 size_t n_modules = target_images.GetSize();
269 for (size_t i = 0; i < n_modules; i++) {
270 // If this is the last level supplied, then call the callback directly,
271 // otherwise descend.
272 ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i));
273 if (!ModulePasses(module_sp))
276 if (searcher.GetDepth() == lldb::eSearchDepthModule) {
277 SymbolContext matchingContext(m_target_sp, module_sp);
279 Searcher::CallbackReturn shouldContinue =
280 searcher.SearchCallback(*this, matchingContext, nullptr);
281 if (shouldContinue == Searcher::eCallbackReturnStop ||
282 shouldContinue == Searcher::eCallbackReturnPop)
283 return shouldContinue;
285 Searcher::CallbackReturn shouldContinue =
286 DoCUIteration(module_sp, context, searcher);
287 if (shouldContinue == Searcher::eCallbackReturnStop)
288 return shouldContinue;
289 else if (shouldContinue == Searcher::eCallbackReturnPop)
294 return Searcher::eCallbackReturnContinue;
297 Searcher::CallbackReturn
298 SearchFilter::DoCUIteration(const ModuleSP &module_sp,
299 const SymbolContext &context, Searcher &searcher) {
300 Searcher::CallbackReturn shouldContinue;
301 if (context.comp_unit != nullptr) {
302 if (CompUnitPasses(*context.comp_unit)) {
303 SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit);
304 return searcher.SearchCallback(*this, matchingContext, nullptr);
306 return Searcher::eCallbackReturnContinue;
309 const size_t num_comp_units = module_sp->GetNumCompileUnits();
310 for (size_t i = 0; i < num_comp_units; i++) {
311 CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i));
314 if (!CompUnitPasses(*(cu_sp.get())))
317 if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) {
318 SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
320 shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr);
322 if (shouldContinue == Searcher::eCallbackReturnPop)
323 return Searcher::eCallbackReturnContinue;
324 else if (shouldContinue == Searcher::eCallbackReturnStop)
325 return shouldContinue;
329 // First make sure this compile unit's functions are parsed
330 // since CompUnit::ForeachFunction only iterates over already
332 SymbolFile *sym_file = module_sp->GetSymbolFile();
335 if (!sym_file->ParseFunctions(*cu_sp))
337 // If we got any functions, use ForeachFunction to do the iteration.
338 cu_sp->ForeachFunction([&](const FunctionSP &func_sp) {
339 if (!FunctionPasses(*func_sp.get()))
340 return false; // Didn't pass the filter, just keep going.
341 if (searcher.GetDepth() == lldb::eSearchDepthFunction) {
342 SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get(),
345 searcher.SearchCallback(*this, matchingContext, nullptr);
347 shouldContinue = DoFunctionIteration(func_sp.get(), context, searcher);
349 return shouldContinue != Searcher::eCallbackReturnContinue;
352 return Searcher::eCallbackReturnContinue;
355 Searcher::CallbackReturn SearchFilter::DoFunctionIteration(
356 Function *function, const SymbolContext &context, Searcher &searcher) {
357 // FIXME: Implement...
358 return Searcher::eCallbackReturnContinue;
361 // SearchFilterForUnconstrainedSearches:
362 // Selects a shared library matching a given file spec, consulting the targets
364 SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
365 Target &target, const StructuredData::Dictionary &data_dict,
367 // No options for an unconstrained search.
368 return std::make_shared<SearchFilterForUnconstrainedSearches>(
369 target.shared_from_this());
372 StructuredData::ObjectSP
373 SearchFilterForUnconstrainedSearches::SerializeToStructuredData() {
374 // The options dictionary is an empty dictionary:
375 auto result_sp = std::make_shared<StructuredData::Dictionary>();
376 return WrapOptionsDict(result_sp);
379 bool SearchFilterForUnconstrainedSearches::ModulePasses(
380 const FileSpec &module_spec) {
381 return !m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec);
384 bool SearchFilterForUnconstrainedSearches::ModulePasses(
385 const lldb::ModuleSP &module_sp) {
388 else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp))
393 lldb::SearchFilterSP SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint(
394 Breakpoint &breakpoint) {
395 return std::make_shared<SearchFilterForUnconstrainedSearches>(*this);
398 // SearchFilterByModule:
399 // Selects a shared library matching a given file spec
401 SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp,
402 const FileSpec &module)
403 : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {}
405 SearchFilterByModule::~SearchFilterByModule() = default;
407 bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) {
409 FileSpec::Match(m_module_spec, module_sp->GetFileSpec()));
412 bool SearchFilterByModule::ModulePasses(const FileSpec &spec) {
413 return FileSpec::Match(m_module_spec, spec);
416 bool SearchFilterByModule::AddressPasses(Address &address) {
417 // FIXME: Not yet implemented
421 bool SearchFilterByModule::CompUnitPasses(FileSpec &fileSpec) { return true; }
423 bool SearchFilterByModule::CompUnitPasses(CompileUnit &compUnit) {
427 void SearchFilterByModule::Search(Searcher &searcher) {
431 if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
432 SymbolContext empty_sc;
433 empty_sc.target_sp = m_target_sp;
434 searcher.SearchCallback(*this, empty_sc, nullptr);
437 // If the module file spec is a full path, then we can just find the one
438 // filespec that passes. Otherwise, we need to go through all modules and
439 // find the ones that match the file name.
441 const ModuleList &target_modules = m_target_sp->GetImages();
442 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
444 const size_t num_modules = target_modules.GetSize();
445 for (size_t i = 0; i < num_modules; i++) {
446 Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
447 if (FileSpec::Match(m_module_spec, module->GetFileSpec())) {
448 SymbolContext matchingContext(m_target_sp, module->shared_from_this());
449 Searcher::CallbackReturn shouldContinue;
451 shouldContinue = DoModuleIteration(matchingContext, searcher);
452 if (shouldContinue == Searcher::eCallbackReturnStop)
458 void SearchFilterByModule::GetDescription(Stream *s) {
459 s->PutCString(", module = ");
460 s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>"));
463 uint32_t SearchFilterByModule::GetFilterRequiredItems() {
464 return eSymbolContextModule;
467 void SearchFilterByModule::Dump(Stream *s) const {}
470 SearchFilterByModule::DoCopyForBreakpoint(Breakpoint &breakpoint) {
471 return std::make_shared<SearchFilterByModule>(*this);
474 SearchFilterSP SearchFilterByModule::CreateFromStructuredData(
475 Target &target, const StructuredData::Dictionary &data_dict,
477 StructuredData::Array *modules_array;
478 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
481 error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
485 size_t num_modules = modules_array->GetSize();
486 if (num_modules > 1) {
487 error.SetErrorString(
488 "SFBM::CFSD: Only one modules allowed for SearchFilterByModule.");
492 llvm::StringRef module;
493 success = modules_array->GetItemAtIndexAsString(0, module);
495 error.SetErrorString("SFBM::CFSD: filter module item not a string.");
498 FileSpec module_spec(module);
500 return std::make_shared<SearchFilterByModule>(target.shared_from_this(),
504 StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() {
505 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
506 auto module_array_sp = std::make_shared<StructuredData::Array>();
507 module_array_sp->AddItem(
508 std::make_shared<StructuredData::String>(m_module_spec.GetPath()));
509 options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp);
510 return WrapOptionsDict(options_dict_sp);
513 // SearchFilterByModuleList:
514 // Selects a shared library matching a given file spec
516 SearchFilterByModuleList::SearchFilterByModuleList(
517 const lldb::TargetSP &target_sp, const FileSpecList &module_list)
518 : SearchFilter(target_sp, FilterTy::ByModules),
519 m_module_spec_list(module_list) {}
521 SearchFilterByModuleList::SearchFilterByModuleList(
522 const lldb::TargetSP &target_sp, const FileSpecList &module_list,
523 enum FilterTy filter_ty)
524 : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {}
526 SearchFilterByModuleList::~SearchFilterByModuleList() = default;
528 bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) {
529 if (m_module_spec_list.GetSize() == 0)
532 return module_sp && m_module_spec_list.FindFileIndex(
533 0, module_sp->GetFileSpec(), false) != UINT32_MAX;
536 bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) {
537 if (m_module_spec_list.GetSize() == 0)
540 return m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX;
543 bool SearchFilterByModuleList::AddressPasses(Address &address) {
544 // FIXME: Not yet implemented
548 bool SearchFilterByModuleList::CompUnitPasses(FileSpec &fileSpec) {
552 bool SearchFilterByModuleList::CompUnitPasses(CompileUnit &compUnit) {
556 void SearchFilterByModuleList::Search(Searcher &searcher) {
560 if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
561 SymbolContext empty_sc;
562 empty_sc.target_sp = m_target_sp;
563 searcher.SearchCallback(*this, empty_sc, nullptr);
566 // If the module file spec is a full path, then we can just find the one
567 // filespec that passes. Otherwise, we need to go through all modules and
568 // find the ones that match the file name.
570 const ModuleList &target_modules = m_target_sp->GetImages();
571 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
573 const size_t num_modules = target_modules.GetSize();
574 for (size_t i = 0; i < num_modules; i++) {
575 Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
576 if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) ==
579 SymbolContext matchingContext(m_target_sp, module->shared_from_this());
580 Searcher::CallbackReturn shouldContinue;
582 shouldContinue = DoModuleIteration(matchingContext, searcher);
583 if (shouldContinue == Searcher::eCallbackReturnStop)
588 void SearchFilterByModuleList::GetDescription(Stream *s) {
589 size_t num_modules = m_module_spec_list.GetSize();
590 if (num_modules == 1) {
591 s->Printf(", module = ");
593 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
598 s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules);
599 for (size_t i = 0; i < num_modules; i++) {
601 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
603 if (i != num_modules - 1)
608 uint32_t SearchFilterByModuleList::GetFilterRequiredItems() {
609 return eSymbolContextModule;
612 void SearchFilterByModuleList::Dump(Stream *s) const {}
615 SearchFilterByModuleList::DoCopyForBreakpoint(Breakpoint &breakpoint) {
616 return std::make_shared<SearchFilterByModuleList>(*this);
619 SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
620 Target &target, const StructuredData::Dictionary &data_dict,
622 StructuredData::Array *modules_array;
623 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
627 return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(),
629 FileSpecList modules;
630 size_t num_modules = modules_array->GetSize();
631 for (size_t i = 0; i < num_modules; i++) {
632 llvm::StringRef module;
633 success = modules_array->GetItemAtIndexAsString(i, module);
635 error.SetErrorStringWithFormat(
636 "SFBM::CFSD: filter module item %zu not a string.", i);
639 modules.EmplaceBack(module);
641 return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(),
645 void SearchFilterByModuleList::SerializeUnwrapped(
646 StructuredData::DictionarySP &options_dict_sp) {
647 SerializeFileSpecList(options_dict_sp, OptionNames::ModList,
651 StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() {
652 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
653 SerializeUnwrapped(options_dict_sp);
654 return WrapOptionsDict(options_dict_sp);
657 // SearchFilterByModuleListAndCU:
658 // Selects a shared library matching a given file spec
660 SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
661 const lldb::TargetSP &target_sp, const FileSpecList &module_list,
662 const FileSpecList &cu_list)
663 : SearchFilterByModuleList(target_sp, module_list,
664 FilterTy::ByModulesAndCU),
665 m_cu_spec_list(cu_list) {}
667 SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default;
669 lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
670 Target &target, const StructuredData::Dictionary &data_dict,
672 StructuredData::Array *modules_array = nullptr;
673 SearchFilterSP result_sp;
674 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
676 FileSpecList modules;
678 size_t num_modules = modules_array->GetSize();
679 for (size_t i = 0; i < num_modules; i++) {
680 llvm::StringRef module;
681 success = modules_array->GetItemAtIndexAsString(i, module);
683 error.SetErrorStringWithFormat(
684 "SFBM::CFSD: filter module item %zu not a string.", i);
687 modules.EmplaceBack(module);
691 StructuredData::Array *cus_array = nullptr;
693 data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array);
695 error.SetErrorString("SFBM::CFSD: Could not find the CU list key.");
699 size_t num_cus = cus_array->GetSize();
701 for (size_t i = 0; i < num_cus; i++) {
703 success = cus_array->GetItemAtIndexAsString(i, cu);
705 error.SetErrorStringWithFormat(
706 "SFBM::CFSD: filter CU item %zu not a string.", i);
712 return std::make_shared<SearchFilterByModuleListAndCU>(
713 target.shared_from_this(), modules, cus);
716 StructuredData::ObjectSP
717 SearchFilterByModuleListAndCU::SerializeToStructuredData() {
718 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
719 SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp);
720 SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list);
721 return WrapOptionsDict(options_dict_sp);
724 bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
725 SymbolContext sym_ctx;
726 address.CalculateSymbolContext(&sym_ctx, eSymbolContextEverything);
727 if (!sym_ctx.comp_unit) {
728 if (m_cu_spec_list.GetSize() != 0)
729 return false; // Has no comp_unit so can't pass the file check.
732 if (sym_ctx.comp_unit)
733 cu_spec = sym_ctx.comp_unit->GetPrimaryFile();
734 if (m_cu_spec_list.FindFileIndex(0, cu_spec, false) == UINT32_MAX)
735 return false; // Fails the file check
736 return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp);
739 bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
740 return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX;
743 bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) {
744 bool in_cu_list = m_cu_spec_list.FindFileIndex(0, compUnit.GetPrimaryFile(),
745 false) != UINT32_MAX;
749 ModuleSP module_sp(compUnit.GetModule());
753 return SearchFilterByModuleList::ModulePasses(module_sp);
756 void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
760 if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
761 SymbolContext empty_sc;
762 empty_sc.target_sp = m_target_sp;
763 searcher.SearchCallback(*this, empty_sc, nullptr);
766 // If the module file spec is a full path, then we can just find the one
767 // filespec that passes. Otherwise, we need to go through all modules and
768 // find the ones that match the file name.
770 ModuleList matching_modules;
771 const ModuleList &target_images = m_target_sp->GetImages();
772 std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
774 const size_t num_modules = target_images.GetSize();
775 bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
776 for (size_t i = 0; i < num_modules; i++) {
777 lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i);
778 if (!no_modules_in_filter &&
779 m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) ==
783 SymbolContext matchingContext(m_target_sp, module_sp);
784 Searcher::CallbackReturn shouldContinue;
786 if (searcher.GetDepth() == lldb::eSearchDepthModule) {
787 shouldContinue = DoModuleIteration(matchingContext, searcher);
788 if (shouldContinue == Searcher::eCallbackReturnStop)
793 const size_t num_cu = module_sp->GetNumCompileUnits();
794 for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) {
795 CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
796 matchingContext.comp_unit = cu_sp.get();
797 if (!matchingContext.comp_unit)
799 if (m_cu_spec_list.FindFileIndex(
800 0, matchingContext.comp_unit->GetPrimaryFile(), false) ==
803 shouldContinue = DoCUIteration(module_sp, matchingContext, searcher);
804 if (shouldContinue == Searcher::eCallbackReturnStop)
810 void SearchFilterByModuleListAndCU::GetDescription(Stream *s) {
811 size_t num_modules = m_module_spec_list.GetSize();
812 if (num_modules == 1) {
813 s->Printf(", module = ");
815 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
817 } else if (num_modules > 0) {
818 s->Printf(", modules(%" PRIu64 ") = ", static_cast<uint64_t>(num_modules));
819 for (size_t i = 0; i < num_modules; i++) {
821 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
823 if (i != num_modules - 1)
829 uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() {
830 return eSymbolContextModule | eSymbolContextCompUnit;
833 void SearchFilterByModuleListAndCU::Dump(Stream *s) const {}
836 SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) {
837 return std::make_shared<SearchFilterByModuleListAndCU>(*this);