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::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) 356 { 357 Mutex::Locker locker(m_modules_mutex); 358 359 if (!append) 360 types.Clear(); 361 362 uint32_t total_matches = 0; 363 collection::const_iterator pos, end = m_modules.end(); 364 for (pos = m_modules.begin(); pos != end; ++pos) 365 { 366 if (sc.module_sp.get() == NULL || sc.module_sp.get() == (*pos).get()) 367 total_matches += (*pos)->FindTypes (sc, name, NULL, true, max_matches, types); 368 369 if (total_matches >= max_matches) 370 break; 371 } 372 return total_matches; 373 } 374 375 bool 376 ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const 377 { 378 Mutex::Locker locker(m_modules_mutex); 379 collection::const_iterator pos, end = m_modules.end(); 380 for (pos = m_modules.begin(); pos != end; ++pos) 381 { 382 if ((*pos)->FindSourceFile (orig_spec, new_spec)) 383 return true; 384 } 385 return false; 386 } 387 388 389 390 ModuleSP 391 ModuleList::FindFirstModule (const ModuleSpec &module_spec) 392 { 393 ModuleSP module_sp; 394 Mutex::Locker locker(m_modules_mutex); 395 collection::const_iterator pos, end = m_modules.end(); 396 for (pos = m_modules.begin(); pos != end; ++pos) 397 { 398 ModuleSP module_sp(*pos); 399 if (module_sp->MatchesModuleSpec (module_spec)) 400 return module_sp; 401 } 402 return module_sp; 403 404 } 405 406 size_t 407 ModuleList::GetSize() const 408 { 409 size_t size = 0; 410 { 411 Mutex::Locker locker(m_modules_mutex); 412 size = m_modules.size(); 413 } 414 return size; 415 } 416 417 418 void 419 ModuleList::Dump(Stream *s) const 420 { 421 // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); 422 // s.Indent(); 423 // s << "ModuleList\n"; 424 425 Mutex::Locker locker(m_modules_mutex); 426 collection::const_iterator pos, end = m_modules.end(); 427 for (pos = m_modules.begin(); pos != end; ++pos) 428 { 429 (*pos)->Dump(s); 430 } 431 } 432 433 void 434 ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr) 435 { 436 if (log_sp) 437 { 438 Mutex::Locker locker(m_modules_mutex); 439 char uuid_cstr[256]; 440 collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end(); 441 for (pos = begin; pos != end; ++pos) 442 { 443 Module *module = pos->get(); 444 module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr)); 445 const FileSpec &module_file_spec = module->GetFileSpec(); 446 log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"", 447 prefix_cstr ? prefix_cstr : "", 448 (uint32_t)std::distance (begin, pos), 449 uuid_cstr, 450 module->GetArchitecture().GetArchitectureName(), 451 module_file_spec.GetDirectory().GetCString(), 452 module_file_spec.GetFilename().GetCString()); 453 } 454 } 455 } 456 457 bool 458 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) 459 { 460 Mutex::Locker locker(m_modules_mutex); 461 collection::const_iterator pos, end = m_modules.end(); 462 for (pos = m_modules.begin(); pos != end; ++pos) 463 { 464 if ((*pos)->ResolveFileAddress (vm_addr, so_addr)) 465 return true; 466 } 467 468 return false; 469 } 470 471 uint32_t 472 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) 473 { 474 // The address is already section offset so it has a module 475 uint32_t resolved_flags = 0; 476 ModuleSP module_sp (so_addr.GetModule()); 477 if (module_sp) 478 { 479 resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr, 480 resolve_scope, 481 sc); 482 } 483 else 484 { 485 Mutex::Locker locker(m_modules_mutex); 486 collection::const_iterator pos, end = m_modules.end(); 487 for (pos = m_modules.begin(); pos != end; ++pos) 488 { 489 resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr, 490 resolve_scope, 491 sc); 492 if (resolved_flags != 0) 493 break; 494 } 495 } 496 497 return resolved_flags; 498 } 499 500 uint32_t 501 ModuleList::ResolveSymbolContextForFilePath 502 ( 503 const char *file_path, 504 uint32_t line, 505 bool check_inlines, 506 uint32_t resolve_scope, 507 SymbolContextList& sc_list 508 ) 509 { 510 FileSpec file_spec(file_path, false); 511 return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 512 } 513 514 uint32_t 515 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) 516 { 517 Mutex::Locker locker(m_modules_mutex); 518 collection::const_iterator pos, end = m_modules.end(); 519 for (pos = m_modules.begin(); pos != end; ++pos) 520 { 521 (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 522 } 523 524 return sc_list.GetSize(); 525 } 526 527 uint32_t 528 ModuleList::GetIndexForModule (const Module *module) const 529 { 530 if (module) 531 { 532 Mutex::Locker locker(m_modules_mutex); 533 collection::const_iterator pos; 534 collection::const_iterator begin = m_modules.begin(); 535 collection::const_iterator end = m_modules.end(); 536 for (pos = begin; pos != end; ++pos) 537 { 538 if ((*pos).get() == module) 539 return std::distance (begin, pos); 540 } 541 } 542 return LLDB_INVALID_INDEX32; 543 } 544 545 static ModuleList & 546 GetSharedModuleList () 547 { 548 static ModuleList g_shared_module_list; 549 return g_shared_module_list; 550 } 551 552 bool 553 ModuleList::ModuleIsInCache (const Module *module_ptr) 554 { 555 if (module_ptr) 556 { 557 ModuleList &shared_module_list = GetSharedModuleList (); 558 return shared_module_list.FindModule (module_ptr).get() != NULL; 559 } 560 return false; 561 } 562 563 size_t 564 ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list) 565 { 566 return GetSharedModuleList ().FindModules (module_spec, matching_module_list); 567 } 568 569 uint32_t 570 ModuleList::RemoveOrphanSharedModules () 571 { 572 return GetSharedModuleList ().RemoveOrphans(); 573 } 574 575 Error 576 ModuleList::GetSharedModule 577 ( 578 const ModuleSpec &module_spec, 579 ModuleSP &module_sp, 580 const FileSpecList *module_search_paths_ptr, 581 ModuleSP *old_module_sp_ptr, 582 bool *did_create_ptr, 583 bool always_create 584 ) 585 { 586 ModuleList &shared_module_list = GetSharedModuleList (); 587 Mutex::Locker locker(shared_module_list.m_modules_mutex); 588 char path[PATH_MAX]; 589 char uuid_cstr[64]; 590 591 Error error; 592 593 module_sp.reset(); 594 595 if (did_create_ptr) 596 *did_create_ptr = false; 597 if (old_module_sp_ptr) 598 old_module_sp_ptr->reset(); 599 600 const UUID *uuid_ptr = module_spec.GetUUIDPtr(); 601 const FileSpec &module_file_spec = module_spec.GetFileSpec(); 602 const ArchSpec &arch = module_spec.GetArchitecture(); 603 604 // Make sure no one else can try and get or create a module while this 605 // function is actively working on it by doing an extra lock on the 606 // global mutex list. 607 if (always_create == false) 608 { 609 ModuleList matching_module_list; 610 const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list); 611 if (num_matching_modules > 0) 612 { 613 for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) 614 { 615 module_sp = matching_module_list.GetModuleAtIndex(module_idx); 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 ModuleList matching_module_list; 712 if (shared_module_list.FindModules (module_spec, matching_module_list) > 0) 713 { 714 module_sp = matching_module_list.GetModuleAtIndex(0); 715 716 // If we didn't have a UUID in mind when looking for the object file, 717 // then we should make sure the modification time hasn't changed! 718 if (module_spec.GetUUIDPtr() == NULL) 719 { 720 TimeValue file_spec_mod_time(file_spec.GetModificationTime()); 721 if (file_spec_mod_time.IsValid()) 722 { 723 if (file_spec_mod_time != module_sp->GetModificationTime()) 724 { 725 if (old_module_sp_ptr) 726 *old_module_sp_ptr = module_sp; 727 shared_module_list.Remove (module_sp); 728 module_sp.reset(); 729 } 730 } 731 } 732 } 733 734 if (module_sp.get() == NULL) 735 { 736 module_sp.reset (new Module (module_spec)); 737 // Make sure there are a module and an object file since we can specify 738 // a valid file path with an architecture that might not be in that file. 739 // By getting the object file we can guarantee that the architecture matches 740 if (module_sp && module_sp->GetObjectFile()) 741 { 742 if (did_create_ptr) 743 *did_create_ptr = true; 744 745 shared_module_list.Append(module_sp); 746 } 747 else 748 { 749 file_spec.GetPath(path, sizeof(path)); 750 751 if (file_spec) 752 { 753 if (arch.IsValid()) 754 error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); 755 else 756 error.SetErrorStringWithFormat("unable to open '%s'", path); 757 } 758 else 759 { 760 if (uuid_ptr && uuid_ptr->IsValid()) 761 uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); 762 else 763 uuid_cstr[0] = '\0'; 764 765 if (uuid_cstr[0]) 766 error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr); 767 else 768 error.SetErrorStringWithFormat("cannot locate a module"); 769 } 770 } 771 } 772 } 773 774 return error; 775 } 776 777 bool 778 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) 779 { 780 return GetSharedModuleList ().Remove (module_sp); 781 } 782 783 784