15ffd83dbSDimitry Andric //===-- SearchFilter.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/SearchFilter.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h"
120b57cec5SDimitry Andric #include "lldb/Core/Module.h"
130b57cec5SDimitry Andric #include "lldb/Core/ModuleList.h"
140b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
150b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
169dba64beSDimitry Andric #include "lldb/Symbol/SymbolFile.h"
170b57cec5SDimitry Andric #include "lldb/Target/Target.h"
180b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
200b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
210b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #include <memory>
270b57cec5SDimitry Andric #include <mutex>
280b57cec5SDimitry Andric #include <string>
290b57cec5SDimitry Andric 
30fe6060f1SDimitry Andric #include <cinttypes>
31fe6060f1SDimitry Andric #include <cstring>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric namespace lldb_private {
340b57cec5SDimitry Andric class Address;
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric namespace lldb_private {
370b57cec5SDimitry Andric class Function;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric using namespace lldb;
410b57cec5SDimitry Andric using namespace lldb_private;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception",
440b57cec5SDimitry Andric                                             "Module",        "Modules",
450b57cec5SDimitry Andric                                             "ModulesAndCU",  "Unknown"};
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric const char
480b57cec5SDimitry Andric     *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = {
490b57cec5SDimitry Andric         "ModuleList", "CUList"};
500b57cec5SDimitry Andric 
FilterTyToName(enum FilterTy type)510b57cec5SDimitry Andric const char *SearchFilter::FilterTyToName(enum FilterTy type) {
520b57cec5SDimitry Andric   if (type > LastKnownFilterType)
530b57cec5SDimitry Andric     return g_ty_to_name[UnknownFilter];
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   return g_ty_to_name[type];
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
NameToFilterTy(llvm::StringRef name)580b57cec5SDimitry Andric SearchFilter::FilterTy SearchFilter::NameToFilterTy(llvm::StringRef name) {
590b57cec5SDimitry Andric   for (size_t i = 0; i <= LastKnownFilterType; i++) {
600b57cec5SDimitry Andric     if (name == g_ty_to_name[i])
610b57cec5SDimitry Andric       return (FilterTy)i;
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric   return UnknownFilter;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric Searcher::Searcher() = default;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric Searcher::~Searcher() = default;
690b57cec5SDimitry Andric 
GetDescription(Stream * s)700b57cec5SDimitry Andric void Searcher::GetDescription(Stream *s) {}
710b57cec5SDimitry Andric 
SearchFilter(const TargetSP & target_sp,unsigned char filterType)720b57cec5SDimitry Andric SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType)
730b57cec5SDimitry Andric     : m_target_sp(target_sp), SubclassID(filterType) {}
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric SearchFilter::~SearchFilter() = default;
760b57cec5SDimitry Andric 
CreateFromStructuredData(const lldb::TargetSP & target_sp,const StructuredData::Dictionary & filter_dict,Status & error)770b57cec5SDimitry Andric SearchFilterSP SearchFilter::CreateFromStructuredData(
785ffd83dbSDimitry Andric     const lldb::TargetSP& target_sp,
795ffd83dbSDimitry Andric     const StructuredData::Dictionary &filter_dict,
800b57cec5SDimitry Andric     Status &error) {
810b57cec5SDimitry Andric   SearchFilterSP result_sp;
820b57cec5SDimitry Andric   if (!filter_dict.IsValid()) {
830b57cec5SDimitry Andric     error.SetErrorString("Can't deserialize from an invalid data object.");
840b57cec5SDimitry Andric     return result_sp;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   llvm::StringRef subclass_name;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   bool success = filter_dict.GetValueForKeyAsString(
900b57cec5SDimitry Andric       GetSerializationSubclassKey(), subclass_name);
910b57cec5SDimitry Andric   if (!success) {
92e8d8bef9SDimitry Andric     error.SetErrorString("Filter data missing subclass key");
930b57cec5SDimitry Andric     return result_sp;
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   FilterTy filter_type = NameToFilterTy(subclass_name);
970b57cec5SDimitry Andric   if (filter_type == UnknownFilter) {
980b57cec5SDimitry Andric     error.SetErrorStringWithFormatv("Unknown filter type: {0}.", subclass_name);
990b57cec5SDimitry Andric     return result_sp;
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   StructuredData::Dictionary *subclass_options = nullptr;
1030b57cec5SDimitry Andric   success = filter_dict.GetValueForKeyAsDictionary(
1040b57cec5SDimitry Andric       GetSerializationSubclassOptionsKey(), subclass_options);
1050b57cec5SDimitry Andric   if (!success || !subclass_options || !subclass_options->IsValid()) {
1060b57cec5SDimitry Andric     error.SetErrorString("Filter data missing subclass options key.");
1070b57cec5SDimitry Andric     return result_sp;
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   switch (filter_type) {
1110b57cec5SDimitry Andric   case Unconstrained:
1120b57cec5SDimitry Andric     result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
1135ffd83dbSDimitry Andric         target_sp, *subclass_options, error);
1140b57cec5SDimitry Andric     break;
1150b57cec5SDimitry Andric   case ByModule:
1160b57cec5SDimitry Andric     result_sp = SearchFilterByModule::CreateFromStructuredData(
1175ffd83dbSDimitry Andric         target_sp, *subclass_options, error);
1180b57cec5SDimitry Andric     break;
1190b57cec5SDimitry Andric   case ByModules:
1200b57cec5SDimitry Andric     result_sp = SearchFilterByModuleList::CreateFromStructuredData(
1215ffd83dbSDimitry Andric         target_sp, *subclass_options, error);
1220b57cec5SDimitry Andric     break;
1230b57cec5SDimitry Andric   case ByModulesAndCU:
1240b57cec5SDimitry Andric     result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData(
1255ffd83dbSDimitry Andric         target_sp, *subclass_options, error);
1260b57cec5SDimitry Andric     break;
1270b57cec5SDimitry Andric   case Exception:
1280b57cec5SDimitry Andric     error.SetErrorString("Can't serialize exception breakpoints yet.");
1290b57cec5SDimitry Andric     break;
1300b57cec5SDimitry Andric   default:
1310b57cec5SDimitry Andric     llvm_unreachable("Should never get an uresolvable filter type.");
1320b57cec5SDimitry Andric   }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   return result_sp;
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric 
ModulePasses(const FileSpec & spec)1370b57cec5SDimitry Andric bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; }
1380b57cec5SDimitry Andric 
ModulePasses(const ModuleSP & module_sp)1390b57cec5SDimitry Andric bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; }
1400b57cec5SDimitry Andric 
AddressPasses(Address & address)1410b57cec5SDimitry Andric bool SearchFilter::AddressPasses(Address &address) { return true; }
1420b57cec5SDimitry Andric 
CompUnitPasses(FileSpec & fileSpec)1430b57cec5SDimitry Andric bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; }
1440b57cec5SDimitry Andric 
CompUnitPasses(CompileUnit & compUnit)1450b57cec5SDimitry Andric bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; }
1460b57cec5SDimitry Andric 
FunctionPasses(Function & function)1470b57cec5SDimitry Andric bool SearchFilter::FunctionPasses(Function &function) {
1480b57cec5SDimitry Andric   // This is a slightly cheesy job, but since we don't have finer grained
1490b57cec5SDimitry Andric   // filters yet, just checking that the start address passes is probably
1500b57cec5SDimitry Andric   // good enough for the base class behavior.
1510b57cec5SDimitry Andric   Address addr = function.GetAddressRange().GetBaseAddress();
1520b57cec5SDimitry Andric   return AddressPasses(addr);
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric 
GetFilterRequiredItems()1560b57cec5SDimitry Andric uint32_t SearchFilter::GetFilterRequiredItems() {
1570b57cec5SDimitry Andric   return (lldb::SymbolContextItem)0;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
GetDescription(Stream * s)1600b57cec5SDimitry Andric void SearchFilter::GetDescription(Stream *s) {}
1610b57cec5SDimitry Andric 
Dump(Stream * s) const1620b57cec5SDimitry Andric void SearchFilter::Dump(Stream *s) const {}
1630b57cec5SDimitry Andric 
CreateCopy(lldb::TargetSP & target_sp)1645ffd83dbSDimitry Andric lldb::SearchFilterSP SearchFilter::CreateCopy(lldb::TargetSP& target_sp) {
1655ffd83dbSDimitry Andric   SearchFilterSP ret_sp = DoCreateCopy();
1660b57cec5SDimitry Andric   ret_sp->SetTarget(target_sp);
1670b57cec5SDimitry Andric   return ret_sp;
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric // Helper functions for serialization.
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric StructuredData::DictionarySP
WrapOptionsDict(StructuredData::DictionarySP options_dict_sp)1730b57cec5SDimitry Andric SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) {
1740b57cec5SDimitry Andric   if (!options_dict_sp || !options_dict_sp->IsValid())
1750b57cec5SDimitry Andric     return StructuredData::DictionarySP();
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   auto type_dict_sp = std::make_shared<StructuredData::Dictionary>();
1780b57cec5SDimitry Andric   type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetFilterName());
1790b57cec5SDimitry Andric   type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp);
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   return type_dict_sp;
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
SerializeFileSpecList(StructuredData::DictionarySP & options_dict_sp,OptionNames name,FileSpecList & file_list)1840b57cec5SDimitry Andric void SearchFilter::SerializeFileSpecList(
1850b57cec5SDimitry Andric     StructuredData::DictionarySP &options_dict_sp, OptionNames name,
1860b57cec5SDimitry Andric     FileSpecList &file_list) {
1870b57cec5SDimitry Andric   size_t num_modules = file_list.GetSize();
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   // Don't serialize empty lists.
1900b57cec5SDimitry Andric   if (num_modules == 0)
1910b57cec5SDimitry Andric     return;
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   auto module_array_sp = std::make_shared<StructuredData::Array>();
1940b57cec5SDimitry Andric   for (size_t i = 0; i < num_modules; i++) {
1950b57cec5SDimitry Andric     module_array_sp->AddItem(std::make_shared<StructuredData::String>(
1960b57cec5SDimitry Andric         file_list.GetFileSpecAtIndex(i).GetPath()));
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric   options_dict_sp->AddItem(GetKey(name), module_array_sp);
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric // UTILITY Functions to help iterate down through the elements of the
2020b57cec5SDimitry Andric // SymbolContext.
2030b57cec5SDimitry Andric 
Search(Searcher & searcher)2040b57cec5SDimitry Andric void SearchFilter::Search(Searcher &searcher) {
2050b57cec5SDimitry Andric   SymbolContext empty_sc;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   if (!m_target_sp)
2080b57cec5SDimitry Andric     return;
2090b57cec5SDimitry Andric   empty_sc.target_sp = m_target_sp;
2100b57cec5SDimitry Andric 
211480093f4SDimitry Andric   if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
2129dba64beSDimitry Andric     searcher.SearchCallback(*this, empty_sc, nullptr);
213480093f4SDimitry Andric     return;
214480093f4SDimitry Andric   }
215480093f4SDimitry Andric 
2160b57cec5SDimitry Andric   DoModuleIteration(empty_sc, searcher);
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
SearchInModuleList(Searcher & searcher,ModuleList & modules)2190b57cec5SDimitry Andric void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
2200b57cec5SDimitry Andric   SymbolContext empty_sc;
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   if (!m_target_sp)
2230b57cec5SDimitry Andric     return;
2240b57cec5SDimitry Andric   empty_sc.target_sp = m_target_sp;
2250b57cec5SDimitry Andric 
226480093f4SDimitry Andric   if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
2279dba64beSDimitry Andric     searcher.SearchCallback(*this, empty_sc, nullptr);
228480093f4SDimitry Andric     return;
229480093f4SDimitry Andric   }
230480093f4SDimitry Andric 
231e8d8bef9SDimitry Andric   for (ModuleSP module_sp : modules.Modules()) {
232480093f4SDimitry Andric     if (!ModulePasses(module_sp))
233480093f4SDimitry Andric       continue;
234480093f4SDimitry Andric     if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop)
2350b57cec5SDimitry Andric       return;
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric Searcher::CallbackReturn
DoModuleIteration(const lldb::ModuleSP & module_sp,Searcher & searcher)2400b57cec5SDimitry Andric SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp,
2410b57cec5SDimitry Andric                                 Searcher &searcher) {
2420b57cec5SDimitry Andric   SymbolContext matchingContext(m_target_sp, module_sp);
2430b57cec5SDimitry Andric   return DoModuleIteration(matchingContext, searcher);
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric Searcher::CallbackReturn
DoModuleIteration(const SymbolContext & context,Searcher & searcher)2470b57cec5SDimitry Andric SearchFilter::DoModuleIteration(const SymbolContext &context,
2480b57cec5SDimitry Andric                                 Searcher &searcher) {
249480093f4SDimitry Andric   if (searcher.GetDepth() < lldb::eSearchDepthModule)
250480093f4SDimitry Andric     return Searcher::eCallbackReturnContinue;
251480093f4SDimitry Andric 
2520b57cec5SDimitry Andric   if (context.module_sp) {
253480093f4SDimitry Andric     if (searcher.GetDepth() != lldb::eSearchDepthModule)
254480093f4SDimitry Andric       return DoCUIteration(context.module_sp, context, searcher);
255480093f4SDimitry Andric 
2560b57cec5SDimitry Andric     SymbolContext matchingContext(context.module_sp.get());
2579dba64beSDimitry Andric     searcher.SearchCallback(*this, matchingContext, nullptr);
258480093f4SDimitry Andric     return Searcher::eCallbackReturnContinue;
2590b57cec5SDimitry Andric   }
260480093f4SDimitry Andric 
261e8d8bef9SDimitry Andric   for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
2620b57cec5SDimitry Andric     // If this is the last level supplied, then call the callback directly,
2630b57cec5SDimitry Andric     // otherwise descend.
2640b57cec5SDimitry Andric     if (!ModulePasses(module_sp))
2650b57cec5SDimitry Andric       continue;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric     if (searcher.GetDepth() == lldb::eSearchDepthModule) {
2680b57cec5SDimitry Andric       SymbolContext matchingContext(m_target_sp, module_sp);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric       Searcher::CallbackReturn shouldContinue =
2719dba64beSDimitry Andric           searcher.SearchCallback(*this, matchingContext, nullptr);
2720b57cec5SDimitry Andric       if (shouldContinue == Searcher::eCallbackReturnStop ||
2730b57cec5SDimitry Andric           shouldContinue == Searcher::eCallbackReturnPop)
2740b57cec5SDimitry Andric         return shouldContinue;
2750b57cec5SDimitry Andric     } else {
2760b57cec5SDimitry Andric       Searcher::CallbackReturn shouldContinue =
2770b57cec5SDimitry Andric           DoCUIteration(module_sp, context, searcher);
2780b57cec5SDimitry Andric       if (shouldContinue == Searcher::eCallbackReturnStop)
2790b57cec5SDimitry Andric         return shouldContinue;
2800b57cec5SDimitry Andric       else if (shouldContinue == Searcher::eCallbackReturnPop)
2810b57cec5SDimitry Andric         continue;
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric   }
284480093f4SDimitry Andric 
2850b57cec5SDimitry Andric   return Searcher::eCallbackReturnContinue;
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric Searcher::CallbackReturn
DoCUIteration(const ModuleSP & module_sp,const SymbolContext & context,Searcher & searcher)2890b57cec5SDimitry Andric SearchFilter::DoCUIteration(const ModuleSP &module_sp,
2900b57cec5SDimitry Andric                             const SymbolContext &context, Searcher &searcher) {
2910b57cec5SDimitry Andric   Searcher::CallbackReturn shouldContinue;
292480093f4SDimitry Andric   if (context.comp_unit != nullptr) {
293480093f4SDimitry Andric     if (CompUnitPasses(*context.comp_unit)) {
294480093f4SDimitry Andric       SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit);
295480093f4SDimitry Andric       return searcher.SearchCallback(*this, matchingContext, nullptr);
296480093f4SDimitry Andric     }
297480093f4SDimitry Andric     return Searcher::eCallbackReturnContinue;
298480093f4SDimitry Andric   }
299480093f4SDimitry Andric 
3000b57cec5SDimitry Andric   const size_t num_comp_units = module_sp->GetNumCompileUnits();
3010b57cec5SDimitry Andric   for (size_t i = 0; i < num_comp_units; i++) {
3020b57cec5SDimitry Andric     CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i));
303480093f4SDimitry Andric     if (!cu_sp)
304480093f4SDimitry Andric       continue;
3050b57cec5SDimitry Andric     if (!CompUnitPasses(*(cu_sp.get())))
3060b57cec5SDimitry Andric       continue;
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric     if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) {
3090b57cec5SDimitry Andric       SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
3100b57cec5SDimitry Andric 
311480093f4SDimitry Andric       shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr);
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric       if (shouldContinue == Searcher::eCallbackReturnPop)
3140b57cec5SDimitry Andric         return Searcher::eCallbackReturnContinue;
3150b57cec5SDimitry Andric       else if (shouldContinue == Searcher::eCallbackReturnStop)
3160b57cec5SDimitry Andric         return shouldContinue;
317480093f4SDimitry Andric       continue;
318480093f4SDimitry Andric     }
319480093f4SDimitry Andric 
3200b57cec5SDimitry Andric     // First make sure this compile unit's functions are parsed
3210b57cec5SDimitry Andric     // since CompUnit::ForeachFunction only iterates over already
3220b57cec5SDimitry Andric     // parsed functions.
3239dba64beSDimitry Andric     SymbolFile *sym_file = module_sp->GetSymbolFile();
3249dba64beSDimitry Andric     if (!sym_file)
3250b57cec5SDimitry Andric       continue;
3269dba64beSDimitry Andric     if (!sym_file->ParseFunctions(*cu_sp))
3270b57cec5SDimitry Andric       continue;
3280b57cec5SDimitry Andric     // If we got any functions, use ForeachFunction to do the iteration.
3290b57cec5SDimitry Andric     cu_sp->ForeachFunction([&](const FunctionSP &func_sp) {
3300b57cec5SDimitry Andric       if (!FunctionPasses(*func_sp.get()))
3310b57cec5SDimitry Andric         return false; // Didn't pass the filter, just keep going.
3320b57cec5SDimitry Andric       if (searcher.GetDepth() == lldb::eSearchDepthFunction) {
333480093f4SDimitry Andric         SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get(),
334480093f4SDimitry Andric                                       func_sp.get());
3359dba64beSDimitry Andric         shouldContinue =
3369dba64beSDimitry Andric             searcher.SearchCallback(*this, matchingContext, nullptr);
3370b57cec5SDimitry Andric       } else {
338480093f4SDimitry Andric         shouldContinue = DoFunctionIteration(func_sp.get(), context, searcher);
3390b57cec5SDimitry Andric       }
3400b57cec5SDimitry Andric       return shouldContinue != Searcher::eCallbackReturnContinue;
3410b57cec5SDimitry Andric     });
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric   return Searcher::eCallbackReturnContinue;
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
DoFunctionIteration(Function * function,const SymbolContext & context,Searcher & searcher)3460b57cec5SDimitry Andric Searcher::CallbackReturn SearchFilter::DoFunctionIteration(
3470b57cec5SDimitry Andric     Function *function, const SymbolContext &context, Searcher &searcher) {
3480b57cec5SDimitry Andric   // FIXME: Implement...
3490b57cec5SDimitry Andric   return Searcher::eCallbackReturnContinue;
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric //  SearchFilterForUnconstrainedSearches:
3530b57cec5SDimitry Andric //  Selects a shared library matching a given file spec, consulting the targets
3540b57cec5SDimitry Andric //  "black list".
CreateFromStructuredData(const lldb::TargetSP & target_sp,const StructuredData::Dictionary & data_dict,Status & error)3550b57cec5SDimitry Andric SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
3565ffd83dbSDimitry Andric     const lldb::TargetSP& target_sp,
3575ffd83dbSDimitry Andric     const StructuredData::Dictionary &data_dict,
3580b57cec5SDimitry Andric     Status &error) {
3590b57cec5SDimitry Andric   // No options for an unconstrained search.
3605ffd83dbSDimitry Andric   return std::make_shared<SearchFilterForUnconstrainedSearches>(target_sp);
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric StructuredData::ObjectSP
SerializeToStructuredData()3640b57cec5SDimitry Andric SearchFilterForUnconstrainedSearches::SerializeToStructuredData() {
3650b57cec5SDimitry Andric   // The options dictionary is an empty dictionary:
3660b57cec5SDimitry Andric   auto result_sp = std::make_shared<StructuredData::Dictionary>();
3670b57cec5SDimitry Andric   return WrapOptionsDict(result_sp);
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
ModulePasses(const FileSpec & module_spec)3700b57cec5SDimitry Andric bool SearchFilterForUnconstrainedSearches::ModulePasses(
3710b57cec5SDimitry Andric     const FileSpec &module_spec) {
3720b57cec5SDimitry Andric   return !m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec);
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric 
ModulePasses(const lldb::ModuleSP & module_sp)3750b57cec5SDimitry Andric bool SearchFilterForUnconstrainedSearches::ModulePasses(
3760b57cec5SDimitry Andric     const lldb::ModuleSP &module_sp) {
3770b57cec5SDimitry Andric   if (!module_sp)
3780b57cec5SDimitry Andric     return true;
3790b57cec5SDimitry Andric   else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp))
3800b57cec5SDimitry Andric     return false;
3810b57cec5SDimitry Andric   return true;
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric 
DoCreateCopy()3845ffd83dbSDimitry Andric SearchFilterSP SearchFilterForUnconstrainedSearches::DoCreateCopy() {
3850b57cec5SDimitry Andric   return std::make_shared<SearchFilterForUnconstrainedSearches>(*this);
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric //  SearchFilterByModule:
3890b57cec5SDimitry Andric //  Selects a shared library matching a given file spec
3900b57cec5SDimitry Andric 
SearchFilterByModule(const lldb::TargetSP & target_sp,const FileSpec & module)3910b57cec5SDimitry Andric SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp,
3920b57cec5SDimitry Andric                                            const FileSpec &module)
3930b57cec5SDimitry Andric     : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {}
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric SearchFilterByModule::~SearchFilterByModule() = default;
3960b57cec5SDimitry Andric 
ModulePasses(const ModuleSP & module_sp)3970b57cec5SDimitry Andric bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) {
3980b57cec5SDimitry Andric   return (module_sp &&
399480093f4SDimitry Andric           FileSpec::Match(m_module_spec, module_sp->GetFileSpec()));
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric 
ModulePasses(const FileSpec & spec)4020b57cec5SDimitry Andric bool SearchFilterByModule::ModulePasses(const FileSpec &spec) {
403480093f4SDimitry Andric   return FileSpec::Match(m_module_spec, spec);
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
AddressPasses(Address & address)4060b57cec5SDimitry Andric bool SearchFilterByModule::AddressPasses(Address &address) {
4070b57cec5SDimitry Andric   // FIXME: Not yet implemented
4080b57cec5SDimitry Andric   return true;
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric 
Search(Searcher & searcher)4110b57cec5SDimitry Andric void SearchFilterByModule::Search(Searcher &searcher) {
4120b57cec5SDimitry Andric   if (!m_target_sp)
4130b57cec5SDimitry Andric     return;
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
4160b57cec5SDimitry Andric     SymbolContext empty_sc;
4170b57cec5SDimitry Andric     empty_sc.target_sp = m_target_sp;
4189dba64beSDimitry Andric     searcher.SearchCallback(*this, empty_sc, nullptr);
4190b57cec5SDimitry Andric   }
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   // If the module file spec is a full path, then we can just find the one
4220b57cec5SDimitry Andric   // filespec that passes.  Otherwise, we need to go through all modules and
4230b57cec5SDimitry Andric   // find the ones that match the file name.
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   const ModuleList &target_modules = m_target_sp->GetImages();
4260b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
4270b57cec5SDimitry Andric 
428e8d8bef9SDimitry Andric   for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
429e8d8bef9SDimitry Andric     if (FileSpec::Match(m_module_spec, module_sp->GetFileSpec())) {
430e8d8bef9SDimitry Andric       SymbolContext matchingContext(m_target_sp, module_sp);
4310b57cec5SDimitry Andric       Searcher::CallbackReturn shouldContinue;
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric       shouldContinue = DoModuleIteration(matchingContext, searcher);
4340b57cec5SDimitry Andric       if (shouldContinue == Searcher::eCallbackReturnStop)
4350b57cec5SDimitry Andric         return;
4360b57cec5SDimitry Andric     }
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
GetDescription(Stream * s)4400b57cec5SDimitry Andric void SearchFilterByModule::GetDescription(Stream *s) {
4410b57cec5SDimitry Andric   s->PutCString(", module = ");
4420b57cec5SDimitry Andric   s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>"));
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric 
GetFilterRequiredItems()4450b57cec5SDimitry Andric uint32_t SearchFilterByModule::GetFilterRequiredItems() {
4460b57cec5SDimitry Andric   return eSymbolContextModule;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
Dump(Stream * s) const4490b57cec5SDimitry Andric void SearchFilterByModule::Dump(Stream *s) const {}
4500b57cec5SDimitry Andric 
DoCreateCopy()4515ffd83dbSDimitry Andric SearchFilterSP SearchFilterByModule::DoCreateCopy() {
4520b57cec5SDimitry Andric   return std::make_shared<SearchFilterByModule>(*this);
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
CreateFromStructuredData(const lldb::TargetSP & target_sp,const StructuredData::Dictionary & data_dict,Status & error)4550b57cec5SDimitry Andric SearchFilterSP SearchFilterByModule::CreateFromStructuredData(
4565ffd83dbSDimitry Andric     const lldb::TargetSP& target_sp,
4575ffd83dbSDimitry Andric     const StructuredData::Dictionary &data_dict,
4580b57cec5SDimitry Andric     Status &error) {
4590b57cec5SDimitry Andric   StructuredData::Array *modules_array;
4600b57cec5SDimitry Andric   bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
4610b57cec5SDimitry Andric                                                  modules_array);
4620b57cec5SDimitry Andric   if (!success) {
4630b57cec5SDimitry Andric     error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
4640b57cec5SDimitry Andric     return nullptr;
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   size_t num_modules = modules_array->GetSize();
4680b57cec5SDimitry Andric   if (num_modules > 1) {
4690b57cec5SDimitry Andric     error.SetErrorString(
4700b57cec5SDimitry Andric         "SFBM::CFSD: Only one modules allowed for SearchFilterByModule.");
4710b57cec5SDimitry Andric     return nullptr;
4720b57cec5SDimitry Andric   }
4730b57cec5SDimitry Andric 
4745f757f3fSDimitry Andric   std::optional<llvm::StringRef> maybe_module =
4755f757f3fSDimitry Andric       modules_array->GetItemAtIndexAsString(0);
4765f757f3fSDimitry Andric   if (!maybe_module) {
4770b57cec5SDimitry Andric     error.SetErrorString("SFBM::CFSD: filter module item not a string.");
4780b57cec5SDimitry Andric     return nullptr;
4790b57cec5SDimitry Andric   }
4805f757f3fSDimitry Andric   FileSpec module_spec(*maybe_module);
4810b57cec5SDimitry Andric 
4825ffd83dbSDimitry Andric   return std::make_shared<SearchFilterByModule>(target_sp, module_spec);
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric 
SerializeToStructuredData()4850b57cec5SDimitry Andric StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() {
4860b57cec5SDimitry Andric   auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
4870b57cec5SDimitry Andric   auto module_array_sp = std::make_shared<StructuredData::Array>();
4880b57cec5SDimitry Andric   module_array_sp->AddItem(
4890b57cec5SDimitry Andric       std::make_shared<StructuredData::String>(m_module_spec.GetPath()));
4900b57cec5SDimitry Andric   options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp);
4910b57cec5SDimitry Andric   return WrapOptionsDict(options_dict_sp);
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric //  SearchFilterByModuleList:
4950b57cec5SDimitry Andric //  Selects a shared library matching a given file spec
4960b57cec5SDimitry Andric 
SearchFilterByModuleList(const lldb::TargetSP & target_sp,const FileSpecList & module_list)4970b57cec5SDimitry Andric SearchFilterByModuleList::SearchFilterByModuleList(
4980b57cec5SDimitry Andric     const lldb::TargetSP &target_sp, const FileSpecList &module_list)
4990b57cec5SDimitry Andric     : SearchFilter(target_sp, FilterTy::ByModules),
5000b57cec5SDimitry Andric       m_module_spec_list(module_list) {}
5010b57cec5SDimitry Andric 
SearchFilterByModuleList(const lldb::TargetSP & target_sp,const FileSpecList & module_list,enum FilterTy filter_ty)5020b57cec5SDimitry Andric SearchFilterByModuleList::SearchFilterByModuleList(
5030b57cec5SDimitry Andric     const lldb::TargetSP &target_sp, const FileSpecList &module_list,
5040b57cec5SDimitry Andric     enum FilterTy filter_ty)
5050b57cec5SDimitry Andric     : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {}
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric SearchFilterByModuleList::~SearchFilterByModuleList() = default;
5080b57cec5SDimitry Andric 
ModulePasses(const ModuleSP & module_sp)5090b57cec5SDimitry Andric bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) {
5100b57cec5SDimitry Andric   if (m_module_spec_list.GetSize() == 0)
5110b57cec5SDimitry Andric     return true;
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   return module_sp && m_module_spec_list.FindFileIndex(
5140b57cec5SDimitry Andric                           0, module_sp->GetFileSpec(), false) != UINT32_MAX;
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric 
ModulePasses(const FileSpec & spec)5170b57cec5SDimitry Andric bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) {
5180b57cec5SDimitry Andric   if (m_module_spec_list.GetSize() == 0)
5190b57cec5SDimitry Andric     return true;
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   return m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
AddressPasses(Address & address)5240b57cec5SDimitry Andric bool SearchFilterByModuleList::AddressPasses(Address &address) {
5250b57cec5SDimitry Andric   // FIXME: Not yet implemented
5260b57cec5SDimitry Andric   return true;
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric 
Search(Searcher & searcher)5290b57cec5SDimitry Andric void SearchFilterByModuleList::Search(Searcher &searcher) {
5300b57cec5SDimitry Andric   if (!m_target_sp)
5310b57cec5SDimitry Andric     return;
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
5340b57cec5SDimitry Andric     SymbolContext empty_sc;
5350b57cec5SDimitry Andric     empty_sc.target_sp = m_target_sp;
5369dba64beSDimitry Andric     searcher.SearchCallback(*this, empty_sc, nullptr);
5370b57cec5SDimitry Andric   }
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   // If the module file spec is a full path, then we can just find the one
5400b57cec5SDimitry Andric   // filespec that passes.  Otherwise, we need to go through all modules and
5410b57cec5SDimitry Andric   // find the ones that match the file name.
542e8d8bef9SDimitry Andric   for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
543e8d8bef9SDimitry Andric     if (m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) ==
544480093f4SDimitry Andric         UINT32_MAX)
545480093f4SDimitry Andric       continue;
546e8d8bef9SDimitry Andric     SymbolContext matchingContext(m_target_sp, module_sp);
5470b57cec5SDimitry Andric     Searcher::CallbackReturn shouldContinue;
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric     shouldContinue = DoModuleIteration(matchingContext, searcher);
5500b57cec5SDimitry Andric     if (shouldContinue == Searcher::eCallbackReturnStop)
5510b57cec5SDimitry Andric       return;
5520b57cec5SDimitry Andric   }
5530b57cec5SDimitry Andric }
5540b57cec5SDimitry Andric 
GetDescription(Stream * s)5550b57cec5SDimitry Andric void SearchFilterByModuleList::GetDescription(Stream *s) {
5560b57cec5SDimitry Andric   size_t num_modules = m_module_spec_list.GetSize();
5570b57cec5SDimitry Andric   if (num_modules == 1) {
5580b57cec5SDimitry Andric     s->Printf(", module = ");
5590b57cec5SDimitry Andric     s->PutCString(
5600b57cec5SDimitry Andric         m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
5610b57cec5SDimitry Andric             "<Unknown>"));
562480093f4SDimitry Andric     return;
563480093f4SDimitry Andric   }
564480093f4SDimitry Andric 
5650b57cec5SDimitry Andric   s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules);
5660b57cec5SDimitry Andric   for (size_t i = 0; i < num_modules; i++) {
5670b57cec5SDimitry Andric     s->PutCString(
5680b57cec5SDimitry Andric         m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
5690b57cec5SDimitry Andric             "<Unknown>"));
5700b57cec5SDimitry Andric     if (i != num_modules - 1)
5710b57cec5SDimitry Andric       s->PutCString(", ");
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric 
GetFilterRequiredItems()5750b57cec5SDimitry Andric uint32_t SearchFilterByModuleList::GetFilterRequiredItems() {
5760b57cec5SDimitry Andric   return eSymbolContextModule;
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric 
Dump(Stream * s) const5790b57cec5SDimitry Andric void SearchFilterByModuleList::Dump(Stream *s) const {}
5800b57cec5SDimitry Andric 
DoCreateCopy()5815ffd83dbSDimitry Andric lldb::SearchFilterSP SearchFilterByModuleList::DoCreateCopy() {
5820b57cec5SDimitry Andric   return std::make_shared<SearchFilterByModuleList>(*this);
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric 
CreateFromStructuredData(const lldb::TargetSP & target_sp,const StructuredData::Dictionary & data_dict,Status & error)5850b57cec5SDimitry Andric SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
5865ffd83dbSDimitry Andric     const lldb::TargetSP& target_sp,
5875ffd83dbSDimitry Andric     const StructuredData::Dictionary &data_dict,
5880b57cec5SDimitry Andric     Status &error) {
5890b57cec5SDimitry Andric   StructuredData::Array *modules_array;
5900b57cec5SDimitry Andric   bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
5910b57cec5SDimitry Andric                                                  modules_array);
592480093f4SDimitry Andric 
593480093f4SDimitry Andric   if (!success)
5945ffd83dbSDimitry Andric     return std::make_shared<SearchFilterByModuleList>(target_sp,
595480093f4SDimitry Andric                                                       FileSpecList{});
5960b57cec5SDimitry Andric   FileSpecList modules;
5970b57cec5SDimitry Andric   size_t num_modules = modules_array->GetSize();
5980b57cec5SDimitry Andric   for (size_t i = 0; i < num_modules; i++) {
5995f757f3fSDimitry Andric     std::optional<llvm::StringRef> maybe_module =
6005f757f3fSDimitry Andric         modules_array->GetItemAtIndexAsString(i);
6015f757f3fSDimitry Andric     if (!maybe_module) {
6020b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
6030b57cec5SDimitry Andric           "SFBM::CFSD: filter module item %zu not a string.", i);
6040b57cec5SDimitry Andric       return nullptr;
6050b57cec5SDimitry Andric     }
6065f757f3fSDimitry Andric     modules.EmplaceBack(*maybe_module);
6070b57cec5SDimitry Andric   }
6085ffd83dbSDimitry Andric   return std::make_shared<SearchFilterByModuleList>(target_sp, modules);
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric 
SerializeUnwrapped(StructuredData::DictionarySP & options_dict_sp)6110b57cec5SDimitry Andric void SearchFilterByModuleList::SerializeUnwrapped(
6120b57cec5SDimitry Andric     StructuredData::DictionarySP &options_dict_sp) {
6130b57cec5SDimitry Andric   SerializeFileSpecList(options_dict_sp, OptionNames::ModList,
6140b57cec5SDimitry Andric                         m_module_spec_list);
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
SerializeToStructuredData()6170b57cec5SDimitry Andric StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() {
6180b57cec5SDimitry Andric   auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
6190b57cec5SDimitry Andric   SerializeUnwrapped(options_dict_sp);
6200b57cec5SDimitry Andric   return WrapOptionsDict(options_dict_sp);
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric //  SearchFilterByModuleListAndCU:
6240b57cec5SDimitry Andric //  Selects a shared library matching a given file spec
6250b57cec5SDimitry Andric 
SearchFilterByModuleListAndCU(const lldb::TargetSP & target_sp,const FileSpecList & module_list,const FileSpecList & cu_list)6260b57cec5SDimitry Andric SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
6270b57cec5SDimitry Andric     const lldb::TargetSP &target_sp, const FileSpecList &module_list,
6280b57cec5SDimitry Andric     const FileSpecList &cu_list)
6290b57cec5SDimitry Andric     : SearchFilterByModuleList(target_sp, module_list,
6300b57cec5SDimitry Andric                                FilterTy::ByModulesAndCU),
6310b57cec5SDimitry Andric       m_cu_spec_list(cu_list) {}
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default;
6340b57cec5SDimitry Andric 
CreateFromStructuredData(const lldb::TargetSP & target_sp,const StructuredData::Dictionary & data_dict,Status & error)6350b57cec5SDimitry Andric lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
6365ffd83dbSDimitry Andric     const lldb::TargetSP& target_sp,
6375ffd83dbSDimitry Andric     const StructuredData::Dictionary &data_dict,
6380b57cec5SDimitry Andric     Status &error) {
6390b57cec5SDimitry Andric   StructuredData::Array *modules_array = nullptr;
6400b57cec5SDimitry Andric   SearchFilterSP result_sp;
6410b57cec5SDimitry Andric   bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
6420b57cec5SDimitry Andric                                                  modules_array);
6430b57cec5SDimitry Andric   FileSpecList modules;
6440b57cec5SDimitry Andric   if (success) {
6450b57cec5SDimitry Andric     size_t num_modules = modules_array->GetSize();
6460b57cec5SDimitry Andric     for (size_t i = 0; i < num_modules; i++) {
6475f757f3fSDimitry Andric       std::optional<llvm::StringRef> maybe_module =
6485f757f3fSDimitry Andric           modules_array->GetItemAtIndexAsString(i);
6495f757f3fSDimitry Andric       if (!maybe_module) {
6500b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
6510b57cec5SDimitry Andric             "SFBM::CFSD: filter module item %zu not a string.", i);
6520b57cec5SDimitry Andric         return result_sp;
6530b57cec5SDimitry Andric       }
6545f757f3fSDimitry Andric       modules.EmplaceBack(*maybe_module);
6550b57cec5SDimitry Andric     }
6560b57cec5SDimitry Andric   }
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric   StructuredData::Array *cus_array = nullptr;
6590b57cec5SDimitry Andric   success =
6600b57cec5SDimitry Andric       data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array);
6610b57cec5SDimitry Andric   if (!success) {
6620b57cec5SDimitry Andric     error.SetErrorString("SFBM::CFSD: Could not find the CU list key.");
6630b57cec5SDimitry Andric     return result_sp;
6640b57cec5SDimitry Andric   }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   size_t num_cus = cus_array->GetSize();
6670b57cec5SDimitry Andric   FileSpecList cus;
6680b57cec5SDimitry Andric   for (size_t i = 0; i < num_cus; i++) {
6695f757f3fSDimitry Andric     std::optional<llvm::StringRef> maybe_cu =
6705f757f3fSDimitry Andric         cus_array->GetItemAtIndexAsString(i);
6715f757f3fSDimitry Andric     if (!maybe_cu) {
6720b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
673480093f4SDimitry Andric           "SFBM::CFSD: filter CU item %zu not a string.", i);
6740b57cec5SDimitry Andric       return nullptr;
6750b57cec5SDimitry Andric     }
6765f757f3fSDimitry Andric     cus.EmplaceBack(*maybe_cu);
6770b57cec5SDimitry Andric   }
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric   return std::make_shared<SearchFilterByModuleListAndCU>(
6805ffd83dbSDimitry Andric       target_sp, modules, cus);
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric StructuredData::ObjectSP
SerializeToStructuredData()6840b57cec5SDimitry Andric SearchFilterByModuleListAndCU::SerializeToStructuredData() {
6850b57cec5SDimitry Andric   auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
6860b57cec5SDimitry Andric   SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp);
6870b57cec5SDimitry Andric   SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list);
6880b57cec5SDimitry Andric   return WrapOptionsDict(options_dict_sp);
6890b57cec5SDimitry Andric }
6900b57cec5SDimitry Andric 
AddressPasses(Address & address)6910b57cec5SDimitry Andric bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
6920b57cec5SDimitry Andric   SymbolContext sym_ctx;
6930b57cec5SDimitry Andric   address.CalculateSymbolContext(&sym_ctx, eSymbolContextEverything);
6940b57cec5SDimitry Andric   if (!sym_ctx.comp_unit) {
6950b57cec5SDimitry Andric     if (m_cu_spec_list.GetSize() != 0)
6960b57cec5SDimitry Andric       return false; // Has no comp_unit so can't pass the file check.
6970b57cec5SDimitry Andric   }
698480093f4SDimitry Andric   FileSpec cu_spec;
699480093f4SDimitry Andric   if (sym_ctx.comp_unit)
700480093f4SDimitry Andric     cu_spec = sym_ctx.comp_unit->GetPrimaryFile();
701480093f4SDimitry Andric   if (m_cu_spec_list.FindFileIndex(0, cu_spec, false) == UINT32_MAX)
7020b57cec5SDimitry Andric     return false; // Fails the file check
7030b57cec5SDimitry Andric   return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp);
7040b57cec5SDimitry Andric }
7050b57cec5SDimitry Andric 
CompUnitPasses(FileSpec & fileSpec)7060b57cec5SDimitry Andric bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
7070b57cec5SDimitry Andric   return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX;
7080b57cec5SDimitry Andric }
7090b57cec5SDimitry Andric 
CompUnitPasses(CompileUnit & compUnit)7100b57cec5SDimitry Andric bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) {
711480093f4SDimitry Andric   bool in_cu_list = m_cu_spec_list.FindFileIndex(0, compUnit.GetPrimaryFile(),
712480093f4SDimitry Andric                                                  false) != UINT32_MAX;
713480093f4SDimitry Andric   if (!in_cu_list)
7140b57cec5SDimitry Andric     return false;
715480093f4SDimitry Andric 
716480093f4SDimitry Andric   ModuleSP module_sp(compUnit.GetModule());
717480093f4SDimitry Andric   if (!module_sp)
718480093f4SDimitry Andric     return true;
719480093f4SDimitry Andric 
720480093f4SDimitry Andric   return SearchFilterByModuleList::ModulePasses(module_sp);
7210b57cec5SDimitry Andric }
7220b57cec5SDimitry Andric 
Search(Searcher & searcher)7230b57cec5SDimitry Andric void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
7240b57cec5SDimitry Andric   if (!m_target_sp)
7250b57cec5SDimitry Andric     return;
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
7280b57cec5SDimitry Andric     SymbolContext empty_sc;
7290b57cec5SDimitry Andric     empty_sc.target_sp = m_target_sp;
7309dba64beSDimitry Andric     searcher.SearchCallback(*this, empty_sc, nullptr);
7310b57cec5SDimitry Andric   }
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric   // If the module file spec is a full path, then we can just find the one
7340b57cec5SDimitry Andric   // filespec that passes.  Otherwise, we need to go through all modules and
7350b57cec5SDimitry Andric   // find the ones that match the file name.
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric   ModuleList matching_modules;
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric   bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
740e8d8bef9SDimitry Andric   for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
741480093f4SDimitry Andric     if (!no_modules_in_filter &&
742480093f4SDimitry Andric         m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) ==
743480093f4SDimitry Andric             UINT32_MAX)
744480093f4SDimitry Andric       continue;
745480093f4SDimitry Andric 
7460b57cec5SDimitry Andric     SymbolContext matchingContext(m_target_sp, module_sp);
7470b57cec5SDimitry Andric     Searcher::CallbackReturn shouldContinue;
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric     if (searcher.GetDepth() == lldb::eSearchDepthModule) {
7500b57cec5SDimitry Andric       shouldContinue = DoModuleIteration(matchingContext, searcher);
7510b57cec5SDimitry Andric       if (shouldContinue == Searcher::eCallbackReturnStop)
7520b57cec5SDimitry Andric         return;
753480093f4SDimitry Andric       continue;
754480093f4SDimitry Andric     }
755480093f4SDimitry Andric 
7560b57cec5SDimitry Andric     const size_t num_cu = module_sp->GetNumCompileUnits();
7570b57cec5SDimitry Andric     for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) {
7580b57cec5SDimitry Andric       CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
7590b57cec5SDimitry Andric       matchingContext.comp_unit = cu_sp.get();
760480093f4SDimitry Andric       if (!matchingContext.comp_unit)
761480093f4SDimitry Andric         continue;
762480093f4SDimitry Andric       if (m_cu_spec_list.FindFileIndex(
763480093f4SDimitry Andric               0, matchingContext.comp_unit->GetPrimaryFile(), false) ==
764480093f4SDimitry Andric           UINT32_MAX)
765480093f4SDimitry Andric         continue;
766480093f4SDimitry Andric       shouldContinue = DoCUIteration(module_sp, matchingContext, searcher);
7670b57cec5SDimitry Andric       if (shouldContinue == Searcher::eCallbackReturnStop)
7680b57cec5SDimitry Andric         return;
7690b57cec5SDimitry Andric     }
7700b57cec5SDimitry Andric   }
7710b57cec5SDimitry Andric }
7720b57cec5SDimitry Andric 
GetDescription(Stream * s)7730b57cec5SDimitry Andric void SearchFilterByModuleListAndCU::GetDescription(Stream *s) {
7740b57cec5SDimitry Andric   size_t num_modules = m_module_spec_list.GetSize();
7750b57cec5SDimitry Andric   if (num_modules == 1) {
7760b57cec5SDimitry Andric     s->Printf(", module = ");
7770b57cec5SDimitry Andric     s->PutCString(
7780b57cec5SDimitry Andric         m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
7790b57cec5SDimitry Andric             "<Unknown>"));
7800b57cec5SDimitry Andric   } else if (num_modules > 0) {
7810b57cec5SDimitry Andric     s->Printf(", modules(%" PRIu64 ") = ", static_cast<uint64_t>(num_modules));
7820b57cec5SDimitry Andric     for (size_t i = 0; i < num_modules; i++) {
7830b57cec5SDimitry Andric       s->PutCString(
7840b57cec5SDimitry Andric           m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
7850b57cec5SDimitry Andric               "<Unknown>"));
7860b57cec5SDimitry Andric       if (i != num_modules - 1)
7870b57cec5SDimitry Andric         s->PutCString(", ");
7880b57cec5SDimitry Andric     }
7890b57cec5SDimitry Andric   }
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric 
GetFilterRequiredItems()7920b57cec5SDimitry Andric uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() {
7930b57cec5SDimitry Andric   return eSymbolContextModule | eSymbolContextCompUnit;
7940b57cec5SDimitry Andric }
7950b57cec5SDimitry Andric 
Dump(Stream * s) const7960b57cec5SDimitry Andric void SearchFilterByModuleListAndCU::Dump(Stream *s) const {}
7970b57cec5SDimitry Andric 
DoCreateCopy()7985ffd83dbSDimitry Andric SearchFilterSP SearchFilterByModuleListAndCU::DoCreateCopy() {
7990b57cec5SDimitry Andric   return std::make_shared<SearchFilterByModuleListAndCU>(*this);
8000b57cec5SDimitry Andric }
801