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