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