1 //===-- ModuleList.cpp ------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Core/ModuleList.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/Log.h" 17 #include "lldb/Core/Module.h" 18 #include "lldb/Host/Host.h" 19 #include "lldb/Host/Symbols.h" 20 #include "lldb/Symbol/ClangNamespaceDecl.h" 21 #include "lldb/Symbol/ObjectFile.h" 22 #include "lldb/Symbol/VariableList.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 //---------------------------------------------------------------------- 28 // ModuleList constructor 29 //---------------------------------------------------------------------- 30 ModuleList::ModuleList() : 31 m_modules(), 32 m_modules_mutex (Mutex::eMutexTypeRecursive) 33 { 34 } 35 36 //---------------------------------------------------------------------- 37 // Copy constructor 38 //---------------------------------------------------------------------- 39 ModuleList::ModuleList(const ModuleList& rhs) : 40 m_modules(rhs.m_modules) 41 { 42 } 43 44 //---------------------------------------------------------------------- 45 // Assignment operator 46 //---------------------------------------------------------------------- 47 const ModuleList& 48 ModuleList::operator= (const ModuleList& rhs) 49 { 50 if (this != &rhs) 51 { 52 Mutex::Locker locker(m_modules_mutex); 53 m_modules = rhs.m_modules; 54 } 55 return *this; 56 } 57 58 //---------------------------------------------------------------------- 59 // Destructor 60 //---------------------------------------------------------------------- 61 ModuleList::~ModuleList() 62 { 63 } 64 65 void 66 ModuleList::Append (const ModuleSP &module_sp) 67 { 68 if (module_sp) 69 { 70 Mutex::Locker locker(m_modules_mutex); 71 m_modules.push_back(module_sp); 72 } 73 } 74 75 bool 76 ModuleList::AppendIfNeeded (const ModuleSP &module_sp) 77 { 78 if (module_sp) 79 { 80 Mutex::Locker locker(m_modules_mutex); 81 collection::iterator pos, end = m_modules.end(); 82 for (pos = m_modules.begin(); pos != end; ++pos) 83 { 84 if (pos->get() == module_sp.get()) 85 return false; // Already in the list 86 } 87 // Only push module_sp on the list if it wasn't already in there. 88 m_modules.push_back(module_sp); 89 return true; 90 } 91 return false; 92 } 93 94 bool 95 ModuleList::Remove (const ModuleSP &module_sp) 96 { 97 if (module_sp) 98 { 99 Mutex::Locker locker(m_modules_mutex); 100 collection::iterator pos, end = m_modules.end(); 101 for (pos = m_modules.begin(); pos != end; ++pos) 102 { 103 if (pos->get() == module_sp.get()) 104 { 105 m_modules.erase (pos); 106 return true; 107 } 108 } 109 } 110 return false; 111 } 112 113 114 size_t 115 ModuleList::RemoveOrphans () 116 { 117 Mutex::Locker locker(m_modules_mutex); 118 collection::iterator pos = m_modules.begin(); 119 size_t remove_count = 0; 120 while (pos != m_modules.end()) 121 { 122 if (pos->unique()) 123 { 124 pos = m_modules.erase (pos); 125 ++remove_count; 126 } 127 else 128 { 129 ++pos; 130 } 131 } 132 return remove_count; 133 } 134 135 size_t 136 ModuleList::Remove (ModuleList &module_list) 137 { 138 Mutex::Locker locker(m_modules_mutex); 139 size_t num_removed = 0; 140 collection::iterator pos, end = module_list.m_modules.end(); 141 for (pos = module_list.m_modules.begin(); pos != end; ++pos) 142 { 143 if (Remove (*pos)) 144 ++num_removed; 145 } 146 return num_removed; 147 } 148 149 150 151 void 152 ModuleList::Clear() 153 { 154 Mutex::Locker locker(m_modules_mutex); 155 m_modules.clear(); 156 } 157 158 void 159 ModuleList::Destroy() 160 { 161 Mutex::Locker locker(m_modules_mutex); 162 collection empty; 163 m_modules.swap(empty); 164 } 165 166 Module* 167 ModuleList::GetModulePointerAtIndex (uint32_t idx) const 168 { 169 Mutex::Locker locker(m_modules_mutex); 170 if (idx < m_modules.size()) 171 return m_modules[idx].get(); 172 return NULL; 173 } 174 175 ModuleSP 176 ModuleList::GetModuleAtIndex(uint32_t idx) 177 { 178 Mutex::Locker locker(m_modules_mutex); 179 ModuleSP module_sp; 180 if (idx < m_modules.size()) 181 module_sp = m_modules[idx]; 182 return module_sp; 183 } 184 185 uint32_t 186 ModuleList::FindFunctions (const ConstString &name, 187 uint32_t name_type_mask, 188 bool include_symbols, 189 bool include_inlines, 190 bool append, 191 SymbolContextList &sc_list) 192 { 193 if (!append) 194 sc_list.Clear(); 195 196 Mutex::Locker locker(m_modules_mutex); 197 collection::const_iterator pos, end = m_modules.end(); 198 for (pos = m_modules.begin(); pos != end; ++pos) 199 { 200 (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list); 201 } 202 203 return sc_list.GetSize(); 204 } 205 206 uint32_t 207 ModuleList::FindCompileUnits (const FileSpec &path, 208 bool append, 209 SymbolContextList &sc_list) 210 { 211 if (!append) 212 sc_list.Clear(); 213 214 Mutex::Locker locker(m_modules_mutex); 215 collection::const_iterator pos, end = m_modules.end(); 216 for (pos = m_modules.begin(); pos != end; ++pos) 217 { 218 (*pos)->FindCompileUnits (path, true, sc_list); 219 } 220 221 return sc_list.GetSize(); 222 } 223 224 uint32_t 225 ModuleList::FindGlobalVariables (const ConstString &name, 226 bool append, 227 uint32_t max_matches, 228 VariableList& variable_list) 229 { 230 size_t initial_size = variable_list.GetSize(); 231 Mutex::Locker locker(m_modules_mutex); 232 collection::iterator pos, end = m_modules.end(); 233 for (pos = m_modules.begin(); pos != end; ++pos) 234 { 235 (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list); 236 } 237 return variable_list.GetSize() - initial_size; 238 } 239 240 241 uint32_t 242 ModuleList::FindGlobalVariables (const RegularExpression& regex, 243 bool append, 244 uint32_t max_matches, 245 VariableList& variable_list) 246 { 247 size_t initial_size = variable_list.GetSize(); 248 Mutex::Locker locker(m_modules_mutex); 249 collection::iterator pos, end = m_modules.end(); 250 for (pos = m_modules.begin(); pos != end; ++pos) 251 { 252 (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list); 253 } 254 return variable_list.GetSize() - initial_size; 255 } 256 257 258 size_t 259 ModuleList::FindSymbolsWithNameAndType (const ConstString &name, 260 SymbolType symbol_type, 261 SymbolContextList &sc_list, 262 bool append) 263 { 264 Mutex::Locker locker(m_modules_mutex); 265 if (!append) 266 sc_list.Clear(); 267 size_t initial_size = sc_list.GetSize(); 268 269 collection::iterator pos, end = m_modules.end(); 270 for (pos = m_modules.begin(); pos != end; ++pos) 271 (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list); 272 return sc_list.GetSize() - initial_size; 273 } 274 275 size_t 276 ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, 277 lldb::SymbolType symbol_type, 278 SymbolContextList &sc_list, 279 bool append) 280 { 281 Mutex::Locker locker(m_modules_mutex); 282 if (!append) 283 sc_list.Clear(); 284 size_t initial_size = sc_list.GetSize(); 285 286 collection::iterator pos, end = m_modules.end(); 287 for (pos = m_modules.begin(); pos != end; ++pos) 288 (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list); 289 return sc_list.GetSize() - initial_size; 290 } 291 292 size_t 293 ModuleList::FindModules (const ModuleSpec &module_spec, ModuleList& matching_module_list) const 294 { 295 size_t existing_matches = matching_module_list.GetSize(); 296 297 Mutex::Locker locker(m_modules_mutex); 298 collection::const_iterator pos, end = m_modules.end(); 299 for (pos = m_modules.begin(); pos != end; ++pos) 300 { 301 ModuleSP module_sp(*pos); 302 if (module_sp->MatchesModuleSpec (module_spec)) 303 matching_module_list.Append(module_sp); 304 } 305 return matching_module_list.GetSize() - existing_matches; 306 } 307 308 ModuleSP 309 ModuleList::FindModule (const Module *module_ptr) 310 { 311 ModuleSP module_sp; 312 313 // Scope for "locker" 314 { 315 Mutex::Locker locker(m_modules_mutex); 316 collection::const_iterator pos, end = m_modules.end(); 317 318 for (pos = m_modules.begin(); pos != end; ++pos) 319 { 320 if ((*pos).get() == module_ptr) 321 { 322 module_sp = (*pos); 323 break; 324 } 325 } 326 } 327 return module_sp; 328 329 } 330 331 ModuleSP 332 ModuleList::FindModule (const UUID &uuid) 333 { 334 ModuleSP module_sp; 335 336 if (uuid.IsValid()) 337 { 338 Mutex::Locker locker(m_modules_mutex); 339 collection::const_iterator pos, end = m_modules.end(); 340 341 for (pos = m_modules.begin(); pos != end; ++pos) 342 { 343 if ((*pos)->GetUUID() == uuid) 344 { 345 module_sp = (*pos); 346 break; 347 } 348 } 349 } 350 return module_sp; 351 } 352 353 354 uint32_t 355 ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, uint32_t max_matches, TypeList& types) 356 { 357 Mutex::Locker locker(m_modules_mutex); 358 359 uint32_t total_matches = 0; 360 collection::const_iterator pos, end = m_modules.end(); 361 if (sc.module_sp) 362 { 363 // The symbol context "sc" contains a module so we want to search that 364 // one first if it is in our list... 365 for (pos = m_modules.begin(); pos != end; ++pos) 366 { 367 if (sc.module_sp.get() == (*pos).get()) 368 { 369 total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types); 370 371 if (total_matches >= max_matches) 372 break; 373 } 374 } 375 } 376 377 if (total_matches < max_matches) 378 { 379 for (pos = m_modules.begin(); pos != end; ++pos) 380 { 381 // Search the module if the module is not equal to the one in the symbol 382 // context "sc". If "sc" contains a empty module shared pointer, then 383 // the comparisong will always be true (valid_module_ptr != NULL). 384 if (sc.module_sp.get() != (*pos).get()) 385 total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types); 386 387 if (total_matches >= max_matches) 388 break; 389 } 390 } 391 392 return total_matches; 393 } 394 395 bool 396 ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const 397 { 398 Mutex::Locker locker(m_modules_mutex); 399 collection::const_iterator pos, end = m_modules.end(); 400 for (pos = m_modules.begin(); pos != end; ++pos) 401 { 402 if ((*pos)->FindSourceFile (orig_spec, new_spec)) 403 return true; 404 } 405 return false; 406 } 407 408 409 410 ModuleSP 411 ModuleList::FindFirstModule (const ModuleSpec &module_spec) 412 { 413 ModuleSP module_sp; 414 Mutex::Locker locker(m_modules_mutex); 415 collection::const_iterator pos, end = m_modules.end(); 416 for (pos = m_modules.begin(); pos != end; ++pos) 417 { 418 ModuleSP module_sp(*pos); 419 if (module_sp->MatchesModuleSpec (module_spec)) 420 return module_sp; 421 } 422 return module_sp; 423 424 } 425 426 size_t 427 ModuleList::GetSize() const 428 { 429 size_t size = 0; 430 { 431 Mutex::Locker locker(m_modules_mutex); 432 size = m_modules.size(); 433 } 434 return size; 435 } 436 437 438 void 439 ModuleList::Dump(Stream *s) const 440 { 441 // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); 442 // s.Indent(); 443 // s << "ModuleList\n"; 444 445 Mutex::Locker locker(m_modules_mutex); 446 collection::const_iterator pos, end = m_modules.end(); 447 for (pos = m_modules.begin(); pos != end; ++pos) 448 { 449 (*pos)->Dump(s); 450 } 451 } 452 453 void 454 ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr) 455 { 456 if (log_sp) 457 { 458 Mutex::Locker locker(m_modules_mutex); 459 char uuid_cstr[256]; 460 collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end(); 461 for (pos = begin; pos != end; ++pos) 462 { 463 Module *module = pos->get(); 464 module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr)); 465 const FileSpec &module_file_spec = module->GetFileSpec(); 466 log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"", 467 prefix_cstr ? prefix_cstr : "", 468 (uint32_t)std::distance (begin, pos), 469 uuid_cstr, 470 module->GetArchitecture().GetArchitectureName(), 471 module_file_spec.GetDirectory().GetCString(), 472 module_file_spec.GetFilename().GetCString()); 473 } 474 } 475 } 476 477 bool 478 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) 479 { 480 Mutex::Locker locker(m_modules_mutex); 481 collection::const_iterator pos, end = m_modules.end(); 482 for (pos = m_modules.begin(); pos != end; ++pos) 483 { 484 if ((*pos)->ResolveFileAddress (vm_addr, so_addr)) 485 return true; 486 } 487 488 return false; 489 } 490 491 uint32_t 492 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) 493 { 494 // The address is already section offset so it has a module 495 uint32_t resolved_flags = 0; 496 ModuleSP module_sp (so_addr.GetModule()); 497 if (module_sp) 498 { 499 resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr, 500 resolve_scope, 501 sc); 502 } 503 else 504 { 505 Mutex::Locker locker(m_modules_mutex); 506 collection::const_iterator pos, end = m_modules.end(); 507 for (pos = m_modules.begin(); pos != end; ++pos) 508 { 509 resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr, 510 resolve_scope, 511 sc); 512 if (resolved_flags != 0) 513 break; 514 } 515 } 516 517 return resolved_flags; 518 } 519 520 uint32_t 521 ModuleList::ResolveSymbolContextForFilePath 522 ( 523 const char *file_path, 524 uint32_t line, 525 bool check_inlines, 526 uint32_t resolve_scope, 527 SymbolContextList& sc_list 528 ) 529 { 530 FileSpec file_spec(file_path, false); 531 return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 532 } 533 534 uint32_t 535 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) 536 { 537 Mutex::Locker locker(m_modules_mutex); 538 collection::const_iterator pos, end = m_modules.end(); 539 for (pos = m_modules.begin(); pos != end; ++pos) 540 { 541 (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 542 } 543 544 return sc_list.GetSize(); 545 } 546 547 uint32_t 548 ModuleList::GetIndexForModule (const Module *module) const 549 { 550 if (module) 551 { 552 Mutex::Locker locker(m_modules_mutex); 553 collection::const_iterator pos; 554 collection::const_iterator begin = m_modules.begin(); 555 collection::const_iterator end = m_modules.end(); 556 for (pos = begin; pos != end; ++pos) 557 { 558 if ((*pos).get() == module) 559 return std::distance (begin, pos); 560 } 561 } 562 return LLDB_INVALID_INDEX32; 563 } 564 565 static ModuleList & 566 GetSharedModuleList () 567 { 568 static ModuleList g_shared_module_list; 569 return g_shared_module_list; 570 } 571 572 bool 573 ModuleList::ModuleIsInCache (const Module *module_ptr) 574 { 575 if (module_ptr) 576 { 577 ModuleList &shared_module_list = GetSharedModuleList (); 578 return shared_module_list.FindModule (module_ptr).get() != NULL; 579 } 580 return false; 581 } 582 583 size_t 584 ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list) 585 { 586 return GetSharedModuleList ().FindModules (module_spec, matching_module_list); 587 } 588 589 uint32_t 590 ModuleList::RemoveOrphanSharedModules () 591 { 592 return GetSharedModuleList ().RemoveOrphans(); 593 } 594 595 Error 596 ModuleList::GetSharedModule 597 ( 598 const ModuleSpec &module_spec, 599 ModuleSP &module_sp, 600 const FileSpecList *module_search_paths_ptr, 601 ModuleSP *old_module_sp_ptr, 602 bool *did_create_ptr, 603 bool always_create 604 ) 605 { 606 ModuleList &shared_module_list = GetSharedModuleList (); 607 Mutex::Locker locker(shared_module_list.m_modules_mutex); 608 char path[PATH_MAX]; 609 char uuid_cstr[64]; 610 611 Error error; 612 613 module_sp.reset(); 614 615 if (did_create_ptr) 616 *did_create_ptr = false; 617 if (old_module_sp_ptr) 618 old_module_sp_ptr->reset(); 619 620 const UUID *uuid_ptr = module_spec.GetUUIDPtr(); 621 const FileSpec &module_file_spec = module_spec.GetFileSpec(); 622 const ArchSpec &arch = module_spec.GetArchitecture(); 623 624 // Make sure no one else can try and get or create a module while this 625 // function is actively working on it by doing an extra lock on the 626 // global mutex list. 627 if (always_create == false) 628 { 629 ModuleList matching_module_list; 630 const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list); 631 if (num_matching_modules > 0) 632 { 633 for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) 634 { 635 module_sp = matching_module_list.GetModuleAtIndex(module_idx); 636 // If we had a UUID and we found a match, then that is good enough for a match 637 if (uuid_ptr) 638 break; 639 if (module_file_spec) 640 { 641 // If we didn't have a UUID in mind when looking for the object file, 642 // then we should make sure the modification time hasn't changed! 643 TimeValue file_spec_mod_time(module_file_spec.GetModificationTime()); 644 if (file_spec_mod_time.IsValid()) 645 { 646 if (file_spec_mod_time == module_sp->GetModificationTime()) 647 return error; 648 } 649 } 650 if (old_module_sp_ptr && !old_module_sp_ptr->get()) 651 *old_module_sp_ptr = module_sp; 652 shared_module_list.Remove (module_sp); 653 module_sp.reset(); 654 } 655 } 656 } 657 658 if (module_sp) 659 return error; 660 else 661 { 662 module_sp.reset (new Module (module_spec)); 663 // Make sure there are a module and an object file since we can specify 664 // a valid file path with an architecture that might not be in that file. 665 // By getting the object file we can guarantee that the architecture matches 666 if (module_sp) 667 { 668 if (module_sp->GetObjectFile()) 669 { 670 // If we get in here we got the correct arch, now we just need 671 // to verify the UUID if one was given 672 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) 673 module_sp.reset(); 674 else 675 { 676 if (did_create_ptr) 677 *did_create_ptr = true; 678 679 shared_module_list.Append(module_sp); 680 return error; 681 } 682 } 683 else 684 module_sp.reset(); 685 } 686 } 687 688 // Either the file didn't exist where at the path, or no path was given, so 689 // we now have to use more extreme measures to try and find the appropriate 690 // module. 691 692 // Fixup the incoming path in case the path points to a valid file, yet 693 // the arch or UUID (if one was passed in) don't match. 694 FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec); 695 696 // Don't look for the file if it appears to be the same one we already 697 // checked for above... 698 if (file_spec != module_file_spec) 699 { 700 if (!file_spec.Exists()) 701 { 702 file_spec.GetPath(path, sizeof(path)); 703 if (path[0] == '\0') 704 module_file_spec.GetPath(path, sizeof(path)); 705 if (file_spec.Exists()) 706 { 707 if (uuid_ptr && uuid_ptr->IsValid()) 708 uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); 709 else 710 uuid_cstr[0] = '\0'; 711 712 713 if (arch.IsValid()) 714 { 715 if (uuid_cstr[0]) 716 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr); 717 else 718 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName()); 719 } 720 } 721 else 722 { 723 error.SetErrorStringWithFormat("'%s' does not exist", path); 724 } 725 if (error.Fail()) 726 module_sp.reset(); 727 return error; 728 } 729 730 731 // Make sure no one else can try and get or create a module while this 732 // function is actively working on it by doing an extra lock on the 733 // global mutex list. 734 ModuleSpec platform_module_spec(module_spec); 735 platform_module_spec.GetFileSpec() = file_spec; 736 platform_module_spec.GetPlatformFileSpec() = file_spec; 737 ModuleList matching_module_list; 738 if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0) 739 { 740 module_sp = matching_module_list.GetModuleAtIndex(0); 741 742 // If we didn't have a UUID in mind when looking for the object file, 743 // then we should make sure the modification time hasn't changed! 744 if (platform_module_spec.GetUUIDPtr() == NULL) 745 { 746 TimeValue file_spec_mod_time(file_spec.GetModificationTime()); 747 if (file_spec_mod_time.IsValid()) 748 { 749 if (file_spec_mod_time != module_sp->GetModificationTime()) 750 { 751 if (old_module_sp_ptr) 752 *old_module_sp_ptr = module_sp; 753 shared_module_list.Remove (module_sp); 754 module_sp.reset(); 755 } 756 } 757 } 758 } 759 760 if (module_sp.get() == NULL) 761 { 762 module_sp.reset (new Module (platform_module_spec)); 763 // Make sure there are a module and an object file since we can specify 764 // a valid file path with an architecture that might not be in that file. 765 // By getting the object file we can guarantee that the architecture matches 766 if (module_sp && module_sp->GetObjectFile()) 767 { 768 if (did_create_ptr) 769 *did_create_ptr = true; 770 771 shared_module_list.Append(module_sp); 772 } 773 else 774 { 775 file_spec.GetPath(path, sizeof(path)); 776 777 if (file_spec) 778 { 779 if (arch.IsValid()) 780 error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); 781 else 782 error.SetErrorStringWithFormat("unable to open '%s'", path); 783 } 784 else 785 { 786 if (uuid_ptr && uuid_ptr->IsValid()) 787 uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); 788 else 789 uuid_cstr[0] = '\0'; 790 791 if (uuid_cstr[0]) 792 error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr); 793 else 794 error.SetErrorStringWithFormat("cannot locate a module"); 795 } 796 } 797 } 798 } 799 800 return error; 801 } 802 803 bool 804 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) 805 { 806 return GetSharedModuleList ().Remove (module_sp); 807 } 808 809 810