1 //===-- SymbolContext.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/Symbol/SymbolContext.h" 11 12 #include "lldb/Core/Log.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Interpreter/Args.h" 15 #include "lldb/Symbol/CompileUnit.h" 16 #include "lldb/Symbol/ObjectFile.h" 17 #include "lldb/Symbol/Symbol.h" 18 #include "lldb/Symbol/SymbolVendor.h" 19 #include "lldb/Target/Target.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 24 SymbolContext::SymbolContext() : 25 target_sp (), 26 module_sp (), 27 comp_unit (NULL), 28 function (NULL), 29 block (NULL), 30 line_entry (), 31 symbol (NULL) 32 { 33 } 34 35 SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) : 36 target_sp (), 37 module_sp (m), 38 comp_unit (cu), 39 function (f), 40 block (b), 41 line_entry (), 42 symbol (s) 43 { 44 if (le) 45 line_entry = *le; 46 } 47 48 SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) : 49 target_sp (t), 50 module_sp (m), 51 comp_unit (cu), 52 function (f), 53 block (b), 54 line_entry (), 55 symbol (s) 56 { 57 if (le) 58 line_entry = *le; 59 } 60 61 SymbolContext::SymbolContext(const SymbolContext& rhs) : 62 target_sp (rhs.target_sp), 63 module_sp (rhs.module_sp), 64 comp_unit (rhs.comp_unit), 65 function (rhs.function), 66 block (rhs.block), 67 line_entry (rhs.line_entry), 68 symbol (rhs.symbol) 69 { 70 } 71 72 73 SymbolContext::SymbolContext (SymbolContextScope *sc_scope) : 74 target_sp (), 75 module_sp (), 76 comp_unit (NULL), 77 function (NULL), 78 block (NULL), 79 line_entry (), 80 symbol (NULL) 81 { 82 sc_scope->CalculateSymbolContext (this); 83 } 84 85 const SymbolContext& 86 SymbolContext::operator= (const SymbolContext& rhs) 87 { 88 if (this != &rhs) 89 { 90 target_sp = rhs.target_sp; 91 module_sp = rhs.module_sp; 92 comp_unit = rhs.comp_unit; 93 function = rhs.function; 94 block = rhs.block; 95 line_entry = rhs.line_entry; 96 symbol = rhs.symbol; 97 } 98 return *this; 99 } 100 101 void 102 SymbolContext::Clear() 103 { 104 target_sp.reset(); 105 module_sp.reset(); 106 comp_unit = NULL; 107 function = NULL; 108 block = NULL; 109 line_entry.Clear(); 110 symbol = NULL; 111 } 112 113 bool 114 SymbolContext::DumpStopContext 115 ( 116 Stream *s, 117 ExecutionContextScope *exe_scope, 118 const Address &addr, 119 bool show_fullpaths, 120 bool show_module, 121 bool show_inlined_frames 122 ) const 123 { 124 bool dumped_something = false; 125 if (show_module && module_sp) 126 { 127 if (show_fullpaths) 128 *s << module_sp->GetFileSpec(); 129 else 130 *s << module_sp->GetFileSpec().GetFilename(); 131 s->PutChar('`'); 132 dumped_something = true; 133 } 134 135 if (function != NULL) 136 { 137 if (function->GetMangled().GetName()) 138 { 139 dumped_something = true; 140 function->GetMangled().GetName().Dump(s); 141 } 142 143 if (addr.IsValid()) 144 { 145 const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset(); 146 if (function_offset) 147 { 148 dumped_something = true; 149 s->Printf(" + %llu", function_offset); 150 } 151 } 152 153 if (block != NULL) 154 { 155 s->IndentMore(); 156 block->DumpStopContext (s, this, NULL, show_fullpaths, show_inlined_frames); 157 s->IndentLess(); 158 dumped_something = true; 159 } 160 else 161 { 162 if (line_entry.IsValid()) 163 { 164 dumped_something = true; 165 s->PutCString(" at "); 166 if (line_entry.DumpStopContext(s, show_fullpaths)) 167 dumped_something = true; 168 } 169 } 170 } 171 else if (symbol != NULL) 172 { 173 if (symbol->GetMangled().GetName()) 174 { 175 dumped_something = true; 176 symbol->GetMangled().GetName().Dump(s); 177 } 178 179 if (addr.IsValid() && symbol->GetAddressRangePtr()) 180 { 181 const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddressRangePtr()->GetBaseAddress().GetOffset(); 182 if (symbol_offset) 183 { 184 dumped_something = true; 185 s->Printf(" + %llu", symbol_offset); 186 } 187 } 188 } 189 else if (addr.IsValid()) 190 { 191 addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress); 192 dumped_something = true; 193 } 194 return dumped_something; 195 } 196 197 void 198 SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target) const 199 { 200 if (module_sp) 201 { 202 s->Indent(" Module: file = \""); 203 module_sp->GetFileSpec().Dump(s); 204 *s << '"'; 205 if (module_sp->GetArchitecture().IsValid()) 206 s->Printf (", arch = \"%s\"", module_sp->GetArchitecture().GetArchitectureName()); 207 s->EOL(); 208 } 209 210 if (comp_unit != NULL) 211 { 212 s->Indent("CompileUnit: "); 213 comp_unit->GetDescription (s, level); 214 s->EOL(); 215 } 216 217 if (function != NULL) 218 { 219 s->Indent(" Function: "); 220 function->GetDescription (s, level, target); 221 s->EOL(); 222 223 Type *func_type = function->GetType(); 224 if (func_type) 225 { 226 s->Indent(" FuncType: "); 227 func_type->GetDescription (s, level, false); 228 s->EOL(); 229 } 230 } 231 232 if (block != NULL) 233 { 234 std::vector<Block *> blocks; 235 blocks.push_back (block); 236 Block *parent_block = block->GetParent(); 237 238 while (parent_block) 239 { 240 blocks.push_back (parent_block); 241 parent_block = parent_block->GetParent(); 242 } 243 std::vector<Block *>::reverse_iterator pos; 244 std::vector<Block *>::reverse_iterator begin = blocks.rbegin(); 245 std::vector<Block *>::reverse_iterator end = blocks.rend(); 246 for (pos = begin; pos != end; ++pos) 247 { 248 if (pos == begin) 249 s->Indent(" Blocks: "); 250 else 251 s->Indent(" "); 252 (*pos)->GetDescription(s, function, level, target); 253 s->EOL(); 254 } 255 } 256 257 if (line_entry.IsValid()) 258 { 259 s->Indent(" LineEntry: "); 260 line_entry.GetDescription (s, level, comp_unit, target, false); 261 s->EOL(); 262 } 263 264 if (symbol != NULL) 265 { 266 s->Indent(" Symbol: "); 267 symbol->GetDescription(s, level, target); 268 s->EOL(); 269 } 270 } 271 272 uint32_t 273 SymbolContext::GetResolvedMask () const 274 { 275 uint32_t resolved_mask = 0; 276 if (target_sp) resolved_mask |= eSymbolContextTarget; 277 if (module_sp) resolved_mask |= eSymbolContextModule; 278 if (comp_unit) resolved_mask |= eSymbolContextCompUnit; 279 if (function) resolved_mask |= eSymbolContextFunction; 280 if (block) resolved_mask |= eSymbolContextBlock; 281 if (line_entry.IsValid()) resolved_mask |= eSymbolContextLineEntry; 282 if (symbol) resolved_mask |= eSymbolContextSymbol; 283 return resolved_mask; 284 } 285 286 287 void 288 SymbolContext::Dump(Stream *s, Target *target) const 289 { 290 *s << (void *)this << ": "; 291 s->Indent(); 292 s->PutCString("SymbolContext"); 293 s->IndentMore(); 294 s->EOL(); 295 s->IndentMore(); 296 s->Indent(); 297 *s << "Module = " << (void *)module_sp.get() << ' '; 298 if (module_sp) 299 module_sp->GetFileSpec().Dump(s); 300 s->EOL(); 301 s->Indent(); 302 *s << "CompileUnit = " << (void *)comp_unit; 303 if (comp_unit != NULL) 304 *s << " {0x" << comp_unit->GetID() << "} " << *(static_cast<FileSpec*> (comp_unit)); 305 s->EOL(); 306 s->Indent(); 307 *s << "Function = " << (void *)function; 308 if (function != NULL) 309 { 310 *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = "; 311 function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); 312 s->EOL(); 313 s->Indent(); 314 Type* func_type = function->GetType(); 315 if (func_type) 316 { 317 *s << " Type = "; 318 func_type->Dump (s, false); 319 } 320 } 321 s->EOL(); 322 s->Indent(); 323 *s << "Block = " << (void *)block; 324 if (block != NULL) 325 *s << " {0x" << block->GetID() << '}'; 326 // Dump the block and pass it a negative depth to we print all the parent blocks 327 //if (block != NULL) 328 // block->Dump(s, function->GetFileAddress(), INT_MIN); 329 s->EOL(); 330 s->Indent(); 331 *s << "LineEntry = "; 332 line_entry.Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true); 333 s->EOL(); 334 s->Indent(); 335 *s << "Symbol = " << (void *)symbol; 336 if (symbol != NULL && symbol->GetMangled()) 337 *s << ' ' << symbol->GetMangled().GetName().AsCString(); 338 s->EOL(); 339 s->IndentLess(); 340 s->IndentLess(); 341 } 342 343 bool 344 lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs) 345 { 346 return lhs.function == rhs.function 347 && lhs.symbol == rhs.symbol 348 && lhs.module_sp.get() == rhs.module_sp.get() 349 && lhs.comp_unit == rhs.comp_unit 350 && lhs.target_sp.get() == rhs.target_sp.get() 351 && LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0; 352 } 353 354 bool 355 lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs) 356 { 357 return lhs.function != rhs.function 358 || lhs.symbol != rhs.symbol 359 || lhs.module_sp.get() != rhs.module_sp.get() 360 || lhs.comp_unit != rhs.comp_unit 361 || lhs.target_sp.get() != rhs.target_sp.get() 362 || LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0; 363 } 364 365 bool 366 SymbolContext::GetAddressRange (uint32_t scope, 367 uint32_t range_idx, 368 bool use_inline_block_range, 369 AddressRange &range) const 370 { 371 if ((scope & eSymbolContextLineEntry) && line_entry.IsValid()) 372 { 373 range = line_entry.range; 374 return true; 375 } 376 377 if ((scope & eSymbolContextBlock) && (block != NULL)) 378 { 379 if (use_inline_block_range) 380 { 381 Block *inline_block = block->GetContainingInlinedBlock(); 382 if (inline_block) 383 return inline_block->GetRangeAtIndex (range_idx, range); 384 } 385 else 386 { 387 return block->GetRangeAtIndex (range_idx, range); 388 } 389 } 390 391 if ((scope & eSymbolContextFunction) && (function != NULL)) 392 { 393 if (range_idx == 0) 394 { 395 range = function->GetAddressRange(); 396 return true; 397 } 398 } 399 400 if ((scope & eSymbolContextSymbol) && (symbol != NULL) && (symbol->GetAddressRangePtr() != NULL)) 401 { 402 if (range_idx == 0) 403 { 404 range = *symbol->GetAddressRangePtr(); 405 406 if (range.GetByteSize() == 0) 407 { 408 if (module_sp) 409 { 410 ObjectFile *objfile = module_sp->GetObjectFile(); 411 if (objfile) 412 { 413 Symtab *symtab = objfile->GetSymtab(); 414 if (symtab) 415 range.SetByteSize(symtab->CalculateSymbolSize (symbol)); 416 } 417 } 418 } 419 return true; 420 } 421 } 422 range.Clear(); 423 return false; 424 } 425 426 ClangNamespaceDecl 427 SymbolContext::FindNamespace (const ConstString &name) const 428 { 429 ClangNamespaceDecl namespace_decl; 430 if (module_sp) 431 namespace_decl = module_sp->GetSymbolVendor()->FindNamespace (*this, name); 432 return namespace_decl; 433 } 434 435 size_t 436 SymbolContext::FindFunctionsByName (const ConstString &name, 437 bool include_symbols, 438 bool append, 439 SymbolContextList &sc_list) const 440 { 441 if (!append) 442 sc_list.Clear(); 443 444 if (function != NULL) 445 { 446 // FIXME: Look in the class of the current function, if it exists, 447 // for methods matching name. 448 } 449 450 if (module_sp != NULL) 451 module_sp->FindFunctions (name, eFunctionNameTypeBase | eFunctionNameTypeFull, include_symbols, true, sc_list); 452 453 if (target_sp) 454 target_sp->GetImages().FindFunctions (name, eFunctionNameTypeBase | eFunctionNameTypeFull, include_symbols, true, sc_list); 455 456 return sc_list.GetSize(); 457 } 458 459 //lldb::VariableSP 460 //SymbolContext::FindVariableByName (const char *name) const 461 //{ 462 // lldb::VariableSP return_value; 463 // return return_value; 464 //} 465 466 lldb::TypeSP 467 SymbolContext::FindTypeByName (const ConstString &name) const 468 { 469 lldb::TypeSP return_value; 470 471 TypeList types; 472 473 if (module_sp && module_sp->FindTypes (*this, name, false, 1, types)) 474 return types.GetTypeAtIndex(0); 475 476 SymbolContext sc_for_global_search; 477 478 sc_for_global_search.target_sp = target_sp; 479 480 if (!return_value.get() && target_sp && target_sp->GetImages().FindTypes (sc_for_global_search, name, false, 1, types)) 481 return types.GetTypeAtIndex(0); 482 483 return return_value; 484 } 485 486 //---------------------------------------------------------------------- 487 // 488 // SymbolContextSpecifier 489 // 490 //---------------------------------------------------------------------- 491 492 bool 493 SymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type) 494 { 495 bool return_value = true; 496 switch (type) 497 { 498 case eNothingSpecified: 499 Clear(); 500 break; 501 case eLineStartSpecified: 502 m_start_line = line_no; 503 m_type |= eLineStartSpecified; 504 break; 505 case eLineEndSpecified: 506 m_end_line = line_no; 507 m_type |= eLineEndSpecified; 508 break; 509 default: 510 return_value = false; 511 break; 512 } 513 return return_value; 514 } 515 516 bool 517 SymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type) 518 { 519 bool return_value = true; 520 switch (type) 521 { 522 case eNothingSpecified: 523 Clear(); 524 break; 525 case eModuleSpecified: 526 { 527 // See if we can find the Module, if so stick it in the SymbolContext. 528 FileSpec module_spec(spec_string, false); 529 lldb::ModuleSP module_sp = m_target_sp->GetImages().FindFirstModuleForFileSpec (module_spec, NULL, NULL); 530 m_type |= eModuleSpecified; 531 if (module_sp) 532 m_module_sp = module_sp; 533 else 534 m_module_spec.assign (spec_string); 535 } 536 break; 537 case eFileSpecified: 538 // CompUnits can't necessarily be resolved here, since an inlined function might show up in 539 // a number of CompUnits. Instead we just convert to a FileSpec and store it away. 540 m_file_spec_ap.reset (new FileSpec (spec_string, false)); 541 m_type |= eFileSpecified; 542 break; 543 case eLineStartSpecified: 544 m_start_line = Args::StringToSInt32(spec_string, 0, 0, &return_value); 545 if (return_value) 546 m_type |= eLineStartSpecified; 547 break; 548 case eLineEndSpecified: 549 m_end_line = Args::StringToSInt32(spec_string, 0, 0, &return_value); 550 if (return_value) 551 m_type |= eLineEndSpecified; 552 break; 553 case eFunctionSpecified: 554 m_function_spec.assign(spec_string); 555 m_type |= eFunctionSpecified; 556 break; 557 case eClassOrNamespaceSpecified: 558 Clear(); 559 m_class_name.assign (spec_string); 560 m_type = eClassOrNamespaceSpecified; 561 break; 562 case eAddressRangeSpecified: 563 // Not specified yet... 564 break; 565 } 566 567 return return_value; 568 } 569 570 void 571 SymbolContextSpecifier::Clear() 572 { 573 m_module_spec.clear(); 574 m_file_spec_ap.reset(); 575 m_function_spec.clear(); 576 m_class_name.clear(); 577 m_start_line = 0; 578 m_end_line = 0; 579 m_address_range_ap.reset(); 580 581 m_type = eNothingSpecified; 582 } 583 584 bool 585 SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) 586 { 587 if (m_type == eNothingSpecified) 588 return true; 589 590 if (m_target_sp.get() != sc.target_sp.get()) 591 return false; 592 593 if (m_type & eModuleSpecified) 594 { 595 if (sc.module_sp) 596 { 597 if (m_module_sp.get() != NULL) 598 { 599 if (m_module_sp.get() != sc.module_sp.get()) 600 return false; 601 } 602 else 603 { 604 FileSpec module_file_spec (m_module_spec.c_str(), false); 605 if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false)) 606 return false; 607 } 608 } 609 } 610 if (m_type & eFileSpecified) 611 { 612 if (m_file_spec_ap.get()) 613 { 614 // If we don't have a block or a comp_unit, then we aren't going to match a source file. 615 if (sc.block == NULL && sc.comp_unit == NULL) 616 return false; 617 618 // Check if the block is present, and if so is it inlined: 619 bool was_inlined = false; 620 if (sc.block != NULL) 621 { 622 const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo(); 623 if (inline_info != NULL) 624 { 625 was_inlined = true; 626 if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false)) 627 return false; 628 } 629 } 630 631 // Next check the comp unit, but only if the SymbolContext was not inlined. 632 if (!was_inlined && sc.comp_unit != NULL) 633 { 634 if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false)) 635 return false; 636 } 637 } 638 } 639 if (m_type & eLineStartSpecified 640 || m_type & eLineEndSpecified) 641 { 642 if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line) 643 return false; 644 } 645 646 if (m_type & eFunctionSpecified) 647 { 648 // First check the current block, and if it is inlined, get the inlined function name: 649 bool was_inlined = false; 650 ConstString func_name(m_function_spec.c_str()); 651 652 if (sc.block != NULL) 653 { 654 const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo(); 655 if (inline_info != NULL) 656 { 657 was_inlined = true; 658 const Mangled &name = inline_info->GetMangled(); 659 if (!name.NameMatches (func_name)) 660 return false; 661 } 662 } 663 // If it wasn't inlined, check the name in the function or symbol: 664 if (!was_inlined) 665 { 666 if (sc.function != NULL) 667 { 668 if (!sc.function->GetMangled().NameMatches(func_name)) 669 return false; 670 } 671 else if (sc.symbol != NULL) 672 { 673 if (!sc.symbol->GetMangled().NameMatches(func_name)) 674 return false; 675 } 676 } 677 678 679 } 680 681 return true; 682 } 683 684 bool 685 SymbolContextSpecifier::AddressMatches(lldb::addr_t addr) 686 { 687 if (m_type & eAddressRangeSpecified) 688 { 689 690 } 691 else 692 { 693 Address match_address (addr, NULL); 694 SymbolContext sc; 695 m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc); 696 return SymbolContextMatches(sc); 697 } 698 return true; 699 } 700 701 void 702 SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const 703 { 704 char path_str[PATH_MAX + 1]; 705 706 if (m_type == eNothingSpecified) 707 { 708 s->Printf ("Nothing specified.\n"); 709 } 710 711 if (m_type == eModuleSpecified) 712 { 713 s->Indent(); 714 if (m_module_sp) 715 { 716 m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX); 717 s->Printf ("Module: %s\n", path_str); 718 } 719 else 720 s->Printf ("Module: %s\n", m_module_spec.c_str()); 721 } 722 723 if (m_type == eFileSpecified && m_file_spec_ap.get() != NULL) 724 { 725 m_file_spec_ap->GetPath (path_str, PATH_MAX); 726 s->Indent(); 727 s->Printf ("File: %s", path_str); 728 if (m_type == eLineStartSpecified) 729 { 730 s->Printf (" from line %d", m_start_line); 731 if (m_type == eLineEndSpecified) 732 s->Printf ("to line %d", m_end_line); 733 else 734 s->Printf ("to end", m_end_line); 735 } 736 else if (m_type == eLineEndSpecified) 737 { 738 s->Printf (" from start to line %d", m_end_line); 739 } 740 s->Printf (".\n"); 741 } 742 743 if (m_type == eLineStartSpecified) 744 { 745 s->Indent(); 746 s->Printf ("From line %d", m_start_line); 747 if (m_type == eLineEndSpecified) 748 s->Printf ("to line %d", m_end_line); 749 else 750 s->Printf ("to end", m_end_line); 751 s->Printf (".\n"); 752 } 753 else if (m_type == eLineEndSpecified) 754 { 755 s->Printf ("From start to line %d.\n", m_end_line); 756 } 757 758 if (m_type == eFunctionSpecified) 759 { 760 s->Indent(); 761 s->Printf ("Function: %s.\n", m_function_spec.c_str()); 762 } 763 764 if (m_type == eClassOrNamespaceSpecified) 765 { 766 s->Indent(); 767 s->Printf ("Class name: %s.\n", m_class_name.c_str()); 768 } 769 770 if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != NULL) 771 { 772 s->Indent(); 773 s->PutCString ("Address range: "); 774 m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); 775 s->PutCString ("\n"); 776 } 777 } 778 779 //---------------------------------------------------------------------- 780 // 781 // SymbolContextList 782 // 783 //---------------------------------------------------------------------- 784 785 786 SymbolContextList::SymbolContextList() : 787 m_symbol_contexts() 788 { 789 } 790 791 SymbolContextList::~SymbolContextList() 792 { 793 } 794 795 void 796 SymbolContextList::Append(const SymbolContext& sc) 797 { 798 m_symbol_contexts.push_back(sc); 799 } 800 801 bool 802 SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function) 803 { 804 collection::iterator pos, end = m_symbol_contexts.end(); 805 for (pos = m_symbol_contexts.begin(); pos != end; ++pos) 806 { 807 if (*pos == sc) 808 return false; 809 } 810 if (merge_symbol_into_function 811 && sc.symbol != NULL 812 && sc.comp_unit == NULL 813 && sc.function == NULL 814 && sc.block == NULL 815 && sc.line_entry.IsValid() == false) 816 { 817 const AddressRange *symbol_range = sc.symbol->GetAddressRangePtr(); 818 if (symbol_range) 819 { 820 for (pos = m_symbol_contexts.begin(); pos != end; ++pos) 821 { 822 if (pos->function) 823 { 824 if (pos->function->GetAddressRange().GetBaseAddress() == symbol_range->GetBaseAddress()) 825 { 826 // Do we already have a function with this symbol? 827 if (pos->symbol == sc.symbol) 828 return false; 829 if (pos->symbol == NULL) 830 { 831 pos->symbol = sc.symbol; 832 return false; 833 } 834 } 835 } 836 } 837 } 838 } 839 m_symbol_contexts.push_back(sc); 840 return true; 841 } 842 843 void 844 SymbolContextList::Clear() 845 { 846 m_symbol_contexts.clear(); 847 } 848 849 void 850 SymbolContextList::Dump(Stream *s, Target *target) const 851 { 852 853 *s << (void *)this << ": "; 854 s->Indent(); 855 s->PutCString("SymbolContextList"); 856 s->EOL(); 857 s->IndentMore(); 858 859 collection::const_iterator pos, end = m_symbol_contexts.end(); 860 for (pos = m_symbol_contexts.begin(); pos != end; ++pos) 861 { 862 pos->Dump(s, target); 863 } 864 s->IndentLess(); 865 } 866 867 bool 868 SymbolContextList::GetContextAtIndex(uint32_t idx, SymbolContext& sc) const 869 { 870 if (idx < m_symbol_contexts.size()) 871 { 872 sc = m_symbol_contexts[idx]; 873 return true; 874 } 875 return false; 876 } 877 878 bool 879 SymbolContextList::RemoveContextAtIndex (uint32_t idx) 880 { 881 if (idx < m_symbol_contexts.size()) 882 { 883 m_symbol_contexts.erase(m_symbol_contexts.begin() + idx); 884 return true; 885 } 886 return false; 887 } 888 889 uint32_t 890 SymbolContextList::GetSize() const 891 { 892 return m_symbol_contexts.size(); 893 } 894 895 uint32_t 896 SymbolContextList::NumLineEntriesWithLine (uint32_t line) const 897 { 898 uint32_t match_count = 0; 899 const uint32_t size = m_symbol_contexts.size(); 900 for (uint32_t idx = 0; idx<size; ++idx) 901 { 902 if (m_symbol_contexts[idx].line_entry.line == line) 903 ++match_count; 904 } 905 return match_count; 906 } 907 908