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