1 //===-- ModuleList.cpp ------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Core/ModuleList.h" 11 12 // C Includes 13 #include <stdint.h> 14 15 // C++ Includes 16 #include <mutex> // std::once 17 18 // Other libraries and framework includes 19 // Project includes 20 #include "lldb/Core/Log.h" 21 #include "lldb/Core/Module.h" 22 #include "lldb/Core/ModuleSpec.h" 23 #include "lldb/Host/Host.h" 24 #include "lldb/Host/Symbols.h" 25 #include "lldb/Symbol/ObjectFile.h" 26 #include "lldb/Symbol/VariableList.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 //---------------------------------------------------------------------- 32 // ModuleList constructor 33 //---------------------------------------------------------------------- 34 ModuleList::ModuleList() : 35 m_modules(), 36 m_modules_mutex (Mutex::eMutexTypeRecursive), 37 m_notifier(NULL) 38 { 39 } 40 41 //---------------------------------------------------------------------- 42 // Copy constructor 43 //---------------------------------------------------------------------- 44 ModuleList::ModuleList(const ModuleList& rhs) : 45 m_modules(), 46 m_modules_mutex (Mutex::eMutexTypeRecursive), 47 m_notifier(NULL) 48 { 49 Mutex::Locker lhs_locker(m_modules_mutex); 50 Mutex::Locker rhs_locker(rhs.m_modules_mutex); 51 m_modules = rhs.m_modules; 52 } 53 54 ModuleList::ModuleList (ModuleList::Notifier* notifier) : 55 m_modules(), 56 m_modules_mutex (Mutex::eMutexTypeRecursive), 57 m_notifier(notifier) 58 { 59 } 60 61 //---------------------------------------------------------------------- 62 // Assignment operator 63 //---------------------------------------------------------------------- 64 const ModuleList& 65 ModuleList::operator= (const ModuleList& rhs) 66 { 67 if (this != &rhs) 68 { 69 // That's probably me nit-picking, but in theoretical situation: 70 // 71 // * that two threads A B and 72 // * two ModuleList's x y do opposite assignments ie.: 73 // 74 // in thread A: | in thread B: 75 // x = y; | y = x; 76 // 77 // This establishes correct(same) lock taking order and thus 78 // avoids priority inversion. 79 if (uintptr_t(this) > uintptr_t(&rhs)) 80 { 81 Mutex::Locker lhs_locker(m_modules_mutex); 82 Mutex::Locker rhs_locker(rhs.m_modules_mutex); 83 m_modules = rhs.m_modules; 84 } 85 else 86 { 87 Mutex::Locker rhs_locker(rhs.m_modules_mutex); 88 Mutex::Locker lhs_locker(m_modules_mutex); 89 m_modules = rhs.m_modules; 90 } 91 } 92 return *this; 93 } 94 95 //---------------------------------------------------------------------- 96 // Destructor 97 //---------------------------------------------------------------------- 98 ModuleList::~ModuleList() 99 { 100 } 101 102 void 103 ModuleList::AppendImpl (const ModuleSP &module_sp, bool use_notifier) 104 { 105 if (module_sp) 106 { 107 Mutex::Locker locker(m_modules_mutex); 108 m_modules.push_back(module_sp); 109 if (use_notifier && m_notifier) 110 m_notifier->ModuleAdded(*this, module_sp); 111 } 112 } 113 114 void 115 ModuleList::Append (const ModuleSP &module_sp) 116 { 117 AppendImpl (module_sp); 118 } 119 120 void 121 ModuleList::ReplaceEquivalent (const ModuleSP &module_sp) 122 { 123 if (module_sp) 124 { 125 Mutex::Locker locker(m_modules_mutex); 126 127 // First remove any equivalent modules. Equivalent modules are modules 128 // whose path, platform path and architecture match. 129 ModuleSpec equivalent_module_spec (module_sp->GetFileSpec(), module_sp->GetArchitecture()); 130 equivalent_module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec(); 131 132 size_t idx = 0; 133 while (idx < m_modules.size()) 134 { 135 ModuleSP module_sp (m_modules[idx]); 136 if (module_sp->MatchesModuleSpec (equivalent_module_spec)) 137 RemoveImpl(m_modules.begin() + idx); 138 else 139 ++idx; 140 } 141 // Now add the new module to the list 142 Append(module_sp); 143 } 144 } 145 146 bool 147 ModuleList::AppendIfNeeded (const ModuleSP &module_sp) 148 { 149 if (module_sp) 150 { 151 Mutex::Locker locker(m_modules_mutex); 152 collection::iterator pos, end = m_modules.end(); 153 for (pos = m_modules.begin(); pos != end; ++pos) 154 { 155 if (pos->get() == module_sp.get()) 156 return false; // Already in the list 157 } 158 // Only push module_sp on the list if it wasn't already in there. 159 Append(module_sp); 160 return true; 161 } 162 return false; 163 } 164 165 void 166 ModuleList::Append (const ModuleList& module_list) 167 { 168 for (auto pos : module_list.m_modules) 169 Append(pos); 170 } 171 172 bool 173 ModuleList::AppendIfNeeded (const ModuleList& module_list) 174 { 175 bool any_in = false; 176 for (auto pos : module_list.m_modules) 177 { 178 if (AppendIfNeeded(pos)) 179 any_in = true; 180 } 181 return any_in; 182 } 183 184 bool 185 ModuleList::RemoveImpl (const ModuleSP &module_sp, bool use_notifier) 186 { 187 if (module_sp) 188 { 189 Mutex::Locker locker(m_modules_mutex); 190 collection::iterator pos, end = m_modules.end(); 191 for (pos = m_modules.begin(); pos != end; ++pos) 192 { 193 if (pos->get() == module_sp.get()) 194 { 195 m_modules.erase (pos); 196 if (use_notifier && m_notifier) 197 m_notifier->ModuleRemoved(*this, module_sp); 198 return true; 199 } 200 } 201 } 202 return false; 203 } 204 205 ModuleList::collection::iterator 206 ModuleList::RemoveImpl (ModuleList::collection::iterator pos, bool use_notifier) 207 { 208 ModuleSP module_sp(*pos); 209 collection::iterator retval = m_modules.erase(pos); 210 if (use_notifier && m_notifier) 211 m_notifier->ModuleRemoved(*this, module_sp); 212 return retval; 213 } 214 215 bool 216 ModuleList::Remove (const ModuleSP &module_sp) 217 { 218 return RemoveImpl (module_sp); 219 } 220 221 bool 222 ModuleList::ReplaceModule (const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp) 223 { 224 if (!RemoveImpl(old_module_sp, false)) 225 return false; 226 AppendImpl (new_module_sp, false); 227 if (m_notifier) 228 m_notifier->ModuleUpdated(*this, old_module_sp,new_module_sp); 229 return true; 230 } 231 232 bool 233 ModuleList::RemoveIfOrphaned (const Module *module_ptr) 234 { 235 if (module_ptr) 236 { 237 Mutex::Locker locker(m_modules_mutex); 238 collection::iterator pos, end = m_modules.end(); 239 for (pos = m_modules.begin(); pos != end; ++pos) 240 { 241 if (pos->get() == module_ptr) 242 { 243 if (pos->unique()) 244 { 245 pos = RemoveImpl(pos); 246 return true; 247 } 248 else 249 return false; 250 } 251 } 252 } 253 return false; 254 } 255 256 size_t 257 ModuleList::RemoveOrphans (bool mandatory) 258 { 259 Mutex::Locker locker; 260 261 if (mandatory) 262 { 263 locker.Lock (m_modules_mutex); 264 } 265 else 266 { 267 // Not mandatory, remove orphans if we can get the mutex 268 if (!locker.TryLock(m_modules_mutex)) 269 return 0; 270 } 271 collection::iterator pos = m_modules.begin(); 272 size_t remove_count = 0; 273 while (pos != m_modules.end()) 274 { 275 if (pos->unique()) 276 { 277 pos = RemoveImpl(pos); 278 ++remove_count; 279 } 280 else 281 { 282 ++pos; 283 } 284 } 285 return remove_count; 286 } 287 288 size_t 289 ModuleList::Remove (ModuleList &module_list) 290 { 291 Mutex::Locker locker(m_modules_mutex); 292 size_t num_removed = 0; 293 collection::iterator pos, end = module_list.m_modules.end(); 294 for (pos = module_list.m_modules.begin(); pos != end; ++pos) 295 { 296 if (Remove (*pos)) 297 ++num_removed; 298 } 299 return num_removed; 300 } 301 302 303 void 304 ModuleList::Clear() 305 { 306 ClearImpl(); 307 } 308 309 void 310 ModuleList::Destroy() 311 { 312 ClearImpl(); 313 } 314 315 void 316 ModuleList::ClearImpl (bool use_notifier) 317 { 318 Mutex::Locker locker(m_modules_mutex); 319 if (use_notifier && m_notifier) 320 m_notifier->WillClearList(*this); 321 m_modules.clear(); 322 } 323 324 Module* 325 ModuleList::GetModulePointerAtIndex (size_t idx) const 326 { 327 Mutex::Locker locker(m_modules_mutex); 328 return GetModulePointerAtIndexUnlocked(idx); 329 } 330 331 Module* 332 ModuleList::GetModulePointerAtIndexUnlocked (size_t idx) const 333 { 334 if (idx < m_modules.size()) 335 return m_modules[idx].get(); 336 return NULL; 337 } 338 339 ModuleSP 340 ModuleList::GetModuleAtIndex(size_t idx) const 341 { 342 Mutex::Locker locker(m_modules_mutex); 343 return GetModuleAtIndexUnlocked(idx); 344 } 345 346 ModuleSP 347 ModuleList::GetModuleAtIndexUnlocked(size_t idx) const 348 { 349 ModuleSP module_sp; 350 if (idx < m_modules.size()) 351 module_sp = m_modules[idx]; 352 return module_sp; 353 } 354 355 size_t 356 ModuleList::FindFunctions (const ConstString &name, 357 uint32_t name_type_mask, 358 bool include_symbols, 359 bool include_inlines, 360 bool append, 361 SymbolContextList &sc_list) const 362 { 363 if (!append) 364 sc_list.Clear(); 365 366 const size_t old_size = sc_list.GetSize(); 367 368 if (name_type_mask & eFunctionNameTypeAuto) 369 { 370 ConstString lookup_name; 371 uint32_t lookup_name_type_mask = 0; 372 bool match_name_after_lookup = false; 373 Module::PrepareForFunctionNameLookup (name, name_type_mask, 374 eLanguageTypeUnknown, // TODO: add support 375 lookup_name, 376 lookup_name_type_mask, 377 match_name_after_lookup); 378 379 Mutex::Locker locker(m_modules_mutex); 380 collection::const_iterator pos, end = m_modules.end(); 381 for (pos = m_modules.begin(); pos != end; ++pos) 382 { 383 (*pos)->FindFunctions (lookup_name, 384 NULL, 385 lookup_name_type_mask, 386 include_symbols, 387 include_inlines, 388 true, 389 sc_list); 390 } 391 392 if (match_name_after_lookup) 393 { 394 SymbolContext sc; 395 size_t i = old_size; 396 while (i<sc_list.GetSize()) 397 { 398 if (sc_list.GetContextAtIndex(i, sc)) 399 { 400 const char *func_name = sc.GetFunctionName().GetCString(); 401 if (func_name && strstr (func_name, name.GetCString()) == NULL) 402 { 403 // Remove the current context 404 sc_list.RemoveContextAtIndex(i); 405 // Don't increment i and continue in the loop 406 continue; 407 } 408 } 409 ++i; 410 } 411 } 412 413 } 414 else 415 { 416 Mutex::Locker locker(m_modules_mutex); 417 collection::const_iterator pos, end = m_modules.end(); 418 for (pos = m_modules.begin(); pos != end; ++pos) 419 { 420 (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list); 421 } 422 } 423 return sc_list.GetSize() - old_size; 424 } 425 426 size_t 427 ModuleList::FindFunctionSymbols (const ConstString &name, 428 uint32_t name_type_mask, 429 SymbolContextList& sc_list) 430 { 431 const size_t old_size = sc_list.GetSize(); 432 433 if (name_type_mask & eFunctionNameTypeAuto) 434 { 435 ConstString lookup_name; 436 uint32_t lookup_name_type_mask = 0; 437 bool match_name_after_lookup = false; 438 Module::PrepareForFunctionNameLookup (name, name_type_mask, 439 eLanguageTypeUnknown, // TODO: add support 440 lookup_name, 441 lookup_name_type_mask, 442 match_name_after_lookup); 443 444 Mutex::Locker locker(m_modules_mutex); 445 collection::const_iterator pos, end = m_modules.end(); 446 for (pos = m_modules.begin(); pos != end; ++pos) 447 { 448 (*pos)->FindFunctionSymbols (lookup_name, 449 lookup_name_type_mask, 450 sc_list); 451 } 452 453 if (match_name_after_lookup) 454 { 455 SymbolContext sc; 456 size_t i = old_size; 457 while (i<sc_list.GetSize()) 458 { 459 if (sc_list.GetContextAtIndex(i, sc)) 460 { 461 const char *func_name = sc.GetFunctionName().GetCString(); 462 if (func_name && strstr (func_name, name.GetCString()) == NULL) 463 { 464 // Remove the current context 465 sc_list.RemoveContextAtIndex(i); 466 // Don't increment i and continue in the loop 467 continue; 468 } 469 } 470 ++i; 471 } 472 } 473 474 } 475 else 476 { 477 Mutex::Locker locker(m_modules_mutex); 478 collection::const_iterator pos, end = m_modules.end(); 479 for (pos = m_modules.begin(); pos != end; ++pos) 480 { 481 (*pos)->FindFunctionSymbols (name, name_type_mask, sc_list); 482 } 483 } 484 485 return sc_list.GetSize() - old_size; 486 } 487 488 489 size_t 490 ModuleList::FindFunctions(const RegularExpression &name, 491 bool include_symbols, 492 bool include_inlines, 493 bool append, 494 SymbolContextList& sc_list) 495 { 496 const size_t old_size = sc_list.GetSize(); 497 498 Mutex::Locker locker(m_modules_mutex); 499 collection::const_iterator pos, end = m_modules.end(); 500 for (pos = m_modules.begin(); pos != end; ++pos) 501 { 502 (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list); 503 } 504 505 return sc_list.GetSize() - old_size; 506 } 507 508 size_t 509 ModuleList::FindCompileUnits (const FileSpec &path, 510 bool append, 511 SymbolContextList &sc_list) const 512 { 513 if (!append) 514 sc_list.Clear(); 515 516 Mutex::Locker locker(m_modules_mutex); 517 collection::const_iterator pos, end = m_modules.end(); 518 for (pos = m_modules.begin(); pos != end; ++pos) 519 { 520 (*pos)->FindCompileUnits (path, true, sc_list); 521 } 522 523 return sc_list.GetSize(); 524 } 525 526 size_t 527 ModuleList::FindGlobalVariables (const ConstString &name, 528 bool append, 529 size_t max_matches, 530 VariableList& variable_list) const 531 { 532 size_t initial_size = variable_list.GetSize(); 533 Mutex::Locker locker(m_modules_mutex); 534 collection::const_iterator pos, end = m_modules.end(); 535 for (pos = m_modules.begin(); pos != end; ++pos) 536 { 537 (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list); 538 } 539 return variable_list.GetSize() - initial_size; 540 } 541 542 543 size_t 544 ModuleList::FindGlobalVariables (const RegularExpression& regex, 545 bool append, 546 size_t max_matches, 547 VariableList& variable_list) const 548 { 549 size_t initial_size = variable_list.GetSize(); 550 Mutex::Locker locker(m_modules_mutex); 551 collection::const_iterator pos, end = m_modules.end(); 552 for (pos = m_modules.begin(); pos != end; ++pos) 553 { 554 (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list); 555 } 556 return variable_list.GetSize() - initial_size; 557 } 558 559 560 size_t 561 ModuleList::FindSymbolsWithNameAndType (const ConstString &name, 562 SymbolType symbol_type, 563 SymbolContextList &sc_list, 564 bool append) const 565 { 566 Mutex::Locker locker(m_modules_mutex); 567 if (!append) 568 sc_list.Clear(); 569 size_t initial_size = sc_list.GetSize(); 570 571 collection::const_iterator pos, end = m_modules.end(); 572 for (pos = m_modules.begin(); pos != end; ++pos) 573 (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list); 574 return sc_list.GetSize() - initial_size; 575 } 576 577 size_t 578 ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, 579 lldb::SymbolType symbol_type, 580 SymbolContextList &sc_list, 581 bool append) const 582 { 583 Mutex::Locker locker(m_modules_mutex); 584 if (!append) 585 sc_list.Clear(); 586 size_t initial_size = sc_list.GetSize(); 587 588 collection::const_iterator pos, end = m_modules.end(); 589 for (pos = m_modules.begin(); pos != end; ++pos) 590 (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list); 591 return sc_list.GetSize() - initial_size; 592 } 593 594 size_t 595 ModuleList::FindModules (const ModuleSpec &module_spec, ModuleList& matching_module_list) const 596 { 597 size_t existing_matches = matching_module_list.GetSize(); 598 599 Mutex::Locker locker(m_modules_mutex); 600 collection::const_iterator pos, end = m_modules.end(); 601 for (pos = m_modules.begin(); pos != end; ++pos) 602 { 603 ModuleSP module_sp(*pos); 604 if (module_sp->MatchesModuleSpec (module_spec)) 605 matching_module_list.Append(module_sp); 606 } 607 return matching_module_list.GetSize() - existing_matches; 608 } 609 610 ModuleSP 611 ModuleList::FindModule (const Module *module_ptr) const 612 { 613 ModuleSP module_sp; 614 615 // Scope for "locker" 616 { 617 Mutex::Locker locker(m_modules_mutex); 618 collection::const_iterator pos, end = m_modules.end(); 619 620 for (pos = m_modules.begin(); pos != end; ++pos) 621 { 622 if ((*pos).get() == module_ptr) 623 { 624 module_sp = (*pos); 625 break; 626 } 627 } 628 } 629 return module_sp; 630 631 } 632 633 ModuleSP 634 ModuleList::FindModule (const UUID &uuid) const 635 { 636 ModuleSP module_sp; 637 638 if (uuid.IsValid()) 639 { 640 Mutex::Locker locker(m_modules_mutex); 641 collection::const_iterator pos, end = m_modules.end(); 642 643 for (pos = m_modules.begin(); pos != end; ++pos) 644 { 645 if ((*pos)->GetUUID() == uuid) 646 { 647 module_sp = (*pos); 648 break; 649 } 650 } 651 } 652 return module_sp; 653 } 654 655 656 size_t 657 ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, size_t max_matches, TypeList& types) const 658 { 659 Mutex::Locker locker(m_modules_mutex); 660 661 size_t total_matches = 0; 662 collection::const_iterator pos, end = m_modules.end(); 663 if (sc.module_sp) 664 { 665 // The symbol context "sc" contains a module so we want to search that 666 // one first if it is in our list... 667 for (pos = m_modules.begin(); pos != end; ++pos) 668 { 669 if (sc.module_sp.get() == (*pos).get()) 670 { 671 total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types); 672 673 if (total_matches >= max_matches) 674 break; 675 } 676 } 677 } 678 679 if (total_matches < max_matches) 680 { 681 SymbolContext world_sc; 682 for (pos = m_modules.begin(); pos != end; ++pos) 683 { 684 // Search the module if the module is not equal to the one in the symbol 685 // context "sc". If "sc" contains a empty module shared pointer, then 686 // the comparison will always be true (valid_module_ptr != NULL). 687 if (sc.module_sp.get() != (*pos).get()) 688 total_matches += (*pos)->FindTypes (world_sc, name, name_is_fully_qualified, max_matches, types); 689 690 if (total_matches >= max_matches) 691 break; 692 } 693 } 694 695 return total_matches; 696 } 697 698 bool 699 ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const 700 { 701 Mutex::Locker locker(m_modules_mutex); 702 collection::const_iterator pos, end = m_modules.end(); 703 for (pos = m_modules.begin(); pos != end; ++pos) 704 { 705 if ((*pos)->FindSourceFile (orig_spec, new_spec)) 706 return true; 707 } 708 return false; 709 } 710 711 void 712 ModuleList::FindAddressesForLine (const lldb::TargetSP target_sp, 713 const FileSpec &file, uint32_t line, 714 Function *function, 715 std::vector<Address> &output_local, std::vector<Address> &output_extern) 716 { 717 Mutex::Locker locker(m_modules_mutex); 718 collection::const_iterator pos, end = m_modules.end(); 719 for (pos = m_modules.begin(); pos != end; ++pos) 720 { 721 (*pos)->FindAddressesForLine(target_sp, file, line, function, output_local, output_extern); 722 } 723 } 724 725 ModuleSP 726 ModuleList::FindFirstModule (const ModuleSpec &module_spec) const 727 { 728 ModuleSP module_sp; 729 Mutex::Locker locker(m_modules_mutex); 730 collection::const_iterator pos, end = m_modules.end(); 731 for (pos = m_modules.begin(); pos != end; ++pos) 732 { 733 ModuleSP module_sp(*pos); 734 if (module_sp->MatchesModuleSpec (module_spec)) 735 return module_sp; 736 } 737 return module_sp; 738 739 } 740 741 size_t 742 ModuleList::GetSize() const 743 { 744 size_t size = 0; 745 { 746 Mutex::Locker locker(m_modules_mutex); 747 size = m_modules.size(); 748 } 749 return size; 750 } 751 752 753 void 754 ModuleList::Dump(Stream *s) const 755 { 756 // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); 757 // s.Indent(); 758 // s << "ModuleList\n"; 759 760 Mutex::Locker locker(m_modules_mutex); 761 collection::const_iterator pos, end = m_modules.end(); 762 for (pos = m_modules.begin(); pos != end; ++pos) 763 { 764 (*pos)->Dump(s); 765 } 766 } 767 768 void 769 ModuleList::LogUUIDAndPaths (Log *log, const char *prefix_cstr) 770 { 771 if (log) 772 { 773 Mutex::Locker locker(m_modules_mutex); 774 collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end(); 775 for (pos = begin; pos != end; ++pos) 776 { 777 Module *module = pos->get(); 778 const FileSpec &module_file_spec = module->GetFileSpec(); 779 log->Printf ("%s[%u] %s (%s) \"%s\"", 780 prefix_cstr ? prefix_cstr : "", 781 (uint32_t)std::distance (begin, pos), 782 module->GetUUID().GetAsString().c_str(), 783 module->GetArchitecture().GetArchitectureName(), 784 module_file_spec.GetPath().c_str()); 785 } 786 } 787 } 788 789 bool 790 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) const 791 { 792 Mutex::Locker locker(m_modules_mutex); 793 collection::const_iterator pos, end = m_modules.end(); 794 for (pos = m_modules.begin(); pos != end; ++pos) 795 { 796 if ((*pos)->ResolveFileAddress (vm_addr, so_addr)) 797 return true; 798 } 799 800 return false; 801 } 802 803 uint32_t 804 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) const 805 { 806 // The address is already section offset so it has a module 807 uint32_t resolved_flags = 0; 808 ModuleSP module_sp (so_addr.GetModule()); 809 if (module_sp) 810 { 811 resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr, 812 resolve_scope, 813 sc); 814 } 815 else 816 { 817 Mutex::Locker locker(m_modules_mutex); 818 collection::const_iterator pos, end = m_modules.end(); 819 for (pos = m_modules.begin(); pos != end; ++pos) 820 { 821 resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr, 822 resolve_scope, 823 sc); 824 if (resolved_flags != 0) 825 break; 826 } 827 } 828 829 return resolved_flags; 830 } 831 832 uint32_t 833 ModuleList::ResolveSymbolContextForFilePath 834 ( 835 const char *file_path, 836 uint32_t line, 837 bool check_inlines, 838 uint32_t resolve_scope, 839 SymbolContextList& sc_list 840 ) const 841 { 842 FileSpec file_spec(file_path, false); 843 return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 844 } 845 846 uint32_t 847 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) const 848 { 849 Mutex::Locker locker(m_modules_mutex); 850 collection::const_iterator pos, end = m_modules.end(); 851 for (pos = m_modules.begin(); pos != end; ++pos) 852 { 853 (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 854 } 855 856 return sc_list.GetSize(); 857 } 858 859 size_t 860 ModuleList::GetIndexForModule (const Module *module) const 861 { 862 if (module) 863 { 864 Mutex::Locker locker(m_modules_mutex); 865 collection::const_iterator pos; 866 collection::const_iterator begin = m_modules.begin(); 867 collection::const_iterator end = m_modules.end(); 868 for (pos = begin; pos != end; ++pos) 869 { 870 if ((*pos).get() == module) 871 return std::distance (begin, pos); 872 } 873 } 874 return LLDB_INVALID_INDEX32; 875 } 876 877 static ModuleList & 878 GetSharedModuleList () 879 { 880 static ModuleList *g_shared_module_list = NULL; 881 static std::once_flag g_once_flag; 882 std::call_once(g_once_flag, [](){ 883 // NOTE: Intentionally leak the module list so a program doesn't have to 884 // cleanup all modules and object files as it exits. This just wastes time 885 // doing a bunch of cleanup that isn't required. 886 if (g_shared_module_list == NULL) 887 g_shared_module_list = new ModuleList(); // <--- Intentional leak!!! 888 }); 889 return *g_shared_module_list; 890 } 891 892 bool 893 ModuleList::ModuleIsInCache (const Module *module_ptr) 894 { 895 if (module_ptr) 896 { 897 ModuleList &shared_module_list = GetSharedModuleList (); 898 return shared_module_list.FindModule (module_ptr).get() != NULL; 899 } 900 return false; 901 } 902 903 size_t 904 ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list) 905 { 906 return GetSharedModuleList ().FindModules (module_spec, matching_module_list); 907 } 908 909 size_t 910 ModuleList::RemoveOrphanSharedModules (bool mandatory) 911 { 912 return GetSharedModuleList ().RemoveOrphans(mandatory); 913 } 914 915 Error 916 ModuleList::GetSharedModule 917 ( 918 const ModuleSpec &module_spec, 919 ModuleSP &module_sp, 920 const FileSpecList *module_search_paths_ptr, 921 ModuleSP *old_module_sp_ptr, 922 bool *did_create_ptr, 923 bool always_create 924 ) 925 { 926 ModuleList &shared_module_list = GetSharedModuleList (); 927 Mutex::Locker locker(shared_module_list.m_modules_mutex); 928 char path[PATH_MAX]; 929 930 Error error; 931 932 module_sp.reset(); 933 934 if (did_create_ptr) 935 *did_create_ptr = false; 936 if (old_module_sp_ptr) 937 old_module_sp_ptr->reset(); 938 939 const UUID *uuid_ptr = module_spec.GetUUIDPtr(); 940 const FileSpec &module_file_spec = module_spec.GetFileSpec(); 941 const ArchSpec &arch = module_spec.GetArchitecture(); 942 943 // Make sure no one else can try and get or create a module while this 944 // function is actively working on it by doing an extra lock on the 945 // global mutex list. 946 if (always_create == false) 947 { 948 ModuleList matching_module_list; 949 const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list); 950 if (num_matching_modules > 0) 951 { 952 for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) 953 { 954 module_sp = matching_module_list.GetModuleAtIndex(module_idx); 955 956 // Make sure the file for the module hasn't been modified 957 if (module_sp->FileHasChanged()) 958 { 959 if (old_module_sp_ptr && !old_module_sp_ptr->get()) 960 *old_module_sp_ptr = module_sp; 961 962 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES)); 963 if (log) 964 log->Printf("module changed: %p, removing from global module list", 965 static_cast<void*>(module_sp.get())); 966 967 shared_module_list.Remove (module_sp); 968 module_sp.reset(); 969 } 970 else 971 { 972 // The module matches and the module was not modified from 973 // when it was last loaded. 974 return error; 975 } 976 } 977 } 978 } 979 980 if (module_sp) 981 return error; 982 983 module_sp.reset (new Module (module_spec)); 984 // Make sure there are a module and an object file since we can specify 985 // a valid file path with an architecture that might not be in that file. 986 // By getting the object file we can guarantee that the architecture matches 987 if (module_sp->GetObjectFile()) 988 { 989 // If we get in here we got the correct arch, now we just need 990 // to verify the UUID if one was given 991 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) 992 { 993 module_sp.reset(); 994 } 995 else 996 { 997 if (module_sp->GetObjectFile() && module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) 998 { 999 module_sp.reset(); 1000 } 1001 else 1002 { 1003 if (did_create_ptr) 1004 { 1005 *did_create_ptr = true; 1006 } 1007 1008 shared_module_list.ReplaceEquivalent(module_sp); 1009 return error; 1010 } 1011 } 1012 } 1013 else 1014 { 1015 module_sp.reset(); 1016 } 1017 1018 if (module_search_paths_ptr) 1019 { 1020 const auto num_directories = module_search_paths_ptr->GetSize(); 1021 for (size_t idx = 0; idx < num_directories; ++idx) 1022 { 1023 auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx); 1024 if (!search_path_spec.ResolvePath()) 1025 continue; 1026 if (!search_path_spec.Exists() || !search_path_spec.IsDirectory()) 1027 continue; 1028 search_path_spec.AppendPathComponent(module_spec.GetFileSpec().GetFilename().AsCString()); 1029 if (!search_path_spec.Exists()) 1030 continue; 1031 1032 auto resolved_module_spec(module_spec); 1033 resolved_module_spec.GetFileSpec() = search_path_spec; 1034 module_sp.reset (new Module (resolved_module_spec)); 1035 if (module_sp->GetObjectFile()) 1036 { 1037 // If we get in here we got the correct arch, now we just need 1038 // to verify the UUID if one was given 1039 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) 1040 { 1041 module_sp.reset(); 1042 } 1043 else 1044 { 1045 if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) 1046 { 1047 module_sp.reset(); 1048 } 1049 else 1050 { 1051 if (did_create_ptr) 1052 *did_create_ptr = true; 1053 1054 shared_module_list.ReplaceEquivalent(module_sp); 1055 return Error(); 1056 } 1057 } 1058 } 1059 else 1060 { 1061 module_sp.reset(); 1062 } 1063 } 1064 } 1065 1066 // Either the file didn't exist where at the path, or no path was given, so 1067 // we now have to use more extreme measures to try and find the appropriate 1068 // module. 1069 1070 // Fixup the incoming path in case the path points to a valid file, yet 1071 // the arch or UUID (if one was passed in) don't match. 1072 ModuleSpec located_binary_modulespec = Symbols::LocateExecutableObjectFile (module_spec); 1073 1074 // Don't look for the file if it appears to be the same one we already 1075 // checked for above... 1076 if (located_binary_modulespec.GetFileSpec() != module_file_spec) 1077 { 1078 if (!located_binary_modulespec.GetFileSpec().Exists()) 1079 { 1080 located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); 1081 if (path[0] == '\0') 1082 module_file_spec.GetPath(path, sizeof(path)); 1083 // How can this check ever be true? This branch it is false, and we haven't modified file_spec. 1084 if (located_binary_modulespec.GetFileSpec().Exists()) 1085 { 1086 std::string uuid_str; 1087 if (uuid_ptr && uuid_ptr->IsValid()) 1088 uuid_str = uuid_ptr->GetAsString(); 1089 1090 if (arch.IsValid()) 1091 { 1092 if (!uuid_str.empty()) 1093 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_str.c_str()); 1094 else 1095 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName()); 1096 } 1097 } 1098 else 1099 { 1100 error.SetErrorStringWithFormat("'%s' does not exist", path); 1101 } 1102 if (error.Fail()) 1103 module_sp.reset(); 1104 return error; 1105 } 1106 1107 1108 // Make sure no one else can try and get or create a module while this 1109 // function is actively working on it by doing an extra lock on the 1110 // global mutex list. 1111 ModuleSpec platform_module_spec(module_spec); 1112 platform_module_spec.GetFileSpec() = located_binary_modulespec.GetFileSpec(); 1113 platform_module_spec.GetPlatformFileSpec() = located_binary_modulespec.GetFileSpec(); 1114 platform_module_spec.GetSymbolFileSpec() = located_binary_modulespec.GetSymbolFileSpec(); 1115 ModuleList matching_module_list; 1116 if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0) 1117 { 1118 module_sp = matching_module_list.GetModuleAtIndex(0); 1119 1120 // If we didn't have a UUID in mind when looking for the object file, 1121 // then we should make sure the modification time hasn't changed! 1122 if (platform_module_spec.GetUUIDPtr() == NULL) 1123 { 1124 TimeValue file_spec_mod_time(located_binary_modulespec.GetFileSpec().GetModificationTime()); 1125 if (file_spec_mod_time.IsValid()) 1126 { 1127 if (file_spec_mod_time != module_sp->GetModificationTime()) 1128 { 1129 if (old_module_sp_ptr) 1130 *old_module_sp_ptr = module_sp; 1131 shared_module_list.Remove (module_sp); 1132 module_sp.reset(); 1133 } 1134 } 1135 } 1136 } 1137 1138 if (module_sp.get() == NULL) 1139 { 1140 module_sp.reset (new Module (platform_module_spec)); 1141 // Make sure there are a module and an object file since we can specify 1142 // a valid file path with an architecture that might not be in that file. 1143 // By getting the object file we can guarantee that the architecture matches 1144 if (module_sp && module_sp->GetObjectFile()) 1145 { 1146 if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) 1147 { 1148 module_sp.reset(); 1149 } 1150 else 1151 { 1152 if (did_create_ptr) 1153 *did_create_ptr = true; 1154 1155 shared_module_list.ReplaceEquivalent(module_sp); 1156 } 1157 } 1158 else 1159 { 1160 located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); 1161 1162 if (located_binary_modulespec.GetFileSpec()) 1163 { 1164 if (arch.IsValid()) 1165 error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); 1166 else 1167 error.SetErrorStringWithFormat("unable to open '%s'", path); 1168 } 1169 else 1170 { 1171 std::string uuid_str; 1172 if (uuid_ptr && uuid_ptr->IsValid()) 1173 uuid_str = uuid_ptr->GetAsString(); 1174 1175 if (!uuid_str.empty()) 1176 error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_str.c_str()); 1177 else 1178 error.SetErrorStringWithFormat("cannot locate a module"); 1179 } 1180 } 1181 } 1182 } 1183 1184 return error; 1185 } 1186 1187 bool 1188 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) 1189 { 1190 return GetSharedModuleList ().Remove (module_sp); 1191 } 1192 1193 bool 1194 ModuleList::RemoveSharedModuleIfOrphaned (const Module *module_ptr) 1195 { 1196 return GetSharedModuleList ().RemoveIfOrphaned (module_ptr); 1197 } 1198 1199 bool 1200 ModuleList::LoadScriptingResourcesInTarget (Target *target, 1201 std::list<Error>& errors, 1202 Stream *feedback_stream, 1203 bool continue_on_error) 1204 { 1205 if (!target) 1206 return false; 1207 Mutex::Locker locker(m_modules_mutex); 1208 for (auto module : m_modules) 1209 { 1210 Error error; 1211 if (module) 1212 { 1213 if (!module->LoadScriptingResourceInTarget(target, error, feedback_stream)) 1214 { 1215 if (error.Fail() && error.AsCString()) 1216 { 1217 error.SetErrorStringWithFormat("unable to load scripting data for module %s - error reported was %s", 1218 module->GetFileSpec().GetFileNameStrippingExtension().GetCString(), 1219 error.AsCString()); 1220 errors.push_back(error); 1221 1222 if (!continue_on_error) 1223 return false; 1224 } 1225 } 1226 } 1227 } 1228 return errors.size() == 0; 1229 } 1230 1231 void 1232 ModuleList::ForEach (std::function <bool (const ModuleSP &module_sp)> const &callback) const 1233 { 1234 Mutex::Locker locker(m_modules_mutex); 1235 for (const auto &module : m_modules) 1236 { 1237 // If the callback returns false, then stop iterating and break out 1238 if (!callback (module)) 1239 break; 1240 } 1241 } 1242