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