Module.cpp revision 296b06d325413723f5aac5988eed977b278a7807
1//===-- Module.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/lldb-python.h" 11 12#include "lldb/Core/Error.h" 13#include "lldb/Core/Module.h" 14#include "lldb/Core/DataBuffer.h" 15#include "lldb/Core/DataBufferHeap.h" 16#include "lldb/Core/Log.h" 17#include "lldb/Core/ModuleList.h" 18#include "lldb/Core/ModuleSpec.h" 19#include "lldb/Core/RegularExpression.h" 20#include "lldb/Core/Section.h" 21#include "lldb/Core/StreamString.h" 22#include "lldb/Core/Timer.h" 23#include "lldb/Host/Host.h" 24#include "lldb/Host/Symbols.h" 25#include "lldb/Interpreter/CommandInterpreter.h" 26#include "lldb/Interpreter/ScriptInterpreter.h" 27#include "lldb/lldb-private-log.h" 28#include "lldb/Symbol/CompileUnit.h" 29#include "lldb/Symbol/ObjectFile.h" 30#include "lldb/Symbol/SymbolContext.h" 31#include "lldb/Symbol/SymbolVendor.h" 32#include "lldb/Target/CPPLanguageRuntime.h" 33#include "lldb/Target/ObjCLanguageRuntime.h" 34#include "lldb/Target/Process.h" 35#include "lldb/Target/Target.h" 36 37using namespace lldb; 38using namespace lldb_private; 39 40// Shared pointers to modules track module lifetimes in 41// targets and in the global module, but this collection 42// will track all module objects that are still alive 43typedef std::vector<Module *> ModuleCollection; 44 45static ModuleCollection & 46GetModuleCollection() 47{ 48 // This module collection needs to live past any module, so we could either make it a 49 // shared pointer in each module or just leak is. Since it is only an empty vector by 50 // the time all the modules have gone away, we just leak it for now. If we decide this 51 // is a big problem we can introduce a Finalize method that will tear everything down in 52 // a predictable order. 53 54 static ModuleCollection *g_module_collection = NULL; 55 if (g_module_collection == NULL) 56 g_module_collection = new ModuleCollection(); 57 58 return *g_module_collection; 59} 60 61Mutex * 62Module::GetAllocationModuleCollectionMutex() 63{ 64 // NOTE: The mutex below must be leaked since the global module list in 65 // the ModuleList class will get torn at some point, and we can't know 66 // if it will tear itself down before the "g_module_collection_mutex" below 67 // will. So we leak a Mutex object below to safeguard against that 68 69 static Mutex *g_module_collection_mutex = NULL; 70 if (g_module_collection_mutex == NULL) 71 g_module_collection_mutex = new Mutex (Mutex::eMutexTypeRecursive); // NOTE: known leak 72 return g_module_collection_mutex; 73} 74 75size_t 76Module::GetNumberAllocatedModules () 77{ 78 Mutex::Locker locker (GetAllocationModuleCollectionMutex()); 79 return GetModuleCollection().size(); 80} 81 82Module * 83Module::GetAllocatedModuleAtIndex (size_t idx) 84{ 85 Mutex::Locker locker (GetAllocationModuleCollectionMutex()); 86 ModuleCollection &modules = GetModuleCollection(); 87 if (idx < modules.size()) 88 return modules[idx]; 89 return NULL; 90} 91#if 0 92 93// These functions help us to determine if modules are still loaded, yet don't require that 94// you have a command interpreter and can easily be called from an external debugger. 95namespace lldb { 96 97 void 98 ClearModuleInfo (void) 99 { 100 const bool mandatory = true; 101 ModuleList::RemoveOrphanSharedModules(mandatory); 102 } 103 104 void 105 DumpModuleInfo (void) 106 { 107 Mutex::Locker locker (Module::GetAllocationModuleCollectionMutex()); 108 ModuleCollection &modules = GetModuleCollection(); 109 const size_t count = modules.size(); 110 printf ("%s: %" PRIu64 " modules:\n", __PRETTY_FUNCTION__, (uint64_t)count); 111 for (size_t i=0; i<count; ++i) 112 { 113 114 StreamString strm; 115 Module *module = modules[i]; 116 const bool in_shared_module_list = ModuleList::ModuleIsInCache (module); 117 module->GetDescription(&strm, eDescriptionLevelFull); 118 printf ("%p: shared = %i, ref_count = %3u, module = %s\n", 119 module, 120 in_shared_module_list, 121 (uint32_t)module->use_count(), 122 strm.GetString().c_str()); 123 } 124 } 125} 126 127#endif 128 129Module::Module (const ModuleSpec &module_spec) : 130 m_mutex (Mutex::eMutexTypeRecursive), 131 m_mod_time (module_spec.GetFileSpec().GetModificationTime()), 132 m_arch (module_spec.GetArchitecture()), 133 m_uuid (), 134 m_file (module_spec.GetFileSpec()), 135 m_platform_file(module_spec.GetPlatformFileSpec()), 136 m_symfile_spec (module_spec.GetSymbolFileSpec()), 137 m_object_name (module_spec.GetObjectName()), 138 m_object_offset (module_spec.GetObjectOffset()), 139 m_objfile_sp (), 140 m_symfile_ap (), 141 m_ast (), 142 m_source_mappings (), 143 m_did_load_objfile (false), 144 m_did_load_symbol_vendor (false), 145 m_did_parse_uuid (false), 146 m_did_init_ast (false), 147 m_is_dynamic_loader_module (false), 148 m_file_has_changed (false), 149 m_first_file_changed_log (false) 150{ 151 // Scope for locker below... 152 { 153 Mutex::Locker locker (GetAllocationModuleCollectionMutex()); 154 GetModuleCollection().push_back(this); 155 } 156 157 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT|LIBLLDB_LOG_MODULES)); 158 if (log) 159 log->Printf ("%p Module::Module((%s) '%s/%s%s%s%s')", 160 this, 161 m_arch.GetArchitectureName(), 162 m_file.GetDirectory().AsCString(""), 163 m_file.GetFilename().AsCString(""), 164 m_object_name.IsEmpty() ? "" : "(", 165 m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), 166 m_object_name.IsEmpty() ? "" : ")"); 167} 168 169Module::Module(const FileSpec& file_spec, 170 const ArchSpec& arch, 171 const ConstString *object_name, 172 off_t object_offset) : 173 m_mutex (Mutex::eMutexTypeRecursive), 174 m_mod_time (file_spec.GetModificationTime()), 175 m_arch (arch), 176 m_uuid (), 177 m_file (file_spec), 178 m_platform_file(), 179 m_symfile_spec (), 180 m_object_name (), 181 m_object_offset (object_offset), 182 m_objfile_sp (), 183 m_symfile_ap (), 184 m_ast (), 185 m_source_mappings (), 186 m_did_load_objfile (false), 187 m_did_load_symbol_vendor (false), 188 m_did_parse_uuid (false), 189 m_did_init_ast (false), 190 m_is_dynamic_loader_module (false), 191 m_file_has_changed (false), 192 m_first_file_changed_log (false) 193{ 194 // Scope for locker below... 195 { 196 Mutex::Locker locker (GetAllocationModuleCollectionMutex()); 197 GetModuleCollection().push_back(this); 198 } 199 200 if (object_name) 201 m_object_name = *object_name; 202 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT|LIBLLDB_LOG_MODULES)); 203 if (log) 204 log->Printf ("%p Module::Module((%s) '%s/%s%s%s%s')", 205 this, 206 m_arch.GetArchitectureName(), 207 m_file.GetDirectory().AsCString(""), 208 m_file.GetFilename().AsCString(""), 209 m_object_name.IsEmpty() ? "" : "(", 210 m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), 211 m_object_name.IsEmpty() ? "" : ")"); 212} 213 214Module::~Module() 215{ 216 // Scope for locker below... 217 { 218 Mutex::Locker locker (GetAllocationModuleCollectionMutex()); 219 ModuleCollection &modules = GetModuleCollection(); 220 ModuleCollection::iterator end = modules.end(); 221 ModuleCollection::iterator pos = std::find(modules.begin(), end, this); 222 assert (pos != end); 223 modules.erase(pos); 224 } 225 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT|LIBLLDB_LOG_MODULES)); 226 if (log) 227 log->Printf ("%p Module::~Module((%s) '%s/%s%s%s%s')", 228 this, 229 m_arch.GetArchitectureName(), 230 m_file.GetDirectory().AsCString(""), 231 m_file.GetFilename().AsCString(""), 232 m_object_name.IsEmpty() ? "" : "(", 233 m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), 234 m_object_name.IsEmpty() ? "" : ")"); 235 // Release any auto pointers before we start tearing down our member 236 // variables since the object file and symbol files might need to make 237 // function calls back into this module object. The ordering is important 238 // here because symbol files can require the module object file. So we tear 239 // down the symbol file first, then the object file. 240 m_symfile_ap.reset(); 241 m_objfile_sp.reset(); 242} 243 244ObjectFile * 245Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t header_addr, Error &error) 246{ 247 if (m_objfile_sp) 248 { 249 error.SetErrorString ("object file already exists"); 250 } 251 else 252 { 253 Mutex::Locker locker (m_mutex); 254 if (process_sp) 255 { 256 m_did_load_objfile = true; 257 std::auto_ptr<DataBufferHeap> data_ap (new DataBufferHeap (512, 0)); 258 Error readmem_error; 259 const size_t bytes_read = process_sp->ReadMemory (header_addr, 260 data_ap->GetBytes(), 261 data_ap->GetByteSize(), 262 readmem_error); 263 if (bytes_read == 512) 264 { 265 DataBufferSP data_sp(data_ap.release()); 266 m_objfile_sp = ObjectFile::FindPlugin(shared_from_this(), process_sp, header_addr, data_sp); 267 if (m_objfile_sp) 268 { 269 StreamString s; 270 s.Printf("0x%16.16" PRIx64, header_addr); 271 m_object_name.SetCString (s.GetData()); 272 273 // Once we get the object file, update our module with the object file's 274 // architecture since it might differ in vendor/os if some parts were 275 // unknown. 276 m_objfile_sp->GetArchitecture (m_arch); 277 } 278 else 279 { 280 error.SetErrorString ("unable to find suitable object file plug-in"); 281 } 282 } 283 else 284 { 285 error.SetErrorStringWithFormat ("unable to read header from memory: %s", readmem_error.AsCString()); 286 } 287 } 288 else 289 { 290 error.SetErrorString ("invalid process"); 291 } 292 } 293 return m_objfile_sp.get(); 294} 295 296 297const lldb_private::UUID& 298Module::GetUUID() 299{ 300 Mutex::Locker locker (m_mutex); 301 if (m_did_parse_uuid == false) 302 { 303 ObjectFile * obj_file = GetObjectFile (); 304 305 if (obj_file != NULL) 306 { 307 obj_file->GetUUID(&m_uuid); 308 m_did_parse_uuid = true; 309 } 310 } 311 return m_uuid; 312} 313 314ClangASTContext & 315Module::GetClangASTContext () 316{ 317 Mutex::Locker locker (m_mutex); 318 if (m_did_init_ast == false) 319 { 320 ObjectFile * objfile = GetObjectFile(); 321 ArchSpec object_arch; 322 if (objfile && objfile->GetArchitecture(object_arch)) 323 { 324 m_did_init_ast = true; 325 326 // LLVM wants this to be set to iOS or MacOSX; if we're working on 327 // a bare-boards type image, change the triple for llvm's benefit. 328 if (object_arch.GetTriple().getVendor() == llvm::Triple::Apple 329 && object_arch.GetTriple().getOS() == llvm::Triple::UnknownOS) 330 { 331 if (object_arch.GetTriple().getArch() == llvm::Triple::arm || 332 object_arch.GetTriple().getArch() == llvm::Triple::thumb) 333 { 334 object_arch.GetTriple().setOS(llvm::Triple::IOS); 335 } 336 else 337 { 338 object_arch.GetTriple().setOS(llvm::Triple::MacOSX); 339 } 340 } 341 m_ast.SetArchitecture (object_arch); 342 } 343 } 344 return m_ast; 345} 346 347void 348Module::ParseAllDebugSymbols() 349{ 350 Mutex::Locker locker (m_mutex); 351 size_t num_comp_units = GetNumCompileUnits(); 352 if (num_comp_units == 0) 353 return; 354 355 SymbolContext sc; 356 sc.module_sp = shared_from_this(); 357 SymbolVendor *symbols = GetSymbolVendor (); 358 359 for (size_t cu_idx = 0; cu_idx < num_comp_units; cu_idx++) 360 { 361 sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get(); 362 if (sc.comp_unit) 363 { 364 sc.function = NULL; 365 symbols->ParseVariablesForContext(sc); 366 367 symbols->ParseCompileUnitFunctions(sc); 368 369 for (size_t func_idx = 0; (sc.function = sc.comp_unit->GetFunctionAtIndex(func_idx).get()) != NULL; ++func_idx) 370 { 371 symbols->ParseFunctionBlocks(sc); 372 373 // Parse the variables for this function and all its blocks 374 symbols->ParseVariablesForContext(sc); 375 } 376 377 378 // Parse all types for this compile unit 379 sc.function = NULL; 380 symbols->ParseTypes(sc); 381 } 382 } 383} 384 385void 386Module::CalculateSymbolContext(SymbolContext* sc) 387{ 388 sc->module_sp = shared_from_this(); 389} 390 391ModuleSP 392Module::CalculateSymbolContextModule () 393{ 394 return shared_from_this(); 395} 396 397void 398Module::DumpSymbolContext(Stream *s) 399{ 400 s->Printf(", Module{%p}", this); 401} 402 403size_t 404Module::GetNumCompileUnits() 405{ 406 Mutex::Locker locker (m_mutex); 407 Timer scoped_timer(__PRETTY_FUNCTION__, "Module::GetNumCompileUnits (module = %p)", this); 408 SymbolVendor *symbols = GetSymbolVendor (); 409 if (symbols) 410 return symbols->GetNumCompileUnits(); 411 return 0; 412} 413 414CompUnitSP 415Module::GetCompileUnitAtIndex (size_t index) 416{ 417 Mutex::Locker locker (m_mutex); 418 size_t num_comp_units = GetNumCompileUnits (); 419 CompUnitSP cu_sp; 420 421 if (index < num_comp_units) 422 { 423 SymbolVendor *symbols = GetSymbolVendor (); 424 if (symbols) 425 cu_sp = symbols->GetCompileUnitAtIndex(index); 426 } 427 return cu_sp; 428} 429 430bool 431Module::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) 432{ 433 Mutex::Locker locker (m_mutex); 434 Timer scoped_timer(__PRETTY_FUNCTION__, "Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")", vm_addr); 435 ObjectFile* ofile = GetObjectFile(); 436 if (ofile) 437 return so_addr.ResolveAddressUsingFileSections(vm_addr, ofile->GetSectionList()); 438 return false; 439} 440 441uint32_t 442Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) 443{ 444 Mutex::Locker locker (m_mutex); 445 uint32_t resolved_flags = 0; 446 447 // Clear the result symbol context in case we don't find anything, but don't clear the target 448 sc.Clear(false); 449 450 // Get the section from the section/offset address. 451 SectionSP section_sp (so_addr.GetSection()); 452 453 // Make sure the section matches this module before we try and match anything 454 if (section_sp && section_sp->GetModule().get() == this) 455 { 456 // If the section offset based address resolved itself, then this 457 // is the right module. 458 sc.module_sp = shared_from_this(); 459 resolved_flags |= eSymbolContextModule; 460 461 // Resolve the compile unit, function, block, line table or line 462 // entry if requested. 463 if (resolve_scope & eSymbolContextCompUnit || 464 resolve_scope & eSymbolContextFunction || 465 resolve_scope & eSymbolContextBlock || 466 resolve_scope & eSymbolContextLineEntry ) 467 { 468 SymbolVendor *symbols = GetSymbolVendor (); 469 if (symbols) 470 resolved_flags |= symbols->ResolveSymbolContext (so_addr, resolve_scope, sc); 471 } 472 473 // Resolve the symbol if requested, but don't re-look it up if we've already found it. 474 if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol)) 475 { 476 ObjectFile* ofile = GetObjectFile(); 477 if (ofile) 478 { 479 Symtab *symtab = ofile->GetSymtab(); 480 if (symtab) 481 { 482 if (so_addr.IsSectionOffset()) 483 { 484 sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); 485 if (sc.symbol) 486 resolved_flags |= eSymbolContextSymbol; 487 } 488 } 489 } 490 } 491 } 492 return resolved_flags; 493} 494 495uint32_t 496Module::ResolveSymbolContextForFilePath 497( 498 const char *file_path, 499 uint32_t line, 500 bool check_inlines, 501 uint32_t resolve_scope, 502 SymbolContextList& sc_list 503) 504{ 505 FileSpec file_spec(file_path, false); 506 return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 507} 508 509uint32_t 510Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) 511{ 512 Mutex::Locker locker (m_mutex); 513 Timer scoped_timer(__PRETTY_FUNCTION__, 514 "Module::ResolveSymbolContextForFilePath (%s%s%s:%u, check_inlines = %s, resolve_scope = 0x%8.8x)", 515 file_spec.GetDirectory().AsCString(""), 516 file_spec.GetDirectory() ? "/" : "", 517 file_spec.GetFilename().AsCString(""), 518 line, 519 check_inlines ? "yes" : "no", 520 resolve_scope); 521 522 const uint32_t initial_count = sc_list.GetSize(); 523 524 SymbolVendor *symbols = GetSymbolVendor (); 525 if (symbols) 526 symbols->ResolveSymbolContext (file_spec, line, check_inlines, resolve_scope, sc_list); 527 528 return sc_list.GetSize() - initial_count; 529} 530 531 532size_t 533Module::FindGlobalVariables (const ConstString &name, 534 const ClangNamespaceDecl *namespace_decl, 535 bool append, 536 size_t max_matches, 537 VariableList& variables) 538{ 539 SymbolVendor *symbols = GetSymbolVendor (); 540 if (symbols) 541 return symbols->FindGlobalVariables(name, namespace_decl, append, max_matches, variables); 542 return 0; 543} 544 545size_t 546Module::FindGlobalVariables (const RegularExpression& regex, 547 bool append, 548 size_t max_matches, 549 VariableList& variables) 550{ 551 SymbolVendor *symbols = GetSymbolVendor (); 552 if (symbols) 553 return symbols->FindGlobalVariables(regex, append, max_matches, variables); 554 return 0; 555} 556 557size_t 558Module::FindCompileUnits (const FileSpec &path, 559 bool append, 560 SymbolContextList &sc_list) 561{ 562 if (!append) 563 sc_list.Clear(); 564 565 const size_t start_size = sc_list.GetSize(); 566 const size_t num_compile_units = GetNumCompileUnits(); 567 SymbolContext sc; 568 sc.module_sp = shared_from_this(); 569 const bool compare_directory = path.GetDirectory(); 570 for (size_t i=0; i<num_compile_units; ++i) 571 { 572 sc.comp_unit = GetCompileUnitAtIndex(i).get(); 573 if (sc.comp_unit) 574 { 575 if (FileSpec::Equal (*sc.comp_unit, path, compare_directory)) 576 sc_list.Append(sc); 577 } 578 } 579 return sc_list.GetSize() - start_size; 580} 581 582size_t 583Module::FindFunctions (const ConstString &name, 584 const ClangNamespaceDecl *namespace_decl, 585 uint32_t name_type_mask, 586 bool include_symbols, 587 bool include_inlines, 588 bool append, 589 SymbolContextList& sc_list) 590{ 591 if (!append) 592 sc_list.Clear(); 593 594 const size_t old_size = sc_list.GetSize(); 595 596 // Find all the functions (not symbols, but debug information functions... 597 SymbolVendor *symbols = GetSymbolVendor (); 598 599 if (name_type_mask & eFunctionNameTypeAuto) 600 { 601 ConstString lookup_name; 602 uint32_t lookup_name_type_mask = 0; 603 bool match_name_after_lookup = false; 604 Module::PrepareForFunctionNameLookup (name, 605 name_type_mask, 606 lookup_name, 607 lookup_name_type_mask, 608 match_name_after_lookup); 609 610 if (symbols) 611 symbols->FindFunctions(lookup_name, 612 namespace_decl, 613 lookup_name_type_mask, 614 include_inlines, 615 append, 616 sc_list); 617 618 // Now check our symbol table for symbols that are code symbols if requested 619 if (include_symbols) 620 { 621 ObjectFile *objfile = GetObjectFile(); 622 if (objfile) 623 { 624 Symtab *symtab = objfile->GetSymtab(); 625 if (symtab) 626 symtab->FindFunctionSymbols(lookup_name, lookup_name_type_mask, sc_list); 627 } 628 } 629 630 if (match_name_after_lookup) 631 { 632 SymbolContext sc; 633 size_t i = old_size; 634 while (i<sc_list.GetSize()) 635 { 636 if (sc_list.GetContextAtIndex(i, sc)) 637 { 638 const char *func_name = sc.GetFunctionName().GetCString(); 639 if (func_name && strstr (func_name, name.GetCString()) == NULL) 640 { 641 // Remove the current context 642 sc_list.RemoveContextAtIndex(i); 643 // Don't increment i and continue in the loop 644 continue; 645 } 646 } 647 ++i; 648 } 649 } 650 651 } 652 else 653 { 654 if (symbols) 655 symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list); 656 657 // Now check our symbol table for symbols that are code symbols if requested 658 if (include_symbols) 659 { 660 ObjectFile *objfile = GetObjectFile(); 661 if (objfile) 662 { 663 Symtab *symtab = objfile->GetSymtab(); 664 if (symtab) 665 symtab->FindFunctionSymbols(name, name_type_mask, sc_list); 666 } 667 } 668 } 669 670 return sc_list.GetSize() - old_size; 671} 672 673size_t 674Module::FindFunctions (const RegularExpression& regex, 675 bool include_symbols, 676 bool include_inlines, 677 bool append, 678 SymbolContextList& sc_list) 679{ 680 if (!append) 681 sc_list.Clear(); 682 683 const size_t start_size = sc_list.GetSize(); 684 685 SymbolVendor *symbols = GetSymbolVendor (); 686 if (symbols) 687 symbols->FindFunctions(regex, include_inlines, append, sc_list); 688 // Now check our symbol table for symbols that are code symbols if requested 689 if (include_symbols) 690 { 691 ObjectFile *objfile = GetObjectFile(); 692 if (objfile) 693 { 694 Symtab *symtab = objfile->GetSymtab(); 695 if (symtab) 696 { 697 std::vector<uint32_t> symbol_indexes; 698 symtab->AppendSymbolIndexesMatchingRegExAndType (regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); 699 const size_t num_matches = symbol_indexes.size(); 700 if (num_matches) 701 { 702 const bool merge_symbol_into_function = true; 703 SymbolContext sc(this); 704 for (size_t i=0; i<num_matches; i++) 705 { 706 sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); 707 SymbolType sym_type = sc.symbol->GetType(); 708 if (sc.symbol && (sym_type == eSymbolTypeCode || 709 sym_type == eSymbolTypeResolver)) 710 sc_list.AppendIfUnique (sc, merge_symbol_into_function); 711 } 712 } 713 } 714 } 715 } 716 return sc_list.GetSize() - start_size; 717} 718 719size_t 720Module::FindTypes_Impl (const SymbolContext& sc, 721 const ConstString &name, 722 const ClangNamespaceDecl *namespace_decl, 723 bool append, 724 size_t max_matches, 725 TypeList& types) 726{ 727 Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 728 if (sc.module_sp.get() == NULL || sc.module_sp.get() == this) 729 { 730 SymbolVendor *symbols = GetSymbolVendor (); 731 if (symbols) 732 return symbols->FindTypes(sc, name, namespace_decl, append, max_matches, types); 733 } 734 return 0; 735} 736 737size_t 738Module::FindTypesInNamespace (const SymbolContext& sc, 739 const ConstString &type_name, 740 const ClangNamespaceDecl *namespace_decl, 741 size_t max_matches, 742 TypeList& type_list) 743{ 744 const bool append = true; 745 return FindTypes_Impl(sc, type_name, namespace_decl, append, max_matches, type_list); 746} 747 748lldb::TypeSP 749Module::FindFirstType (const SymbolContext& sc, 750 const ConstString &name, 751 bool exact_match) 752{ 753 TypeList type_list; 754 const size_t num_matches = FindTypes (sc, name, exact_match, 1, type_list); 755 if (num_matches) 756 return type_list.GetTypeAtIndex(0); 757 return TypeSP(); 758} 759 760 761size_t 762Module::FindTypes (const SymbolContext& sc, 763 const ConstString &name, 764 bool exact_match, 765 size_t max_matches, 766 TypeList& types) 767{ 768 size_t num_matches = 0; 769 const char *type_name_cstr = name.GetCString(); 770 std::string type_scope; 771 std::string type_basename; 772 const bool append = true; 773 TypeClass type_class = eTypeClassAny; 774 if (Type::GetTypeScopeAndBasename (type_name_cstr, type_scope, type_basename, type_class)) 775 { 776 // Check if "name" starts with "::" which means the qualified type starts 777 // from the root namespace and implies and exact match. The typenames we 778 // get back from clang do not start with "::" so we need to strip this off 779 // in order to get the qualfied names to match 780 781 if (type_scope.size() >= 2 && type_scope[0] == ':' && type_scope[1] == ':') 782 { 783 type_scope.erase(0,2); 784 exact_match = true; 785 } 786 ConstString type_basename_const_str (type_basename.c_str()); 787 if (FindTypes_Impl(sc, type_basename_const_str, NULL, append, max_matches, types)) 788 { 789 types.RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); 790 num_matches = types.GetSize(); 791 } 792 } 793 else 794 { 795 // The type is not in a namespace/class scope, just search for it by basename 796 if (type_class != eTypeClassAny) 797 { 798 // The "type_name_cstr" will have been modified if we have a valid type class 799 // prefix (like "struct", "class", "union", "typedef" etc). 800 num_matches = FindTypes_Impl(sc, ConstString(type_name_cstr), NULL, append, max_matches, types); 801 types.RemoveMismatchedTypes (type_class); 802 num_matches = types.GetSize(); 803 } 804 else 805 { 806 num_matches = FindTypes_Impl(sc, name, NULL, append, max_matches, types); 807 } 808 } 809 810 return num_matches; 811 812} 813 814SymbolVendor* 815Module::GetSymbolVendor (bool can_create, lldb_private::Stream *feedback_strm) 816{ 817 Mutex::Locker locker (m_mutex); 818 if (m_did_load_symbol_vendor == false && can_create) 819 { 820 ObjectFile *obj_file = GetObjectFile (); 821 if (obj_file != NULL) 822 { 823 Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 824 m_symfile_ap.reset(SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); 825 m_did_load_symbol_vendor = true; 826 } 827 } 828 return m_symfile_ap.get(); 829} 830 831void 832Module::SetFileSpecAndObjectName (const FileSpec &file, const ConstString &object_name) 833{ 834 // Container objects whose paths do not specify a file directly can call 835 // this function to correct the file and object names. 836 m_file = file; 837 m_mod_time = file.GetModificationTime(); 838 m_object_name = object_name; 839} 840 841const ArchSpec& 842Module::GetArchitecture () const 843{ 844 return m_arch; 845} 846 847void 848Module::GetDescription (Stream *s, lldb::DescriptionLevel level) 849{ 850 Mutex::Locker locker (m_mutex); 851 852 if (level >= eDescriptionLevelFull) 853 { 854 if (m_arch.IsValid()) 855 s->Printf("(%s) ", m_arch.GetArchitectureName()); 856 } 857 858 if (level == eDescriptionLevelBrief) 859 { 860 const char *filename = m_file.GetFilename().GetCString(); 861 if (filename) 862 s->PutCString (filename); 863 } 864 else 865 { 866 char path[PATH_MAX]; 867 if (m_file.GetPath(path, sizeof(path))) 868 s->PutCString(path); 869 } 870 871 const char *object_name = m_object_name.GetCString(); 872 if (object_name) 873 s->Printf("(%s)", object_name); 874} 875 876void 877Module::ReportError (const char *format, ...) 878{ 879 if (format && format[0]) 880 { 881 StreamString strm; 882 strm.PutCString("error: "); 883 GetDescription(&strm, lldb::eDescriptionLevelBrief); 884 strm.PutChar (' '); 885 va_list args; 886 va_start (args, format); 887 strm.PrintfVarArg(format, args); 888 va_end (args); 889 890 const int format_len = strlen(format); 891 if (format_len > 0) 892 { 893 const char last_char = format[format_len-1]; 894 if (last_char != '\n' || last_char != '\r') 895 strm.EOL(); 896 } 897 Host::SystemLog (Host::eSystemLogError, "%s", strm.GetString().c_str()); 898 899 } 900} 901 902bool 903Module::FileHasChanged () const 904{ 905 if (m_file_has_changed == false) 906 m_file_has_changed = (m_file.GetModificationTime() != m_mod_time); 907 return m_file_has_changed; 908} 909 910void 911Module::ReportErrorIfModifyDetected (const char *format, ...) 912{ 913 if (m_first_file_changed_log == false) 914 { 915 if (FileHasChanged ()) 916 { 917 m_first_file_changed_log = true; 918 if (format) 919 { 920 StreamString strm; 921 strm.PutCString("error: the object file "); 922 GetDescription(&strm, lldb::eDescriptionLevelFull); 923 strm.PutCString (" has been modified\n"); 924 925 va_list args; 926 va_start (args, format); 927 strm.PrintfVarArg(format, args); 928 va_end (args); 929 930 const int format_len = strlen(format); 931 if (format_len > 0) 932 { 933 const char last_char = format[format_len-1]; 934 if (last_char != '\n' || last_char != '\r') 935 strm.EOL(); 936 } 937 strm.PutCString("The debug session should be aborted as the original debug information has been overwritten.\n"); 938 Host::SystemLog (Host::eSystemLogError, "%s", strm.GetString().c_str()); 939 } 940 } 941 } 942} 943 944void 945Module::ReportWarning (const char *format, ...) 946{ 947 if (format && format[0]) 948 { 949 StreamString strm; 950 strm.PutCString("warning: "); 951 GetDescription(&strm, lldb::eDescriptionLevelFull); 952 strm.PutChar (' '); 953 954 va_list args; 955 va_start (args, format); 956 strm.PrintfVarArg(format, args); 957 va_end (args); 958 959 const int format_len = strlen(format); 960 if (format_len > 0) 961 { 962 const char last_char = format[format_len-1]; 963 if (last_char != '\n' || last_char != '\r') 964 strm.EOL(); 965 } 966 Host::SystemLog (Host::eSystemLogWarning, "%s", strm.GetString().c_str()); 967 } 968} 969 970void 971Module::LogMessage (Log *log, const char *format, ...) 972{ 973 if (log) 974 { 975 StreamString log_message; 976 GetDescription(&log_message, lldb::eDescriptionLevelFull); 977 log_message.PutCString (": "); 978 va_list args; 979 va_start (args, format); 980 log_message.PrintfVarArg (format, args); 981 va_end (args); 982 log->PutCString(log_message.GetString().c_str()); 983 } 984} 985 986void 987Module::LogMessageVerboseBacktrace (Log *log, const char *format, ...) 988{ 989 if (log) 990 { 991 StreamString log_message; 992 GetDescription(&log_message, lldb::eDescriptionLevelFull); 993 log_message.PutCString (": "); 994 va_list args; 995 va_start (args, format); 996 log_message.PrintfVarArg (format, args); 997 va_end (args); 998 if (log->GetVerbose()) 999 Host::Backtrace (log_message, 1024); 1000 log->PutCString(log_message.GetString().c_str()); 1001 } 1002} 1003 1004void 1005Module::Dump(Stream *s) 1006{ 1007 Mutex::Locker locker (m_mutex); 1008 //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 1009 s->Indent(); 1010 s->Printf("Module %s/%s%s%s%s\n", 1011 m_file.GetDirectory().AsCString(), 1012 m_file.GetFilename().AsCString(), 1013 m_object_name ? "(" : "", 1014 m_object_name ? m_object_name.GetCString() : "", 1015 m_object_name ? ")" : ""); 1016 1017 s->IndentMore(); 1018 ObjectFile *objfile = GetObjectFile (); 1019 1020 if (objfile) 1021 objfile->Dump(s); 1022 1023 SymbolVendor *symbols = GetSymbolVendor (); 1024 1025 if (symbols) 1026 symbols->Dump(s); 1027 1028 s->IndentLess(); 1029} 1030 1031 1032TypeList* 1033Module::GetTypeList () 1034{ 1035 SymbolVendor *symbols = GetSymbolVendor (); 1036 if (symbols) 1037 return &symbols->GetTypeList(); 1038 return NULL; 1039} 1040 1041const ConstString & 1042Module::GetObjectName() const 1043{ 1044 return m_object_name; 1045} 1046 1047ObjectFile * 1048Module::GetObjectFile() 1049{ 1050 Mutex::Locker locker (m_mutex); 1051 if (m_did_load_objfile == false) 1052 { 1053 m_did_load_objfile = true; 1054 Timer scoped_timer(__PRETTY_FUNCTION__, 1055 "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString("")); 1056 DataBufferSP data_sp; 1057 lldb::offset_t data_offset = 0; 1058 m_objfile_sp = ObjectFile::FindPlugin (shared_from_this(), 1059 &m_file, 1060 m_object_offset, 1061 m_file.GetByteSize(), 1062 data_sp, 1063 data_offset); 1064 if (m_objfile_sp) 1065 { 1066 // Once we get the object file, update our module with the object file's 1067 // architecture since it might differ in vendor/os if some parts were 1068 // unknown. 1069 m_objfile_sp->GetArchitecture (m_arch); 1070 } 1071 } 1072 return m_objfile_sp.get(); 1073} 1074 1075 1076const Symbol * 1077Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type) 1078{ 1079 Timer scoped_timer(__PRETTY_FUNCTION__, 1080 "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)", 1081 name.AsCString(), 1082 symbol_type); 1083 ObjectFile *objfile = GetObjectFile(); 1084 if (objfile) 1085 { 1086 Symtab *symtab = objfile->GetSymtab(); 1087 if (symtab) 1088 return symtab->FindFirstSymbolWithNameAndType (name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); 1089 } 1090 return NULL; 1091} 1092void 1093Module::SymbolIndicesToSymbolContextList (Symtab *symtab, std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) 1094{ 1095 // No need to protect this call using m_mutex all other method calls are 1096 // already thread safe. 1097 1098 size_t num_indices = symbol_indexes.size(); 1099 if (num_indices > 0) 1100 { 1101 SymbolContext sc; 1102 CalculateSymbolContext (&sc); 1103 for (size_t i = 0; i < num_indices; i++) 1104 { 1105 sc.symbol = symtab->SymbolAtIndex (symbol_indexes[i]); 1106 if (sc.symbol) 1107 sc_list.Append (sc); 1108 } 1109 } 1110} 1111 1112size_t 1113Module::FindFunctionSymbols (const ConstString &name, 1114 uint32_t name_type_mask, 1115 SymbolContextList& sc_list) 1116{ 1117 Timer scoped_timer(__PRETTY_FUNCTION__, 1118 "Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)", 1119 name.AsCString(), 1120 name_type_mask); 1121 ObjectFile *objfile = GetObjectFile (); 1122 if (objfile) 1123 { 1124 Symtab *symtab = objfile->GetSymtab(); 1125 if (symtab) 1126 return symtab->FindFunctionSymbols (name, name_type_mask, sc_list); 1127 } 1128 return 0; 1129} 1130 1131size_t 1132Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list) 1133{ 1134 // No need to protect this call using m_mutex all other method calls are 1135 // already thread safe. 1136 1137 1138 Timer scoped_timer(__PRETTY_FUNCTION__, 1139 "Module::FindSymbolsWithNameAndType (name = %s, type = %i)", 1140 name.AsCString(), 1141 symbol_type); 1142 const size_t initial_size = sc_list.GetSize(); 1143 ObjectFile *objfile = GetObjectFile (); 1144 if (objfile) 1145 { 1146 Symtab *symtab = objfile->GetSymtab(); 1147 if (symtab) 1148 { 1149 std::vector<uint32_t> symbol_indexes; 1150 symtab->FindAllSymbolsWithNameAndType (name, symbol_type, symbol_indexes); 1151 SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); 1152 } 1153 } 1154 return sc_list.GetSize() - initial_size; 1155} 1156 1157size_t 1158Module::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, SymbolType symbol_type, SymbolContextList &sc_list) 1159{ 1160 // No need to protect this call using m_mutex all other method calls are 1161 // already thread safe. 1162 1163 Timer scoped_timer(__PRETTY_FUNCTION__, 1164 "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)", 1165 regex.GetText(), 1166 symbol_type); 1167 const size_t initial_size = sc_list.GetSize(); 1168 ObjectFile *objfile = GetObjectFile (); 1169 if (objfile) 1170 { 1171 Symtab *symtab = objfile->GetSymtab(); 1172 if (symtab) 1173 { 1174 std::vector<uint32_t> symbol_indexes; 1175 symtab->FindAllSymbolsMatchingRexExAndType (regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); 1176 SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); 1177 } 1178 } 1179 return sc_list.GetSize() - initial_size; 1180} 1181 1182const TimeValue & 1183Module::GetModificationTime () const 1184{ 1185 return m_mod_time; 1186} 1187 1188bool 1189Module::IsExecutable () 1190{ 1191 if (GetObjectFile() == NULL) 1192 return false; 1193 else 1194 return GetObjectFile()->IsExecutable(); 1195} 1196 1197bool 1198Module::IsLoadedInTarget (Target *target) 1199{ 1200 ObjectFile *obj_file = GetObjectFile(); 1201 if (obj_file) 1202 { 1203 SectionList *sections = obj_file->GetSectionList(); 1204 if (sections != NULL) 1205 { 1206 size_t num_sections = sections->GetSize(); 1207 for (size_t sect_idx = 0; sect_idx < num_sections; sect_idx++) 1208 { 1209 SectionSP section_sp = sections->GetSectionAtIndex(sect_idx); 1210 if (section_sp->GetLoadBaseAddress(target) != LLDB_INVALID_ADDRESS) 1211 { 1212 return true; 1213 } 1214 } 1215 } 1216 } 1217 return false; 1218} 1219 1220bool 1221Module::LoadScriptingResourceInTarget (Target *target, Error& error) 1222{ 1223 if (!target) 1224 { 1225 error.SetErrorString("invalid destination Target"); 1226 return false; 1227 } 1228 1229 Debugger &debugger = target->GetDebugger(); 1230 const ScriptLanguage script_language = debugger.GetScriptLanguage(); 1231 if (script_language != eScriptLanguageNone) 1232 { 1233 1234 PlatformSP platform_sp(target->GetPlatform()); 1235 1236 if (!platform_sp) 1237 { 1238 error.SetErrorString("invalid Platform"); 1239 return false; 1240 } 1241 1242 FileSpecList file_specs = platform_sp->LocateExecutableScriptingResources (target, 1243 *this); 1244 1245 1246 const uint32_t num_specs = file_specs.GetSize(); 1247 if (num_specs) 1248 { 1249 ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); 1250 if (script_interpreter) 1251 { 1252 for (uint32_t i=0; i<num_specs; ++i) 1253 { 1254 FileSpec scripting_fspec (file_specs.GetFileSpecAtIndex(i)); 1255 if (scripting_fspec && scripting_fspec.Exists()) 1256 { 1257 1258 StreamString scripting_stream; 1259 scripting_fspec.Dump(&scripting_stream); 1260 const bool can_reload = false; 1261 const bool init_lldb_globals = false; 1262 bool did_load = script_interpreter->LoadScriptingModule(scripting_stream.GetData(), can_reload, init_lldb_globals, error); 1263 if (!did_load) 1264 return false; 1265 } 1266 } 1267 } 1268 else 1269 { 1270 error.SetErrorString("invalid ScriptInterpreter"); 1271 return false; 1272 } 1273 } 1274 } 1275 return true; 1276} 1277 1278bool 1279Module::SetArchitecture (const ArchSpec &new_arch) 1280{ 1281 if (!m_arch.IsValid()) 1282 { 1283 m_arch = new_arch; 1284 return true; 1285 } 1286 return m_arch.IsExactMatch(new_arch); 1287} 1288 1289bool 1290Module::SetLoadAddress (Target &target, lldb::addr_t offset, bool &changed) 1291{ 1292 size_t num_loaded_sections = 0; 1293 ObjectFile *objfile = GetObjectFile(); 1294 if (objfile) 1295 { 1296 SectionList *section_list = objfile->GetSectionList (); 1297 if (section_list) 1298 { 1299 const size_t num_sections = section_list->GetSize(); 1300 size_t sect_idx = 0; 1301 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) 1302 { 1303 // Iterate through the object file sections to find the 1304 // first section that starts of file offset zero and that 1305 // has bytes in the file... 1306 SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); 1307 // Only load non-thread specific sections when given a slide 1308 if (section_sp && !section_sp->IsThreadSpecific()) 1309 { 1310 if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + offset)) 1311 ++num_loaded_sections; 1312 } 1313 } 1314 } 1315 } 1316 changed = num_loaded_sections > 0; 1317 return num_loaded_sections > 0; 1318} 1319 1320 1321bool 1322Module::MatchesModuleSpec (const ModuleSpec &module_ref) 1323{ 1324 const UUID &uuid = module_ref.GetUUID(); 1325 1326 if (uuid.IsValid()) 1327 { 1328 // If the UUID matches, then nothing more needs to match... 1329 if (uuid == GetUUID()) 1330 return true; 1331 else 1332 return false; 1333 } 1334 1335 const FileSpec &file_spec = module_ref.GetFileSpec(); 1336 if (file_spec) 1337 { 1338 if (!FileSpec::Equal (file_spec, m_file, file_spec.GetDirectory())) 1339 return false; 1340 } 1341 1342 const FileSpec &platform_file_spec = module_ref.GetPlatformFileSpec(); 1343 if (platform_file_spec) 1344 { 1345 if (!FileSpec::Equal (platform_file_spec, GetPlatformFileSpec (), platform_file_spec.GetDirectory())) 1346 return false; 1347 } 1348 1349 const ArchSpec &arch = module_ref.GetArchitecture(); 1350 if (arch.IsValid()) 1351 { 1352 if (!m_arch.IsCompatibleMatch(arch)) 1353 return false; 1354 } 1355 1356 const ConstString &object_name = module_ref.GetObjectName(); 1357 if (object_name) 1358 { 1359 if (object_name != GetObjectName()) 1360 return false; 1361 } 1362 return true; 1363} 1364 1365bool 1366Module::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const 1367{ 1368 Mutex::Locker locker (m_mutex); 1369 return m_source_mappings.FindFile (orig_spec, new_spec); 1370} 1371 1372bool 1373Module::RemapSourceFile (const char *path, std::string &new_path) const 1374{ 1375 Mutex::Locker locker (m_mutex); 1376 return m_source_mappings.RemapPath(path, new_path); 1377} 1378 1379uint32_t 1380Module::GetVersion (uint32_t *versions, uint32_t num_versions) 1381{ 1382 ObjectFile *obj_file = GetObjectFile(); 1383 if (obj_file) 1384 return obj_file->GetVersion (versions, num_versions); 1385 1386 if (versions && num_versions) 1387 { 1388 for (uint32_t i=0; i<num_versions; ++i) 1389 versions[i] = UINT32_MAX; 1390 } 1391 return 0; 1392} 1393 1394void 1395Module::PrepareForFunctionNameLookup (const ConstString &name, 1396 uint32_t name_type_mask, 1397 ConstString &lookup_name, 1398 uint32_t &lookup_name_type_mask, 1399 bool &match_name_after_lookup) 1400{ 1401 const char *name_cstr = name.GetCString(); 1402 lookup_name_type_mask = eFunctionNameTypeNone; 1403 match_name_after_lookup = false; 1404 const char *base_name_start = NULL; 1405 const char *base_name_end = NULL; 1406 1407 if (name_type_mask & eFunctionNameTypeAuto) 1408 { 1409 if (CPPLanguageRuntime::IsCPPMangledName (name_cstr)) 1410 lookup_name_type_mask = eFunctionNameTypeFull; 1411 else if (ObjCLanguageRuntime::IsPossibleObjCMethodName (name_cstr)) 1412 lookup_name_type_mask = eFunctionNameTypeFull; 1413 else 1414 { 1415 if (ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr)) 1416 lookup_name_type_mask |= eFunctionNameTypeSelector; 1417 1418 if (CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end)) 1419 lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); 1420 } 1421 } 1422 else 1423 { 1424 lookup_name_type_mask = name_type_mask; 1425 if (lookup_name_type_mask & eFunctionNameTypeMethod || name_type_mask & eFunctionNameTypeBase) 1426 { 1427 // If they've asked for a CPP method or function name and it can't be that, we don't 1428 // even need to search for CPP methods or names. 1429 if (!CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end)) 1430 { 1431 lookup_name_type_mask &= ~(eFunctionNameTypeMethod | eFunctionNameTypeBase); 1432 if (lookup_name_type_mask == eFunctionNameTypeNone) 1433 return; 1434 } 1435 } 1436 1437 if (lookup_name_type_mask & eFunctionNameTypeSelector) 1438 { 1439 if (!ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr)) 1440 { 1441 lookup_name_type_mask &= ~(eFunctionNameTypeSelector); 1442 if (lookup_name_type_mask == eFunctionNameTypeNone) 1443 return; 1444 } 1445 } 1446 } 1447 1448 if (base_name_start && 1449 base_name_end && 1450 base_name_start != name_cstr && 1451 base_name_start < base_name_end) 1452 { 1453 // The name supplied was a partial C++ path like "a::count". In this case we want to do a 1454 // lookup on the basename "count" and then make sure any matching results contain "a::count" 1455 // so that it would match "b::a::count" and "a::count". This is why we set "match_name_after_lookup" 1456 // to true 1457 lookup_name.SetCStringWithLength(base_name_start, base_name_end - base_name_start); 1458 match_name_after_lookup = true; 1459 } 1460 else 1461 { 1462 // The name is already correct, just use the exact name as supplied, and we won't need 1463 // to check if any matches contain "name" 1464 lookup_name = name; 1465 match_name_after_lookup = false; 1466 } 1467}