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 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/Log.h" 17 #include "lldb/Core/Module.h" 18 #include "lldb/Host/Host.h" 19 #include "lldb/Host/Symbols.h" 20 #include "lldb/Symbol/ClangNamespaceDecl.h" 21 #include "lldb/Symbol/ObjectFile.h" 22 #include "lldb/Symbol/VariableList.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 //---------------------------------------------------------------------- 28 // ModuleList constructor 29 //---------------------------------------------------------------------- 30 ModuleList::ModuleList() : 31 m_modules(), 32 m_modules_mutex (Mutex::eMutexTypeRecursive) 33 { 34 } 35 36 //---------------------------------------------------------------------- 37 // Copy constructor 38 //---------------------------------------------------------------------- 39 ModuleList::ModuleList(const ModuleList& rhs) : 40 m_modules(rhs.m_modules) 41 { 42 } 43 44 //---------------------------------------------------------------------- 45 // Assignment operator 46 //---------------------------------------------------------------------- 47 const ModuleList& 48 ModuleList::operator= (const ModuleList& rhs) 49 { 50 if (this != &rhs) 51 { 52 Mutex::Locker locker(m_modules_mutex); 53 m_modules = rhs.m_modules; 54 } 55 return *this; 56 } 57 58 //---------------------------------------------------------------------- 59 // Destructor 60 //---------------------------------------------------------------------- 61 ModuleList::~ModuleList() 62 { 63 } 64 65 void 66 ModuleList::Append (const ModuleSP &module_sp) 67 { 68 if (module_sp) 69 { 70 Mutex::Locker locker(m_modules_mutex); 71 m_modules.push_back(module_sp); 72 } 73 } 74 75 bool 76 ModuleList::AppendIfNeeded (const ModuleSP &module_sp) 77 { 78 if (module_sp) 79 { 80 Mutex::Locker locker(m_modules_mutex); 81 collection::iterator pos, end = m_modules.end(); 82 for (pos = m_modules.begin(); pos != end; ++pos) 83 { 84 if (pos->get() == module_sp.get()) 85 return false; // Already in the list 86 } 87 // Only push module_sp on the list if it wasn't already in there. 88 m_modules.push_back(module_sp); 89 return true; 90 } 91 return false; 92 } 93 94 bool 95 ModuleList::Remove (const ModuleSP &module_sp) 96 { 97 if (module_sp) 98 { 99 Mutex::Locker locker(m_modules_mutex); 100 collection::iterator pos, end = m_modules.end(); 101 for (pos = m_modules.begin(); pos != end; ++pos) 102 { 103 if (pos->get() == module_sp.get()) 104 { 105 m_modules.erase (pos); 106 return true; 107 } 108 } 109 } 110 return false; 111 } 112 113 114 size_t 115 ModuleList::RemoveOrphans () 116 { 117 Mutex::Locker locker(m_modules_mutex); 118 collection::iterator pos = m_modules.begin(); 119 size_t remove_count = 0; 120 while (pos != m_modules.end()) 121 { 122 if (pos->unique()) 123 { 124 pos = m_modules.erase (pos); 125 ++remove_count; 126 } 127 else 128 { 129 ++pos; 130 } 131 } 132 return remove_count; 133 } 134 135 size_t 136 ModuleList::Remove (ModuleList &module_list) 137 { 138 Mutex::Locker locker(m_modules_mutex); 139 size_t num_removed = 0; 140 collection::iterator pos, end = module_list.m_modules.end(); 141 for (pos = module_list.m_modules.begin(); pos != end; ++pos) 142 { 143 if (Remove (*pos)) 144 ++num_removed; 145 } 146 return num_removed; 147 } 148 149 150 151 void 152 ModuleList::Clear() 153 { 154 Mutex::Locker locker(m_modules_mutex); 155 m_modules.clear(); 156 } 157 158 void 159 ModuleList::Destroy() 160 { 161 Mutex::Locker locker(m_modules_mutex); 162 collection empty; 163 m_modules.swap(empty); 164 } 165 166 Module* 167 ModuleList::GetModulePointerAtIndex (uint32_t idx) const 168 { 169 Mutex::Locker locker(m_modules_mutex); 170 if (idx < m_modules.size()) 171 return m_modules[idx].get(); 172 return NULL; 173 } 174 175 ModuleSP 176 ModuleList::GetModuleAtIndex(uint32_t idx) 177 { 178 Mutex::Locker locker(m_modules_mutex); 179 ModuleSP module_sp; 180 if (idx < m_modules.size()) 181 module_sp = m_modules[idx]; 182 return module_sp; 183 } 184 185 uint32_t 186 ModuleList::FindFunctions (const ConstString &name, 187 uint32_t name_type_mask, 188 bool include_symbols, 189 bool include_inlines, 190 bool append, 191 SymbolContextList &sc_list) 192 { 193 if (!append) 194 sc_list.Clear(); 195 196 Mutex::Locker locker(m_modules_mutex); 197 collection::const_iterator pos, end = m_modules.end(); 198 for (pos = m_modules.begin(); pos != end; ++pos) 199 { 200 (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list); 201 } 202 203 return sc_list.GetSize(); 204 } 205 206 uint32_t 207 ModuleList::FindCompileUnits (const FileSpec &path, 208 bool append, 209 SymbolContextList &sc_list) 210 { 211 if (!append) 212 sc_list.Clear(); 213 214 Mutex::Locker locker(m_modules_mutex); 215 collection::const_iterator pos, end = m_modules.end(); 216 for (pos = m_modules.begin(); pos != end; ++pos) 217 { 218 (*pos)->FindCompileUnits (path, true, sc_list); 219 } 220 221 return sc_list.GetSize(); 222 } 223 224 uint32_t 225 ModuleList::FindGlobalVariables (const ConstString &name, 226 bool append, 227 uint32_t max_matches, 228 VariableList& variable_list) 229 { 230 size_t initial_size = variable_list.GetSize(); 231 Mutex::Locker locker(m_modules_mutex); 232 collection::iterator pos, end = m_modules.end(); 233 for (pos = m_modules.begin(); pos != end; ++pos) 234 { 235 (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list); 236 } 237 return variable_list.GetSize() - initial_size; 238 } 239 240 241 uint32_t 242 ModuleList::FindGlobalVariables (const RegularExpression& regex, 243 bool append, 244 uint32_t max_matches, 245 VariableList& variable_list) 246 { 247 size_t initial_size = variable_list.GetSize(); 248 Mutex::Locker locker(m_modules_mutex); 249 collection::iterator pos, end = m_modules.end(); 250 for (pos = m_modules.begin(); pos != end; ++pos) 251 { 252 (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list); 253 } 254 return variable_list.GetSize() - initial_size; 255 } 256 257 258 size_t 259 ModuleList::FindSymbolsWithNameAndType (const ConstString &name, 260 SymbolType symbol_type, 261 SymbolContextList &sc_list, 262 bool append) 263 { 264 Mutex::Locker locker(m_modules_mutex); 265 if (!append) 266 sc_list.Clear(); 267 size_t initial_size = sc_list.GetSize(); 268 269 collection::iterator pos, end = m_modules.end(); 270 for (pos = m_modules.begin(); pos != end; ++pos) 271 (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list); 272 return sc_list.GetSize() - initial_size; 273 } 274 275 size_t 276 ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, 277 lldb::SymbolType symbol_type, 278 SymbolContextList &sc_list, 279 bool append) 280 { 281 Mutex::Locker locker(m_modules_mutex); 282 if (!append) 283 sc_list.Clear(); 284 size_t initial_size = sc_list.GetSize(); 285 286 collection::iterator pos, end = m_modules.end(); 287 for (pos = m_modules.begin(); pos != end; ++pos) 288 (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list); 289 return sc_list.GetSize() - initial_size; 290 } 291 292 size_t 293 ModuleList::FindModules (const ModuleSpec &module_spec, ModuleList& matching_module_list) const 294 { 295 size_t existing_matches = matching_module_list.GetSize(); 296 297 Mutex::Locker locker(m_modules_mutex); 298 collection::const_iterator pos, end = m_modules.end(); 299 for (pos = m_modules.begin(); pos != end; ++pos) 300 { 301 ModuleSP module_sp(*pos); 302 if (module_sp->MatchesModuleSpec (module_spec)) 303 matching_module_list.Append(module_sp); 304 } 305 return matching_module_list.GetSize() - existing_matches; 306 } 307 308 ModuleSP 309 ModuleList::FindModule (const Module *module_ptr) 310 { 311 ModuleSP module_sp; 312 313 // Scope for "locker" 314 { 315 Mutex::Locker locker(m_modules_mutex); 316 collection::const_iterator pos, end = m_modules.end(); 317 318 for (pos = m_modules.begin(); pos != end; ++pos) 319 { 320 if ((*pos).get() == module_ptr) 321 { 322 module_sp = (*pos); 323 break; 324 } 325 } 326 } 327 return module_sp; 328 329 } 330 331 ModuleSP 332 ModuleList::FindModule (const UUID &uuid) 333 { 334 ModuleSP module_sp; 335 336 if (uuid.IsValid()) 337 { 338 Mutex::Locker locker(m_modules_mutex); 339 collection::const_iterator pos, end = m_modules.end(); 340 341 for (pos = m_modules.begin(); pos != end; ++pos) 342 { 343 if ((*pos)->GetUUID() == uuid) 344 { 345 module_sp = (*pos); 346 break; 347 } 348 } 349 } 350 return module_sp; 351 } 352 353 354 uint32_t 355 ModuleList::FindTypes2 (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, uint32_t max_matches, TypeList& types) 356 { 357 Mutex::Locker locker(m_modules_mutex); 358 359 uint32_t total_matches = 0; 360 collection::const_iterator pos, end = m_modules.end(); 361 for (pos = m_modules.begin(); pos != end; ++pos) 362 { 363 if (sc.module_sp.get() == NULL || sc.module_sp.get() == (*pos).get()) 364 total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types); 365 366 if (total_matches >= max_matches) 367 break; 368 } 369 return total_matches; 370 } 371 372 bool 373 ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const 374 { 375 Mutex::Locker locker(m_modules_mutex); 376 collection::const_iterator pos, end = m_modules.end(); 377 for (pos = m_modules.begin(); pos != end; ++pos) 378 { 379 if ((*pos)->FindSourceFile (orig_spec, new_spec)) 380 return true; 381 } 382 return false; 383 } 384 385 386 387 ModuleSP 388 ModuleList::FindFirstModule (const ModuleSpec &module_spec) 389 { 390 ModuleSP module_sp; 391 Mutex::Locker locker(m_modules_mutex); 392 collection::const_iterator pos, end = m_modules.end(); 393 for (pos = m_modules.begin(); pos != end; ++pos) 394 { 395 ModuleSP module_sp(*pos); 396 if (module_sp->MatchesModuleSpec (module_spec)) 397 return module_sp; 398 } 399 return module_sp; 400 401 } 402 403 size_t 404 ModuleList::GetSize() const 405 { 406 size_t size = 0; 407 { 408 Mutex::Locker locker(m_modules_mutex); 409 size = m_modules.size(); 410 } 411 return size; 412 } 413 414 415 void 416 ModuleList::Dump(Stream *s) const 417 { 418 // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); 419 // s.Indent(); 420 // s << "ModuleList\n"; 421 422 Mutex::Locker locker(m_modules_mutex); 423 collection::const_iterator pos, end = m_modules.end(); 424 for (pos = m_modules.begin(); pos != end; ++pos) 425 { 426 (*pos)->Dump(s); 427 } 428 } 429 430 void 431 ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr) 432 { 433 if (log_sp) 434 { 435 Mutex::Locker locker(m_modules_mutex); 436 char uuid_cstr[256]; 437 collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end(); 438 for (pos = begin; pos != end; ++pos) 439 { 440 Module *module = pos->get(); 441 module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr)); 442 const FileSpec &module_file_spec = module->GetFileSpec(); 443 log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"", 444 prefix_cstr ? prefix_cstr : "", 445 (uint32_t)std::distance (begin, pos), 446 uuid_cstr, 447 module->GetArchitecture().GetArchitectureName(), 448 module_file_spec.GetDirectory().GetCString(), 449 module_file_spec.GetFilename().GetCString()); 450 } 451 } 452 } 453 454 bool 455 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) 456 { 457 Mutex::Locker locker(m_modules_mutex); 458 collection::const_iterator pos, end = m_modules.end(); 459 for (pos = m_modules.begin(); pos != end; ++pos) 460 { 461 if ((*pos)->ResolveFileAddress (vm_addr, so_addr)) 462 return true; 463 } 464 465 return false; 466 } 467 468 uint32_t 469 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) 470 { 471 // The address is already section offset so it has a module 472 uint32_t resolved_flags = 0; 473 ModuleSP module_sp (so_addr.GetModule()); 474 if (module_sp) 475 { 476 resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr, 477 resolve_scope, 478 sc); 479 } 480 else 481 { 482 Mutex::Locker locker(m_modules_mutex); 483 collection::const_iterator pos, end = m_modules.end(); 484 for (pos = m_modules.begin(); pos != end; ++pos) 485 { 486 resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr, 487 resolve_scope, 488 sc); 489 if (resolved_flags != 0) 490 break; 491 } 492 } 493 494 return resolved_flags; 495 } 496 497 uint32_t 498 ModuleList::ResolveSymbolContextForFilePath 499 ( 500 const char *file_path, 501 uint32_t line, 502 bool check_inlines, 503 uint32_t resolve_scope, 504 SymbolContextList& sc_list 505 ) 506 { 507 FileSpec file_spec(file_path, false); 508 return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 509 } 510 511 uint32_t 512 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) 513 { 514 Mutex::Locker locker(m_modules_mutex); 515 collection::const_iterator pos, end = m_modules.end(); 516 for (pos = m_modules.begin(); pos != end; ++pos) 517 { 518 (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 519 } 520 521 return sc_list.GetSize(); 522 } 523 524 uint32_t 525 ModuleList::GetIndexForModule (const Module *module) const 526 { 527 if (module) 528 { 529 Mutex::Locker locker(m_modules_mutex); 530 collection::const_iterator pos; 531 collection::const_iterator begin = m_modules.begin(); 532 collection::const_iterator end = m_modules.end(); 533 for (pos = begin; pos != end; ++pos) 534 { 535 if ((*pos).get() == module) 536 return std::distance (begin, pos); 537 } 538 } 539 return LLDB_INVALID_INDEX32; 540 } 541 542 static ModuleList & 543 GetSharedModuleList () 544 { 545 static ModuleList g_shared_module_list; 546 return g_shared_module_list; 547 } 548 549 bool 550 ModuleList::ModuleIsInCache (const Module *module_ptr) 551 { 552 if (module_ptr) 553 { 554 ModuleList &shared_module_list = GetSharedModuleList (); 555 return shared_module_list.FindModule (module_ptr).get() != NULL; 556 } 557 return false; 558 } 559 560 size_t 561 ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list) 562 { 563 return GetSharedModuleList ().FindModules (module_spec, matching_module_list); 564 } 565 566 uint32_t 567 ModuleList::RemoveOrphanSharedModules () 568 { 569 return GetSharedModuleList ().RemoveOrphans(); 570 } 571 572 Error 573 ModuleList::GetSharedModule 574 ( 575 const ModuleSpec &module_spec, 576 ModuleSP &module_sp, 577 const FileSpecList *module_search_paths_ptr, 578 ModuleSP *old_module_sp_ptr, 579 bool *did_create_ptr, 580 bool always_create 581 ) 582 { 583 ModuleList &shared_module_list = GetSharedModuleList (); 584 Mutex::Locker locker(shared_module_list.m_modules_mutex); 585 char path[PATH_MAX]; 586 char uuid_cstr[64]; 587 588 Error error; 589 590 module_sp.reset(); 591 592 if (did_create_ptr) 593 *did_create_ptr = false; 594 if (old_module_sp_ptr) 595 old_module_sp_ptr->reset(); 596 597 const UUID *uuid_ptr = module_spec.GetUUIDPtr(); 598 const FileSpec &module_file_spec = module_spec.GetFileSpec(); 599 const ArchSpec &arch = module_spec.GetArchitecture(); 600 601 // Make sure no one else can try and get or create a module while this 602 // function is actively working on it by doing an extra lock on the 603 // global mutex list. 604 if (always_create == false) 605 { 606 ModuleList matching_module_list; 607 const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list); 608 if (num_matching_modules > 0) 609 { 610 for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) 611 { 612 module_sp = matching_module_list.GetModuleAtIndex(module_idx); 613 // If we had a UUID and we found a match, then that is good enough for a match 614 if (uuid_ptr) 615 break; 616 if (module_file_spec) 617 { 618 // If we didn't have a UUID in mind when looking for the object file, 619 // then we should make sure the modification time hasn't changed! 620 TimeValue file_spec_mod_time(module_file_spec.GetModificationTime()); 621 if (file_spec_mod_time.IsValid()) 622 { 623 if (file_spec_mod_time == module_sp->GetModificationTime()) 624 return error; 625 } 626 } 627 if (old_module_sp_ptr && !old_module_sp_ptr->get()) 628 *old_module_sp_ptr = module_sp; 629 shared_module_list.Remove (module_sp); 630 module_sp.reset(); 631 } 632 } 633 } 634 635 if (module_sp) 636 return error; 637 else 638 { 639 module_sp.reset (new Module (module_spec)); 640 // Make sure there are a module and an object file since we can specify 641 // a valid file path with an architecture that might not be in that file. 642 // By getting the object file we can guarantee that the architecture matches 643 if (module_sp) 644 { 645 if (module_sp->GetObjectFile()) 646 { 647 // If we get in here we got the correct arch, now we just need 648 // to verify the UUID if one was given 649 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) 650 module_sp.reset(); 651 else 652 { 653 if (did_create_ptr) 654 *did_create_ptr = true; 655 656 shared_module_list.Append(module_sp); 657 return error; 658 } 659 } 660 else 661 module_sp.reset(); 662 } 663 } 664 665 // Either the file didn't exist where at the path, or no path was given, so 666 // we now have to use more extreme measures to try and find the appropriate 667 // module. 668 669 // Fixup the incoming path in case the path points to a valid file, yet 670 // the arch or UUID (if one was passed in) don't match. 671 FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec); 672 673 // Don't look for the file if it appears to be the same one we already 674 // checked for above... 675 if (file_spec != module_file_spec) 676 { 677 if (!file_spec.Exists()) 678 { 679 file_spec.GetPath(path, sizeof(path)); 680 if (path[0] == '\0') 681 module_file_spec.GetPath(path, sizeof(path)); 682 if (file_spec.Exists()) 683 { 684 if (uuid_ptr && uuid_ptr->IsValid()) 685 uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); 686 else 687 uuid_cstr[0] = '\0'; 688 689 690 if (arch.IsValid()) 691 { 692 if (uuid_cstr[0]) 693 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr); 694 else 695 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName()); 696 } 697 } 698 else 699 { 700 error.SetErrorStringWithFormat("'%s' does not exist", path); 701 } 702 if (error.Fail()) 703 module_sp.reset(); 704 return error; 705 } 706 707 708 // Make sure no one else can try and get or create a module while this 709 // function is actively working on it by doing an extra lock on the 710 // global mutex list. 711 ModuleSpec platform_module_spec(module_spec); 712 platform_module_spec.GetFileSpec() = file_spec; 713 platform_module_spec.GetPlatformFileSpec() = file_spec; 714 ModuleList matching_module_list; 715 if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0) 716 { 717 module_sp = matching_module_list.GetModuleAtIndex(0); 718 719 // If we didn't have a UUID in mind when looking for the object file, 720 // then we should make sure the modification time hasn't changed! 721 if (platform_module_spec.GetUUIDPtr() == NULL) 722 { 723 TimeValue file_spec_mod_time(file_spec.GetModificationTime()); 724 if (file_spec_mod_time.IsValid()) 725 { 726 if (file_spec_mod_time != module_sp->GetModificationTime()) 727 { 728 if (old_module_sp_ptr) 729 *old_module_sp_ptr = module_sp; 730 shared_module_list.Remove (module_sp); 731 module_sp.reset(); 732 } 733 } 734 } 735 } 736 737 if (module_sp.get() == NULL) 738 { 739 module_sp.reset (new Module (platform_module_spec)); 740 // Make sure there are a module and an object file since we can specify 741 // a valid file path with an architecture that might not be in that file. 742 // By getting the object file we can guarantee that the architecture matches 743 if (module_sp && module_sp->GetObjectFile()) 744 { 745 if (did_create_ptr) 746 *did_create_ptr = true; 747 748 shared_module_list.Append(module_sp); 749 } 750 else 751 { 752 file_spec.GetPath(path, sizeof(path)); 753 754 if (file_spec) 755 { 756 if (arch.IsValid()) 757 error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); 758 else 759 error.SetErrorStringWithFormat("unable to open '%s'", path); 760 } 761 else 762 { 763 if (uuid_ptr && uuid_ptr->IsValid()) 764 uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); 765 else 766 uuid_cstr[0] = '\0'; 767 768 if (uuid_cstr[0]) 769 error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr); 770 else 771 error.SetErrorStringWithFormat("cannot locate a module"); 772 } 773 } 774 } 775 } 776 777 return error; 778 } 779 780 bool 781 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) 782 { 783 return GetSharedModuleList ().Remove (module_sp); 784 } 785 786 787