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