//===-- SearchFilter.cpp ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/SearchFilter.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Target/Target.h" #include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception", "Module", "Modules", "ModulesAndCU", "Unknown"}; const char *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = { "ModuleList", "CUList"}; const char *SearchFilter::FilterTyToName(enum FilterTy type) { if (type > LastKnownFilterType) return g_ty_to_name[UnknownFilter]; return g_ty_to_name[type]; } SearchFilter::FilterTy SearchFilter::NameToFilterTy(const char *name) { for (size_t i = 0; i <= LastKnownFilterType; i++) { if (strcmp(name, g_ty_to_name[i]) == 0) return (FilterTy)i; } return UnknownFilter; } Searcher::Searcher() = default; Searcher::~Searcher() = default; void Searcher::GetDescription(Stream *s) {} SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType) : m_target_sp(target_sp), SubclassID(filterType) {} SearchFilter::SearchFilter(const SearchFilter &rhs) = default; SearchFilter &SearchFilter::operator=(const SearchFilter &rhs) = default; SearchFilter::~SearchFilter() = default; SearchFilterSP SearchFilter::CreateFromStructuredData( Target &target, const StructuredData::Dictionary &filter_dict, Error &error) { SearchFilterSP result_sp; if (!filter_dict.IsValid()) { error.SetErrorString("Can't deserialize from an invalid data object."); return result_sp; } std::string subclass_name; bool success = filter_dict.GetValueForKeyAsString( GetSerializationSubclassKey(), subclass_name); if (!success) { error.SetErrorStringWithFormat("Filter data missing subclass key"); return result_sp; } FilterTy filter_type = NameToFilterTy(subclass_name.c_str()); if (filter_type == UnknownFilter) { error.SetErrorStringWithFormat("Unknown filter type: %s.", subclass_name.c_str()); return result_sp; } StructuredData::Dictionary *subclass_options = nullptr; success = filter_dict.GetValueForKeyAsDictionary( GetSerializationSubclassOptionsKey(), subclass_options); if (!success || !subclass_options || !subclass_options->IsValid()) { error.SetErrorString("Filter data missing subclass options key."); return result_sp; } switch (filter_type) { case Unconstrained: result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData( target, *subclass_options, error); break; case ByModule: result_sp = SearchFilterByModule::CreateFromStructuredData( target, *subclass_options, error); break; case ByModules: result_sp = SearchFilterByModuleList::CreateFromStructuredData( target, *subclass_options, error); break; case ByModulesAndCU: result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData( target, *subclass_options, error); break; case Exception: error.SetErrorString("Can't serialize exception breakpoints yet."); break; default: llvm_unreachable("Should never get an uresolvable filter type."); } return result_sp; } bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; } bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; } bool SearchFilter::AddressPasses(Address &address) { return true; } bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; } bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; } uint32_t SearchFilter::GetFilterRequiredItems() { return (lldb::SymbolContextItem)0; } void SearchFilter::GetDescription(Stream *s) {} void SearchFilter::Dump(Stream *s) const {} lldb::SearchFilterSP SearchFilter::CopyForBreakpoint(Breakpoint &breakpoint) { SearchFilterSP ret_sp = DoCopyForBreakpoint(breakpoint); TargetSP target_sp = breakpoint.GetTargetSP(); ret_sp->SetTarget(target_sp); return ret_sp; } //---------------------------------------------------------------------- // Helper functions for serialization. //---------------------------------------------------------------------- StructuredData::DictionarySP SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) { if (!options_dict_sp || !options_dict_sp->IsValid()) return StructuredData::DictionarySP(); StructuredData::DictionarySP type_dict_sp(new StructuredData::Dictionary()); type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetFilterName()); type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp); return type_dict_sp; } void SearchFilter::SerializeFileSpecList( StructuredData::DictionarySP &options_dict_sp, OptionNames name, FileSpecList &file_list) { size_t num_modules = file_list.GetSize(); // Don't serialize empty lists. if (num_modules == 0) return; StructuredData::ArraySP module_array_sp(new StructuredData::Array()); for (size_t i = 0; i < num_modules; i++) { module_array_sp->AddItem(StructuredData::StringSP( new StructuredData::String(file_list.GetFileSpecAtIndex(i).GetPath()))); } options_dict_sp->AddItem(GetKey(name), module_array_sp); } //---------------------------------------------------------------------- // UTILITY Functions to help iterate down through the elements of the // SymbolContext. //---------------------------------------------------------------------- void SearchFilter::Search(Searcher &searcher) { SymbolContext empty_sc; if (!m_target_sp) return; empty_sc.target_sp = m_target_sp; if (searcher.GetDepth() == Searcher::eDepthTarget) searcher.SearchCallback(*this, empty_sc, nullptr, false); else DoModuleIteration(empty_sc, searcher); } void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) { SymbolContext empty_sc; if (!m_target_sp) return; empty_sc.target_sp = m_target_sp; if (searcher.GetDepth() == Searcher::eDepthTarget) searcher.SearchCallback(*this, empty_sc, nullptr, false); else { std::lock_guard guard(modules.GetMutex()); const size_t numModules = modules.GetSize(); for (size_t i = 0; i < numModules; i++) { ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i)); if (ModulePasses(module_sp)) { if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop) return; } } } } Searcher::CallbackReturn SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp, Searcher &searcher) { SymbolContext matchingContext(m_target_sp, module_sp); return DoModuleIteration(matchingContext, searcher); } Searcher::CallbackReturn SearchFilter::DoModuleIteration(const SymbolContext &context, Searcher &searcher) { if (searcher.GetDepth() >= Searcher::eDepthModule) { if (context.module_sp) { if (searcher.GetDepth() == Searcher::eDepthModule) { SymbolContext matchingContext(context.module_sp.get()); searcher.SearchCallback(*this, matchingContext, nullptr, false); } else { return DoCUIteration(context.module_sp, context, searcher); } } else { const ModuleList &target_images = m_target_sp->GetImages(); std::lock_guard guard(target_images.GetMutex()); size_t n_modules = target_images.GetSize(); for (size_t i = 0; i < n_modules; i++) { // If this is the last level supplied, then call the callback directly, // otherwise descend. ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i)); if (!ModulePasses(module_sp)) continue; if (searcher.GetDepth() == Searcher::eDepthModule) { SymbolContext matchingContext(m_target_sp, module_sp); Searcher::CallbackReturn shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr, false); if (shouldContinue == Searcher::eCallbackReturnStop || shouldContinue == Searcher::eCallbackReturnPop) return shouldContinue; } else { Searcher::CallbackReturn shouldContinue = DoCUIteration(module_sp, context, searcher); if (shouldContinue == Searcher::eCallbackReturnStop) return shouldContinue; else if (shouldContinue == Searcher::eCallbackReturnPop) continue; } } } } return Searcher::eCallbackReturnContinue; } Searcher::CallbackReturn SearchFilter::DoCUIteration(const ModuleSP &module_sp, const SymbolContext &context, Searcher &searcher) { Searcher::CallbackReturn shouldContinue; if (context.comp_unit == nullptr) { const size_t num_comp_units = module_sp->GetNumCompileUnits(); for (size_t i = 0; i < num_comp_units; i++) { CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i)); if (cu_sp) { if (!CompUnitPasses(*(cu_sp.get()))) continue; if (searcher.GetDepth() == Searcher::eDepthCompUnit) { SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get()); shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr, false); if (shouldContinue == Searcher::eCallbackReturnPop) return Searcher::eCallbackReturnContinue; else if (shouldContinue == Searcher::eCallbackReturnStop) return shouldContinue; } else { // FIXME Descend to block. } } } } else { if (CompUnitPasses(*context.comp_unit)) { SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit); return searcher.SearchCallback(*this, matchingContext, nullptr, false); } } return Searcher::eCallbackReturnContinue; } Searcher::CallbackReturn SearchFilter::DoFunctionIteration( Function *function, const SymbolContext &context, Searcher &searcher) { // FIXME: Implement... return Searcher::eCallbackReturnContinue; } //---------------------------------------------------------------------- // SearchFilterForUnconstrainedSearches: // Selects a shared library matching a given file spec, consulting the targets // "black list". //---------------------------------------------------------------------- SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData( Target &target, const StructuredData::Dictionary &data_dict, Error &error) { // No options for an unconstrained search. return SearchFilterSP( new SearchFilterForUnconstrainedSearches(target.shared_from_this())); } StructuredData::ObjectSP SearchFilterForUnconstrainedSearches::SerializeToStructuredData() { // The options dictionary is an empty dictionary: StructuredData::DictionarySP result_sp(new StructuredData::Dictionary()); return WrapOptionsDict(result_sp); } bool SearchFilterForUnconstrainedSearches::ModulePasses( const FileSpec &module_spec) { if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec)) return false; else return true; } bool SearchFilterForUnconstrainedSearches::ModulePasses( const lldb::ModuleSP &module_sp) { if (!module_sp) return true; else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp)) return false; else return true; } lldb::SearchFilterSP SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint( Breakpoint &breakpoint) { SearchFilterSP ret_sp(new SearchFilterForUnconstrainedSearches(*this)); return ret_sp; } //---------------------------------------------------------------------- // SearchFilterByModule: // Selects a shared library matching a given file spec //---------------------------------------------------------------------- SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp, const FileSpec &module) : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {} SearchFilterByModule::SearchFilterByModule(const SearchFilterByModule &rhs) = default; SearchFilterByModule &SearchFilterByModule:: operator=(const SearchFilterByModule &rhs) { m_target_sp = rhs.m_target_sp; m_module_spec = rhs.m_module_spec; return *this; } SearchFilterByModule::~SearchFilterByModule() = default; bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) { return (module_sp && FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false)); } bool SearchFilterByModule::ModulePasses(const FileSpec &spec) { // Do a full match only if "spec" has a directory const bool full_match = (bool)spec.GetDirectory(); return FileSpec::Equal(spec, m_module_spec, full_match); } bool SearchFilterByModule::AddressPasses(Address &address) { // FIXME: Not yet implemented return true; } bool SearchFilterByModule::CompUnitPasses(FileSpec &fileSpec) { return true; } bool SearchFilterByModule::CompUnitPasses(CompileUnit &compUnit) { return true; } void SearchFilterByModule::Search(Searcher &searcher) { if (!m_target_sp) return; if (searcher.GetDepth() == Searcher::eDepthTarget) { SymbolContext empty_sc; empty_sc.target_sp = m_target_sp; searcher.SearchCallback(*this, empty_sc, nullptr, false); } // If the module file spec is a full path, then we can just find the one // filespec that passes. Otherwise, we need to go through all modules and // find the ones that match the file name. const ModuleList &target_modules = m_target_sp->GetImages(); std::lock_guard guard(target_modules.GetMutex()); const size_t num_modules = target_modules.GetSize(); for (size_t i = 0; i < num_modules; i++) { Module *module = target_modules.GetModulePointerAtIndexUnlocked(i); const bool full_match = (bool)m_module_spec.GetDirectory(); if (FileSpec::Equal(m_module_spec, module->GetFileSpec(), full_match)) { SymbolContext matchingContext(m_target_sp, module->shared_from_this()); Searcher::CallbackReturn shouldContinue; shouldContinue = DoModuleIteration(matchingContext, searcher); if (shouldContinue == Searcher::eCallbackReturnStop) return; } } } void SearchFilterByModule::GetDescription(Stream *s) { s->PutCString(", module = "); if (s->GetVerbose()) { char buffer[2048]; m_module_spec.GetPath(buffer, 2047); s->PutCString(buffer); } else { s->PutCString(m_module_spec.GetFilename().AsCString("")); } } uint32_t SearchFilterByModule::GetFilterRequiredItems() { return eSymbolContextModule; } void SearchFilterByModule::Dump(Stream *s) const {} lldb::SearchFilterSP SearchFilterByModule::DoCopyForBreakpoint(Breakpoint &breakpoint) { SearchFilterSP ret_sp(new SearchFilterByModule(*this)); return ret_sp; } SearchFilterSP SearchFilterByModule::CreateFromStructuredData( Target &target, const StructuredData::Dictionary &data_dict, Error &error) { StructuredData::Array *modules_array; bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), modules_array); if (!success) { error.SetErrorString("SFBM::CFSD: Could not find the module list key."); return nullptr; } size_t num_modules = modules_array->GetSize(); if (num_modules > 1) { error.SetErrorString( "SFBM::CFSD: Only one modules allowed for SearchFilterByModule."); return nullptr; } std::string module; success = modules_array->GetItemAtIndexAsString(0, module); if (!success) { error.SetErrorString("SFBM::CFSD: filter module item not a string."); return nullptr; } FileSpec module_spec(module, false); return SearchFilterSP( new SearchFilterByModule(target.shared_from_this(), module_spec)); } StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() { StructuredData::DictionarySP options_dict_sp( new StructuredData::Dictionary()); StructuredData::ArraySP module_array_sp(new StructuredData::Array()); module_array_sp->AddItem(StructuredData::StringSP( new StructuredData::String(m_module_spec.GetPath()))); options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp); return WrapOptionsDict(options_dict_sp); } //---------------------------------------------------------------------- // SearchFilterByModuleList: // Selects a shared library matching a given file spec //---------------------------------------------------------------------- SearchFilterByModuleList::SearchFilterByModuleList( const lldb::TargetSP &target_sp, const FileSpecList &module_list) : SearchFilter(target_sp, FilterTy::ByModules), m_module_spec_list(module_list) {} SearchFilterByModuleList::SearchFilterByModuleList( const lldb::TargetSP &target_sp, const FileSpecList &module_list, enum FilterTy filter_ty) : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {} SearchFilterByModuleList::SearchFilterByModuleList( const SearchFilterByModuleList &rhs) = default; SearchFilterByModuleList &SearchFilterByModuleList:: operator=(const SearchFilterByModuleList &rhs) { m_target_sp = rhs.m_target_sp; m_module_spec_list = rhs.m_module_spec_list; return *this; } SearchFilterByModuleList::~SearchFilterByModuleList() = default; bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) { if (m_module_spec_list.GetSize() == 0) return true; if (module_sp && m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != UINT32_MAX) return true; else return false; } bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) { if (m_module_spec_list.GetSize() == 0) return true; if (m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX) return true; else return false; } bool SearchFilterByModuleList::AddressPasses(Address &address) { // FIXME: Not yet implemented return true; } bool SearchFilterByModuleList::CompUnitPasses(FileSpec &fileSpec) { return true; } bool SearchFilterByModuleList::CompUnitPasses(CompileUnit &compUnit) { return true; } void SearchFilterByModuleList::Search(Searcher &searcher) { if (!m_target_sp) return; if (searcher.GetDepth() == Searcher::eDepthTarget) { SymbolContext empty_sc; empty_sc.target_sp = m_target_sp; searcher.SearchCallback(*this, empty_sc, nullptr, false); } // If the module file spec is a full path, then we can just find the one // filespec that passes. Otherwise, we need to go through all modules and // find the ones that match the file name. const ModuleList &target_modules = m_target_sp->GetImages(); std::lock_guard guard(target_modules.GetMutex()); const size_t num_modules = target_modules.GetSize(); for (size_t i = 0; i < num_modules; i++) { Module *module = target_modules.GetModulePointerAtIndexUnlocked(i); if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) != UINT32_MAX) { SymbolContext matchingContext(m_target_sp, module->shared_from_this()); Searcher::CallbackReturn shouldContinue; shouldContinue = DoModuleIteration(matchingContext, searcher); if (shouldContinue == Searcher::eCallbackReturnStop) return; } } } void SearchFilterByModuleList::GetDescription(Stream *s) { size_t num_modules = m_module_spec_list.GetSize(); if (num_modules == 1) { s->Printf(", module = "); if (s->GetVerbose()) { char buffer[2048]; m_module_spec_list.GetFileSpecAtIndex(0).GetPath(buffer, 2047); s->PutCString(buffer); } else { s->PutCString( m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString( "")); } } else { s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules); for (size_t i = 0; i < num_modules; i++) { if (s->GetVerbose()) { char buffer[2048]; m_module_spec_list.GetFileSpecAtIndex(i).GetPath(buffer, 2047); s->PutCString(buffer); } else { s->PutCString( m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString( "")); } if (i != num_modules - 1) s->PutCString(", "); } } } uint32_t SearchFilterByModuleList::GetFilterRequiredItems() { return eSymbolContextModule; } void SearchFilterByModuleList::Dump(Stream *s) const {} lldb::SearchFilterSP SearchFilterByModuleList::DoCopyForBreakpoint(Breakpoint &breakpoint) { SearchFilterSP ret_sp(new SearchFilterByModuleList(*this)); return ret_sp; } SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData( Target &target, const StructuredData::Dictionary &data_dict, Error &error) { StructuredData::Array *modules_array; bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), modules_array); FileSpecList modules; if (success) { size_t num_modules = modules_array->GetSize(); for (size_t i = 0; i < num_modules; i++) { std::string module; success = modules_array->GetItemAtIndexAsString(i, module); if (!success) { error.SetErrorStringWithFormat( "SFBM::CFSD: filter module item %zu not a string.", i); return nullptr; } modules.Append(FileSpec(module, false)); } } return SearchFilterSP( new SearchFilterByModuleList(target.shared_from_this(), modules)); } void SearchFilterByModuleList::SerializeUnwrapped( StructuredData::DictionarySP &options_dict_sp) { SerializeFileSpecList(options_dict_sp, OptionNames::ModList, m_module_spec_list); } StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() { StructuredData::DictionarySP options_dict_sp( new StructuredData::Dictionary()); SerializeUnwrapped(options_dict_sp); return WrapOptionsDict(options_dict_sp); } //---------------------------------------------------------------------- // SearchFilterByModuleListAndCU: // Selects a shared library matching a given file spec //---------------------------------------------------------------------- SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU( const lldb::TargetSP &target_sp, const FileSpecList &module_list, const FileSpecList &cu_list) : SearchFilterByModuleList(target_sp, module_list, FilterTy::ByModulesAndCU), m_cu_spec_list(cu_list) {} SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU( const SearchFilterByModuleListAndCU &rhs) = default; SearchFilterByModuleListAndCU &SearchFilterByModuleListAndCU:: operator=(const SearchFilterByModuleListAndCU &rhs) { if (&rhs != this) { m_target_sp = rhs.m_target_sp; m_module_spec_list = rhs.m_module_spec_list; m_cu_spec_list = rhs.m_cu_spec_list; } return *this; } SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default; lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData( Target &target, const StructuredData::Dictionary &data_dict, Error &error) { StructuredData::Array *modules_array = nullptr; SearchFilterSP result_sp; bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), modules_array); FileSpecList modules; if (success) { size_t num_modules = modules_array->GetSize(); for (size_t i = 0; i < num_modules; i++) { std::string module; success = modules_array->GetItemAtIndexAsString(i, module); if (!success) { error.SetErrorStringWithFormat( "SFBM::CFSD: filter module item %zu not a string.", i); return result_sp; } modules.Append(FileSpec(module, false)); } } StructuredData::Array *cus_array = nullptr; success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array); if (!success) { error.SetErrorString("SFBM::CFSD: Could not find the CU list key."); return result_sp; } size_t num_cus = cus_array->GetSize(); FileSpecList cus; for (size_t i = 0; i < num_cus; i++) { std::string cu; success = cus_array->GetItemAtIndexAsString(i, cu); if (!success) { error.SetErrorStringWithFormat( "SFBM::CFSD: filter cu item %zu not a string.", i); return nullptr; } cus.Append(FileSpec(cu, false)); } return SearchFilterSP(new SearchFilterByModuleListAndCU( target.shared_from_this(), modules, cus)); } StructuredData::ObjectSP SearchFilterByModuleListAndCU::SerializeToStructuredData() { StructuredData::DictionarySP options_dict_sp( new StructuredData::Dictionary()); SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp); SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list); return WrapOptionsDict(options_dict_sp); } bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) { return true; } bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) { return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX; } bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) { bool in_cu_list = m_cu_spec_list.FindFileIndex(0, compUnit, false) != UINT32_MAX; if (in_cu_list) { ModuleSP module_sp(compUnit.GetModule()); if (module_sp) { bool module_passes = SearchFilterByModuleList::ModulePasses(module_sp); return module_passes; } else return true; } else return false; } void SearchFilterByModuleListAndCU::Search(Searcher &searcher) { if (!m_target_sp) return; if (searcher.GetDepth() == Searcher::eDepthTarget) { SymbolContext empty_sc; empty_sc.target_sp = m_target_sp; searcher.SearchCallback(*this, empty_sc, nullptr, false); } // If the module file spec is a full path, then we can just find the one // filespec that passes. Otherwise, we need to go through all modules and // find the ones that match the file name. ModuleList matching_modules; const ModuleList &target_images = m_target_sp->GetImages(); std::lock_guard guard(target_images.GetMutex()); const size_t num_modules = target_images.GetSize(); bool no_modules_in_filter = m_module_spec_list.GetSize() == 0; for (size_t i = 0; i < num_modules; i++) { lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i); if (no_modules_in_filter || m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != UINT32_MAX) { SymbolContext matchingContext(m_target_sp, module_sp); Searcher::CallbackReturn shouldContinue; if (searcher.GetDepth() == Searcher::eDepthModule) { shouldContinue = DoModuleIteration(matchingContext, searcher); if (shouldContinue == Searcher::eCallbackReturnStop) return; } else { const size_t num_cu = module_sp->GetNumCompileUnits(); for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) { CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx); matchingContext.comp_unit = cu_sp.get(); if (matchingContext.comp_unit) { if (m_cu_spec_list.FindFileIndex(0, *matchingContext.comp_unit, false) != UINT32_MAX) { shouldContinue = DoCUIteration(module_sp, matchingContext, searcher); if (shouldContinue == Searcher::eCallbackReturnStop) return; } } } } } } } void SearchFilterByModuleListAndCU::GetDescription(Stream *s) { size_t num_modules = m_module_spec_list.GetSize(); if (num_modules == 1) { s->Printf(", module = "); if (s->GetVerbose()) { char buffer[2048]; m_module_spec_list.GetFileSpecAtIndex(0).GetPath(buffer, 2047); s->PutCString(buffer); } else { s->PutCString( m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString( "")); } } else if (num_modules > 0) { s->Printf(", modules(%" PRIu64 ") = ", static_cast(num_modules)); for (size_t i = 0; i < num_modules; i++) { if (s->GetVerbose()) { char buffer[2048]; m_module_spec_list.GetFileSpecAtIndex(i).GetPath(buffer, 2047); s->PutCString(buffer); } else { s->PutCString( m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString( "")); } if (i != num_modules - 1) s->PutCString(", "); } } } uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() { return eSymbolContextModule | eSymbolContextCompUnit; } void SearchFilterByModuleListAndCU::Dump(Stream *s) const {} lldb::SearchFilterSP SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) { SearchFilterSP ret_sp(new SearchFilterByModuleListAndCU(*this)); return ret_sp; }