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