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