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                 Log *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\n",
521                                          curr_inlined_block->GetID(),
522                                          curr_frame_pc.GetFileAddress(),
523                                          objfile->GetFileSpec().GetPath().c_str());
524                     }
525                     else
526                     {
527                         Host::SystemLog (Host::eSystemLogWarning,
528                                          "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n",
529                                          curr_inlined_block->GetID(),
530                                          curr_frame_pc.GetFileAddress());
531                     }
532                 }
533 #endif
534             }
535         }
536     }
537 
538     return false;
539 }
540 
541 Block *
542 SymbolContext::GetFunctionBlock ()
543 {
544     if (function)
545     {
546         if (block)
547         {
548             // If this symbol context has a block, check to see if this block
549             // is itself, or is contained within a block with inlined function
550             // information. If so, then the inlined block is the block that
551             // defines the function.
552             Block *inlined_block = block->GetContainingInlinedBlock();
553             if (inlined_block)
554                 return inlined_block;
555 
556             // The block in this symbol context is not inside an inlined
557             // block, so the block that defines the function is the function's
558             // top level block, which is returned below.
559         }
560 
561         // There is no block information in this symbol context, so we must
562         // assume that the block that is desired is the top level block of
563         // the function itself.
564         return &function->GetBlock(true);
565     }
566     return NULL;
567 }
568 
569 bool
570 SymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language,
571                                       bool &is_instance_method,
572                                       ConstString &language_object_name)
573 
574 
575 {
576     Block *function_block = GetFunctionBlock ();
577     if (function_block)
578     {
579         clang::DeclContext *decl_context = function_block->GetClangDeclContext();
580 
581         if (decl_context)
582         {
583             return ClangASTContext::GetClassMethodInfoForDeclContext (decl_context,
584                                                                       language,
585                                                                       is_instance_method,
586                                                                       language_object_name);
587         }
588     }
589     language = eLanguageTypeUnknown;
590     is_instance_method = false;
591     language_object_name.Clear();
592     return false;
593 }
594 
595 ConstString
596 SymbolContext::GetFunctionName (Mangled::NamePreference preference)
597 {
598     if (function)
599     {
600         if (block)
601         {
602             Block *inlined_block = block->GetContainingInlinedBlock();
603 
604             if (inlined_block)
605             {
606                 const InlineFunctionInfo *inline_info = inlined_block->GetInlinedFunctionInfo();
607                 if (inline_info)
608                     return inline_info->GetName();
609             }
610         }
611         return function->GetMangled().GetName(preference);
612     }
613     else if (symbol && symbol->ValueIsAddress())
614     {
615         return symbol->GetMangled().GetName(preference);
616     }
617     else
618     {
619         // No function, return an empty string.
620         return ConstString();
621     }
622 }
623 
624 //----------------------------------------------------------------------
625 //
626 //  SymbolContextSpecifier
627 //
628 //----------------------------------------------------------------------
629 
630 SymbolContextSpecifier::SymbolContextSpecifier (const TargetSP &target_sp) :
631     m_target_sp (target_sp),
632     m_module_spec (),
633     m_module_sp (),
634     m_file_spec_ap (),
635     m_start_line (0),
636     m_end_line (0),
637     m_function_spec (),
638     m_class_name (),
639     m_address_range_ap (),
640     m_type (eNothingSpecified)
641 {
642 }
643 
644 SymbolContextSpecifier::~SymbolContextSpecifier()
645 {
646 }
647 
648 bool
649 SymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type)
650 {
651     bool return_value = true;
652     switch (type)
653     {
654     case eNothingSpecified:
655         Clear();
656         break;
657     case eLineStartSpecified:
658         m_start_line = line_no;
659         m_type |= eLineStartSpecified;
660         break;
661     case eLineEndSpecified:
662         m_end_line = line_no;
663         m_type |= eLineEndSpecified;
664         break;
665     default:
666         return_value = false;
667         break;
668     }
669     return return_value;
670 }
671 
672 bool
673 SymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type)
674 {
675     bool return_value = true;
676     switch (type)
677     {
678     case eNothingSpecified:
679         Clear();
680         break;
681     case eModuleSpecified:
682         {
683             // See if we can find the Module, if so stick it in the SymbolContext.
684             FileSpec module_file_spec(spec_string, false);
685             ModuleSpec module_spec (module_file_spec);
686             lldb::ModuleSP module_sp (m_target_sp->GetImages().FindFirstModule (module_spec));
687             m_type |= eModuleSpecified;
688             if (module_sp)
689                 m_module_sp = module_sp;
690             else
691                 m_module_spec.assign (spec_string);
692         }
693         break;
694     case eFileSpecified:
695         // CompUnits can't necessarily be resolved here, since an inlined function might show up in
696         // a number of CompUnits.  Instead we just convert to a FileSpec and store it away.
697         m_file_spec_ap.reset (new FileSpec (spec_string, false));
698         m_type |= eFileSpecified;
699         break;
700     case eLineStartSpecified:
701         m_start_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
702         if (return_value)
703             m_type |= eLineStartSpecified;
704         break;
705     case eLineEndSpecified:
706         m_end_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
707         if (return_value)
708             m_type |= eLineEndSpecified;
709         break;
710     case eFunctionSpecified:
711         m_function_spec.assign(spec_string);
712         m_type |= eFunctionSpecified;
713         break;
714     case eClassOrNamespaceSpecified:
715         Clear();
716         m_class_name.assign (spec_string);
717         m_type = eClassOrNamespaceSpecified;
718         break;
719     case eAddressRangeSpecified:
720         // Not specified yet...
721         break;
722     }
723 
724     return return_value;
725 }
726 
727 void
728 SymbolContextSpecifier::Clear()
729 {
730     m_module_spec.clear();
731     m_file_spec_ap.reset();
732     m_function_spec.clear();
733     m_class_name.clear();
734     m_start_line = 0;
735     m_end_line = 0;
736     m_address_range_ap.reset();
737 
738     m_type = eNothingSpecified;
739 }
740 
741 bool
742 SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
743 {
744     if (m_type == eNothingSpecified)
745         return true;
746 
747     if (m_target_sp.get() != sc.target_sp.get())
748         return false;
749 
750     if (m_type & eModuleSpecified)
751     {
752         if (sc.module_sp)
753         {
754             if (m_module_sp.get() != NULL)
755             {
756                 if (m_module_sp.get() != sc.module_sp.get())
757                     return false;
758             }
759             else
760             {
761                 FileSpec module_file_spec (m_module_spec.c_str(), false);
762                 if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false))
763                     return false;
764             }
765         }
766     }
767     if (m_type & eFileSpecified)
768     {
769         if (m_file_spec_ap.get())
770         {
771             // If we don't have a block or a comp_unit, then we aren't going to match a source file.
772             if (sc.block == NULL && sc.comp_unit == NULL)
773                 return false;
774 
775             // Check if the block is present, and if so is it inlined:
776             bool was_inlined = false;
777             if (sc.block != NULL)
778             {
779                 const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
780                 if (inline_info != NULL)
781                 {
782                     was_inlined = true;
783                     if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false))
784                         return false;
785                 }
786             }
787 
788             // Next check the comp unit, but only if the SymbolContext was not inlined.
789             if (!was_inlined && sc.comp_unit != NULL)
790             {
791                 if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false))
792                     return false;
793             }
794         }
795     }
796     if (m_type & eLineStartSpecified
797         || m_type & eLineEndSpecified)
798     {
799         if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
800             return false;
801     }
802 
803     if (m_type & eFunctionSpecified)
804     {
805         // First check the current block, and if it is inlined, get the inlined function name:
806         bool was_inlined = false;
807         ConstString func_name(m_function_spec.c_str());
808 
809         if (sc.block != NULL)
810         {
811             const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
812             if (inline_info != NULL)
813             {
814                 was_inlined = true;
815                 const Mangled &name = inline_info->GetMangled();
816                 if (!name.NameMatches (func_name))
817                     return false;
818             }
819         }
820         //  If it wasn't inlined, check the name in the function or symbol:
821         if (!was_inlined)
822         {
823             if (sc.function != NULL)
824             {
825                 if (!sc.function->GetMangled().NameMatches(func_name))
826                     return false;
827             }
828             else if (sc.symbol != NULL)
829             {
830                 if (!sc.symbol->GetMangled().NameMatches(func_name))
831                     return false;
832             }
833         }
834 
835 
836     }
837 
838     return true;
839 }
840 
841 bool
842 SymbolContextSpecifier::AddressMatches(lldb::addr_t addr)
843 {
844     if (m_type & eAddressRangeSpecified)
845     {
846 
847     }
848     else
849     {
850         Address match_address (addr, NULL);
851         SymbolContext sc;
852         m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc);
853         return SymbolContextMatches(sc);
854     }
855     return true;
856 }
857 
858 void
859 SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const
860 {
861     char path_str[PATH_MAX + 1];
862 
863     if (m_type == eNothingSpecified)
864     {
865         s->Printf ("Nothing specified.\n");
866     }
867 
868     if (m_type == eModuleSpecified)
869     {
870         s->Indent();
871         if (m_module_sp)
872         {
873             m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX);
874             s->Printf ("Module: %s\n", path_str);
875         }
876         else
877             s->Printf ("Module: %s\n", m_module_spec.c_str());
878     }
879 
880     if (m_type == eFileSpecified  && m_file_spec_ap.get() != NULL)
881     {
882         m_file_spec_ap->GetPath (path_str, PATH_MAX);
883         s->Indent();
884         s->Printf ("File: %s", path_str);
885         if (m_type == eLineStartSpecified)
886         {
887             s->Printf (" from line %lu", m_start_line);
888             if (m_type == eLineEndSpecified)
889                 s->Printf ("to line %lu", m_end_line);
890             else
891                 s->Printf ("to end");
892         }
893         else if (m_type == eLineEndSpecified)
894         {
895             s->Printf (" from start to line %ld", m_end_line);
896         }
897         s->Printf (".\n");
898     }
899 
900     if (m_type == eLineStartSpecified)
901     {
902         s->Indent();
903         s->Printf ("From line %lu", m_start_line);
904         if (m_type == eLineEndSpecified)
905             s->Printf ("to line %lu", m_end_line);
906         else
907             s->Printf ("to end");
908         s->Printf (".\n");
909     }
910     else if (m_type == eLineEndSpecified)
911     {
912         s->Printf ("From start to line %ld.\n", m_end_line);
913     }
914 
915     if (m_type == eFunctionSpecified)
916     {
917         s->Indent();
918         s->Printf ("Function: %s.\n", m_function_spec.c_str());
919     }
920 
921     if (m_type == eClassOrNamespaceSpecified)
922     {
923         s->Indent();
924         s->Printf ("Class name: %s.\n", m_class_name.c_str());
925     }
926 
927     if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != NULL)
928     {
929         s->Indent();
930         s->PutCString ("Address range: ");
931         m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
932         s->PutCString ("\n");
933     }
934 }
935 
936 //----------------------------------------------------------------------
937 //
938 //  SymbolContextList
939 //
940 //----------------------------------------------------------------------
941 
942 
943 SymbolContextList::SymbolContextList() :
944     m_symbol_contexts()
945 {
946 }
947 
948 SymbolContextList::~SymbolContextList()
949 {
950 }
951 
952 void
953 SymbolContextList::Append(const SymbolContext& sc)
954 {
955     m_symbol_contexts.push_back(sc);
956 }
957 
958 void
959 SymbolContextList::Append (const SymbolContextList& sc_list)
960 {
961     collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
962     for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
963         m_symbol_contexts.push_back (*pos);
964 }
965 
966 
967 uint32_t
968 SymbolContextList::AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function)
969 {
970     uint32_t unique_sc_add_count = 0;
971     collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
972     for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
973     {
974         if (AppendIfUnique (*pos, merge_symbol_into_function))
975             ++unique_sc_add_count;
976     }
977     return unique_sc_add_count;
978 }
979 
980 bool
981 SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function)
982 {
983     collection::iterator pos, end = m_symbol_contexts.end();
984     for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
985     {
986         if (*pos == sc)
987             return false;
988     }
989     if (merge_symbol_into_function
990         && sc.symbol    != NULL
991         && sc.comp_unit == NULL
992         && sc.function  == NULL
993         && sc.block     == NULL
994         && sc.line_entry.IsValid() == false)
995     {
996         if (sc.symbol->ValueIsAddress())
997         {
998             for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
999             {
1000                 if (pos->function)
1001                 {
1002                     if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddress())
1003                     {
1004                         // Do we already have a function with this symbol?
1005                         if (pos->symbol == sc.symbol)
1006                             return false;
1007                         if (pos->symbol == NULL)
1008                         {
1009                             pos->symbol = sc.symbol;
1010                             return false;
1011                         }
1012                     }
1013                 }
1014             }
1015         }
1016     }
1017     m_symbol_contexts.push_back(sc);
1018     return true;
1019 }
1020 
1021 void
1022 SymbolContextList::Clear()
1023 {
1024     m_symbol_contexts.clear();
1025 }
1026 
1027 void
1028 SymbolContextList::Dump(Stream *s, Target *target) const
1029 {
1030 
1031     *s << (void *)this << ": ";
1032     s->Indent();
1033     s->PutCString("SymbolContextList");
1034     s->EOL();
1035     s->IndentMore();
1036 
1037     collection::const_iterator pos, end = m_symbol_contexts.end();
1038     for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1039     {
1040         //pos->Dump(s, target);
1041         pos->GetDescription(s, eDescriptionLevelVerbose, target);
1042     }
1043     s->IndentLess();
1044 }
1045 
1046 bool
1047 SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext& sc) const
1048 {
1049     if (idx < m_symbol_contexts.size())
1050     {
1051         sc = m_symbol_contexts[idx];
1052         return true;
1053     }
1054     return false;
1055 }
1056 
1057 bool
1058 SymbolContextList::GetLastContext(SymbolContext& sc) const
1059 {
1060     if (!m_symbol_contexts.empty())
1061     {
1062         sc = m_symbol_contexts.back();
1063         return true;
1064     }
1065     return false;
1066 }
1067 
1068 bool
1069 SymbolContextList::RemoveContextAtIndex (size_t idx)
1070 {
1071     if (idx < m_symbol_contexts.size())
1072     {
1073         m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
1074         return true;
1075     }
1076     return false;
1077 }
1078 
1079 uint32_t
1080 SymbolContextList::GetSize() const
1081 {
1082     return m_symbol_contexts.size();
1083 }
1084 
1085 uint32_t
1086 SymbolContextList::NumLineEntriesWithLine (uint32_t line) const
1087 {
1088     uint32_t match_count = 0;
1089     const size_t size = m_symbol_contexts.size();
1090     for (size_t idx = 0; idx<size; ++idx)
1091     {
1092         if (m_symbol_contexts[idx].line_entry.line == line)
1093             ++match_count;
1094     }
1095     return match_count;
1096 }
1097 
1098 void
1099 SymbolContextList::GetDescription(Stream *s,
1100                                   lldb::DescriptionLevel level,
1101                                   Target *target) const
1102 {
1103     const size_t size = m_symbol_contexts.size();
1104     for (size_t idx = 0; idx<size; ++idx)
1105         m_symbol_contexts[idx].GetDescription (s, level, target);
1106 }
1107 
1108 bool
1109 lldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs)
1110 {
1111     const uint32_t size = lhs.GetSize();
1112     if (size != rhs.GetSize())
1113         return false;
1114 
1115     SymbolContext lhs_sc;
1116     SymbolContext rhs_sc;
1117     for (uint32_t i=0; i<size; ++i)
1118     {
1119         lhs.GetContextAtIndex(i, lhs_sc);
1120         rhs.GetContextAtIndex(i, rhs_sc);
1121         if (lhs_sc != rhs_sc)
1122             return false;
1123     }
1124     return true;
1125 }
1126 
1127 bool
1128 lldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs)
1129 {
1130     return !(lhs == rhs);
1131 }
1132 
1133