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