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