SearchFilter.cpp revision 360784
1//===-- SearchFilter.cpp ----------------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "lldb/Core/SearchFilter.h" 10 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" 22 23#include "llvm/ADT/StringRef.h" 24#include "llvm/Support/ErrorHandling.h" 25 26#include <memory> 27#include <mutex> 28#include <string> 29 30#include <inttypes.h> 31#include <string.h> 32 33namespace lldb_private { 34class Address; 35} 36namespace lldb_private { 37class Function; 38} 39 40using namespace lldb; 41using namespace lldb_private; 42 43const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception", 44 "Module", "Modules", 45 "ModulesAndCU", "Unknown"}; 46 47const char 48 *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = { 49 "ModuleList", "CUList"}; 50 51const char *SearchFilter::FilterTyToName(enum FilterTy type) { 52 if (type > LastKnownFilterType) 53 return g_ty_to_name[UnknownFilter]; 54 55 return g_ty_to_name[type]; 56} 57 58SearchFilter::FilterTy SearchFilter::NameToFilterTy(llvm::StringRef name) { 59 for (size_t i = 0; i <= LastKnownFilterType; i++) { 60 if (name == g_ty_to_name[i]) 61 return (FilterTy)i; 62 } 63 return UnknownFilter; 64} 65 66Searcher::Searcher() = default; 67 68Searcher::~Searcher() = default; 69 70void Searcher::GetDescription(Stream *s) {} 71 72SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType) 73 : m_target_sp(target_sp), SubclassID(filterType) {} 74 75SearchFilter::~SearchFilter() = default; 76 77SearchFilterSP SearchFilter::CreateFromStructuredData( 78 Target &target, const StructuredData::Dictionary &filter_dict, 79 Status &error) { 80 SearchFilterSP result_sp; 81 if (!filter_dict.IsValid()) { 82 error.SetErrorString("Can't deserialize from an invalid data object."); 83 return result_sp; 84 } 85 86 llvm::StringRef subclass_name; 87 88 bool success = filter_dict.GetValueForKeyAsString( 89 GetSerializationSubclassKey(), subclass_name); 90 if (!success) { 91 error.SetErrorStringWithFormat("Filter data missing subclass key"); 92 return result_sp; 93 } 94 95 FilterTy filter_type = NameToFilterTy(subclass_name); 96 if (filter_type == UnknownFilter) { 97 error.SetErrorStringWithFormatv("Unknown filter type: {0}.", subclass_name); 98 return result_sp; 99 } 100 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."); 106 return result_sp; 107 } 108 109 switch (filter_type) { 110 case Unconstrained: 111 result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData( 112 target, *subclass_options, error); 113 break; 114 case ByModule: 115 result_sp = SearchFilterByModule::CreateFromStructuredData( 116 target, *subclass_options, error); 117 break; 118 case ByModules: 119 result_sp = SearchFilterByModuleList::CreateFromStructuredData( 120 target, *subclass_options, error); 121 break; 122 case ByModulesAndCU: 123 result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData( 124 target, *subclass_options, error); 125 break; 126 case Exception: 127 error.SetErrorString("Can't serialize exception breakpoints yet."); 128 break; 129 default: 130 llvm_unreachable("Should never get an uresolvable filter type."); 131 } 132 133 return result_sp; 134} 135 136bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; } 137 138bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; } 139 140bool SearchFilter::AddressPasses(Address &address) { return true; } 141 142bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; } 143 144bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; } 145 146bool 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); 152} 153 154 155uint32_t SearchFilter::GetFilterRequiredItems() { 156 return (lldb::SymbolContextItem)0; 157} 158 159void SearchFilter::GetDescription(Stream *s) {} 160 161void SearchFilter::Dump(Stream *s) const {} 162 163lldb::SearchFilterSP SearchFilter::CopyForBreakpoint(Breakpoint &breakpoint) { 164 SearchFilterSP ret_sp = DoCopyForBreakpoint(breakpoint); 165 TargetSP target_sp = breakpoint.GetTargetSP(); 166 ret_sp->SetTarget(target_sp); 167 return ret_sp; 168} 169 170// Helper functions for serialization. 171 172StructuredData::DictionarySP 173SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) { 174 if (!options_dict_sp || !options_dict_sp->IsValid()) 175 return StructuredData::DictionarySP(); 176 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); 180 181 return type_dict_sp; 182} 183 184void SearchFilter::SerializeFileSpecList( 185 StructuredData::DictionarySP &options_dict_sp, OptionNames name, 186 FileSpecList &file_list) { 187 size_t num_modules = file_list.GetSize(); 188 189 // Don't serialize empty lists. 190 if (num_modules == 0) 191 return; 192 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())); 197 } 198 options_dict_sp->AddItem(GetKey(name), module_array_sp); 199} 200 201// UTILITY Functions to help iterate down through the elements of the 202// SymbolContext. 203 204void SearchFilter::Search(Searcher &searcher) { 205 SymbolContext empty_sc; 206 207 if (!m_target_sp) 208 return; 209 empty_sc.target_sp = m_target_sp; 210 211 if (searcher.GetDepth() == lldb::eSearchDepthTarget) { 212 searcher.SearchCallback(*this, empty_sc, nullptr); 213 return; 214 } 215 216 DoModuleIteration(empty_sc, searcher); 217} 218 219void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) { 220 SymbolContext empty_sc; 221 222 if (!m_target_sp) 223 return; 224 empty_sc.target_sp = m_target_sp; 225 226 if (searcher.GetDepth() == lldb::eSearchDepthTarget) { 227 searcher.SearchCallback(*this, empty_sc, nullptr); 228 return; 229 } 230 231 std::lock_guard<std::recursive_mutex> guard(modules.GetMutex()); 232 const size_t numModules = modules.GetSize(); 233 234 for (size_t i = 0; i < numModules; i++) { 235 ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i)); 236 if (!ModulePasses(module_sp)) 237 continue; 238 if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop) 239 return; 240 } 241} 242 243Searcher::CallbackReturn 244SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp, 245 Searcher &searcher) { 246 SymbolContext matchingContext(m_target_sp, module_sp); 247 return DoModuleIteration(matchingContext, searcher); 248} 249 250Searcher::CallbackReturn 251SearchFilter::DoModuleIteration(const SymbolContext &context, 252 Searcher &searcher) { 253 if (searcher.GetDepth() < lldb::eSearchDepthModule) 254 return Searcher::eCallbackReturnContinue; 255 256 if (context.module_sp) { 257 if (searcher.GetDepth() != lldb::eSearchDepthModule) 258 return DoCUIteration(context.module_sp, context, searcher); 259 260 SymbolContext matchingContext(context.module_sp.get()); 261 searcher.SearchCallback(*this, matchingContext, nullptr); 262 return Searcher::eCallbackReturnContinue; 263 } 264 265 const ModuleList &target_images = m_target_sp->GetImages(); 266 std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); 267 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)) 274 continue; 275 276 if (searcher.GetDepth() == lldb::eSearchDepthModule) { 277 SymbolContext matchingContext(m_target_sp, module_sp); 278 279 Searcher::CallbackReturn shouldContinue = 280 searcher.SearchCallback(*this, matchingContext, nullptr); 281 if (shouldContinue == Searcher::eCallbackReturnStop || 282 shouldContinue == Searcher::eCallbackReturnPop) 283 return shouldContinue; 284 } else { 285 Searcher::CallbackReturn shouldContinue = 286 DoCUIteration(module_sp, context, searcher); 287 if (shouldContinue == Searcher::eCallbackReturnStop) 288 return shouldContinue; 289 else if (shouldContinue == Searcher::eCallbackReturnPop) 290 continue; 291 } 292 } 293 294 return Searcher::eCallbackReturnContinue; 295} 296 297Searcher::CallbackReturn 298SearchFilter::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); 305 } 306 return Searcher::eCallbackReturnContinue; 307 } 308 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)); 312 if (!cu_sp) 313 continue; 314 if (!CompUnitPasses(*(cu_sp.get()))) 315 continue; 316 317 if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) { 318 SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get()); 319 320 shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr); 321 322 if (shouldContinue == Searcher::eCallbackReturnPop) 323 return Searcher::eCallbackReturnContinue; 324 else if (shouldContinue == Searcher::eCallbackReturnStop) 325 return shouldContinue; 326 continue; 327 } 328 329 // First make sure this compile unit's functions are parsed 330 // since CompUnit::ForeachFunction only iterates over already 331 // parsed functions. 332 SymbolFile *sym_file = module_sp->GetSymbolFile(); 333 if (!sym_file) 334 continue; 335 if (!sym_file->ParseFunctions(*cu_sp)) 336 continue; 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(), 343 func_sp.get()); 344 shouldContinue = 345 searcher.SearchCallback(*this, matchingContext, nullptr); 346 } else { 347 shouldContinue = DoFunctionIteration(func_sp.get(), context, searcher); 348 } 349 return shouldContinue != Searcher::eCallbackReturnContinue; 350 }); 351 } 352 return Searcher::eCallbackReturnContinue; 353} 354 355Searcher::CallbackReturn SearchFilter::DoFunctionIteration( 356 Function *function, const SymbolContext &context, Searcher &searcher) { 357 // FIXME: Implement... 358 return Searcher::eCallbackReturnContinue; 359} 360 361// SearchFilterForUnconstrainedSearches: 362// Selects a shared library matching a given file spec, consulting the targets 363// "black list". 364SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData( 365 Target &target, const StructuredData::Dictionary &data_dict, 366 Status &error) { 367 // No options for an unconstrained search. 368 return std::make_shared<SearchFilterForUnconstrainedSearches>( 369 target.shared_from_this()); 370} 371 372StructuredData::ObjectSP 373SearchFilterForUnconstrainedSearches::SerializeToStructuredData() { 374 // The options dictionary is an empty dictionary: 375 auto result_sp = std::make_shared<StructuredData::Dictionary>(); 376 return WrapOptionsDict(result_sp); 377} 378 379bool SearchFilterForUnconstrainedSearches::ModulePasses( 380 const FileSpec &module_spec) { 381 return !m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec); 382} 383 384bool SearchFilterForUnconstrainedSearches::ModulePasses( 385 const lldb::ModuleSP &module_sp) { 386 if (!module_sp) 387 return true; 388 else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp)) 389 return false; 390 return true; 391} 392 393lldb::SearchFilterSP SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint( 394 Breakpoint &breakpoint) { 395 return std::make_shared<SearchFilterForUnconstrainedSearches>(*this); 396} 397 398// SearchFilterByModule: 399// Selects a shared library matching a given file spec 400 401SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp, 402 const FileSpec &module) 403 : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {} 404 405SearchFilterByModule::~SearchFilterByModule() = default; 406 407bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) { 408 return (module_sp && 409 FileSpec::Match(m_module_spec, module_sp->GetFileSpec())); 410} 411 412bool SearchFilterByModule::ModulePasses(const FileSpec &spec) { 413 return FileSpec::Match(m_module_spec, spec); 414} 415 416bool SearchFilterByModule::AddressPasses(Address &address) { 417 // FIXME: Not yet implemented 418 return true; 419} 420 421bool SearchFilterByModule::CompUnitPasses(FileSpec &fileSpec) { return true; } 422 423bool SearchFilterByModule::CompUnitPasses(CompileUnit &compUnit) { 424 return true; 425} 426 427void SearchFilterByModule::Search(Searcher &searcher) { 428 if (!m_target_sp) 429 return; 430 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); 435 } 436 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. 440 441 const ModuleList &target_modules = m_target_sp->GetImages(); 442 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); 443 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; 450 451 shouldContinue = DoModuleIteration(matchingContext, searcher); 452 if (shouldContinue == Searcher::eCallbackReturnStop) 453 return; 454 } 455 } 456} 457 458void SearchFilterByModule::GetDescription(Stream *s) { 459 s->PutCString(", module = "); 460 s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>")); 461} 462 463uint32_t SearchFilterByModule::GetFilterRequiredItems() { 464 return eSymbolContextModule; 465} 466 467void SearchFilterByModule::Dump(Stream *s) const {} 468 469lldb::SearchFilterSP 470SearchFilterByModule::DoCopyForBreakpoint(Breakpoint &breakpoint) { 471 return std::make_shared<SearchFilterByModule>(*this); 472} 473 474SearchFilterSP SearchFilterByModule::CreateFromStructuredData( 475 Target &target, const StructuredData::Dictionary &data_dict, 476 Status &error) { 477 StructuredData::Array *modules_array; 478 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), 479 modules_array); 480 if (!success) { 481 error.SetErrorString("SFBM::CFSD: Could not find the module list key."); 482 return nullptr; 483 } 484 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."); 489 return nullptr; 490 } 491 492 llvm::StringRef module; 493 success = modules_array->GetItemAtIndexAsString(0, module); 494 if (!success) { 495 error.SetErrorString("SFBM::CFSD: filter module item not a string."); 496 return nullptr; 497 } 498 FileSpec module_spec(module); 499 500 return std::make_shared<SearchFilterByModule>(target.shared_from_this(), 501 module_spec); 502} 503 504StructuredData::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); 511} 512 513// SearchFilterByModuleList: 514// Selects a shared library matching a given file spec 515 516SearchFilterByModuleList::SearchFilterByModuleList( 517 const lldb::TargetSP &target_sp, const FileSpecList &module_list) 518 : SearchFilter(target_sp, FilterTy::ByModules), 519 m_module_spec_list(module_list) {} 520 521SearchFilterByModuleList::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) {} 525 526SearchFilterByModuleList::~SearchFilterByModuleList() = default; 527 528bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) { 529 if (m_module_spec_list.GetSize() == 0) 530 return true; 531 532 return module_sp && m_module_spec_list.FindFileIndex( 533 0, module_sp->GetFileSpec(), false) != UINT32_MAX; 534} 535 536bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) { 537 if (m_module_spec_list.GetSize() == 0) 538 return true; 539 540 return m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX; 541} 542 543bool SearchFilterByModuleList::AddressPasses(Address &address) { 544 // FIXME: Not yet implemented 545 return true; 546} 547 548bool SearchFilterByModuleList::CompUnitPasses(FileSpec &fileSpec) { 549 return true; 550} 551 552bool SearchFilterByModuleList::CompUnitPasses(CompileUnit &compUnit) { 553 return true; 554} 555 556void SearchFilterByModuleList::Search(Searcher &searcher) { 557 if (!m_target_sp) 558 return; 559 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); 564 } 565 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. 569 570 const ModuleList &target_modules = m_target_sp->GetImages(); 571 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); 572 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) == 577 UINT32_MAX) 578 continue; 579 SymbolContext matchingContext(m_target_sp, module->shared_from_this()); 580 Searcher::CallbackReturn shouldContinue; 581 582 shouldContinue = DoModuleIteration(matchingContext, searcher); 583 if (shouldContinue == Searcher::eCallbackReturnStop) 584 return; 585 } 586} 587 588void SearchFilterByModuleList::GetDescription(Stream *s) { 589 size_t num_modules = m_module_spec_list.GetSize(); 590 if (num_modules == 1) { 591 s->Printf(", module = "); 592 s->PutCString( 593 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString( 594 "<Unknown>")); 595 return; 596 } 597 598 s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules); 599 for (size_t i = 0; i < num_modules; i++) { 600 s->PutCString( 601 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString( 602 "<Unknown>")); 603 if (i != num_modules - 1) 604 s->PutCString(", "); 605 } 606} 607 608uint32_t SearchFilterByModuleList::GetFilterRequiredItems() { 609 return eSymbolContextModule; 610} 611 612void SearchFilterByModuleList::Dump(Stream *s) const {} 613 614lldb::SearchFilterSP 615SearchFilterByModuleList::DoCopyForBreakpoint(Breakpoint &breakpoint) { 616 return std::make_shared<SearchFilterByModuleList>(*this); 617} 618 619SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData( 620 Target &target, const StructuredData::Dictionary &data_dict, 621 Status &error) { 622 StructuredData::Array *modules_array; 623 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), 624 modules_array); 625 626 if (!success) 627 return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(), 628 FileSpecList{}); 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); 634 if (!success) { 635 error.SetErrorStringWithFormat( 636 "SFBM::CFSD: filter module item %zu not a string.", i); 637 return nullptr; 638 } 639 modules.EmplaceBack(module); 640 } 641 return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(), 642 modules); 643} 644 645void SearchFilterByModuleList::SerializeUnwrapped( 646 StructuredData::DictionarySP &options_dict_sp) { 647 SerializeFileSpecList(options_dict_sp, OptionNames::ModList, 648 m_module_spec_list); 649} 650 651StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() { 652 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>(); 653 SerializeUnwrapped(options_dict_sp); 654 return WrapOptionsDict(options_dict_sp); 655} 656 657// SearchFilterByModuleListAndCU: 658// Selects a shared library matching a given file spec 659 660SearchFilterByModuleListAndCU::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) {} 666 667SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default; 668 669lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData( 670 Target &target, const StructuredData::Dictionary &data_dict, 671 Status &error) { 672 StructuredData::Array *modules_array = nullptr; 673 SearchFilterSP result_sp; 674 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), 675 modules_array); 676 FileSpecList modules; 677 if (success) { 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); 682 if (!success) { 683 error.SetErrorStringWithFormat( 684 "SFBM::CFSD: filter module item %zu not a string.", i); 685 return result_sp; 686 } 687 modules.EmplaceBack(module); 688 } 689 } 690 691 StructuredData::Array *cus_array = nullptr; 692 success = 693 data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array); 694 if (!success) { 695 error.SetErrorString("SFBM::CFSD: Could not find the CU list key."); 696 return result_sp; 697 } 698 699 size_t num_cus = cus_array->GetSize(); 700 FileSpecList cus; 701 for (size_t i = 0; i < num_cus; i++) { 702 llvm::StringRef cu; 703 success = cus_array->GetItemAtIndexAsString(i, cu); 704 if (!success) { 705 error.SetErrorStringWithFormat( 706 "SFBM::CFSD: filter CU item %zu not a string.", i); 707 return nullptr; 708 } 709 cus.EmplaceBack(cu); 710 } 711 712 return std::make_shared<SearchFilterByModuleListAndCU>( 713 target.shared_from_this(), modules, cus); 714} 715 716StructuredData::ObjectSP 717SearchFilterByModuleListAndCU::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); 722} 723 724bool 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. 730 } 731 FileSpec cu_spec; 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); 737} 738 739bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) { 740 return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX; 741} 742 743bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) { 744 bool in_cu_list = m_cu_spec_list.FindFileIndex(0, compUnit.GetPrimaryFile(), 745 false) != UINT32_MAX; 746 if (!in_cu_list) 747 return false; 748 749 ModuleSP module_sp(compUnit.GetModule()); 750 if (!module_sp) 751 return true; 752 753 return SearchFilterByModuleList::ModulePasses(module_sp); 754} 755 756void SearchFilterByModuleListAndCU::Search(Searcher &searcher) { 757 if (!m_target_sp) 758 return; 759 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); 764 } 765 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. 769 770 ModuleList matching_modules; 771 const ModuleList &target_images = m_target_sp->GetImages(); 772 std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); 773 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) == 780 UINT32_MAX) 781 continue; 782 783 SymbolContext matchingContext(m_target_sp, module_sp); 784 Searcher::CallbackReturn shouldContinue; 785 786 if (searcher.GetDepth() == lldb::eSearchDepthModule) { 787 shouldContinue = DoModuleIteration(matchingContext, searcher); 788 if (shouldContinue == Searcher::eCallbackReturnStop) 789 return; 790 continue; 791 } 792 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) 798 continue; 799 if (m_cu_spec_list.FindFileIndex( 800 0, matchingContext.comp_unit->GetPrimaryFile(), false) == 801 UINT32_MAX) 802 continue; 803 shouldContinue = DoCUIteration(module_sp, matchingContext, searcher); 804 if (shouldContinue == Searcher::eCallbackReturnStop) 805 return; 806 } 807 } 808} 809 810void SearchFilterByModuleListAndCU::GetDescription(Stream *s) { 811 size_t num_modules = m_module_spec_list.GetSize(); 812 if (num_modules == 1) { 813 s->Printf(", module = "); 814 s->PutCString( 815 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString( 816 "<Unknown>")); 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++) { 820 s->PutCString( 821 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString( 822 "<Unknown>")); 823 if (i != num_modules - 1) 824 s->PutCString(", "); 825 } 826 } 827} 828 829uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() { 830 return eSymbolContextModule | eSymbolContextCompUnit; 831} 832 833void SearchFilterByModuleListAndCU::Dump(Stream *s) const {} 834 835lldb::SearchFilterSP 836SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) { 837 return std::make_shared<SearchFilterByModuleListAndCU>(*this); 838} 839