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