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