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