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