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 ModuleSP 376 ModuleList::FindFirstModule (const ModuleSpec &module_spec) 377 { 378 ModuleSP module_sp; 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 ModuleSP module_sp(*pos); 384 if (module_sp->MatchesModuleSpec (module_spec)) 385 return module_sp; 386 } 387 return module_sp; 388 389 } 390 391 size_t 392 ModuleList::GetSize() const 393 { 394 size_t size = 0; 395 { 396 Mutex::Locker locker(m_modules_mutex); 397 size = m_modules.size(); 398 } 399 return size; 400 } 401 402 403 void 404 ModuleList::Dump(Stream *s) const 405 { 406 // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); 407 // s.Indent(); 408 // s << "ModuleList\n"; 409 410 Mutex::Locker locker(m_modules_mutex); 411 collection::const_iterator pos, end = m_modules.end(); 412 for (pos = m_modules.begin(); pos != end; ++pos) 413 { 414 (*pos)->Dump(s); 415 } 416 } 417 418 void 419 ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr) 420 { 421 if (log_sp) 422 { 423 Mutex::Locker locker(m_modules_mutex); 424 char uuid_cstr[256]; 425 collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end(); 426 for (pos = begin; pos != end; ++pos) 427 { 428 Module *module = pos->get(); 429 module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr)); 430 const FileSpec &module_file_spec = module->GetFileSpec(); 431 log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"", 432 prefix_cstr ? prefix_cstr : "", 433 (uint32_t)std::distance (begin, pos), 434 uuid_cstr, 435 module->GetArchitecture().GetArchitectureName(), 436 module_file_spec.GetDirectory().GetCString(), 437 module_file_spec.GetFilename().GetCString()); 438 } 439 } 440 } 441 442 bool 443 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) 444 { 445 Mutex::Locker locker(m_modules_mutex); 446 collection::const_iterator pos, end = m_modules.end(); 447 for (pos = m_modules.begin(); pos != end; ++pos) 448 { 449 if ((*pos)->ResolveFileAddress (vm_addr, so_addr)) 450 return true; 451 } 452 453 return false; 454 } 455 456 uint32_t 457 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) 458 { 459 // The address is already section offset so it has a module 460 uint32_t resolved_flags = 0; 461 ModuleSP module_sp (so_addr.GetModule()); 462 if (module_sp) 463 { 464 resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr, 465 resolve_scope, 466 sc); 467 } 468 else 469 { 470 Mutex::Locker locker(m_modules_mutex); 471 collection::const_iterator pos, end = m_modules.end(); 472 for (pos = m_modules.begin(); pos != end; ++pos) 473 { 474 resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr, 475 resolve_scope, 476 sc); 477 if (resolved_flags != 0) 478 break; 479 } 480 } 481 482 return resolved_flags; 483 } 484 485 uint32_t 486 ModuleList::ResolveSymbolContextForFilePath 487 ( 488 const char *file_path, 489 uint32_t line, 490 bool check_inlines, 491 uint32_t resolve_scope, 492 SymbolContextList& sc_list 493 ) 494 { 495 FileSpec file_spec(file_path, false); 496 return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 497 } 498 499 uint32_t 500 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) 501 { 502 Mutex::Locker locker(m_modules_mutex); 503 collection::const_iterator pos, end = m_modules.end(); 504 for (pos = m_modules.begin(); pos != end; ++pos) 505 { 506 (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 507 } 508 509 return sc_list.GetSize(); 510 } 511 512 uint32_t 513 ModuleList::GetIndexForModule (const Module *module) const 514 { 515 if (module) 516 { 517 Mutex::Locker locker(m_modules_mutex); 518 collection::const_iterator pos; 519 collection::const_iterator begin = m_modules.begin(); 520 collection::const_iterator end = m_modules.end(); 521 for (pos = begin; pos != end; ++pos) 522 { 523 if ((*pos).get() == module) 524 return std::distance (begin, pos); 525 } 526 } 527 return LLDB_INVALID_INDEX32; 528 } 529 530 static ModuleList & 531 GetSharedModuleList () 532 { 533 static ModuleList g_shared_module_list; 534 return g_shared_module_list; 535 } 536 537 bool 538 ModuleList::ModuleIsInCache (const Module *module_ptr) 539 { 540 if (module_ptr) 541 { 542 ModuleList &shared_module_list = GetSharedModuleList (); 543 return shared_module_list.FindModule (module_ptr).get() != NULL; 544 } 545 return false; 546 } 547 548 size_t 549 ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list) 550 { 551 return GetSharedModuleList ().FindModules (module_spec, matching_module_list); 552 } 553 554 uint32_t 555 ModuleList::RemoveOrphanSharedModules () 556 { 557 return GetSharedModuleList ().RemoveOrphans(); 558 } 559 560 Error 561 ModuleList::GetSharedModule 562 ( 563 const ModuleSpec &module_spec, 564 ModuleSP &module_sp, 565 const FileSpecList *module_search_paths_ptr, 566 ModuleSP *old_module_sp_ptr, 567 bool *did_create_ptr, 568 bool always_create 569 ) 570 { 571 ModuleList &shared_module_list = GetSharedModuleList (); 572 Mutex::Locker locker(shared_module_list.m_modules_mutex); 573 char path[PATH_MAX]; 574 char uuid_cstr[64]; 575 576 Error error; 577 578 module_sp.reset(); 579 580 if (did_create_ptr) 581 *did_create_ptr = false; 582 if (old_module_sp_ptr) 583 old_module_sp_ptr->reset(); 584 585 const UUID *uuid_ptr = module_spec.GetUUIDPtr(); 586 const FileSpec &module_file_spec = module_spec.GetFileSpec(); 587 const ArchSpec &arch = module_spec.GetArchitecture(); 588 589 // Make sure no one else can try and get or create a module while this 590 // function is actively working on it by doing an extra lock on the 591 // global mutex list. 592 if (always_create == false) 593 { 594 ModuleList matching_module_list; 595 const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list); 596 if (num_matching_modules > 0) 597 { 598 for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) 599 { 600 module_sp = matching_module_list.GetModuleAtIndex(module_idx); 601 if (module_file_spec) 602 { 603 // If we didn't have a UUID in mind when looking for the object file, 604 // then we should make sure the modification time hasn't changed! 605 TimeValue file_spec_mod_time(module_file_spec.GetModificationTime()); 606 if (file_spec_mod_time.IsValid()) 607 { 608 if (file_spec_mod_time == module_sp->GetModificationTime()) 609 return error; 610 } 611 } 612 if (old_module_sp_ptr && !old_module_sp_ptr->get()) 613 *old_module_sp_ptr = module_sp; 614 shared_module_list.Remove (module_sp); 615 module_sp.reset(); 616 } 617 } 618 } 619 620 if (module_sp) 621 return error; 622 else 623 { 624 module_sp.reset (new Module (module_spec)); 625 // Make sure there are a module and an object file since we can specify 626 // a valid file path with an architecture that might not be in that file. 627 // By getting the object file we can guarantee that the architecture matches 628 if (module_sp) 629 { 630 if (module_sp->GetObjectFile()) 631 { 632 // If we get in here we got the correct arch, now we just need 633 // to verify the UUID if one was given 634 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) 635 module_sp.reset(); 636 else 637 { 638 if (did_create_ptr) 639 *did_create_ptr = true; 640 641 shared_module_list.Append(module_sp); 642 return error; 643 } 644 } 645 else 646 module_sp.reset(); 647 } 648 } 649 650 // Either the file didn't exist where at the path, or no path was given, so 651 // we now have to use more extreme measures to try and find the appropriate 652 // module. 653 654 // Fixup the incoming path in case the path points to a valid file, yet 655 // the arch or UUID (if one was passed in) don't match. 656 FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec); 657 658 // Don't look for the file if it appears to be the same one we already 659 // checked for above... 660 if (file_spec != module_file_spec) 661 { 662 if (!file_spec.Exists()) 663 { 664 file_spec.GetPath(path, sizeof(path)); 665 if (path[0] == '\0') 666 module_file_spec.GetPath(path, sizeof(path)); 667 if (file_spec.Exists()) 668 { 669 if (uuid_ptr && uuid_ptr->IsValid()) 670 uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); 671 else 672 uuid_cstr[0] = '\0'; 673 674 675 if (arch.IsValid()) 676 { 677 if (uuid_cstr[0]) 678 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr); 679 else 680 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName()); 681 } 682 } 683 else 684 { 685 error.SetErrorStringWithFormat("'%s' does not exist", path); 686 } 687 if (error.Fail()) 688 module_sp.reset(); 689 return error; 690 } 691 692 693 // Make sure no one else can try and get or create a module while this 694 // function is actively working on it by doing an extra lock on the 695 // global mutex list. 696 ModuleList matching_module_list; 697 if (shared_module_list.FindModules (module_spec, matching_module_list) > 0) 698 { 699 module_sp = matching_module_list.GetModuleAtIndex(0); 700 701 // If we didn't have a UUID in mind when looking for the object file, 702 // then we should make sure the modification time hasn't changed! 703 if (module_spec.GetUUIDPtr() == NULL) 704 { 705 TimeValue file_spec_mod_time(file_spec.GetModificationTime()); 706 if (file_spec_mod_time.IsValid()) 707 { 708 if (file_spec_mod_time != module_sp->GetModificationTime()) 709 { 710 if (old_module_sp_ptr) 711 *old_module_sp_ptr = module_sp; 712 shared_module_list.Remove (module_sp); 713 module_sp.reset(); 714 } 715 } 716 } 717 } 718 719 if (module_sp.get() == NULL) 720 { 721 module_sp.reset (new Module (module_spec)); 722 // Make sure there are a module and an object file since we can specify 723 // a valid file path with an architecture that might not be in that file. 724 // By getting the object file we can guarantee that the architecture matches 725 if (module_sp && module_sp->GetObjectFile()) 726 { 727 if (did_create_ptr) 728 *did_create_ptr = true; 729 730 shared_module_list.Append(module_sp); 731 } 732 else 733 { 734 file_spec.GetPath(path, sizeof(path)); 735 736 if (file_spec) 737 { 738 if (arch.IsValid()) 739 error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); 740 else 741 error.SetErrorStringWithFormat("unable to open '%s'", path); 742 } 743 else 744 { 745 if (uuid_ptr && uuid_ptr->IsValid()) 746 uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); 747 else 748 uuid_cstr[0] = '\0'; 749 750 if (uuid_cstr[0]) 751 error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr); 752 else 753 error.SetErrorStringWithFormat("cannot locate a module"); 754 } 755 } 756 } 757 } 758 759 return error; 760 } 761 762 bool 763 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) 764 { 765 return GetSharedModuleList ().Remove (module_sp); 766 } 767 768 769