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