1 //===-- SymbolContext.cpp ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Symbol/SymbolContext.h"
12 #include "lldb/Core/Log.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/ModuleSpec.h"
15 #include "lldb/Host/Host.h"
16 #include "lldb/Host/StringConvert.h"
17 #include "lldb/Symbol/Block.h"
18 #include "lldb/Symbol/ClangASTContext.h"
19 #include "lldb/Symbol/CompileUnit.h"
20 #include "lldb/Symbol/ObjectFile.h"
21 #include "lldb/Symbol/Symbol.h"
22 #include "lldb/Symbol/SymbolFile.h"
23 #include "lldb/Symbol/SymbolVendor.h"
24 #include "lldb/Symbol/Variable.h"
25 #include "lldb/Target/Target.h"
28 using namespace lldb_private;
30 SymbolContext::SymbolContext() :
42 SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
56 SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
70 SymbolContext::SymbolContext(const SymbolContext& rhs) :
71 target_sp (rhs.target_sp),
72 module_sp (rhs.module_sp),
73 comp_unit (rhs.comp_unit),
74 function (rhs.function),
76 line_entry (rhs.line_entry),
78 variable (rhs.variable)
83 SymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
93 sc_scope->CalculateSymbolContext (this);
96 SymbolContext::~SymbolContext ()
101 SymbolContext::operator= (const SymbolContext& rhs)
105 target_sp = rhs.target_sp;
106 module_sp = rhs.module_sp;
107 comp_unit = rhs.comp_unit;
108 function = rhs.function;
110 line_entry = rhs.line_entry;
112 variable = rhs.variable;
118 SymbolContext::Clear(bool clear_target)
132 SymbolContext::DumpStopContext (
134 ExecutionContextScope *exe_scope,
138 bool show_inlined_frames,
139 bool show_function_arguments,
140 bool show_function_name
143 bool dumped_something = false;
144 if (show_module && module_sp)
147 *s << module_sp->GetFileSpec();
149 *s << module_sp->GetFileSpec().GetFilename();
151 dumped_something = true;
154 if (function != nullptr)
156 SymbolContext inline_parent_sc;
157 Address inline_parent_addr;
158 if (show_function_name == false)
161 dumped_something = true;
166 if (show_function_arguments == false)
167 name = function->GetNameNoArguments();
169 name = function->GetName();
176 const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset();
177 if (show_function_name == false)
179 // Print +offset even if offset is 0
180 dumped_something = true;
181 s->Printf("+%" PRIu64 ">", function_offset);
183 else if (function_offset)
185 dumped_something = true;
186 s->Printf(" + %" PRIu64, function_offset);
190 if (GetParentOfInlinedScope (addr, inline_parent_sc, inline_parent_addr))
192 dumped_something = true;
193 Block *inlined_block = block->GetContainingInlinedBlock();
194 const InlineFunctionInfo* inlined_block_info = inlined_block->GetInlinedFunctionInfo();
195 s->Printf (" [inlined] %s", inlined_block_info->GetName(function->GetLanguage()).GetCString());
197 lldb_private::AddressRange block_range;
198 if (inlined_block->GetRangeContainingAddress(addr, block_range))
200 const addr_t inlined_function_offset = addr.GetOffset() - block_range.GetBaseAddress().GetOffset();
201 if (inlined_function_offset)
203 s->Printf(" + %" PRIu64, inlined_function_offset);
206 const Declaration &call_site = inlined_block_info->GetCallSite();
207 if (call_site.IsValid())
209 s->PutCString(" at ");
210 call_site.DumpStopContext (s, show_fullpaths);
212 if (show_inlined_frames)
216 const bool show_function_name = true;
217 return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames, show_function_arguments, show_function_name);
222 if (line_entry.IsValid())
224 dumped_something = true;
225 s->PutCString(" at ");
226 if (line_entry.DumpStopContext(s, show_fullpaths))
227 dumped_something = true;
231 else if (symbol != nullptr)
233 if (show_function_name == false)
236 dumped_something = true;
238 else if (symbol->GetName())
240 dumped_something = true;
241 if (symbol->GetType() == eSymbolTypeTrampoline)
242 s->PutCString("symbol stub for: ");
243 symbol->GetName().Dump(s);
246 if (addr.IsValid() && symbol->ValueIsAddress())
248 const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddressRef().GetOffset();
249 if (show_function_name == false)
251 // Print +offset even if offset is 0
252 dumped_something = true;
253 s->Printf("+%" PRIu64 ">", symbol_offset);
255 else if (symbol_offset)
257 dumped_something = true;
258 s->Printf(" + %" PRIu64, symbol_offset);
262 else if (addr.IsValid())
264 addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
265 dumped_something = true;
267 return dumped_something;
271 SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target) const
275 s->Indent(" Module: file = \"");
276 module_sp->GetFileSpec().Dump(s);
278 if (module_sp->GetArchitecture().IsValid())
279 s->Printf (", arch = \"%s\"", module_sp->GetArchitecture().GetArchitectureName());
283 if (comp_unit != nullptr)
285 s->Indent("CompileUnit: ");
286 comp_unit->GetDescription (s, level);
290 if (function != nullptr)
292 s->Indent(" Function: ");
293 function->GetDescription (s, level, target);
296 Type *func_type = function->GetType();
299 s->Indent(" FuncType: ");
300 func_type->GetDescription (s, level, false);
305 if (block != nullptr)
307 std::vector<Block *> blocks;
308 blocks.push_back (block);
309 Block *parent_block = block->GetParent();
313 blocks.push_back (parent_block);
314 parent_block = parent_block->GetParent();
316 std::vector<Block *>::reverse_iterator pos;
317 std::vector<Block *>::reverse_iterator begin = blocks.rbegin();
318 std::vector<Block *>::reverse_iterator end = blocks.rend();
319 for (pos = begin; pos != end; ++pos)
322 s->Indent(" Blocks: ");
325 (*pos)->GetDescription(s, function, level, target);
330 if (line_entry.IsValid())
332 s->Indent(" LineEntry: ");
333 line_entry.GetDescription (s, level, comp_unit, target, false);
337 if (symbol != nullptr)
339 s->Indent(" Symbol: ");
340 symbol->GetDescription(s, level, target);
344 if (variable != nullptr)
346 s->Indent(" Variable: ");
348 s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID());
350 switch (variable->GetScope())
352 case eValueTypeVariableGlobal:
353 s->PutCString("kind = global, ");
356 case eValueTypeVariableStatic:
357 s->PutCString("kind = static, ");
360 case eValueTypeVariableArgument:
361 s->PutCString("kind = argument, ");
364 case eValueTypeVariableLocal:
365 s->PutCString("kind = local, ");
372 s->Printf ("name = \"%s\"\n", variable->GetName().GetCString());
377 SymbolContext::GetResolvedMask () const
379 uint32_t resolved_mask = 0;
380 if (target_sp) resolved_mask |= eSymbolContextTarget;
381 if (module_sp) resolved_mask |= eSymbolContextModule;
382 if (comp_unit) resolved_mask |= eSymbolContextCompUnit;
383 if (function) resolved_mask |= eSymbolContextFunction;
384 if (block) resolved_mask |= eSymbolContextBlock;
385 if (line_entry.IsValid()) resolved_mask |= eSymbolContextLineEntry;
386 if (symbol) resolved_mask |= eSymbolContextSymbol;
387 if (variable) resolved_mask |= eSymbolContextVariable;
388 return resolved_mask;
392 SymbolContext::Dump(Stream *s, Target *target) const
396 s->PutCString("SymbolContext");
401 *s << "Module = " << module_sp.get() << ' ';
403 module_sp->GetFileSpec().Dump(s);
406 *s << "CompileUnit = " << comp_unit;
407 if (comp_unit != nullptr)
408 *s << " {0x" << comp_unit->GetID() << "} " << *(static_cast<FileSpec*> (comp_unit));
411 *s << "Function = " << function;
412 if (function != nullptr)
414 *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = ";
415 function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
418 Type* func_type = function->GetType();
422 func_type->Dump (s, false);
427 *s << "Block = " << block;
428 if (block != nullptr)
429 *s << " {0x" << block->GetID() << '}';
430 // Dump the block and pass it a negative depth to we print all the parent blocks
432 // block->Dump(s, function->GetFileAddress(), INT_MIN);
435 *s << "LineEntry = ";
436 line_entry.Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
439 *s << "Symbol = " << symbol;
440 if (symbol != nullptr && symbol->GetMangled())
441 *s << ' ' << symbol->GetName().AsCString();
443 *s << "Variable = " << variable;
444 if (variable != nullptr)
446 *s << " {0x" << variable->GetID() << "} " << variable->GetType()->GetName();
454 lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs)
456 return lhs.function == rhs.function
457 && lhs.symbol == rhs.symbol
458 && lhs.module_sp.get() == rhs.module_sp.get()
459 && lhs.comp_unit == rhs.comp_unit
460 && lhs.target_sp.get() == rhs.target_sp.get()
461 && LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0
462 && lhs.variable == rhs.variable;
466 lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs)
468 return lhs.function != rhs.function
469 || lhs.symbol != rhs.symbol
470 || lhs.module_sp.get() != rhs.module_sp.get()
471 || lhs.comp_unit != rhs.comp_unit
472 || lhs.target_sp.get() != rhs.target_sp.get()
473 || LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0
474 || lhs.variable != rhs.variable;
478 SymbolContext::GetAddressRange (uint32_t scope,
480 bool use_inline_block_range,
481 AddressRange &range) const
483 if ((scope & eSymbolContextLineEntry) && line_entry.IsValid())
485 range = line_entry.range;
489 if ((scope & eSymbolContextBlock) && (block != nullptr))
491 if (use_inline_block_range)
493 Block *inline_block = block->GetContainingInlinedBlock();
495 return inline_block->GetRangeAtIndex (range_idx, range);
499 return block->GetRangeAtIndex (range_idx, range);
503 if ((scope & eSymbolContextFunction) && (function != nullptr))
507 range = function->GetAddressRange();
512 if ((scope & eSymbolContextSymbol) && (symbol != nullptr))
516 if (symbol->ValueIsAddress())
518 range.GetBaseAddress() = symbol->GetAddressRef();
519 range.SetByteSize (symbol->GetByteSize());
529 SymbolContext::GetLanguage () const
533 (lang = function->GetLanguage()) != eLanguageTypeUnknown)
538 (lang = variable->GetLanguage()) != eLanguageTypeUnknown)
543 (lang = symbol->GetLanguage()) != eLanguageTypeUnknown)
547 else if (comp_unit &&
548 (lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown)
554 // If all else fails, try to guess the language from the name.
555 return symbol->GetMangled().GuessLanguage();
557 return eLanguageTypeUnknown;
561 SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc,
562 SymbolContext &next_frame_sc,
563 Address &next_frame_pc) const
565 next_frame_sc.Clear(false);
566 next_frame_pc.Clear();
570 //const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
572 // In order to get the parent of an inlined function we first need to
573 // see if we are in an inlined block as "this->block" could be an
574 // inlined block, or a parent of "block" could be. So lets check if
575 // this block or one of this blocks parents is an inlined function.
576 Block *curr_inlined_block = block->GetContainingInlinedBlock();
577 if (curr_inlined_block)
579 // "this->block" is contained in an inline function block, so to
580 // get the scope above the inlined block, we get the parent of the
581 // inlined block itself
582 Block *next_frame_block = curr_inlined_block->GetParent();
583 // Now calculate the symbol context of the containing block
584 next_frame_block->CalculateSymbolContext (&next_frame_sc);
586 // If we get here we weren't able to find the return line entry using the nesting of the blocks and
587 // the line table. So just use the call site info from our inlined block.
590 if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range))
592 // To see there this new frame block it, we need to look at the
593 // call site information from
594 const InlineFunctionInfo* curr_inlined_block_inlined_info = curr_inlined_block->GetInlinedFunctionInfo();
595 next_frame_pc = range.GetBaseAddress();
596 next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;
597 next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile();
598 next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine();
599 next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn();
604 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
608 log->Printf ("warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64,
609 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
611 #ifdef LLDB_CONFIGURATION_DEBUG
614 ObjectFile *objfile = NULL;
617 SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
620 SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
622 objfile = symbol_file->GetObjectFile();
627 Host::SystemLog (Host::eSystemLogWarning,
628 "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 " in %s\n",
629 curr_inlined_block->GetID(),
630 curr_frame_pc.GetFileAddress(),
631 objfile->GetFileSpec().GetPath().c_str());
635 Host::SystemLog (Host::eSystemLogWarning,
636 "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n",
637 curr_inlined_block->GetID(),
638 curr_frame_pc.GetFileAddress());
650 SymbolContext::GetFunctionBlock ()
656 // If this symbol context has a block, check to see if this block
657 // is itself, or is contained within a block with inlined function
658 // information. If so, then the inlined block is the block that
659 // defines the function.
660 Block *inlined_block = block->GetContainingInlinedBlock();
662 return inlined_block;
664 // The block in this symbol context is not inside an inlined
665 // block, so the block that defines the function is the function's
666 // top level block, which is returned below.
669 // There is no block information in this symbol context, so we must
670 // assume that the block that is desired is the top level block of
671 // the function itself.
672 return &function->GetBlock(true);
678 SymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language,
679 bool &is_instance_method,
680 ConstString &language_object_name)
684 Block *function_block = GetFunctionBlock();
687 CompilerDeclContext decl_ctx = function_block->GetDeclContext();
689 return decl_ctx.IsClassMethod(&language, &is_instance_method, &language_object_name);
695 SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const
697 Block * curr_block = block;
698 bool isInlinedblock = false;
699 if (curr_block != nullptr && curr_block->GetContainingInlinedBlock() != nullptr)
700 isInlinedblock = true;
702 //----------------------------------------------------------------------
703 // Find all types that match the current block if we have one and put
704 // them first in the list. Keep iterating up through all blocks.
705 //----------------------------------------------------------------------
706 while (curr_block != nullptr && !isInlinedblock)
708 type_map.ForEach([curr_block, &type_list](const lldb::TypeSP& type_sp) -> bool {
709 SymbolContextScope *scs = type_sp->GetSymbolContextScope();
710 if (scs && curr_block == scs->CalculateSymbolContextBlock())
711 type_list.Insert(type_sp);
712 return true; // Keep iterating
715 // Remove any entries that are now in "type_list" from "type_map"
716 // since we can't remove from type_map while iterating
717 type_list.ForEach([&type_map](const lldb::TypeSP& type_sp) -> bool {
718 type_map.Remove(type_sp);
719 return true; // Keep iterating
721 curr_block = curr_block->GetParent();
723 //----------------------------------------------------------------------
724 // Find all types that match the current function, if we have onem, and
725 // put them next in the list.
726 //----------------------------------------------------------------------
727 if (function != nullptr && !type_map.Empty())
729 const size_t old_type_list_size = type_list.GetSize();
730 type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
731 SymbolContextScope *scs = type_sp->GetSymbolContextScope();
732 if (scs && function == scs->CalculateSymbolContextFunction())
733 type_list.Insert(type_sp);
734 return true; // Keep iterating
737 // Remove any entries that are now in "type_list" from "type_map"
738 // since we can't remove from type_map while iterating
739 const size_t new_type_list_size = type_list.GetSize();
740 if (new_type_list_size > old_type_list_size)
742 for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
743 type_map.Remove(type_list.GetTypeAtIndex(i));
746 //----------------------------------------------------------------------
747 // Find all types that match the current compile unit, if we have one,
748 // and put them next in the list.
749 //----------------------------------------------------------------------
750 if (comp_unit != nullptr && !type_map.Empty())
752 const size_t old_type_list_size = type_list.GetSize();
754 type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
755 SymbolContextScope *scs = type_sp->GetSymbolContextScope();
756 if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit())
757 type_list.Insert(type_sp);
758 return true; // Keep iterating
761 // Remove any entries that are now in "type_list" from "type_map"
762 // since we can't remove from type_map while iterating
763 const size_t new_type_list_size = type_list.GetSize();
764 if (new_type_list_size > old_type_list_size)
766 for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
767 type_map.Remove(type_list.GetTypeAtIndex(i));
770 //----------------------------------------------------------------------
771 // Find all types that match the current module, if we have one, and put
772 // them next in the list.
773 //----------------------------------------------------------------------
774 if (module_sp && !type_map.Empty())
776 const size_t old_type_list_size = type_list.GetSize();
777 type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
778 SymbolContextScope *scs = type_sp->GetSymbolContextScope();
779 if (scs && module_sp == scs->CalculateSymbolContextModule())
780 type_list.Insert(type_sp);
781 return true; // Keep iterating
783 // Remove any entries that are now in "type_list" from "type_map"
784 // since we can't remove from type_map while iterating
785 const size_t new_type_list_size = type_list.GetSize();
786 if (new_type_list_size > old_type_list_size)
788 for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
789 type_map.Remove(type_list.GetTypeAtIndex(i));
792 //----------------------------------------------------------------------
793 // Any types that are left get copied into the list an any order.
794 //----------------------------------------------------------------------
795 if (!type_map.Empty())
797 type_map.ForEach([&type_list](const lldb::TypeSP& type_sp) -> bool {
798 type_list.Insert(type_sp);
799 return true; // Keep iterating
805 SymbolContext::GetFunctionName (Mangled::NamePreference preference) const
811 Block *inlined_block = block->GetContainingInlinedBlock();
815 const InlineFunctionInfo *inline_info = inlined_block->GetInlinedFunctionInfo();
817 return inline_info->GetName(function->GetLanguage());
820 return function->GetMangled().GetName(function->GetLanguage(), preference);
822 else if (symbol && symbol->ValueIsAddress())
824 return symbol->GetMangled().GetName(symbol->GetLanguage(), preference);
828 // No function, return an empty string.
829 return ConstString();
834 SymbolContext::GetFunctionStartLineEntry () const
836 LineEntry line_entry;
840 Block *inlined_block = block->GetContainingInlinedBlock();
843 if (inlined_block->GetStartAddress (start_addr))
845 if (start_addr.CalculateSymbolContextLineEntry (line_entry))
854 if (function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry(line_entry))
860 //----------------------------------------------------------------------
862 // SymbolContextSpecifier
864 //----------------------------------------------------------------------
866 SymbolContextSpecifier::SymbolContextSpecifier (const TargetSP &target_sp) :
867 m_target_sp (target_sp),
875 m_address_range_ap (),
876 m_type (eNothingSpecified)
880 SymbolContextSpecifier::~SymbolContextSpecifier()
885 SymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type)
887 bool return_value = true;
890 case eNothingSpecified:
893 case eLineStartSpecified:
894 m_start_line = line_no;
895 m_type |= eLineStartSpecified;
897 case eLineEndSpecified:
898 m_end_line = line_no;
899 m_type |= eLineEndSpecified;
902 return_value = false;
909 SymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type)
911 bool return_value = true;
914 case eNothingSpecified:
917 case eModuleSpecified:
919 // See if we can find the Module, if so stick it in the SymbolContext.
920 FileSpec module_file_spec(spec_string, false);
921 ModuleSpec module_spec (module_file_spec);
922 lldb::ModuleSP module_sp (m_target_sp->GetImages().FindFirstModule (module_spec));
923 m_type |= eModuleSpecified;
925 m_module_sp = module_sp;
927 m_module_spec.assign (spec_string);
931 // CompUnits can't necessarily be resolved here, since an inlined function might show up in
932 // a number of CompUnits. Instead we just convert to a FileSpec and store it away.
933 m_file_spec_ap.reset (new FileSpec (spec_string, false));
934 m_type |= eFileSpecified;
936 case eLineStartSpecified:
937 m_start_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value);
939 m_type |= eLineStartSpecified;
941 case eLineEndSpecified:
942 m_end_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value);
944 m_type |= eLineEndSpecified;
946 case eFunctionSpecified:
947 m_function_spec.assign(spec_string);
948 m_type |= eFunctionSpecified;
950 case eClassOrNamespaceSpecified:
952 m_class_name.assign (spec_string);
953 m_type = eClassOrNamespaceSpecified;
955 case eAddressRangeSpecified:
956 // Not specified yet...
964 SymbolContextSpecifier::Clear()
966 m_module_spec.clear();
967 m_file_spec_ap.reset();
968 m_function_spec.clear();
969 m_class_name.clear();
972 m_address_range_ap.reset();
974 m_type = eNothingSpecified;
978 SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
980 if (m_type == eNothingSpecified)
983 if (m_target_sp.get() != sc.target_sp.get())
986 if (m_type & eModuleSpecified)
990 if (m_module_sp.get() != nullptr)
992 if (m_module_sp.get() != sc.module_sp.get())
997 FileSpec module_file_spec (m_module_spec.c_str(), false);
998 if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false))
1003 if (m_type & eFileSpecified)
1005 if (m_file_spec_ap.get())
1007 // If we don't have a block or a comp_unit, then we aren't going to match a source file.
1008 if (sc.block == nullptr && sc.comp_unit == nullptr)
1011 // Check if the block is present, and if so is it inlined:
1012 bool was_inlined = false;
1013 if (sc.block != nullptr)
1015 const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
1016 if (inline_info != nullptr)
1019 if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false))
1024 // Next check the comp unit, but only if the SymbolContext was not inlined.
1025 if (!was_inlined && sc.comp_unit != nullptr)
1027 if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false))
1032 if (m_type & eLineStartSpecified
1033 || m_type & eLineEndSpecified)
1035 if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
1039 if (m_type & eFunctionSpecified)
1041 // First check the current block, and if it is inlined, get the inlined function name:
1042 bool was_inlined = false;
1043 ConstString func_name(m_function_spec.c_str());
1045 if (sc.block != nullptr)
1047 const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
1048 if (inline_info != nullptr)
1051 const Mangled &name = inline_info->GetMangled();
1052 if (!name.NameMatches (func_name, sc.function->GetLanguage()))
1056 // If it wasn't inlined, check the name in the function or symbol:
1059 if (sc.function != nullptr)
1061 if (!sc.function->GetMangled().NameMatches(func_name, sc.function->GetLanguage()))
1064 else if (sc.symbol != nullptr)
1066 if (!sc.symbol->GetMangled().NameMatches(func_name, sc.symbol->GetLanguage()))
1078 SymbolContextSpecifier::AddressMatches(lldb::addr_t addr)
1080 if (m_type & eAddressRangeSpecified)
1086 Address match_address (addr, nullptr);
1088 m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc);
1089 return SymbolContextMatches(sc);
1095 SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const
1097 char path_str[PATH_MAX + 1];
1099 if (m_type == eNothingSpecified)
1101 s->Printf ("Nothing specified.\n");
1104 if (m_type == eModuleSpecified)
1109 m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX);
1110 s->Printf ("Module: %s\n", path_str);
1113 s->Printf ("Module: %s\n", m_module_spec.c_str());
1116 if (m_type == eFileSpecified && m_file_spec_ap.get() != nullptr)
1118 m_file_spec_ap->GetPath (path_str, PATH_MAX);
1120 s->Printf ("File: %s", path_str);
1121 if (m_type == eLineStartSpecified)
1123 s->Printf (" from line %" PRIu64 "", (uint64_t)m_start_line);
1124 if (m_type == eLineEndSpecified)
1125 s->Printf ("to line %" PRIu64 "", (uint64_t)m_end_line);
1127 s->Printf ("to end");
1129 else if (m_type == eLineEndSpecified)
1131 s->Printf (" from start to line %" PRIu64 "", (uint64_t)m_end_line);
1136 if (m_type == eLineStartSpecified)
1139 s->Printf ("From line %" PRIu64 "", (uint64_t)m_start_line);
1140 if (m_type == eLineEndSpecified)
1141 s->Printf ("to line %" PRIu64 "", (uint64_t)m_end_line);
1143 s->Printf ("to end");
1146 else if (m_type == eLineEndSpecified)
1148 s->Printf ("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line);
1151 if (m_type == eFunctionSpecified)
1154 s->Printf ("Function: %s.\n", m_function_spec.c_str());
1157 if (m_type == eClassOrNamespaceSpecified)
1160 s->Printf ("Class name: %s.\n", m_class_name.c_str());
1163 if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != nullptr)
1166 s->PutCString ("Address range: ");
1167 m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
1168 s->PutCString ("\n");
1172 //----------------------------------------------------------------------
1174 // SymbolContextList
1176 //----------------------------------------------------------------------
1179 SymbolContextList::SymbolContextList() :
1184 SymbolContextList::~SymbolContextList()
1189 SymbolContextList::Append(const SymbolContext& sc)
1191 m_symbol_contexts.push_back(sc);
1195 SymbolContextList::Append (const SymbolContextList& sc_list)
1197 collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
1198 for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
1199 m_symbol_contexts.push_back (*pos);
1204 SymbolContextList::AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function)
1206 uint32_t unique_sc_add_count = 0;
1207 collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
1208 for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
1210 if (AppendIfUnique (*pos, merge_symbol_into_function))
1211 ++unique_sc_add_count;
1213 return unique_sc_add_count;
1217 SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function)
1219 collection::iterator pos, end = m_symbol_contexts.end();
1220 for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1225 if (merge_symbol_into_function
1226 && sc.symbol != nullptr
1227 && sc.comp_unit == nullptr
1228 && sc.function == nullptr
1229 && sc.block == nullptr
1230 && sc.line_entry.IsValid() == false)
1232 if (sc.symbol->ValueIsAddress())
1234 for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1236 // Don't merge symbols into inlined function symbol contexts
1237 if (pos->block && pos->block->GetContainingInlinedBlock())
1242 if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddressRef())
1244 // Do we already have a function with this symbol?
1245 if (pos->symbol == sc.symbol)
1247 if (pos->symbol == nullptr)
1249 pos->symbol = sc.symbol;
1257 m_symbol_contexts.push_back(sc);
1262 SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc,
1266 if (symbol_sc.symbol != nullptr
1267 && symbol_sc.comp_unit == nullptr
1268 && symbol_sc.function == nullptr
1269 && symbol_sc.block == nullptr
1270 && symbol_sc.line_entry.IsValid() == false)
1272 if (symbol_sc.symbol->ValueIsAddress())
1274 const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx);
1275 for (size_t i=start_idx; i<end; ++i)
1277 const SymbolContext &function_sc = m_symbol_contexts[i];
1278 // Don't merge symbols into inlined function symbol contexts
1279 if (function_sc.block && function_sc.block->GetContainingInlinedBlock())
1282 if (function_sc.function)
1284 if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRef())
1286 // Do we already have a function with this symbol?
1287 if (function_sc.symbol == symbol_sc.symbol)
1288 return true; // Already have a symbol context with this symbol, return true
1290 if (function_sc.symbol == nullptr)
1292 // We successfully merged this symbol into an existing symbol context
1293 m_symbol_contexts[i].symbol = symbol_sc.symbol;
1305 SymbolContextList::Clear()
1307 m_symbol_contexts.clear();
1311 SymbolContextList::Dump(Stream *s, Target *target) const
1316 s->PutCString("SymbolContextList");
1320 collection::const_iterator pos, end = m_symbol_contexts.end();
1321 for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1323 //pos->Dump(s, target);
1324 pos->GetDescription(s, eDescriptionLevelVerbose, target);
1330 SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext& sc) const
1332 if (idx < m_symbol_contexts.size())
1334 sc = m_symbol_contexts[idx];
1341 SymbolContextList::GetLastContext(SymbolContext& sc) const
1343 if (!m_symbol_contexts.empty())
1345 sc = m_symbol_contexts.back();
1352 SymbolContextList::RemoveContextAtIndex (size_t idx)
1354 if (idx < m_symbol_contexts.size())
1356 m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
1363 SymbolContextList::GetSize() const
1365 return m_symbol_contexts.size();
1369 SymbolContextList::NumLineEntriesWithLine (uint32_t line) const
1371 uint32_t match_count = 0;
1372 const size_t size = m_symbol_contexts.size();
1373 for (size_t idx = 0; idx<size; ++idx)
1375 if (m_symbol_contexts[idx].line_entry.line == line)
1382 SymbolContextList::GetDescription(Stream *s,
1383 lldb::DescriptionLevel level,
1384 Target *target) const
1386 const size_t size = m_symbol_contexts.size();
1387 for (size_t idx = 0; idx<size; ++idx)
1388 m_symbol_contexts[idx].GetDescription (s, level, target);
1392 lldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs)
1394 const uint32_t size = lhs.GetSize();
1395 if (size != rhs.GetSize())
1398 SymbolContext lhs_sc;
1399 SymbolContext rhs_sc;
1400 for (uint32_t i=0; i<size; ++i)
1402 lhs.GetContextAtIndex(i, lhs_sc);
1403 rhs.GetContextAtIndex(i, rhs_sc);
1404 if (lhs_sc != rhs_sc)
1411 lldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs)
1413 return !(lhs == rhs);