1 //===-- SearchFilter.cpp --------------------------------------------------===// 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 <cinttypes> 31 #include <cstring> 32 33 namespace lldb_private { 34 class Address; 35 } 36 namespace lldb_private { 37 class Function; 38 } 39 40 using namespace lldb; 41 using namespace lldb_private; 42 43 const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception", 44 "Module", "Modules", 45 "ModulesAndCU", "Unknown"}; 46 47 const char 48 *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = { 49 "ModuleList", "CUList"}; 50 51 const 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 58 SearchFilter::FilterTy SearchFilter::NameToFilterTy(llvm::StringRef name) { 59 for (size_t i = 0; i <= LastKnownFilterType; i++) { 60 if (name == g_ty_to_name[i]) 61 return (FilterTy)i; 62 } 63 return UnknownFilter; 64 } 65 66 Searcher::Searcher() = default; 67 68 Searcher::~Searcher() = default; 69 70 void Searcher::GetDescription(Stream *s) {} 71 72 SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType) 73 : m_target_sp(target_sp), SubclassID(filterType) {} 74 75 SearchFilter::~SearchFilter() = default; 76 77 SearchFilterSP SearchFilter::CreateFromStructuredData( 78 const lldb::TargetSP& target_sp, 79 const StructuredData::Dictionary &filter_dict, 80 Status &error) { 81 SearchFilterSP result_sp; 82 if (!filter_dict.IsValid()) { 83 error.SetErrorString("Can't deserialize from an invalid data object."); 84 return result_sp; 85 } 86 87 llvm::StringRef subclass_name; 88 89 bool success = filter_dict.GetValueForKeyAsString( 90 GetSerializationSubclassKey(), subclass_name); 91 if (!success) { 92 error.SetErrorString("Filter data missing subclass key"); 93 return result_sp; 94 } 95 96 FilterTy filter_type = NameToFilterTy(subclass_name); 97 if (filter_type == UnknownFilter) { 98 error.SetErrorStringWithFormatv("Unknown filter type: {0}.", subclass_name); 99 return result_sp; 100 } 101 102 StructuredData::Dictionary *subclass_options = nullptr; 103 success = filter_dict.GetValueForKeyAsDictionary( 104 GetSerializationSubclassOptionsKey(), subclass_options); 105 if (!success || !subclass_options || !subclass_options->IsValid()) { 106 error.SetErrorString("Filter data missing subclass options key."); 107 return result_sp; 108 } 109 110 switch (filter_type) { 111 case Unconstrained: 112 result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData( 113 target_sp, *subclass_options, error); 114 break; 115 case ByModule: 116 result_sp = SearchFilterByModule::CreateFromStructuredData( 117 target_sp, *subclass_options, error); 118 break; 119 case ByModules: 120 result_sp = SearchFilterByModuleList::CreateFromStructuredData( 121 target_sp, *subclass_options, error); 122 break; 123 case ByModulesAndCU: 124 result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData( 125 target_sp, *subclass_options, error); 126 break; 127 case Exception: 128 error.SetErrorString("Can't serialize exception breakpoints yet."); 129 break; 130 default: 131 llvm_unreachable("Should never get an uresolvable filter type."); 132 } 133 134 return result_sp; 135 } 136 137 bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; } 138 139 bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; } 140 141 bool SearchFilter::AddressPasses(Address &address) { return true; } 142 143 bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; } 144 145 bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; } 146 147 bool SearchFilter::FunctionPasses(Function &function) { 148 // This is a slightly cheesy job, but since we don't have finer grained 149 // filters yet, just checking that the start address passes is probably 150 // good enough for the base class behavior. 151 Address addr = function.GetAddressRange().GetBaseAddress(); 152 return AddressPasses(addr); 153 } 154 155 156 uint32_t SearchFilter::GetFilterRequiredItems() { 157 return (lldb::SymbolContextItem)0; 158 } 159 160 void SearchFilter::GetDescription(Stream *s) {} 161 162 void SearchFilter::Dump(Stream *s) const {} 163 164 lldb::SearchFilterSP SearchFilter::CreateCopy(lldb::TargetSP& target_sp) { 165 SearchFilterSP ret_sp = DoCreateCopy(); 166 ret_sp->SetTarget(target_sp); 167 return ret_sp; 168 } 169 170 // Helper functions for serialization. 171 172 StructuredData::DictionarySP 173 SearchFilter::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 184 void 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 204 void 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 219 void 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 for (ModuleSP module_sp : modules.Modules()) { 232 if (!ModulePasses(module_sp)) 233 continue; 234 if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop) 235 return; 236 } 237 } 238 239 Searcher::CallbackReturn 240 SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp, 241 Searcher &searcher) { 242 SymbolContext matchingContext(m_target_sp, module_sp); 243 return DoModuleIteration(matchingContext, searcher); 244 } 245 246 Searcher::CallbackReturn 247 SearchFilter::DoModuleIteration(const SymbolContext &context, 248 Searcher &searcher) { 249 if (searcher.GetDepth() < lldb::eSearchDepthModule) 250 return Searcher::eCallbackReturnContinue; 251 252 if (context.module_sp) { 253 if (searcher.GetDepth() != lldb::eSearchDepthModule) 254 return DoCUIteration(context.module_sp, context, searcher); 255 256 SymbolContext matchingContext(context.module_sp.get()); 257 searcher.SearchCallback(*this, matchingContext, nullptr); 258 return Searcher::eCallbackReturnContinue; 259 } 260 261 for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) { 262 // If this is the last level supplied, then call the callback directly, 263 // otherwise descend. 264 if (!ModulePasses(module_sp)) 265 continue; 266 267 if (searcher.GetDepth() == lldb::eSearchDepthModule) { 268 SymbolContext matchingContext(m_target_sp, module_sp); 269 270 Searcher::CallbackReturn shouldContinue = 271 searcher.SearchCallback(*this, matchingContext, nullptr); 272 if (shouldContinue == Searcher::eCallbackReturnStop || 273 shouldContinue == Searcher::eCallbackReturnPop) 274 return shouldContinue; 275 } else { 276 Searcher::CallbackReturn shouldContinue = 277 DoCUIteration(module_sp, context, searcher); 278 if (shouldContinue == Searcher::eCallbackReturnStop) 279 return shouldContinue; 280 else if (shouldContinue == Searcher::eCallbackReturnPop) 281 continue; 282 } 283 } 284 285 return Searcher::eCallbackReturnContinue; 286 } 287 288 Searcher::CallbackReturn 289 SearchFilter::DoCUIteration(const ModuleSP &module_sp, 290 const SymbolContext &context, Searcher &searcher) { 291 Searcher::CallbackReturn shouldContinue; 292 if (context.comp_unit != nullptr) { 293 if (CompUnitPasses(*context.comp_unit)) { 294 SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit); 295 return searcher.SearchCallback(*this, matchingContext, nullptr); 296 } 297 return Searcher::eCallbackReturnContinue; 298 } 299 300 const size_t num_comp_units = module_sp->GetNumCompileUnits(); 301 for (size_t i = 0; i < num_comp_units; i++) { 302 CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i)); 303 if (!cu_sp) 304 continue; 305 if (!CompUnitPasses(*(cu_sp.get()))) 306 continue; 307 308 if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) { 309 SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get()); 310 311 shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr); 312 313 if (shouldContinue == Searcher::eCallbackReturnPop) 314 return Searcher::eCallbackReturnContinue; 315 else if (shouldContinue == Searcher::eCallbackReturnStop) 316 return shouldContinue; 317 continue; 318 } 319 320 // First make sure this compile unit's functions are parsed 321 // since CompUnit::ForeachFunction only iterates over already 322 // parsed functions. 323 SymbolFile *sym_file = module_sp->GetSymbolFile(); 324 if (!sym_file) 325 continue; 326 if (!sym_file->ParseFunctions(*cu_sp)) 327 continue; 328 // If we got any functions, use ForeachFunction to do the iteration. 329 cu_sp->ForeachFunction([&](const FunctionSP &func_sp) { 330 if (!FunctionPasses(*func_sp.get())) 331 return false; // Didn't pass the filter, just keep going. 332 if (searcher.GetDepth() == lldb::eSearchDepthFunction) { 333 SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get(), 334 func_sp.get()); 335 shouldContinue = 336 searcher.SearchCallback(*this, matchingContext, nullptr); 337 } else { 338 shouldContinue = DoFunctionIteration(func_sp.get(), context, searcher); 339 } 340 return shouldContinue != Searcher::eCallbackReturnContinue; 341 }); 342 } 343 return Searcher::eCallbackReturnContinue; 344 } 345 346 Searcher::CallbackReturn SearchFilter::DoFunctionIteration( 347 Function *function, const SymbolContext &context, Searcher &searcher) { 348 // FIXME: Implement... 349 return Searcher::eCallbackReturnContinue; 350 } 351 352 // SearchFilterForUnconstrainedSearches: 353 // Selects a shared library matching a given file spec, consulting the targets 354 // "black list". 355 SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData( 356 const lldb::TargetSP& target_sp, 357 const StructuredData::Dictionary &data_dict, 358 Status &error) { 359 // No options for an unconstrained search. 360 return std::make_shared<SearchFilterForUnconstrainedSearches>(target_sp); 361 } 362 363 StructuredData::ObjectSP 364 SearchFilterForUnconstrainedSearches::SerializeToStructuredData() { 365 // The options dictionary is an empty dictionary: 366 auto result_sp = std::make_shared<StructuredData::Dictionary>(); 367 return WrapOptionsDict(result_sp); 368 } 369 370 bool SearchFilterForUnconstrainedSearches::ModulePasses( 371 const FileSpec &module_spec) { 372 return !m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec); 373 } 374 375 bool SearchFilterForUnconstrainedSearches::ModulePasses( 376 const lldb::ModuleSP &module_sp) { 377 if (!module_sp) 378 return true; 379 else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp)) 380 return false; 381 return true; 382 } 383 384 SearchFilterSP SearchFilterForUnconstrainedSearches::DoCreateCopy() { 385 return std::make_shared<SearchFilterForUnconstrainedSearches>(*this); 386 } 387 388 // SearchFilterByModule: 389 // Selects a shared library matching a given file spec 390 391 SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp, 392 const FileSpec &module) 393 : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {} 394 395 SearchFilterByModule::~SearchFilterByModule() = default; 396 397 bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) { 398 return (module_sp && 399 FileSpec::Match(m_module_spec, module_sp->GetFileSpec())); 400 } 401 402 bool SearchFilterByModule::ModulePasses(const FileSpec &spec) { 403 return FileSpec::Match(m_module_spec, spec); 404 } 405 406 bool SearchFilterByModule::AddressPasses(Address &address) { 407 // FIXME: Not yet implemented 408 return true; 409 } 410 411 void SearchFilterByModule::Search(Searcher &searcher) { 412 if (!m_target_sp) 413 return; 414 415 if (searcher.GetDepth() == lldb::eSearchDepthTarget) { 416 SymbolContext empty_sc; 417 empty_sc.target_sp = m_target_sp; 418 searcher.SearchCallback(*this, empty_sc, nullptr); 419 } 420 421 // If the module file spec is a full path, then we can just find the one 422 // filespec that passes. Otherwise, we need to go through all modules and 423 // find the ones that match the file name. 424 425 const ModuleList &target_modules = m_target_sp->GetImages(); 426 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); 427 428 for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) { 429 if (FileSpec::Match(m_module_spec, module_sp->GetFileSpec())) { 430 SymbolContext matchingContext(m_target_sp, module_sp); 431 Searcher::CallbackReturn shouldContinue; 432 433 shouldContinue = DoModuleIteration(matchingContext, searcher); 434 if (shouldContinue == Searcher::eCallbackReturnStop) 435 return; 436 } 437 } 438 } 439 440 void SearchFilterByModule::GetDescription(Stream *s) { 441 s->PutCString(", module = "); 442 s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>")); 443 } 444 445 uint32_t SearchFilterByModule::GetFilterRequiredItems() { 446 return eSymbolContextModule; 447 } 448 449 void SearchFilterByModule::Dump(Stream *s) const {} 450 451 SearchFilterSP SearchFilterByModule::DoCreateCopy() { 452 return std::make_shared<SearchFilterByModule>(*this); 453 } 454 455 SearchFilterSP SearchFilterByModule::CreateFromStructuredData( 456 const lldb::TargetSP& target_sp, 457 const StructuredData::Dictionary &data_dict, 458 Status &error) { 459 StructuredData::Array *modules_array; 460 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), 461 modules_array); 462 if (!success) { 463 error.SetErrorString("SFBM::CFSD: Could not find the module list key."); 464 return nullptr; 465 } 466 467 size_t num_modules = modules_array->GetSize(); 468 if (num_modules > 1) { 469 error.SetErrorString( 470 "SFBM::CFSD: Only one modules allowed for SearchFilterByModule."); 471 return nullptr; 472 } 473 474 std::optional<llvm::StringRef> maybe_module = 475 modules_array->GetItemAtIndexAsString(0); 476 if (!maybe_module) { 477 error.SetErrorString("SFBM::CFSD: filter module item not a string."); 478 return nullptr; 479 } 480 FileSpec module_spec(*maybe_module); 481 482 return std::make_shared<SearchFilterByModule>(target_sp, module_spec); 483 } 484 485 StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() { 486 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>(); 487 auto module_array_sp = std::make_shared<StructuredData::Array>(); 488 module_array_sp->AddItem( 489 std::make_shared<StructuredData::String>(m_module_spec.GetPath())); 490 options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp); 491 return WrapOptionsDict(options_dict_sp); 492 } 493 494 // SearchFilterByModuleList: 495 // Selects a shared library matching a given file spec 496 497 SearchFilterByModuleList::SearchFilterByModuleList( 498 const lldb::TargetSP &target_sp, const FileSpecList &module_list) 499 : SearchFilter(target_sp, FilterTy::ByModules), 500 m_module_spec_list(module_list) {} 501 502 SearchFilterByModuleList::SearchFilterByModuleList( 503 const lldb::TargetSP &target_sp, const FileSpecList &module_list, 504 enum FilterTy filter_ty) 505 : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {} 506 507 SearchFilterByModuleList::~SearchFilterByModuleList() = default; 508 509 bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) { 510 if (m_module_spec_list.GetSize() == 0) 511 return true; 512 513 return module_sp && m_module_spec_list.FindFileIndex( 514 0, module_sp->GetFileSpec(), false) != UINT32_MAX; 515 } 516 517 bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) { 518 if (m_module_spec_list.GetSize() == 0) 519 return true; 520 521 return m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX; 522 } 523 524 bool SearchFilterByModuleList::AddressPasses(Address &address) { 525 // FIXME: Not yet implemented 526 return true; 527 } 528 529 void SearchFilterByModuleList::Search(Searcher &searcher) { 530 if (!m_target_sp) 531 return; 532 533 if (searcher.GetDepth() == lldb::eSearchDepthTarget) { 534 SymbolContext empty_sc; 535 empty_sc.target_sp = m_target_sp; 536 searcher.SearchCallback(*this, empty_sc, nullptr); 537 } 538 539 // If the module file spec is a full path, then we can just find the one 540 // filespec that passes. Otherwise, we need to go through all modules and 541 // find the ones that match the file name. 542 for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) { 543 if (m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) == 544 UINT32_MAX) 545 continue; 546 SymbolContext matchingContext(m_target_sp, module_sp); 547 Searcher::CallbackReturn shouldContinue; 548 549 shouldContinue = DoModuleIteration(matchingContext, searcher); 550 if (shouldContinue == Searcher::eCallbackReturnStop) 551 return; 552 } 553 } 554 555 void SearchFilterByModuleList::GetDescription(Stream *s) { 556 size_t num_modules = m_module_spec_list.GetSize(); 557 if (num_modules == 1) { 558 s->Printf(", module = "); 559 s->PutCString( 560 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString( 561 "<Unknown>")); 562 return; 563 } 564 565 s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules); 566 for (size_t i = 0; i < num_modules; i++) { 567 s->PutCString( 568 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString( 569 "<Unknown>")); 570 if (i != num_modules - 1) 571 s->PutCString(", "); 572 } 573 } 574 575 uint32_t SearchFilterByModuleList::GetFilterRequiredItems() { 576 return eSymbolContextModule; 577 } 578 579 void SearchFilterByModuleList::Dump(Stream *s) const {} 580 581 lldb::SearchFilterSP SearchFilterByModuleList::DoCreateCopy() { 582 return std::make_shared<SearchFilterByModuleList>(*this); 583 } 584 585 SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData( 586 const lldb::TargetSP& target_sp, 587 const StructuredData::Dictionary &data_dict, 588 Status &error) { 589 StructuredData::Array *modules_array; 590 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), 591 modules_array); 592 593 if (!success) 594 return std::make_shared<SearchFilterByModuleList>(target_sp, 595 FileSpecList{}); 596 FileSpecList modules; 597 size_t num_modules = modules_array->GetSize(); 598 for (size_t i = 0; i < num_modules; i++) { 599 std::optional<llvm::StringRef> maybe_module = 600 modules_array->GetItemAtIndexAsString(i); 601 if (!maybe_module) { 602 error.SetErrorStringWithFormat( 603 "SFBM::CFSD: filter module item %zu not a string.", i); 604 return nullptr; 605 } 606 modules.EmplaceBack(*maybe_module); 607 } 608 return std::make_shared<SearchFilterByModuleList>(target_sp, modules); 609 } 610 611 void SearchFilterByModuleList::SerializeUnwrapped( 612 StructuredData::DictionarySP &options_dict_sp) { 613 SerializeFileSpecList(options_dict_sp, OptionNames::ModList, 614 m_module_spec_list); 615 } 616 617 StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() { 618 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>(); 619 SerializeUnwrapped(options_dict_sp); 620 return WrapOptionsDict(options_dict_sp); 621 } 622 623 // SearchFilterByModuleListAndCU: 624 // Selects a shared library matching a given file spec 625 626 SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU( 627 const lldb::TargetSP &target_sp, const FileSpecList &module_list, 628 const FileSpecList &cu_list) 629 : SearchFilterByModuleList(target_sp, module_list, 630 FilterTy::ByModulesAndCU), 631 m_cu_spec_list(cu_list) {} 632 633 SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default; 634 635 lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData( 636 const lldb::TargetSP& target_sp, 637 const StructuredData::Dictionary &data_dict, 638 Status &error) { 639 StructuredData::Array *modules_array = nullptr; 640 SearchFilterSP result_sp; 641 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), 642 modules_array); 643 FileSpecList modules; 644 if (success) { 645 size_t num_modules = modules_array->GetSize(); 646 for (size_t i = 0; i < num_modules; i++) { 647 std::optional<llvm::StringRef> maybe_module = 648 modules_array->GetItemAtIndexAsString(i); 649 if (!maybe_module) { 650 error.SetErrorStringWithFormat( 651 "SFBM::CFSD: filter module item %zu not a string.", i); 652 return result_sp; 653 } 654 modules.EmplaceBack(*maybe_module); 655 } 656 } 657 658 StructuredData::Array *cus_array = nullptr; 659 success = 660 data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array); 661 if (!success) { 662 error.SetErrorString("SFBM::CFSD: Could not find the CU list key."); 663 return result_sp; 664 } 665 666 size_t num_cus = cus_array->GetSize(); 667 FileSpecList cus; 668 for (size_t i = 0; i < num_cus; i++) { 669 std::optional<llvm::StringRef> maybe_cu = 670 cus_array->GetItemAtIndexAsString(i); 671 if (!maybe_cu) { 672 error.SetErrorStringWithFormat( 673 "SFBM::CFSD: filter CU item %zu not a string.", i); 674 return nullptr; 675 } 676 cus.EmplaceBack(*maybe_cu); 677 } 678 679 return std::make_shared<SearchFilterByModuleListAndCU>( 680 target_sp, modules, cus); 681 } 682 683 StructuredData::ObjectSP 684 SearchFilterByModuleListAndCU::SerializeToStructuredData() { 685 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>(); 686 SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp); 687 SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list); 688 return WrapOptionsDict(options_dict_sp); 689 } 690 691 bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) { 692 SymbolContext sym_ctx; 693 address.CalculateSymbolContext(&sym_ctx, eSymbolContextEverything); 694 if (!sym_ctx.comp_unit) { 695 if (m_cu_spec_list.GetSize() != 0) 696 return false; // Has no comp_unit so can't pass the file check. 697 } 698 FileSpec cu_spec; 699 if (sym_ctx.comp_unit) 700 cu_spec = sym_ctx.comp_unit->GetPrimaryFile(); 701 if (m_cu_spec_list.FindFileIndex(0, cu_spec, false) == UINT32_MAX) 702 return false; // Fails the file check 703 return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp); 704 } 705 706 bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) { 707 return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX; 708 } 709 710 bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) { 711 bool in_cu_list = m_cu_spec_list.FindFileIndex(0, compUnit.GetPrimaryFile(), 712 false) != UINT32_MAX; 713 if (!in_cu_list) 714 return false; 715 716 ModuleSP module_sp(compUnit.GetModule()); 717 if (!module_sp) 718 return true; 719 720 return SearchFilterByModuleList::ModulePasses(module_sp); 721 } 722 723 void SearchFilterByModuleListAndCU::Search(Searcher &searcher) { 724 if (!m_target_sp) 725 return; 726 727 if (searcher.GetDepth() == lldb::eSearchDepthTarget) { 728 SymbolContext empty_sc; 729 empty_sc.target_sp = m_target_sp; 730 searcher.SearchCallback(*this, empty_sc, nullptr); 731 } 732 733 // If the module file spec is a full path, then we can just find the one 734 // filespec that passes. Otherwise, we need to go through all modules and 735 // find the ones that match the file name. 736 737 ModuleList matching_modules; 738 739 bool no_modules_in_filter = m_module_spec_list.GetSize() == 0; 740 for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) { 741 if (!no_modules_in_filter && 742 m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) == 743 UINT32_MAX) 744 continue; 745 746 SymbolContext matchingContext(m_target_sp, module_sp); 747 Searcher::CallbackReturn shouldContinue; 748 749 if (searcher.GetDepth() == lldb::eSearchDepthModule) { 750 shouldContinue = DoModuleIteration(matchingContext, searcher); 751 if (shouldContinue == Searcher::eCallbackReturnStop) 752 return; 753 continue; 754 } 755 756 const size_t num_cu = module_sp->GetNumCompileUnits(); 757 for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) { 758 CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx); 759 matchingContext.comp_unit = cu_sp.get(); 760 if (!matchingContext.comp_unit) 761 continue; 762 if (m_cu_spec_list.FindFileIndex( 763 0, matchingContext.comp_unit->GetPrimaryFile(), false) == 764 UINT32_MAX) 765 continue; 766 shouldContinue = DoCUIteration(module_sp, matchingContext, searcher); 767 if (shouldContinue == Searcher::eCallbackReturnStop) 768 return; 769 } 770 } 771 } 772 773 void SearchFilterByModuleListAndCU::GetDescription(Stream *s) { 774 size_t num_modules = m_module_spec_list.GetSize(); 775 if (num_modules == 1) { 776 s->Printf(", module = "); 777 s->PutCString( 778 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString( 779 "<Unknown>")); 780 } else if (num_modules > 0) { 781 s->Printf(", modules(%" PRIu64 ") = ", static_cast<uint64_t>(num_modules)); 782 for (size_t i = 0; i < num_modules; i++) { 783 s->PutCString( 784 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString( 785 "<Unknown>")); 786 if (i != num_modules - 1) 787 s->PutCString(", "); 788 } 789 } 790 } 791 792 uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() { 793 return eSymbolContextModule | eSymbolContextCompUnit; 794 } 795 796 void SearchFilterByModuleListAndCU::Dump(Stream *s) const {} 797 798 SearchFilterSP SearchFilterByModuleListAndCU::DoCreateCopy() { 799 return std::make_shared<SearchFilterByModuleListAndCU>(*this); 800 } 801